from collections import deque
H,W = map(int,input().split())
#A = list(map(int,input().split()))
S = []

def bfs(maze,sy, sx):
    visited = [[-1 for i in range(W)] for j in range(H)]
    queue = deque([[sy, sx]])
    visited[sy][sx] = 0
    while queue:
        y, x = queue.popleft()
        for j, k in ([1, 0], [-1, 0], [0, 1], [0, -1]):
            new_y, new_x = y+j, x+k
            if 0 <=new_y<=H-1 and 0<= new_x<=W-1:
                if maze[new_y][new_x] == "." and visited[new_y][new_x] == -1:
                    visited[new_y][new_x] = visited[y][x] + 1
                    queue.append([new_y, new_x])
    maxa = 0
    for i in range(H):
        maxa = max(maxa,max(visited[i]))
    for i in range(H):
        if maxa in visited[i]:
            ret = [i,visited[i].index(maxa)]
            break
    return ret
def bfs2(maze,sy, sx):
    visited = [[-1 for i in range(W)] for j in range(H)]
    queue = deque([[sy, sx]])
    visited[sy][sx] = 0
    while queue:
        y, x = queue.popleft()
        for j, k in ([1, 0], [-1, 0], [0, 1], [0, -1]):
            new_y, new_x = y+j, x+k
            if 0 <=new_y<=H-1 and 0<= new_x<=W-1:
                if maze[new_y][new_x] == "." and visited[new_y][new_x] == -1:
                    visited[new_y][new_x] = visited[y][x] + 1
                    queue.append([new_y, new_x])
    maxa = 0
    for i in range(H):
        maxa = max(maxa,max(visited[i]))
    return maxa
    

for i in range(H):
    s = list(input())
    S.append(s)
for i in range(H):
    if '.' in s:
        start = [i,S[i].index('.')]
        break
ret = bfs(S,start[0],start[1])
ans = bfs2(S,ret[0],ret[1])
print(ans)

### FIXED CODE ###

from collections import deque
H,W = map(int,input().split())
#A = list(map(int,input().split()))
S = []

def bfs(maze,sy, sx):
    visited = [[-1 for i in range(W)] for j in range(H)]
    queue = deque()
    queue.append([sy, sx])
    visited[sy][sx] = 0
    while queue:
        y, x = queue.popleft()
        for j, k in ([1, 0], [-1, 0], [0, 1], [0, -1]):
            new_y, new_x = y+j, x+k
            if 0 <=new_y<=H-1 and 0<= new_x<=W-1:
                if maze[new_y][new_x] == "." and visited[new_y][new_x] == -1:
                    visited[new_y][new_x] = visited[y][x] + 1
                    queue.append([new_y, new_x])
    maxa = 0
    for i in range(H):
        maxa = max(maxa,max(visited[i]))
    for i in range(H):
        if maxa in visited[i]:
            ret = [i,visited[i].index(maxa)]
            break
    return ret
def bfs2(maze,sy, sx):
    visited = [[-1 for i in range(W)] for j in range(H)]
    queue = deque()
    queue.append([sy, sx])
    visited[sy][sx] = 0
    while queue:
        y, x = queue.popleft()
        for j, k in ([1, 0], [-1, 0], [0, 1], [0, -1]):
            new_y, new_x = y+j, x+k
            if 0 <=new_y<=H-1 and 0<= new_x<=W-1:
                if maze[new_y][new_x] == "." and visited[new_y][new_x] == -1:
                    visited[new_y][new_x] = visited[y][x] + 1
                    queue.append([new_y, new_x])
    maxa = 0
    for i in range(H):
        maxa = max(maxa,max(visited[i]))
    return maxa
    

for i in range(H):
    s = list(input())
    S.append(s)
ans2 = []
for i in range(H):
    for j in range(W):
        if S[i][j] == '.':
            start = [i,S[i].index('.')]
            ret = bfs(S,start[0],start[1])
            ans = bfs2(S,ret[0],ret[1])
            ans2.append(ans)

print(max(ans2))