#include <bits/stdc++.h>
using namespace std;
long long gcd(long long a, long long b) { return b ? gcd(b, a % b) : a; }
long long lcm(long long a, long long b) { return a / gcd(a, b) * b; }
struct Corr {
  long long y;
  long long x;
  long long depth;
};
long long H, W;
long long s_y, s_x, g_y, g_x;
long long y, x, depth;
vector<string> maze;
queue<Corr> q;
vector<long long> y_vec = {0, 0, -1, +1};
vector<long long> x_vec = {-1, +1, 0, 0};
long long bfs(vector<vector<long long>> &path) {
  long long res = 0;
  while (!q.empty()) {
    Corr now = q.front();
    q.pop();
    y = now.y, x = now.x, depth = now.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 &&
          maze[next.y][next.x] == '.') {
        if (path[next.y][next.x] != -1) {
          continue;
        } else {
          res = max(res, next.depth);
          path[next.y][next.x] = next.depth;
          q.push(next);
        }
      }
    }
  }
  return res;
}
int main() {
  cin >> H >> W;
  for (long long i = 0; i < (H); i++) {
    string s;
    cin >> s;
    maze.push_back(s);
  }
  long long ans = 0;
  for (long long i = 0; i < (H); i++) {
    for (long long j = 0; j < (W); j++) {
      vector<vector<long long>> path(H, vector<long long>(W, -1));
      path[i][j] = 0;
      Corr start = {i, j, 0};
      q.emplace(start);
      ans = max(ans, bfs(path));
    }
  }
  cout << ans << endl;
  return 0;
}
