#include <bits/stdc++.h>
using namespace std;
const int N = 20;
int h, w;
int grid[20][20];
int getdist(pair<int, int> start, pair<int, int> end) {
  int visited[h][w];
  memset(visited, 0, sizeof(visited));
  queue<pair<int, int>> q;
  q.push(start);
  visited[start.first][start.second] = 1;
  auto isValid = [&](int dx, int dy) {
    if (dx < 0 or dx >= h or dy < 0 or dy >= w) {
      return false;
    }
    if (grid[dx][dy] == 1) {
      return false;
    }
    return true;
  };
  while (!q.empty()) {
    auto pt = q.front();
    q.pop();
    int x = pt.first;
    int y = pt.second;
    vector<int> dx = {1, -1, 0, 0};
    vector<int> dy = {0, 0, 1, -1};
    for (int i = 0; i < 4; ++i) {
      if (isValid(x + dx[i], y + dy[i]) and
          visited[x + dx[i]][y + dy[i]] == 0) {
        visited[x + dx[i]][y + dy[i]] = 1 + visited[x][y];
        pair<int, int> nxt = {x + dx[i], y + dy[i]};
        q.push(nxt);
      }
    }
  }
  return visited[end.first][end.second];
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cin >> h >> w;
  vector<pair<int, int>> pts;
  for (int i = 0; i < h; ++i) {
    string x;
    cin >> x;
    for (int j = 0; j < w; ++j) {
      if (x[j] == '.') {
        grid[i][j] = 0;
        pts.push_back({i, j});
      } else {
        grid[i][j] = 1;
      }
    }
  }
  int max_ans = 0;
  for (int i = 0; i < pts.size(); ++i) {
    for (int j = i + 1; j < pts.size(); ++j) {
      max_ans = max(max_ans, getdist(pts[i], pts[j]));
    }
  }
  cout << max_ans - 1 << '\n';
  return 0;
}
