#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
using namespace std;
template <typename T>
inline bool chmax(T& a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <typename T>
inline bool chmin(T& a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
const int INF = 1e9;
const int dh[4] = {0, 1, 0, -1};
const int dw[4] = {1, 0, -1, 0};
int main() {
  int H, W;
  cin >> H >> W;
  vector<string> S(H);
  for (int i = 0; i < H; i++) cin >> S[i];
  auto bfs = [&](int sh, int sw) {
    if (S[sh][sw] == '#') return -1;
    vector<vector<bool>> seen(H, vector<bool>(W, false));
    vector<vector<int>> dist(H, vector<int>(W, INF));
    dist[sh][sw] = 0;
    queue<pair<int, int>> que;
    que.emplace(sh, sw);
    while (!que.empty()) {
      int h, w;
      tie(h, w) = que.front();
      que.pop();
      seen[h][w] = true;
      for (int i = 0; i < 4; i++) {
        int nh = h + dh[i], nw = w + dw[i];
        if (nh < 0 || H <= nh || nw < 0 || W <= nw) continue;
        if (seen[nh][nw]) continue;
        if (S[nh][nw] == '#') continue;
        dist[nh][nw] = dist[h][w] + 1;
        que.emplace(nh, nw);
      }
    }
    int ret = -1;
    for (int i = 0; i < H; i++) {
      for (int j = 0; j < W; j++) {
        if (S[i][j] == '#') continue;
        chmax(ret, dist[i][j]);
      }
    }
    return ret;
  };
  int ans = -1;
  for (int i = 0; i < H; i++)
    for (int j = 0; j < W; j++) {
      if (S[i][j] == '#') continue;
      int res = bfs(i, j);
      chmax(ans, res);
    }
  cout << ans << endl;
  return 0;
}
