// bfs

#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector<string> field;
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};

// int true_max = 0;
int tmp_max = 0;

int main(){
  int h, w;
  cin >> h >> w;

  field.resize(h);
  for(int i = 0; i < h; ++i)cin >> field[i];

  int is_wall[h][w];
  for(int i = 0; i < h; ++i){
    for(int j = 0; j < w; ++j){
      is_wall[h][w] = 0;
    }
  }

  for(int i = 0; i < h; ++i){
    for(int j = 0; j < w; ++j){
      if(field[i][j] == '#')is_wall[i][j] = 1
    }
  }

  for(int i = 1; i <= h; ++i){
    for(int j = 1; j <= w; ++j){
      if(is_wall[i][j])continue;

      int sy, sx;
      sy = i;
      sx = j;

      vector<vector<int>> dist(h, vector<int>(w, -1)); // init
      queue<pair<int, int>> que;

      dist[sy - 1][sx - 1] = 0;
      que.push(make_pair(sx - 1, sy - 1));

      while(!que.empty()){
        pair<int, int> v = que.front();
        que.pop();

        for(int i = 0; i < 4; ++i){
          int nx = v.first + dx[i];
          int ny = v.second + dy[i];

          if(ny < 0 || ny >= h || nx < 0 || nx >= w)continue;
          if(field[ny][nx] == '#')continue;

          if(dist[ny][nx] != -1)continue;

          dist[ny][nx] = dist[v.second][v.first] + 1;
          que.push(make_pair(nx, ny));
        }
      }

      for(int i = 0; i < h; ++i){
        for(int j = 0; j < w; ++j){
          tmp_max = max(tmp_max, dist[i][j]);
        }
      }
    }
  }

  cout << tmp_max << endl;
}
