### BUGGY CODE ###

from collections import deque

INF = float('inf')

h,w = map(int, input().split())

point_list = []
for i in range(w*h):
    point_list.append([w*h]*w*h)
maze = []

Q = deque([])


for i in range(h):
    tmp = list(input())
    maze.append(tmp)

for s_y in range(h):
    for s_x in range(w):
        if maze[s_y][s_x] == "#":
            continue
        check = []
        Q.append((s_y,s_x))
        check.append((s_y,s_x))
        point_list[s_x+s_y*w][s_x+s_y*w] = 0
        while Q:
            y, x = Q.popleft()
            if y == 0:
                pass
            elif maze[y-1][x]=="#":
                pass
            else:
                point_list[s_x+s_y*w][x+(y-1)*w] = min(point_list[s_x+s_y*w][x+(y-1)*w],point_list[s_x+s_y*w][x+y*w]+1)
                if (y-1,x) in check:
                    pass
                else:
                    check.append((y-1,x))
                    Q.append((y-1,x))
                    

            if y == h-1 :
                pass
            elif maze[y+1][x]=="#":
                pass
            else:
                point_list[s_x+s_y*w][x+(y+1)*w] = min(point_list[s_x+s_y*w][x+(y+1)*w],point_list[s_x+s_y*w][x+y*w]+1)
                if (y+1,x) in check:
                    pass
                else:
                    check.append((y+1,x))
                    Q.append((y+1,x))
                    

            if x==0:
                pass
            elif maze[y][x-1]=="#":
                pass
            else:
                point_list[s_x+s_y*w][(x-1)+y*w] = min(point_list[s_x+s_y*w][(x-1)+y*w],point_list[s_x+s_y*w][x+y*w]+1)
                if (y,x-1) in check:
                    pass
                else:
                    check.append((y,x-1))
                    Q.append((y,x-1))
                    

            if x==w-1:
                pass
            elif maze[y][x+1]=="#":
                pass
            else:
                point_list[s_x+s_y*w][(x+1)+y*w] = min(point_list[s_x+s_y*w][(x+1)+y*w],point_list[s_x+s_y*w][x+y*w]+1)
                if (y,x+1) in check:
                    pass
                else:
                    check.append((y,x+1))
                    Q.append((y,x+1))
                    
max_list = []
for i in range(w*h):
    tmp = set(point_list[i])
    if min(tmp)==w*h:
        continue
    if w*h in tmp:
        tmp.remove(w*h)
    max_list.append(max(tmp))

ans = max(max_list)
print(ans)

### FIXED CODE ###

# from collections import deque

INF = float('inf')

h,w = map(int, input().split())

point_list = []
for i in range(w*h):
    point_list.append([w*h]*w*h)
maze = []

Q = []

for i in range(h):
    tmp = list(input())
    maze.append(tmp)

for s_y in range(h):
    for s_x in range(w):
        if maze[s_y][s_x] == "#":
            continue
        check = []
        Q.append((s_y,s_x))
        check.append((s_y,s_x))
        point_list[s_x+s_y*w][s_x+s_y*w] = 0
        while Q:
            y, x = Q.pop(0)
            if y == 0:
                pass
            elif maze[y-1][x]=="#":
                pass
            else:
                point_list[s_x+s_y*w][x+(y-1)*w] = min(point_list[s_x+s_y*w][x+(y-1)*w],point_list[s_x+s_y*w][x+y*w]+1)
                if (y-1,x) in check:
                    pass
                else:
                    check.append((y-1,x))
                    Q.append((y-1,x))
                    

            if y == h-1 :
                pass
            elif maze[y+1][x]=="#":
                pass
            else:
                point_list[s_x+s_y*w][x+(y+1)*w] = min(point_list[s_x+s_y*w][x+(y+1)*w],point_list[s_x+s_y*w][x+y*w]+1)
                if (y+1,x) in check:
                    pass
                else:
                    check.append((y+1,x))
                    Q.append((y+1,x))
                    

            if x==0:
                pass
            elif maze[y][x-1]=="#":
                pass
            else:
                point_list[s_x+s_y*w][(x-1)+y*w] = min(point_list[s_x+s_y*w][(x-1)+y*w],point_list[s_x+s_y*w][x+y*w]+1)
                if (y,x-1) in check:
                    pass
                else:
                    check.append((y,x-1))
                    Q.append((y,x-1))
                    

            if x==w-1:
                pass
            elif maze[y][x+1]=="#":
                pass
            else:
                point_list[s_x+s_y*w][(x+1)+y*w] = min(point_list[s_x+s_y*w][(x+1)+y*w],point_list[s_x+s_y*w][x+y*w]+1)
                if (y,x+1) in check:
                    pass
                else:
                    check.append((y,x+1))
                    Q.append((y,x+1))
                    
max_list = []
for i in range(w*h):
    tmp = set(point_list[i])
    if min(tmp)==w*h:
        continue
    if w*h in tmp:
        tmp.remove(w*h)
    max_list.append(max(tmp))

ans = max(max_list)
print(ans)