#include <bits/stdc++.h>
using namespace std;
struct XX {
  long long a;
  int i;
};
class xxGreater {
 public:
  bool operator()(const XX& riLeft, const XX& riRight) const {
    if ((riLeft.a) == (riRight.a)) {
      return riLeft.i < riRight.i;
    }
    return (riLeft.a) > (riRight.a);
  }
};
int ppar[100001];
int rrank[100001];
void init(int n) {
  for (int i = 0; i < n; i++) {
    ppar[i] = i;
    rrank[i] = 0;
  }
}
int find(int x) {
  if (ppar[x] == x) {
    return x;
  } else {
    return ppar[x] = find(ppar[x]);
  }
}
void unite(int x, int y) {
  x = find(x);
  y = find(y);
  if (x == y) {
    return;
  }
  if (rrank[x] < rrank[y]) {
    ppar[x] = y;
  } else {
    ppar[y] = x;
    if (rrank[x] == rrank[y]) {
      rrank[x]++;
    }
  }
}
bool same(int x, int y) { return find(x) == find(y); }
int H, W;
string mat[20];
int d[1000];
struct X {
  int i;
  int j;
  int kyori;
};
int di[] = {-1, 0, 1, 0};
int dj[] = {0, -1, 0, 1};
queue<X> qq;
void bfs(int i, int j, int k) {
  X x;
  x.i = i;
  x.j = j;
  x.kyori = k;
  qq.push(x);
  d[i * W + j] = k;
  while (!qq.empty()) {
    X tmp = qq.front();
    qq.pop();
    for (int ind = 0; ind < 4; ind++) {
      int ti = tmp.i + di[ind];
      int tj = tmp.j + dj[ind];
      if (ti < 0 || tj < 0 || ti >= H || tj >= W) {
        continue;
      }
      if (mat[ti][tj] == '#') {
        continue;
      }
      X x;
      x.i = ti;
      x.j = tj;
      x.kyori = tmp.kyori + 1;
      qq.push(x);
      d[ti * W + tj + 1] = tmp.kyori + 1;
    }
  }
}
int main(int argc, const char* argv[]) {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cin >> H >> W;
  for (int i = 0; i < H; i++) {
    cin >> mat[i];
  }
  init(H * W);
  for (int i = 0; i < H; i++) {
    for (int j = 0; j < W; j++) {
      if (mat[i][j] == '.') {
        if (j + 1 < W && mat[i][j + 1] == '.') {
          unite(i * W + j, i * W + j + 1);
        }
        if (j - 1 >= 0 && mat[i][j - 1] == '.') {
          unite(i * W + j, i * W + j - 1);
        }
        if (i + 1 < W && mat[i + 1][j] == '.') {
          unite(i * W + j, (i + 1) * W + j);
        }
        if (i - 1 >= 0 && mat[i - 1][j] == '.') {
          unite(i * W + j, (i - 1) * W + j);
        }
      }
    }
  }
  set<int> mp;
  for (int i = 0; i < H; i++) {
    for (int j = 0; j < W; j++) {
      mp.insert(find(i * W + j));
    }
  }
  int ans = 0;
  for (auto s : mp) {
    int p = s / W;
    int q = s % W;
    bfs(p, q, 0);
    int t = 0;
    int ti = 0;
    for (int i = 0; i < H; i++) {
      for (int j = 0; j < W; j++) {
        if (t < d[i * W + j]) {
          t = d[i * W + j];
          ti = i * W + j;
        }
        d[i * W + j] = 0;
      }
    }
    p = ti / W;
    q = ti % W;
    bfs(p, q, 0);
    for (int i = 0; i < H; i++) {
      for (int j = 0; j < W; j++) {
        ans = max(ans, d[i * W + j]);
        d[i * W + j] = 0;
      }
    }
  }
  cout << ans << endl;
  return 0;
}
