#include <bits/stdc++.h>
using namespace std;
long long int fast_expo(long long int x, long long int p) {
  if (p == 0)
    return 1;
  else if (p % 2 == 0) {
    long long int t = fast_expo(x, p / 2) % 1000000007;
    return (t * t) % 1000000007;
  } else
    return (x * (fast_expo(x, p - 1)) % 1000000007) % 1000000007;
}
int ans = 0;
struct Node {
  int x, y, dist;
};
int row[] = {-1, 0, 0, 1};
int col[] = {0, -1, 1, 0};
bool isValid(int mat[][20], bool visited[][20], int row, int col) {
  return (row >= 0) && (row < 20) && (col >= 0) && (col < 20) &&
         mat[row][col] && !visited[row][col];
}
void BFS(int mat[][20], int i, int j, int x, int y) {
  bool visited[20][20];
  memset(visited, false, sizeof visited);
  queue<Node> q;
  visited[i][j] = true;
  q.push({i, j, 0});
  int min_dist = INT_MAX;
  while (!q.empty()) {
    Node node = q.front();
    q.pop();
    int i = node.x, j = node.y, dist = node.dist;
    if (i == x && j == y) {
      min_dist = dist;
      break;
    }
    for (int k = 0; k < 4; k++) {
      if (isValid(mat, visited, i + row[k], j + col[k])) {
        visited[i + row[k]][j + col[k]] = true;
        q.push({i + row[k], j + col[k], dist + 1});
      }
    }
  }
  if (min_dist != INT_MAX) ans = max(min_dist, ans);
}
int main() {
  int i, j;
  int mat[20][20];
  for (i = 0; i < 20; i++) {
    for (j = 0; j < 20; j++) {
      mat[i][j] = 0;
    }
  }
  int N1, M1;
  cin >> N1 >> M1;
  char ch;
  for (i = 0; i < N1; i++) {
    for (j = 0; j < M1; j++) {
      cin >> ch;
      if (ch == '#')
        mat[i][j] = 0;
      else
        mat[i][j] = 1;
    }
  }
  int k, k1;
  int st1, st2, en1, en2;
  for (i = 0; i < N1; i++) {
    st1 = i;
    for (j = 0; j < M1; j++) {
      st2 = j;
      for (k = 0; k < N1; k++) {
        en1 = k;
        for (k1 = 0; k1 < M1; k1++) {
          en2 = k1;
          BFS(mat, st1, st2, en1, en2);
        }
      }
    }
  }
  cout << ans << endl;
  return 0;
}
