import Data.Array
import qualified Data.Map.Strict as Map

main = do
  h:w:_ <- map read . words <$> getLine :: IO [Int]
  ss <- lines <$> getContents :: IO [String]
  putStrLn $ show $ solveAll $ readAsMatrix h w ss

readAsMatrix :: Int -> Int -> [String] -> Array Int (Array Int Bool)
readAsMatrix n m ss = array (1, n) $ zip [1..n] $ map line ss
    where line s = array (1, m) $ zip [1..m] $ map figToInt s
          figToInt '#' = False
          figToInt '.' = True

solveAll :: Array Int (Array Int Bool) -> Int
solveAll maze = maximum $ let n = length $ indices maze
                              m = length $ indices (maze ! 1)
                          in [ solve n m (i, j) maze | i <- indices maze, j <- indices (maze ! i) ]

solve :: Int -> Int -> (Int, Int) -> Array Int (Array Int Bool) -> Int
solve n m (i,j) maze = Map.foldr max 0 $ bfs [((i, j), 0)] Map.empty
    where bfs :: [((Int, Int), Int)] -> Map.Map (Int, Int) Int -> Map.Map (Int, Int) Int
          bfs [] a = a
          bfs (((i,j),d):q) a = case  Map.lookup (i, j) a of
                                  Just _ -> bfs q a
                                  Nothing -> bfs (q ++ r) $ Map.insert (i, j) d a
                                      where r = [ ((y, x), d + 1) | (y,x) <- around (i, j), (maze ! y) ! x, Map.lookup (y, x) a == Nothing ]
                                            around (i, j) = [ (y, x) | (y,x) <- [(i+1, j), (i, j-1), (i-1, j), (i, j+1)], 0 < y, y <= n, 0 < x, x <= m ]
