#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
template <class T>
using v = vector<T>;
template <class T, class U>
using p = pair<T, U>;
template <class T>
T read() {
  T x{};
  cin >> x;
  return x;
}
template <class T>
v<T> read(int N) {
  v<T> x(N);
  for (ll i = 0; i < N; ++i) cin >> x[i];
  return x;
}
template <class T>
void write(const T &x) {
  cout << x << endl;
}
void write(double x) { printf("%.15f\n", x); }
template <class T>
T &chmin(T &obj, T val) {
  return obj = min(obj, val);
}
template <class T>
T &chmax(T &obj, T val) {
  return obj = max(obj, val);
}
template <class Pred>
ll bsearch(ll low, ll high, Pred pred) {
  while (low + 1 < high) {
    const ll mid = low + (high - low) / 2;
    if (pred(mid)) {
      low = mid;
    } else {
      high = mid;
    }
  }
  return low;
}
const ll MOD = (ll)1e9 + 7;
const ll INF = (ll)1e15;
ll S[20][20] = {};
ll dist[400][400] = {};
int main() {
  ll H, W;
  cin >> H >> W;
  ll N = 0;
  for (ll h = 0; h < H; ++h) {
    for (ll w = 0; w < W; ++w) {
      char c;
      cin >> c;
      if (c == '.') {
        S[h][w] = N++;
      }
      if (c == '#') {
        S[h][w] = -1;
      }
    }
  }
  if (H == 1 && W == 1) {
    cout << 0 << endl;
    return 0;
  }
  if (N == 0) {
    cout << 0 << endl;
    return 0;
  }
  for (ll i = 0; i < N; ++i)
    for (ll j = 0; j < N; ++j) dist[i][j] = INF;
  for (ll h = 0; h < H; ++h)
    for (ll w = 0; w < W; ++w) {
      ll n = S[h][w];
      if (n < 0) continue;
      ll n2 = h > 0 ? S[h - 1][w] : -1;
      ll n3 = w > 0 ? S[h][w - 1] : -1;
      if (n2 >= 0) dist[n][n2] = dist[n2][n] = 1;
      if (n3 >= 0) dist[n][n3] = dist[n3][n] = 1;
    }
  for (int k = 0; k < N; k++)
    for (int i = 0; i < N; i++)
      for (int j = 0; j < N; j++)
        dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
  ll ans = 0;
  for (int i = 0; i < N; i++)
    for (int j = 0; j < N; j++) chmax(ans, dist[i][j]);
  write(ans);
}
