#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
const ll INF=4e18;
ll nodeno[30][30];
vector<ll> adj_list[maxn*maxn];
bool visited[30*30];
ll level[30*30];
void assign_nodeno(ll h,ll w)
{
	ll k=1;
	for(ll i=0;i<h;i++)
	{
		for(ll j=0;j<w;j++)
		{
			nodeno[i][j]=k;
			k++;
		}
	}
}
void bfs(ll s)
{
	visited[s]=true;
	queue<ll> q;
	q.push(s);
	level[s]=0;
	while(!q.empty())
	{
		ll x=q.front();
		q.pop();
		for(auto it:adj_list[x])
		{
			if(!visited[it])
			{
				level[it]=level[x]+1;
				visited[it]=true;
				q.push(it);
			}
		}
	}
}
void solve()
{
	ll h,w;
	cin>>h>>w;
	assign_nodeno(h,w);
	memset(visited,false,sizeof(visited));
	memset(visited,0,sizeof(level));
	char g[30][30]; 
	for(ll i=0;i<h;i++)
	{
		for(ll j=0;j<w;j++)
		{
			cin>>g[i][j];
		}
	}
	for(ll i=0;i<h;i++)
	{
		for(ll j=0;j<w;j++)
		{
			if(i!=0)
			{
				if(g[i-1][j]!='#')
					adj_list[nodeno[i][j]].push_back(nodeno[i-1][j]);
			}
			if(i!=h-1)
			{
				if(g[i+1][j]!='#')
					adj_list[nodeno[i][j]].push_back(nodeno[i+1][j]);
			}
			if(j!=0)
			{
				if(g[i][j-1]!='#')
					adj_list[nodeno[i][j]].push_back(nodeno[i][j-1]);
			}
			if(j!=w-1)
			{
				if(g[i][j+1]!='#')
					adj_list[nodeno[i][j]].push_back(nodeno[i][j+1]);
			}
		}
	}
	ll ans=0;
	for(ll p=0;p<h;p++)
	{
		for(ll q=0;q<w;q++)
		{	
			if(g[p][q]!='#')
			{
				bfs(nodeno[p][q]);
				for(ll j=1;j<=h*w;j++)
				{
					ans=max(ans,level[j]);
				}
				memset(level,0,sizeof(level));
				memset(visited,0,sizeof(visited));
			}
		}
	}
	cout<<ans<<"\n";
}
int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	ll T=1,p=0;
	//cin>>T;
	do
	{
		solve();
		p++;
	}while(p<T);
	return 0;
}

