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,
* Only send frame if send-window > 0.
*/
if ((self->window > 0) && (!self->remote_busy)) {
int nextfit;
#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
* link than its possible to do with the current
* speed and turn-around-time.
*/
if (skb->len > self->bytes_left) {
IRDA_DEBUG(4, "%s(), Not allowed to transmit"
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));
/*
* 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,
* trigger anyway now, so we just wait for it
* 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;
}
/* Substract space used by this skb */
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
* and there is more frames after this one to be sent
*/
if ((self->window > 1) &&
skb_queue_len( &self->txq) > 0)
{
if ((self->window > 1) && (nextfit)) {
/* More packet to send in current window */
irlap_send_data_primary(self, skb);
irlap_next_state(self, LAP_XMIT_P);
} else {
/* Final packet of window */
irlap_send_data_primary_poll(self, skb);
irlap_next_state(self, LAP_NRM_P);
......@@ -1683,16 +1729,37 @@ static int irlap_state_xmit_s(struct irlap_cb *self, IRLAP_EVENT event,
switch (event) {
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)) {
int nextfit;
#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
* link than its possible to do with the current
* 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));
/*
......@@ -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_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 */
}
/* Substract space used by this skb */
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 */
/*
* Send data with final bit cleared only if window > 1
* and there is more frames to be sent
*/
if ((self->window > 1) &&
skb_queue_len(&self->txq) > 0)
{
if ((self->window > 1) && (nextfit)) {
irlap_send_data_secondary(self, skb);
irlap_next_state(self, LAP_XMIT_S);
} 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