#include <bits/stdc++.h>
using namespace std;
int ans;
int H,W;
bool is_valid_move(vector<string> &board, vector<vector<bool>> &checked, int x, int y) {
  
 
  // 移動先がマス目の外である場合
  if (x <= -1 || x >= W || y <= -1 || y >= H) {
    return false;
  }
  // 移動先が壁マス
  if (board.at(y).at(x) == '#') {
    return false;
  }
  // 既に調べているマスへの移動は調べないのでfalseを返す
  if (checked.at(y).at(x)) {
    return false;
  }
 
  // それ以外なら正しい移動
  return true;
}
int reachable(vector<string> &board, vector<vector<bool>> &checked,int sx,int sy,int gx,int gy) {
 int x; 
 int y;
  x=sx;
  y=sy;
  // ベースケース
  if (x == gx && y == gy) {
    // ゴールにいる状態
    return 0;
  }
 
  // 再帰ステップ
 
  checked.at(y).at(x) = true;  // 既に調べているという状態に変えておく
 
  // 「上」「右」「下」「左」のいずれかの移動でゴールに到達できるか？
 
 
  // 上へ移動したマスからゴールに到達できるか？
  if (is_valid_move(board, checked, x, y - 1)) {
    ans++;
    x=x;
    y=y-1;
  }
  // 右へ移動したマスからゴールに到達できるか？
  if (is_valid_move(board, checked, x + 1, y) ) {
    ans++;
    x++;
  }
  // 下へ移動したマスからゴールに到達できるか？
  if (is_valid_move(board, checked, x, y + 1) ) {
    ans++;
    y++;
  }
  // 左へ移動したマスからゴールに到達できるか？
  if (is_valid_move(board, checked, x - 1, y) ) {
    ans++;
    x--;
  }
 
  return ans;
}
 

          
          
int main(){

  cin>>H>>W;
 vector<string> board(N);
  for (int i = 0; i < N; i++) {
    cin >> board.at(i);
  }
  vector<vector<bool>> checked(H, vector<bool>(W, false));
  int A=0;
  for(int i=0;i<H;i++){
    for(int j=0;j<W;j++){
      for(int k=i;k<H;k++){
        for(int l=0;l<W;l++){
          int a=reachble(board,checked,i,j,k,l);
          A=max(A,a);
        }
      }
    }
  }
  cout<<A<<endl;
}
  