#include <bits/stdc++.h>
using namespace std;
struct cww {
  cww() {
    ios::sync_with_stdio(false);
    cin.tie(0);
  }
} star;
const long long INF = numeric_limits<long long>::max();
int dx[] = {1, 0, -1, 0};
int dy[] = {0, 1, 0, -1};
int H, W;
int bfs(int H, int W, vector<vector<char>> S, int x, int y) {
  int ans = 0;
  vector<vector<int>> distance(W, vector<int>(H));
  if (S[x][y] == '#') {
    return 0;
  }
  pair<int, int> start = {x, y};
  vector<vector<bool>> arrived(W + 1, vector<bool>(H + 1));
  for (int Y = 0; Y < (H); Y++) {
    for (int X = 0; X < (W); X++) {
      distance[X][Y] = -1;
    }
  }
  distance[x][y] = 0;
  queue<pair<int, int>> q;
  q.push(start);
  while (!q.empty()) {
    pair<int, int> now = q.front();
    int nowx = now.first;
    int nowy = now.second;
    int dis = distance[nowx][nowy];
    arrived[nowx][nowy] = true;
    q.pop();
    for (int k = 0; k < (4); k++) {
      if ((nowx + dx[k] < W and nowx + dx[k] >= 0 and nowy + dy[k] < H and
           nowy + dy[k] >= 0 and S[nowx + dx[k]][nowy + dy[k]] == '.') and
          arrived[nowx + dx[k]][nowy + dy[k]] == 0) {
        q.push({nowx + dx[k], nowy + dy[k]});
        distance[nowx + dx[k]][nowy + dy[k]] = dis + 1;
      }
    }
  }
  for (int s = 0; s < (W); s++) {
    for (int t = 0; t < (H); t++) {
      ans = max(distance[s][t], ans);
    }
  }
  return ans;
}
int main() {
  cin >> H >> W;
  vector<vector<char>> S(W, vector<char>(H));
  int Answer = 0;
  for (int y = 0; y < (H); y++) {
    for (int x = 0; x < (W); x++) {
      cin >> S[x][y];
    }
  }
  for (int y = 0; y < (H); y++) {
    for (int x = 0; x < (W); x++) {
      Answer = max(Answer, bfs(H, W, S, x, y));
    }
  }
  cout << Answer;
  return 0;
}
