import std.stdio, std.array, std.string, std.conv, std.algorithm;
import std.typecons, std.range, std.random, std.math, std.container;
import std.numeric, std.bigint, core.bitop, core.stdc.stdio;

void main() {
    auto s = readln.split.map!(to!int);
    auto H = s[0];
    auto W = s[1];
    auto A = H.iota.map!(_ => readln.chomp).array;

    immutable int INF = 1 << 29;
    immutable int[] dr = [0, 0, -1, 1];
    immutable int[] dc = [-1, 1, 0, 0];

    DList!(int[]) que;
    auto dist = new int[][](H, W);

    int f(int sr, int sc) {
        que.clear;
        foreach (i; 0..H) dist[i][] = INF;
        que.insertBack([sr, sc, 0]);

        while (!que.empty) {
            auto t = que.front;
            que.removeFront;
            auto r = t[0];
            auto c = t[1];
            auto d = t[2];
            if (dist[r][c] != INF) continue;
            dist[r][c] = d;
            foreach (i; 0..4) {
                auto nr = r + dr[i];
                auto nc = c + dc[i];
                if (nr < 0 || nr >= H || nc < 0 || nc >= W || A[nr][nc] == '#') continue;
                if (dist[nr][nc] == INF) que.insertBack([nr, nc, d+1]);
            }
        }

        int ans = -1;
        foreach (i; 0..H) foreach (j; 0..W) if (dist[i][j] != INF) ans = max(ans, dist[i][j]);
        return ans;
    }

    int ans = -1;
    foreach (i; 0..H) foreach (j; 0..W) if (A[i][j] != '#') ans = max(ans, f(i, j));
    ans.writeln;
}