// Contest: AtCoder Beginner Contest 151 (https://atcoder.jp/contests/abc151)
// Problem: D: Maze Master (https://atcoder.jp/contests/abc151/tasks/abc151_d)


// region {{{ boilerplate
#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdint>
#include <deque>
#include <exception>
#include <forward_list>
#include <functional>
#include <initializer_list>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <limits>
#include <list>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

#if __cplusplus >= 201703L
#   include <optional>
#   include <string_view>
#   include <variant>
#endif

using namespace std;

#if __cpp_lib_nonmember_container_access >= 201411
#   define sz(x) ((int)size(x))
#else
#   define sz(x) ((int)(x).size())
#endif

#define rep(a, b)      for(int a = 0; a < (b); ++a)
#define reps(a, b, c)  for(int a = (b); a < (c); ++a)
#define all(a)         (a).begin(),(a).end()
#define trav(a, b)     for(auto& a : b)

using ll = long long;
using ld = long double;
using u64 = uint64_t;
using u32 = uint32_t;

using pi = pair<int, int>;
using pl = pair<ll, ll>;
using vi = vector<int>;
using vl = vector<ll>;
using vvi = vector<vi>;
using vpi = vector<pi>;

#if __has_cpp_attribute(maybe_unused) >= 201603
#   define MAYBE_UNUSED [[maybe_unused]]
#else
#   define MAYBE_UNUSED
#endif

MAYBE_UNUSED static constexpr int INF = (int)1e9;
MAYBE_UNUSED static constexpr ll INFL = (ll)1e18;
//endregion }}}


int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int h, w; cin >> h >> w;
    vector<string> g(h);
    trav(r, g) cin >> r;

    auto val = [&](int x, int y) { return 0 <= x && x < w && 0 <= y && y < h && g[y][x] == '.'; };
    int mx = 0;
    rep(xi, w) rep(yi, h) {
        vvi d = vvi(w, vi(h, INF));
        d[xi][yi] = 0;
        queue<pi> q;
        q.emplace(xi, yi);
        while (sz(q)) {
            int x, y;
            tie(x, y) = q.front(); q.pop();
            for (auto off : {make_pair(-1,0), make_pair(1,0), make_pair(0,1), make_pair(0,-1)}) {
                int dx, dy; tie(dx, dy) = off;
                if (val(x+dx, y+dy) && d[x+dx][y+dy] == INF) {
                    d[x+dx][y+dy] = d[x][y] + 1;
                    q.emplace(x+dx,y+dy);
                }
            }
        }
        rep(x2, w) rep(y2, h)
            mx = max(mx, d[x2][y2]);
    }

    cout << mx << '\n';
    return 0;
}