#include <bits/stdc++.h>
using namespace std;
vector<vector<char>> field;
vector<vector<int>> d;
vector<vector<int>> used;
int n, m, asd = 1, ans = 0;
bool can(int i, int j) {
  return i >= 0 && j >= 0 && i < n && j < m && field[i][j] == '.' &&
         used[i][j] != asd;
}
signed main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  cin >> n >> m;
  field.resize(n, vector<char>(m));
  d.resize(n, vector<int>(m));
  used.resize(n, vector<int>(m, 0));
  for (int i = 0; i < n; i++)
    for (int j = 0; j < m; j++) cin >> field[i][j];
  for (int i = 0; i < n; i++)
    for (int j = 0; j < m; j++) {
      if (field[i][j] == '#') continue;
      pair<int, int> u = {i, j};
      queue<pair<int, int>> s;
      s.push({u.first, u.second});
      d[u.first][u.second] = 0;
      while (!s.empty()) {
        auto cur = s.front();
        used[cur.first][cur.second] = asd;
        s.pop();
        ans = max(ans, d[cur.first][cur.second]);
        if (can(cur.first - 1, cur.second))
          s.push({cur.first - 1, cur.second}),
              d[cur.first - 1][cur.second] = d[cur.first][cur.second] + 1;
        if (can(cur.first + 1, cur.second))
          s.push({cur.first + 1, cur.second}),
              d[cur.first + 1][cur.second] = d[cur.first][cur.second] + 1;
        if (can(cur.first, cur.second - 1))
          s.push({cur.first, cur.second - 1}),
              d[cur.first][cur.second - 1] = d[cur.first][cur.second] + 1;
        if (can(cur.first, cur.second + 1))
          s.push({cur.first, cur.second + 1}),
              d[cur.first][cur.second + 1] = d[cur.first][cur.second] + 1;
      }
      asd++;
    }
  cout << ans << "\n";
  return 0;
}
