package main

import (
	"bufio"
	"fmt"
	"os"
)

var sc = bufio.NewScanner(os.Stdin)

func main() {
	var h, w int
	var roads []int
	fmt.Scan(&h, &w)
	graph := readTwoDGraph(h, w)
	for i := 0; i < h; i++ {
		for j := 0; j < w; j++ {
			if graph[i][j] == '.' {
				roads = append(roads, bfs(i, j, h, w, graph))
			}
		}
	}
	fmt.Println(max(roads))
}

func bfs(i int, j int, h int, w int, graph [][]rune) int {
	dist := make([][]int, h)
	for k := 0; k < h; k++ {
		dist[k] = make([]int, w)
	}
	maxes := make([]int, h)
	dist[i][j] = 0
	que := []int{}
	que = append(que, i)
	que = append(que, j)
	for len(que) > 0 {
		i = que[0]
		que = que[1:]
		j = que[0]
		que = que[1:]
		visit(dist, i, j, h, w, 1, 0, graph, &que)
		visit(dist, i, j, h, w, -1, 0, graph, &que)
		visit(dist, i, j, h, w, 0, 1, graph, &que)
		visit(dist, i, j, h, w, 0, -1, graph, &que)
	}
	for k := 0; k < h; k++ {
		maxes[k] = max(dist[k])
	}
	return max(maxes)
}

func visit(dist [][]int, i int, j int, h int, w int, dx int, dy int, graph [][]rune, que *[]int) {
	if i+dy >= h || j+dx >= w || i+dy < 0 || j+dx < 0 {
		return
	}
	r := graph[i+dy][j+dx]
	if r == '#' {
		return
	}
	if r == '.'&& dist[i+dy][j+dx] == 0 {
		dist[i+dy][j+dx] = dist[i][j] + 1
		*que = append(*que, i+dy)
		*que = append(*que, j+dx)
	}
}

func max(s []int) int {
	var r int
	for _, value := range s {
		if value > r {
			r = value
		}
	}
	return r
}

func nextLine() string {
	sc.Scan()
	return sc.Text()
}

func readTwoDGraph(h int, w int) [][]rune {
	matrix := make([][]rune, h)
	for i := 0; i < h; i++ {
		matrix[i] = make([]rune, w)
		tmp := nextLine()
		for j := 0; j < w; j++ {
			matrix[i][j] = rune(tmp[j])
			/* if matrix[i][j] == 's' {
				startIdx[0] = i
				startIdx[1] = j
			}
			if matrix[i][j] == 'g' {
				goalIdx[0] = i
				goalIdx[1] = j
			} */
		}
	}
	return matrix
}
