#include <bits/stdc++.h>
#define FOR(i,b,e) for (common_type_t<decltype(b),decltype(e)> i = (b), i ## __end = (e); i < i ## __end; ++ i)
#define rep(i,n)   FOR (i, size_t{}, n)
#define ALL(x)     begin (x), end (x)
using namespace std;
using ll = int64_t;
constexpr ll inf = 2e18;
constexpr size_t invalid = ~0ull;

template <typename T>
auto make_vector (size_t n, T v)
{
  return vector <T> (n, v);
}

template <typename ... Args>
auto make_vector (size_t n, Args ... rest)
{
  auto value = make_vector (rest ...);
  using T = decay_t <decltype (value)>;
  return vector <T> (n, value);
}

size_t H, W;
vector <vector <char>> s;

inline auto solve (size_t starty, size_t startx)
{
  using P = tuple <size_t, size_t, ll>;
  queue <P> q;
  q.push (P {starty, startx, 0});
  auto visited = make_vector (H, W, char {0});
  auto costto = make_vector (H, W, inf);
  vector <P> endpoints;
  while (not q.empty ())
  {
    auto now = q.front (); q.pop ();
    size_t x, y;
    ll cost;
    bool is_endpoint = true;
    tie (y, x, cost) = now;
    visited [y] [x] = true;
    costto [y] [x] = min (costto [y][x], cost);
    if (y > 0)
    {
      auto nexty = y - 1;
      if (s [nexty][x] == '.' && not visited [nexty][x])
      {
        q.push (P {nexty, x, cost + 1});
        is_endpoint = false;
      }
    }
    if (y + 1 < H)
    {
      auto nexty = y + 1;
      if (s [nexty][x] == '.' && not visited [nexty][x])
      {
        q.push (P {nexty, x, cost + 1});
        is_endpoint = false;
      }
    }
    if (x > 0)
    {
      auto nextx = x - 1;
      if (s [y][nextx] == '.' && not visited [y][nextx])
      {
        q.push (P {y, nextx, cost + 1});
        is_endpoint = false;
      }
    }
    if (x + 1 < W)
    {
      auto nextx = x + 1;
      if (s [y][nextx] == '.' && not visited [y][nextx])
      {
        q.push (P {y, nextx, cost + 1});
        is_endpoint = false;
      }
    }

    if (is_endpoint)
    {
      endpoints.emplace_back (y, x, cost);
    }

  }
  return endpoints;
}

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

  cin >> H >> W;
  s = make_vector (H, W, char {});
  rep (i, H) rep (j, W) cin >> s [i][j];


  vector <pair <size_t, size_t>> valid_paths;

  rep (i, H) rep (j, W)
  {
    if (s [i][j] == '.')
    {
      valid_paths.emplace_back (i, j);
    }
  }

  ll ans = 0;
  for (auto && start : valid_paths)
  {
    size_t x, y;
    tie (y, x) = start;
    auto endpoints = solve (y, x);
    for (auto && elem : endpoints)
    {
      ll cost;
      tie (ignore, ignore, cost) = elem;
      ans = max (ans, cost);
    }
  }
  cout << ans << endl;
}
