#include <bits/stdc++.h>
using namespace std;
using T = tuple<int, int, int>;
const int INF = 1e+8;
const int dx[4] = {0, 1, 0, -1};
const int dy[4] = {1, 0, -1, 0};
int main() {
  int h, w;
  cin >> h >> w;
  vector<vector<char>> field(h, vector<char>(w));
  for (int x = 0; x < h; x++) {
    for (int y = 0; y < w; y++) {
      cin >> field[x][y];
    }
  }
  int ans = 0;
  for (int sx = 0; sx < h; sx++) {
    for (int sy = 0; sy < w; sy++) {
      if (field[sx][sy] == '#') continue;
      for (int gx = 0; gx < h; gx++) {
        for (int gy = 0; gy < w; gy++) {
          if (field[gx][gy] == '#') continue;
          vector<vector<int>> dst(h, vector<int>(w, INF));
          int mxdst = 0;
          queue<T> q;
          q.push({sx, sy, 0});
          while (!q.empty()) {
            int x, y, d;
            tie(x, y, d) = q.front();
            q.pop();
            dst[x][y] = min(dst[x][y], d);
            mxdst = max(mxdst, dst[x][y]);
            for (int i = 0; i < 4; i++) {
              if (x + dx[i] < 0) continue;
              if (y + dy[i] < 0) continue;
              if (x + dx[i] >= h) continue;
              if (y + dy[i] >= w) continue;
              if (dst[x + dx[i]][y + dy[i]] <= d + 1) continue;
              if (field[x + dx[i]][y + dy[i]] == '#') continue;
              q.push({x + dx[i], y + dy[i], d + 1});
            }
          }
          ans = max(mxdst, ans);
        }
      }
    }
  }
  cout << ans << endl;
}
