#include <bits/stdc++.h>
using namespace std;
template <typename Arg1>
void __f(const char* name, Arg1&& arg1) {
  cerr << name << ": " << arg1 << endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args) {
  const char* comma = strchr(names + 1, ',');
  cerr.write(names, comma - names) << ": " << arg1 << " |";
  __f(comma + 1, args...);
}
const int N = 22;
char s[N][N];
int n_, m_;
bool used[N][N];
int mstep;
int D[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
struct node {
  int x, y, step;
  node(int x, int y, int step) : x(x), y(y), step(step){};
  node(){};
} ednode;
void bfs(int x, int y) {
  queue<node> q;
  q.push({x, y, 0});
  while (!q.empty()) {
    auto now = q.front();
    q.pop();
    if (now.step > mstep) {
      mstep = now.step;
      ednode.x = now.x;
      ednode.y = now.y;
    }
    for (int i = 0; i < 4; i++) {
      int xx = now.x + D[i][0];
      int yy = now.y + D[i][1];
      if (xx >= 0 && xx <= n_ && yy >= 0 && yy < m_ && !used[xx][yy] &&
          s[xx][yy] == '.') {
        node next({xx, yy, now.step + 1});
        q.push(next);
        used[xx][yy] = 1;
      }
    }
  }
}
int main() {
  cin >> n_ >> m_;
  for (int i = 0; i < n_; i++) {
    for (int j = 0; j < m_; j++) {
      cin >> s[i][j];
    }
  }
  int ans = 0;
  for (int i = 0; i < n_; i++) {
    for (int j = 0; j < m_; j++) {
      if (s[i][j] == '.') {
        memset(used, 0, sizeof used);
        mstep = 0;
        bfs(i, j);
        mstep = 0;
        memset(used, 0, sizeof used);
        bfs(ednode.x, ednode.y);
        ans = max(ans, mstep);
        break;
      }
    }
  }
  cout << ans << endl;
  return 0;
}
