diff -u -p linux/include/net/irda/timer.d4.h linux/include/net/irda/timer.h --- linux/include/net/irda/timer.d4.h Mon Nov 17 15:39:13 2003 +++ linux/include/net/irda/timer.h Mon Nov 17 16:34:59 2003 @@ -40,14 +40,14 @@ struct lsap_cb; struct lap_cb; /* - * Timeout definitions, some defined in IrLAP p. 92 + * Timeout definitions, some defined in IrLAP 6.13.5 - p. 92 */ #define POLL_TIMEOUT (450*HZ/1000) /* Must never exceed 500 ms */ #define FINAL_TIMEOUT (500*HZ/1000) /* Must never exceed 500 ms */ /* - * Normally twice of p-timer. Note 3, IrLAP p. 60 suggests at least twice - * duration of the P-timer. + * Normally twice of p-timer. Note 3, IrLAP 6.3.11.2 - p. 60 suggests + * at least twice duration of the P-timer. */ #define WD_TIMEOUT (POLL_TIMEOUT*2) diff -u -p linux/net/irda/irlap_event.d4.c linux/net/irda/irlap_event.c --- linux/net/irda/irlap_event.d4.c Mon Nov 17 15:37:57 2003 +++ linux/net/irda/irlap_event.c Mon Nov 17 17:03:12 2003 @@ -932,6 +932,12 @@ static int irlap_state_setup(struct irla /* This frame will actually be sent at the new speed */ irlap_send_rr_frame(self, CMD_FRAME); + /* The timer is set to half the normal timer to quickly + * detect a failure to negociate the new connection + * parameters. IrLAP 6.11.3.2, note 3. + * Note that currently we don't process this failure + * properly, as we should do a quick disconnect. + * Jean II */ irlap_start_final_timer(self, self->final_timeout/2); irlap_next_state(self, LAP_NRM_P); @@ -1312,7 +1318,12 @@ static int irlap_state_nrm_p(struct irla irlap_resend_rejected_frames(self, CMD_FRAME); self->ack_required = FALSE; - irlap_start_final_timer(self, self->final_timeout); + + /* Make sure we account for the time + * to transmit our frames. See comemnts + * in irlap_send_data_primary_poll(). + * Jean II */ + irlap_start_final_timer(self, 2 * self->final_timeout); /* Keep state, do not move this line */ irlap_next_state(self, LAP_NRM_P); @@ -1352,8 +1363,9 @@ static int irlap_state_nrm_p(struct irla /* Resend rejected frames */ irlap_resend_rejected_frames(self, CMD_FRAME); - /* Give peer some time to retransmit! */ - irlap_start_final_timer(self, self->final_timeout); + /* Give peer some time to retransmit! + * But account for our own Tx. */ + irlap_start_final_timer(self, 2 * self->final_timeout); /* Keep state, do not move this line */ irlap_next_state(self, LAP_NRM_P); @@ -1450,6 +1462,8 @@ static int irlap_state_nrm_p(struct irla /* Resend rejected frames */ irlap_resend_rejected_frames(self, CMD_FRAME); + /* Final timer ??? Jean II */ + irlap_next_state(self, LAP_NRM_P); } else if (ret == NR_INVALID) { IRDA_DEBUG(1, "%s(), Received RR with " @@ -1541,7 +1555,7 @@ static int irlap_state_nrm_p(struct irla irlap_send_rr_frame(self, CMD_FRAME); } else irlap_resend_rejected_frames(self, CMD_FRAME); - irlap_start_final_timer(self, self->final_timeout); + irlap_start_final_timer(self, 2 * self->final_timeout); break; case RECV_SREJ_RSP: irlap_update_nr_received(self, info->nr); @@ -1550,7 +1564,7 @@ static int irlap_state_nrm_p(struct irla irlap_send_rr_frame(self, CMD_FRAME); } else irlap_resend_rejected_frame(self, CMD_FRAME); - irlap_start_final_timer(self, self->final_timeout); + irlap_start_final_timer(self, 2 * self->final_timeout); break; case RECV_RD_RSP: IRDA_DEBUG(1, "%s(), RECV_RD_RSP\n", __FUNCTION__); diff -u -p linux/net/irda/irlap_frame.d4.c linux/net/irda/irlap_frame.c --- linux/net/irda/irlap_frame.d4.c Mon Nov 17 16:09:09 2003 +++ linux/net/irda/irlap_frame.c Mon Nov 17 17:09:07 2003 @@ -779,6 +779,7 @@ void irlap_send_data_primary(struct irla void irlap_send_data_primary_poll(struct irlap_cb *self, struct sk_buff *skb) { struct sk_buff *tx_skb; + int transmission_time; /* Stop P timer */ del_timer(&self->poll_timer); @@ -829,13 +830,49 @@ void irlap_send_data_primary_poll(struct } } + /* How much time we took for transmission of all frames. + * We don't know, so let assume we used the full window. Jean II */ + transmission_time = self->final_timeout; + + /* Reset parameter so that we can fill next window */ self->window = self->window_size; + #ifdef CONFIG_IRDA_DYNAMIC_WINDOW + /* Remove what we have not used. Just do a prorata of the + * bytes left in window to window capacity. + * See max_line_capacities[][] in qos.c for details. Jean II */ + transmission_time -= (self->final_timeout * self->bytes_left + / self->line_capacity); + IRDA_DEBUG(4, "%s() adjusting transmission_time : ft=%d, bl=%d, lc=%d -> tt=%d\n", __FUNCTION__, self->final_timeout, self->bytes_left, self->line_capacity, transmission_time); + /* We are allowed to transmit a maximum number of bytes again. */ self->bytes_left = self->line_capacity; #endif /* CONFIG_IRDA_DYNAMIC_WINDOW */ - irlap_start_final_timer(self, self->final_timeout); + /* + * The network layer has a intermediate buffer between IrLAP + * and the IrDA driver which can contain 8 frames. So, even + * though IrLAP is currently sending the *last* frame of the + * tx-window, the driver most likely has only just started + * sending the *first* frame of the same tx-window. + * I.e. we are always at the very begining of or Tx window. + * Now, we are supposed to set the final timer from the end + * of our tx-window to let the other peer reply. So, we need + * to add extra time to compensate for the fact that we + * are really at the start of tx-window, otherwise the final timer + * might expire before he can answer... + * Jean II + */ + irlap_start_final_timer(self, self->final_timeout + transmission_time); + + /* + * The clever amongst you might ask why we do this adjustement + * only here, and not in all the other cases in irlap_event.c. + * In all those other case, we only send a very short management + * frame (few bytes), so the adjustement would be lost in the + * noise... + * The exception of course is irlap_resend_rejected_frame(). + * Jean II */ } /* @@ -1003,7 +1040,7 @@ void irlap_resend_rejected_frames(struct } #if 0 /* Not yet */ /* - * We can now fill the window with additinal data frames + * We can now fill the window with additional data frames */ while (skb_queue_len( &self->txq) > 0) {