#include <bits/stdc++.h>
using namespace std;
template <class T>
inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <class T>
inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
const long long INF = 1e18;
const long long MOD = 998244353;
const long long MX = 1000001;
int H, W;
char grid[20][20];
set<pair<long long, long long>> checked;
int dy[4] = {0, -1, 0, 1};
int dx[4] = {1, 0, -1, 0};
int ans = 0;
void solve() {
  cin >> H >> W;
  for (int i = 0; i < H; i++) {
    for (int j = 0; j < W; j++) {
      cin >> grid[i][j];
    }
  }
  for (int r = 0; r < H; r++) {
    for (int c = 0; c < W; c++) {
      if (grid[r][c] == '.') {
        checked.clear();
        queue<pair<pair<long long, long long>, int>> q;
        q.push({{r, c}, 0});
        while (!q.empty()) {
          pair<pair<long long, long long>, int> v = q.front();
          q.pop();
          checked.insert({v.first.first, v.first.second});
          chmax(ans, v.second);
          for (int i = 0; i < 4; i++) {
            int a = v.first.first + dy[i], b = v.first.second + dx[i];
            if (a < 0 || a >= H || b < 0 || b >= W) continue;
            if (checked.find({a, b}) != checked.end()) continue;
            if (grid[a][b] != '.') continue;
            q.push({{a, b}, v.second + 1});
          }
        }
      }
    }
  }
  cout << ans;
}
int main() {
  cin.sync_with_stdio(0);
  cin.tie(0);
  long long T = 1;
  while (T--) solve();
  return 0;
}
