#include<bits/stdc++.h>
#define Open(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout);
#define inl inline
#define reg register
#define i64 long long 
using namespace std;
inl int read(){int x=0,f=0;char ch=0;while(!isdigit(ch))f|=(ch=='-'),ch=getchar();while(isdigit(ch))(x*=10)+=(ch^48),ch=getchar();return f?-x:x;}
inl void Ot(reg int x){if(x<0)x=-x,putchar('-');if(x>=10)Ot(x/10);putchar(x%10+'0');}
inl void Print(reg int x,char til='\n'){Ot(x);putchar(til);}
inl int Max(reg int x,reg int y){return x>y?x:y;}
inl int Min(reg int x,reg int y){return x<y?x:y;}
inl int Abs(reg int x){return x<0?-x:x;}
const int MAXN=22;
int n,m;
char mp[MAXN][MAXN];
bool mark[MAXN][MAXN];
int mv[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
struct Node{
	int x,y;
	int step;
};
bool check(int x,int y){
	if(mark[x][y]||mp[x][y]=='#')return 0;
	if(x<1||x>n||y<1||y>m)return 0;
	return 1;
}
int bfs(int x,int y){
	queue<Node>que;
	que.push((Node){x,y,0});
	mark[x][y]=1;
	int ans=0;
	while(!que.empty()){
		Node h=que.front();
		que.pop();
		// printf("(%d %d) %d\n",h.x,h.y,h.step);
		ans=Max(ans,h.step);
		for(reg int i=0;i<4;i++){
			int nx=h.x+mv[i][0];
			int ny=h.y+mv[i][1];
			if(check(nx,ny)){
				mark[nx][ny]=1;
				que.push((Node){nx,ny,h.step+1});
			}
		}
	}
	return ans;
}
signed main(){
	#ifndef ONLINE_JUDGE
		freopen("../../data.in","r",stdin);
	#endif
	n=read(),m=read();
	for(reg int i=1;i<=n;i++)
		for(reg int j=1;j<=m;j++)
			cin>>mp[i][j];
	int ret=0;
	// printf("%d\n",bfs(3,1));
	for(reg int i=1;i<=n;i++)
		for(reg int j=1;j<=m;j++){
			memset(mark,0,sizeof(mark));
			if(mp[i][j]=='.')
			ret=Max(ret,bfs(i,j));
		}
	Print(ret);
	return 0;
}