#include <bits/stdc++.h>
using namespace std;
const int MOD = 1000000007;
int H, W;
using P = pair<int, int>;
int distance(P s, P g, const vector<vector<char>>& Maze) {
  queue<P> que;
  int res;
  vector<vector<int>> Dist(H, vector<int>(W, INT_MAX));
  que.push(s);
  Dist[s.second][s.first] = 0;
  while (que.size()) {
    P point = que.front();
    que.pop();
    if (point == g) break;
    auto isInMaze = [&Maze](P p) {
      return p.first >= 0 && p.first < W && p.second >= 0 && p.second < H &&
             Maze[p.second][p.first] != '#';
    };
    auto visited = [&Dist](P p) { return Dist[p.second][p.first] != INT_MAX; };
    const array<P, 4> dVec{make_pair(1, 0), make_pair(-1, 0), make_pair(0, 1),
                           make_pair(0, -1)};
    for (auto dv : dVec) {
      P pointNew{dv.first + point.first, dv.second + point.second};
      if (isInMaze(pointNew) && !visited(pointNew)) {
        que.push(pointNew);
        Dist[pointNew.second][pointNew.first] =
            Dist[point.second][point.first] + 1;
      }
    }
  }
  return Dist[g.second][g.first];
}
int main() {
  cin >> H >> W;
  vector<vector<char>> Maze(H, vector<char>(W));
  for (long long h = (0); h < (H); ++h) {
    for (long long w = (0); w < (W); ++w) {
      cin >> Maze[h][w];
    }
  }
  set<P> searched;
  int res = 0;
  for (long long sx = (0); sx < (W); ++sx) {
    for (long long sy = (0); sy < (H); ++sy) {
      if (Maze[sy][sx] == '#') break;
      for (long long gx = (0); gx < (W); ++gx) {
        for (long long gy = (0); gy < (H); ++gy) {
          if (Maze[gy][gx] == '#' && searched.find(P{gx, gy}) == searched.end())
            break;
          res = max(res, distance(P{sx, sy}, P{gx, gy}, Maze));
        }
      }
      searched.insert(P{sx, sy});
    }
  }
  cout << res << endl;
  return 0;
}
