#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using P = pair<int, int>;
using vi = vector<int>;
using vvi = vector<vi>;
using vp = vector<P>;
using vl = vector<ll>;
template <typename T>
void Yes(T flag) {
  cout << (flag ? "Yes" : "No") << endl;
}
template <typename T>
void pv(vector<T> vec) {
  cout << "[";
  for (auto& v : vec) {
    cout << v << ",";
  }
  cout << "]" << endl;
}
template <>
void pv(vector<P> vec) {
  cout << "[";
  for (auto& v : vec) {
    cout << "<" << v.first << "," << v.second << ">"
         << ",";
  }
  cout << "]" << endl;
}
template <typename T>
void pv2(vector<vector<T>> vec) {
  for (auto& v : vec) pv(v);
}
vi dx = {1, 0, -1, 0}, dy = {0, 1, 0, -1};
const int INF = 100100101;
int main() {
  int h, w;
  cin >> h >> w;
  vvi maze(h, vi(w, 0));
  for (long long i = 0; i < (h); ++i)
    for (long long j = 0; j < (w); ++j) {
      char a;
      cin >> a;
      if (a == '.')
        maze.at(i).at(j) = 1;
      else
        maze.at(i).at(j) = 0;
    }
  vvi defa(h, vi(w, INF));
  int ans = 0;
  for (long long i = 0; i < (h); ++i)
    for (long long j = 0; j < (w); ++j) {
      if (!maze.at(i).at(j)) continue;
      queue<P> que;
      que.push(P(i, j));
      int tmp = 0;
      vvi d = defa;
      vvi mazemaze = maze;
      d.at(i).at(j) = 0;
      while (que.size()) {
        P q = que.front();
        que.pop();
        int x = q.first, y = q.second;
        mazemaze.at(x).at(y) = 0;
        for (long long k = 0; k < (4); ++k) {
          int nx = x + dx[k];
          int ny = y + dy[k];
          if (((0) <= (nx) && (nx) < (h)) and ((0) <= (ny) && (ny) < (w)) and
              mazemaze.at(nx).at(ny) == 1) {
            que.push(P(nx, ny));
            d[nx][ny] = d[x][y] + 1;
            tmp = max(tmp, d[x][y] + 1);
          }
        }
      }
      ans = max(ans, tmp);
    }
  cout << ans << endl;
  return 0;
}
