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

typedef long long int LL;
typedef long long int LLint;

//Faster Program
#define endl "\n"

//Faster Coding
#define ED return
#define GET(a) int a;cin >> a
#define DGET(a) double a;cin >> a
#define SGET(a) string a;cin >> a
#define CGET(a) char a;cin >> a
#define PRINT(a) cout << a << "\n"
#define ANS(a,b) int a;cin >> a;cout << b << "\n"
#define FOR(n) for(int i = 0;i < n;i++)
#define SORT(vec) sort(vec.begin(),vec.end())
#define REV(vec) reverse(vec.begin(),vec.end())

//As Function
#define UP(a,b) ((a+(b-1))/b)
#define ipow(x,y) LL(pow(x,y))

//Debug
#define TEST cout << "OK\n"

const double PI = M_PI;
const long long INF = int(999999999);
const long long MOD = int(1000000007);

//Settings
const bool DO_BENCHMARK = false;
const int DOUBLE_ACCURACY = 15;

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(DOUBLE_ACCURACY);
    void solve();
    if(DO_BENCHMARK){
        clock_t clock_start = clock();
        solve();
        clock_t clock_end = clock();
        const double time = static_cast<double>(clock_end-clock_start)/CLOCKS_PER_SEC*1000.0;
        cout << "\n" << time << "[ms]\n";
    }
    else solve();
}

void solve(){
    int H, W;
    cin >> H >> W;
    vector<vector<bool>> wall (H+2,vector<bool>(W+2,true));
    for(int i = 0;i < H;i++){
        for(int j = 0;j < W;j++){
            char dummy;
            cin >> dummy;
            if(dummy == '.'){
                wall[i+1][j+1] = false;
            }
            else{
                wall[i+1][j+1] = true;
            }
        }
    }
    int b_max = 0;
    for(int h = 0;h < H+2;h++){
        for(int w = 0;w < W+2;w++){
            if(wall[h][w]){
                continue;
            }
            vector<vector<int>> dist (H+2,vector<int>(W+2,INF));
            dist[h][w] = 0;
            vector<pair<int,int>> next (1,make_pair(h,w));
            int i = 0;
            while(next.size() > i){
                if(wall[next[i].first][next[i].second] == false && dist[next[i].first+1][next[i].second] > dist[next[i].first][next[i].second]+1){
                    dist[next[i].first+1][next[i].second] = dist[next[i].first][next[i].second]+1;
                    next.push_back(make_pair(next[i].first+1,next[i].second));
                }
                if(wall[next[i].first][next[i].second] == false && dist[next[i].first-1][next[i].second] > dist[next[i].first][next[i].second]+1){
                    dist[next[i].first-1][next[i].second] = dist[next[i].first][next[i].second]+1;
                    next.push_back(make_pair(next[i].first-1,next[i].second));
                }
                if(wall[next[i].first][next[i].second] == false && dist[next[i].first][next[i].second+1] > dist[next[i].first][next[i].second]+1){
                    dist[next[i].first][next[i].second+1] = dist[next[i].first][next[i].second]+1;
                    next.push_back(make_pair(next[i].first,next[i].second+1));
                }
                if(wall[next[i].first][next[i].second] == false && dist[next[i].first][next[i].second-1] > dist[next[i].first][next[i].second]+1){
                    dist[next[i].first][next[i].second-1] = dist[next[i].first][next[i].second]+1;
                    next.push_back(make_pair(next[i].first,next[i].second-1));
                }
                i++;
            }
            int s_max = 0;
            for(int a = 0;a < H+2;a++){
                for(int b = 0;b < W+2;b++){
                    if(wall[a][b] == false){
                        //cout << dist[a][b];
                        s_max = max(s_max,dist[a][b]);
                    }
                    //else cout << '#';
                }
                //cout << endl;
            }
            //cout << h << "," << w << " dist=" << s_max << endl;
            b_max = max(b_max,s_max);
        }
    }
    cout << b_max << endl;
}


Measured memory_bytes: 256