### BUGGY CODE ###

import copy
from collections import deque
h, w = map(int, input().split())
road = [0]*h
for i in range(h):
  road[i] = input()

def judge(i, j):
  ans = []
  if i != 0 and road[i-1][j] == ".":
    ans.append([[i, j], [i-1, j]])
  if i != h-1 and road[i+1][j] == ".":
    ans.append([[i, j], [i+1, j]])
  if j != 0 and road[i][j-1] == ".":
    ans.append([[i, j], [i, j-1]])
  if j != w-1 and road[i][j+1] == ".":
    ans.append([[i, j], [i, j+1]])
  return ans

already = [[False]*w for i in range(h)]
for i in range(h):
  for j in range(w):
    if road[i][j] == "#":
      already[i][j] = True
ans = 0
for i in range(h):
  for j in range(w):
    if road[i][j] == "#":
      continue
    
    yet = copy.deepcopy(already)
    yet[i][j] = True
    not_yet = deque(judge(i, j))
    depth = [[0]*w for i in range(h)]
    
    while not_yet:
      key = not_yet[0]
      bef_i, bef_j, aft_i, aft_j = key[0][0], key[0][1], key[1][0], key[1][1]
      not_yet.popleft()
      depth[aft_i][aft_j] = depth[bef_i][bef_j] + 1
      yet[aft_i][aft_j] = True
      
      judgement = judge(aft_i, aft_j)
      for value in judgement:
        if yet[value[1][0]][value[1][1]]:
          continue
        not_yet.append(value)
    max_depth = 0
    for p in range(h):
      p_depth = max(depth[p])
      if max_depth < p_depth:
        max_depth = p_depth 
    if ans < max_depth:
      ans = max_depth
print(ans)

### FIXED CODE ###

import copy
from collections import deque
h, w = map(int, input().split())
mapping = [0]*h
for i in range(h):
  mapping[i] = input()

  
already = [[False]*w for i in range(h)]
for i in range(h):
  for j in range(w):
    if mapping[i][j] == "#":
      already[i][j] = True


ans = 0

for i in range(h):
  for j in range(w):
    if already[i][j]:
      continue
    
    yet = copy.deepcopy(already)
    yet[i][j] = True
    not_yet = deque([])
    
    depth = [[0]*w for i in range(h)]
    
    if i != 0 and not yet[i-1][j]:
        not_yet.append([i-1, j])
        depth[i-1][j] = 1
        yet[i-1][j] = True
    if i != h-1 and not yet[i+1][j]:
        not_yet.append([i+1, j])
        depth[i+1][j] = 1
        yet[i+1][j] = True
    if j != 0 and not yet[i][j-1]:
        not_yet.append([i, j-1])
        depth[i][j-1] = 1
        yet[i][j-1] = True
    if j != w-1 and not yet[i][j+1]:
        not_yet.append([i, j+1])
        depth[i][j+1] = 1
        yet[i][j+1] = True
    
    while len(not_yet) > 0:
        key = not_yet.popleft()
        a, b = key[0], key[1]
        
        if a != 0 and not yet[a-1][b]:
            not_yet.append([a-1, b])
            yet[a-1][b] = True
            depth[a-1][b] = depth[a][b]+1
            
        if a != h-1 and not yet[a+1][b]:
            not_yet.append([a+1, b])
            yet[a+1][b] = True
            depth[a+1][b] = depth[a][b]+1
            
        if b != 0 and not yet[a][b-1]:
            not_yet.append([a, b-1])
            yet[a][b-1] = True
            depth[a][b-1] = depth[a][b]+1
            
        if b != w-1 and not yet[a][b+1]:
            not_yet.append([a, b+1])
            yet[a][b+1] = True
            depth[a][b+1] = depth[a][b]+1
            
    for x in range(h):
        for y in range(w):
            if ans < depth[x][y]:
                ans = depth[x][y]
print(ans)