#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 = H * W;
  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 hw = h * W + w;
      char c;
      cin >> c;
      if (c == '.') {
        S[h][w] = 1;
        if (h > 0 && S[h - 1][w] == 1) {
          dist[hw - W][hw] = dist[hw][hw - W] = 1;
        }
        if (w > 0 && S[h][w - 1] == 1) {
          dist[hw - 1][hw] = dist[hw][hw - 1] = 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++)
      if (S[i / W][i % W] && S[j / W][j % W]) chmax(ans, dist[i][j]);
  write(ans);
}
