#include <bits/stdc++.h>
void read_from_cin() {}
template <typename T, typename... Ts>
void read_from_cin(T& value, Ts&... args) {
  std::cin >> value;
  read_from_cin(args...);
}
template <typename T>
void write_to_cout(const T& value) {
  std::cout << value << std::endl;
}
template <typename T, typename... Ts>
void write_to_cout(const T& value, const Ts&... args) {
  std::cout << value << ' ';
  write_to_cout(args...);
}
using ll = long long;
using namespace std;
int main() {
  int H, W;
  read_from_cin(H, W);
  ;
  vector<string> m(H);
  for (int i = 0; i < (int)(H); ++i) cin >> m[i];
  int ans = 0;
  for (int sr = 0; sr < (int)(H); ++sr)
    for (int sc = 0; sc < (int)(W); ++sc)
      for (int gr = 0; gr < (int)(H); ++gr)
        for (int gc = 0; gc < (int)(W); ++gc) {
          if (m[sr][sc] != '.' || m[gr][gc] != '.') continue;
          queue<tuple<int, int, int>> que;
          que.push(make_tuple(sr, sc, 0));
          set<pair<int, int>> seen;
          seen.insert({sr, sc});
          while (!que.empty()) {
            int cr, cc, dist;
            tie(cr, cc, dist) = que.front();
            que.pop();
            if (cr == gr && cc == gc) {
              ans = max(ans, dist);
              break;
            }
            for (int d = 0; d < (int)(4); ++d) {
              int dr[] = {0, 0, 1, -1};
              int dc[] = {1, -1, 0, 0};
              int nr = cr + dr[d];
              int nc = cc + dc[d];
              if (nr < 0 || H <= nr || nc < 0 || W <= nc || m[nr][nc] != '.')
                continue;
              if (seen.count({nr, nc})) continue;
              seen.insert({nr, nc});
              que.push(make_tuple(nr, nc, dist + 1));
            }
          }
        }
  write_to_cout(ans);
  ;
}
