#include <bits/stdc++.h>
using namespace std;
vector<int> idy = {1, 0, -1, 0};
vector<int> idx = {0, 1, 0, -1};
pair<int, int> start;
bool check(vector<string> m, vector<vector<int>> dp) {
  for (int i = 0; i < m.size(); i++) {
    for (int j = 0; j < m.at(0).size(); j++) {
      if (dp.at(i).at(j) == -1 && m.at(i).at(j) == '.') {
        start = pair<int, int>(i, j);
        return true;
      }
    }
  }
  return false;
}
int main() {
  int h, w;
  cin >> h >> w;
  vector<string> maze(h);
  for (int i = 0; i < h; i++) {
    cin >> maze.at(i);
  }
  vector<vector<int>> dp1(h, vector<int>(w, -1));
  vector<vector<int>> dp2(h, vector<int>(w, -1));
  int ans = 0;
  queue<pair<int, int>> q;
  pair<int, int> maxp;
  dp1.at(start.first).at(start.second) = 0;
  q.push(start);
  while (q.size()) {
    pair<int, int> now = q.front();
    q.pop();
    for (int i = 0; i < 4; i++) {
      int ny = now.first + idy.at(i);
      int nx = now.second + idx.at(i);
      if (ny > -1 && nx > -1 && ny < h && nx < w) {
        if (dp1.at(ny).at(nx) == -1 && maze.at(ny).at(nx) == '.') {
          dp1.at(ny).at(nx) = dp1.at(now.first).at(now.second) + 1;
          maxp = pair<int, int>(ny, nx);
          q.push(pair<int, int>(ny, nx));
        }
      }
    }
  }
  dp2.at(maxp.first).at(maxp.second) = 0;
  q.push(maxp);
  while (q.size()) {
    pair<int, int> now = q.front();
    q.pop();
    for (int i = 0; i < 4; i++) {
      int ny = now.first + idy.at(i);
      int nx = now.second + idx.at(i);
      if (ny > -1 && nx > -1 && ny < h && nx < w) {
        if (dp2.at(ny).at(nx) == -1 && maze.at(ny).at(nx) == '.') {
          dp2.at(ny).at(nx) = dp2.at(now.first).at(now.second) + 1;
          ans = max(ans, dp2.at(ny).at(nx));
          q.push(pair<int, int>(ny, nx));
        }
      }
    }
  }
  cout << ans << endl;
}
