#include <bits/stdc++.h>
using namespace std;
int main() {
  int i, j, k;
  int h, w;
  cin >> h >> w;
  vector<string> maze(h);
  for (i = 0; i < h; ++i) {
    cin >> maze.at(i);
  }
  vector<int> ans;
  for (i = 0; i < h; ++i) {
    for (j = 0; j < w; ++j) {
      if (maze.at(i).at(j) == '#') {
        continue;
      }
      int temp_max = 0;
      int temp_num = 0;
      vector<vector<int>> num(h, vector<int>(w, -1));
      vector<vector<bool>> visit(h, vector<bool>(w, false));
      queue<pair<int, int>> que;
      que.emplace(i, j);
      num.at(i).at(j) = 0;
      int tate[4] = {0, 1, 0, -1};
      int yoko[4] = {1, 0, -1, 0};
      while (!que.empty()) {
        int temp_i = que.front().first;
        int temp_j = que.front().second;
        que.pop();
        temp_num = num.at(temp_i).at(temp_j);
        if (temp_num > temp_max) {
          temp_max = temp_num;
        }
        visit.at(temp_i).at(temp_j) = true;
        for (k = 0; k < 4; ++k) {
          int temp_t = temp_i + tate[k];
          int temp_y = temp_j + yoko[k];
          if (temp_t < 0 || temp_t >= h) {
            continue;
          } else if (temp_y < 0 || temp_y >= w) {
            continue;
          } else if (maze.at(temp_t).at(temp_y) == '#') {
            continue;
          }
          if (!(visit.at(temp_t).at(temp_y))) {
            que.emplace(temp_t, temp_y);
            num.at(temp_t).at(temp_y) = temp_num + 1;
          }
        }
      }
      ans.push_back(temp_max);
    }
  }
  sort(ans.begin(), ans.end());
  cout << ans.back() << endl;
  return 0;
}
