#include <bits/stdc++.h>
using namespace std;
pair<int, set<int>> bfs(int node, set<int> adj[]) {
  bool vis[400];
  memset(vis, false, sizeof vis);
  queue<pair<int, int>> q;
  set<int> v[40];
  q.push({node, 0});
  vis[node] = 1;
  while (!q.empty()) {
    auto x = q.front();
    v[x.second].insert(x.first);
    q.pop();
    for (auto k : adj[x.first]) {
      if (!vis[k]) {
        vis[k] = 1;
        q.push({k, x.second + 1});
      }
    }
  }
  int ans;
  for (long long i = 0; i < 40; i++)
    if (v[i].size()) ans = i;
  return {ans, v[ans]};
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  int t = 1;
  while (t--) {
    int h, w;
    cin >> h >> w;
    bool arr[h][w];
    memset(arr, false, sizeof arr);
    for (long long i = 0; i < h; i++)
      for (long long j = 0; j < w; j++) {
        char c;
        cin >> c;
        if (c == '.') arr[i][j] = 1;
      }
    set<int> adj[h * w];
    for (long long i = 0; i < h; i++)
      for (long long j = 0; j < w; j++) {
        int num = i * w + j;
        int top = num - w;
        int bottom = num + w;
        int left;
        if (j == 0)
          left = -1;
        else
          left = num - 1;
        int right;
        if (j == w - 1)
          right = -1;
        else
          right = num + 1;
        if (arr[i][j]) {
          if (top > 0 && arr[i - 1][j]) {
            adj[top].insert(num);
            adj[num].insert(top);
          }
          if (bottom < h * w && arr[i + 1][j]) {
            adj[bottom].insert(num);
            adj[num].insert(bottom);
          }
          if (left > 0 && arr[i][j - 1]) {
            adj[left].insert(num);
            adj[num].insert(left);
          }
          if (right > 0 && arr[i][j + 1]) {
            adj[right].insert(num);
            adj[num].insert(right);
          }
        }
      }
    auto x = bfs(0, adj);
    int maxim = -1;
    for (auto k : x.second) {
      maxim = max(maxim, bfs(k, adj).first);
    }
    cout << maxim << "\n";
  }
}
