/*
lakshaygpt28
Lakshay Gupta
*/

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;

using ll = long long;
using db = double;
using pii = pair < int, int >;
using pll = pair < ll, ll >;
using vll = vector < ll >;

template < typename T > using OrderedMultiSet = tree < T, null_type, less_equal < T >, rb_tree_tag, tree_order_statistics_node_update >;
template < typename T > using OrderedSet = tree < T, null_type, less < T >, rb_tree_tag, tree_order_statistics_node_update >;
template < typename T > using MinPriorityQueue = priority_queue < T, vector < T >, greater < T > >;


#ifndef ONLINE_JUDGE
#define debug(...) __f(#__VA_ARGS__, __VA_ARGS__)
template < typename Arg1 >
void __f(const char* name, Arg1&& arg1) {
    cerr << name << " : " << arg1 << std :: endl;
}
template < typename Arg1, typename... Args >
void __f(const char* names, Arg1&& arg1, Args&&... args) {
    const char* comma = strchr(names + 1, ',');
    cerr.write(names, comma - names) << " : " << arg1 << " | ";
    __f(comma + 1, args...);
}
#else
#define debug(...)
#endif

#define fast_io() ios_base :: sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define eb emplace_back
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()

const db PI = acos(-1);
const ll LINF = LLONG_MAX;
const int INF = INT_MAX, MOD = 1e9 + 7, N = 22;

char s[N][N];
ll dp[N][N];
bool vis[N][N];
int h, w;
void bfs(int i, int j);

int main() {
    fast_io();
    cin >> h >> w;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            s[i][j] = '#';
        }
    }
    for (int i = 1; i <= h; i++) {
        for (int j = 1; j <= w; j++) {
            cin >> s[i][j];
        }
    }
    ll rst = 0;
    for (int i = 1; i <= h; i++) {
        for (int j = 1; j <= w; j++) {
            if (s[i][j] == '.') {
                for (int i2 = 0; i2 < N; i2++) {
                    for (int j2 = 0; j2 < N; j2++) {
                        dp[i2][j2] = INT_MAX;
                        vis[i2][j2] = 0;
                    }
                }
                bfs(i, j);
                for (int i2 = 1; i2 <= h; i2++) {
                    for (int j2 = 1; j2 <= w; j2++) {
                        if (s[i2][j2] == '.') {
                            ll cur = dp[i2][j2];
                            // debug(i2, j2, cur);
                            rst = max(rst, cur);
                        }
                    }
                }
            }
        }
    }
    cout << rst << "\n";
    return 0;
}

vector<int> dr = {0, 0, 1, -1};
vector<int> dc = {1, -1, 0, 0};

void bfs(int x, int y) {
    queue < pair < int, int > > q;
    dp[x][y] = 0;
    vis[x][y] = 1;
    q.push({x, y});
    while (!q.empty()) {
        int i = q.front().first, j = q.front().second;
        // debug(i, j);
        q.pop();
        for (int dir = 0; dir < 4; ++dir) {
            int _i = i + dr[dir];
            int _j = j + dc[dir];
            // debug(_i, _j);
            if (_i > 0 and _j > 0 and _i <= h and _j <= w and s[_i][_j] == '.') {
                dp[_i][_j] = min(dp[_i][_j], 1 + dp[i][j]);
                if (!vis[_i][_j]) {
                    vis[_i][_j] = 1;
                    q.push({_i, _j});
                }
            }
        }
    }
}
//
// void bfs(int x, int y) {
//     // debug(i, j, x, y);
//     queue < pair < int, int > > q;
//     dp[x][y] = 0;
//     q.push({x, y});
//     while (!q.empty()) {
//         int i = q.front().first, j = q.front().second;
//         // debug(i, j);
//         vis[i][j] = 1;
//         q.pop();
//         if (s[i + 1][j] == '.') {
//             dp[i + 1][j] = min(dp[i + 1][j], 1 + dp[i][j]);
//             if (!vis[i + 1][j]) {
//                 q.push({i + 1, j});
//             }
//         }
//         if (s[i - 1][j] == '.') {
//             dp[i - 1][j] = min(dp[i - 1][j], 1 + dp[i][j]);
//             if (!vis[i - 1][j]) {
//                 q.push({i - 1, j});
//             }
//         }
//         if (s[i][j + 1] == '.') {
//             dp[i][j + 1] = min(dp[i][j + 1], 1 + dp[i][j]);
//             if (!vis[i][j + 1]) {
//                 q.push({i, j + 1});
//             }
//         }
//         if (s[i][j - 1] == '.') {
//             dp[i][j - 1] = min(dp[i][j - 1], 1 + dp[i][j]);
//             if (!vis[i][j - 1]) {
//                 q.push({i, j - 1});
//             }
//         }
//     }
// }


Measured memory_bytes: 256