#include <bits/stdc++.h>
using namespace std;
typedef vector<int> vint;
typedef vector<double> vdouble;
typedef vector<long long> vll;
typedef vector<long double> vld;
typedef vector<pair<long long, long long>> vl_l;
typedef vector<pair<int, int>> vi_i;
typedef vector<pair<double, double>> vd_d;
template <typename T>
void read(T& x) {
  cin >> x;
}
template <typename T, typename T0>
void read(T& x, T0& y) {
  cin >> x >> y;
}
template <typename T, typename T0, typename T1>
void read(T& x, T0& y, T1& z) {
  cin >> x >> y >> z;
}
template <typename T, typename T0, typename T1, typename T2>
void read(T& x, T0& y, T1& z, T2& w) {
  cin >> x >> y >> z >> w;
}
template <typename T>
void read(vector<T>& oneD, int n) {
  long long n1 = (long long)n;
  for (long long i = 0; i < (n1); i++) {
    long long x;
    read(x);
    oneD.push_back(x);
  }
}
template <typename T>
void read(vector<T>& oneD, long long n) {
  for (long long i = 0; i < (n); i++) {
    long long x;
    read(x);
    oneD.push_back(x);
  }
}
template <typename T>
void read(T oneD[], int n) {
  long long n1 = (long long)n;
  for (long long i = 1; i <= (n1); i++) {
    read(oneD[i]);
  }
}
template <typename T>
void read(T oneD[], long long n) {
  for (long long i = 1; i <= (n); i++) {
    read(oneD[i]);
  }
}
template <typename T, typename T0>
void read(pair<T, T0>& p) {
  cin >> p.first >> p.second;
}
template <typename T>
void write(T& x) {
  cout << x << endl;
}
template <typename T, typename T0>
void write(T& x, T0& y) {
  cout << x << " " << y << "\n";
}
template <typename T, typename T0, typename T1>
void write(T& x, T0& y, T1& z) {
  cout << x << " " << y << " " << z << "\n";
}
template <typename T, typename T0, typename T1, typename T2>
void write(T& x, T0& y, T1& z, T2& w) {
  cout << x << " " << y << " " << z << " " << w << "\n";
}
template <typename T>
void write(vector<T>& oneD, int n) {
  long long n1 = (long long)n;
  for (long long i = 0; i < (n1); i++) {
    cout << oneD[i] << " ";
  }
  cout << endl;
}
template <typename T>
void write(vector<T>& oneD, long long n) {
  for (long long i = 0; i < (n); i++) {
    cout << oneD[i] << " ";
  }
  cout << endl;
}
template <typename T>
void write(T oneD[], int n) {
  long long n1 = (long long)n;
  for (long long i = 1; i <= (n1); i++) {
    write(oneD[i]);
  }
  cout << endl;
}
template <typename T>
void write(T oneD[], long long n) {
  for (long long i = 1; i <= (n); i++) {
    write(oneD[i]);
  }
  cout << endl;
}
template <typename T, typename T0>
void write(pair<T, T0>& p) {
  cout << p.first << " " << p.second << " ";
  cout << endl;
}
const int dx[8] = {1, 0, -1, 0, 1, 1, -1, -1};
const int dy[8] = {0, 1, 0, -1, 1, -1, 1, -1};
int fh, fw;
vector<string> field;
int main(void) {
  read(fh, fw);
  field.resize(fh);
  for (int h = 0; h < fh; ++h) cin >> field[h];
  int s[2], g[2];
  int max = 0;
  for (int h = 0; h < fh; ++h) {
    for (int w = 0; w < fw; ++w) {
      if (field[h][w] == '#') break;
      s[0] = h;
      s[1] = w;
      for (int h = 0; h < fh; ++h) {
        for (int w = 0; w < fw; ++w) {
          if (field[h][w] == '#') break;
          g[0] = h;
          g[1] = w;
          int dist[50][50];
          memset(dist, -1, sizeof(dist));
          queue<pair<int, int>> que;
          dist[s[0]][s[1]] = 0;
          pair<int, int> sp(s[0], s[1]);
          que.push(sp);
          while (!que.empty()) {
            pair<int, int> v = que.front();
            que.pop();
            for (int dir = 0; dir < 4; ++dir) {
              int nh = v.first + dx[dir];
              int nw = v.second + dy[dir];
              if (nh < 0 || nh >= fh || nw < 0 || nw >= fw)
                continue;
              else if (field[nh][nw] == '#')
                continue;
              else if (dist[nh][nw] != -1)
                continue;
              dist[nh][nw] = dist[v.first][v.second] + 1;
              pair<int, int> np(nh, nw);
              que.push(np);
            }
          }
          for (int h = 0; h < fh; h++) {
            for (int w = 0; w < fw; w++) {
              if (g[0] == h && g[1] == w) {
                if (max < dist[h][w]) {
                  max = dist[h][w];
                  break;
                }
              }
            }
          }
        }
      }
    }
  }
  write(max);
  return 0;
}
