#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll MOD = (ll)1e9 + 7;
const int INF = (ll)1e9 + 7;
const ll INFLL = (ll)1e18;
const double EPS = 1e-5;
using namespace std;
template <class t>
using vvector = vector<vector<t>>;
template <class t>
using vvvector = vector<vector<vector<t>>>;
template <class t>
using priority_queuer = priority_queue<t, vector<t>, greater<t>>;
template <class t, class u>
bool chmax(t &a, u b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <class t, class u>
bool chmin(t &a, u b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
ll modpow(ll x, ll b) {
  ll res = 1;
  while (b) {
    if (b & 1) res = res * x % MOD;
    x = x * x % MOD;
    b >>= 1;
  }
  return res;
}
ll modinv(ll x) { return modpow(x, MOD - 2); }
bool was_output = false;
template <class t>
void output(t a) {
  if (was_output) cout << " ";
  cout << a;
  was_output = true;
}
void outendl() {
  was_output = false;
  cout << endl;
}
int h, w;
vvector<bool> road;
int mx[] = {1, 0, -1, 0}, my[] = {0, 1, 0, -1};
bool isin(int y, int x) { return y >= 0 && x >= 0 && y < h && x < w; }
pair<int, int> most_far(int y, int x) {
  vvector<int> fast(h, vector<int>(w, INF));
  stack<pair<int, int>> st;
  st.emplace(y, x);
  fast[y][x] = 0;
  while (st.size()) {
    pair<int, int> d = st.top();
    st.pop();
    for (int i = 0; i < (4); ++i) {
      pair<int, int> np = pair<int, int>(d.first + my[i], d.second + mx[i]);
      if (!isin(np.first, np.second)) continue;
      if (road[np.first][np.second] == false) continue;
      int nt = fast[d.first][d.second] + 1;
      if (nt < fast[np.first][np.second]) {
        fast[np.first][np.second] = nt;
        st.emplace(np);
      }
    }
  }
  pair<int, int> res(0, 0);
  for (int i = 0; i < (h); ++i) {
    for (int j = 0; j < (w); ++j) {
      if (fast[i][j] == INF) continue;
      if (fast[res.first][res.second] < fast[i][j]) {
        res = pair<int, int>(i, j);
      }
    }
  }
  return res;
}
int most_dis(int y, int x) {
  vvector<int> fast(h, vector<int>(w, INF));
  stack<pair<int, int>> st;
  st.emplace(y, x);
  fast[y][x] = 0;
  while (st.size()) {
    pair<int, int> d = st.top();
    st.pop();
    for (int i = 0; i < (4); ++i) {
      pair<int, int> np = pair<int, int>(d.first + my[i], d.second + mx[i]);
      if (!isin(np.first, np.second)) continue;
      if (road[np.first][np.second] == false) continue;
      int nt = fast[d.first][d.second] + 1;
      if (nt < fast[np.first][np.second]) {
        fast[np.first][np.second] = nt;
        st.emplace(np);
      }
    }
  }
  int res = 0;
  for (int i = 0; i < (h); ++i) {
    for (int j = 0; j < (w); ++j) {
      if (fast[i][j] == INF) continue;
      chmax(res, fast[i][j]);
    }
  }
  return res;
}
int main() {
  cin >> h >> w;
  road = vvector<bool>(h, vector<bool>(w, false));
  for (int i = 0; i < (h); ++i) {
    for (int j = 0; j < (w); ++j) {
      char d;
      cin >> d;
      road[i][j] = d == '.';
    }
  }
  int ans = 0;
  for (int i = 0; i < (h); ++i) {
    for (int j = 0; j < (w); ++j) {
      if (!road[i][j]) continue;
      pair<int, int> p = most_far(i, j);
      ans = most_dis(p.first, p.second);
      break;
    }
  }
  cout << ans << endl;
  return 0;
}
