### BUGGY CODE ###

import queue
import copy
 
def ngoin(bo,now):
    return 0 <= now[0] and now[0] < len(bo) and 0 <= now[1] and now[1] < len(bo[0])
 
def minido(bo,si,sj,ei,ej):
    tb = [[False for i in range(len(bo[0]))] for j in range(len(bo))]
    q = queue.Queue()
    q.put([si,sj,0])
    while not q.empty():
        now = q.get()
        if now[0] == ei and now[1] == ej:
            return now[2]
        if tb[now[0]][now[1]]:
            continue
        tb[now[0]][now[1]] = True
        if ngoin(bo,[now[0]-1,now[1]]):
            if bo[now[0]-1][now[1]]:
                q.put([now[0]-1,now[1],now[2]+1])
        if ngoin(bo,[now[0],now[1]+1]):
            if bo[now[0]][now[1]+1]:
                q.put([now[0],now[1]+1,now[2]+1])
        if ngoin(bo,[now[0]+1,now[1]]):
            if bo[now[0]+1][now[1]]:
                q.put([now[0]+1,now[1],now[2]+1])
        if ngoin(bo,[now[0],now[1]-1]):
            if bo[now[0]][now[1]-1]:
                q.put([now[0],now[1]-1,now[2]+1])
            
            
 
h,w = map(int,input().split())
bo = [[True if x == '.' else False for x in input()] for i in range(h)]
grap = [[float('inf') for i in range(h*w)] for j in range(h*w)]
ans = 0
for i in range(h*w):
    grap[i][i] = 0
for si in range(h):
    for sj in range(w):
        if not bo[si][sj]:
            continue
        now = [si,sj]
        if ngoin(bo,[now[0]-1,now[1]]):
            if bo[now[0]-1][now[1]]:
                grap[now[0]*w+now[1]][(now[0]-1)*w+now[1]] = 1
        if ngoin(bo,[now[0],now[1]+1]):
            if bo[now[0]][now[1]+1]:
                grap[now[0]*w+now[1]][1+now[0]*w+now[1]] = 1
        if ngoin(bo,[now[0]+1,now[1]]):
            if bo[now[0]+1][now[1]]:
                grap[now[0]*w+now[1]][(now[0]+1)*w+now[1]] = 1
        if ngoin(bo,[now[0],now[1]-1]):
            if bo[now[0]][now[1]-1]:
                grap[now[0]*w+now[1]][now[0]*w-1+now[1]] = 1
                
for k in range(w*h):
    for i in range(w*h):
        for j in range(w*h):
            if grap[i][j] > grap[i][k] + grap[k][j]:
                grap[i][j] = grap[i][k] + grap[k][j]

ans = 0
for i in range(w*h):
    for j in range(w*h):
        if grap[i][j] == float('inf'):
            continue
        ans = max(grap[i][j],ans)

print(ans)


### FIXED CODE ###

import queue
import copy
 
def ngoin(bo,now):
    return 0 <= now[0] and now[0] < len(bo) and 0 <= now[1] and now[1] < len(bo[0])
 
def minido(bo,si,sj):
    tb = [[False for i in range(len(bo[0]))] for j in range(len(bo))]
    q = queue.Queue()
    q.put([si,sj,0])
    tb[si][sj] = True
    ret = 0
    while not q.empty():
        now = q.get()
        ret = now[2]
        if ngoin(bo,[now[0]-1,now[1]]):
            if bo[now[0]-1][now[1]] and not tb[now[0]-1][now[1]]:
                q.put([now[0]-1,now[1],now[2]+1])
                tb[now[0]-1][now[1]] = True
                
        if ngoin(bo,[now[0],now[1]+1]):
            if bo[now[0]][now[1]+1] and not tb[now[0]][now[1]+1]:
                q.put([now[0],now[1]+1,now[2]+1])
                tb[now[0]][now[1]+1] = True
                
        if ngoin(bo,[now[0]+1,now[1]]):
            if bo[now[0]+1][now[1]] and not tb[now[0]+1][now[1]]:
                q.put([now[0]+1,now[1],now[2]+1])
                tb[now[0]+1][now[1]] = True
                
        if ngoin(bo,[now[0],now[1]-1]):
            if bo[now[0]][now[1]-1] and not tb[now[0]][now[1]-1]:
                q.put([now[0],now[1]-1,now[2]+1])
                tb[now[0]][now[1]-1] = True
    return ret
            
 
h,w = map(int,input().split())
bo = [[True if x == '.' else False for x in input()] for i in range(h)]
grap = [[float('inf') for i in range(h*w)] for j in range(h*w)]
ans = 0
for i in range(h*w):
    grap[i][i] = 0
for si in range(h):
    for sj in range(w):
        if not bo[si][sj]:
            continue
        ans = max(ans,minido(bo,si,sj))
                
print(ans)