#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 watch(x) cout<<(#x)<<"="<<(x)<<'\n'
#define mset(d,val) memset(d,val,sizeof(d))
#define setp(x) cout<<fixed<<setprecision(x)
#define forn(i,a,b) for(int i=a;i<b;i++)
#define fore(i,a,b) for(int i=a;i<=b;i++)
#define pb push_back
#define F first
#define S second
#define INF int(1e9)
#define MOD 998244353
#define pqueue priority_queue
#define fbo find_by_order
#define ook order_of_key
typedef long long ll;
typedef pair<int,int> ii;
typedef vector<ll> vi;
typedef vector<ii> vii;
typedef long double ld;
typedef tree<ll, null_type, less<ll>, rb_tree_tag, tree_order_statistics_node_update> pbds;

#define MAXN 100005

int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};

int n,m;

bool oob(int x,int y){
	return x<0 || x>=n || y<0 || y>=m;
}

int main()
{
	ios_base::sync_with_stdio(0); cin.tie(0);
	
	cin>>n>>m;
	string a[n];
	forn(i,0,n) cin>>a[i];
	
	int ans=0;
	forn(s1,0,n){forn(s2,0,m){
		if(a[s1][s2]=='#') continue;
		forn(t1,0,n){forn(t2,0,m){
			if(a[t1][t2]=='#') continue;
			
			bool found=0;
			queue<pair<ii,int> > q;
			q.push({{s1,s2},0});
			
			while(!q.empty())
			{
				if(found) break;				
				int x=q.front().F.F, y=q.front().F.S;
				int dist=q.front().S;
				q.pop();
				
				if(oob(x,y)) continue;
				if(a[x][y]=='#') continue;
				
				if(x==t1 && y==t2){
					ans=max(ans,dist);
					found=1;
					break;
				}
				
				forn(i,0,4){
					q.push({{x+dx[i],y+dy[i]},dist+1});
				}
			}
		}}
	}}
	
	cout<<ans<<'\n';
	
	return 0;
}
