From: Jean Tourrilhes <jt@bougret.hpl.hp.com>
To: Linus Torvalds <torvalds@transmeta.com>,
Jeff Garzik <jgarzik@mandrakesoft.com>,
Linux kernel mailing list <linux-kernel@vger.kernel.org>,
irda-users@lists.sourceforge.net
Subject: [PATCH 2.5] : ir255_nsc_speed-4.diff
Date: Thu, 29 Aug 2002 15:49:01 -0700 [thread overview]
Message-ID: <20020829224900.GD14118@bougret.hpl.hp.com> (raw)
ir255_nsc_speed-4.diff :
----------------------
o [FEATURE] Cleanly change speed back to 9600bps
o [CORRECT] Change speed under spinlock/irq disabled
o [CORRECT] Make sure interrupt handlers don't mess irq mask
o [CORRECT] Don't change speed if we haven't fully finished to Tx
diff -u -p linux/include/net/irda/nsc-ircc.d2.h linux/include/net/irda/nsc-ircc.h
--- linux/include/net/irda/nsc-ircc.d2.h Mon Jul 15 16:13:58 2002
+++ linux/include/net/irda/nsc-ircc.h Mon Jul 15 16:18:55 2002
@@ -253,6 +253,7 @@ struct nsc_ircc_cb {
__u32 flags; /* Interface flags */
__u32 new_speed;
+ int speed_cnt; /* Number of frames before speed change */
int index; /* Instance index */
struct pm_dev *dev;
diff -u -p linux/drivers/net/irda/nsc-ircc.d2.c linux/drivers/net/irda/nsc-ircc.c
--- linux/drivers/net/irda/nsc-ircc.d2.c Mon Jul 15 15:42:50 2002
+++ linux/drivers/net/irda/nsc-ircc.c Tue Jul 16 10:43:37 2002
@@ -953,6 +953,7 @@ static void nsc_ircc_change_dongle_speed
*
* Change the speed of the device
*
+ * This function *must* be called with irq off and spin-lock.
*/
static void nsc_ircc_change_speed(struct nsc_ircc_cb *self, __u32 speed)
{
@@ -1048,7 +1049,6 @@ static void nsc_ircc_change_speed(struct
/* Restore BSR */
outb(bank, iobase+BSR);
- netif_wake_queue(dev);
}
@@ -1074,20 +1074,30 @@ static int nsc_ircc_hard_xmit_sir(struct
netif_stop_queue(dev);
+ /* Make sure tests *& speed change are atomic */
+ spin_lock_irqsave(&self->lock, flags);
+
/* Check if we need to change the speed */
speed = irda_get_next_speed(skb);
if ((speed != self->io.speed) && (speed != -1)) {
- /* Check for empty frame */
+ /* Check for empty frame. */
if (!skb->len) {
- nsc_ircc_change_speed(self, speed);
+ /* If we just sent a frame, we get called before
+ * the last bytes get out (because of the SIR FIFO).
+ * If this is the case, let interrupt handler change
+ * the speed itself... Jean II */
+ if (self->io.direction == IO_RECV)
+ nsc_ircc_change_speed(self, speed);
+ else
+ self->new_speed = speed;
+ spin_unlock_irqrestore(&self->lock, flags);
dev_kfree_skb(skb);
+ netif_wake_queue(dev);
return 0;
} else
self->new_speed = speed;
}
- spin_lock_irqsave(&self->lock, flags);
-
/* Save current bank */
bank = inb(iobase+BSR);
@@ -1126,20 +1136,34 @@ static int nsc_ircc_hard_xmit_fir(struct
netif_stop_queue(dev);
+ /* Make sure tests *& speed change are atomic */
+ spin_lock_irqsave(&self->lock, flags);
+
/* Check if we need to change the speed */
speed = irda_get_next_speed(skb);
if ((speed != self->io.speed) && (speed != -1)) {
- /* Check for empty frame */
+ /* Check for empty frame. */
if (!skb->len) {
- nsc_ircc_change_speed(self, speed);
+ /* If we are currently transmitting, defer to
+ * interrupt handler. - Jean II */
+ if(self->tx_fifo.len == 0)
+ nsc_ircc_change_speed(self, speed);
+ else {
+ self->new_speed = speed;
+ self->speed_cnt = self->tx_fifo.len;
+ }
+ spin_unlock_irqrestore(&self->lock, flags);
dev_kfree_skb(skb);
+ netif_wake_queue(dev);
return 0;
- } else
+ } else {
self->new_speed = speed;
+ /* Save the number of frames currently in the fifo
+ * so that we know *when* to change the speed. */
+ self->speed_cnt = self->tx_fifo.len + 1;
+ }
}
- spin_lock_irqsave(&self->lock, flags);
-
/* Save current bank */
bank = inb(iobase+BSR);
@@ -1334,16 +1358,23 @@ static int nsc_ircc_dma_xmit_complete(st
self->stats.tx_packets++;
}
- /* Check if we need to change the speed */
- if (self->new_speed) {
- nsc_ircc_change_speed(self, self->new_speed);
- self->new_speed = 0;
- }
-
/* Finished with this frame, so prepare for next */
self->tx_fifo.ptr++;
self->tx_fifo.len--;
+ /* Check if we need to change the speed.
+ * Do it after self->tx_fifo.len--; to avoid races with
+ * nsc_ircc_hard_xmit_fir().
+ * We do it synchronous to the packets in the fifo, so that's
+ * why we wait for the right frame to do it. - Jean II */
+ if ((self->new_speed) && (--self->speed_cnt == 0)) {
+ /* There seem to be some issue with corrupting the
+ * frame just before a speed change. Workaround. Jean II */
+ udelay(100);
+ nsc_ircc_change_speed(self, self->new_speed);
+ self->new_speed = 0;
+ }
+
/* Any frames to be sent back-to-back? */
if (self->tx_fifo.len) {
nsc_ircc_dma_xmit(self, iobase);
@@ -1634,7 +1665,12 @@ static void nsc_ircc_sir_interrupt(struc
}
/* Check if transmission has completed */
if (eir & EIR_TXEMP_EV) {
- /* Check if we need to change the speed? */
+ /* Turn around and get ready to receive some data */
+ self->io.direction = IO_RECV;
+ self->ier = IER_RXHDL_IE;
+ /* Check if we need to change the speed?
+ * Need to be after self->io.direction to avoid race with
+ * nsc_ircc_hard_xmit_sir() - Jean II */
if (self->new_speed) {
IRDA_DEBUG(2, __FUNCTION__ "(), Changing speed!\n");
nsc_ircc_change_speed(self, self->new_speed);
@@ -1649,9 +1685,6 @@ static void nsc_ircc_sir_interrupt(struc
return;
}
}
- /* Turn around and get ready to receive some data */
- self->io.direction = IO_RECV;
- self->ier = IER_RXHDL_IE;
}
/* Rx FIFO threshold or timeout */
next reply other threads:[~2002-08-29 22:50 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2002-08-29 22:49 Jean Tourrilhes [this message]
2002-08-30 0:55 ` [PATCH 2.5] : ir252_nsc_speed_both.diff (don't apply ir255_nsc_speed-4.diff) Jean Tourrilhes
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20020829224900.GD14118@bougret.hpl.hp.com \
--to=jt@bougret.hpl.hp.com \
--cc=irda-users@lists.sourceforge.net \
--cc=jgarzik@mandrakesoft.com \
--cc=jt@hpl.hp.com \
--cc=linux-kernel@vger.kernel.org \
--cc=torvalds@transmeta.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox