#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 h,w,cost_max=0;
vector<vector<char>> s(21 , vector<char>(21));
vvi cost;
int dy[4]={1,0,-1,0} , dx[4]={0,1,0,-1};

int bfs(int y , int x){
  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();

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

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

  return cost_max;
}

int main(){
  faster();
  cin >> h >> w;
  rep(i,h)rep(j,w) cin >> s[i][j];
  int ans=0;
  rep(i,h)rep(j,w){
    cost = vvi(21 , vector<int>(21,-1));
    ans = max(ans , bfs(i,j));
  }
  cout << ans << 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;
  }
} 

