#include <iostream>
#include <queue>
using namespace std;
const int H = 20;
const int INF = 999999999;
struct node{
    int cost;
    bool isvisit;
    bool ispath;
};

struct index{
    int h;
    int w;
};
node map[H][H];

void resetmap(int h, int w){
    for(int i = 0; i < h; i++){
        for(int j = 0; j < w; j++){
            map[i][j].isvisit = false;
            map[i][j].cost = INF;
        }
    }
}

int bfs(int h, int w, int i, int j){
    queue<index> memo;
    index ci;
    index tmpindex;
    int max = 0;
    
    ci.h = i;
    ci.w = j;
    map[i][j].isvisit = true;
    map[i][j].cost = 0;
    
    memo.push(ci);
    
    while(memo.size()){
        ci = memo.front();
        memo.pop();
        
        if(ci.h >= 0 && ci.h < h && ci.w-1 >= 0 && ci.w < w && map[ci.h][ci.w-1].ispath){
            if(map[ci.h][ci.w-1].cost > map[ci.h][ci.w].cost +1){
                map[ci.h][ci.w-1].cost = map[ci.h][ci.w].cost +1;
                if(max < map[ci.h][ci.w-1].cost) max = map[ci.h][ci.w-1].cost;
            }
            if(!map[ci.h][ci.w-1].isvisit){
                map[ci.h][ci.w-1].isvisit = true;
                tmpindex.h = ci.h;
                tmpindex.w = ci.w-1;
                memo.push(tmpindex);
            }
        }
        
        if(ci.h >= 0 && ci.h < h && ci.w+1 >= 0 && ci.w < w && map[ci.h][ci.w+1].ispath){
            if(map[ci.h][ci.w+1].cost > map[ci.h][ci.w].cost +1){
                map[ci.h][ci.w+1].cost = map[ci.h][ci.w].cost +1;
                if(max < map[ci.h][ci.w+1].cost) max = map[ci.h][ci.w+1].cost;
            }
            if(!map[ci.h][ci.w+1].isvisit){
                map[ci.h][ci.w+1].isvisit = true;
                tmpindex.h = ci.h;
                tmpindex.w = ci.w+1;
                memo.push(tmpindex);
            }
        }
        
        if(ci.h-1 >= 0 && ci.h-1 < h && ci.w >= 0 && ci.w < w && map[ci.h-1][ci.w].ispath){
            if(map[ci.h-1][ci.w].cost > map[ci.h][ci.w].cost +1){
                map[ci.h-1][ci.w].cost = map[ci.h][ci.w].cost +1;
                if(max < map[ci.h-1][ci.w].cost) max = map[ci.h-1][ci.w].cost;
            }
            if(!map[ci.h-1][ci.w].isvisit){
                map[ci.h-1][ci.w].isvisit = true;
                tmpindex.h = ci.h-1;
                tmpindex.w = ci.w;
                memo.push(tmpindex);
            }
        }
        
        if(ci.h+1 >= 0 && ci.h+1 < h && ci.w >= 0 && ci.w < w && map[ci.h+1][ci.w].ispath){
            if(map[ci.h+1][ci.w].cost > map[ci.h][ci.w].cost +1){
                map[ci.h+1][ci.w].cost = map[ci.h][ci.w].cost +1;
                if(max < map[ci.h+1][ci.w].cost) max = map[ci.h+1][ci.w].cost;
            }
            if(!map[ci.h+1][ci.w].isvisit){
                map[ci.h+1][ci.w].isvisit = true;
                tmpindex.h = ci.h+1;
                tmpindex.w = ci.w;
                memo.push(tmpindex);
            }
        }
    }
    
    return max;
}

int main(void){
    int h, w;
    char tmp;
    
    cin >> h >> w;
    for(int i = 0; i < H; i++){
        for(int j = 0; j < H; j++){
            map[i][j].ispath = false;
            map[i][j].isvisit = false;
            map[i][j].cost = INF;
        }
    }
    for(int i = 0; i < h; i++){
        for(int j = 0; j < w; j++){
            cin >> tmp;
            if(tmp == '.'){
                map[i][j].ispath = true;
            }
        }
    }
    
    int max = 0;
    int temp;
    for(int i = 0; i < h; i++){
        for(int j = 0; j < w; j++){
            temp = -1;
            if(map[i][j].ispath){
                temp = bfs(h, w, i, j);
                max = (temp > max) ? temp : max;
                resetmap(h, w);
            }
            
            //cout << temp << " ";
        }
        //cout << endl;
    }
    
    cout << max << endl;
    
    return 0;
}