#include <bits/stdc++.h>
long long gcd(long long a, long long b) { return b ? gcd(b, a % b) : a; }
using namespace std;
inline int toInt(string s) {
  int v;
  istringstream sin(s);
  sin >> v;
  return v;
}
template <class T>
inline string toString(T x) {
  ostringstream sout;
  sout << x;
  return sout.str();
}
template <class T>
T maxt(T x, T y) {
  if (x > y)
    return x;
  else
    return y;
}
template <class T>
T mint(T x, T y) {
  if (x > y)
    return y;
  else
    return x;
}
long long m = 1e9 + 7, mod = 1e9 + 7;
long long modinv(long long a, long long m = 1e9 + 7) {
  long long b = m, u = 1, v = 0;
  while (b) {
    long long t = a / b;
    a -= t * b;
    swap(a, b);
    u -= t * v;
    swap(u, v);
  }
  u %= m;
  if (u < 0) u += m;
  return u;
}
int main() {
  int H, W;
  string s;
  cin >> H >> W;
  const int INF = 1000000;
  vector<string> S(1, string(W + 2, '#'));
  vector<vector<int> > v(H * W, vector<int>(H * W, INF));
  for (int i = 0; i < H; i++) {
    cin >> s;
    s = '#' + s + '#';
    S.push_back(s);
  }
  S.push_back(string(W + 2, '#'));
  for (int i = (1); i < (H + 1); ++i) {
    for (int j = (1); j < (W + 1); ++j) {
      if (S[i][j] == '.' && S[i][j + 1] == '.')
        v[(i - 1) * H + j - 1][(i - 1) * H + j] =
            v[(i - 1) * H + j][(i - 1) * H + j - 1] = 1;
      if (S[i][j] == '.' && S[i + 1][j] == '.')
        v[(i - 1) * H + j - 1][(i)*H + j - 1] =
            v[(i)*H + j - 1][(i - 1) * H + j - 1] = 1;
      v[(i - 1) * H + j - 1][(i - 1) * H + j - 1] = 0;
    }
  }
  for (int k = 0; k < H * W; k++) {
    for (int i = 0; i < H * W; i++) {
      for (int j = 0; j < H * W; j++) {
        v[i][j] = min(v[i][j], v[i][k] + v[k][j]);
      }
    }
  }
  int ans = 0;
  for (int i = 0; i < H * W; i++) {
    for (int j = 0; j < H * W; j++) {
      if (v[i][j] > ans && v[i][j] < INF) ans = v[i][j];
    }
  }
  cout << ans << endl;
}
