#include <bits/stdc++.h>
using namespace std;
class DMazeMaster {
 public:
  int bfs(int x, int y) {
    queue<pair<int, int>> q;
    q.push(make_pair(x, y));
    int cost = 0;
    distance[x][y] = cost;
    visited[x][y] = true;
    while (!q.empty()) {
      auto p = q.front();
      q.pop();
      x = p.first;
      y = p.second;
      cost = distance[x][y] + 1;
      for (const auto &next : move) {
        int moved_x = x + next.first;
        int moved_y = y + next.second;
        if (moved_x < 0 || moved_x >= h || moved_y < 0 || moved_y >= w) {
          continue;
        } else if (maze[moved_x][moved_y] == '#') {
          continue;
        }
        if (visited[moved_x][moved_y]) continue;
        distance[moved_x][moved_y] = cost;
        visited[moved_x][moved_y] = true;
        q.push(make_pair(moved_x, moved_y));
      }
    }
    int ret = 0;
    for (const auto &item : distance) {
      for (const auto &item2 : item) {
        ret = max(item2, ret);
      }
    }
    return ret;
  }
  void solve(std::istream &cin, std::ostream &cout) {
    cin >> h >> w;
    maze.resize(h);
    visited.resize(h, vector<bool>(w, false));
    for (int i = 0; i < h; ++i) {
      cin >> maze[i];
    }
    move.emplace_back(1, 0);
    move.emplace_back(-1, 0);
    move.emplace_back(0, 1);
    move.emplace_back(0, -1);
    int ans = 0;
    for (int i = 0; i < h; ++i) {
      for (int j = 0; j < w; ++j) {
        if (maze[i][j] == '#') continue;
        distance.clear();
        distance.resize(h, vector<int>(w, -1));
        ans = max(ans, bfs(i, j));
      }
    }
    cout << ans << endl;
  }
  int h, w;
  vector<string> maze;
  vector<vector<int>> distance;
  vector<vector<bool>> visited;
  vector<pair<int, int>> move;
};
int main() {
  DMazeMaster solver;
  std::istream &in(std::cin);
  std::ostream &out(std::cout);
  solver.solve(in, out);
  return 0;
}
