import java.util.*

fun main(args: Array<String>) {
    val INF = -100000007
    val (H, W) = readLine()!!.split(" ").map(String::toInt)
    val maze = Array(H) {
       readLine()!!.toCharArray()
    }
    fun bfs(sx: Int, sy: Int): Int {
        var dmax = 0
        val dx = arrayOf(1,0,-1,0)
        val dy = arrayOf(0,1,0,-1)
        val que = ArrayDeque<Pair<Int,Int>>()
        que.addLast(Pair(sx, sy))
        val d = Array(H){ Array(W) {INF} }
        d[sy][sx] = 0
        while (que.size > 0) {
            val p = que.removeFirst()
            for (i in 0..3) {
                val nx = p.first + dx[i]
                val ny = p.second + dy[i]
                if ((nx in 0 until W) && (ny in 0 until H) && maze[ny][nx] == '.' && d[ny][nx] == INF) {
                    que.addLast(Pair(nx, ny))
                    d[ny][nx] = d[p.second][p.first] + 1
                    if (dmax <  d[ny][nx]) {
                        dmax = d[ny][nx]
                    }
                }
            }
        }
        return dmax
    }
    var ans = 0
    for (h in 0 until H) {
        for (w in 0 until W) {
            if (maze[h][w] != '.') continue
            ans = Math.max(ans, bfs(w, h))
        }
    }
    println(ans)
}