#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll MAX=1e12;
ll mod=1e9+7;
#define pb push_back
#define se second
#define fi first
#define maxe max_element
#define mine min_element
#define debug(x) cout<<#x<<" :: "<<x<<endl;
#define debug2(x,y) cout<<#x<<" :: "<<x<<"\t"<<#y<<" :: "<<y<<endl;
#define debug3(x,y,z) cout<<#x<<" :: "<<x<<"\t"<<#y<<" :: "<<y<<"\t"<<#z<<" :: "<<z<<endl;
#define debug4(x,y,z,w) cout<<#x<<" :: "<<x<<"\t"<<#y<<" :: "<<y<<"\t"<<#z<<" :: "<<z<<"\t"<<#w<<" :: "<<w<<endl;
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define boost  ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
vector<int> graph[205];
int color[205];
int nCk[100][100];
bool bipartite_jugding(int v, int c){
    color[v] = c;
    for(int i = 0; i < graph[v].size(); ++i){
        if(color[graph[v][i]] == c) return false;
        if(color[graph[v][i]] == 0 && !bipartite_jugding(graph[v][i], -c)){
            return false;
        }
    }
    return true;
}

 void combi() {
	for (int i = 0; i <= 99; ++i) nCk[i][0] = 1;
	for (int i = 1; i <= 99; ++i) for (int j = 1; j <= i; ++j) {
		nCk[i][j] = (nCk[i-1][j] + nCk[i-1][j-1]) % mod;
	}
}

long long expo(ll x,ll n,ll M)
{
    if(n==0)
        return 1;
    else if(n%2 == 0)        //n is even
        return expo((x*x)%M,n/2,M);
    else                             //n is odd
        return (x*expo((x*x)%M,(n-1)/2,M))%M;

}
int h,w;
 vector<vector<char> > mat(20,vector<char> (20));
int X[]={0,1,0,-1};
int Y[]={-1,0,1,0};
bool valid(int x,int y){
    if(x>=0 && x<h && y>=0 && y<w && mat[x][y]!='#')return true;
    return false;}

int moves(int x1,int y1,int x2,int y2)
{
    vector<vector<int> > visi(h,vector<int> (w,0));
    queue<pair<int,int> > q;
    q.push({x1,y1});int level=1;int ans=0;
    while(q.size())
    {
    x1=q.front().fi;y1=q.front().se;level--;q.pop();
    if(x1==x2 && y1== y2)return ans;
    visi[x1][y1]=1;
    for(int i=0;i<4;i++)
    {
            if(valid(x1+X[i],y1+Y[i]) && !visi[x1+X[i]][y1+Y[i]])
            q.push({x1+X[i],y1+Y[i]});

    }
    if(level==0)
    {
        ans++;
        level=q.size();
    }
    }
    return -1;
}

void solve(){
    boost;
  cin>>h>>w;
  for(int i=0;i<h;i++)
      for(int j=0;j<w;j++)
        cin>>mat[i][j];
    int ans=0;
    for(int i=0;i<h;i++)
        for(int j=0;j<w;j++)
             for(int i1=i;i1<h;i1++)
    for(int j1=j;j1<w;j1++){ int k=-1;
    if(mat[i][j]=='.' && mat[i1][j1]=='.')
        k=moves(i,j,i1,j1);
        if(k!=-1)ans=max(ans,k);}
  cout<<ans<<endl;
}

int main(){
    boost;
  solve();
}
