### BUGGY CODE ###

h, w = map(int, input().split())
s = [list(input()) for _ in range(h)]
visited = [[0 for _ in range(w)] for _ in range(h)]
checkde = [[[[0 for _ in range(w)] for _ in range(h)] for _ in range(w)] for _ in range(h)]
# print(s)
for i in range(h):
    for j in range(w):
        if s[i][j] == "#":
            visited[i][j] = 1
import copy

ans = 0
for iS in range(h):
    for jS in range(w):
        for iG in range(h):
            for jG in range(w):
                if s[iS][jS] == "#" or s[iG][jG] == "#" or checkde[iG][jG][iS][jS]:
                    continue
                checkde[iS][jS][iG][jG] = 1
                checkde[iG][jG][iS][jS] = 1
                thisVisited = copy.deepcopy(visited)
                now = 0
                dis = 0
                next_point = [[iS, jS, dis]]
                thisVisited[iS][jS] = 1
                while now < len(next_point):
                    nowi = next_point[now][0]
                    nowj = next_point[now][1]
                    nowdis = next_point[now][2]
                    dis = max(nowdis, dis)
                    # print(nowi, nowj, iG, jG, nowdis)

                    if nowi == iG and nowj == jG:
                        ans = max(dis, ans)
                        break

                    if nowi != 0:
                        if thisVisited[nowi - 1][nowj] == 0:
                            next_point.append([nowi - 1, nowj, nowdis + 1])
                            thisVisited[nowi - 1][nowj] = 1

                    if nowi != h - 1:
                        if thisVisited[nowi + 1][nowj] == 0:
                            next_point.append([nowi + 1, nowj, nowdis + 1])
                            thisVisited[nowi + 1][nowj] = 1

                    if nowj != w - 1:
                        if thisVisited[nowi][nowj + 1] == 0:
                            next_point.append([nowi, nowj + 1, nowdis + 1])
                            thisVisited[nowi][nowj + 1] = 1

                    if nowj != 0:
                        if thisVisited[nowi][nowj - 1] == 0:
                            next_point.append([nowi, nowj - 1, nowdis + 1])
                            thisVisited[nowi][nowj - 1] = 1

                    now += 1
                # print(next_point)
# print(checkde)
print(ans)

### FIXED CODE ###

h, w = map(int, input().split())
s = [list(input()) for _ in range(h)]
visited = [[0 for _ in range(w)] for _ in range(h)]
disList = [[[[0 for _ in range(w)] for _ in range(h)] for _ in range(w)] for _ in range(h)]
# print(s)
for i in range(h):
    for j in range(w):
        if s[i][j] == "#":
            visited[i][j] = 1
import copy

ans = 0
for i in range(h):
    for j in range(w):
        nowdis = 0
        now = 0
        next_point = [[i, j, nowdis]]
        thisVisited = copy.deepcopy(visited)
        thisVisited[i][j] = 1
        if s[i][j] == "#":
            continue

        while now < len(next_point):
            nowi = next_point[now][0]
            nowj = next_point[now][1]
            nowdis = next_point[now][2]
            disList[i][j][nowi][nowj] = nowdis

            if nowi != 0:
                if thisVisited[nowi - 1][nowj] == 0:
                    next_point.append([nowi - 1, nowj, nowdis + 1])
                    thisVisited[nowi - 1][nowj] = 1

            if nowi != h - 1:
                if thisVisited[nowi + 1][nowj] == 0:
                    next_point.append([nowi + 1, nowj, nowdis + 1])
                    thisVisited[nowi + 1][nowj] = 1

            if nowj != w - 1:
                if thisVisited[nowi][nowj + 1] == 0:
                    next_point.append([nowi, nowj + 1, nowdis + 1])
                    thisVisited[nowi][nowj + 1] = 1

            if nowj != 0:
                if thisVisited[nowi][nowj - 1] == 0:
                    next_point.append([nowi, nowj - 1, nowdis + 1])
                    thisVisited[nowi][nowj - 1] = 1
            now += 1

# print(disList)
ans = 0
for i in disList:
    for j in i:
        for k in j:
            # print(k)
            ans = max(ans, max(k))

print(ans)