#include <bits/stdc++.h>
#define WHOLE(v) (v).begin(), (v).end()
#define REV_WHOLE(v) (v).rbegin(), (v).rend()
using i64 = int64_t;
using namespace std;
template<class F>auto recursive(F f){return[f](auto...a){return f(f,a...);};}
template<class I,class V=typename I::value_type>V sum_up(const I&l,const I&r){V v;for(I i=l;i!=r;i++)v=i==l?*i:v+*i;return v;}
template<class I,class T=iterator_traits<I>>I operator+(I it,int n){for(int i=0;i<n;i++)it++;return it;}
template<class I,class T=iterator_traits<I>>I operator-(I it,int n){for(int i=0;i<n;i++)it--;return it;}
template<class T>using rev_priority_queue=priority_queue<T,vector<T>,greater<T>>;
template<class T>using vector2d=vector<vector<T>>;
struct fixprec{int x;fixprec(int d):x(d){}};
ostream&operator<<(ostream&o,fixprec f){return o<<fixed<<setprecision(f.x);}
void R_YESNO(bool p) { cout << (p ? "YES" : "NO") << endl; }
void R_YesNo(bool p) { cout << (p ? "Yes" : "No") << endl; }
/*!* [warshall_floyd] *!*/
/*+* ワーシャルフロイド法,全ての二点間距離をO(V^3)で求める *+*/
template <typename T>
void WarshallFloyd(vector<vector<T>> &link) {
    int N = link.size();
    for (int k = 0; k < N; k++)
        for (int i = 0; i < N; i++)
            for (int j = 0; j < N; j++)
                link[i][j] = min(link[i][j], link[i][k] + link[k][j]);
}
int D[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
int main() {
    int H, W;
    cin >> H >> W;
    vector2d<bool> S(H, vector<bool>(W));
    for(int i = 0; i < H; i++) {
        string s;
        cin >> s;
        for(int j = 0; j < W; j++) {
            S[i][j] = s[j] == '.' ? 1 : 0;
        }
    }
    const int INF = 1e8;
    vector2d<int> v(H * W, vector<int>(H * W, INF));
    for(int i = 0; i < H; i++) {
        for(int j = 0; j < W; j++) {
            for(int d = 0; d < 4; d++) {
                int ni = i + D[d][0], nj = j + D[d][1];
                if(0 <= ni && ni < H && 0 <= nj && nj <= W && S[i][j] && S[ni][nj]) {
                    v[ni * H + nj][i * H + j] = 1;
                    v[i * H + j][ni * H + nj] = 1;
                }
            }
        }
    }
    int ans = 0;
    WarshallFloyd(v);
    for(int i = 0; i < H; i++) {
        for(int j = 0; j < W; j++) {
            for(int ni = 0; ni < H; ni++) {
                for(int nj = 0; nj < W; nj++) {
                    if(S[ni][nj] && S[i][j]) {
                        ans = max(ans, v[ni * H + nj][i * H + j]);
                    }
                }
            }
        }
    }
    cout << ans << endl;
    return 0;
}

