#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <bitset>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <string>
#include <vector>

using namespace std;
uint64_t gcd(uint64_t a, uint64_t b);
uint64_t lcm(uint64_t a, uint64_t b);

template <typename T>
static inline void ArrayInput(vector<T>& A) {
  for (auto itr = A.begin(); itr < A.end(); ++itr) cin >> *itr;
}

template <typename T>
static inline void ArrayPut(const vector<T>& A) {
  for (auto itr = A.begin(); itr < A.end(); ++itr) cout << *itr << " ";
  cout << endl;
}

bool Sec_compare(pair<uint64_t, uint64_t> a, pair<uint64_t, uint64_t> b) {
  if (a.second != b.second) {
    return a.second < b.second;
  } else {
    return a.first < b.first;
  }
}

int main() {
  int32_t H, W;
  cin >> H >> W;
  char S[20][20];
  for (uint32_t i = 0; i < H; ++i) {
    for (uint32_t j = 0; j < W; ++j) {
      cin >> S[i][j];
    }
  }
  int32_t Res = 0;
  for (int32_t gy = 0; gy < H; ++gy) {
    for (int32_t gx = 0; gx < W; ++gx) {
      if (S[gy][gx] == '#') continue;
      int32_t Score[20][20];
      for (uint32_t i = 0; i < H; ++i) {
        for (uint32_t j = 0; j < W; ++j) {
          if (S[i][j] == '#')
            Score[i][j] = -1;
          else
            Score[i][j] = 0;
        }
      }
      queue<pair<uint32_t, uint32_t>> next;
      next.push(make_pair(gy, gx));
      Score[gy][gx] = 1;
      while (!next.empty()) {
        pair<uint32_t, uint32_t> pos;
        pos = next.front();
        uint32_t tmp = Score[pos.first][pos.second];
        next.pop();
        if ((pos.first + 1) < H) {
          if (S[pos.first + 1][pos.second] == '.') {
            if (Score[pos.first + 1][pos.second] == 0) {
              Score[pos.first + 1][pos.second] = tmp + 1;
              next.push(make_pair(pos.first + 1, pos.second));
            }
          }
        }
        if (pos.first > 0) {
          if (S[pos.first - 1][pos.second] == '.') {
            if (Score[pos.first - 1][pos.second] == 0) {
              Score[pos.first - 1][pos.second] = tmp + 1;
              next.push(make_pair(pos.first - 1, pos.second));
            }
          }
        }
        if ((pos.second + 1) < W) {
          if (S[pos.first][pos.second + 1] == '.') {
            if (Score[pos.first][pos.second + 1] == 0) {
              Score[pos.first][pos.second + 1] = tmp + 1;
              next.push(make_pair(pos.first, pos.second + 1));
            }
          }
        }
        if (pos.second > 0) {
          if (S[pos.first][pos.second - 1] == '.') {
            if (Score[pos.first][pos.second - 1] == 0) {
              Score[pos.first][pos.second - 1] = tmp + 1;
              next.push(make_pair(pos.first, pos.second - 1));
            }
          }
        }
      }
      int32_t M_Score = 0;
      for (uint32_t i = 0; i < H; ++i) {
        for (uint32_t j = 0; j < W; ++j) {
          if (Score[i][j] > M_Score) M_Score = Score[i][j];
        }
      }
      if (Res < M_Score) Res = M_Score;
    }
  }
  cout << Res - 1 << endl;
  return 0;
}

uint64_t gcd(uint64_t a, uint64_t b) {
  if (a < b) {
    a ^= b;
    b ^= a;
    a ^= b;
  }

  return b ? gcd(b, a % b) : a;
}

uint64_t lcm(uint64_t a, uint64_t b) { return a * b / gcd(a, b); }

Measured memory_bytes: 256