#include <bits/stdc++.h>
using namespace std;

int main() {
	cin.tie(0);
	ios::sync_with_stdio(false);
	int H, W;
	char tmp;

	scanf("%d %d", &H, &W);
	scanf("%c", &tmp);

	vector<vector<int>> S(H, vector<int>(W));
	vector<vector<pair<int, bool>>> d(
	    H, vector<pair<int, bool>>(W, make_pair(H * W, false)));

	int count = 0;

	for (int i = 0; i < H; i++) {
		for (int j = 0; j < W; j++) {
			scanf("%c", &tmp);
			if (tmp == '.') {
				S[i][j] = 1;
				// d[i][j].second = false;
			} else {
				S[i][j] = 0;
				d[i][j].second = true;
			}
		}
		scanf("%c", &tmp);
	}
	// printf("count = %d\n", count);

	int max_max_d = 0;
	for (int ii = 0; ii < H; ii++) {
		for (int jj = 0; jj < W; jj++) {
			if (S[ii][jj] == 0) {
				continue;
			}
			/* 初期化 */

			for (int i = 0; i < H; i++) {
				for (int j = 0; j < W; j++) {
					if (S[i][j] == 1) {
						d[i][j].first = H * W;
						d[i][j].second = false;
					}
				}
			}
			pair<int, int> check_pos = make_pair(ii, jj);
			d[ii][jj].first = 0;
			int d_pl;

			while (true) {
				// printf("check (%d,%d)\n", check_pos.first, check_pos.second);
				d[check_pos.first][check_pos.second].second = true;
				// if (check_pos.first == H - 1 && check_pos.second == W - 1) {
				// 	break;
				// }
				d_pl = d[check_pos.first][check_pos.second].first + 1;
				for (auto i :
				     {make_pair(check_pos.first, check_pos.second - 1),
				      make_pair(check_pos.first, check_pos.second + 1),
				      make_pair(check_pos.first - 1, check_pos.second),
				      make_pair(check_pos.first + 1, check_pos.second)}) {
					// printf("(%d, %d) check\n", i.first, i.second);
					if (i.first < 0 || i.first >= H || i.second < 0 ||
					    i.second >= W) {
						// printf("out of range\n");
						continue;
					}
					if (d[i.first][i.second].second == true) {
						// printf("already check\n");
						continue;
					}
					// printf("min(%d,%d)\n", d[i.first][i.second].first, d_pl);
					d[i.first][i.second].first =
					    min(d[i.first][i.second].first, d_pl);
				}

				int min_d = H * W;
				for (int i = 0; i < H; i++) {
					for (int j = 0; j < W; j++) {
						// printf("(%d, %d)\n", i, j);
						if (d[i][j].second == true) {
							// printf("(%d, %d) true\n", i, j);
							continue;
						}
						// printf("d[i][j].first = %d min_d = %d\n",
						// d[i][j].first,
						//    min_d);
						if (d[i][j].first < min_d) {
							min_d = d[i][j].first;
							check_pos = make_pair(i, j);
							// printf("change (%d,%d)\n", check_pos.first,
							//    check_pos.second);
						}
					}
				}
				if (min_d == H * W) {
					goto finish;
				}
			}
		finish:
			// printf("retult = %d\n", d[H - 1][W - 1].first);

			/* 最大距離 */
			int max_d = 0;
			for (int i = 0; i < H; i++) {
				for (int j = 0; j < W; j++) {
					// printf("(%d, %d)\n", i, j);
					if (S[i][j] == 0) {
						// printf("(%d, %d) true\n", i, j);
						// printf("#");
						continue;
					}
					// printf("%d", d[i][j]);
					if (d[i][j].first > max_d) {
						max_d = d[i][j].first;
						// printf("change (%d,%d)\n", check_pos.first,
						//    check_pos.second);
					}
				}
				// printf("\n");
			}
			max_max_d = max(max_d, max_max_d);
			// printf("(%d %d) %d %d\n", ii, jj, max_d, max_max_d);
		}
	}

	printf("%d", max_max_d);

	return 0;
}

Measured memory_bytes: 256