#include <bits/stdc++.h>
using namespace std;
const unsigned long long INF = 1e15;
const unsigned long long MINF = LONG_LONG_MIN;
bool contain(set<int> &s, int a) { return s.find(a) != s.end(); }
const int mod = 1000000007;
void warshall_floyd(int n, vector<vector<int>> &d) {
  for (int k = 0; k < n; k++) {
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) {
        d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
      }
    }
  }
}
int main() {
  int h, w;
  cin >> h >> w;
  vector<vector<char>> maze(h, vector<char>(w));
  for (int y = 0; y < (h); ++y)
    for (int x = 0; x < (w); ++x) {
      char c;
      cin >> c;
      maze[y][x] = c;
    }
  vector<vector<int>> distances(h * w, vector<int>(h * w, 1000));
  auto toID = [&](int y, int x) { return y * w + x; };
  vector<pair<int, int>> move = {
      {0, 1},
      {1, 0},
      {0, -1},
      {-1, 0},
  };
  for (int y = 0; y < (h); ++y)
    for (int x = 0; x < (w); ++x) {
      if (maze[y][x] == '#') continue;
      for (pair<int, int> p : move) {
        int cy = p.first;
        int cx = p.second;
        int ny = y + cy;
        int nx = x + cx;
        if (ny == -1) continue;
        if (nx == -1) continue;
        if (ny == h) continue;
        if (nx == w) continue;
        if (maze[y][x] == '.' && maze[ny][nx] == '.') {
          distances[toID(y, x)][toID(ny, nx)] = 1;
          distances[toID(ny, nx)][toID(y, x)] = 1;
        }
      }
    }
  warshall_floyd(w * h, distances);
  int ans = 0;
  for (int i = 0; i < (h * w); ++i)
    for (int j = 0; j < (h * w); ++j) {
      int d = distances[i][j];
      if (d >= 1000) {
        continue;
      }
      ans = max(ans, d);
    }
  assert(ans < 1000);
  cout << ans << endl;
}
