#include <bits/stdc++.h>
using namespace std;
int main() {
  int h, w;
  cin >> h >> w;
  char way[21 + 3][21 + 3] = {};
  int route[21 + 3][21 + 3] = {};
  int x0 = -1;
  int y0 = -1;
  for (int y = 1; y <= h; ++y) {
    for (int x = 1; x <= w; ++x) {
      char c;
      cin >> c;
      way[y][x] = (c == '.');
      if (way[y][x] && x0 < 0 && y0 < 0) {
        x0 = x;
        y0 = y;
      }
    }
  }
  auto open = vector<int>();
  open.reserve(20 * 20);
  struct XY {
    int x, y;
  };
  const XY dir[4] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
  struct XYR {
    int x, y, max_r;
  };
  const auto &fill_route = [&](int x_start, int y_start) {
    open.clear();
    open.push_back(x_start + y_start * 256);
    memset(route, 0, sizeof(route));
    route[y_start][x_start] = 1;
    while (!open.empty()) {
      int xy = open.front();
      open.erase(open.begin());
      int x = xy % 256;
      int y = xy / 256;
      int K = route[y][x];
      for (auto d : dir) {
        int nx = x + d.x;
        int ny = y + d.y;
        if (!way[ny][nx]) continue;
        if (route[ny][nx]) continue;
        route[ny][nx] = K + 1;
        open.push_back(nx + ny * 256);
      }
    }
  };
  const auto &find_max = [&]() {
    int max_r = 0;
    int sx, sy;
    for (int y = 1; y <= h; ++y) {
      for (int x = 1; x <= w; ++x) {
        if (route[y][x] > max_r) {
          sx = x;
          sy = y;
          max_r = route[y][x];
        }
      }
    }
    return XYR{sx, sy, max_r};
  };
  cerr << x0 << ", " << y0 << "\n";
  fill_route(x0, y0);
  auto xyr = find_max();
  cerr << xyr.x << ", " << xyr.y << ": " << xyr.max_r << "\n";
  fill_route(xyr.x, xyr.y);
  xyr = find_max();
  cout << (xyr.max_r - 1);
  return 0;
}
