#include <bits/stdc++.h>
using namespace std;
long long gcd(long long n, long long m) {
  if (n == 0) return m;
  return gcd(m % n, n);
}
bool ifprime(long long n) {
  if (n == 1) return false;
  long long i;
  for (i = 2; i * i <= n; i++) {
    if (n % i == 0) return false;
  }
  return true;
}
void disp(vector<long long> v) {
  for (auto u : v) cout << u << " ";
  cout << "\n";
}
void remleadzero(vector<int> &v) {
  vector<int> u;
  int i = 0;
  while (v[i] == 0) i++;
  while (i < v.size()) {
    u.push_back(v[i]);
    i++;
  }
  v = u;
}
long long fast_expo(long long n, long long m, long long md) {
  long long a = 1;
  while (m > 0) {
    if (m & 1) a = (a * n) % md;
    n = (n * n) % md;
    m /= 2;
  }
  return a % md;
}
long long sqroot(long long n) {
  long double N = n;
  N = sqrtl(N);
  long long sq = N - 2;
  sq = max(sq, 0LL);
  while (sq * sq < n) {
    sq++;
  }
  if ((sq * sq) == n) return sq;
  return -1;
}
int dig(int n) {
  int ret = 0;
  while (n > 0) {
    n /= 10;
    ret++;
  }
  return ret;
}
long long dist[405][405];
int main() {
  ios::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);
  ;
  int n, m;
  cin >> n >> m;
  string grid[n];
  for (int i = 0; i < n; i++) {
    cin >> grid[i];
  }
  for (int i = 0; i < n * m; i++) {
    for (int j = 0; j < n * m; j++) dist[i][j] = 1e18;
  }
  for (int i = 0; i < n * m; i++) dist[i][i] = 0;
  for (int i = 0; i < n * m; i++) {
    int x = i / m, y = i % m;
    if (x + 1 < n and grid[x + 1][y] != '#') {
      dist[i][(x + 1) * m + y] = 1;
      dist[(x + 1) * m + y][i] = 1;
    }
    if (y + 1 < m and grid[x][y + 1] != '#') {
      dist[i][x * m + (y + 1)] = 1;
      dist[x * m + (y + 1)][i] = 1;
    }
  }
  for (int k = 0; k < n * m; k++) {
    for (int i = 0; i < n * m; i++) {
      for (int j = 0; j < n * m; j++) {
        dist[i][j] = min(dist[i][k] + dist[k][j], dist[i][j]);
      }
    }
  }
  long long ans = 0;
  for (int i = 0; i < n * m; i++) {
    for (int j = 0; j < n * m; j++) {
      int x = i / m, y = i % m;
      int x1 = j / m, y1 = j % m;
      if (grid[x][y] == '.' and grid[x1][y1] == '.') ans = max(dist[i][j], ans);
    }
  }
  cout << ans;
  return 0;
}
