#include <bits/stdc++.h>
using namespace std;
long long solve(vector<vector<bool>> ADJ) {
  long long dist = 0;
  long long N = ADJ.size();
  vector<vector<long long>> MD(N, vector<long long>(N, 1000000001));
  for (long long i = 0; i < N; i++) {
    for (long long j = 0; j < N; j++) {
      if (ADJ[i][j] == true) {
        MD[i][j] = 1;
        dist = 1;
      }
    }
  }
  for (long long k = 0; k < N; k++) {
    for (long long i = 0; i < N; i++) {
      for (long long j = 0; j < N; j++) {
        if (MD[i][j] > MD[i][k] + MD[k][j]) {
          MD[i][j] = MD[i][k] + MD[k][j];
        }
      }
    }
  }
  for (long long i = 0; i < MD.size(); i++) {
    for (const auto& e : MD[i]) {
      if (e < 1000000000) {
        if (dist < e) dist = e;
      }
    }
  }
  return dist;
}
int main() {
  long long H, W;
  cin >> H >> W;
  vector<vector<bool>> M(H, vector<bool>(W, false));
  for (long long i = 0; i < H; i++) {
    for (long long j = 0; j < W; j++) {
      char a;
      cin >> a;
      if (a == '.') M[i][j] = true;
    }
  }
  vector<vector<bool>> ADJ(H * W, vector<bool>(H * W, false));
  for (long long i = 0; i < H; i++) {
    for (long long j = 0; j < W; j++) {
      long long from = W * i + j;
      if (M[i][j] == true) {
        if (j < W - 1) {
          if (M[i][j + 1] == true) {
            long long to = W * i + j + 1;
            ADJ[from][to] = true;
            ADJ[to][from] = true;
          }
        }
        if (i < H - 1) {
          if (M[i + 1][j] == true) {
            long long to = W * (i + 1) + j;
            ADJ[from][to] = true;
            ADJ[to][from] = true;
          }
        }
      } else {
      }
    }
  }
  long long dist = solve(ADJ);
  cout << dist << endl;
  return 0;
}
