#include <bits/stdc++.h>
using namespace std;
long long INFl = 1e+18 + 1;
int INF = 1e+9 + 1;
int N;
vector<pair<int, int> > adj[500];
int d[10000], color[10000], p[10000];
void dijkstra(int st) {
  priority_queue<pair<int, int> > PQ;
  for (int i = 0; i < N; i++) {
    d[i] = INF;
    color[i] = 0;
  }
  d[st] = 0;
  color[st] = 1;
  PQ.push(make_pair(0, st));
  while (!PQ.empty()) {
    pair<int, int> f = PQ.top();
    PQ.pop();
    int u = f.second;
    color[u] = 2;
    if (d[u] < -f.first) continue;
    for (int j = 0; j < adj[u].size(); j++) {
      int v = adj[u][j].first;
      if (color[v] == 2) continue;
      if (d[v] > d[u] + adj[u][j].second) {
        d[v] = d[u] + adj[u][j].second;
        PQ.push(make_pair(-d[v], v));
        color[v] = 1;
      }
    }
  }
}
int main() {
  int H, W;
  char S[25][25];
  int sti, stj;
  cin >> H >> W;
  N = H * W;
  for (int i = 0; i < H; i++) {
    cin >> S[i];
  }
  for (int i = 0; i < H; i++)
    for (int j = 0; j < W; j++)
      if (S[i][j] == '.') sti = i, stj = j;
  for (int i = 0; i < H; i++) {
    for (int j = 0; j < W - 1; j++) {
      if (S[i][j] == '.' && S[i][j + 1] == '.') {
        adj[i * W + j].push_back({i * W + j + 1, 1});
        adj[i * W + j + 1].push_back({i * W + j, 1});
      }
    }
  }
  for (int j = 0; j < W; j++) {
    for (int i = 0; i < H - 1; i++) {
      if (S[i][j] == '.' && S[i + 1][j] == '.') {
        adj[i * W + j].push_back({(i + 1) * W + j, 1});
        adj[(i + 1) * W + j].push_back({i * W + j, 1});
      }
    }
  }
  dijkstra(sti * W + stj);
  int dmax = 0, mi, mj;
  for (int i = 0; i < H; i++)
    for (int j = 0; j < W; j++)
      if (dmax < d[i * W + j] && d[i * W + j] != INF)
        mi = i, mj = j, dmax = d[i * W + j];
  dijkstra(mi * W + mj);
  int ans = 0;
  for (int i = 0; i < H; i++)
    for (int j = 0; j < W; j++)
      if (d[i * W + j] != INF) ans = max(ans, d[i * W + j]);
  cout << ans << endl;
  return 0;
}
