#include <bits/stdc++.h>
using namespace std;
struct Corr {
  long long y;
  long long x;
  long long depth;
};
long long N, M;
long long s_y, s_x, g_y, g_x;
long long y, x, depth;
queue<Corr> q;
bool seen[50][50];
vector<long long> y_vec = {0, 0, -1, +1};
vector<long long> x_vec = {-1, +1, 0, 0};
vector<string> s;
long long bfs() {
  while (!q.empty()) {
    Corr now = q.front();
    q.pop();
    y = now.y, x = now.x, depth = now.depth;
    if (y == g_y && x == g_x) return depth;
    for (long long i = (0); i < (4); i++) {
      Corr next = {y + y_vec[i], x + x_vec[i], depth + 1};
      if (0 <= next.y && next.y <= N - 1 && 0 <= next.x && next.x <= M - 1 &&
          seen[next.y][next.x] == false && s[next.y][next.x] == '.') {
        seen[next.y][next.x] = true;
        q.push(next);
      }
    }
  }
  return 0;
}
signed main() {
  cout << fixed << setprecision(10);
  cerr << fixed << setprecision(10);
  cin >> N >> M;
  s.resize(N);
  for (long long i = (0); i < (N); i++) cin >> s[i];
  long long ans = 0;
  for (long long i = (0); i < (N); i++) {
    for (long long j = (0); j < (M); j++) {
      for (long long k = (0); k < (N); k++) {
        for (long long l = (0); l < (M); l++) {
          s_x = i;
          s_y = j;
          g_x = k;
          g_y = l;
          if (s[i][j] == '.' && s[k][l] == '.') {
            Corr start = {s_y, s_x, 0};
            q.emplace(start);
            memset(seen, 0, sizeof(seen));
            seen[s_x][s_y] = true;
            ans = max(bfs(), ans);
          } else
            continue;
        }
      }
    }
  }
  cout << ans << endl;
  return 0;
}
