patch-2.4.7 linux/net/irda/irlmp_event.c
Next file: linux/net/irda/irproc.c
Previous file: linux/net/irda/irlmp.c
Back to the patch index
Back to the overall index
- Lines: 107
- Date:
Wed Jul 4 11:50:38 2001
- Orig file:
v2.4.6/linux/net/irda/irlmp_event.c
- Orig date:
Sat May 19 17:47:55 2001
diff -u --recursive --new-file v2.4.6/linux/net/irda/irlmp_event.c linux/net/irda/irlmp_event.c
@@ -379,13 +379,23 @@
irlmp_start_idle_timer(self, LM_IDLE_TIMEOUT);
else {
/* No more connections, so close IrLAP */
- irlmp_next_lap_state(self, LAP_STANDBY);
+
+ /* We don't want to change state just yet, because
+ * we want to reflect accurately the real state of
+ * the LAP, not the the state we whish it was in,
+ * so that we don't loose LM_LAP_CONNECT_REQUEST.
+ * In some cases, IrLAP won't close the LAP
+ * immediately. For example, it might still be
+ * retrying packets or waiting for the pf bit.
+ * As the LAP always send a DISCONNECT_INDICATION
+ * in PCLOSE or SCLOSE, just change state on that.
+ * Jean II */
irlap_disconnect_request(self->irlap);
}
break;
case LM_LAP_IDLE_TIMEOUT:
if (HASHBIN_GET_SIZE(self->lsaps) == 0) {
- irlmp_next_lap_state(self, LAP_STANDBY);
+ /* Same reasoning as above - keep state */
irlap_disconnect_request(self->irlap);
}
break;
@@ -472,8 +482,6 @@
irlmp_start_watchdog_timer(self, 5*HZ);
break;
case LM_CONNECT_INDICATION:
- irlmp_next_lsap_state(self, LSAP_CONNECT_PEND);
-
if (self->conn_skb) {
WARNING(__FUNCTION__
"(), busy with another request!\n");
@@ -481,7 +489,20 @@
}
self->conn_skb = skb;
+ irlmp_next_lsap_state(self, LSAP_CONNECT_PEND);
+
irlmp_do_lap_event(self->lap, LM_LAP_CONNECT_REQUEST, NULL);
+
+ /* Start watchdog timer
+ * This is not mentionned in the spec, but there is a rare
+ * race condition that can get the socket stuck.
+ * If we receive this event while our LAP is closing down,
+ * the LM_LAP_CONNECT_REQUEST get lost and we get stuck in
+ * CONNECT_PEND state forever.
+ * Anyway, it make sense to make sure that we always have
+ * a backup plan. 1 second is plenty (should be immediate).
+ * Jean II */
+ irlmp_start_watchdog_timer(self, 1*HZ);
break;
default:
IRDA_DEBUG(2, __FUNCTION__ "(), Unknown event %s\n",
@@ -533,6 +554,16 @@
irlmp_next_lsap_state(self, LSAP_DATA_TRANSFER_READY);
break;
+ case LM_WATCHDOG_TIMEOUT:
+ /* May happen, who knows...
+ * Jean II */
+ IRDA_DEBUG(0, __FUNCTION__ "() WATCHDOG_TIMEOUT!\n");
+
+ /* Here, we should probably disconnect proper */
+ self->dlsap_sel = LSAP_ANY;
+ self->conn_skb = NULL;
+ irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
+ break;
default:
IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %s\n",
irlmp_event[event]);
@@ -563,6 +594,15 @@
case LM_CONNECT_REQUEST:
/* Keep state */
break;
+ case LM_CONNECT_INDICATION:
+ /* Will happen in some rare cases when the socket get stuck,
+ * the other side retries the connect request.
+ * We just unstuck the socket - Jean II */
+ IRDA_DEBUG(0, __FUNCTION__ "(), LM_CONNECT_INDICATION, "
+ "LSAP stuck in CONNECT_PEND state...\n");
+ /* Keep state */
+ irlmp_do_lap_event(self->lap, LM_LAP_CONNECT_REQUEST, NULL);
+ break;
case LM_CONNECT_RESPONSE:
IRDA_DEBUG(0, __FUNCTION__ "(), LM_CONNECT_RESPONSE, "
"no indication issued yet\n");
@@ -581,6 +621,17 @@
self->conn_skb = NULL;
irlmp_connect_indication(self, skb);
+ break;
+ case LM_WATCHDOG_TIMEOUT:
+ /* Will happen in some rare cases because of a race condition.
+ * Just make sure we don't stay there forever...
+ * Jean II */
+ IRDA_DEBUG(0, __FUNCTION__ "() WATCHDOG_TIMEOUT!\n");
+
+ /* Go back to disconnected mode, keep the socket waiting */
+ self->dlsap_sel = LSAP_ANY;
+ self->conn_skb = NULL;
+ irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
break;
default:
IRDA_DEBUG(0, __FUNCTION__ "Unknown event %s\n",
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)