#include"bits/stdc++.h"
#include<boost/multi_array.hpp>
#include<boost/optional.hpp>
#include<boost/range/irange.hpp>
#include<boost/range/algorithm.hpp>
#include<boost/range/adaptors.hpp>
using namespace std;
namespace adaptor = boost::adaptors;

#define rep(i,n) for(int (i)=0;(i)<(n);(i)++)
#define rep3(i,m,n) for(int (i)=m;(i)<=(n);(i)++)
#define rep3rev(i,m,n) for(int (i)=m;(i)>=(n);(i)--)
#define MP make_pair
typedef long long ll;
typedef vector<vector<int>> vvi;
typedef pair<int,int> pii;

int max_vvi(vvi v){
  int mx=0;
  int h = v.size();
  int w = v[0].size();
  rep(i,h){
    rep(j,w){
      mx = max(mx, v[i][j]);
    }
  }
  return mx;
}

void Main()
{
  	int h, w;
	cin >> h >> w;
    vvi data(h,vector<int>(w,1));
    string s;
    int count = 0;
    rep(i,h) {
      	cin >> s;
        rep(j,w){
          if(s[j]=='.'){
            data[i][j]=0;
            count++;
            }
        }
    }
  
    /*
    rep(i,h){
        rep(j,w){
             cout << data[i][j] << " ";
        }
      cout << endl;
    }
    */
    
    vvi seen(h,vector<int>(w));
    vvi dist(h,vector<int>(w));
    vvi zero(h,vector<int>(w,0));
    queue<pii> q;
    int tempi,tempj,mx;
    int ans = 0;
    	 
    auto inrange = [&](int x, int y){
      return (x>=0 && x<h && y>=0 && y<w && seen[x][y] == 0);
    };
  
    rep(i,h){
        rep(j,w){
            // bfs(i,j,data,dist);
            if(data[i][j]==0){
                seen = data;
                dist = zero;
                seen[i][j]=1;
                q.push(MP(i,j));
                while(!q.empty()){
                    tempi = q.front().first;
                    tempj = q.front().second;
                    q.pop();
                    if(inrange(tempi-1,tempj)) {
                        q.push(MP(tempi-1,tempj));
                        seen[tempi-1][tempj]=1;
                        dist[tempi-1][tempj]=dist[tempi][tempj]+1;
                    }
                    if(inrange(tempi+1,tempj)) {
                        q.push(MP(tempi+1,tempj));
                        seen[tempi+1][tempj]=1;
                        dist[tempi+1][tempj]=dist[tempi][tempj]+1;
                    }
                    if(inrange(tempi,tempj-1)) {
                        q.push(MP(tempi,tempj-1));
                        seen[tempi][tempj-1]=1;
                        dist[tempi][tempj-1]=dist[tempi][tempj]+1;
                    }
                    if(inrange(tempi,tempj+1)) {
                        q.push(MP(tempi,tempj+1));
                        seen[tempi][tempj+1]=1;
                        dist[tempi][tempj+1]=dist[tempi][tempj]+1;
                    }
                }
            mx = max_vvi(dist);
            // cout << i << "," << j << ": " << mx << endl;
            ans = max(ans,mx);
            }
        }
    }
    /*
    rep(i,h){
      rep(j,w){
  	     cout << dist[i][j] << ", ";
      }
      cout << endl;
    }
    */
    /*
    rep(i,h){
        rep(j,w){
            cout << seen[i][j] << dist[i][j] << " ";
        }
        cout << endl;
    }
    */
    cout << ans << endl;
	return;
}

int main()
{
	cin.tie(nullptr);
	ios_base::sync_with_stdio(false);
	cout << fixed << setprecision(15);
	Main();
	return 0;
}

Measured memory_bytes: 256