using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        var input = Console.ReadLine().Split(' ');
        var ySize = int.Parse(input[0]);
        var xSize = int.Parse(input[1]);

        var maze = new Maze(xSize, ySize);

        for (var i = 0; i < ySize; i++)
        {
            var line = Console.ReadLine().ToCharArray();
            for (var j = 0; j < xSize; j++)
            {
                var isPath = line[j] == '.' ? true : false;
                maze.Map[j, i] = new Cell(j, i, isPath);
            }
        }

        var ans = 0;

        foreach(var startCell in maze.Map)
        {
            foreach(var goalCell in maze.Map)
            {
                if (startCell != goalCell && startCell.IsPath && goalCell.IsPath)
                {
                    var count = DepthFirstSearch.CheckExistPath(maze, startCell, goalCell);
                    if(ans < count)
                    {
                        ans = count;
                    }
                }
            }
        }

        Console.WriteLine(ans);
        Console.ReadLine();
    }
}

class DepthFirstSearch
{


    public static int CheckExistPath(Maze maze, Cell start, Cell goal)
    {
        //BFSの場合
        var list = new List<int[]>();

        list.Add(new int[2] { start.X, start.Y });

        //そもそも配列で持たせた方が良い？
        foreach (var cell in maze.Map)
        {
            cell.Visited = false;
            cell.Count = 0;
        }
        start.Visited = true;


        var finished = false;

        var count = 0;

        var goalX = goal.X;
        var goalY = goal.Y;

        var ans = 0;

        while (!finished)
        {
            if(list.Count == count)
            {
                finished = true;
                continue;
            }

            var cell = list[count];


            count++;


            var currentCount = maze.Map[cell[0], cell[1]].Count;


            var right = new int[2] { cell[0] + 1, cell[1] };
            if (cell[0] < maze.XSize -1) 
            {
                if (maze.Map[right[0], right[1]].IsPath && !maze.Map[right[0], right[1]].Visited)
                {
                    maze.Map[right[0], right[1]].Visited = true;
                    list.Add(new int[2] { right[0], right[1] });
                    maze.Map[right[0], right[1]].Count = currentCount + 1;
                }
            }
            var down = new int[2] { cell[0], cell[1] + 1 };
            if (cell[1] < maze.YSize - 1)
            {
                if (maze.Map[down[0], down[1]].IsPath && !maze.Map[down[0], down[1]].Visited)
                {
                    maze.Map[down[0], down[1]].Visited = true;
                    list.Add(new int[2] { down[0], down[1] });
                    maze.Map[down[0], down[1]].Count = currentCount + 1;
                }
            }
            var left = new int[2] { cell[0] - 1, cell[1] };
            if (cell[0] > 0)
            {
                if (maze.Map[left[0], left[1]].IsPath && !maze.Map[left[0], left[1]].Visited)
                {
                    maze.Map[left[0], left[1]].Visited = true;
                    list.Add(new int[2] { left[0], left[1] });
                    maze.Map[left[0], left[1]].Count = currentCount + 1;
                }
            }

            var up = new int[2] { cell[0], cell[1] - 1 };
            if (cell[1] > 0)
            {
                if (maze.Map[up[0], up[1]].IsPath && !maze.Map[up[0], up[1]].Visited)
                {
                    maze.Map[up[0], up[1]].Visited = true;
                    list.Add(new int[2] { up[0], up[1] });
                    maze.Map[up[0], up[1]].Count = currentCount + 1;
                }
            }

            if (maze.Map[goalX, goalY].Visited == true)
            {
                finished = true;
                ans = currentCount + 1;
            }


        }

        return ans;

    }

}

class Cell
{
    public int X { get; set; }
    public int Y { get; set; }
    public bool Visited { get; set; }
    public bool IsPath { get; set; }
    public int Count { get; set; }

    public Cell(int x, int y, bool isPath)
    {
        this.X = x;
        this.Y = y;
        this.Visited = false;
        this.IsPath = isPath;
    }
}

class Maze
{
    public int XSize { get; set; }
    public int YSize { get; set; }
    public Cell[,] Map { get; set; }

    public Maze(int xSize, int ySize)
    {
        this.XSize = xSize;
        this.YSize = ySize;
        this.Map = new Cell[xSize, ySize];
    }

    public void LoadMapData(int x, int y, bool isPath)
    {
        this.Map[x, y] = new Cell(x, y, isPath);
    }

}
