#include <bits/stdc++.h>
using namespace std;
int64_t H, W;
int64_t x, y, depth;
const int64_t H_max = 30;
const int64_t W_max = 30;
char maze[H_max][W_max];
char maze_sub[H_max][W_max];
const int64_t dx[4] = {1, 0, -1, 0};
const int64_t dy[4] = {0, 1, 0, -1};
struct Corr {
  int64_t x;
  int64_t y;
  int64_t depth;
};
queue<Corr> que;
int64_t bfs(int64_t gx, int64_t gy) {
  while (!que.empty()) {
    Corr now = que.front();
    que.pop();
    x = now.x;
    y = now.y;
    depth = now.depth;
    for (int64_t i = 0; i < 4; ++i) {
      Corr next = {x + dx[i], y + dy[i], depth + 1};
      if (next.x == gx and next.y == gy) {
        return next.depth;
      }
      if (0 <= next.x and next.x < H and 0 <= next.y and next.y < W and
          maze[next.x][next.y] == '.') {
        maze[next.x][next.y] = 'x';
        que.push(next);
      }
    }
  }
  return 0;
}
int64_t bfs_main(int64_t sx, int64_t sy, int64_t gx, int64_t gy) {
  while (!que.empty()) {
    que.pop();
  }
  Corr start = {sx, sy, 0};
  que.emplace(start);
  return bfs(gx, gy);
}
int main() {
  cin >> H >> W;
  for (int i = 0; i < H; ++i) {
    for (int j = 0; j < W; ++j) {
      cin >> maze_sub[i][j];
    }
  }
  int64_t length = 0;
  int64_t ans = 0;
  for (int64_t sx = 0; sx < H; ++sx) {
    for (int64_t sy = 0; sy < W; ++sy) {
      for (int64_t gx = 0; gx < H; ++gx) {
        for (int64_t gy = 0; gy < W; ++gy) {
          for (int i = 0; i < H; ++i) {
            for (int j = 0; j < W; ++j) {
              maze[i][j] = maze_sub[i][j];
            }
          }
          if (sx == gx and sy == gy) {
            length = 0;
          } else {
            length = bfs_main(sx, sy, gx, gy);
          }
          ans = max(ans, length);
        }
      }
    }
  }
  cout << ans << endl;
  return 0;
}
