#include <bits/stdc++.h>
using namespace std;
const long long mod = 1000000000 + 7;
const long long INF = mod;
using ll = long long;
using P = pair<long long, long long>;
using vl = vector<long long>;
long long gcd(long long m, long long n) {
  long long a = max((ll)m, (ll)n);
  long long b = min((ll)m, (ll)n);
  long long r = a % b;
  while (r != 0) {
    a = b;
    b = r;
    r = a % b;
  }
  return b;
}
long long lcd(long long m, long long n) { return m * n / gcd(m, n); }
long long power(long long x, long long N) {
  long long ret = 1;
  for (long long i = 0; i < N; i++) ret *= x;
  return ret;
}
long long C(long long n, long long r);
long long modC(long long n, long long r) {
  vector<long long> f(n + 1), inv(n + 1), invf(n + 1);
  f[0] = f[1] = 1;
  invf[0] = invf[1] = 1;
  inv[1] = 1;
  for (long long i = 2; i < n + 1; i++) {
    f[i] = (i * f[i - 1]) % mod;
    inv[i] = mod - ((mod / i) * inv[mod % i]) % mod;
    invf[i] = (inv[i] * invf[i - 1]) % mod;
  }
  long long cmb = f[n] * (invf[r] * invf[n - r] % mod) % mod;
  if (n >= r)
    return cmb;
  else
    return 0;
}
map<long long, long long> factor(long long p) {
  ll p1 = p;
  map<long long, long long> ret;
  for (long long i = 2; i * i <= p1; i++) {
    while (p % i == 0) {
      ret[i]++;
      p /= i;
    }
  }
  if (p != 1) ret[p]++;
  return ret;
}
bool is_prime(long long N) {
  for (long long i = 2; i * i <= N; i++) {
    if (N % i == 0) return false;
  }
  return true;
}
void chmax(long long &a, long long b) { a = max((ll)a, (ll)b); }
void chmin(long long &a, long long b) { a = min((ll)a, (ll)b); }
int main() {
  cout << fixed << setprecision(10);
  long long H;
  cin >> H;
  long long W;
  cin >> W;
  vector<vector<char>> maze(H, vector<char>(W));
  for (int i = 0; i < H; i++) {
    for (int j = 0; j < W; j++) {
      cin >> maze[i][j];
    }
  }
  vl dh = {1, 0, -1, 0};
  vl dw = {0, 1, 0, -1};
  ll res = 0;
  for (int sh = 0; sh < H; sh++) {
    for (int sw = 0; sw < W; sw++) {
      if (maze[sh][sw] == '#') continue;
      ll M = 0;
      vector<vector<bool>> undone(H, vector<bool>(W, true));
      vector<vector<ll>> d(H, vector<ll>(W, -INF));
      d[sh][sw] = 0;
      queue<P> Q;
      Q.push(make_pair(sh, sw));
      while (Q.size() > 0) {
        ll h = Q.front().first, w = Q.front().second;
        Q.pop();
        for (int i = 0; i < 4; i++) {
          ll nh = h + dh[i], nw = w + dw[i];
          if (0 <= nh && nh < H && 0 <= nw && nw < W && maze[nh][nw] == '.' &&
              undone[nh][nw]) {
            Q.push(make_pair(nh, nw));
            undone[nh][nw] = false;
            chmax(d[nh][nw], d[h][w] + 1);
          }
        }
      }
      for (int i = 0; i < H; i++) {
        for (int j = 0; j < W; j++) {
          M = max((ll)M, (ll)d[i][j]);
        }
      }
      chmax(res, M);
    }
  }
  cout << res;
}
