#include <bits/stdc++.h>
using namespace std;
using ll = long long;
ll INF = LLONG_MAX;
using vc = vector<char>;
using vi = vector<int>;
bool grid[20][20];
int main() {
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  int H, W;
  cin >> H >> W;
  int bestDist = 0;
  for (int y = (0); y < (H); ++y) {
    for (int x = (0); x < (W); ++x) {
      char c;
      cin >> c;
      grid[y][x] = (c == '#');
    }
  }
  for (int y = (0); y < (H); ++y) {
    for (int x = (0); x < (W); ++x) {
      if (grid[y][x]) continue;
      int dist[20][20];
      bool visited[20][20];
      for (int i = (0); i < (20); ++i) {
        for (int j = (0); j < (20); ++j) {
          dist[i][j] = 0;
          visited[i][j] = false;
        }
      }
      queue<pair<int, int>> q;
      q.push(pair<int, int>{x, y});
      while (!q.empty()) {
        pair<int, int> cur = q.front();
        q.pop();
        for (pair<int, int> delta :
             vector<pair<int, int>>{{-1, 0}, {1, 0}, {0, -1}, {0, 1}}) {
          int nx = cur.first + delta.first;
          int ny = cur.second + delta.second;
          if (nx < 0 || nx >= W || ny < 0 || ny >= H) continue;
          if (visited[ny][nx]) continue;
          if (grid[ny][nx]) continue;
          q.push(pair<int, int>{nx, ny});
          visited[ny][nx] = true;
          dist[ny][nx] = dist[cur.second][cur.first] + 1;
        }
      }
      for (int i = (0); i < (20); ++i) {
        for (int j = (0); j < (20); ++j) {
          bestDist = max(bestDist, dist[i][j]);
        }
      }
    }
  }
  cout << bestDist << endl;
}
