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

using Graph = vector<vector<int>>;

int bfs(const Graph& G, vector<bool>& seen, queue<int>& todo, int depth) {
    bool flag = true;
    while(!todo.empty()) {
        if(todo.front() == -1) {
            depth++;
            todo.pop();
            flag = true;
        }

        else {
            if(!seen[todo.front()]) {
                seen[todo.front()] = true;
                if(flag) {
                    todo.push(-1);
                    flag = false;
                }
                for(auto next_v : G[todo.front()]) {
                    if(seen[next_v]) continue;
                    todo.push(next_v);
                }
            }
            todo.pop();
        }
    }
    
    return depth;
}

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

    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('#');

    //とりあえず確認
    // for(int i=0; i<h+2; i++) {
    //     for(int j=0; j<w+2; j++) {
    //         cout<<maze[i][j];
    //     }
    //     cout<<endl;
    // }

    //cout<<maze[h-1][w]<<endl;
    //if(maze[h-1][w] == '.') cout<<"ok"<<endl;

    //グラフ入力作業
    Graph G(h*w+1);
    for(int i=1; i<=h; i++) {
        for(int j=1; j<=w; j++) {
            int posi = w*(i-1) + j;
            if(maze[i][j]=='.') {
                if(maze[i][j-1] == '.') G[posi].push_back(posi-1);
                if(maze[i-1][j] == '.') G[posi].push_back(posi-w);
                if(maze[i][j+1] == '.') G[posi].push_back(posi+1);
                if(maze[i+1][j] == '.') G[posi].push_back(posi+w);
            }
        }
    }
    //cout<<"OK"<<endl;

    //グラフ入力確認
    // for(int i=1; i<=h*w; i++) {
    //     if(G[i].size()==0) cout<<i<<": Wall"<<endl;
    //     else {
    //         cout<<i<<": ";
    //         for(auto n : G[i]) cout<<n<<' ';
    //         cout<<endl;
    //     }
    // }
    // cout<<"OK"<<endl;

    vector<bool> seen;
    seen.assign(h*w+1, false);
    queue<int> todo;

    // cout<<"OK"<<endl;
    // for(auto next : G[1]) {
    //     //cout<<"OK"<<endl;
    //     seen[next] = true;
    //     todo.push(next);
    // }
    // cout<<"OK"<<endl;
    // int a = bfs(G, seen, todo, 0);
    // cout<<a<<endl;

    vector<int> proponent;
    for(int i=1; i<=h; i++) {
        for(int j=1; j<=w; j++) {
            if(maze[i][j]=='.') {
                int start = w*(i-1)+j;
                seen[start] = true;
                for(auto next : G[start]) {
                    //seen[next] = true;
                    todo.push(next);
                }
                int a = bfs(G, seen, todo, 0);
                proponent.push_back(a);
                seen.assign(h*w+1, false);
            }
        }
    }

    int ans = *max_element(proponent.begin(), proponent.end());

    cout<<ans<<endl;

    // for(int i=0; i<count; i++) cout<<proponent[i]<<' ';
    // cout<<endl;
    

    return 0;
}

Measured memory_bytes: 256