package main

import (
	"fmt"
)

func main() {

	var h, w int
	fmt.Scanf("%d %d", &h, &w)

	maze := make([][]bool, h)
	oi, oj := 0, 0
	for i := 0; i < h; i++ {
		line := make([]bool, w)
		var s string
		fmt.Scanf("%s", &s)
		for j, c := range s {
			if c == '.' {
				line[j] = true
				oi, oj = i, j
			}
		}
		maze[i] = line
	}

	si, sj, _ := farthest(maze, oi, oj)
	_, _, gd := farthest(maze, si, sj)

	fmt.Printf("%d\n", gd)
}

type point struct {
	i int
	j int
}

type node struct {
	point point
	dist  int
}

func farthest(maze [][]bool, oi, oj int) (int, int, int) {

	mi, mj, md := 0, 0, 0

	origin := point{i: oi, j: oj}
	queue := []node{node{point: origin, dist: 0}}
	visited := map[point]struct{}{}

	for len(queue) > 0 {
		n := queue[0]
		queue = queue[1:]

		if _, ok := visited[n.point]; ok {
			continue
		}

		visited[n.point] = struct{}{}
		i, j, dist := n.point.i, n.point.j, n.dist

		if dist > md {
			mi, mj, md = i, j, dist
		}

		if i > 0 && maze[i-1][j] {
			queue = append(queue, node{point: point{i: i - 1, j: j}, dist: dist + 1})
		}
		if i < len(maze)-1 && maze[i+1][j] {
			queue = append(queue, node{point: point{i: i + 1, j: j}, dist: dist + 1})
		}
		if j > 0 && maze[i][j-1] {
			queue = append(queue, node{point: point{i: i, j: j - 1}, dist: dist + 1})
		}
		if j < len(maze[i])-1 && maze[i][j+1] {
			queue = append(queue, node{point: point{i: i, j: j + 1}, dist: dist + 1})
		}

	}

	return mi, mj, md
}
