use std::io::*;
use std::str::FromStr;

pub fn read<T: FromStr>() -> T {
    let stdin = stdin();
    let stdin = stdin.lock();
    let token: String = stdin
        .bytes()
        .map(|c| c.expect("failed to read char") as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().expect("failed to parse token")
}

pub fn read_n<T: FromStr>(n: usize) -> Vec<T> {
    read_n_logic::<T>(n, vec![])
}

pub fn read_n_logic<T: FromStr>(n: usize, mut a: Vec<T>) -> Vec<T> {
    match n {
        0 => a,
        _ => {
            a.push(read::<T>());
            read_n_logic(n - 1, a)
        }
    }
}
use std::cmp::{max, min};

fn main() {
    let mut h: usize = read();
    let mut w: usize = read();
    let mut map: Vec<Vec<char>> = vec![];
    let mut ans = 0;

    for _ in 0..h {
        let row: String = read();
        let row_chars: Vec<char> = row.chars().collect();
        map.push(row_chars)
    }

    for i in 0..h * w {
        let s_h = i / w;
        let s_w = i % w;

        if &map[s_h][s_w] == &'#' {
            continue;
        }

        let mut dammy_map: Vec<Vec<i64>> = vec![vec![std::i64::MAX; w]; h];
        dfs(&map, &mut dammy_map, h, w, s_h, s_w, 0);
        let mut longest = 0;

        for i in dammy_map {
            for j in i {
                if j == std::i64::MAX {
                    continue
                }
                longest = max(j, longest);
            }
        }

        ans = max(ans, longest);
    }
    println!("{}", ans);
}

fn dfs(
    map: &Vec<Vec<char>>,
    cnt_map: &mut Vec<Vec<i64>>,
    h: usize,
    w: usize,
    sh: usize,
    sw: usize,
    depth: i64,
) {
    if cnt_map[sh][sw] < depth {
        return;
    }
    cnt_map[sh][sw] = depth;

    if sh != 0 && map[sh - 1][sw] != '#' {
        dfs(map, cnt_map, h, w, sh - 1, sw, depth + 1)
    }

    if sw != 0 && map[sh][sw - 1] != '#' {
        dfs(map, cnt_map, h, w, sh, sw - 1, depth + 1)
    }

    if sh != h - 1 && map[sh + 1][sw] != '#' {
        dfs(map, cnt_map, h, w, sh + 1, sw, depth + 1)
    }

    if sw != w - 1 && map[sh][sw + 1] != '#' {
        dfs(map, cnt_map, h, w, sh, sw + 1, depth + 1)
    }
}
