#include <bits/stdc++.h>
using namespace std;
template <typename A, size_t N, typename T>
void Fill(A (&array)[N], const T& val) {
  std::fill((T*)array, (T*)(array + N), val);
}
pair<long long, long long> Dir[4] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
struct Edge {
  int from, to;
  long long w;
  bool operator<(const Edge& rhs) const {
    return make_pair((w), (make_pair((from), (to)))) <
           make_pair((rhs.w), (make_pair((rhs.from), (rhs.to))));
  }
};
long long gcd(long long a, long long b) {
  if (b == 0) return a;
  return gcd(b, a % b);
}
long long facmemo[200000] = {};
long long factorial(long long n) {
  if (facmemo[n] != 0) return facmemo[n];
  if (n == 0) return 1;
  long long ret = n * factorial(n - 1);
  ret %= 1000000007LL;
  return facmemo[n] = ret;
}
long long mod_pow(long long x, long long n, long long mod) {
  long long res = 1;
  while (n > 0) {
    if (n & 1) res = res * x % mod;
    x = x * x % mod;
    n >>= 1;
  }
  return res;
}
long long divmod(long long a, long long b, long long m) {
  return (a * 1LL * mod_pow(b, m - 2, m)) % m;
}
long long ncr(long long n, long long r) {
  if (r == 0) return 1;
  if (n < r) return 1;
  return divmod(factorial(n),
                (factorial(r) * (factorial(n - r))) % 1000000007LL,
                1000000007LL);
}
bool sankaku(int a, int b, int c) {
  return a <= b + c && b <= a + c && c <= b + a;
}
using ld = double;
using P = complex<ld>;
using G = vector<P>;
const ld pi = acos(-1);
const ld eps = 1e-10;
const ld inf = 1e12;
ld cross(const P& a, const P& b) {
  return a.real() * b.imag() - a.imag() * b.real();
}
ld dot(const P& a, const P& b) {
  return a.real() * b.real() + a.imag() * b.imag();
}
signed main() {
  int h, w;
  cin >> h >> w;
  vector<vector<int>> m(h, vector<int>(w));
  for (int i = (0); (h) > i; i++)
    for (int j = (0); (w) > j; j++) {
      char buf;
      cin >> buf;
      m[i][j] = buf == '#';
    }
  auto bfs = [&](int sy, int sx) {
    int ret = 0;
    queue<pair<int, pair<int, int>>> que;
    que.push({0, {sy, sx}});
    vector<vector<int>> md(h, vector<int>(w, -1));
    while (que.size()) {
      pair<int, pair<int, int>> cur = que.front();
      que.pop();
      if (md[cur.second.first][cur.second.second] != -1) continue;
      md[cur.second.first][cur.second.second] = cur.first;
      ret = max(ret, cur.first);
      for (int i = (0); (4) > i; i++) {
        pair<int, int> nex = cur.second;
        nex.first += Dir[i].first;
        nex.second += Dir[i].second;
        if (nex.first < 0 || nex.first >= h || nex.second < 0 ||
            nex.second >= w) {
          continue;
        }
        if (m[nex.first][nex.second] == 0) {
          que.push({cur.first + 1, nex});
        }
      }
    }
    return ret;
  };
  int ans = -1;
  for (int i = (0); (h) > i; i++) {
    for (int j = (0); (w) > j; j++) {
      ans = max(ans, bfs(i, j));
    }
  }
  cout << ans << endl;
  return 0;
}
