//aea ctmr
#pragma GCC optimize("unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <bits/stdc++.h>
//v.erase(unique(v.begin(),v.end()),v.end());
#define f(i,a,b) for( ll i = a; i < b ; i++ ) 
#define af(i,a,b) for( ll i = a; i >= b ; i--)
#define rep(i,a,b,k) for(ll i = a; i < b ; i+= k )
#define arep(i,a,b,k) for( ll i = a; i >= b ; i-= k)
#define ff first
#define ss second
#define pb push_back
#define mp make_pair
#define sor(a) sort( a.begin(), a.end() )
#define fastio ios_base::sync_with_stdio(false);cin.tie(NULL)
#define PI 3.14159265358979323846
 
typedef long double ld;
typedef long long ll;
const ll N = 100500;
const ll mod = 1e9 + 7;
using namespace std;
 
#define TRACE
#ifdef TRACE
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1) {
  cerr << name << " : " << arg1 << endl;}
 
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args) {
  const char* comma = strchr(names + 1, ',');
  cerr.write(names, comma - names) << " : " << arg1<<" | ";
  __f(comma+1, args...);}
#else
#define trace(...)
#endif

int alt[250][250];
int vis[250][250];
char grid[250][250];
int n, m;

void bfs(pair <int, int> u){
    queue <pair<int, int>> q;
    vis[u.ff][u.ss] = true;
    q.push(u);

    while(!q.empty()){
        pair <int, int> v = q.front();
        q.pop();
        //trace(v.ff, v.ss);
        //cout << q.size() << endl;

        if(v.ff >= 1 and !vis[v.ff - 1][v.ss] and grid[v.ff - 1][v.ss] == '.'){
            vis[v.ff - 1][v.ss] = true;
            q.push({v.ff - 1, v.ss});
            alt[v.ff - 1][v.ss] = alt[v.ff][v.ss] + 1;
        } 
        if(v.ff <= n - 2 and !vis[v.ff + 1][v.ss] and grid[v.ff + 1][v.ss] == '.'){
            vis[v.ff + 1][v.ss] = true;
            q.push({v.ff + 1, v.ss});
            alt[v.ff + 1][v.ss] = alt[v.ff][v.ss] + 1;
        } 
        if(v.ss >= 1 and !vis[v.ff][v.ss - 1] and grid[v.ff][v.ss - 1] == '.'){
            vis[v.ff][v.ss - 1] = true;
            q.push({v.ff, v.ss - 1});
            alt[v.ff][v.ss - 1] = alt[v.ff][v.ss] + 1;
        } 
        if(v.ss <= m - 2 and !vis[v.ff][v.ss + 1] and grid[v.ff][v.ss + 1] == '.'){
            vis[v.ff][v.ss + 1] = true;
            q.push({v.ff, v.ss + 1});
            alt[v.ff][v.ss + 1] = alt[v.ff][v.ss] + 1;
        } 
    }
} 

int main(){
    fastio;
    cin >> n >> m;
    pair <int, int> p; 
    for(int i = 0; i < n; i++){
        string s;
        cin >> s;

        for(int j = 0; j < m; j++){
            grid[i][j] = s[j];
            if(s[j] == '.') p = {i, j};
        }
    }


    //se limpia
    int maxi = 0;
    

    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            if(grid[i][j] == '.'){
                //limpia
                for(int i = 0; i < 250; i++){
                    for(int j = 0; j < 250; j++){
                        alt[i][j] = 0;
                        vis[i][j] = false;
                    }
                }
                bfs({i, j});
                for(int i = 0; i < n; i++){
                    for(int j = 0; j < m; j++){
                        maxi = max(maxi, alt[i][j]);
                        //trace(i, j, alt[i][j]);
                    }
                }

            }
        }
    }

    cout << maxi << endl;

    return 0;
}


Measured memory_bytes: 768