#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using edge = struct {
  int to;
  ll cost;
};
long long combination[10001][10001];
int h, w;
char maze[100][100];
bool mazeVisit[100][100];
int mazeDis[100][100];
queue<pair<int, int>> mazeQ;
void mazeBFS();
void mazeInit();
int ans = 0;
void solve() {
  cin >> h >> w;
  for (int i = 1; i <= h; i++) {
    for (int j = 1; j <= w; j++) cin >> maze[i][j];
  }
  for (int i = 1; i <= h; i++) {
    for (int j = 1; j <= w; j++) {
      if (maze[i][j] == '.') {
        mazeInit();
        mazeQ.push(make_pair(i, j));
        while (!mazeQ.empty()) {
          mazeBFS();
        }
      }
    }
  }
  cout << ans << "\n";
}
int main() {
  solve();
  return 0;
}
void initC(int n) {
  combination[0][0] = 1ll;
  for (int i = 1; i <= n; i++) {
    combination[i][0] = 1ll;
    combination[i][i] = 1ll;
    for (int j = 1; j <= i - 1; j++) {
      combination[i][j] = combination[i - 1][j] + combination[i - 1][j - 1];
    }
  }
}
void mazeInit() {
  for (int i = 0; i <= h + 1; i++) {
    for (int j = 0; j <= w + 1; j++) {
      if (i == 0 || i == h + 1 || j == 0 || j == w + 1)
        mazeVisit[i][j] = true;
      else if (maze[i][j] == '.')
        mazeVisit[i][j] = false;
      else
        maze[i][j] = true;
      mazeDis[i][j] = 0;
    }
  }
}
void mazeBFS() {
  auto now = mazeQ.front();
  mazeQ.pop();
  int i = now.first, j = now.second;
  mazeVisit[i][j] = true;
  ans = max(ans, mazeDis[i][j]);
  if (!mazeVisit[i + 1][j]) mazeQ.push(make_pair(i + 1, j));
  mazeDis[i + 1][j] = mazeDis[i][j] + 1;
  if (!mazeVisit[i - 1][j]) mazeQ.push(make_pair(i - 1, j));
  mazeDis[i - 1][j] = mazeDis[i][j] + 1;
  if (!mazeVisit[i][j + 1]) mazeQ.push(make_pair(i, j + 1));
  mazeDis[i][j + 1] = mazeDis[i][j] + 1;
  if (!mazeVisit[i][j - 1]) mazeQ.push(make_pair(i, j - 1));
  mazeDis[i][j - 1] = mazeDis[i][j] + 1;
}
