#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;
typedef long long ll;
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;
ll dx[]={0,1,0,-1};
ll dy[]={1,0,-1,0};
ll n,m;
string *s;
bool chk(ll x,ll y,ll n,ll m)
{
    return (x<n && x>=0 && y<m && y>=0);
}
ll solve(ll x1,ll y1, ll x2,ll y2)
{
    ll dp[n][m];
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
        dp[i][j]=1e8;
    dp[x1][y1]=0;
    queue<pair<ll,ll> >q;
    q.push(make_pair(x1,y1));
    while(!q.empty())
    {
        pair<ll,ll> p=q.front();
        ll x=p.first;ll y=p.second;
        q.pop();
        for(int i=0;i<4;i++)
        {
            ll xx=x+dx[i];
            ll yy=y+dy[i];

            if(chk(xx,yy,n,m) && s[xx][yy]=='.')
            {

                if(dp[xx][yy] > dp[x][y]+1)
                {
                    dp[xx][yy]=dp[x][y]+1;
                    q.push(make_pair(xx,yy));
                }
            }
        }
    }

    return dp[x2][y2];
}
int main()
{
  cin>>n>>m;
  s=new string[n];
  for(int i=0;i<n;i++)
    cin>>s[i];
    ll ans=0;
  for(int x1=0;x1<n;x1++)
  {
      for(int y1=0;y1<m;y1++)
      {
          for(int x2=x1;x2<n;x2++)
          {
              for(int y2=y1;y2<m;y2++)
              {
                  if(s[x1][y1]=='.' && s[x2][y2]=='.'){
                    ans=max(ans,solve(x1,y1,x2,y2));
                  }
              }
          }
      }
  }
  cout<<ans;
}
