#include <bits/stdc++.h>
using namespace std;
typedef struct {
  int x;
  int y;
} pos_t;
int isin(int);
int icos(int);
int main(void) {
  int H, W;
  cin >> H >> W;
  bool MAP[H + 2][W + 2];
  for (int i = 1; i <= H + 1; i++) {
    MAP[i][0] = false;
    MAP[i - 1][W + 1] = false;
  }
  for (int i = 1; i <= W + 1; i++) {
    MAP[0][i + 1] = false;
    MAP[H + 1][i] = false;
  }
  for (int y = 1; y <= H; y++) {
    string line;
    cin >> line;
    for (int x = 1; x <= W; x++) {
      if (line[x - 1] == '.') {
        MAP[y][x] = true;
      } else {
        MAP[y][x] = false;
      }
    }
  }
  int ans = 0;
  for (int y = 1; y <= H; y++) {
    for (int x = 1; x <= W; x++) {
      if (!MAP[y][x]) continue;
      vector<pos_t> curr, next;
      bool canPass[H + 2][W + 2];
      memcpy(canPass, MAP, sizeof(canPass));
      pos_t S;
      S.x = x;
      S.y = y;
      canPass[S.y][S.x] = false;
      next.push_back(S);
      int move = -1;
      while (!next.empty()) {
        move++;
        curr = next;
        next.clear();
        for (auto it = curr.begin(); it != curr.end(); it++) {
          for (int th = 0; th < 4; th++) {
            int dy, dx;
            dy = isin(th);
            dx = icos(th);
            if (canPass[it->y + dy][it->x + dx]) {
              pos_t ne;
              ne.y = it->y + dy;
              ne.x = it->x + dx;
              canPass[ne.y][ne.x] = false;
              next.push_back(ne);
            }
          }
        }
      }
      if (move > ans) ans = move;
    }
  }
  cout << ans << endl;
  return 0;
}
int isin(int th) { return ((th & 1) == 0 ? 0 : 1) * ((th & 2) == 0 ? 1 : -1); }
int icos(int th) { return ((th & 1) == 0 ? 1 : 0) * ((th & 2) == 0 ? 1 : -1); }
