package main

import "fmt"

const maxDepth = 1000
const childNum = 4

type mentry struct {
	Mtype bool
	Depth int
}

func newMap(h, w int) [][]mentry {
	m := make([][]mentry, h)
	for hi := 0; hi < h; hi++ {
		m[hi] = make([]mentry, w)
		var mstr string
		fmt.Scan(&mstr)
		for wi, c := range mstr {
			if c == '.' {
				m[hi][wi].Mtype = true
			}
			m[hi][wi].Depth = maxDepth
		}
	}
	return m
}

func clearMap(m [][]mentry, h, w int) {
	for hi := 0; hi < h; hi++ {
		for wi := 0; wi < w; wi++ {
			m[hi][wi].Depth = maxDepth
		}
	}
}

type tentry struct {
	ID       int
	Depth    int
	MaxDepth [childNum]int
	Chiled   [childNum]*tentry
}

func newTentry(id, depth int) *tentry {
	te := new(tentry)
	te.ID = id
	te.Depth = depth
	for i := 0; i < childNum; i++ {
		te.MaxDepth[i] = maxDepth
	}
	return te
}

func (te *tentry) maxDepth() int {
	ret := 0
	for i := 0; i < childNum; i++ {
		if ret < te.MaxDepth[i] {
			ret = te.MaxDepth[i]
		}
	}
	return ret
}

func createTree(e *tentry, m [][]mentry, md int, idl map[int]struct{}) int {
	// push id to list
	idl[e.ID] = struct{}{}

	cd := e.Depth
	ch, cw := id2pos(e.ID)
	var nh, nw int

	// create childe entry
	if cd == md-1 {
		for i := 0; i < childNum; i++ {
			switch i {
			case 0: //UP
				nh = ch - 1
				nw = cw
			case 1: //Dwon
				nh = ch + 1
				nw = cw
			case 2: //Left
				nh = ch
				nw = cw - 1
			case 3: //Right
				nh = ch
				nw = cw + 1
			}
			if nh >= 0 && nh < h && nw >= 0 && nw < w && m[nh][nw].Mtype && m[nh][nw].Depth >= cd {
				if _, ok := idl[pos2id(nh, nw)]; !ok {
					m[nh][nw].Depth = cd
					e.Chiled[i] = newTentry(pos2id(nh, nw), cd+1)
				}
			}
			if e.Chiled[i] == nil {
				e.MaxDepth[i] = cd
			}
		}
	}

	// move to childe entry
	if cd < md-1 {
		for i := 0; i < childNum; i++ {
			if e.Chiled[i] != nil && e.MaxDepth[i] > md {
				e.MaxDepth[i] = createTree(e.Chiled[i], m, md, idl)
			}
		}
	}

	// pop id from lit
	delete(idl, e.ID)
	return e.maxDepth()
}

// id <-> pos 変換関数
var h, w int
var root *tentry

func id2pos(id int) (int, int) {
	rh := id / w
	rw := id % w
	return rh, rw
}
func pos2id(ah, aw int) int {
	return ah*w + aw
}

func main() {
	// 入力読み込み
	fmt.Scan(&h, &w)

	// map読み込み
	m := newMap(h, w)

	// treeを作成して最大の深さを取得
	var ans int
	for rh := 0; rh < h; rh++ {
		for rw := 0; rw < w; rw++ {
			if m[rh][rw].Mtype == false {
				continue
			}
			// root entry
			rid := pos2id(rh, rw)
			root = newTentry(rid, 0)
			m[rh][rw].Depth = 0

			// create tree
			idl := make(map[int]struct{}, 100)
			var cd, md int
			cd = 1
			for {
				md = createTree(root, m, cd, idl)
				if md < cd {
					break
				}
				cd++
			}
			if md > ans {
				ans = md
			}
			clearMap(m, h, w)
		}
	}

	fmt.Println(ans)

}
