#include <bits/stdc++.h>
using namespace std;
using Pair = pair<int64_t, int64_t>;
constexpr int64_t kInf = INT64_MAX / 2L;
const int64_t di[] = {-1, 0, 1, 0};
const int64_t dj[] = {0, -1, 0, 1};
int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  int64_t H, W;
  cin >> H >> W;
  vector<vector<bool>> grid(H, vector<bool>(W, false));
  for (int64_t r = 0; r < H; ++r) {
    string s;
    cin >> s;
    for (int64_t c = 0; c < W; ++c) {
      grid[r][c] = (s[c] == '.');
    }
  }
  int64_t max_distance = 0;
  for (int64_t start_r = 0; start_r < H; ++start_r) {
    for (int64_t start_c = 0; start_c < W; ++start_c) {
      vector<vector<int64_t>> distances(H, vector<int64_t>(W, kInf));
      queue<Pair> q;
      distances[start_r][start_c] = 0;
      q.emplace(start_r, start_c);
      while (!q.empty()) {
        const Pair target = q.front();
        q.pop();
        const int64_t t_distance = distances[target.first][target.second];
        for (int64_t n = 0; n < 4; ++n) {
          const Pair next(target.first + di[n], target.second + dj[n]);
          if (next.first >= 0 && next.first < H && next.second >= 0 &&
              next.second < W) {
            if (grid[next.first][next.second] &&
                t_distance + 1 < distances[next.first][next.second]) {
              distances[next.first][next.second] = t_distance + 1;
              q.emplace(next.first, next.second);
            }
          }
        }
      }
      for (int64_t r = 0; r < H; ++r) {
        for (int64_t c = 0; c < W; ++c) {
          if (grid[r][c]) {
            max_distance = max(max_distance, distances[r][c]);
          }
        }
      }
    }
  }
  cout << max_distance << endl;
  return 0;
}
