#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <queue>
#include <bitset>
#include <random>
#include <chrono>
#include <complex>
#include <algorithm>
#include <utility>
#include <functional>
#include <cmath>
#include <cstring>
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <iomanip> 
#include <string>

using namespace std;

#define sqr(x) ((x)*(x))
#define mp make_pair
#define pb push_back
#define FOR(i,a,b) for (int i = (a); i <= (b); i++)
#define RE(i, n) FOR(i,1,n)
#define REP(i,n) FOR(i, 0, (int)(n)-1)
#define fst first
#define snd second

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, int> pli;
typedef pair<ll, ll> pll;
typedef long double ld;
typedef tuple<int,int,int> iii;

string to_string(string s) {
    return '"' + s + '"';
}
    
string to_string(const char* s) {
    return to_string((string) s);
}
    
string to_string(bool b) {
    return (b ? "true" : "false");
}
    
template <typename A, typename B>
string to_string(pair<A, B> p) {
    return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}
    
template <typename A>
string to_string(A v) {
    bool first = true;
    string res = "{";
    for (const auto &x : v) {
        if (!first) {
            res += ", ";
        }
        first = false;
        res += to_string(x);
    }
    res += "}";
    return res;
}

void debug_out() { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
    cerr << " " << to_string(H);
    debug_out(T...);
}

void fastIO() {
    cin.sync_with_stdio(false);
    cin.tie(0);
}


int XMOV[4] = {0, 0, 1, -1};
int YMOV[4] = {1, -1, 0, 0};

//#############################
const int MAXN = 1000005;

bool visited[25][25];
int h, w;
char grid[25][25];

bool check(int r, int c) {
    return r >= 0 && r < h && c >= 0 && c < w;
}

int dfs(pii s) {
    int ans = 0;
    int r, c;
    r = s.fst, c = s.snd;
    visited[r][c] = 1;
    queue<pair<int, pii>> q;
    q.push(pair<int,pii>(0, pii(r,c)));
    while(!q.empty()) {
        int stp = q.front().fst;
        ans = max(ans, stp);
        r = q.front().snd.fst;
        c = q.front().snd.snd;
        // cout << r << " " << c << " " << stp << endl;
        q.pop();
        for(int i = 0; i < 4; i++) {
            int newr, newc;
            newr = r + XMOV[i];
            newc = c + YMOV[i];
            if (check(newr, newc) && !visited[newr][newc] && grid[newr][newc] == '.'){
                visited[newr][newc] = 1;
                // cout << "pushing: " << newr << " " << newc << " " << stp+1 << endl;
                q.push(pair<int, pii>(stp+1, pii(newr, newc)));
            }
        }
    }
    return ans;
}

int main() {
    char x;
    cin >> h >> w;
    vector<pii> st;
    cin.ignore();
    for (int r = 0; r < h; r++){
        for (int c = 0; c < w; c++){
            x = getchar();
            grid[r][c]= x;
            if (x == '.')
                st.pb(pii(r,c));
        }
        getchar();
    }
    // cout << to_string(st) << endl;
    int ans = -1;
    for (int i = 0; i < st.size(); i++) {
        memset(visited, 0, sizeof(visited));
        ans = max(ans,dfs(st[i]));
    }
    
    cout << ans;

    return 0;
}

Measured memory_bytes: 256