#include <bits/stdc++.h>
using namespace std;
using P = pair<long long, long long>;
template <class T>
inline bool chmin(T& a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <class T>
inline bool chmax(T& a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
const long long MOD = 1000000007;
const int INF = 1 << 29;
struct Corr {
  long long y;
  long long x;
  long long depth;
};
vector<string> field;
queue<Corr> q;
vector<int> x_vec = {0, 0, +1, -1};
vector<int> y_vec = {+1, -1, 0, 0};
long long H, W;
long long s_y, s_x, g_y, g_x;
long long y, x, depth;
long long bfs() {
  while (!q.empty()) {
    y = q.front().y, x = q.front().x, depth = q.front().depth;
    q.pop();
    if (y == g_y && x == g_x) return depth;
    for (int i = 0; i < 4; ++i) {
      Corr next = {y + y_vec[i], x + x_vec[i], depth + 1};
      if (0 <= next.y && next.y < H && 0 <= next.x && next.x < W &&
          field[next.y][next.x] == '.') {
        q.push(next);
        field[next.y][next.x] = 'x';
      }
    }
  }
  return 0;
}
int main() {
  cin >> H >> W;
  field.resize(H);
  for (int i = 0; i < H; i++) cin >> field[i];
  vector<string> tmp = field;
  long long ans = 0;
  for (int sy = 0; sy < H; ++sy) {
    for (int sx = 0; sx < W; ++sx) {
      for (int gy = 0; gy < H; ++gy) {
        for (int gx = 0; gx < W; ++gx) {
          if (sy == gy && gy == gx) continue;
          Corr start = {sy, sx, 0};
          queue<Corr>().swap(q);
          q.push(start);
          g_y = gy, g_x = gx;
          ans = max(ans, bfs());
          field = tmp;
        }
      }
    }
  }
  cout << ans << endl;
}
