import copy
H = 0
W = 0


def search_route(maps, x_start, y_start, x_end, y_end):
    # print('starting search shortest path:')
    # print('start:', x_start, y_start, 'end:', x_end, y_end)
    maps[y_start][x_start]['distance'] = 0
    maps[y_start][x_start]['from_p'] = 'start'
    maps[y_end][x_end]['distance'] = 0
    maps[y_end][x_end]['from_p'] = 'end'

    # スタートとゴールから一歩ずつ移動する
    latest_searched_from_start =[{'x': x_start, 'y': y_start}]
    latest_searched_from_end = [{'x': x_end, 'y': y_end}]
    for i in range(1, H*W):
        new_latest_searched_from_start = []
        for road in latest_searched_from_start:
            for direction in [{'x': 1, 'y': 0}, {'x': -1, 'y': 0}, {'x': 0, 'y': 1}, {'x': 0, 'y': -1}]:
                x = road['x'] + direction['x']
                y = road['y'] + direction['y']
                if x < 0 or x >= W or y < 0 or y >= H:
                    continue
                object_r = maps[y][x]
                if 'from_p' in object_r.keys() and object_r['from_p'] == 'end':  # 探索済みだったら終了
                    return (i - 1) * 2 + 1
                if not object_r['isWall'] and 'from_p' not in object_r.keys():
                    object_r['distance'] = i
                    object_r['from_p'] = 'start'
                    new_latest_searched_from_start.append({'x': x, 'y': y})
        latest_searched_from_start = new_latest_searched_from_start
        # print(latest_searched_from_start)

        new_latest_searched_from_end = []
        for road in latest_searched_from_end:
            for direction in [{'x': 1, 'y': 0}, {'x': -1, 'y': 0}, {'x': 0, 'y': 1}, {'x': 0, 'y': -1}]:
                x = road['x'] + direction['x']
                y = road['y'] + direction['y']
                if x < 0 or x >= W or y < 0 or y >= H:
                    continue
                object_r = maps[y][x]
                if 'from_p' in object_r.keys() and object_r['from_p'] == 'start':  # 探索済みだったら終了
                    return i * 2
                if not object_r['isWall'] and 'from_p' not in object_r.keys():
                    object_r['distance'] = i
                    object_r['from_p'] = 'end'
                    new_latest_searched_from_end.append({'x': x, 'y': y})
        latest_searched_from_end = new_latest_searched_from_end
        # print(latest_searched_from_end)

    return None


def main():
    global H, W
    H, W = map(int, input().split())
    maps = []
    for i in range(H):
        row = []
        for load in list(input()):
            if load == '#':
                row.append({'isWall': True})
            else:
                row.append({'isWall': False})
        maps.append(row)

    max_times = 0  # 移動回数の最大値
    for i_start in range(H*W):  # 縦：５　横：３のマップで i = 10のとき
        x_start = i_start % W  # x_start = 1
        y_start = i_start // W  # y_start = 3
        if maps[y_start][x_start]['isWall']:
            continue
        for i_end in range(i_start+1, H*W):
            x_end = i_end % W
            y_end = i_end // W
            times = search_route(copy.deepcopy(maps), x_start, y_start, x_end, y_end)
            # print('shortest path takes', times, 'times')
            # print('')
            if times > max_times:
                max_times = times

    # x_start = 0  # x_start = 1
    # y_start = 0  # y_start = 3
    # x_end = 2
    # y_end = 2
    # times = search_route(copy.deepcopy(maps), x_start, y_start, x_end, y_end)
    # print('shortest path takes', times, 'times')
    # print('')
    # if times > max_times:
    #     max_times = times

    print(max_times)


if __name__ == "__main__":
    main()
