#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace std;
using namespace __gnu_pbds;

#define ll long long

using pi = pair<int, int>;

typedef tree< pi, null_type, less<pi>, rb_tree_tag, tree_order_statistics_node_update>Order_Set;

Order_Set X;

const int mxn = 1e6+100;
const int Mod = 1e9+7;

int arr[mxn], qs[mxn];
int bitOn[55];
map<int,int>Mp, cnt, op;
vector<int>Pi, Ans;
vector<int>G[mxn];
set<int>seet[mxn];

char str[25][25];
int n, k;
int visit[25][25];
int dist[25][25];
int dx[] = {1, -1, 0, 0};
int dy[] = {0, 0, 1, -1};

int BFS(int i, int j)
{
    queue<pi>q;
    visit[i][j] = 1;
    dist[i][j] = 0;
    q.push({i, j});
    int cost = 0;
    while(!q.empty()){
            int x = q.front().first;
            int y = q.front().second;
            q.pop();
            for(int c=0 ; c<4 ; c++){
                int nx = x + dx[c];
                int ny = y + dy[c];
                if(nx < 0 or nx >= n or ny < 0 or ny >= k or str[nx][ny] == '#' ) continue;
                if(!visit[nx][ny]){
                    visit[nx][ny] = 1;
                    dist[nx][ny] = dist[x][y] + 1;
                    cost = max(dist[nx][ny], cost);
                    q.push({nx, ny});
                }
            }
    }
    return cost;
}

int main()
{
    ios::sync_with_stdio(false);

    cin>>n>>k;
    for(int i=0 ; i<n ; i++){
        for(int j=0 ; j<k ; j++){
            char ch;
            cin>>ch;
            str[i][j] = ch;
        }
    }

    int Ans = 0;
    for(int i=0 ; i<n ; i++){
        for(int j=0 ; j<k ; j++){
            memset(visit, 0, sizeof visit);
            int co;
            if(str[i][j] == '.') co = BFS(i, j);
            Ans = max(Ans, co);
        }
    }

    cout<<Ans<<endl;

    return 0;
}
