from bisect import bisect_right, bisect_left
from itertools import groupby, permutations, combinations
from fractions import gcd
import numpy as np
from sys import stdin, stderr


def lcm(x, y):
    return (x * y) // gcd(x, y)


def movement_max(start_h, start_w, maze):
    H, W = len(maze), len(maze[0])
    score = []
    unvisited = set()
    visited = set()
    unvisited.add(start_h + start_w*100)
    for h in range(H):
        score.append([1000] * W)
        for w in range(W):
            if maze[h][w] == "#":
                visited.add(h + w*100)
    score[start_h][start_w] = 0
    ret = 0
    while len(unvisited) > 0:
        hw = unvisited.pop()
        h = hw % 100
        w = hw // 100
        visited.add(hw)
        if maze[h][w] == "#":
            continue
        s = score[h][w] + 1
        ret = max(ret, score[h][w])
        if h > 0:
            score[h-1][w] = min(s, score[h-1][w])
            if (h-1 + w*100) not in visited:
                unvisited.add(h-1 + w*100)
        if h < H - 1:
            score[h+1][w] = min(s, score[h+1][w])
            if (h+1 + w*100) not in visited:
                unvisited.add(h+1 + w*100)
        if w > 0:
            score[h][w-1] = min(s, score[h][w-1])
            if (h + (w-1)*100) not in visited:
                unvisited.add(h + (w-1)*100)
        if w < W - 1:
            score[h][w+1] = min(s, score[h][w+1])
            if (h + (w+1)*100) not in visited:
                unvisited.add(h + (w+1)*100)
    return ret


def main():
    H, W = [int(x) for x in input().split()]
    maze = [""] * H
    score = []
    for i in range(H):
        maze[i] = input()
        score.append([-1] * W)
    result = 0
    for h in range(H):
        for w in range(W):
            if maze[h][w] == "#":
                continue
            score[h][w] = movement_max(h, w, maze)
            result = max(result, movement_max(h, w, maze))
            # print(result)
        # print(score[h])
    return result


if __name__ == "__main__":
    print(main())