#include <bits/stdc++.h>
using namespace std;
struct p {
  long long x, y, idx;
  unsigned long long sqrdist(p b) {
    return (x - b.x) * (x - b.x) + (y - b.y) * (y - b.y);
  }
  void read() { cin >> x >> y; }
  long long operator*(p b) { return x * b.y - y * b.x; }
  bool operator==(p b) { return x == b.x && y == b.y; }
  void operator-=(p b) { x -= b.x, y -= b.y; }
  bool operator>=(p b) { return x >= b.x && y >= b.y; }
  bool operator<=(p b) { return x <= b.x && y <= b.y; }
  p operator-(p b) { return {x - b.x, y - b.y}; }
  long long crossprod(p a, p b) {
    a.x -= x, b.x -= x, a.y -= y, b.y -= y;
    return a * b;
  }
};
struct segment {
  p p1, p2;
  void equal(p a, p b) { p1 = a, p2 = b; }
  void readseg() { p1.read(), p2.read(); }
};
bool comp(p a, p b) { return a.y < b.y; }
void convexhull(vector<p> v, vector<p> c) {
  sort(v.begin(), v.end(), comp);
  for (long long q = 0; q < 2; q += 1) {
    vector<p> g;
    g.push_back(v[0]);
    for (long long i = 1; i < v.size(); i += 1) {
      while (g.size() >= 2 &&
             ((v[i] - g[g.size() - 2]) * (g.back() - g[g.size() - 2]) <= 0)) {
        g.pop_back();
      }
      g.push_back(v[i]);
    }
    if (q == 0) {
      g.pop_back();
    }
    for (p i : g) {
      c.push_back(i);
    }
    reverse(v.begin(), v.end());
  }
}
bool intersect(segment a, segment b) {
  for (long long i = 0; i < 2; i += 1) {
    p p1 = a.p1;
    long long v1 = (b.p1 - p1) * (a.p2 - p1), v2 = (b.p2 - p1) * (a.p2 - p1);
    if (v1 * v2 > 0) {
      return false;
    } else if (v1 == 0 && v2 == 0) {
      if (max(a.p1.x, a.p2.x) < min(b.p1.x, b.p2.x) ||
          max(a.p1.y, a.p2.y) < min(b.p1.y, b.p2.y)) {
        return false;
      }
    }
    swap(a, b);
  }
  return true;
}
bool equal(vector<p> a, vector<p> b) {
  if (a.size() != b.size()) {
    return false;
  }
  for (long long i = 0; i < a.size(); i += 1) {
    if (a[i] == b[i]) {
      continue;
    }
    return false;
  }
  return true;
}
vector<p> all = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
bool ok[22][22];
int n, m;
int bfs(p s, p e) {
  queue<p> q;
  q.push(s);
  vector<vector<bool>> seen(21, vector<bool>(21, false));
  int dist = 0;
  while (q.size()) {
    int f = q.size();
    while (f--) {
      p a = q.front();
      q.pop();
      if (seen[a.x][a.y] || a.x <= 0 || a.x > n || a.y <= 0 || a.y > m) {
        continue;
      }
      seen[a.x][a.y] = true;
      if (a.x == e.x && a.y == e.y) {
        return dist;
      }
      for (p i : all) {
        p next = {a.x + i.x, a.y + i.y};
        if (!seen[next.x][next.y] && ok[next.x][next.y]) {
          q.push(next);
        }
      }
    }
    dist += 1;
  }
}
int main() {
  cin >> n >> m;
  for (int i = 1; i <= n; i += 1) {
    for (int j = 1; j <= m; j += 1) {
      char a;
      cin >> a;
      if (a == '.') {
        ok[i][j] = true;
      }
    }
  }
  int maxi = 0;
  for (int i = 1; i <= n; i += 1) {
    for (int j = 1; j <= m; j += 1) {
      for (int ii = 1; ii <= n; ii += 1) {
        for (int jj = 1; jj <= m; jj += 1) {
          if (ok[i][j] && ok[ii][jj]) {
            p a = {i, j}, b = {ii, jj};
            maxi = max(maxi, bfs(a, b));
          }
        }
      }
    }
  }
  cout << maxi << endl;
}
