#include <bits/stdc++.h>
struct P {
  int x;
  int y;
};
using Q = std::queue<std::pair<P, int>>;
using Maze = std::vector<std::string>;
using Map = std::vector<std::vector<int>>;
void try_push(Q& queue, const Maze& maze, Map& map, const P& p, int count) {
  if (p.y < 0 || p.y >= static_cast<int>(maze.size())) return;
  if (p.x < 0 || p.x >= static_cast<int>(maze[0].size())) return;
  if (maze[p.y][p.x] == '#') return;
  if (map[p.y][p.x] > 0) return;
  map[p.y][p.x] = 1;
  queue.push({p, count});
}
int go(const Maze& maze, Map& map, Q& queue) {
  const auto pair = queue.front();
  queue.pop();
  const auto p = pair.first;
  const auto count = pair.second + 1;
  try_push(queue, maze, map, P{p.x + 1, p.y}, count);
  try_push(queue, maze, map, P{p.x - 1, p.y}, count);
  try_push(queue, maze, map, P{p.x, p.y + 1}, count);
  try_push(queue, maze, map, P{p.x, p.y - 1}, count);
  return queue.empty() ? pair.second : go(maze, map, queue);
}
int count(const Maze& maze, const P& s) {
  Map map(maze.size(), std::vector<int>(maze[0].size(), 0));
  Q queue;
  queue.push({s, 0});
  return go(maze, map, queue);
}
int solve(int h, int w, const Maze& maze) {
  int result = 0;
  for (int y = 0; y < static_cast<int>(maze.size()); ++y) {
    for (int x = 0; x < static_cast<int>(maze[0].size()); ++x) {
      if (maze[y][x] == '.') {
        result = std::max(result, count(maze, {x, y}));
      }
    }
  }
  return result;
}
int main() {
  int h, w;
  std::cin >> h >> w;
  Maze maze(h);
  for (auto& s : maze) {
    std::cin >> s;
  }
  std::cout << solve(h, w, maze) << std::endl;
}
