#include <bits/stdc++.h>
using namespace std;
int main() {
  int H, W;
  cin >> H >> W;
  vector<string> grids(H);
  for (int i = 0; i < H; i++) cin >> grids[i];
  int ans = 0;
  for (int i = 0; i < H; i++) {
    for (int j = 0; j < W; j++) {
      if (grids[i][j] == '.') {
        vector<vector<bool>> added(H, vector<bool>(W));
        queue<tuple<int, int, int>> q;
        q.push(tuple<int, int, int>(i, j, 0));
        while (!q.empty()) {
          int h, w, d;
          tie(h, w, d) = q.front();
          q.pop();
          ans = max(ans, d);
          if (h != 0 && grids[h - 1][w] == '.' && !added[h - 1][w]) {
            q.push(tuple<int, int, int>(h - 1, w, d + 1));
            added[h - 1][w] = true;
          }
          if (h != H - 1 && grids[h + 1][w] == '.' && !added[h + 1][w]) {
            q.push(tuple<int, int, int>(h + 1, w, d + 1));
            added[h + 1][w] = true;
          }
          if (w != 0 && grids[h][w - 1] == '.' && !added[h][w - 1]) {
            q.push(tuple<int, int, int>(h, w - 1, d + 1));
            added[h][w - 1] = true;
          }
          if (w != W - 1 && grids[h][w + 1] == '.' && !added[h][w + 1]) {
            q.push(tuple<int, int, int>(h, w + 1, d + 1));
            added[h][w + 1] = true;
          }
        }
      }
    }
  }
  cout << ans << endl;
  return 0;
}
