#include <bits/stdc++.h>
using namespace std;
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
template <class T>
inline bool chmax(T& a, T b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T>
inline bool chmin(T& a, T b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
struct io {
  io() {
    ios::sync_with_stdio(false);
    cin.tie(0);
  }
};
const int INF = INT_MAX / 2;
const long long int LLINF = 1LL << 60;
constexpr long long int MOD = 1000000007;
const double EPS = 1e-9;
signed main(void) {
  cin.tie(0);
  ios::sync_with_stdio(false);
  int H, W;
  cin >> H >> W;
  vector<vector<int> > edges(H * W, vector<int>(H * W));
  vector<string> ss(H);
  for (int i = 0; i < (H); ++i) {
    cin >> ss[i];
  }
  for (int i = 0; i < (H); ++i) {
    for (int j = 0; j < (W); ++j) {
      if (ss[i][j] != '.') continue;
      if (i < H - 1 && ss[i + 1][j] == '.') {
        edges[i * H + j][(i + 1) * H + j] = 1;
        edges[(i + 1) * H + j][i * H + j] = 1;
      }
      if (j < W - 1 && ss[i][j + 1] == '.') {
        edges[i * H + j][i * H + j + 1] = 1;
        edges[i * H + j + 1][i * H + j] = 1;
      }
    }
  }
  vector<vector<int> > dist(H * W, vector<int>(W * W));
  for (int i = 0; i < (H * W); ++i) {
    for (int j = 0; j < (H * W); ++j) {
      dist[i][j] = edges[i][j] ? 1 : INF;
    }
  }
  for (int i = 0; i < (H * W); ++i) {
    dist[i][i] = 0;
  }
  for (int i = 0; i < (H * W); ++i) {
    for (int j = 0; j < (H * W); ++j) {
      for (int k = 0; k < (H * W); ++k) {
        if (dist[j][k] > dist[j][i] + dist[i][k]) {
          dist[j][k] = dist[j][i] + dist[i][k];
        }
      }
    }
  }
  int maxv = 0;
  for (int i = 0; i < (H * W); ++i) {
    for (int j = 0; j < (H * W); ++j) {
      if (dist[i][j] != INF) {
        chmax(maxv, dist[i][j]);
      }
    }
  }
  cout << (maxv) << '\n';
}
