import java.util.*

fun main(args: Array<String>) {
    val scanner = Scanner(System.`in`)
    val h = scanner.nextInt()
    val w = scanner.nextInt()
    val queue = Queue<Pair<Int, Int>>()
    val isRoad: List<MutableList<Boolean>> = List(h, { i -> MutableList(w, { i -> false }) } )
    for (i in 0..h-1) {
        val line = scanner.next()
        for (j in 0..w-1) {
            isRoad[i][j] = line[j] == '.'
        }
    }

    var max = 0

    for (i in 0..h-1) {
        for (j in 0..w-1) {
            if (isRoad[i][j]) {
                val distance: List<MutableList<Int>> = List(h, { i -> MutableList(w, { i -> -1 }) } )
                distance[i][j] = 0
                queue.enqueue((i to j))

                while (queue.isEmpty().not()) {
                    val element = queue.dequeue()
                    val k = element.first
                    val l = element.second

                    // hidari
                    if (l-1 >= 0 && isRoad[k][l-1] && distance[k][l-1] == -1) {
                        queue.enqueue((k to l-1))
                        distance[k][j-1] = distance[k][l] + 1
                        if (max < distance[k][l] + 1) max = distance[k][l] + 1
                    }

                    // migi
                    if (l+1 < w && isRoad[k][l+1] && distance[k][l+1] == -1) {
                        queue.enqueue((k to l+1))
                        distance[k][l+1] = distance[k][l] + 1
                        if (max < distance[k][l] + 1) max = distance[k][l] + 1
                    }

                    // ue
                    if (k-1 >= 0 && isRoad[k-1][l] && distance[k-1][l] == -1) {
                        queue.enqueue((k-1 to l))
                        distance[k-1][l] = distance[k][l] + 1
                        if (max < distance[k][l] + 1) max = distance[k][l] + 1
                    }

                    // shita
                    if (k+1 < h && isRoad[k+1][l] && distance[k+1][l] == -1) {
                        queue.enqueue((k+1 to l))
                        distance[k+1][l] = distance[k][l] + 1
                        if (max < distance[k][l] + 1) max = distance[k][l] + 1
                    }
                }
            }
        }
    }

    println(max)
}

class Queue<T> {
    private val queue = mutableListOf<T>()

    fun isEmpty() = queue.isEmpty()
    fun count() = queue.count()
    fun enqueue(element: T) = queue.add(element)
    fun dequeue() = if (queue.isEmpty().not()) queue.removeAt(0) else throw IndexOutOfBoundsException("Queue is empty.")

    override fun toString() = queue.toString()
}
