Commit 4f5e7c1d authored by Jean Tourrilhes's avatar Jean Tourrilhes Committed by Linus Torvalds

[PATCH] : IrLAP dynamic window code fix

	o [FEATURE] Fix the dynamic window code to properly send the pf bit.
		Increase perf by 40% for large packets at SIR.
parent 7dce0496
...@@ -982,15 +982,48 @@ static int irlap_state_xmit_p(struct irlap_cb *self, IRLAP_EVENT event, ...@@ -982,15 +982,48 @@ static int irlap_state_xmit_p(struct irlap_cb *self, IRLAP_EVENT event,
* Only send frame if send-window > 0. * Only send frame if send-window > 0.
*/ */
if ((self->window > 0) && (!self->remote_busy)) { if ((self->window > 0) && (!self->remote_busy)) {
int nextfit;
#ifdef CONFIG_IRDA_DYNAMIC_WINDOW #ifdef CONFIG_IRDA_DYNAMIC_WINDOW
struct sk_buff *skb_next;
/* With DYNAMIC_WINDOW, we keep the window size
* maximum, and adapt on the packets we are sending.
* At 115k, we can send only 2 packets of 2048 bytes
* in a 500 ms turnaround. Without this option, we
* would always limit the window to 2. With this
* option, if we send smaller packets, we can send
* up to 7 of them (always depending on QoS).
* Jean II */
/* Look at the next skb. This is safe, as we are
* the only consumer of the Tx queue (if we are not,
* we have other problems) - Jean II */
skb_next = skb_peek(&self->txq);
/* Check if a subsequent skb exist and would fit in
* the current window (with respect to turnaround
* time).
* This allow us to properly mark the current packet
* with the pf bit, to avoid falling back on the
* second test below, and avoid waiting the
* end of the window and sending a extra RR.
* Note : (skb_next != NULL) <=> (skb_queue_len() > 0)
* Jean II */
nextfit = ((skb_next != NULL) &&
((skb_next->len + skb->len) <=
self->bytes_left));
/* /*
* The current packet may not fit ! Because of test
* above, this should not happen any more !!!
* Test if we have transmitted more bytes over the * Test if we have transmitted more bytes over the
* link than its possible to do with the current * link than its possible to do with the current
* speed and turn-around-time. * speed and turn-around-time.
*/ */
if (skb->len > self->bytes_left) { if((!nextfit) && (skb->len > self->bytes_left)) {
IRDA_DEBUG(4, "%s(), Not allowed to transmit" IRDA_DEBUG(0, "%s(), Not allowed to transmit"
" more bytes!\n", __FUNCTION__); " more bytes!\n", __FUNCTION__);
/* Requeue the skb */
skb_queue_head(&self->txq, skb_get(skb)); skb_queue_head(&self->txq, skb_get(skb));
/* /*
* We should switch state to LAP_NRM_P, but * We should switch state to LAP_NRM_P, but
...@@ -1000,20 +1033,33 @@ static int irlap_state_xmit_p(struct irlap_cb *self, IRLAP_EVENT event, ...@@ -1000,20 +1033,33 @@ static int irlap_state_xmit_p(struct irlap_cb *self, IRLAP_EVENT event,
* trigger anyway now, so we just wait for it * trigger anyway now, so we just wait for it
* DB * DB
*/ */
/*
* Sorry, but that's not totally true. If
* we send 2000B packets, we may wait another
* 1000B until our turnaround expire. That's
* why we need to be proactive in avoiding
* comming here. - Jean II
*/
return -EPROTO; return -EPROTO;
} }
/* Substract space used by this skb */
self->bytes_left -= skb->len; self->bytes_left -= skb->len;
#endif /* CONFIG_IRDA_DYNAMIC_WINDOW */ #else /* CONFIG_IRDA_DYNAMIC_WINDOW */
/* Window has been adjusted for the max packet
* size, so much simpler... - Jean II */
nextfit = (skb_queue_len(&self->txq) > 0);
#endif /* CONFIG_IRDA_DYNAMIC_WINDOW */
/* /*
* Send data with poll bit cleared only if window > 1 * Send data with poll bit cleared only if window > 1
* and there is more frames after this one to be sent * and there is more frames after this one to be sent
*/ */
if ((self->window > 1) && if ((self->window > 1) && (nextfit)) {
skb_queue_len( &self->txq) > 0) /* More packet to send in current window */
{
irlap_send_data_primary(self, skb); irlap_send_data_primary(self, skb);
irlap_next_state(self, LAP_XMIT_P); irlap_next_state(self, LAP_XMIT_P);
} else { } else {
/* Final packet of window */
irlap_send_data_primary_poll(self, skb); irlap_send_data_primary_poll(self, skb);
irlap_next_state(self, LAP_NRM_P); irlap_next_state(self, LAP_NRM_P);
...@@ -1683,16 +1729,37 @@ static int irlap_state_xmit_s(struct irlap_cb *self, IRLAP_EVENT event, ...@@ -1683,16 +1729,37 @@ static int irlap_state_xmit_s(struct irlap_cb *self, IRLAP_EVENT event,
switch (event) { switch (event) {
case SEND_I_CMD: case SEND_I_CMD:
/* /*
* Send frame only if send window > 1 * Send frame only if send window > 0
*/ */
if ((self->window > 0) && (!self->remote_busy)) { if ((self->window > 0) && (!self->remote_busy)) {
int nextfit;
#ifdef CONFIG_IRDA_DYNAMIC_WINDOW #ifdef CONFIG_IRDA_DYNAMIC_WINDOW
struct sk_buff *skb_next;
/*
* Same deal as in irlap_state_xmit_p(), so see
* the comments at that point.
* We are the secondary, so there are only subtle
* differences. - Jean II
*/
/* Check if a subsequent skb exist and would fit in
* the current window (with respect to turnaround
* time). - Jean II */
skb_next = skb_peek(&self->txq);
nextfit = ((skb_next != NULL) &&
((skb_next->len + skb->len) <=
self->bytes_left));
/* /*
* Test if we have transmitted more bytes over the * Test if we have transmitted more bytes over the
* link than its possible to do with the current * link than its possible to do with the current
* speed and turn-around-time. * speed and turn-around-time.
*/ */
if (skb->len > self->bytes_left) { if((!nextfit) && (skb->len > self->bytes_left)) {
IRDA_DEBUG(0, "%s(), Not allowed to transmit"
" more bytes!\n", __FUNCTION__);
/* Requeue the skb */
skb_queue_head(&self->txq, skb_get(skb)); skb_queue_head(&self->txq, skb_get(skb));
/* /*
...@@ -1706,18 +1773,24 @@ static int irlap_state_xmit_s(struct irlap_cb *self, IRLAP_EVENT event, ...@@ -1706,18 +1773,24 @@ static int irlap_state_xmit_s(struct irlap_cb *self, IRLAP_EVENT event,
irlap_start_wd_timer(self, self->wd_timeout); irlap_start_wd_timer(self, self->wd_timeout);
irlap_next_state(self, LAP_NRM_S); irlap_next_state(self, LAP_NRM_S);
/* Slight difference with primary :
* here we would wait for the other side to
* expire the turnaround. - Jean II */
return -EPROTO; /* Try again later */ return -EPROTO; /* Try again later */
} }
/* Substract space used by this skb */
self->bytes_left -= skb->len; self->bytes_left -= skb->len;
#else /* CONFIG_IRDA_DYNAMIC_WINDOW */
/* Window has been adjusted for the max packet
* size, so much simpler... - Jean II */
nextfit = (skb_queue_len(&self->txq) > 0);
#endif /* CONFIG_IRDA_DYNAMIC_WINDOW */ #endif /* CONFIG_IRDA_DYNAMIC_WINDOW */
/* /*
* Send data with final bit cleared only if window > 1 * Send data with final bit cleared only if window > 1
* and there is more frames to be sent * and there is more frames to be sent
*/ */
if ((self->window > 1) && if ((self->window > 1) && (nextfit)) {
skb_queue_len(&self->txq) > 0)
{
irlap_send_data_secondary(self, skb); irlap_send_data_secondary(self, skb);
irlap_next_state(self, LAP_XMIT_S); irlap_next_state(self, LAP_XMIT_S);
} else { } else {
......
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