#include <bits/stdc++.h>
using namespace std;
template <typename T>
struct Graph {
  vector<vector<pair<T, int> > > edge;
  int size;
  Graph(int v) {
    size = v;
    edge.resize(v);
  }
  void add_edge(int s, int e) {
    edge[s].push_back(make_pair(1, e));
    edge[e].push_back(make_pair(1, s));
  }
  void add_edge(T d, int s, int e) {
    edge[s].push_back(make_pair(d, e));
    edge[e].push_back(make_pair(d, s));
  }
  vector<vector<T> > warshall_floyd() {
    vector<vector<T> > d(size, vector<T>(size, 99999999));
    d.resize(size);
    int i, j, k;
    for (i = 0; i < size; i++) d[i].resize(size);
    for (i = 0; i < size; i++) {
      for (j = 0; j < edge[i].size(); j++) {
        d[i][edge[i][j].second] = edge[i][j].first;
      }
    }
    for (k = 0; k < size; k++) {
      for (i = 0; i < size; i++) {
        for (j = 0; j < size; j++) {
          if (d[i][j] > d[i][k] + d[k][j]) {
            d[i][j] = d[i][k] + d[k][j];
          }
        }
      }
    }
    return d;
  }
};
int h, w;
int check(char x, char y) { return x == '.' && y == '.'; }
void solve() {
  int i, j;
  string str;
  cin >> h >> w;
  vector<string> strs(h);
  for (i = 0; i < h; i++) cin >> strs[i];
  Graph<int> g(h * w);
  for (i = 0; i < h; i++) {
    for (j = 0; j < w; j++) {
      if (j < w - 1 && strs[i][j] == '.' && strs[i][j + 1] == '.') {
        g.add_edge(i * w + j, i * w + j + 1);
      }
      if (i < h - 1 && strs[i][j] == '.' && strs[i + 1][j] == '.') {
        g.add_edge(i * w + j, i * w + w + j);
      }
    }
  }
  vector<vector<int> > res = g.warshall_floyd();
  long long ans = 0;
  for (i = 0; i < res.size(); i++) {
    for (j = 0; j < res[i].size(); j++) {
      if (ans < res[i][j] && res[i][j] != 99999999) ans = res[i][j];
    }
  }
  cout << ans << endl;
}
int main() { solve(); }
