#include <bits/stdc++.h>
using namespace std;
int h, w;
vector<int> adj[405];
vector<int> dist(405);
vector<int> vis(405);
int m1 = INT_MAX;
void dijkstra(int s) {
  for (int i = 0; i <= 400; i++) {
    dist[i] = m1;
    vis[i] = 0;
  }
  dist[s] = 0;
  for (int i = 0; i < 401; i++) {
    int v = -1;
    for (int j = 0; j < 401; j++) {
      if (vis[j] == 0 && (v == -1 || dist[j] < dist[v])) v = j;
    }
    if (dist[v] == m1) break;
    vis[v] = 1;
    for (auto edge : adj[v]) {
      if (dist[v] + 1 < dist[edge]) {
        dist[edge] = dist[v] + 1;
      }
    }
  }
}
int solve(int s) {
  dijkstra(s);
  int m2 = -1;
  for (int i = 0; i < (h)*w; i++) {
    if (dist[i] > m2 && dist[i] != m1) m2 = dist[i];
  }
  return m2;
}
int main() {
  cin >> h >> w;
  vector<string> v[h];
  for (int i = 0; i < h; i++) {
    string s;
    cin >> s;
    v[i].push_back(s);
  }
  for (int i = 0; i < h; i++) {
    for (int j = 0; j < w; j++) {
      if (v[i][0][j] != '#') {
        if (j + 1 < w && v[i][0][j + 1] == '.') {
          int v1 = (i * w) + j;
          int v2 = (i * w) + j + 1;
          adj[v1].push_back(v2);
          adj[v2].push_back(v1);
        }
        if (j - 1 >= 0 && v[i][0][j - 1] == '.') {
          int v1 = (i * w) + j;
          int v2 = (i * w) + j - 1;
          adj[v1].push_back(v2);
          adj[v2].push_back(v1);
        }
        if (i - 1 >= 0 && v[i - 1][0][j] == '.') {
          int v1 = (i * w) + j;
          int v2 = ((i - 1) * w) + j;
          adj[v1].push_back(v2);
          adj[v2].push_back(v1);
        }
        if (i + 1 < h && v[i + 1][0][j] == '.') {
          int v1 = (i * w) + j;
          int v2 = ((i + 1) * w) + j;
          adj[v1].push_back(v2);
          adj[v2].push_back(v1);
        }
      }
    }
  }
  int h1 = -1, h2;
  for (int i = 0; i < h; i++) {
    for (int j = 0; j < w; j++) {
      if (v[i][0][j] != '#') h2 = solve(i * w + j);
      h1 = max(h1, h2);
    }
  }
  cout << h1;
}
