#include <bits/stdc++.h>
using namespace std;
using ull = unsigned long long;
using ll = long long;
using prll = pair<ll, ll>;
static const ll MOD = 1000000007;
static const ll mINF = -922337200085470000;
static const ll pINF = 1LL << 60;
static const ull uINF = 1844674407399900000;
static const double pi = 3.1415926535897932384;
static const ll juu = 100000;
static const ll hyaku = 1000000;
ll factor[300];
ll memory[300];
void primefac(ll num) {
  int i = 0, kosuu = 0;
  while (*(factor + i) != 0) {
    while (num % *(factor + i) == 0) {
      num /= *(factor + i);
      memory[*(factor + i)] += 1;
    }
    if (num == 1) break;
    i++;
  }
}
int elast(ll number) {
  ll tmp = 0;
  int flag = 0;
  *factor = 2;
  for (int i = 3; i <= number; i++) {
    flag = 0;
    for (int j = 0; j <= tmp; j++) {
      if (i % (*(factor + j)) == 0) {
        flag = 1;
        break;
      }
    }
    if (flag) continue;
    tmp += 1;
    *(factor + tmp) = i;
  }
  return tmp + 2;
}
ll nCr(ll n, ll r) {
  ll val = 1;
  ll i;
  if (r == 0) return 1;
  for (i = 0; i < n - r; i++) {
    val *= (n - i);
    val /= (i + 1);
  }
  return val;
}
ll nPr(ll n, ll r) {
  ll val = 1;
  ll i;
  for (i = 0; i < r; i++) {
    val *= (n - i);
  }
  return val;
}
template <typename T>
bool chmin(T &a, const T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <typename T>
bool chmax(T &a, const T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <typename T>
void eraseSame(T &a) {
  sort(a.begin(), a.end());
  a.erase(unique(a.begin(), a.end()), a.end());
}
template <typename T>
bool swapmax(T &a, T &b) {
  T temp;
  temp = a;
  if (a > b) {
    a = b;
    b = temp;
    return false;
  }
  return true;
}
ll gcd(ll x, ll y) { return (x % y) ? gcd(y, x % y) : y; }
ll lcm(ll x, ll y) { return x / gcd(x, y) * y; }
template <typename T>
void splitIn(ll N, vector<T> &array) {
  T temp;
  int i = 0;
  if (N == 0) {
    return;
  }
  array.resize(N);
  while (cin >> temp) {
    array[i] = temp;
    i++;
    if (i >= N) {
      break;
    }
  }
  return;
}
ll BFS() {
  queue<pair<ll, ll>> q;
  const ll dx[4] = {0, 0, 1, -1};
  const ll dy[4] = {1, -1, 0, 0};
  ll x, y;
  prll goal, start;
  ll ans = 0;
  cin >> x >> y;
  vector<string> gra(x);
  for (ll i = 0; i < (ll)(x); i++) {
    cin >> gra[i];
  }
  ans = 0;
  for (int jj = 1; jj <= x; ++jj) {
    vector<vector<ll>> dist(x, vector<ll>(y, pINF));
    for (int kk = 1; kk <= y; ++kk) {
      if (gra[jj - 1][kk - 1] == '#') continue;
      for (int rr = 1; rr <= x; ++rr) {
        for (int ww = 1; ww <= y; ++ww) {
          if (gra[rr - 1][ww - 1] == '#') continue;
          start.first = jj;
          start.second = kk;
          goal.first = rr;
          goal.second = ww;
          dist[start.first - 1][start.second - 1] = 0;
          q.push(make_pair(start.first - 1, start.second - 1));
          while (!q.empty()) {
            prll pr = q.front();
            q.pop();
            for (int i = 0; i < 4; ++i) {
              ll nextx = pr.first + dx[i];
              ll nexty = pr.second + dy[i];
              if (nexty >= 0 && nextx >= 0 && nextx < x && nexty < y) {
                if (dist[nextx][nexty] == pINF && gra[nextx][nexty] == '.') {
                  chmin(dist[nextx][nexty], dist[pr.first][pr.second] + 1);
                  q.push(make_pair(nextx, nexty));
                }
              }
            }
          }
          chmax(ans, dist[goal.first - 1][goal.second - 1]);
        }
      }
    }
  }
  return ans;
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  ll n, k, m;
  ll ans = 0;
  string s;
  vector<ll> v;
  ans = BFS();
  cout << ans << endl;
  return 0;
}
