#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using Point = pair<int, int>;
const int MOD = (int)1e9 + 7;
bool is_valid_point(const int H, const int W, const vector<vector<bool>> S,
                    const int y, const int x) {
  return 0 <= y && y < H && 0 <= x && x < W && S.at(y).at(x);
}
vector<Point> get_next_points(const int y, const int x) {
  vector<Point> ans(4);
  ans.at(0) = make_pair(y, x + 1);
  ans.at(1) = make_pair(y, x - 1);
  ans.at(2) = make_pair(y + 1, x);
  ans.at(3) = make_pair(y - 1, x);
  return ans;
}
int distance(const int H, const int W, const vector<vector<bool>> S,
             const int start_h, const int start_w, const int goal_h,
             const int goal_w) {
  vector<vector<int>> d(H, vector<int>(W, -1));
  d.at(start_h).at(start_w) = 0;
  queue<Point> q;
  q.push(make_pair(start_h, start_w));
  while (!q.empty()) {
    Point p = q.front();
    q.pop();
    int y = p.first;
    int x = p.second;
    vector<Point> next_points = get_next_points(y, x);
    for (auto next_p : next_points) {
      int next_y = next_p.first;
      int next_x = next_p.second;
      if (!is_valid_point(H, W, S, next_y, next_x)) {
        continue;
      }
      if (d.at(next_y).at(next_x) != -1) {
        continue;
      }
      int new_distance = d.at(y).at(x) + 1;
      d.at(next_y).at(next_x) = new_distance;
      q.push(next_p);
    }
  }
  return d.at(goal_h).at(goal_w);
}
signed main() {
  int H, W;
  cin >> H >> W;
  vector<vector<bool>> S(H, vector<bool>(W, false));
  for (int h = 0; h < (H); ++h) {
    string s;
    cin >> s;
    for (int w = 0; w < (W); ++w) {
      if (s.at(w) == '.') {
        S.at(h).at(w) = true;
      } else if (s.at(w) == '#') {
        S.at(h).at(w) = false;
      }
    }
  }
  int ans = 0;
  for (int start_h = 0; start_h < (H); ++start_h) {
    for (int start_w = 0; start_w < (W); ++start_w) {
      if (!S.at(start_h).at(start_w)) {
        continue;
      }
      for (int goal_h = 0; goal_h < (H); ++goal_h) {
        for (int goal_w = 0; goal_w < (W); ++goal_w) {
          if (!S.at(goal_h).at(goal_w)) {
            continue;
          }
          if (start_h == goal_h && start_w == goal_w) {
            continue;
          }
          int d = distance(H, W, S, start_h, start_w, goal_h, goal_w);
          ans = max(ans, d);
        }
      }
    }
  }
  cout << ans << endl;
}
