#define STOPIT
#include<bits/stdc++.h>
#define rep(i,n,m) for(int i = (n); i <(m); i++)
#define rrep(i,n,m) for(int i = (n) - 1; i >=(m); i--)
using namespace std;
using ll = long long;
using tiii = tuple<int, int, int>;

void debug_impl() { cerr << endl; }
template <typename Head, typename... Tail>
void debug_impl(Head head, Tail... tail) { cerr << " " << head; debug_impl(tail...); }
#ifndef STOPIT
    #define debug(...)\
    do {\
        cerr << boolalpha << "[" << #__VA_ARGS__ << "]:";\
        debug_impl(__VA_ARGS__);\
        cerr << std::noboolalpha;\
    } while (false)
#else
    #define debug(...) {}
#endif

template < typename Container, typename Value = typename Container::value_type, enable_if_t<!is_same< Container, string >::value, nullptr_t> = nullptr>
istream& operator>> (istream& is, Container& v)
  { for (auto & x : v) { is >> x; } return is; }

template < typename Container, typename Value = typename Container::value_type, enable_if_t<!is_same< Container, string >::value, nullptr_t> = nullptr >
ostream& operator<< (ostream& os, Container const& v) {
  os << "{";
  for (auto it = v.begin(); it != v.end(); it++)
    {os << (it != v.begin() ? "," : "") << *it;}
  return os << "}";
}

const int INF = 1000000000;


int main()
{
    // read input
    int H, W;
    cin >> H >> W;
    vector<string> grid(H);
    rep(i,0,H) cin >> grid[i];

    int maxd = 0;
    // rep(i, 0, H)
        // rep(j, 0, W)
        {
            int i=2;
            int j=0;
            // do dfs
            debug("***");
            vector<vector<bool>> visited(H, vector<bool>(W, false));
            queue<tiii> que;
            que.push(make_tuple(i, j, 0));
            while (que.size()>0)
            {
                // get now
                int y, x, d;
                tie(y, x, d) = que.front();
                que.pop();

                // check
                if (y<0 or H<=y) continue;
                if (x<0 or W<=x) continue;
                if (grid[y][x]=='#') continue;
                if (visited[y][x]) continue;
                visited[y][x] = true;
                debug(y,x,d);

                // update distance
                maxd = max(maxd, d);

                // move to next
                que.push(make_tuple(y+1,x,d+1));
                que.push(make_tuple(y-1,x,d+1));
                que.push(make_tuple(y,x+1,d+1));
                que.push(make_tuple(y,x-1,d+1));
            }
        }

    cout << maxd << endl;
    return 0;
}