import Control.Monad
import qualified Data.Map as M

main = do
    [h, w] <- map read . words <$> getLine
    maze <- toMap h w <$> replicateM h getLine
    print $ maximum [pathLength maze i j| i <- [1..h], j <- [1..w]]

toMap h w xss = toMap' h w 1 1 xss
  where
    toMap' h w _ _ [] = M.fromList [((i,j),'#')|i<-[0..h+1],j<-[0..w+1],i==0||i==h+1||j==0||j==w+1]
    toMap' h w i j ([]:xss) = toMap' h w (i+1) 1 xss
    toMap' h w i j ((x:xs):xss) = M.insert (i,j) x (toMap' h w i (j+1) (xs:xss))

pathLength maze i j = bfs 0 [((i,j), 0)] maze
    where bfs l [] maze = l
          bfs l (((i,j),d) : q) maze
              | maze M.! (i,j) == '#' = bfs l q maze
              | otherwise = bfs d (q ++ r) $ M.insert (i,j) '#' maze
                  where r = [((x,y),d+1)|(x,y)<-[(i-1,j),(i+1,j),(i,j-1),(i,j+1)], maze M.! (x,y) == '.']