#include <bits/stdc++.h>
using namespace std;
using Graph = vector<vector<long long>>;
long long gcd(long long a, long long b) { return b ? gcd(b, a % b) : a; }
long long lcm(long long a, long long b) { return a / gcd(a, b) * b; }
void dfs(int h, int w, const vector<vector<char>> &field,
         vector<vector<int>> &mp) {
  int H = field.size();
  int W = field[0].size();
  for (int i; i < 4; i++) {
    int dh = 0;
    int dw = 0;
    if (i == 0)
      dw = -1;
    else if (i == 1)
      dw = 1;
    else if (i == 2)
      dh = -1;
    else if (i == 3)
      dh = 1;
    int nh = h + dh;
    int nw = w + dw;
    if (nh < 0 || nh >= H || nw < 0 || nw >= W) continue;
    if (field[nh][nw] == '.') {
      if (mp[nh][nw] > mp[h][w] + 1 || mp[nh][nw] == -1) {
        mp[nh][nw] = mp[h][w] + 1;
        dfs(nh, nw, field, mp);
      }
    }
  }
}
int main() {
  int H, W;
  cin >> H >> W;
  vector<vector<char>> field(H, vector<char>(W));
  vector<vector<int>> f_mp(H, vector<int>(W, -1));
  for (long long i = 0; i < H; i++) {
    for (long long j = 0; j < W; j++) {
      cin >> field[i][j];
    }
  }
  f_mp[0][0] = 0;
  dfs(0, 0, field, f_mp);
  int max_h = 0, max_w = 0;
  int max_mp = 0;
  for (long long i = 0; i < H; i++) {
    for (long long j = 0; j < W; j++) {
      if (max_mp < f_mp[i][j]) {
        max_mp = f_mp[i][j];
        max_h = i;
        max_w = j;
      }
    }
  }
  vector<vector<int>> re_mp(H, vector<int>(W, -1));
  re_mp[max_h][max_w] = 0;
  dfs(max_h, max_w, field, re_mp);
  max_h = 0, max_w = 0;
  max_mp = 0;
  for (long long i = 0; i < H; i++) {
    for (long long j = 0; j < W; j++) {
      if (max_mp < re_mp[i][j]) {
        max_mp = re_mp[i][j];
        max_h = i;
        max_w = j;
      }
    }
  }
  vector<vector<int>> rere_mp(H, vector<int>(W, -1));
  rere_mp[max_h][max_w] = 0;
  dfs(max_h, max_w, field, rere_mp);
  max_h = 0, max_w = 0;
  max_mp = 0;
  for (long long i = 0; i < H; i++) {
    for (long long j = 0; j < W; j++) {
      if (max_mp < rere_mp[i][j]) {
        max_mp = rere_mp[i][j];
        max_h = i;
        max_w = j;
      }
    }
  }
  vector<vector<int>> rerere_mp(H, vector<int>(W, -1));
  rerere_mp[max_h][max_w] = 0;
  dfs(max_h, max_w, field, rerere_mp);
  int ans = 0;
  for (long long i = 0; i < H; i++) {
    for (long long j = 0; j < W; j++) {
      if (ans < rerere_mp[i][j]) {
        ans = rerere_mp[i][j];
      }
    }
  }
  cout << ans << endl;
  return 0;
}
