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

using P = pair<int, int>;  //firstがタテ、secondがヨコの座標
using Graph = map<P, vector<P>>;

//頂点(h,w)=(a,b)に、(i,j)が隣接しているとグラフに入力
void input(Graph& G, int a, int b, int i, int j) {
    P now,next;
    now.first = a;
    now.second = b;
    next.first = i;
    next.second = j;
    G[now].push_back(next);
}

void bfs(const Graph&, map<P, int>&, queue<P>&);

int main() {
    int h,w;
    cin>>h>>w;
    vector<vector<char>> maze(h+2);
    int count = 0;

    //周りを壁で囲んでmaze作ってみた。あれ、悪くないのでは?
    for(int i=0; i<w+2; i++) maze[0].push_back('#');
    for(int i=1; i<=h; i++) {
        maze[i].push_back('#');
        for(int j=0; j<w; j++) {
            char s;
            cin>>s;
            if(s=='.') count++;
            maze[i].push_back(s);
        }
        maze[i].push_back('#');
    }
    for(int i=0; i<w+2; i++) maze[h+1].push_back('#');

    //グラフ入力作業
    Graph G;
    for(int i=1; i<=h; i++) {
        for(int j=1; j<=w; j++) {
            if(maze[i][j]=='.') {
                if(maze[i][j-1] == '.') input(G,i,j,i,j-1);
                if(maze[i-1][j] == '.') input(G,i,j,i-1,j);
                if(maze[i][j+1] == '.') input(G,i,j,i,j+1);
                if(maze[i+1][j] == '.') input(G,i,j,i+1,j);
            }
        }
    }


    vector<int> propo;
    for(int i=1; i<=h; i++) {
        for(int j=1; j<=w; j++) {
            if(maze[i][j]=='.') {
                map<P, int> dist;
                queue<P> todo;
                P start;
                start.first = i;
                start.second = j;
                dist[start] = 1;
                todo.push(start);

                //bfs(G, dist, todo);
                while(!todo.empty()) {
                    P v = todo.front();
                    todo.pop();

                    // cout<<v.first<<' '<<v.second<<endl;
                    // if(v.first==1 && v.second==1) cout<<G[v][0].first<<endl;

                    for(P next_v : G[v]) {
                        if(dist[next_v]!=0) continue;

                        dist[next_v] = dist[v] +1;
                        todo.push(next_v);
                    }
                }
                //int max = *max_element(dist.second.begin(), dist.second.end());
                //int max = 4;
                //int max = dist.size();
                int len = dist.size();
                int dist2[len];
                auto begin = dist.begin();
                auto end = dist.end();
                int k=0;
                for(auto iter=begin; iter!=end; iter++) {
                    dist2[k] = iter->second;
                    k++;
                }
                int max = *max_element(dist2, dist2+len);
                propo.push_back(max);
            }
        }
    }
    // P test;
    // test.first = 1;
    // test.second = 1;
    // cout<<G[test][0].first<<G[test][0].second<<' '<<G[test][1].first<<G[test][1].second<<endl;

    int ans = *max_element(propo.begin(), propo.end()) -1;
    cout<<ans<<endl;

    return 0;
}

    

//幅優先探索！
// void bfs(const Graph& G, map<P, int>& dist, queue<P>& todo) {
//     while(!todo.empty()) {
//         P v = todo.front();
//         todo.pop();

//         // cout<<v.first<<' '<<v.second<<endl;
//         // if(v.first==1 && v.second==1) cout<<G[v][0].first<<endl;

//         for(P next_v : G[v]) {
//             if(dist[next_v]!=0) continue;

//             dist[next_v] = dist[v] +1;
//             todo.push(next_v);
//         }
//     }
// }

Measured memory_bytes: 384