#pragma warning(disable:4996)
#pragma comment(linker, "/STACK:336777216")
#pragma GCC optimize("Ofast")

#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <functional>

using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
#define int long long int
typedef complex<long double> cd;
const long double pi=acos(-1);
typedef double db;
typedef long double ldb;
typedef pair <int, int> pii;
typedef pair <db, db> pdd;
typedef vector<int> vi;
typedef vector<vector<int> > matrix;
#define m1 make_pair
#define pb push_back
#define flush fflush(stdout)
#define IOS std::ios::sync_with_stdio(false); cin.tie(NULL);cout.tie(NULL);
#define reset(x,v) memset(x,v,sizeof(x))
#define sz(x) (int)(x.size())
#define fi first
#define se second
#define endl "\n"
#define debug(x) (cerr << #x << ": " << x << "\n")
#define setbits(x) __builtin_popcount(x)
#define all(x) x.begin(),x.end()
inline ll gcd(ll a,ll b){if(a==0) return b;return gcd(b%a,a);}
inline ll power(ll a,ll n,ll m){if(n==0)return 1;ll p=power(a,n/2,m);p=(p%m*p%m)%m;if(n%2) return (p%m*a%m)%m;else return p;}
const ll MOD =998244353;
const ll hell=1000000007;
const int INF = 1e18;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
typedef tree<int, null_type, less<int>, rb_tree_tag,
tree_order_statistics_node_update>
ordered_set;


void solve()
{
    
    int h,w;
    cin>>h>>w;
    string s[h];
    for(int i=0;i<h;i++)
        cin>>s[i];
    int ans=0;
    for(int i=0;i<h;i++)
    {
        for(int j=0;j<w;j++)
        {
            if(s[i][j]=='.')
            {
                bool visited[h][w];
                memset(visited,0,sizeof(visited));
                int d[h][w];
                memset(d,0,sizeof(d));queue<pair<int,int>>q;
                q.push(m1(i,j));
                visited[i][j]=1;
                while(!q.empty())
                {
                    pair<int,int>pr=q.front();
                    int x=pr.first,y=pr.second;
                    q.pop();
                    if(x>=1&&s[x-1][y]=='.'&&(!visited[x-1][y]))
                    {
                        d[x-1][y]=1+d[x][y];
                        q.push(m1(x-1,y));
                        visited[x-1][y]=1;
                    }
                    if(y>=1&&s[x][y-1]=='.'&&(!visited[x][y-1]))
                    {
                        d[x][y-1]=1+d[x][y];
                        q.push(m1(x,y-1));
                        visited[x][y-1]=1;
                    }
                    if(x<h-1&&s[x+1][y]=='.'&&(!visited[x+1][y]))
                    {
                        d[x+1][y]=1+d[x][y];
                        q.push(m1(x+1,y));
                        visited[x+1][y]=1;
                    }
                    if(y<w-1&&s[x][y+1]=='.'&&(!visited[x][y+1]))
                    {
                        d[x][y+1]=1+d[x][y];
                        q.push(m1(x,y+1));
                        visited[x][y+1]=1;
                    }
                    
                }
                for(int k=0;k<h;k++)
                    for(int l=0;l<w;l++)
                        ans=max(ans,d[k][l]);
            }
        }
    }
    cout<<ans<<endl;
}
int32_t main()
{
    IOS;
    int t;
    t=1;
    //cin>>t;
    while(t--)
    {
        solve();
    }
    return 0;
}


Measured memory_bytes: 256