#include <bits/stdc++.h>
using namespace std;
class maze_calc {
 public:
  maze_calc();
  void set(int h, int w);
  void calc_main(int i, int j, int ig, int jg, vector<string> maze, int cnt);
  void shortest();
  int max_val();

 private:
  int H = 0;
  int W = 0;
  vector<int> val;
  vector<int> min_val;
};
maze_calc::maze_calc() { min_val.clear(); }
void maze_calc::set(int h, int w) {
  H = h;
  W = w;
  val.clear();
  return;
}
void maze_calc::calc_main(int i, int j, int ig, int jg, vector<string> maze,
                          int cnt) {
  if (i == ig && j == jg) {
    val.push_back(cnt);
    return;
  }
  int jdg = 0;
  maze[i][j] = '#';
  if (i - 1 >= 0 && maze[i - 1][j] == '.') {
    jdg += 1;
    calc_main(i - 1, j, ig, jg, maze, cnt + 1);
  }
  if (i + 1 < H && maze[i + 1][j] == '.') {
    jdg += 1;
    calc_main(i + 1, j, ig, jg, maze, cnt + 1);
  }
  if (j - 1 >= 0 && maze[i][j - 1] == '.') {
    jdg += 1;
    calc_main(i, j - 1, ig, jg, maze, cnt + 1);
  }
  if (j + 1 < W && maze[i][j + 1] == '.') {
    jdg += 1;
    calc_main(i, j + 1, ig, jg, maze, cnt + 1);
  }
  if (jdg == 0) {
    return;
  }
}
void maze_calc::shortest() {
  min_val.push_back(*min_element(val.begin(), val.end()));
  val.clear();
}
int maze_calc::max_val() {
  return *max_element(min_val.begin(), min_val.end());
}
int main() {
  int H;
  int W;
  cin >> H;
  cin >> W;
  string str;
  vector<string> maze(H);
  vector<int> way_x;
  vector<int> way_y;
  for (int i = 0; i < H; i++) {
    cin >> str;
    maze[i] = str;
    for (int j = 0; j < W; j++) {
      if (maze[i][j] == '.') {
        way_y.push_back(i);
        way_x.push_back(j);
      }
    }
  }
  maze_calc mc;
  mc.set(H, W);
  for (int i = 0; i < way_y.size() - 1; i++) {
    for (int j = i + 1; j < way_y.size(); j++) {
      mc.calc_main(way_y[i], way_x[i], way_y[j], way_x[j], maze, 0);
      mc.shortest();
    }
  }
  cout << mc.max_val() << endl;
  return 0;
}
