#include <bits/stdc++.h>
using namespace std;
vector<long long> y_vec = {0, 0, -1, +1};
vector<long long> x_vec = {-1, +1, 0, 0};
struct Corr {
  long long y;
  long long x;
  long long depth;
};
long long x, y, depth;
queue<Corr> q;
long long H, W;
vector<vector<bool>> S(20, vector<bool>(20)), vec(20, vector<bool>(20));
long long bfs() {
  long long max_path = 0;
  while (!q.empty()) {
    Corr now = q.front();
    q.pop();
    y = now.y;
    x = now.x;
    depth = now.depth;
    for (int i = 0; i < (int)(4); i++) {
      Corr next = {y + y_vec[i], x + x_vec[i], depth + 1};
      if (0 <= next.y && next.y <= H - 1 && 0 <= next.x && next.x <= W - 1 &&
          vec[next.y][next.x] == true) {
        vec[next.y][next.x] = false;
        q.push(next);
        max_path = max(max_path, next.depth);
      }
    }
  }
  return max_path;
}
int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cin >> H >> W;
  string temp;
  for (int i = 0; i < H; i++) {
    cin >> temp;
    for (int j = 0; j < (int)(W); j++) {
      if (temp[j] == '.') {
        S[i][j] = true;
      } else {
        S[i][j] = false;
      }
    }
  }
  long long ans = 0;
  for (int i = 0; i < (int)(H); i++) {
    for (int j = 0; j < (int)(W); j++) {
      if (S[i][j] == false) {
        continue;
      } else {
        vec = S;
        Corr start = {i, j, 0};
        q.emplace(start);
        ans = max(ans, bfs());
      }
    }
  }
  cout << ans << endl;
  return 0;
}
