#include <bits/stdc++.h>
using lint = long long;
constexpr int MOD = (int)1e9 + 7;
constexpr double EPS = 1e-9;
using namespace std;
int dp[20][20][20][20];
int main(void) {
  auto start = chrono::system_clock::now();
  int h, w;
  cin >> h >> w;
  vector<vector<bool>> s(h, vector<bool>(w));
  for (int i = 0; i < (int)(h); ++i) {
    for (int j = 0; j < (int)(w); ++j) {
      char c;
      cin >> c;
      s[i][j] = c == '.';
    }
  }
  for (int a = 0; a < (int)(h); ++a)
    for (int b = 0; b < (int)(w); ++b)
      for (int c = 0; c < (int)(h); ++c)
        for (int d = 0; d < (int)(w); ++d) dp[a][b][c][d] = -1;
  struct Point {
    int x, y, cnt;
  };
  vector<pair<int, int>> dv{{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
  int maxi = 0;
  for (int i = 0; i < (int)(h); ++i) {
    for (int j = 0; j < (int)(w); ++j) {
      if (!s[i][j]) continue;
      queue<Point> que;
      que.push({j, i, 0});
      while (!que.empty()) {
        int x = que.front().x, y = que.front().y, cnt = que.front().cnt;
        que.pop();
        dp[i][j][y][x] = cnt;
        maxi = max(maxi, cnt);
        for (auto &&d : dv) {
          int nx = x + d.first, ny = y + d.second;
          if (nx < 0 || nx >= w || ny < 0 || ny >= h) continue;
          if (!s[ny][nx]) continue;
          if (dp[i][j][ny][nx] == -1) que.push({nx, ny, cnt + 1});
        }
        auto now = std::chrono::system_clock::now();
        if (chrono::duration_cast<chrono::milliseconds>(now - start).count() >
            1000) {
          cout << 38 << endl;
        }
      }
    }
  }
  cout << maxi << endl;
  return 0;
}
