#include <bits/stdc++.h>
using namespace std;
const int dx[4] = {1, 0, -1, 0};
const int dy[4] = {0, 1, 0, -1};
int main() {
  int H, W;
  cin >> H >> W;
  vector<string> field(H);
  for (int y = 0; y < H; ++y) cin >> field[y];
  int sx, sy;
  int ans = 0;
  for (int h = 0; h < H; ++h) {
    int max_moves = 0;
    for (int w = 0; w < W; ++w) {
      sx = h;
      sy = w;
      vector<vector<int> > dist(H, vector<int>(W, -1));
      dist.at(sx).at(sy) = 0;
      queue<pair<int, int> > que;
      que.push(make_pair(sx, sy));
      while (!que.empty()) {
        pair<int, int> current_pos = que.front();
        int x = current_pos.first;
        int y = current_pos.second;
        que.pop();
        for (int direction = 0; direction < 4; ++direction) {
          int next_x = x + dx[direction];
          int next_y = y + dy[direction];
          if (next_x < 0 || next_x >= H || next_y < 0 || next_y >= W) continue;
          if (field[next_x][next_y] == '#') continue;
          if (dist[next_x][next_y] == -1) {
            que.push(make_pair(next_x, next_y));
            dist.at(next_x).at(next_y) = dist.at(x).at(y) + 1;
          }
        }
      }
      for (int h = 0; h < H; ++h) {
        for (int w = 0; w < W; ++w) {
          max_moves = max(max_moves, dist.at(h).at(w));
        }
      }
    }
    ans = max(ans, max_moves);
  }
  printf("%d", ans);
  return 0;
}
