#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll MAX = LLONG_MAX;
const ll MIN = LLONG_MIN;
typedef struct S {
  int y;
  int x;
  int distance;
} Object;
int main() {
  ll H, W;
  cin >> H >> W;
  char S[H + 2][W + 2];
  for (int i = 0; i < H + 2; i++) {
    for (int j = 0; j < W + 2; j++) {
      S[i][j] = '#';
    }
  }
  for (int i = 1; i < H + 1; i++) {
    for (int j = 1; j < W + 1; j++) {
      cin >> S[i][j];
    }
  }
  ll ans = 0;
  char S2[H + 2][W + 2];
  vector<int> x_vec = {-1, 1, 0, 0};
  vector<int> y_vec = {0, 0, -1, 1};
  queue<Object> q;
  for (int i = 1; i < H + 1; i++) {
    for (int j = 1; j < W + 1; j++) {
      for (int k = 1; k < H + 1; k++) {
        for (int l = 1; l < W + 1; l++) {
          S2[k][l] = S[k][l];
        }
      }
      if (S2[i][j] == '#') {
        continue;
      }
      Object start = {i, j, 0};
      q.push(start);
      vector<int> x_vec = {-1, 1, 0, 0};
      vector<int> y_vec = {0, 0, -1, 1};
      while (!q.empty()) {
        Object current = q.front();
        q.pop();
        S2[current.y][current.x] = '#';
        for (int k = 0; k < 4; k++) {
          if (S2[current.y + y_vec[k]][current.x + x_vec[k]] == '.') {
            Object next = {current.y + y_vec[k], current.x + x_vec[k],
                           current.distance + 1};
            q.push(next);
            ans = max(ans, (ll)(next.distance));
          }
        }
      }
    }
  }
  cout << ans << endl;
}
