#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
using pll = pair<ll, ll>;
static const ll INF = 1001001001;
static const ll LLINF = 1001001001001001001;
void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
  cerr << " " << to_string(H);
  debug_out(T...);
}
static const int dx[4] = {0, 1, 0, -1};
static const int dy[4] = {-1, 0, 1, 0};
int run(istream& in, ostream& out) {
  ll H, W;
  in >> H >> W;
  vector<string> v(H);
  vector<vector<ll>> dist(20 * 20, vector<ll>(20 * 20, INF));
  for (ll i = 0; i < (H); ++i) {
    in >> v[i];
  }
  for (ll i1 = 0; i1 < (H); ++i1) {
    for (ll j1 = 0; j1 < (W); ++j1) {
      if (v[i1][j1] == '#') {
        continue;
      }
      dist[((i1)*20 + (j1))][((i1)*20 + (j1))] = 0;
      for (ll i = 0; i < (4); ++i) {
        auto y = i1 + dy[i];
        auto x = j1 + dx[i];
        if (x >= 0 && y >= 0 && x < W && y < H && v[y][x] == '.') {
          dist[((i1)*20 + (j1))][((y)*20 + (x))] = 1;
          dist[((y)*20 + (x))][((i1)*20 + (j1))] = 1;
        }
      }
    }
  }
  for (ll i1 = 0; i1 < (H); ++i1) {
    for (ll j1 = 0; j1 < (W); ++j1) {
      if (v[i1][j1] == '#') {
        continue;
      }
      for (ll i2 = 0; i2 < (H); ++i2) {
        for (ll j2 = 0; j2 < (W); ++j2) {
          if (v[i2][j2] == '#') {
            continue;
          }
          for (ll i3 = 0; i3 < (H); ++i3) {
            for (ll j3 = 0; j3 < (W); ++j3) {
              if (v[i3][j3] == '#') {
                continue;
              }
              auto direct = dist[((i1)*20 + (j1))][((i3)*20 + (j3))];
              auto pass_by = dist[((i1)*20 + (j1))][((i2)*20 + (j2))] +
                             dist[((i2)*20 + (j2))][((i3)*20 + (j3))];
              if (direct > pass_by) {
                dist[((i1)*20 + (j1))][((i3)*20 + (j3))] = pass_by;
                dist[((i3)*20 + (j3))][((i1)*20 + (j1))] = pass_by;
              }
            }
          }
        }
      }
    }
  }
  ll max_dist = 0;
  for (ll i1 = 0; i1 < (H); ++i1) {
    for (ll j1 = 0; j1 < (W); ++j1) {
      if (v[i1][j1] == '#') {
        continue;
      }
      for (ll i2 = 0; i2 < (H); ++i2) {
        for (ll j2 = 0; j2 < (W); ++j2) {
          if (v[i2][j2] == '#') {
            continue;
          }
          auto candidate = dist[((i1)*20 + (j1))][((i2)*20 + (j2))];
          if (candidate < INF) {
            max_dist = max(max_dist, candidate);
            max_dist = max_dist;
          }
        }
      }
    }
  }
  out << max_dist << endl;
  return 0;
}
int main() { return run(cin, cout); }
