#include <bits/stdc++.h>
using namespace std;
bool in_bound(int x, int l, int r) { return l <= x && x < r; }
int n, m;
vector<string> s;
vector<vector<int>> g;
vector<int> dist;
int bfs(int v) {
  for (int i = 0; i < n * m; ++i) {
    dist[i] = INT_MAX;
  }
  queue<int> q;
  q.push(v);
  dist[v] = 0;
  int mx = 0;
  while (!q.empty()) {
    int u = q.front();
    q.pop();
    for (int w : g[u]) {
      if (dist[w] == INT_MAX) {
        dist[w] = dist[u] + 1;
        q.push(w);
        mx = max(mx, dist[w]);
      }
    }
  }
  return mx;
}
int main() {
  cin >> n >> m;
  s.resize(n);
  for (int i = 0; i < n; ++i) {
    cin >> s[i];
  }
  g.resize(n * m);
  dist.resize(n * m);
  int dx[] = {0, 0, 1, -1};
  int dy[] = {-1, 1, 0, 0};
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < m; ++j) {
      if (s[i][j] != '.') continue;
      for (int k = 0; k < 4; ++k) {
        int x = i + dx[k];
        int y = j + dy[k];
        if (in_bound(x, 0, n) && in_bound(y, 0, m) && s[x][y] != '#') {
          g[i * n + j].push_back(x * n + y);
        }
      }
    }
  }
  int v = -1;
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < m; ++j) {
      if (s[i][j] == '.') {
        v = i * n + j;
      }
    }
  }
  int mx_dist = bfs(v);
  for (int i = 0; i < n * m; ++i) {
    if (dist[i] == mx_dist) {
      v = i;
    }
  }
  cout << bfs(v) << '\n';
  return 0;
}
