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

class Program
{
  static void Main()
  {
    int[] dx = {0, 1, 0, -1};
    int[] dy = {1, 0, -1, 0}; 
    
    var read = Console.ReadLine().Split().Select(int.Parse).ToArray();
    int h = read[0], w = read[1];
    var s = new string[h];
    for (int i = 0; i < h; i++)
      s[i] = Console.ReadLine();
    
    int start = 0;
    while (s[start / w][start % w] != '.')
      start++;
    var now = new Point()
    {
      x = start % w,
      y = start / w
    };
    
    var max = now;
    
    {
      var que = new Queue<Point>();
      que.Enqueue(now);
      var costs = new Dictionary<Point, int>();
      costs[now] = 0;
      
      while (que.Any())
      {
        now = que.Dequeue();      
        for (int i = 0; i < 4; i++)
        {
          var next = new Point()
          {
            x = now.x + dx[i],
            y = now.y + dy[i]
          };
          if (next.x < 0 || next.x >= w) continue;
          if (next.y < 0 || next.y >= h) continue;
          if (costs.ContainsKey(next)) continue;
          if (s[next.y][next.x] == '#') continue;
          costs[next] = costs[now] + 1;
          if (costs[max] < costs[next]) max = next;
          que.Enqueue(next);
        }
      }
    }
    
    now = max;
   
    {
      var que = new Queue<Point>();
      que.Enqueue(now);
      var costs = new Dictionary<Point, int>();
      costs[now] = 0;
      
      while (que.Any())
      {
        now = que.Dequeue();      
        for (int i = 0; i < 4; i++)
        {
          var next = new Point()
          {
            x = now.x + dx[i],
            y = now.y + dy[i]
          };
          if (next.x < 0 || next.x >= w) continue;
          if (next.y < 0 || next.y >= h) continue;
          if (costs.ContainsKey(next)) continue;
          if (s[next.y][next.x] == '#') continue;
          costs[next] = costs[now] + 1;
          if (costs[max] < costs[next]) max = next;
          que.Enqueue(next);
        }
      }
      
      Console.WriteLine(costs[max]);
    }
  }
}

struct Point
{
  public int x;
  public int y;
}