#include <bits/stdc++.h>
using namespace std;
int main() {
  int H, W;
  cin >> H >> W;
  vector<vector<bool> > maze(H + 2, vector<bool>(W + 2, false));
  for (int i = 0; i < H; i++) {
    for (int j = 0; j < W; j++) {
      char s;
      cin >> s;
      if (s == '.') {
        maze[i + 1][j + 1] = true;
      }
    }
  }
  int ans = 0;
  for (int i = 0; i < H; i++) {
    for (int j = 0; j < W; j++) {
      if (maze[i + 1][j + 1]) {
        vector<vector<bool> > searched(H + 2, vector<bool>(W + 2, false));
        queue<vector<int> > q;
        int temp_ans = 0;
        q.push({i + 1, j + 1, 0});
        while (!q.empty()) {
          vector<int> t = q.front();
          int h = t[0];
          int w = t[1];
          int depth = t[2];
          temp_ans = max(temp_ans, depth);
          q.pop();
          if (maze[h + 1][w] && !searched[h + 1][w]) {
            searched[h + 1][w] = true;
            q.push({h + 1, w, depth + 1});
          }
          if (maze[h - 1][w] && !searched[h - 1][w]) {
            searched[h - 1][w] = true;
            q.push({h - 1, w, depth + 1});
          }
          if (maze[h][w + 1] && !searched[h][w + 1]) {
            searched[h][w + 1] = true;
            q.push({h, w + 1, depth + 1});
          }
          if (maze[h][w - 1] && !searched[h][w - 1]) {
            searched[h][w - 1] = true;
            q.push({h, w - 1, depth + 1});
          }
        }
        ans = max(temp_ans, ans);
      }
    }
  }
  cout << ans << endl;
}
