#include <bits/stdc++.h>
using namespace std;
using lint = long long;
struct edge {
  lint to;
  lint cost;
};
using P = pair<lint, lint>;
using D = pair<double, double>;
const lint mod = 1000000007LL;
const lint inf = 3LL * mod * mod;
const double Pi = acos(-1.0);
template <class T>
inline bool chmax(T& a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <class T>
inline bool chmin(T& a, T b) {
  return chmax(b, a);
}
lint modpow(lint x, lint n, lint m) {
  lint ans = 1;
  while (n > 0) {
    if (n & 1) {
      ans *= x;
      if (m <= ans) ans %= m;
    }
    x *= x;
    if (m <= x) x %= m;
    n >>= 1;
  }
  return ans;
}
lint fact[1000000];
void f_init(lint n) {
  if (1000000 <= n) return;
  fact[0] = fact[1] = 1;
  for (lint i = 2; i <= n; ++i) {
    fact[i] = i * fact[i - 1];
    if (mod <= fact[i]) fact[i] %= mod;
  }
  return;
}
lint inver[1000000];
bool inve[100000];
lint inv(lint x) {
  if (x == 0)
    return 0;
  else if (inve[x])
    return inver[x];
  else {
    inve[x] = true;
    return inver[x] = modpow(x, mod - 2, mod);
  }
}
lint comb(lint n, lint r) {
  if (n < r) return 0;
  if (n == r) return 1;
  lint ans = fact[n] * inv(fact[n - r]) % mod * inv(fact[r]) % mod;
  if (ans < 0) return ans + mod;
  return ans;
}
lint nck[1010][1010];
void comb(lint n) {
  for (lint i = 0; i < lint(n + 1); ++i) {
    for (lint j = 0; j < lint(i + 1); ++j) {
      if (j == 0 || i == j)
        nck[i][j] = 1;
      else
        nck[i][j] = nck[i - 1][j - 1] + nck[i - 1][j];
    }
  }
}
lint gcd(lint a, lint b) {
  if (b == 0) return a;
  return gcd(b, a % b);
}
lint lcm(lint a, lint b) { return a / gcd(a, b) * b; }
bool pri(lint p) {
  for (lint i = 2; i * i <= p; i == 2 ? ++i : i += 2)
    if (p % i == 0) return false;
  return p > 1;
}
map<lint, lint> factring(lint n) {
  map<lint, lint> ans;
  for (lint i = 2; i * i <= n; ++i) {
    while (n % i == 0) {
      n /= i;
      ++ans[i];
    }
  }
  if (n != 1) ++ans[n];
  return ans;
}
lint xor128() {
  static lint x = 123456789, y = 362436069, z = 521288629, w = 88675123;
  lint t = (x xor (x << 11));
  x = y;
  y = z;
  z = w;
  return (w = (w xor (w >> 19)) xor (t xor (t >> 8)));
}
double dis(D a, D b) {
  double x = a.first - b.first, y = a.second - b.second;
  return sqrt(x * x + y * y);
}
class unionfind {
 private:
  int par[2 * 100010], ranks[2 * 100010], sizeth[2 * 100010];

 public:
  void init(int n) {
    for (int i = 0; i < n; ++i) {
      par[i] = i;
      ranks[i] = 0;
      sizeth[i] = 1;
    }
  }
  int root(int x) {
    if (par[x] == x) return x;
    return par[x] = root(par[x]);
  }
  bool same(int x, int y) { return root(x) == root(y); }
  void unite(int x, int y) {
    x = root(x);
    y = root(y);
    if (x == y) return;
    if (ranks[x] < ranks[y]) {
      par[x] = y;
      sizeth[y] += sizeth[x];
    } else {
      par[y] = x;
      if (ranks[x] == ranks[y]) ++ranks[x];
      sizeth[x] += sizeth[y];
    }
  }
};
int h, w, n, ans;
char c[22][22];
int d[22][22];
int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
bool can(int x, int y) {
  if (0 <= x && x < w && 0 <= y && y < h) return true;
  return false;
}
int main() {
  cin >> h >> w;
  n = h * w;
  for (lint i = 0; i < lint(h); ++i) {
    for (lint j = 0; j < lint(w); ++j) {
      cin >> c[i][j];
    }
  }
  for (lint i = 0; i < lint(n); ++i) {
    for (lint j = 0; j < lint(n); ++j) {
      if (i != j) d[i][j] = 100000;
    }
  }
  for (lint i = 0; i < lint(h); ++i) {
    for (lint j = 0; j < lint(w); ++j) {
      if (c[i][j] == '.') {
        for (lint k = 0; k < lint(4); ++k) {
          int ny = i + dy[k], nx = j + dx[k];
          if (can(nx, ny)) {
            if (c[ny][nx] == '.') {
              d[w * i + j][w * ny + nx] = d[w * ny + nx][w * i + j] = 1;
            }
          }
        }
      }
    }
  }
  for (lint k = 0; k < lint(n); ++k) {
    for (lint i = 0; i < lint(n); ++i) {
      for (lint j = 0; j < lint(n); ++j) {
        d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
      }
    }
  }
  for (lint i = 0; i < lint(h); ++i) {
    for (lint j = 0; j < lint(w); ++j) {
      for (lint k = 0; k < lint(h); ++k) {
        for (lint l = 0; l < lint(w); ++l) {
          if (c[i][j] == '.' && c[k][l] == '.') {
            ans = max(ans, d[i * w + j][k * w + l]);
          }
        }
      }
    }
  }
  cout << ans << endl;
}
