#include <bits/stdc++.h>
using ll = long long;
using namespace std;
struct point {
  int x, y;
  int dp;
};
int main() {
  int h, w;
  cin >> h >> w;
  vector<vector<char>> maze(w, vector<char>(h));
  int loadcnt = 0;
  string ipt = "";
  for (int _h = 0; _h < h; ++_h) {
    cin >> ipt;
    for (int _w = 0; _w < w; ++_w) {
      maze[_w][_h] = ipt[_w];
      if (maze[_w][_h] == '.') loadcnt++;
    }
  }
  int mx[] = {1, -1, 0, 0}, my[] = {0, 0, 1, -1};
  int mxlen = 0;
  point bgn = {0, 0, 0};
  point now = {0, 0, 0};
  point next = {0, 0, 0};
  vector<vector<char>> tmaze;
  for (int by = 0; by < h; ++by) {
    for (int bx = 0; bx < w; ++bx) {
      bgn = {bx, by, 0};
      queue<point> que;
      que.push(bgn);
      tmaze = maze;
      now = {0, 0, 0};
      while (!que.empty()) {
        now = que.front();
        que.pop();
        for (int i = 0; i < 4; ++i) {
          next = {now.x + mx[i], now.y + my[i], now.dp + 1};
          if (next.x >= 0 && next.x < w && next.y >= 0 && next.y < h) {
            if (tmaze[next.x][next.y] == '.') {
              tmaze[next.x][next.y] = 'x';
              que.push(next);
            }
          }
        }
        mxlen = max(mxlen, now.dp);
      }
    }
  }
  cout << mxlen << endl;
  return 0;
}
