/**akshaykumar99**/
 
#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>

using namespace std;
using namespace __gnu_pbds;
 
template<typename T> using id_set = tree<T,null_type,less<T>,rb_tree_tag,tree_order_statistics_node_update> ;
template<typename T> using id_setp = tree<pair<T,T>,null_type,less<pair<T,T>>,rb_tree_tag,tree_order_statistics_node_update> ;

#define f(i,x,n) for(i=x;i<n;i++)
#define fr(i,x,n) for(i=x;i>=n;i--)
#define pu push_back           
#define pp pop_back
#define F first
#define S second
#define all(v) v.begin(),v.end()
#define rall(v) v.rbegin(),v.rend()
#define SP(x) fixed<<setprecision(x)
#define IOS() ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
 
const long long MOD=1e9+7;
const long double PI = acos(-1);
const long long INF=INT_MAX;
const long long LINF=LLONG_MAX;
const long long N=1e6+1;
 
typedef long long ll;
typedef long double ld;
 
vector<ll> v[N];

int main()
{
   IOS();
   #ifndef ONLINE_JUDGE
      freopen("input.txt", "r", stdin);
      freopen("output.txt","w",stdout);
   #endif
   ll n,m,i,j,h,w;
   cin>>h>>w;
   char a[h+3][w+3];
   ll arr[h+3][w+3];
   f(i,0,w+3)
   {
      a[0][i]='#';
      a[h+1][i]='#';
   }
   f(i,0,h+3)
   {
      a[i][0]='#';
      a[i][w+1]='#';
   }
   ll zz=1;
   f(i,1,h+1)
   {
      f(j,1,w+1)
      {
         cin>>a[i][j];
         if(a[i][j]=='.')
         {
            arr[i][j]=zz;
            zz++;
         }
         else
            arr[i][j]=0;
      }
   }
   f(i,1,h+1)
   {
      f(j,1,w+1)
      {
         if(a[i][j]=='.')
         {
            if(a[i][j+1]=='.')
            {
               v[arr[i][j]].pu(arr[i][j+1]);
               v[arr[i][j+1]].pu(arr[i][j]);
            }
            if(a[i][j-1]=='.')
            {
               v[arr[i][j-1]].pu(arr[i][j]);
               v[arr[i][j]].pu(arr[i][j-1]);
            }
            if(a[i+1][j]=='.')
            {
               v[arr[i+1][j]].pu(arr[i][j]);
               v[arr[i][j]].pu(arr[i+1][j]);
            }
            if(a[i-1][j]=='.')
            {
               v[arr[i-1][j]].pu(arr[i][j]);
               v[arr[i][j]].pu(arr[i-1][j]);
            }
         }
      }
   }
   n=zz+2;
   ll adj[n+1][n+1]={0};
   f(i,0,n+1)
   {
      f(j,0,v[i].size())
      {
         adj[i][v[i][j]]=1;
         adj[v[i][j]][i]=1;

      }
   }  
   ll distance[n+1][n+1]={0};
   for(ll i = 1; i <= n; i++) 
   {
      for(ll j = 1; j <= n; j++) 
      {
         if(i == j) 
            distance[i][j] = 0;
         else if (adj[i][j]) 
            distance[i][j] = adj[i][j];
         else distance[i][j] = INF;
      }
   }
   for (ll k = 1; k <= n; k++) 
   {
      for (ll i = 1; i <= n; i++) 
      {
         for (ll j = 1; j <= n; j++) 
         {
            distance[i][j] = min(distance[i][j],distance[i][k]+distance[k][j]);
         }
      }
   }
   ll ans=0;
   f(i,1,n+1)
   {
      f(j,1,n+1)
      {
         if(distance[i][j]!=INF)
         {
            ans=max(ans,distance[i][j]);
         }
      }
   }
   cout<<ans<<'\n';
   return 0;
}