#include <bits/stdc++.h>
using namespace std;
using ll = long long;
template <class T>
inline bool chmax(T& a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <class T>
inline bool chmin(T& a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
int main() {
  ios::sync_with_stdio(false);
  int h, w;
  cin >> h >> w;
  vector<vector<char>> maze(h, vector<char>(w));
  for (int y = 0; y < (h); ++y) {
    string s;
    cin >> s;
    for (int x = 0; x < (w); ++x) maze[y][x] = s[x];
  }
  vector<int> dx = {0, 0, 1, -1};
  vector<int> dy = {1, -1, 0, 0};
  int max_step = 0;
  for (int sx = 0; sx < (w); ++sx)
    for (int sy = 0; sy < (h); ++sy) {
      if (maze[sy][sx] == '#') continue;
      queue<pair<pair<int, int>, int>> que;
      vector<vector<bool>> seen(h, vector<bool>(w, false));
      que.push(make_pair(make_pair(sx, sy), 0));
      while (que.size() != 0) {
        int x = que.front().first.first;
        int y = que.front().first.second;
        int step = que.front().second;
        que.pop();
        for (int i = 0; i < (4); ++i) {
          int nx = x + dx[i];
          int ny = y + dy[i];
          if (nx < 0 || nx >= w || ny < 0 || ny >= h) continue;
          if (maze[ny][nx] == '#') continue;
          if (seen[ny][nx] == true) continue;
          seen[ny][nx] = true;
          chmax(max_step, step + 1);
          que.push(make_pair(make_pair(nx, ny), step + 1));
        }
      }
    }
  cout << max_step << endl;
}
