import java.util.*

fun main(args: Array<String>) {
    abc151d()
}

fun abc151d() {
    data class Coordinate(val y: Int, val x: Int)

    val INF = 1000000

    val (h, w) = readLine()!!.split(' ').map { it.toInt() }
    val isRoad = (1..h).map { readLine()!!.map { it == '.' }.toBooleanArray() }.toTypedArray()

    val direction = listOf(-1 to 0, 1 to 0, 0 to -1, 0 to 1)
    val minCosts = Array(500) { y -> IntArray(500) { x -> if (y == x) 0 else INF } }
    fun getId(y: Int, x: Int) = y * h + x

    for (y in 0 until h) {
        for (x in 0 until w) {
            if (!isRoad[y][x]) continue

            direction.map { Coordinate(y + it.first, x + it.second) }
                .filter { it.y in 0 until h && it.x in 0 until w && isRoad[it.y][it.x] }
                .forEach { minCosts[getId(y, x)][getId(it.y, it.x)] = 1 }
        }
    }

    val gridSize = h * w

    for (k in 0 until gridSize) {
        for (i in 0 until gridSize) {
            for (j in 0 until gridSize) {
                minCosts[i][j] = Math.min(minCosts[i][j], minCosts[i][k] + minCosts[k][j])
            }
        }
    }

    var answer = 0

    for (y in 0 until h) {
        for (x in 0 until w) {
            if (!isRoad[y][x]) continue
            for (y1 in 0 until h) {
                for (x1 in 0 until w) {
                    if (!isRoad[y1][x1]) continue
                    answer = Math.max(answer, minCosts[getId(y, x)][getId(y1, x1)])
                }
            }
        }
    }

    println(answer)
}
