#include <bits/stdc++.h>
using namespace std;
inline void prep() {
  cin.tie(0);
  cin.sync_with_stdio(0);
};
const double pi = acos(-1.);
long long mod = 1000000007;
long long mymod(long long num) {
  if (num < 0 && !(num % mod == 0)) {
    if (mod == 1) {
      return 0;
    }
    return mod - abs(num) % mod;
  } else {
    return num % mod;
  }
}
double eps = .000000001;
int dx[] = {-1, 0, 1, 0};
int dy[] = {0, -1, 0, 1};
int h, w;
string grid[20];
bool valid(int x, int y) {
  if (x < 0 || y < 0 || x >= h || y >= w) {
    return false;
  }
  if (grid[x][y] == '#') {
    return false;
  }
  return true;
}
int main() {
  prep();
  cin >> h >> w;
  for (int i = 0; i < h; i++) {
    cin >> grid[i];
  }
  int maxest = 0;
  for (int i = 0; i < h; i++) {
    for (int j = 0; j < w; j++) {
      queue<tuple<int, int, int> > q;
      q.emplace(i, j, 0);
      bool vis[h][w];
      memset(vis, false, sizeof(bool) * h * w);
      while (!q.empty()) {
        tuple<int, int, int> top = q.front();
        q.pop();
        int x = get<0>(top);
        int y = get<1>(top);
        int dist = get<2>(top);
        if (vis[x][y]) {
          continue;
        }
        vis[x][y] = true;
        maxest = max(maxest, dist);
        for (int k = 0; k < 4; k++) {
          int newx = x + dx[k];
          int newy = y + dy[k];
          if (!valid(newx, newy)) {
            continue;
          }
          q.emplace(newx, newy, dist + 1);
        }
      }
    }
  }
  cout << maxest;
  return 0;
}
