#include <bits/stdc++.h>
template <typename T>
class Matrix {
 public:
  Matrix(std::size_t N, std::size_t M)
      : m_data(N * M, T()), m_rows(N), m_cols(M) {}
  inline T *operator[](int i) { return &m_data[i * m_cols]; }
  inline T const *operator[](int i) const { return &m_data[i * m_cols]; }
  inline std::size_t rows() const { return m_rows; }
  inline std::size_t cols() const { return m_cols; }

 private:
  std::vector<T> m_data;
  std::size_t m_rows;
  std::size_t m_cols;
};
template <typename T>
std::ostream &operator<<(std::ostream &os, const Matrix<T> &matrix) {
  for (std::size_t i = 0; i < matrix.rows(); ++i) {
    for (std::size_t j = 0; j < matrix.cols(); ++j) {
      os << std::left << std::setw(5) << matrix[i][j];
    }
    os << std::endl;
  }
  return os;
}
using namespace std;
void plb() { cout << "-------------------------------------------\n"; }
void printVb(vector<bool> v) {
  for (const auto &n : v) {
    cout << n << ", ";
  }
  cout << "\n";
}
void printVc(vector<char> v) {
  for (const auto &n : v) {
    cout << n << ", ";
  }
  cout << "\n";
}
void printVi(vector<int> v) {
  for (const auto &n : v) {
    cout << n << ", ";
  }
  cout << "\n";
}
void printVl(vector<long> v) {
  for (const auto &n : v) {
    cout << n << ", ";
  }
  cout << "\n";
}
void printVii(vector<pair<int, int>> v) {
  for (const auto &p : v) {
    cout << "(" << p.first << ", " << p.second << "), ";
  }
  cout << "\n";
}
vector<pair<int, int>> o3{{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
int main() {
  int row, col;
  cin >> row >> col;
  int startX, startY;
  Matrix<char> m(row, col);
  for (int i = 0; i < row; ++i) {
    for (int j = 0; j < col; ++j) {
      cin >> m[i][j];
      if (m[i][j] == '.') {
        startX = i;
        startY = j;
      }
    }
  }
  Matrix<int> visited(row, col);
  Matrix<int> dist(row, col);
  for (int i = 0; i < row; ++i) {
    for (int j = 0; j < col; ++j) {
      visited[i][j] = 0;
      dist[i][j] = -1;
    }
  }
  deque<pair<int, int>> dq;
  dq.push_back({startX, startY});
  visited[startX][startY] = true;
  dist[startX][startY] = 0;
  while (!dq.empty()) {
    pair<int, int> cur = dq.front();
    dq.pop_front();
    for (const auto &offset : o3) {
      int x = cur.first + offset.first;
      int y = cur.second + offset.second;
      if (x < 0 || x >= row || y < 0 || y >= col) continue;
      if (m[x][y] != '.') continue;
      if (!visited[x][y]) {
        dist[x][y] = dist[cur.first][cur.second] + 1;
        visited[x][y] = true;
        dq.emplace_back(x, y);
      }
    }
  }
  int largest = 0;
  int Lx, Ly;
  for (int i = 0; i < row; ++i) {
    for (int j = 0; j < col; ++j) {
      if (dist[i][j] > largest) {
        largest = dist[i][j];
        Lx = i;
        Ly = j;
      }
    }
  }
  for (int i = 0; i < row; ++i) {
    for (int j = 0; j < col; ++j) {
      visited[i][j] = 0;
      dist[i][j] = -1;
    }
  }
  dq.clear();
  dq.push_back({Lx, Ly});
  visited[Lx][Ly] = true;
  dist[Lx][Ly] = 0;
  while (!dq.empty()) {
    pair<int, int> cur = dq.front();
    dq.pop_front();
    for (const auto &offset : o3) {
      int x = cur.first + offset.first;
      int y = cur.second + offset.second;
      if (x < 0 || x >= row || y < 0 || y >= col) continue;
      if (m[x][y] != '.') continue;
      if (!visited[x][y]) {
        dist[x][y] = dist[cur.first][cur.second] + 1;
        visited[x][y] = true;
        dq.emplace_back(x, y);
      }
    }
  }
  largest = 0;
  for (int i = 0; i < row; ++i) {
    for (int j = 0; j < col; ++j) {
      if (dist[i][j] > largest) {
        largest = dist[i][j];
      }
    }
  }
  cout << largest << "\n";
}
