#![allow(unused_imports)]
use std::cmp::*;
use std::collections::*;
use itertools::Itertools;
use num::clamp;
use proconio::{input, marker::*, fastout};
use superslice::*;

#[fastout()]
fn main() {
    input! {
        h: usize, w: usize,
        ss: [Chars; h]
    }

    let mut roads = Vec::new();
    for y in 0usize..h {
        for x in 0usize..w {
            if ss[y][x] == '.' {
                roads.push((x, y));
            }
        }
    }

    let mut ans = 0;
    for i in 0..roads.len() {
        let (sx, sy) = roads[i];
        for j in i+1..roads.len() {
            let (ex,ey) = roads[j];
            let mut que = VecDeque::new();
            let mut memo = vec![vec![false; w]; h];
            memo[sy][sx] = true;
            que.push_back((sx, sy, 0));
            'outer: while let Some((x, y, count)) = que.pop_front() {
                let d = [(0, -1), (0, 1), (-1, 0), (1, 0)];
                for &(dx, dy) in d.iter() {
                    let x = clamp(x as i64 + dx, 0, w as i64 - 1) as usize; 
                    let y = clamp(y as i64 + dy, 0, h as i64 - 1) as usize;
                    if ss[y][x] == '#' {
                        continue;
                    }
                    if x == ex && y == ey {
                        ans = max(ans, count+1);
                        break 'outer;
                    }
                    if !memo[y][x] {
                        que.push_back((x, y, count+1));
                        memo[y][x] = true;
                    }
                }
            }
        }
    }
    println!("{}", ans);

}
