+ptllnd_tx_t *
+ptllnd_find_timed_out_tx(ptllnd_peer_t *peer)
+{
+ time_t now = cfs_time_current_sec();
+ struct list_head *tmp;
+
+ list_for_each(tmp, &peer->plp_txq) {
+ ptllnd_tx_t *tx = list_entry(tmp, ptllnd_tx_t, tx_list);
+
+ if (tx->tx_deadline < now)
+ return tx;
+ }
+
+ list_for_each(tmp, &peer->plp_activeq) {
+ ptllnd_tx_t *tx = list_entry(tmp, ptllnd_tx_t, tx_list);
+
+ if (tx->tx_deadline < now)
+ return tx;
+ }
+
+ return NULL;
+}
+
+void
+ptllnd_check_peer(ptllnd_peer_t *peer)
+{
+ ptllnd_tx_t *tx = ptllnd_find_timed_out_tx(peer);
+
+ if (tx == NULL)
+ return;
+
+ CERROR("%s: timed out\n", libcfs_id2str(peer->plp_id));
+ ptllnd_close_peer(peer, -ETIMEDOUT);
+}
+
+void
+ptllnd_watchdog (lnet_ni_t *ni, time_t now)
+{
+ ptllnd_ni_t *plni = ni->ni_data;
+ const int n = 4;
+ int p = plni->plni_watchdog_interval;
+ int chunk = plni->plni_peer_hash_size;
+ int interval = now - (plni->plni_watchdog_nextt - p);
+ int i;
+ struct list_head *hashlist;
+ struct list_head *tmp;
+ struct list_head *nxt;
+
+ /* Time to check for RDMA timeouts on a few more peers:
+ * I try to do checks every 'p' seconds on a proportion of the peer
+ * table and I need to check every connection 'n' times within a
+ * timeout interval, to ensure I detect a timeout on any connection
+ * within (n+1)/n times the timeout interval. */
+
+ LASSERT (now >= plni->plni_watchdog_nextt);
+
+ if (plni->plni_timeout > n * interval) { /* Scan less than the whole table? */
+ chunk = (chunk * n * interval) / plni->plni_timeout;
+ if (chunk == 0)
+ chunk = 1;
+ }
+
+ for (i = 0; i < chunk; i++) {
+ hashlist = &plni->plni_peer_hash[plni->plni_watchdog_peeridx];
+
+ list_for_each_safe(tmp, nxt, hashlist) {
+ ptllnd_check_peer(list_entry(tmp, ptllnd_peer_t, plp_list));
+ }
+
+ plni->plni_watchdog_peeridx = (plni->plni_watchdog_peeridx + 1) %
+ plni->plni_peer_hash_size;
+ }
+
+ plni->plni_watchdog_nextt = now + p;
+}
+