#include <bits/stdc++.h>
using namespace std;
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};
long long m[20][20];
template <class T>
inline bool chmax(T& a, T b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T>
inline bool chmin(T& a, T b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
struct node {
 public:
  long long x;

 public:
  long long y;
  node(long long xx, long long yy) {
    x = xx;
    y = yy;
  }
};
long long resolve(long long h, long long w, long long sx, long long sy,
                  long long gx, long long gy) {
  long long dist[h][w];
  bool get[h][w];
  for (long long i = 0; i < (long long)(h); i++)
    for (long long j = 0; j < (long long)(w); j++) dist[i][j] = 10000;
  for (long long i = 0; i < (long long)(h); i++)
    for (long long j = 0; j < (long long)(w); j++) get[i][j] = false;
  queue<node> que;
  dist[sx][sy] = 0;
  get[sx][sy] = true;
  node n = {sx, sy};
  que.push(n);
  while (!que.empty()) {
    node v = que.front();
    que.pop();
    long long qx = v.x;
    long long qy = v.y;
    get[qx][qy] = true;
    if (qx == gx && qy == gy) {
      return dist[gx][gy];
    }
    if (qx > 0) {
      if (m[qx - 1][qy] == 0) {
        if (dist[qx - 1][qy] > dist[qx][qy] + 1) {
          dist[qx - 1][qy] = dist[qx][qy] + 1;
        }
        if (!get[qx - 1][qy]) {
          que.push({qx - 1, qy});
        }
      }
    }
    if (qx < h - 1) {
      if (m[qx + 1][qy] == 0) {
        if (dist[qx + 1][qy] > dist[qx][qy] + 1) {
          dist[qx + 1][qy] = dist[qx][qy] + 1;
        }
        if (!get[qx + 1][qy]) {
          que.push({qx + 1, qy});
        }
      }
    }
    if (qy > 0) {
      if (m[qx][qy - 1] == 0) {
        if (dist[qx][qy - 1] > dist[qx][qy] + 1) {
          dist[qx][qy - 1] = dist[qx][qy] + 1;
        }
        if (!get[qx][qy - 1]) {
          que.push({qx, qy - 1});
        }
      }
    }
    if (qy < w - 1) {
      if (m[qx][qy + 1] == 0) {
        if (dist[qx][qy + 1] > dist[qx][qy] + 1) {
          dist[qx][qy + 1] = dist[qx][qy] + 1;
        }
        if (!get[qx][qy + 1]) {
          que.push({qx, qy + 1});
        }
      }
    }
  }
  return dist[gx][gy];
}
int main() {
  long long h, w;
  long long v = 1;
  cin >> h >> w;
  for (long long i = 0; i < (long long)(20); i++)
    for (long long j = 0; j < (long long)(20); j++) m[i][j] = -1;
  for (long long i = 0; i < (long long)(h); i++) {
    for (long long j = 0; j < (long long)(w); j++) {
      char l;
      cin >> l;
      if (l == '.') {
        m[i][j] = 0;
      } else {
        m[i][j] = -1;
      }
    }
  }
  for (long long sx = 0; sx < (long long)(h); sx++) {
    for (long long sy = 0; sy < (long long)(w); sy++) {
      for (long long gx = 0; gx < (long long)(h); gx++) {
        for (long long gy = 0; gy < (long long)(w); gy++) {
          if (sx == gx && sy == gy) {
            continue;
          }
          if (m[sx][sy] != 0 || m[gx][gy] != 0) {
            continue;
          }
          long long f = resolve(h, w, sx, sy, gx, gy);
          if (f > v) {
            v = f;
          }
        }
      }
    }
  }
  cout << v << endl;
  return 0;
}
