#include <bits/stdc++.h>
#pragma GCC optimize("02")
using namespace std;
class complex {
 public:
  inline char gc() {
    static const long long IN_LEN = 1 << 18 | 1;
    static char buf[IN_LEN], *s, *t;
    return (s == t) && (t = (s = buf) + fread(buf, 1, IN_LEN, stdin)),
           s == t ? -1 : *s++;
  }
  template <typename _Tp>
  __inline__ __attribute__((always_inline)) complex &operator>>(_Tp &x) {
    static char ch, sgn;
    ch = gc(), sgn = 0;
    for (; !isdigit(ch); ch = gc()) {
      if (ch == -1) return *this;
      sgn |= ch == '-';
    }
    for (x = 0; isdigit(ch); ch = gc()) x = x * 10 + (ch ^ '0');
    sgn && (x = -x);
    return *this;
  }
} inc;
struct node {
  long long xc, yc, st;
};
long long h, w;
char ch[25][25];
const long long dx[5] = {0, 0, 1, 0, -1};
const long long dy[5] = {0, 1, 0, -1, 0};
bool vis[25][25];
long long bfs(long long x, long long y) {
  long long cnt = -1 << 30;
  queue<node> Q;
  Q.push((node){x, y, 0});
  while (!Q.empty()) {
    node t = Q.front();
    Q.pop();
    for (long long i = 1; i <= 4; i++) {
      long long xpos = t.xc + dx[i];
      long long ypos = t.yc + dy[i];
      if (xpos > 0 && xpos <= h && ypos > 0 && ypos <= w &&
          ch[xpos][ypos] != '#' && !vis[xpos][ypos]) {
        node a;
        a.st = t.st + 1;
        a.xc = xpos;
        a.yc = ypos;
        vis[xpos][ypos] = true;
        Q.push(a);
        cnt = max(a.st, cnt);
      }
    }
  }
  return cnt;
}
signed main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  cin >> h >> w;
  for (long long i = 1; i <= h; i++)
    for (long long j = 1; j <= w; j++) cin >> ch[i][j];
  long long ans = -1 << 30;
  for (long long i = 1; i <= h; i++)
    for (long long j = 1; j <= w; j++)
      if (ch[i][j] == '.') ans = max(ans, bfs(i, j));
  printf("%lld\n", ans);
  return 0;
}
