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

int dh[] = {1, 0, -1, 0}, dw[] = {0, 1, 0, -1};

pair<pair<int, int>, int> longest_point_dist(
                                             const pair<int, int> & first,
                                             const vector<string> & field
                                             ){
  int H = field.size(), W = field[0].size();
  vector<vector<int>> dist(H, vector<int>(W, 1000));

  queue<pair<pair<int, int>, int>> que;
  dist[first.first][first.second] = 0;
  que.push(make_pair(first, 0));
  while(!que.empty()){
    pair<pair<int, int>, int> now = que.front();
    que.pop();

    pair<int, int> now_point = now.first;
    int now_dist = now.second;

    for(int i = 0; i < 4; i++){
      int h = now_point.first + dh[i], w = now_point.second + dw[i];
      if(h >= 0 && h < H && w >= 0 && w < W && field[h][w] == '.' && dist[h][w] == 1000){
        dist[h][w] = now_dist + 1;
        que.push(make_pair(make_pair(h, w), now_dist + 1));
      }
    }
  }

  pair<int, int> ret_point = make_pair(0, 0);
  int ret_dist = 0;
  for(int h = 0; h < H; h++){
    for(int w = 0; w < W; w++){
      if(dist[h][w] != 1000 && dist[h][w] > ret_dist){
        ret_point = make_pair(h, w);
        ret_dist = dist[h][w];
      }
    }
  }
  return make_pair(ret_point, ret_dist);
}

int main(){
  int H, W;
  cin >> H >> W;
  
  vector<string> S(H);
  for(int i = 0; i < H; i++){
    cin >> S[i];
  }

  vector<vector<vector<vector<int>>>>
    dist(H,
         vector<vector<vector<int>>>(W,
                                     vector<vector<int>>(H,
                                                         vector<int>(W, 10000))));
  for(int h = 0; h < H; h++){
    for(int w = 0; w < W; w++){
      dist[h][w][h][w] = 0;
      for(int i = 0; i < 4; i++){
        int next_h = h + dh[i], next_w = w + dw[i];
        if(next_h >= 0 && next_h < H && next_w >= 0 && next_w < W && S[h][w] == '.' && S[next_h][next_w] == '.'){
          dist[h][w][next_h][next_w] = 1;
        }
      }
    }
  }
  for(int kh = 0; kh < H; kh++){
    for(int kw = 0; kw < W; kw++){
      for(int ih = 0; ih < H; ih++){
        for(int iw = 0; iw < W; iw++){
          for(int jh = 0; jh < H; jh++){
            for(int jw = 0; jw < W; jw++){
              dist[ih][iw][jh][jw] = min(dist[ih][iw][jh][jw],
                                         dist[ih][iw][kh][kw] + dist[kh][kw][jh][jw]);
            }
          }
        }
      }
    }
  }
  int ret = 0;
  for(int ih = 0; ih < H; ih++){
    for(int iw = 0; iw < W; iw++){
      for(int jh = 0; jh < H; jh++){
        for(int jw = 0; jw < W; jw++){
          if(dist[ih][iw][jh][jw] != 10000){
            ret = max(ret, dist[ih][iw][jh][jw]);
          }
        }
      }
    }
  }
  cout << ret << endl;
  /*
  int h = 0, w = 0;
  for(h = 0; h < H; h++){
    bool found = false;
    for(w = 0; w < W; w++){
      if(S[h][w] == '.'){
        found = true;
        break;
      }
    }
    if(found){
      break;
    }
  }
  //cout << "b" << endl;
  pair<pair<int, int>, int> ret1 = longest_point_dist(make_pair(h, w), S);
  //cout << "c" << endl;
  pair<pair<int, int>, int> ret2 = longest_point_dist(ret1.first, S);
  //cout << "d" << endl;
  cout << ret2.second << endl;
  */
}


Measured memory_bytes: 1912