#include <bits/stdc++.h>
using namespace std;
bool graph[23][23] = {};
int bfs_ans(int si, int sj) {
  queue<tuple<int, int, int>> que;
  que.push(make_tuple(si, sj, 0));
  bool clr[23][23] = {};
  int ans = 0;
  while (!que.empty()) {
    tuple<int, int, int> q = que.front();
    if (graph[get<0>(q) + 1][get<1>(q)] && !clr[get<0>(q) + 1][get<1>(q)]) {
      clr[get<0>(q) + 1][get<1>(q)] = true;
      que.push(make_tuple(get<0>(q) + 1, get<1>(q), get<2>(q) + 1));
    }
    if (graph[get<0>(q) - 1][get<1>(q)] && !clr[get<0>(q) - 1][get<1>(q)]) {
      clr[get<0>(q) - 1][get<1>(q)] = true;
      que.push(make_tuple(get<0>(q) - 1, get<1>(q), get<2>(q) + 1));
    }
    if (graph[get<0>(q)][1 + get<1>(q)] && !clr[get<0>(q)][1 + get<1>(q)]) {
      clr[get<0>(q)][1 + get<1>(q)] = true;
      que.push(make_tuple(get<0>(q), get<1>(q) + 1, get<2>(q) + 1));
    }
    if (graph[get<0>(q)][get<1>(q) - 1] && !clr[get<0>(q)][get<1>(q) - 1]) {
      clr[get<0>(q)][get<1>(q) - 1] = true;
      que.push(make_tuple(get<0>(q), get<1>(q) - 1, get<2>(q) + 1));
    }
    ans = get<2>(q);
    que.pop();
  }
  return ans;
}
int main() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);
  int h, w;
  cin >> h >> w;
  for (int i = 1; i < h + 1; i++) {
    for (int j = 1; j < w + 1; j++) {
      char pt;
      cin >> pt;
      if (pt == '.')
        graph[i][j] = true;
      else
        graph[i][j] = false;
    }
  }
  int ans = 0;
  for (int i = 1; i < h + 1; i++) {
    for (int j = 1; j < w + 1; j++) {
      if (graph[i][j]) ans = max(ans, bfs_ans(i, j));
    }
  }
  cout << ans << endl;
}
