#define _USE_MATH_DEFINES
#include <iostream>
#include <iomanip>
#include <cmath>
#include <stack>
#include <vector>
#include <algorithm>
#include <string>
#include <map>
#include <queue>
#include <set>
#include <fstream>
#include <list>
#include <deque>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <cassert>
#include <ctime>
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>
//#include <ext/pb_ds/detail/standard_policies.hpp>

using namespace std;
#pragma warning(disable : 4996)
#pragma comment(linker, "/STACK:16777216")
#define _DEBUG
#define vec vector
#define pb push_back
#define en '\n'
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> pll;
typedef pair<ll, ll> pull;
typedef pair<int, int> pii;
typedef pair<int, ll> pil;
typedef long double ld;
typedef unsigned int ui;
typedef map<int,int> mii;
typedef map<ll,ll> mll;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<vector<int>> vi2;
typedef vector<vector<ll>> vll2;
typedef vector<vector<ll>> matrix;
typedef vec<vec<vec<int>>> vi3;

#pragma warning(disable : 4996)
#pragma comment(linker, "/STACK:16777216")
#define pb push_back
#define en '\n'
#define for0(i,n) for(int i = 0;i<n;i++)
#define for1(i,n) for(int i = 1;i<n;i++)
#define all(x) (x).begin(),(x).end()
#define rall(x) (x).rbegin(),(x).rend()
#define vec vector
#define pii pair<int,int>
#define pll pair<ll,ll>
#define REP(a,i,b) for (int i = a;i<b;i++);

#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")

const int inf = 2000000000;
const ll linf = 5000000000000000000;
const ld LDINF = 2e18;
template<typename T> void print(vector<T>& a)
{
    for (int i = 0; i < a.size(); i++)
        cout << a[i] << ' ';
    cout << en;
}

template<typename T> void print(deque<T>& a)
{
    for (int i = 0; i < a.size(); i++)
        cout << a[i] << ' ';
    cout << en;
}

template<typename T> void print(vector<vector<T>>& a)
{
    for (int i = 0; i < a.size(); i++)
    {
        for (int j = 0; j < a[i].size(); j++)
            cout << a[i][j] << ' ';
        cout << en;
    }
}

template <typename T> void input(vector<T>& a)
{
    for (int i = 0; i < a.size(); i++)
        cin >> a[i];
}

template<typename T> void input(deque<T>& a)
{
    for (int i = 0; i < a.size(); i++)
        cin >> a[i];
}

template<typename T> void input(vector<vector<T>>& a)
{
    for (int i = 0; i < a.size(); i++)
        for (int j = 0; j < a[i].size(); j++)
            cin >> a[i][j];
}

ll mod = 1e9 + 7;

ll gcd(ll a, ll b){
    if(b == 0)
        return a;
    else
        return gcd(b, a % b);
}

int w, h;
vec<vec<char>> arr;
bool check(int x, int y, vec<vec<char>>&arr){
    if(x < 0 || x >= w || y < 0 || y >= h)
        return false;
    if(arr[x][y] == '#')
        return false;
    return true;
}

int ans = 0;

vec<int> dx = {1,-1,0,0};
vec<int> dy = {0,0,-1,1};

void bfs(int begx, int begy){
    queue<pii> q;
    vec<vec<int>> d(w, vec<int>(h, -1));
    d[begx][begy] = 0;
    q.push({begx, begy});
    while(!q.empty()){
        int x = q.front().first, y = q.front().second;
        q.pop();
        for0(i, 4){
            int nowx = x + dx[i];
            int nowy = y + dy[i];
            if(!check(nowx, nowy, arr) || d[nowx][nowy] !=-1)
                continue;
            d[nowx][nowy] = d[x][y] + 1;
            ans = max(ans, d[nowx][nowy]);
            q.push({nowx, nowy});
        }
    }
}

void solve(){
    cin >> w >> h;
    arr =vec<vec<char>>(w,vec<char>(h));
    input(arr);
    for(int i = 0; i < w; i++){
        for(int j = 0; j < h; j++){
            if(arr[i][j]!='#')
                bfs(i,j);
        }
    }
    cout << ans;
}

int main()
{
    
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    
#ifdef DEBUG
    freopen("input.txt", "r", stdin);
    freopen("input.txt", "r", stdin);
#endif
    // freopen("graph.in", "r", stdin);
    // freopen("graph.out", "w", stdout);
    
    int tst = 1;
   // cin >> tst;
    while(tst--)
        solve();
}





Measured memory_bytes: 256