#include<bits/stdc++.h>
#include<queue>
#include<string>
using namespace std;


long long H,W, INF= 1000000000;

//文字は一次元は配列
vector<vector<string> > s(H,vector<string>(W));;

//縦横の移動
long long dx[4] = { 0, 0, 1, -1 }, dy[4] = { 1, -1, 0, 0 };

//X,Yはスタート位置
long long BFS(long long X,long long Y){
    //キューの宣言(二次元)
    queue<pair<long long,long long>> q;
    //可変長配列の宣言(H×Wの配列)　INFは初期値　訪問用の記録変数
    vector<vector<long long> > Dist(H,vector<long long>(W,INF));

    q.push({X,Y});
    Dist[X][Y] = 0;
    while(!q.empty()){
        pair<long long , long long> P = q.front();
        q.pop();
        for(int i = 0; i < 4; i++){
            //X座標、Y座標を±1 Pは現在地
            long long NX = P.first + dx[i], NY = P.second + dy[i];

            //次の訪問先が範囲内の場合
            if (0 <= NX && NX < H && 0 <= NY && NY < W) {
                //次の訪問先が移動可能の場合
                if(s.at[NX][NY] == '.' and Dist[NX][NY] == INF){

                    Dist[NX][NY] = Dist[P.first][P.second] + 1;
                    q.push({NX,NY});
                
                }
            }
        }
    }

    long long MAX = 0;
    for(int i = 0; i < H; i++){
        for(int j = 0; j < W; j++)
            if(Dist[i][j] != INF) MAX = max(MAX,Dist[i][j]); 
    }
    return MAX;
}


int main(){
    cin >> H >> W;
    for(int i = 0; i < H; i++ ){
        for(int j = 0; j < W; j++ ){
            cin >> s[i][j];
        }
    } 
    long long ans = 0;
    for(int i = 0; i < H; i++ ){
        for(int j = 0; j < W; j++ ){
            if(s.at[i][j] == '.') ans = max(ans,BFS(i,j)); 
        }
    }
    cout << ans << endl;
}