#include<bits/stdc++.h>
#define mod 1000000007
#define lim 1000000000000000007
#define lim1 18446744073709551615  //Unsigned
#define sq(a) ((a)*(a))
#define all(v) v.begin(),v.end()
#define rall(v) v.rbegin(),v.rend()
#define mms(v,i) memset(v,i,sizeof(v))
#define pb push_back
#define pf push_front
#define ppb pop_back
#define ppf pop_front
#define REP(i,a,b) for (int i = a; i <= b; i++)
#define REPN(i,a,b) for (int i = a; i >= b; i--)
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
typedef pair<int,int> pi;
typedef pair<ll,ll> PL;
typedef pair<ll,int> PLI;
typedef pair<int,ll> PIL;
typedef pair<int,pair<int,int> > pii;
typedef pair<double,double> pdd;
ll power(ll a,ll b) {
    if (b==0) return 1;
    ll c = power(a,b>>1);
    c = (c*c)%mod;
    if (b&1) return (c*a)%mod;
    return c;
}
ll gcdll(ll a,ll b) {
    if (b==0) return a;
    return gcdll(b,a%b);
}
int gcd(int a,int b) {
    if (b==0) return a;
    return gcd(b,a%b);
}

struct custom_hash {
    static uint64_t splitmix64(uint64_t x) {
        // http://xorshift.di.unimi.it/splitmix64.c
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }

    size_t operator()(uint64_t x) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(x + FIXED_RANDOM);
    }
};

const int N = (int)1e5+5;
const int Q = 301;

vector<string> grid;
queue<pi> q;
int h, w;
int dx[] = {-1, 1, 0, 0};
int dy[] = {0, 0, -1, 1};
bool valid(vector<vector<int> >& dist, int x, int y) {
    if (x<0 || x==h || y<0 || y==w || dist[x][y]!=(-1) || grid[x][y]=='#') {
        return false;
    }
    return true;
}
int sol(vector<vector<int> > dist, int a, int b, int c, int d) {
    while (!q.empty()) {
        q.pop();
    }
    dist[a][b] = 0;
    q.push({a,b});
    pi temp;
    while (!q.empty()) {
        temp = q.front();
        q.pop();
        if (temp.first==c && temp.second==d) {
            return dist[temp.first][temp.second];
        }
        REP(k,0,3) {
            if (valid(dist, temp.first + dx[k], temp.second + dy[k])) {
                dist[temp.first + dx[k]][temp.second + dy[k]] = 1 + dist[temp.first][temp.second];
                q.push({temp.first + dx[k], temp.second + dy[k]});
            }
        }
    }
    return -1;
}
void solve() {
    //int h,w;
    cin>>h>>w;
    grid.resize(h);
    REP(i,0,h-1) {
        cin>>grid[i];
    }
    vector<vector<int> > dist(h, vector<int>(w, -1));
    int ans = 0;
    REP(i,0,h-1) {
        REP(j,0,w-1) {
            if (grid[i][j]=='.') {
                REP(r,0,h-1) {
                    REP(c,0,w-1) {
                        if (grid[r][c]=='.') {
                            ans = max(ans, sol(dist, i, j, r, c));
                        }
                    }
                }
            }
        }
    }
    cout<<ans;
}
int main() {
    //freopen("output.txt","r",stdin);
    //freopen("output.txt","w",stdout);

    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int T=1;
    //cin>>T;
    REP(TC,1,T) {
        //cout<<"Case #"<<TC<<": ";
        solve();
        cout<<"\n";
    }
}


Measured memory_bytes: 256