(eval-when (:compile-toplevel :load-toplevel :execute)
  (defparameter OPT
    #+swank '(optimize (speed 3) (safety 2))
    #-swank '(optimize (speed 3) (safety 0) (debug 0)))
  #+swank (progn (ql:quickload '(:cl-debug-print :fiveam))
                 (shadow :run)
                 (use-package :fiveam)))
#+swank (cl-syntax:use-syntax cl-debug-print:debug-print-syntax)



;;; Body


(defparameter *default-deque-size* 100)

(defstruct deque
  (data nil)
  (size nil)
  (head 0)
  (tail 0)
  (count 0))


(defun deque-create (&optional (size *default-deque-size*))
  (make-deque
   :size size
   :data (make-array size)))



(defmethod deque-clear ((d deque))
  (fill (deque-data d) 0)
  (setf (deque-size d) 0)
  (setf (deque-head d) 0)
  (setf (deque-tail d) 0)
  (setf (deque-count d) 0))

;; Subcommand

(declaim (inline deque-empty-p
                 deque-full-p
                 deque-get-prev-index
                 deque-get-next-index))


(defmethod deque-empty-p ((d deque))
  (zerop (deque-count d)))



(defmethod deque-full-p ((d deque))
  (= (deque-count d) (deque-size d)))

(defmethod deque-get-prev-index ((d deque) idx)
  (declare (inline deque-get-next-index))
  (if (zerop idx)
      (1- (deque-size d))
      (1- idx)))

(defmethod deque-get-next-index ((d deque) idx)
  (rem (1+ idx) (deque-size d)))




;;; Main command

(defmethod deque-pushfront ((d deque) item)
  (when (deque-full-p d)
    (error "deque is full"))

  (setf (deque-head d) (deque-get-prev-index d (deque-head d)))
  (setf (aref (deque-data d) (deque-head d)) item)
  (when (deque-empty-p d) ; first insersion
    (setf (deque-tail d) (deque-head d)))
  (incf (deque-count d)))



(defmethod deque-pushback ((d deque) item)
  (when (deque-full-p d)
    (error "deque is full"))
  
  (setf (deque-tail d) (deque-get-next-index d (deque-tail d)))
  (setf (aref (deque-data d) (deque-tail d)) item)
  (when (deque-empty-p d) ; first insersion
    (setf (deque-head d) (deque-tail d)))
  (incf (deque-count d)))


(defmethod deque-popfront ((d deque))
  (when (deque-empty-p d)
    (error "deque is empty,"))
  
  (let ((value (aref (deque-data d) (deque-head d))))
    (setf (deque-head d) (deque-get-next-index d (deque-head d)))
    (decf (deque-count d))
    value))



(defmethod deque-popback ((d deque))
  (when (deque-empty-p d)
    (error "deque is empty,"))
  
  (let ((value (aref (deque-data d) (deque-tail d))))
    (setf (deque-tail d) (deque-get-prev-index d (deque-tail d)))
    (decf (deque-count d))
    value))


(defmethod dref ((d deque) subscripts)
  (let ((arr (deque-data d))
        (size (deque-size d))
        (head (deque-head d)))
    (aref arr (mod (+ subscripts
                      head)
                   size))))


(defparameter *inf* 1000000)

(defparameter *dy-dx* '((1 . 0)
                        (-1 . 0)
                        (0 . 1)
                        (0 . -1)))

(defun bfs (sy sx h w board)
  (declare (fixnum sy sx h w)
           (array board))
  (the fixnum
       (let ((q (deque-create)))
         (deque-pushback q (cons sy sx))
         (setf (aref board sy sx) 0)
         (loop until (deque-empty-p q) do
              (let ((pos (deque-popfront q)))
                (loop for d in *dy-dx* do
                     (let ((ny (+ (first pos) (first d)))
                           (nx (+ (rest pos) (rest d))))
                       (when (and (<= 0 ny (1- h))
                                  (<= 0 nx (1- w))
                                  (= (aref board ny nx) *inf*))
                         (deque-pushback q (cons ny nx))
                         (setf (aref board ny nx)
                               (1+ (aref board (first pos) (rest pos))))))))
            finally
              (let ((cand -1))
                (declare (fixnum cand))
                (dotimes (y h)
                  (dotimes (x w)
                    (when (and (/= (aref board y x) -1)
                               (/= (aref board y x) *inf*))
                      (setf cand (max cand
                                      (aref board y x))))))
                (assert (plusp cand))
                (return cand))))))

(defun solve (h w board)
  (let ((res -1))
    (dotimes (i h)
      (dotimes (j w)
        (when (= (aref board i j) *inf*)
          (setf res (max res
                         (bfs i j h w board))))))
    res))


(defun main ()
  (declare #.OPT)
  (let ((h (read))
        (w (read))
        tmp)
    (let ((board (make-array `(,h ,w) :element-type 'fixnum)))
      (loop for y below h do
           (loop for x below w do
                (setf tmp (read-char))
                (if (char-equal tmp #\.)
                    (setf (aref board y x) *inf*)
                    (setf (aref board y x) -1))))
      (format t "~a~&" (solve h w board)))))

#-swank (main)
