#include <bits/stdc++.h>
using namespace std;
const int INF = 1e9;
const int MOD = 1e9 + 7;
const long long LINF = 1e18;
using Graph = vector<vector<int>>;
using Edge = map<pair<int, int>, int>;
template <typename A, size_t N, typename T>
void Fill(A (&array)[N], const T &val) {
  std::fill((T *)array, (T *)(array + N), val);
}
long long gcd(long long a, long long b) {
  if (a % b == 0)
    return (b);
  else
    return (gcd(b, a % b));
}
long long lcm(long long a, long long b) { return a * b / gcd(a, b); }
int dx[] = {1, -1, 0, 0};
int dy[] = {0, 0, 1, -1};
int main() {
  cout << fixed << setprecision(15);
  long long H, W;
  cin >> H >> W;
  vector<vector<char>> S(H + 1, vector<char>(W + 1));
  for (long long i = 1; i <= H; i++) {
    for (long long j = 1; j <= W; j++) {
      cin >> S[i][j];
    }
  }
  long long ans = 0;
  for (long long i = 1; i <= H; i++) {
    for (long long j = 1; j <= W; j++) {
      queue<pair<long long, long long>> que;
      que.push(pair<long long, long long>(i, j));
      vector<vector<long long>> v(H + 1, vector<long long>(W + 1, -1));
      v[i][j] = 0;
      while (true) {
        if (que.empty()) {
          break;
        }
        pair<long long, long long> p = que.front();
        que.pop();
        int x = p.first;
        int y = p.second;
        int s = v[x][y];
        for (long long k = 0; k < (long long)(4); ++k) {
          int nx = x + dx[k];
          int ny = y + dy[k];
          if (nx <= 0 || nx > H || ny <= 0 || ny > W || v[nx][ny] != -1 ||
              S[nx][ny] == '#')
            continue;
          que.push(pair<long long, long long>(nx, ny));
          v[nx][ny] = s + 1;
        }
      }
      for (long long ii = 1; ii <= H; ii++) {
        for (long long jj = 1; jj <= W; jj++) {
          ans = max(ans, v[ii][jj]);
        }
      }
    }
  }
  cout << ans << endl;
  return 0;
}
