#include <bits/stdc++.h>
using namespace std;
struct Node {
  int x, y, dist;
};
int row[] = {-1, 0, 0, 1};
int col[] = {0, -1, 1, 0};
bool isValid(int mat[][22], bool visited[][22], int row, int col) {
  return (row >= 0) && (row < 22) && (col >= 0) && (col < 22) &&
         mat[row][col] && !visited[row][col];
}
int BFS(int mat[][22], int i, int j, int x, int y) {
  bool visited[22][22];
  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});
      }
    }
  }
  return min_dist;
}
int main() {
  int mat[22][22];
  memset(mat, 0, sizeof(mat));
  int r, c;
  cin >> r >> c;
  char cc;
  for (int i = 0; i < r; ++i) {
    for (int j = 0; j < c; ++j) {
      cin >> cc;
      if (cc == '.') {
        mat[i][j] = 1;
      } else {
        mat[i][j] = 0;
      }
    }
  }
  int max_ans = 0;
  for (int i = 0; i < r; ++i) {
    for (int j = 0; j < c; ++j) {
      for (int k = 0; k < r; ++k) {
        for (int m = 0; m < c; ++m) {
          if (i != k && j != m && mat[i][j] == 1 && mat[k][m] == 1) {
            int dist = BFS(mat, i, j, k, m);
            if (dist != INT_MAX && dist > max_ans) max_ans = dist;
          }
        }
      }
    }
  }
  cout << max_ans << endl;
  return 0;
}
