#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
int R, C;
int g[30][30];
int dist[30][30];
bool visit[30][30];
int dir[5] = {-1, 0, 1, 0, -1};
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  cin >> R >> C;
  pair<int, int> st;
  memset(g, 0, sizeof(g));
  for (int r = 0; r < R; r++) {
    string row;
    cin >> row;
    for (int c = 0; c < C; c++) {
      g[r][c] = row[c];
      if (g[r][c] == '.') st = {r, c};
    }
  }
  queue<pair<int, int>> q;
  q.push(st);
  memset(visit, false, sizeof(visit));
  int maxi = 0;
  while (!q.empty()) {
    int n = q.size();
    for (int i = 0; i < n; i++) {
      auto top = q.front();
      q.pop();
      int r = top.first, c = top.second;
      for (int d = 0; d < 4; d++) {
        int dr = top.first + dir[d];
        int dc = top.second + dir[d + 1];
        if (dr < 0 || dr >= R || dc < 0 || dc >= C || visit[dr][dc] ||
            g[dr][dc] == '#')
          continue;
        dist[dr][dc] = dist[r][c] + 1;
        visit[dr][dc] = true;
        if (dist[dr][dc] > maxi) {
          maxi = dist[dr][dc];
          st = {dr, dc};
        }
        q.push({dr, dc});
      }
    }
  }
  q.push(st);
  maxi = 0;
  memset(visit, false, sizeof(visit));
  memset(dist, 0, sizeof(dist));
  while (!q.empty()) {
    int n = q.size();
    for (int i = 0; i < n; i++) {
      auto top = q.front();
      q.pop();
      int r = top.first, c = top.second;
      for (int d = 0; d < 4; d++) {
        int dr = top.first + dir[d];
        int dc = top.second + dir[d + 1];
        if (dr < 0 || dr >= R || dc < 0 || dc >= C || visit[dr][dc] ||
            g[dr][dc] == '#')
          continue;
        dist[dr][dc] = dist[r][c] + 1;
        visit[dr][dc] = true;
        if (dist[dr][dc] > maxi) {
          maxi = dist[dr][dc];
        }
        q.push({dr, dc});
      }
    }
  }
  cout << maxi << endl;
}
