#include <bits/stdc++.h>
using namespace std;
struct Corr {
  long long h;
  long long w;
  long long depth;
};
long long H, W;
long long s_h, s_w, g_h, g_w;
long long h, w, depth;
queue<Corr> q;
bool seen[50][50];
vector<long long> h_vec = {0, 0, -1, +1};
vector<long long> w_vec = {-1, +1, 0, 0};
vector<string> s;
long long bfs() {
  while (!q.empty()) {
    Corr now = q.front();
    q.pop();
    h = now.h, w = now.w, depth = now.depth;
    if (h == g_h && w == g_w) return depth;
    for (long long i = (0); i < (4); i++) {
      Corr next = {h + h_vec[i], w + w_vec[i], depth + 1};
      if (0 <= next.h && next.h <= H - 1 && 0 <= next.w && next.w <= W - 1 &&
          seen[next.h][next.w] == false && s[next.h][next.w] == '.') {
        seen[next.h][next.w] = true;
        q.push(next);
      }
    }
  }
  return 0;
}
signed main() {
  cout << fixed << setprecision(10);
  cerr << fixed << setprecision(10);
  cin >> H >> W;
  s.resize(H);
  for (long long i = (0); i < (H); i++) cin >> s[i];
  long long ans = 0;
  for (long long i = (0); i < (H); i++) {
    for (long long j = (0); j < (W); j++) {
      for (long long k = (0); k < (H); k++) {
        for (long long l = (0); l < (W); l++) {
          s_h = i;
          s_w = j;
          g_h = k;
          g_w = l;
          if (s[i][j] == '.' && s[k][l] == '.' && (i != k || j != l)) {
            Corr start = {s_h, s_w, 0};
            q.emplace(start);
            memset(seen, false, sizeof(seen));
            seen[s_h][s_w] = true;
            ans = max(bfs(), ans);
          } else
            continue;
        }
      }
    }
  }
  cout << ans << endl;
  return 0;
}
