#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll MOD = 1000000007;
const long long INF = 1LL << 60;
const double pi = acos(-1);
ll H, W;
bool movable(vector<string> &maze, vector<vector<ll>> &memo, ll x, ll y, ll X,
             ll Y) {
  if (X < 0 || X >= W || Y < 0 || Y >= H) {
    return false;
  }
  if (maze.at(Y).at(X) == '#') {
    return false;
  }
  if (memo.at(Y).at(X) <= memo.at(y).at(x) + 1 && memo.at(Y).at(X) != -1) {
    return false;
  }
  return true;
}
int main() {
  cin >> H >> W;
  ll ans = 0;
  vector<string> maze(H);
  for (int i = 0; i < (H); i++) {
    cin >> maze.at(i);
  }
  for (int i = 0; i < (H * W); i++) {
    for (int j = 0; j < (H * W); j++) {
      ll sx = i % W, sy = i / W, gx = j % W, gy = j / W;
      if (maze.at(sy).at(sx) == '#' || maze.at(gy).at(gx) == '#') {
        continue;
      }
      queue<vector<ll>> next;
      vector<vector<ll>> memo(H, vector<ll>(W, -1));
      memo.at(sy).at(sx) = 0;
      next.push({sx, sy});
      while (!next.empty()) {
        ll x = next.front().at(0), y = next.front().at(1);
        next.pop();
        if (x == gx && y == gy) {
          break;
        }
        if (movable(maze, memo, x, y, x + 1, y)) {
          memo.at(y).at(x + 1) = memo.at(y).at(x) + 1;
          next.push({x + 1, y});
        }
        if (movable(maze, memo, x, y, x - 1, y)) {
          memo.at(y).at(x - 1) = memo.at(y).at(x) + 1;
          next.push({x - 1, y});
        }
        if (movable(maze, memo, x, y, x, y + 1)) {
          memo.at(y + 1).at(x) = memo.at(y).at(x) + 1;
          next.push({x, y + 1});
        }
        if (movable(maze, memo, x, y, x, y - 1)) {
          memo.at(y - 1).at(x) = memo.at(y).at(x) + 1;
          next.push({x, y - 1});
        }
      }
      ans = max(ans, memo.at(gy).at(gx));
    }
  }
  cout << ans << endl;
  return 0;
}
