diff options
author | G. Liakhovetski <gl@dsa-ac.de> | 2007-06-08 22:15:17 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2007-06-08 22:15:17 -0400 |
commit | c0cfe7faa12f189ef1024fce5a710791d0062355 (patch) | |
tree | e3f6e22de451d8d679235f8adea313a25c5de497 | |
parent | 81d84a94be8085475c3585596e52b06ccbedd922 (diff) |
[IrDA]: Fix Rx/Tx path race.
From: G. Liakhovetski <gl@dsa-ac.de>
We need to switch to NRM _before_ sending the final packet otherwise
we might hit a race condition where we get the first packet from the
peer while we're still in LAP_XMIT_P.
Signed-off-by: Samuel Ortiz <samuel@sortiz.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/irda/irlap.h | 17 | ||||
-rw-r--r-- | net/irda/irlap_event.c | 18 | ||||
-rw-r--r-- | net/irda/irlap_frame.c | 3 |
3 files changed, 20 insertions, 18 deletions
diff --git a/include/net/irda/irlap.h b/include/net/irda/irlap.h index f0248fb8e196..a3d370efb903 100644 --- a/include/net/irda/irlap.h +++ b/include/net/irda/irlap.h | |||
@@ -289,4 +289,21 @@ static inline void irlap_clear_disconnect(struct irlap_cb *self) | |||
289 | self->disconnect_pending = FALSE; | 289 | self->disconnect_pending = FALSE; |
290 | } | 290 | } |
291 | 291 | ||
292 | /* | ||
293 | * Function irlap_next_state (self, state) | ||
294 | * | ||
295 | * Switches state and provides debug information | ||
296 | * | ||
297 | */ | ||
298 | static inline void irlap_next_state(struct irlap_cb *self, IRLAP_STATE state) | ||
299 | { | ||
300 | /* | ||
301 | if (!self || self->magic != LAP_MAGIC) | ||
302 | return; | ||
303 | |||
304 | IRDA_DEBUG(4, "next LAP state = %s\n", irlap_state[state]); | ||
305 | */ | ||
306 | self->state = state; | ||
307 | } | ||
308 | |||
292 | #endif | 309 | #endif |
diff --git a/net/irda/irlap_event.c b/net/irda/irlap_event.c index 0b02073ffdf3..71c805506933 100644 --- a/net/irda/irlap_event.c +++ b/net/irda/irlap_event.c | |||
@@ -317,23 +317,6 @@ void irlap_do_event(struct irlap_cb *self, IRLAP_EVENT event, | |||
317 | } | 317 | } |
318 | 318 | ||
319 | /* | 319 | /* |
320 | * Function irlap_next_state (self, state) | ||
321 | * | ||
322 | * Switches state and provides debug information | ||
323 | * | ||
324 | */ | ||
325 | static inline void irlap_next_state(struct irlap_cb *self, IRLAP_STATE state) | ||
326 | { | ||
327 | /* | ||
328 | if (!self || self->magic != LAP_MAGIC) | ||
329 | return; | ||
330 | |||
331 | IRDA_DEBUG(4, "next LAP state = %s\n", irlap_state[state]); | ||
332 | */ | ||
333 | self->state = state; | ||
334 | } | ||
335 | |||
336 | /* | ||
337 | * Function irlap_state_ndm (event, skb, frame) | 320 | * Function irlap_state_ndm (event, skb, frame) |
338 | * | 321 | * |
339 | * NDM (Normal Disconnected Mode) state | 322 | * NDM (Normal Disconnected Mode) state |
@@ -1086,7 +1069,6 @@ static int irlap_state_xmit_p(struct irlap_cb *self, IRLAP_EVENT event, | |||
1086 | } else { | 1069 | } else { |
1087 | /* Final packet of window */ | 1070 | /* Final packet of window */ |
1088 | irlap_send_data_primary_poll(self, skb); | 1071 | irlap_send_data_primary_poll(self, skb); |
1089 | irlap_next_state(self, LAP_NRM_P); | ||
1090 | 1072 | ||
1091 | /* | 1073 | /* |
1092 | * Make sure state machine does not try to send | 1074 | * Make sure state machine does not try to send |
diff --git a/net/irda/irlap_frame.c b/net/irda/irlap_frame.c index 3c5a68e36414..3013c49ab975 100644 --- a/net/irda/irlap_frame.c +++ b/net/irda/irlap_frame.c | |||
@@ -798,16 +798,19 @@ void irlap_send_data_primary_poll(struct irlap_cb *self, struct sk_buff *skb) | |||
798 | self->vs = (self->vs + 1) % 8; | 798 | self->vs = (self->vs + 1) % 8; |
799 | self->ack_required = FALSE; | 799 | self->ack_required = FALSE; |
800 | 800 | ||
801 | irlap_next_state(self, LAP_NRM_P); | ||
801 | irlap_send_i_frame(self, tx_skb, CMD_FRAME); | 802 | irlap_send_i_frame(self, tx_skb, CMD_FRAME); |
802 | } else { | 803 | } else { |
803 | IRDA_DEBUG(4, "%s(), sending unreliable frame\n", __FUNCTION__); | 804 | IRDA_DEBUG(4, "%s(), sending unreliable frame\n", __FUNCTION__); |
804 | 805 | ||
805 | if (self->ack_required) { | 806 | if (self->ack_required) { |
806 | irlap_send_ui_frame(self, skb_get(skb), self->caddr, CMD_FRAME); | 807 | irlap_send_ui_frame(self, skb_get(skb), self->caddr, CMD_FRAME); |
808 | irlap_next_state(self, LAP_NRM_P); | ||
807 | irlap_send_rr_frame(self, CMD_FRAME); | 809 | irlap_send_rr_frame(self, CMD_FRAME); |
808 | self->ack_required = FALSE; | 810 | self->ack_required = FALSE; |
809 | } else { | 811 | } else { |
810 | skb->data[1] |= PF_BIT; | 812 | skb->data[1] |= PF_BIT; |
813 | irlap_next_state(self, LAP_NRM_P); | ||
811 | irlap_send_ui_frame(self, skb_get(skb), self->caddr, CMD_FRAME); | 814 | irlap_send_ui_frame(self, skb_get(skb), self->caddr, CMD_FRAME); |
812 | } | 815 | } |
813 | } | 816 | } |