#include<bits/stdc++.h>
using namespace std;

#define rep(i,n) for(int i=0; i<n ; ++i)
#define REP(i,a,b) for(int i=a; i<b; ++i)
using ll = long long;
using vi = vector<int>;
using vl = vector<ll>;
using vvi = vector<vector<int>>;
using vvl = vector<vector<ll>>;

//プロトタイプ宣言
void faster(void);
template <class T>
T gcd(T , T);
template <class T>
T get_digent(T);
template <class T>
T POW(T , T);

int maximum=0;
int h,w;
vector<vector<char>> s;
vvi cost;

int bfs(int x, int y){
  int dx[] = {0,1,0,-1} , dy[] = {1,0,-1,0};

  queue<pair<int,int>> que;
  que.push(make_pair(y,x));
  cost[y][x]=0;

  while(!que.empty()){
    pair<int,int> p = que.front();
    que.pop();
    for(int i=0;i<4;i++){
      int ny = p.first + dy[i] , nx = p.second + dx[i];
      if(nx<0 || ny<0 || nx>=w || ny>=h) continue;
      if(s[ny][nx]=='#') continue;
      if(cost[ny][nx]!=-1) continue;
      cost[ny][nx] = cost[p.first][p.second] + 1;
      que.push(make_pair(ny,nx));
    }
  }

  rep(i,w)rep(j,h){
    int temp = cost[j][i];
    maximum = max(maximum,temp);
  }

  return maximum;
}

int main(){
  faster();
  cin >> h >> w;
  s = vector<vector<char>>(h,vector<char>(w));
  rep(i,w)rep(j,h){
    cin >> s[j][i];
  }
  cost = vector<vector<int>>(h,vector<int>(w,-1));
  int cost_max = 0;
  rep(i,w)rep(j,h){
    int temp2 = bfs(i,j);
    cost_max = max(cost_max,temp2);
  }
  cout << cost_max << endl;
}



























//同期解除
void faster(void){
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
}

//ユークリッドの互除法
template <class T>
T gcd(T a, T b) {
  return (b ? gcd(b, a%b) : a);
} 

//桁数取得
template <class T>
T get_digent(auto x){
  string s;
  s = to_string(x);
  ll digent = s.size();
  return digent;
} 

//べき乗計算
template <class T>
T POW(T x, T y){
  if(y==0) return 1;
  if(y%2 == 1){
    ll temp = POW(x,y-1);
    return (temp*x);
  }
  else{
    ll temp = POW(x,y/2);
    return temp*temp;
  }
} 

