[PATCH 2.5] irport fixes

Jean Tourrilhes (jt@bougret.hpl.hp.com)
Tue, 13 May 2003 15:23:46 -0700


ir259_irport-6.diff :
o [CORRECT] fix module ownership in irport
o [CORRECT] Properly initialise dev->trans_start in irport
o [CORRECT] Add delay to drain the Tx fifo to avoid corrupting
last outgoing Tx byte when changing speed
o [FEATURE] Safer locking around speed change in irport_hard_xmit()
o [FEATURE] Enforce half duplex operation in interrupt handler
o [FEATURE] Optimise interrupt handler for latency and I/O ops
o [FEATURE] Optimise Tx path in irport_write()
o [FEATURE] Add ZeroCopy Rx
o [FEATURE] Better debugging in watchdog timeout
o [FEATURE] Various other cleanups and comments

diff -u -p linux/include/net/irda/irport.d0.h linux/include/net/irda/irport.h
--- linux/include/net/irda/irport.d0.h Mon May 12 18:12:18 2003
+++ linux/include/net/irda/irport.h Mon May 12 18:17:06 2003
@@ -67,6 +67,7 @@ struct irport_cb {
__u32 new_speed;
int mode;
int index; /* Instance index */
+ int transmitting; /* Are we transmitting ? */

spinlock_t lock; /* For serializing operations */

diff -u -p linux/drivers/net/irda/irport.d0.c linux/drivers/net/irda/irport.c
--- linux/drivers/net/irda/irport.d0.c Mon May 12 18:03:50 2003
+++ linux/drivers/net/irda/irport.c Tue May 13 13:07:43 2003
@@ -11,6 +11,7 @@
* Sources: serial.c by Linus Torvalds
*
* Copyright (c) 1997, 1998, 1999-2000 Dag Brattli, All Rights Reserved.
+ * Copyright (c) 2000-2003 Jean Tourrilhes, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -48,6 +49,7 @@
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/spinlock.h>
+#include <linux/delay.h>
#include <linux/rtnetlink.h>

#include <asm/system.h>
@@ -72,14 +74,14 @@ static unsigned int qos_mtt_bits = 0x03;
static struct irport_cb *dev_self[] = { NULL, NULL, NULL, NULL};
static char *driver_name = "irport";

-static void irport_write_wakeup(struct irport_cb *self);
-static int irport_write(int iobase, int fifo_size, __u8 *buf, int len);
-static void irport_receive(struct irport_cb *self);
+static inline void irport_write_wakeup(struct irport_cb *self);
+static inline int irport_write(int iobase, int fifo_size, __u8 *buf, int len);
+static inline void irport_receive(struct irport_cb *self);

static int irport_net_init(struct net_device *dev);
static int irport_net_ioctl(struct net_device *dev, struct ifreq *rq,
int cmd);
-static int irport_is_receiving(struct irport_cb *self);
+static inline int irport_is_receiving(struct irport_cb *self);
static int irport_set_dtr_rts(struct net_device *dev, int dtr, int rts);
static int irport_raw_write(struct net_device *dev, __u8 *buf, int len);
static struct net_device_stats *irport_net_get_stats(struct net_device *dev);
@@ -169,7 +171,7 @@ irport_open(int i, unsigned int iobase,
self->io.sir_base = iobase;
self->io.sir_ext = IO_EXTENT;
self->io.irq = irq;
- self->io.fifo_size = 16;
+ self->io.fifo_size = 16; /* 16550A and compatible */

/* Initialize QoS for this device */
irda_init_max_qos_capabilies(&self->qos);
@@ -181,39 +183,47 @@ irport_open(int i, unsigned int iobase,
irda_qos_bits_to_value(&self->qos);

self->flags = IFF_SIR|IFF_PIO;
+ self->mode = IRDA_IRLAP;
+
+ /* Bootstrap ZeroCopy Rx */
+ self->rx_buff.truesize = IRDA_SKB_MAX_MTU;
+ self->rx_buff.skb = __dev_alloc_skb(self->rx_buff.truesize,
+ GFP_KERNEL);
+ if (self->rx_buff.skb == NULL)
+ return NULL;
+ skb_reserve(self->rx_buff.skb, 1);
+ self->rx_buff.head = self->rx_buff.skb->data;
+ /* No need to memset the buffer, unless you are really pedantic */
+
+ /* Finish setup the Rx buffer descriptor */
+ self->rx_buff.in_frame = FALSE;
+ self->rx_buff.state = OUTSIDE_FRAME;
+ self->rx_buff.data = self->rx_buff.head;

/* Specify how much memory we want */
- self->rx_buff.truesize = 4000;
self->tx_buff.truesize = 4000;

/* Allocate memory if needed */
- if (self->rx_buff.truesize > 0) {
- self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
- GFP_KERNEL);
- if (self->rx_buff.head == NULL)
- return NULL;
- memset(self->rx_buff.head, 0, self->rx_buff.truesize);
- }
if (self->tx_buff.truesize > 0) {
self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize,
GFP_KERNEL);
if (self->tx_buff.head == NULL) {
- kfree(self->rx_buff.head);
+ kfree_skb(self->rx_buff.skb);
+ self->rx_buff.skb = NULL;
+ self->rx_buff.head = NULL;
return NULL;
}
memset(self->tx_buff.head, 0, self->tx_buff.truesize);
}
- self->rx_buff.in_frame = FALSE;
- self->rx_buff.state = OUTSIDE_FRAME;
self->tx_buff.data = self->tx_buff.head;
- self->rx_buff.data = self->rx_buff.head;
- self->mode = IRDA_IRLAP;

if (!(dev = dev_alloc("irda%d", &err))) {
ERROR("%s(), dev_alloc() failed!\n", __FUNCTION__);
return NULL;
}
self->netdev = dev;
+ /* Keep track of module usage */
+ SET_MODULE_OWNER(dev);

/* May be overridden by piggyback drivers */
dev->priv = (void *) self;
@@ -241,7 +251,8 @@ irport_open(int i, unsigned int iobase,
ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
return NULL;
}
- MESSAGE("IrDA: Registered device %s\n", dev->name);
+ MESSAGE("IrDA: Registered device %s (irport io=0x%X irq=%d)\n",
+ dev->name, iobase, irq);

return self;
}
@@ -270,8 +281,9 @@ int irport_close(struct irport_cb *self)
if (self->tx_buff.head)
kfree(self->tx_buff.head);

- if (self->rx_buff.head)
- kfree(self->rx_buff.head);
+ if (self->rx_buff.skb)
+ kfree_skb(self->rx_buff.skb);
+ self->rx_buff.skb = NULL;

/* Remove ourselves */
dev_self[self->index] = NULL;
@@ -306,6 +318,9 @@ void irport_stop(struct irport_cb *self)

/* We can't lock, we may be called from a FIR driver - Jean II */

+ /* We are not transmitting any more */
+ self->transmitting = 0;
+
/* Reset UART */
outb(0, iobase+UART_MCR);

@@ -327,6 +342,33 @@ int irport_probe(int iobase)
}

/*
+ * Function irport_get_fcr (speed)
+ *
+ * Compute value of fcr
+ *
+ */
+static inline unsigned int irport_get_fcr(__u32 speed)
+{
+ unsigned int fcr; /* FIFO control reg */
+
+ /* Enable fifos */
+ fcr = UART_FCR_ENABLE_FIFO;
+
+ /*
+ * Use trigger level 1 to avoid 3 ms. timeout delay at 9600 bps, and
+ * almost 1,7 ms at 19200 bps. At speeds above that we can just forget
+ * about this timeout since it will always be fast enough.
+ */
+ if (speed < 38400)
+ fcr |= UART_FCR_TRIGGER_1;
+ else
+ //fcr |= UART_FCR_TRIGGER_14;
+ fcr |= UART_FCR_TRIGGER_8;
+
+ return(fcr);
+}
+
+/*
* Function irport_change_speed (self, speed)
*
* Set speed of IrDA port to specified baudrate
@@ -337,11 +379,12 @@ void irport_change_speed(void *priv, __u
{
struct irport_cb *self = (struct irport_cb *) priv;
int iobase;
- int fcr; /* FIFO control reg */
- int lcr; /* Line control reg */
+ unsigned int fcr; /* FIFO control reg */
+ unsigned int lcr; /* Line control reg */
int divisor;

ASSERT(self != NULL, return;);
+ ASSERT(speed != 0, return;);

IRDA_DEBUG(1, "%s(), Setting speed to: %d - iobase=%#x\n",
__FUNCTION__, speed, self->io.sir_base);
@@ -358,18 +401,9 @@ void irport_change_speed(void *priv, __u

divisor = SPEED_MAX/speed;

- fcr = UART_FCR_ENABLE_FIFO;
+ /* Get proper fifo configuration */
+ fcr = irport_get_fcr(speed);

- /*
- * Use trigger level 1 to avoid 3 ms. timeout delay at 9600 bps, and
- * almost 1,7 ms at 19200 bps. At speeds above that we can just forget
- * about this timeout since it will always be fast enough.
- */
- if (self->io.speed < 38400)
- fcr |= UART_FCR_TRIGGER_1;
- else
- fcr |= UART_FCR_TRIGGER_14;
-
/* IrDA ports use 8N1 */
lcr = UART_LCR_WLEN8;

@@ -380,7 +414,7 @@ void irport_change_speed(void *priv, __u
outb(fcr, iobase+UART_FCR); /* Enable FIFO's */

/* Turn on interrups */
- /* This will generate a fata interrupt storm.
+ /* This will generate a fatal interrupt storm.
* People calling us will do that properly - Jean II */
//outb(/*UART_IER_RLSI|*/UART_IER_RDI/*|UART_IER_THRI*/, iobase+UART_IER);
}
@@ -467,8 +501,8 @@ int __irport_change_speed(struct irda_ta
irda_task_next_state(task, IRDA_TASK_DONE);
ret = -1;
break;
- }
- /* Put stuff in the sate we found them - Jean II */
+ }
+ /* Put stuff in the state we found them - Jean II */
if(wasunlocked) {
spin_unlock_irqrestore(&self->lock, flags);
}
@@ -477,98 +511,6 @@ int __irport_change_speed(struct irda_ta
}

/*
- * Function irport_write_wakeup (tty)
- *
- * Called by the driver when there's room for more data. If we have
- * more packets to send, we send them here.
- *
- */
-static void irport_write_wakeup(struct irport_cb *self)
-{
- int actual = 0;
- int iobase;
- int fcr;
-
- ASSERT(self != NULL, return;);
-
- IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
-
- iobase = self->io.sir_base;
-
- /* Finished with frame? */
- if (self->tx_buff.len > 0) {
- /* Write data left in transmit buffer */
- actual = irport_write(iobase, self->io.fifo_size,
- self->tx_buff.data, self->tx_buff.len);
- self->tx_buff.data += actual;
- self->tx_buff.len -= actual;
-
- /* Turn on transmit finished interrupt. */
- outb(UART_IER_THRI, iobase+UART_IER);
- } else {
- /*
- * Now serial buffer is almost free & we can start
- * transmission of another packet. But first we must check
- * if we need to change the speed of the hardware
- */
- if (self->new_speed) {
- IRDA_DEBUG(5, "%s(), Changing speed!\n", __FUNCTION__);
- irda_task_execute(self, __irport_change_speed,
- irport_change_speed_complete,
- NULL, (void *) self->new_speed);
- self->new_speed = 0;
- IRDA_DEBUG(5, "%s(), Speed changed!\n", __FUNCTION__ );
- } else {
- /* Tell network layer that we want more frames */
- netif_wake_queue(self->netdev);
- }
- self->stats.tx_packets++;
-
- /*
- * Reset Rx FIFO to make sure that all reflected transmit data
- * is discarded. This is needed for half duplex operation
- */
- fcr = UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR;
- if (self->io.speed < 38400)
- fcr |= UART_FCR_TRIGGER_1;
- else
- fcr |= UART_FCR_TRIGGER_14;
-
- outb(fcr, iobase+UART_FCR);
-
- /* Turn on receive interrupts */
- outb(UART_IER_RDI, iobase+UART_IER);
- }
-}
-
-/*
- * Function irport_write (driver)
- *
- * Fill Tx FIFO with transmit data
- *
- */
-static int irport_write(int iobase, int fifo_size, __u8 *buf, int len)
-{
- int actual = 0;
-
- /* Tx FIFO should be empty! */
- if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
- IRDA_DEBUG(0, "%s(), failed, fifo not empty!\n", __FUNCTION__);
- return 0;
- }
-
- /* Fill FIFO with current frame */
- while ((fifo_size-- > 0) && (actual < len)) {
- /* Transmit next byte */
- outb(buf[actual], iobase+UART_TX);
-
- actual++;
- }
-
- return actual;
-}
-
-/*
* Function irport_change_speed_complete (task)
*
* Called when the change speed operation completes
@@ -604,24 +546,80 @@ static void irport_timeout(struct net_de
{
struct irport_cb *self;
int iobase;
+ int iir, lsr;
unsigned long flags;

self = (struct irport_cb *) dev->priv;
+ ASSERT(self != NULL, return;);
iobase = self->io.sir_base;

- WARNING("%s: transmit timed out\n", dev->name);
+ WARNING("%s: transmit timed out, jiffies = %ld, trans_start = %ld\n",
+ dev->name, jiffies, dev->trans_start);
spin_lock_irqsave(&self->lock, flags);
+
+ /* Debug what's happening... */
+
+ /* Get interrupt status */
+ lsr = inb(iobase+UART_LSR);
+ /* Read interrupt register */
+ iir = inb(iobase+UART_IIR);
+ IRDA_DEBUG(0, "%s(), iir=%02x, lsr=%02x, iobase=%#x\n",
+ __FUNCTION__, iir, lsr, iobase);
+
+ IRDA_DEBUG(0, "%s(), transmitting=%d, remain=%d, done=%d\n",
+ __FUNCTION__, self->transmitting, self->tx_buff.len,
+ self->tx_buff.data - self->tx_buff.head);
+
+ /* Now, restart the port */
irport_start(self);
self->change_speed(self->priv, self->io.speed);
/* This will re-enable irqs */
outb(/*UART_IER_RLSI|*/UART_IER_RDI/*|UART_IER_THRI*/, iobase+UART_IER);
+ dev->trans_start = jiffies;
spin_unlock_irqrestore(&self->lock, flags);

- dev->trans_start = jiffies;
netif_wake_queue(dev);
}

/*
+ * Function irport_wait_hw_transmitter_finish ()
+ *
+ * Wait for the real end of HW transmission
+ *
+ * The UART is a strict FIFO, and we get called only when we have finished
+ * pushing data to the FIFO, so the maximum amount of time we must wait
+ * is only for the FIFO to drain out.
+ *
+ * We use a simple calibrated loop. We may need to adjust the loop
+ * delay (udelay) to balance I/O traffic and latency. And we also need to
+ * adjust the maximum timeout.
+ * It would probably be better to wait for the proper interrupt,
+ * but it doesn't seem to be available.
+ *
+ * We can't use jiffies or kernel timers because :
+ * 1) We are called from the interrupt handler, which disable softirqs,
+ * so jiffies won't be increased
+ * 2) Jiffies granularity is usually very coarse (10ms), and we don't
+ * want to wait that long to detect stuck hardware.
+ * Jean II
+ */
+
+static void irport_wait_hw_transmitter_finish(struct irport_cb *self)
+{
+ int iobase;
+ int count = 1000; /* 1 ms */
+
+ iobase = self->io.sir_base;
+
+ /* Calibrated busy loop */
+ while((count-- > 0) && !(inb(iobase+UART_LSR) & UART_LSR_TEMT))
+ udelay(1);
+
+ if(count == 0)
+ IRDA_DEBUG(0, "%s(): stuck transmitter\n", __FUNCTION__);
+}
+
+/*
* Function irport_hard_start_xmit (struct sk_buff *skb, struct net_device *dev)
*
* Transmits the current frame until FIFO is full, then
@@ -645,8 +643,8 @@ int irport_hard_xmit(struct sk_buff *skb
iobase = self->io.sir_base;

netif_stop_queue(dev);
-
- /* Make sure tests *& speed change are atomic */
+
+ /* Make sure tests & speed change are atomic */
spin_lock_irqsave(&self->lock, flags);

/* Check if we need to change the speed */
@@ -654,10 +652,21 @@ int irport_hard_xmit(struct sk_buff *skb
if ((speed != self->io.speed) && (speed != -1)) {
/* Check for empty frame */
if (!skb->len) {
+ /*
+ * We send frames one by one in SIR mode (no
+ * pipelining), so at this point, if we were sending
+ * a previous frame, we just received the interrupt
+ * telling us it is finished (UART_IIR_THRI).
+ * Therefore, waiting for the transmitter to really
+ * finish draining the fifo won't take too long.
+ * And the interrupt handler is not expected to run.
+ * - Jean II */
+ irport_wait_hw_transmitter_finish(self);
/* Better go there already locked - Jean II */
irda_task_execute(self, __irport_change_speed,
irport_change_speed_complete,
NULL, (void *) speed);
+ dev->trans_start = jiffies;
spin_unlock_irqrestore(&self->lock, flags);
dev_kfree_skb(skb);
return 0;
@@ -674,9 +683,13 @@ int irport_hard_xmit(struct sk_buff *skb

self->stats.tx_bytes += self->tx_buff.len;

+ /* We are transmitting */
+ self->transmitting = 1;
+
/* Turn on transmit finished interrupt. Will fire immediately! */
outb(UART_IER_THRI, iobase+UART_IER);

+ dev->trans_start = jiffies;
spin_unlock_irqrestore(&self->lock, flags);

dev_kfree_skb(skb);
@@ -685,12 +698,100 @@ int irport_hard_xmit(struct sk_buff *skb
}

/*
+ * Function irport_write (driver)
+ *
+ * Fill Tx FIFO with transmit data
+ *
+ * Called only from irport_write_wakeup()
+ */
+static inline int irport_write(int iobase, int fifo_size, __u8 *buf, int len)
+{
+ int actual = 0;
+
+ /* Fill FIFO with current frame */
+ while ((actual < fifo_size) && (actual < len)) {
+ /* Transmit next byte */
+ outb(buf[actual], iobase+UART_TX);
+
+ actual++;
+ }
+
+ return actual;
+}
+
+/*
+ * Function irport_write_wakeup (tty)
+ *
+ * Called by the driver when there's room for more data. If we have
+ * more packets to send, we send them here.
+ *
+ * Called only from irport_interrupt()
+ * Make sure this function is *not* called while we are receiving,
+ * otherwise we will reset fifo and loose data :-(
+ */
+static inline void irport_write_wakeup(struct irport_cb *self)
+{
+ int actual = 0;
+ int iobase;
+ unsigned int fcr;
+
+ ASSERT(self != NULL, return;);
+
+ IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
+
+ iobase = self->io.sir_base;
+
+ /* Finished with frame? */
+ if (self->tx_buff.len > 0) {
+ /* Write data left in transmit buffer */
+ actual = irport_write(iobase, self->io.fifo_size,
+ self->tx_buff.data, self->tx_buff.len);
+ self->tx_buff.data += actual;
+ self->tx_buff.len -= actual;
+ } else {
+ /*
+ * Now serial buffer is almost free & we can start
+ * transmission of another packet. But first we must check
+ * if we need to change the speed of the hardware
+ */
+ if (self->new_speed) {
+ irport_wait_hw_transmitter_finish(self);
+ irda_task_execute(self, __irport_change_speed,
+ irport_change_speed_complete,
+ NULL, (void *) self->new_speed);
+ self->new_speed = 0;
+ } else {
+ /* Tell network layer that we want more frames */
+ netif_wake_queue(self->netdev);
+ }
+ self->stats.tx_packets++;
+
+ /*
+ * Reset Rx FIFO to make sure that all reflected transmit data
+ * is discarded. This is needed for half duplex operation
+ */
+ fcr = irport_get_fcr(self->io.speed);
+ fcr |= UART_FCR_CLEAR_RCVR;
+ outb(fcr, iobase+UART_FCR);
+
+ /* Finished transmitting */
+ self->transmitting = 0;
+
+ /* Turn on receive interrupts */
+ outb(UART_IER_RDI, iobase+UART_IER);
+
+ IRDA_DEBUG(1, "%s() : finished Tx\n", __FUNCTION__);
+ }
+}
+
+/*
* Function irport_receive (self)
*
* Receive one frame from the infrared port
*
+ * Called only from irport_interrupt()
*/
-static void irport_receive(struct irport_cb *self)
+static inline void irport_receive(struct irport_cb *self)
{
int boguscount = 0;
int iobase;
@@ -739,40 +840,51 @@ irqreturn_t irport_interrupt(int irq, vo

iobase = self->io.sir_base;

- iir = inb(iobase+UART_IIR) & UART_IIR_ID;
- while (iir) {
- handled = 1;
+ /* Cut'n'paste interrupt routine from serial.c
+ * This version try to minimise latency and I/O operations.
+ * Simplified and modified to enforce half duplex operation.
+ * - Jean II */

- /* Clear interrupt */
+ /* Check status even is iir reg is cleared, more robust and
+ * eliminate a read on the I/O bus - Jean II */
+ do {
+ /* Get interrupt status ; Clear interrupt */
lsr = inb(iobase+UART_LSR);
-
- IRDA_DEBUG(4, "%s(), iir=%02x, lsr=%02x, iobase=%#x\n",
- __FUNCTION__, iir, lsr, iobase);
-
- switch (iir) {
- case UART_IIR_RLSI:
- IRDA_DEBUG(2, "%s(), RLSI\n", __FUNCTION__);
- break;
- case UART_IIR_RDI:
- /* Receive interrupt */
- irport_receive(self);
- break;
- case UART_IIR_THRI:
- if (lsr & UART_LSR_THRE)
- /* Transmitter ready for data */
- irport_write_wakeup(self);
- break;
- default:
- IRDA_DEBUG(0, "%s(), unhandled IIR=%#x\n", __FUNCTION__, iir);
- break;
- }

- /* Make sure we don't stay here too long */
- if (boguscount++ > 100)
+ /* Are we receiving or transmitting ? */
+ if(!self->transmitting) {
+ /* Received something ? */
+ if (lsr & UART_LSR_DR)
+ irport_receive(self);
+ } else {
+ /* Room in Tx fifo ? */
+ if (lsr & (UART_LSR_THRE | UART_LSR_TEMT))
+ irport_write_wakeup(self);
+ }
+
+ /* A bit hackish, but working as expected... Jean II */
+ if(lsr & (UART_LSR_THRE | UART_LSR_TEMT | UART_LSR_DR))
+ handled = 1;
+
+ /* Make sure we don't stay here to long */
+ if (boguscount++ > 10) {
+ WARNING("%s() irq handler looping : lsr=%02x\n",
+ __FUNCTION__, lsr);
break;
+ }
+
+ /* Read interrupt register */
+ iir = inb(iobase+UART_IIR);
+
+ /* Enable this debug only when no other options and at low
+ * bit rates, otherwise it may cause Rx overruns (lsr=63).
+ * - Jean II */
+ IRDA_DEBUG(6, "%s(), iir=%02x, lsr=%02x, iobase=%#x\n",
+ __FUNCTION__, iir, lsr, iobase);
+
+ /* As long as interrupt pending... */
+ } while ((iir & UART_IIR_NO_INT) == 0);

- iir = inb(iobase + UART_IIR) & UART_IIR_ID;
- }
spin_unlock(&self->lock);
return IRQ_RETVAL(handled);
}
@@ -800,8 +912,8 @@ int irport_net_open(struct net_device *d
char hwname[16];
unsigned long flags;

- IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
-
+ IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
+
ASSERT(dev != NULL, return -1;);
self = (struct irport_cb *) dev->priv;

@@ -815,7 +927,12 @@ int irport_net_open(struct net_device *d
}

spin_lock_irqsave(&self->lock, flags);
+ /* Init uart */
irport_start(self);
+ /* Set 9600 bauds per default, including at the dongle */
+ irda_task_execute(self, __irport_change_speed,
+ irport_change_speed_complete,
+ NULL, (void *) 9600);
spin_unlock_irqrestore(&self->lock, flags);


@@ -828,12 +945,9 @@ int irport_net_open(struct net_device *d
*/
self->irlap = irlap_open(dev, &self->qos, hwname);

- /* FIXME: change speed of dongle */
/* Ready to play! */

netif_start_queue(dev);
-
- MOD_INC_USE_COUNT;

return 0;
}
@@ -873,40 +987,16 @@ int irport_net_close(struct net_device *

free_irq(self->io.irq, dev);

- MOD_DEC_USE_COUNT;
-
return 0;
}

/*
- * Function irport_wait_until_sent (self)
- *
- * Delay exectution until finished transmitting
- *
- */
-#if 0
-void irport_wait_until_sent(struct irport_cb *self)
-{
- int iobase;
-
- iobase = self->io.sir_base;
-
- /* Wait until Tx FIFO is empty */
- while (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
- IRDA_DEBUG(2, "%s(), waiting!\n", __FUNCTION__);
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(MSECS_TO_JIFFIES(60));
- }
-}
-#endif
-
-/*
* Function irport_is_receiving (self)
*
* Returns true is we are currently receiving data
*
*/
-static int irport_is_receiving(struct irport_cb *self)
+static inline int irport_is_receiving(struct irport_cb *self)
{
return (self->rx_buff.state != OUTSIDE_FRAME);
}
@@ -997,6 +1087,12 @@ static int irport_net_ioctl(struct net_d
ret = -EPERM;
break;
}
+
+ /* Locking :
+ * irda_device_dongle_init() can't be locked.
+ * irda_task_execute() doesn't need to be locked.
+ * Jean II
+ */

/* Initialize dongle */
dongle = irda_device_dongle_init(dev, irq->ifr_dongle);
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/