#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vl = vector<ll>;
using vvl = vector<vl>;
using vb = vector<bool>;
using P = pair<ll, ll>;
template <typename T>
using pq = priority_queue<T>;
template <typename T>
using minpq = priority_queue<T, vector<T>, greater<T>>;
template <typename T, typename K>
using ump = unordered_map<T, K>;
const ll dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
const ll mod = 1000000007;
const ll inf = ll(1e9);
const ll e5 = ll(1e5);
const ll ll_inf = ll(1e9) * ll(1e9);
template <class T>
ostream &operator<<(ostream &out, const vector<T> &list) {
  ll n = list.size();
  for (ll i = 0; i < (ll)(n); i++) out << list[i] << ' ';
  return out;
}
template <class T>
istream &operator>>(istream &in, vector<T> &list) {
  ll n = list.size();
  for (ll i = 0; i < (ll)(n); i++) in >> list[i];
  return in;
}
template <class T>
ostream &operator<<(ostream &out, const vector<vector<T>> &list) {
  ll n = list.size();
  for (ll i = 0; i < (ll)(n); i++) out << list[i] << '\n';
  return out;
}
void solve() {
  ll h, w;
  cin >> h >> w;
  vector<string> s(h);
  for (ll i = 0; i < (ll)(h); i++) {
    cin >> s[i];
  }
  ll ans = 0;
  for (ll i = 0; i < (ll)(h); i++) {
    for (ll j = 0; j < (ll)(w); j++) {
      if (s[i][j] == '#') continue;
      bool seen[h][w];
      ll d[h][w];
      queue<P> q;
      q.push(make_pair(i, j));
      d[i][j] = 0;
      ll tmp = 0;
      while (!q.empty()) {
        ll x = q.front().first, y = q.front().second;
        seen[x][y] = true;
        q.pop();
        for (ll k = 0; k < (ll)(4); k++) {
          ll nx = x + dx[k], ny = y + dy[k];
          if (nx < 0 || h - 1 < nx || ny < 0 || w - 1 < ny) continue;
          if (seen[nx][ny] || s[nx][ny] == '#') continue;
          d[nx][ny] = d[x][y] + 1;
          tmp = max(tmp, d[nx][ny]);
          q.push(make_pair(nx, ny));
        }
      }
      ans = max(ans, tmp);
    }
  }
  cout << ans << '\n';
}
int main() {
  solve();
  return 0;
}
