#include <bits/stdc++.h>
using namespace std;
const int INF = 1 << 30;
int H, W;
vector<vector<char>> grid;
bool in_grid(int i, int j) { return 0 <= i && i < H && 0 <= j && j < W; }
bool can_step(int i, int j) { return grid[i][j] == '.'; }
int main() {
  cin >> H >> W;
  grid.resize(H, vector<char>(W));
  for (int i = 0; i < H; ++i)
    for (int j = 0; j < W; ++j) cin >> grid[i][j];
  int ans = 0;
  for (int sh = 0; sh < H; ++sh)
    for (int sw = 0; sw < W; ++sw) {
      if (!can_step(sh, sw)) continue;
      vector<vector<int>> dist(H, vector<int>(W, INF));
      int max_dist = 0;
      using T = tuple<int, int, int>;
      queue<T> q;
      q.push(T(sh, sw, 0));
      while (!q.empty()) {
        T t = q.front();
        q.pop();
        int i, j, d;
        tie(i, j, d) = t;
        dist[i][j] = min(dist[i][j], d);
        max_dist = max(max_dist, dist[i][j]);
        vector<int> dh{1, 0, -1, 0}, dw{0, 1, 0, -1};
        for (int k = 0; k < 4; ++k) {
          int ni = i + dh[k], nj = j + dw[k];
          if (!in_grid(ni, nj) || !can_step(ni, nj) || dist[ni][nj] != INF)
            continue;
          q.push(T(ni, nj, d + 1));
        }
      }
      ans = max(ans, max_dist);
    }
  cout << ans << endl;
}
