#include <bits/stdc++.h>
using namespace std;
vector<int> dx = {0, 1, 0, -1};
vector<int> dy = {1, 0, -1, 0};
queue<tuple<int, int, int>> keep;
int H, W;
int bfs(int i, int j, vector<vector<bool>> &seen, vector<vector<char>> &maze) {
  int ans = 0;
  keep.push(make_tuple(i, j, 0));
  while (!keep.empty()) {
    int a, b, c;
    tie(a, b, c) = keep.front();
    ans = c;
    keep.pop();
    seen.at(a).at(b) = true;
    for (int k = 0; k < 4; k++) {
      if (a + dx.at(k) < 0 || a + dx.at(k) >= H || b + dy.at(k) < 0 ||
          b + dy.at(k) >= W) {
        continue;
      } else if (maze.at(a + dx.at(k)).at(b + dy.at(k)) == '#') {
        continue;
      } else if (seen.at(a + dx.at(k)).at(b + dy.at(k))) {
        continue;
      } else {
        keep.push(make_tuple(a + dx.at(k), b + dy.at(k), c + 1));
      }
    }
  }
  return ans;
}
int main() {
  cin >> H >> W;
  vector<vector<char>> maze(H, vector<char>(W));
  for (int i = 0; i < H; i++) {
    for (int j = 0; j < W; j++) {
      cin >> maze.at(i).at(j);
    }
  }
  int ans = 0;
  for (int i = 0; i < H; i++) {
    for (int j = 0; j < W; j++) {
      if (maze.at(i).at(j) == '.') {
        vector<vector<bool>> seen(H, vector<bool>(W, false));
        int l = bfs(i, j, seen, maze);
        if (l > ans) {
          ans = l;
        }
      }
    }
  }
  cout << ans << endl;
}
