#include <bits/stdc++.H>
using namespace std;
#define rep(i, a, b) for(int i  = a; i < b; i++)
typedef long long ll;

//static const int MAX_V = 400 * 400 + 10;
const int INF = 1e9;
int V;
using namespace std;
static const int N = 100;
static const int INFTY = (1 << 21);
static const int white = 0;
static const int gray = 1;
static const int black = 2;

int H , W;
int ans = 0;
int sy, sx, gy, gx;
int M[N][N];
int d[N][N];
int color[N][N];
vector<string> S;

void bfs(int sy, int sx){
    queue<pair<int, int> > Q;
    color[sy][sx] = gray;
    d[sy][sx] = 0;
    Q.push(make_pair(sy, sx));//全てはスタート地点をqueueに突っ込んでからは閉まる
    while(!Q.empty()){
        pair<int,int> u = Q.front();Q.pop();
        color[u.first][u.second] = black;//動いたら黒に
        if(u.first + 1 < H){//配列の参照範囲内であることを確認したら
            if(color[u.first + 1][u.second] == white){//まだ踏んでいないor可動範囲であることを確認して
                Q.push(make_pair(u.first+1,u.second));//queueに突っ込む
                color[u.first + 1][u.second] = gray;//突っ込んだらgray色にすることを忘れない
                d[u.first + 1][u.second] = d[u.first][u.second] + 1;//距離は元の場所から1足す
            }
        }//以下同様,今回は2次元迷路なので4方向確認している。
        if(u.first - 1 >= 0){
            if(color[u.first - 1][u.second] == white){
                Q.push(make_pair(u.first-1,u.second));
                color[u.first - 1][u.second] = gray;
                d[u.first - 1][u.second] = d[u.first][u.second] + 1;
            }
        }
        if(u.second + 1 < W){
            if(color[u.first][u.second+1] == white){
                Q.push(make_pair(u.first,u.second+1));
                color[u.first][u.second+1] = gray;
                d[u.first][u.second+1] = d[u.first][u.second] + 1;
            }
        }
        if(u.second - 1 >= 0){
            if(color[u.first][u.second-1] == white){
                Q.push(make_pair(u.first,u.second-1));
                color[u.first][u.second-1] = gray;
                d[u.first][u.second-1] = d[u.first][u.second] + 1;
            }
        }
        
    }
    rep(i, 0, H) rep(j, 0, W) if(d[i][j] != INF) ans = max(ans, d[i][j]);

}
int main(){
    cin >> H >> W;
    S.resize(H);
    rep(i, 0, H) cin >> S[i];
    //rep(i, 0, H * W) rep(j, 0, H * W) d[i][j] = INF;
    rep(i, 0, H) rep(j, 0, W){
        rep(k, 0, H) rep(l, 0, W){
            d[k][l] = INF;
            if(S[k][l] == '.') color[k][l] = white;
            else color[k][l] = black;
        }
        bfs(i,j);
    }
    cout << ans << endl;

}