#include <bits/stdc++.h>
using namespace std;
bool sBs(const pair<int, int> &a, const pair<int, int> &b) {
  return (a.second < b.second);
}
long long SUMD(long long n);
long long BS(vector<long long> &PS, long long s, long long e, long long ser);
long long MI(long long a, long long m);
bool P[1000050LL + 1];
void Sieve(int n = 1000050LL);
long long Powb(long long b, long long n);
long long solve(vector<string> &G, int r, int c, int n, int m) {
  queue<pair<int, int> > Q;
  vector<vector<int> > L(n, vector<int>(m, 1000000007));
  L[r][c] = 0;
  Q.push({r, c});
  int ml = 0;
  while (!Q.empty()) {
    auto x = Q.front();
    Q.pop();
    r = x.first;
    c = x.second;
    if (r - 1 >= 0 and G[r - 1][c] == '.' and L[r - 1][c] + 1 > L[r][c]) {
      L[r - 1][c] = L[r][c] + 1;
      Q.push({r - 1, c});
      ml = max(ml, L[r][c] + 1);
    }
    if (r + 1 < n and G[r + 1][c] == '.' and L[r + 1][c] + 1 > L[r][c]) {
      L[r + 1][c] = L[r][c] + 1;
      Q.push({r + 1, c});
      ml = max(ml, L[r][c] + 1);
    }
    if (c - 1 >= 0 and G[r][c - 1] == '.' and L[r][c - 1] + 1 > L[r][c]) {
      L[r][c - 1] = L[r][c] + 1;
      Q.push({r, c - 1});
      ml = max(ml, L[r][c] + 1);
    }
    if (c - 1 < m and G[r][c + 1] == '.' and L[r][c + 1] + 1 > L[r][c]) {
      L[r][c + 1] = L[r][c] + 1;
      Q.push({r, c + 1});
      ml = max(ml, L[r][c] + 1);
    }
  }
  return ml;
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  ;
  long long q = 1, t;
  while (q--) {
    long long n, m, k, i, j, l, r, c = 0, b, a, g, counter = 0, u, v, d, e, p,
                                   x, y, flag = 1;
    cin >> n >> m;
    long long ans = 0;
    vector<string> G(n);
    for (i = 0; i < n; i++) cin >> G[i];
    for (i = 0; i < n; i++) {
      for (j = 0; j < m; j++) {
        if (G[i][j] == '.') ans = max(ans, solve(G, i, j, n, m));
      }
    }
    cout << ans;
  }
  return 0;
}
long long Powb(long long b, long long n) {
  if (n == 0) return 1LL;
  if (n == 1) return b;
  long long temp = Powb(b, n / 2);
  if (n % 2 == 0) {
    return (temp * temp) % 1000000007;
  } else {
    return (b * ((temp * temp) % 1000000007)) % 1000000007;
  }
}
long long SUMD(long long n) {
  long long sum = 0;
  while (n > 0) {
    sum += n % 10;
    n = n / 10;
  }
  return sum;
}
long long BS(vector<long long> &PS, long long s, long long e, long long ser) {
  if (s > e) return s;
  long long mid = (s + e) / 2;
  if (PS[mid] == ser) {
    return mid;
  } else if (PS[mid] > ser) {
    return BS(PS, s, mid - 1, ser);
  } else
    return BS(PS, mid + 1, e, ser);
}
long long MI(long long a, long long m) {
  long long m0 = m;
  long long y = 0, x = 1;
  if (m == 1) return 0;
  while (a > 1) {
    long long q = a / m;
    long long t = m;
    m = a % m, a = t;
    t = y;
    y = x - q * y;
    x = t;
  }
  if (x < 0) x += m0;
  return x;
}
void Sieve(int n) {
  memset(P, true, sizeof(P));
  P[0] = false;
  P[1] = false;
  for (long long i = 2; i * i <= n; i++) {
    if (P[i]) {
      for (long long j = i * i; j <= n; j += i) {
        P[j] = false;
      }
    }
  }
}
