#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vi = vector<ll>;
using vvi = vector<vi>;
using vs = vector<string>;
constexpr ll inf = 1ll << 61;
template <class T>
bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
class warshallfloyd {
 public:
  vector<vector<ll>> dist;
  vector<vector<ll>> prev;
  warshallfloyd(const vector<vector<ll>> &g) : dist(g) {
    ll n = dist.size();
    prev.resize(n);
    for (ll i = 0, i_cond = (n); i < i_cond; ++i) {
      prev[i].resize(n);
      for (ll j = 0, j_cond = (n); j < j_cond; ++j) prev[i][j] = i;
    }
    for (ll k = 0, k_cond = (n); k < k_cond; ++k)
      for (ll i = 0, i_cond = (n); i < i_cond; ++i)
        for (ll j = 0, j_cond = (n); j < j_cond; ++j)
          if (dist[i][j] > dist[i][k] + dist[k][j]) {
            dist[i][j] = dist[i][k] + dist[k][j];
            prev[i][j] = prev[k][j];
          }
  }
};
ll h, w;
vector<ll> dx = {1, 0, -1, 0}, dy = {0, 1, 0, -1};
bool isin(ll x, ll y) {
  bool ans;
  if (0 <= x and x < h and 0 <= y and y < w)
    ans = true;
  else
    ans = false;
  return ans;
}
signed main() {
  cin >> h >> w;
  ll n = h * w;
  vs s(h);
  for (ll i = 0, i_cond = (h); i < i_cond; ++i) cin >> s[i];
  vvi g(n, vi(n, inf));
  for (ll i = 0, i_cond = (n); i < i_cond; ++i) g[i][i] = 0;
  for (ll i = 0, i_cond = (h); i < i_cond; ++i)
    for (ll j = 0, j_cond = (w); j < j_cond; ++j) {
      if (s[i][j] == '#') continue;
      for (ll k = 0, k_cond = (4); k < k_cond; ++k) {
        ll nx = i + dx[k], ny = j + dy[k];
        if (isin(nx, ny) and s[nx][ny] == '.') g[h * i + j][h * nx + ny] = 1;
      }
    }
  struct warshallfloyd wf(g);
  ll ans = 0;
  for (ll i = 0, i_cond = (n); i < i_cond; ++i)
    for (ll j = 0, j_cond = (n); j < j_cond; ++j)
      if (wf.dist[i][j] != inf) chmax(ans, wf.dist[i][j]);
  cout << ans << endl;
}
