Commit 03c2aba9 authored by Jean Tourrilhes's avatar Jean Tourrilhes Committed by Stephen Hemminger

[IRDA]: Proper calculation for F-timer. Improve interoperability.

parent 62b4d8ee
...@@ -40,14 +40,14 @@ struct lsap_cb; ...@@ -40,14 +40,14 @@ struct lsap_cb;
struct lap_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 POLL_TIMEOUT (450*HZ/1000) /* Must never exceed 500 ms */
#define FINAL_TIMEOUT (500*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 * Normally twice of p-timer. Note 3, IrLAP 6.3.11.2 - p. 60 suggests
* duration of the P-timer. * at least twice duration of the P-timer.
*/ */
#define WD_TIMEOUT (POLL_TIMEOUT*2) #define WD_TIMEOUT (POLL_TIMEOUT*2)
......
...@@ -932,6 +932,12 @@ static int irlap_state_setup(struct irlap_cb *self, IRLAP_EVENT event, ...@@ -932,6 +932,12 @@ static int irlap_state_setup(struct irlap_cb *self, IRLAP_EVENT event,
/* This frame will actually be sent at the new speed */ /* This frame will actually be sent at the new speed */
irlap_send_rr_frame(self, CMD_FRAME); 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_start_final_timer(self, self->final_timeout/2);
irlap_next_state(self, LAP_NRM_P); irlap_next_state(self, LAP_NRM_P);
...@@ -1312,7 +1318,12 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event, ...@@ -1312,7 +1318,12 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event,
irlap_resend_rejected_frames(self, CMD_FRAME); irlap_resend_rejected_frames(self, CMD_FRAME);
self->ack_required = FALSE; 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 */ /* Keep state, do not move this line */
irlap_next_state(self, LAP_NRM_P); irlap_next_state(self, LAP_NRM_P);
...@@ -1352,8 +1363,9 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event, ...@@ -1352,8 +1363,9 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event,
/* Resend rejected frames */ /* Resend rejected frames */
irlap_resend_rejected_frames(self, CMD_FRAME); irlap_resend_rejected_frames(self, CMD_FRAME);
/* Give peer some time to retransmit! */ /* Give peer some time to retransmit!
irlap_start_final_timer(self, self->final_timeout); * But account for our own Tx. */
irlap_start_final_timer(self, 2 * self->final_timeout);
/* Keep state, do not move this line */ /* Keep state, do not move this line */
irlap_next_state(self, LAP_NRM_P); irlap_next_state(self, LAP_NRM_P);
...@@ -1450,6 +1462,8 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event, ...@@ -1450,6 +1462,8 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event,
/* Resend rejected frames */ /* Resend rejected frames */
irlap_resend_rejected_frames(self, CMD_FRAME); irlap_resend_rejected_frames(self, CMD_FRAME);
/* Final timer ??? Jean II */
irlap_next_state(self, LAP_NRM_P); irlap_next_state(self, LAP_NRM_P);
} else if (ret == NR_INVALID) { } else if (ret == NR_INVALID) {
IRDA_DEBUG(1, "%s(), Received RR with " IRDA_DEBUG(1, "%s(), Received RR with "
...@@ -1541,7 +1555,7 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event, ...@@ -1541,7 +1555,7 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event,
irlap_send_rr_frame(self, CMD_FRAME); irlap_send_rr_frame(self, CMD_FRAME);
} else } else
irlap_resend_rejected_frames(self, CMD_FRAME); 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; break;
case RECV_SREJ_RSP: case RECV_SREJ_RSP:
irlap_update_nr_received(self, info->nr); irlap_update_nr_received(self, info->nr);
...@@ -1550,7 +1564,7 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event, ...@@ -1550,7 +1564,7 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event,
irlap_send_rr_frame(self, CMD_FRAME); irlap_send_rr_frame(self, CMD_FRAME);
} else } else
irlap_resend_rejected_frame(self, CMD_FRAME); 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; break;
case RECV_RD_RSP: case RECV_RD_RSP:
IRDA_DEBUG(1, "%s(), RECV_RD_RSP\n", __FUNCTION__); IRDA_DEBUG(1, "%s(), RECV_RD_RSP\n", __FUNCTION__);
......
...@@ -779,6 +779,7 @@ void irlap_send_data_primary(struct irlap_cb *self, struct sk_buff *skb) ...@@ -779,6 +779,7 @@ void irlap_send_data_primary(struct irlap_cb *self, struct sk_buff *skb)
void irlap_send_data_primary_poll(struct irlap_cb *self, struct sk_buff *skb) void irlap_send_data_primary_poll(struct irlap_cb *self, struct sk_buff *skb)
{ {
struct sk_buff *tx_skb; struct sk_buff *tx_skb;
int transmission_time;
/* Stop P timer */ /* Stop P timer */
del_timer(&self->poll_timer); del_timer(&self->poll_timer);
...@@ -829,13 +830,49 @@ void irlap_send_data_primary_poll(struct irlap_cb *self, struct sk_buff *skb) ...@@ -829,13 +830,49 @@ void irlap_send_data_primary_poll(struct irlap_cb *self, struct sk_buff *skb)
} }
} }
/* 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; self->window = self->window_size;
#ifdef CONFIG_IRDA_DYNAMIC_WINDOW #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. */ /* We are allowed to transmit a maximum number of bytes again. */
self->bytes_left = self->line_capacity; self->bytes_left = self->line_capacity;
#endif /* CONFIG_IRDA_DYNAMIC_WINDOW */ #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 irlap_cb *self, int command) ...@@ -1003,7 +1040,7 @@ void irlap_resend_rejected_frames(struct irlap_cb *self, int command)
} }
#if 0 /* Not yet */ #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) { while (skb_queue_len( &self->txq) > 0) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment