#include <bits/stdc++.h>
using namespace std;
long long mod = 1e9 + 7;
long long inf = 1e18;
int H;
int W;
int start_y, start_x;
const int NODE_SIZE = 20;
string S[NODE_SIZE];
int field[NODE_SIZE][NODE_SIZE];
string field_s[NODE_SIZE];
int d[NODE_SIZE][NODE_SIZE];
int dx[4] = {0, 1, 0, -1};
int dy[4] = {-1, 0, 1, 0};
int next_start_y, next_start_x;
int max_dist;
void bfs_field() {
  queue<pair<int, int>> q;
  bool visited[NODE_SIZE][NODE_SIZE];
  for (long long i = (0); i < (H); i++)
    for (long long j = (0); j < (W); j++) visited[i][j] = false;
  for (long long i = (0); i < (H); i++)
    for (long long j = (0); j < (W); j++) d[i][j] = -1;
  q.push({start_y, start_x});
  d[start_y][start_x] = 0;
  while (!q.empty()) {
    int cur_y = q.front().first;
    int cur_x = q.front().second;
    int curStep = d[cur_y][cur_x];
    q.pop();
    if (visited[cur_y][cur_x]) continue;
    visited[cur_y][cur_x] = true;
    if (d[cur_y][cur_x] > max_dist) {
      next_start_y = cur_y;
      next_start_x = cur_x;
      max_dist = d[cur_y][cur_x];
    }
    for (long long k = (0); k < (4); k++) {
      int next_y = cur_y + dy[k];
      int next_x = cur_x + dx[k];
      if (!((0) <= (next_y) && (next_y) < (H)) ||
          !((0) <= (next_x) && (next_x) < (W)))
        continue;
      if (S[next_y][next_x] == '#') continue;
      if (!visited[next_y][next_x]) {
        q.push({next_y, next_x});
        d[next_y][next_x] = d[cur_y][cur_x] + 1;
      }
    }
  }
}
int main() {
  cin >> H >> W;
  for (long long i = (0); i < (H); i++) {
    cin >> S[i];
  }
  for (long long i = (0); i < (H); i++) {
    for (long long j = (0); j < (W); j++) {
      if (S[i][j] == '.') {
        start_y = i;
        start_x = j;
        break;
      }
    }
  }
  bfs_field();
  start_y = next_start_y;
  start_x = next_start_x;
  max_dist = 0;
  bfs_field();
  cout << (max_dist) << endl;
  return 0;
}
