#include <iostream>
#include <vector>
#include <queue>
#include <utility>

using namespace std;

vector<vector<char>> field;
vector<vector<int>> d;
vector<vector<int>> used;
int n, m, asd = 1;
struct st { int x, y, px, py; };

bool can(int i, int j)
{
    return i >= 0 && j >= 0 && i < n && j < m && field[i][j] == '.' && used[i][j] != asd;
}

int BFS(pair<int, int> u, pair<int, int> v)
{
    queue<st> s;
    s.push({u.first, u.second, -1, -1});
    d[u.first][u.second] = 0;
    d[v.first][v.second] = -1;
    while (!s.empty())
    {
        auto cur = s.front();
        used[cur.x][cur.y] = asd;
        s.pop();
        if (cur.px != -1) d[cur.x][cur.y] = d[cur.px][cur.py] + 1;
        if (can(cur.x - 1, cur.y)) s.push({cur.x - 1, cur.y, cur.x, cur.y});
        if (can(cur.x + 1, cur.y)) s.push({cur.x + 1, cur.y, cur.x, cur.y});
        if (can(cur.x, cur.y - 1)) s.push({cur.x, cur.y - 1, cur.x, cur.y});
        if (can(cur.x, cur.y + 1)) s.push({cur.x, cur.y + 1, cur.x, cur.y});
    }
    return d[v.first][v.second];
}

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

    int ans = 0;
    cin >> n >> m;

    field.resize(n, vector<char>(m));
    d.resize(n, vector<int>(m));
    used.resize(n, vector<int>(m, 0));
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            cin >> field[i][j];

    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            for (int k = 0; k < n; k++)
                for (int l = 0; l < m; l++)
                {
                    if (i == k && j == l) continue;
                    if (field[i][j] == '#' || field[k][l] == '#') continue;
                    int cur = BFS({i, j}, {k, l});
                    ans = max(ans, cur);
                    asd++;
                }

    cout << ans << "\n";

    return 0;
}
