#include <bits/stdc++.h>
using namespace std;
const int dx[4] = {0, 1, 0, -1};
const int dy[4] = {1, 0, -1, 0};
void dfs(int x, int y, vector<string>& s, vector<vector<int>>& cost) {
  for (auto i = 0; i < 4; i++) {
    int nx = x + dx[i], ny = y + dy[i];
    if (nx < 0 or nx >= (int)s.size()) continue;
    if (ny < 0 or ny >= (int)s[nx].size()) continue;
    if (s[nx][ny] == '#') continue;
    if (cost[nx][ny] != 0) continue;
    cost[nx][ny] = cost[x][y] + 1;
    dfs(nx, ny, s, cost);
  }
}
int main() {
  int h, w;
  cin >> h >> w;
  vector<string> s(h);
  vector<vector<int>> cost;
  for (auto i = 0; i < h; i++) cin >> s[i];
  int ans = 0, max_cost;
  queue<pair<int, int>> q;
  for (auto i = 0; i < h; i++) {
    for (auto j = 0; j < w; j++) {
      cost.assign(h, vector<int>(w, 0));
      q.push({i, j});
      max_cost = 0;
      while (not q.empty()) {
        auto p = q.front();
        q.pop();
        for (auto k = 0; k < 4; k++) {
          int nx = p.first + dx[k], ny = p.second + dy[k];
          if (nx < 0 or nx >= h or ny < 0 or ny >= w) continue;
          if (s[nx][ny] == '#') continue;
          if (cost[nx][ny] != 0) continue;
          cost[nx][ny] = cost[p.first][p.second] + 1;
          max_cost = max(max_cost, cost[nx][ny]);
          q.push({nx, ny});
        }
      }
      ans = max(ans, max_cost);
    }
  }
  cout << ans << endl;
  return 0;
}
