#include <bits/stdc++.h>
#define REP(i, n) for (int i = 0; i < (n); i++)
#define RREP(i, n) for (int i = (n); i >= 0; i--)
#define FOR(i, m, n) for (int i = (m); i < (n); i++)
#define ALL(obj) begin(obj), end(obj)
using namespace std;
using ll = long long;
using ull = unsigned long long;

const int INF = 2100100100;
const int MOD = 1e9 + 7;

// 多次元 vector 生成
template <class T> vector<T> make_vec(size_t a) { return vector<T>(a); }
template <class T, class... Ts> auto make_vec(size_t a, Ts... ts) {
    return vector<decltype(make_vec<T>(ts...))>(a, make_vec<T>(ts...));
}
template <class T> bool chmax(T &a, const T &b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <class T> bool chmin(T &a, const T &b) {
    if (b < a) {
        a = b;
        return 1;
    }
    return 0;
}
int H, W;
char maze[25][25];
int d[25][25];
int solve(int s_i, int s_j, int t_i, int t_j) {
    REP(i, H) {
        REP(j, W) { d[i][j] = INF; }
    }

    queue<pair<int, int>> q;
    q.push(make_pair(s_i, s_j));
    d[s_i][s_j] = 0;
    while (!q.empty()) {
        pair<int, int> p = q.front();
        q.pop();
        if (p.first == t_i && p.second == t_j) {
            break;
        }
        int dx[4] = {1, 0, -1, 0};
        int dy[4] = {0, 1, 0, -1};
        REP(i, 4) {
            int nx = p.first + dx[i];
            int ny = p.second + dy[i];
            if (0 <= nx && nx < H && 0 <= ny && ny < W && maze[nx][ny] != '#' && d[nx][ny] == INF) {
                q.push(make_pair(nx, ny));
                d[nx][ny] = d[p.first][p.second] + 1;
            }
        }
    }
    return d[t_i][t_j];
}
int main() {
    // cin.tie(0);
    // ios::sync_with_stdio(false);

    cin >> H >> W;
    REP(i, H) {
        REP(j, W) {
            char tmp;
            cin >> tmp;
            maze[i][j] = tmp;
        }
    }

    int ans = 0;
    REP(s_i, H) {
        REP(s_j, W) {
            REP(t_i, H) {
                REP(t_j, W) {
                    int tmp = solve(s_i, s_j, t_i, t_j);
                    if (tmp != INF) {
                        chmax(ans, tmp);
                    }
                }
            }
        }
    }

    cout << ans << endl;

    return 0;
}
