#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 int
#define pb push_back
#define mp make_pair
#define ff first
#define ss second
#define all(a) a.begin(),a.end()
ll n, m;
map<pair<ll, ll>, ll> node;
vector<ll> v[500000];
bool valid(ll x, ll y) {
	if(x < n && x >=0 && y < m && y >= 0) {
		return true;
	}
	return false;
}
ll dist[500000], b[500000];
queue<ll> q;
ll bfs1() {
	ll ret = 0, x;
	while(!q.empty()) {
		ll temp = q.front();
		q.pop();
		for(auto u: v[temp]) {
			if(!b[u]) {
				b[u] = 1;
				q.push(u);
				dist[u] = dist[temp] + 1;
				if(ret < dist[u]) {
					ret = dist[u];
					x = u;
				}
			}
		}
	}
	return x;
}
ll bfs2() {
	ll ans = 0;
	while(!q.empty()) {
		ll temp = q.front();
		q.pop();
		for(auto u: v[temp]) {
			if(!b[u]) {
				dist[u] = dist[temp] + 1;
				b[u] = 1;
				ans = max(ans, dist[u]);
				q.push(u);
			}
		}
	}
	return ans;
}
int main(void)
{
	ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    ll i, j, k, x, y, num = 0, ans = 0, l;
    cin>>n>>m;;
    string s[n];
    for(i=0; i<n; i++) {
    	cin>>s[i];
    	for(j=0; j<m; j++) {
    		if(s[i][j] == '.') {
    			node[mp(i, j)] = num++;
    		}
    	}
    }
    for(i=0; i<n; i++) {
    	for(j=0; j<m; j++) {
    		if(s[i][j] == '#') {
    			continue;
    		}
    		for(l = 1; l>=0; l--) {
    			for(k=0; k<=1; k++) {
    				if(abs(l) == abs(k)) {
    					continue;
    				}
    				if(!valid(i + l, j + k)) {
    					continue;
    				}
    				x = i + l;
    				y = j + k;
    				if(s[x][y] == '#') {
    					continue;
    				}
    				v[node[mp(i, j)]].pb(node[mp(x, y)]);
    				v[node[mp(x, y)]].pb(node[mp(i, j)]);
    			}
    		}
    	}
    }
    b[0] = 1;
    q.push(0);
    x = bfs1();
    for(i=0; i<num; i++) {
    	b[i] = 0;
    	dist[i] = 0;
    }
    q.push(x);
    cout<<bfs2()<<"\n";
}