H, W = gets.split.map(&:to_i)
S = H.times.map { gets.chomp.chars }

DY = [-1, 0, 1, 0]
DX = [0, 1, 0, -1]

def calc_path_size(sy, sx, ty, tx)
  queue = []

  queue << [sy, sx, 0]
  max_dist = 0

  visited = Hash.new { |h, k| h[k] = Hash.new(false) }

  until queue.empty?
    y, x, dist = queue.shift

    next if visited[y][x]
    visited[y][x] = true

    if y == ty && x == tx
      return dist
      break
    end

    DY.zip(DX) do |dy, dx|
      ny = y + dy
      nx = x + dx

      next if ny < 0 || nx < 0 || H <= ny || W <= nx
      next if S[ny][nx] == '#'

      queue << [ny, nx, dist + 1]
    end
  end

  max_dist
end

ans = 0

M = H * W - 1

0.upto(M - 2) do |z1|
  y1 = z1 / W
  x1 = z1 % W

  next if S[y1][x1] == '#'

  (z1 + 1).upto(M - 1) do |z2|
    y2 = z2 / W
    x2 = z2 % W

    next if S[y2][x2] == '#'

    dist = calc_path_size(y1, x1, y2, x2)

    ans = dist if ans < dist
  end
end

puts ans
