#include <bits/stdc++.h>
using namespace std;
const long long MOD = 1e9 + 7;
const long long INF = 1e12;
const int INF_INT = 1e9;
template <class T>
inline bool chmin(T& a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <class T>
inline bool chmax(T& a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <class TYPE>
struct edge {
  TYPE to, cost;
  edge(TYPE t, TYPE c) {
    to = t;
    cost = c;
  }
};
int main() {
  int H, W;
  cin >> H >> W;
  vector<string> str(H);
  for (int i = 0; i < H; i++) cin >> str[i];
  vector<pair<int, int>> road;
  for (int x = 0; x < H; x++) {
    for (int y = 0; y < W; y++) {
      road.push_back({x, y});
    }
  }
  vector<pair<int, int>> vec = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
  int res = 0;
  int dis[H][W];
  for (int i = 0; i < H; i++) {
    for (int j = 0; j < W; j++) dis[i][j] = 0;
  }
  for (auto s : road) {
    for (auto g : road) {
      if (s.first == g.first && s.second == g.second) continue;
      int sx = s.first, sy = s.second;
      int gx = g.first, gy = g.second;
      queue<pair<pair<int, int>, int>> q;
      q.push({{sx, sy}, 0});
      while (!q.empty()) {
        pair<pair<int, int>, int> p = q.front();
        q.pop();
        int x = p.first.first;
        int y = p.first.second;
        int cost = p.second;
        if (dis[x][y] > 0) continue;
        dis[x][y] = cost;
        for (auto v : vec) {
          int xx = x + v.first;
          int yy = y + v.second;
          if (0 <= xx && xx < H && 0 <= yy && yy < W && str[xx][yy] == '.') {
            q.push({{xx, yy}, cost + 1});
          }
        }
      }
      res = max(res, dis[gx][gy]);
      for (int i = 0; i < H; i++) {
        for (int j = 0; j < W; j++) dis[i][j] = 0;
      }
    }
  }
  cout << res << endl;
  return 0;
}
