from collections import deque
h, w = map(int, input().split())
s = []
longest = 0

for i in range(h):
    s.append(input())

# print(s)

def getMaxPath(i, j, done):
    if str(i) + str(j) in done:
        return -1
    else:
        done.add(str(i) + str(j))
        # done.append(str(i) + str(j))

    if s[i][j] == '#':
        return 0
        # return 10**10

    r, l, u, d = 0, 0, 0, 0
    # Right
    if j < w-1 and s[i][j+1] == '.':
        r = 1 + getMaxPath(i, j+1, done)

    # Left
    if j > 0 and s[i][j-1] == '.':
        l = 1 + getMaxPath(i, j-1, done)

    # Up
    if i > 0 and s[i-1][j] == '.':
        u = 1 + getMaxPath(i-1, j, done)

    # Down
    if i < h-1 and s[i+1][j] == '.':
        d = 1 + getMaxPath(i+1, j, done)

    # if r == max(r, l, u, d):
    #     return i, j+1, max(r, l, u, d)
    # if l == max(r, l, u, d):
    #     return i, j-1, max(r, l, u, d)
    # if u == max(r, l, u, d):
    #     return i, j+1, max(r, l, u, d)
    # if d == max(r, l, u, d):
    #     return i, j+1, max(r, l, u, d)

    return max(r, l, u, d)

si, sj, gi, gj = None, None, None, None

for i in range(h):
    for j in range(w):
        temp = getMaxPath(i, j, set())
        # temp = getMaxPath(i, j, [])
        if temp > longest:
            longest = temp
            si, sj = i, j

# print('start i, start j, longest will be..')
# print(si, sj, longest)

# q = deque()
# q.append((0, (si, sj)))
# done = set()

# Look for goal
def getGoal(i, j, done, dis):
    # print(i, j, dis)
    # if str(i) + str(j) in done:
    #     return -1
    # else:
    #     done.add(str(i) + str(j))

    if dis == longest:
        # print('Found goal!!', i, j)
        return i, j

    # Right
    if j < w - 1 and s[i][j + 1] == '.':
        if str(i) + str(j+1) not in done:
            done.add(str(i) + str(j+1))
            return getGoal(i, j + 1, done, dis+1)

    # Left
    if j > 0 and s[i][j - 1] == '.':
        if str(i) + str(j-1) not in done:
            done.add(str(i) + str(j-1))
            return getGoal(i, j - 1, done, dis+1)

    # Up
    if i > 0 and s[i - 1][j] == '.':
        if str(i-1) + str(j) not in done:
            done.add(str(i-1) + str(j))
            return getGoal(i - 1, j, done, dis+1)

    # Down
    if i < h - 1 and s[i + 1][j] == '.':
        if str(i+1) + str(j) not in done:
            done.add(str(i+1) + str(j))
            return getGoal(i + 1, j, done, dis+1)
    return i, j

done = set()
done.add(str(si)+str(sj))
gi, gj = getGoal(si, sj, done, 0)

# print('gi, gj:', gi, gj)

q = deque()
q.append((0, (si, sj)))
done = set()

# Look for shortest path
while q:
    dis, tup = q.popleft()
    i, j = tup[0], tup[1]

    if i == gi and j == gj:
        # print('ans(shortest):', dis)
        print(dis)
        break

    # if dis == longest:
    #     gi, gj = i, j
    #     break

    # Right
    if j < w - 1 and s[i][j + 1] == '.':
        if str(i) + str(j+1) not in done:
            done.add(str(i) + str(j+1))
            q.append((dis+1, (i, j+1)))

    # Left
    if j > 0 and s[i][j - 1] == '.':
        if str(i) + str(j-1) not in done:
            done.add(str(i) + str(j-1))
            q.append((dis+1, (i, j-1)))

    # Up
    if i > 0 and s[i - 1][j] == '.':
        if str(i-1) + str(j) not in done:
            done.add(str(i-1) + str(j))
            q.append((dis+1, (i-1, j)))

    # Down
    if i < h - 1 and s[i + 1][j] == '.':
        if str(i+1) + str(j) not in done:
            done.add(str(i+1) + str(j))
            q.append((dis+1, (i+1, j)))


'''
3 3
...
...
...


3 5
...#.
.#.#.
.#...
'''