#include <bits/stdc++.h>
using lint = long long;
constexpr int MOD = (int)1e9 + 7;
constexpr double EPS = 1e-9;
using namespace std;
namespace {
struct INIT {
  INIT() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(15);
  }
} INIT;
}  // namespace
int dp[20][20][20][20];
int main(void) {
  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;
  };
  for (int i = 0; i < (int)(h); ++i) {
    for (int j = 0; j < (int)(w); ++j) {
      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;
        if (x + 1 < w && s[y][x + 1] && dp[i][j][y][x + 1] == -1)
          que.push({x + 1, y, cnt + 1});
        if (x - 1 >= 0 && s[y][x - 1] && dp[i][j][y][x - 1] == -1)
          que.push({x - 1, y, cnt + 1});
        if (y + 1 < h && s[y + 1][x] && dp[i][j][y + 1][x] == -1)
          que.push({x, y + 1, cnt + 1});
        if (y - 1 >= 0 && s[y - 1][x] && dp[i][j][y - 1][x] == -1)
          que.push({x, y - 1, cnt + 1});
      }
    }
  }
  int maxi = 0;
  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) maxi = max(maxi, dp[a][b][c][d]);
  cout << maxi << endl;
  return 0;
}
