Commit 801783b6 authored by Linus Torvalds's avatar Linus Torvalds

Merge http://gkernel.bkbits.net/net-drivers-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents f102df2e b72173b0
...@@ -158,7 +158,7 @@ static int act200l_change_speed(struct irda_task *task) ...@@ -158,7 +158,7 @@ static int act200l_change_speed(struct irda_task *task)
} }
break; break;
case IRDA_TASK_CHILD_WAIT: case IRDA_TASK_CHILD_WAIT:
WARNING(__FUNCTION__ "(), resetting dongle timed out!\n"); WARNING("%s(), resetting dongle timed out!\n", __FUNCTION__);
ret = -1; ret = -1;
break; break;
case IRDA_TASK_CHILD_DONE: case IRDA_TASK_CHILD_DONE:
...@@ -203,7 +203,7 @@ static int act200l_change_speed(struct irda_task *task) ...@@ -203,7 +203,7 @@ static int act200l_change_speed(struct irda_task *task)
self->speed_task = NULL; self->speed_task = NULL;
break; break;
default: default:
ERROR(__FUNCTION__ "(), unknown state %d\n", task->state); ERROR("%s(), unknown state %d\n", __FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE); irda_task_next_state(task, IRDA_TASK_DONE);
self->speed_task = NULL; self->speed_task = NULL;
ret = -1; ret = -1;
...@@ -269,7 +269,7 @@ static int act200l_reset(struct irda_task *task) ...@@ -269,7 +269,7 @@ static int act200l_reset(struct irda_task *task)
self->reset_task = NULL; self->reset_task = NULL;
break; break;
default: default:
ERROR(__FUNCTION__ "(), unknown state %d\n", task->state); ERROR("%s(), unknown state %d\n", __FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE); irda_task_next_state(task, IRDA_TASK_DONE);
self->reset_task = NULL; self->reset_task = NULL;
ret = -1; ret = -1;
......
...@@ -259,7 +259,7 @@ static int actisys_reset(struct irda_task *task) ...@@ -259,7 +259,7 @@ static int actisys_reset(struct irda_task *task)
self->speed = 9600; /* That's the default */ self->speed = 9600; /* That's the default */
break; break;
default: default:
ERROR(__FUNCTION__ "(), unknown state %d\n", task->state); ERROR("%s(), unknown state %d\n", __FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE); irda_task_next_state(task, IRDA_TASK_DONE);
self->reset_task = NULL; self->reset_task = NULL;
ret = -1; ret = -1;
......
...@@ -141,12 +141,12 @@ int __init ali_ircc_init(void) ...@@ -141,12 +141,12 @@ int __init ali_ircc_init(void)
int reg, revision; int reg, revision;
int i = 0; int i = 0;
IRDA_DEBUG(2, __FUNCTION__ "(), ---------------- Start ----------------\n"); IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);
/* Probe for all the ALi chipsets we know about */ /* Probe for all the ALi chipsets we know about */
for (chip= chips; chip->name; chip++, i++) for (chip= chips; chip->name; chip++, i++)
{ {
IRDA_DEBUG(2, __FUNCTION__"(), Probing for %s ...\n", chip->name); IRDA_DEBUG(2, "%s(), Probing for %s ...\n", __FUNCTION__, chip->name);
/* Try all config registers for this chip */ /* Try all config registers for this chip */
for (cfg=0; cfg<2; cfg++) for (cfg=0; cfg<2; cfg++)
...@@ -176,13 +176,11 @@ int __init ali_ircc_init(void) ...@@ -176,13 +176,11 @@ int __init ali_ircc_init(void)
if (reg == chip->cid_value) if (reg == chip->cid_value)
{ {
IRDA_DEBUG(2, __FUNCTION__ IRDA_DEBUG(2, "%s(), Chip found at 0x%03x\n", __FUNCTION__, cfg_base);
"(), Chip found at 0x%03x\n", cfg_base);
outb(0x1F, cfg_base); outb(0x1F, cfg_base);
revision = inb(cfg_base+1); revision = inb(cfg_base+1);
IRDA_DEBUG(2, __FUNCTION__ IRDA_DEBUG(2, "%s(), Found %s chip, revision=%d\n", __FUNCTION__,
"(), Found %s chip, revision=%d\n",
chip->name, revision); chip->name, revision);
/* /*
...@@ -205,15 +203,14 @@ int __init ali_ircc_init(void) ...@@ -205,15 +203,14 @@ int __init ali_ircc_init(void)
} }
else else
{ {
IRDA_DEBUG(2, __FUNCTION__ IRDA_DEBUG(2, "%s(), No %s chip at 0x%03x\n", __FUNCTION__, chip->name, cfg_base);
"(), No %s chip at 0x%03x\n", chip->name, cfg_base);
} }
/* Exit configuration */ /* Exit configuration */
outb(0xbb, cfg_base); outb(0xbb, cfg_base);
} }
} }
IRDA_DEBUG(2, __FUNCTION__ "(), ----------------- End -----------------\n"); IRDA_DEBUG(2, "%s(), ----------------- End -----------------\n", __FUNCTION__);
return ret; return ret;
} }
...@@ -227,7 +224,7 @@ static void __exit ali_ircc_cleanup(void) ...@@ -227,7 +224,7 @@ static void __exit ali_ircc_cleanup(void)
{ {
int i; int i;
IRDA_DEBUG(2, __FUNCTION__ "(), ---------------- Start ----------------\n"); IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);
pm_unregister_all(ali_ircc_pmproc); pm_unregister_all(ali_ircc_pmproc);
...@@ -236,7 +233,7 @@ static void __exit ali_ircc_cleanup(void) ...@@ -236,7 +233,7 @@ static void __exit ali_ircc_cleanup(void)
ali_ircc_close(dev_self[i]); ali_ircc_close(dev_self[i]);
} }
IRDA_DEBUG(2, __FUNCTION__ "(), ----------------- End -----------------\n"); IRDA_DEBUG(2, "%s(), ----------------- End -----------------\n", __FUNCTION__);
} }
/* /*
...@@ -251,9 +248,10 @@ static int ali_ircc_open(int i, chipio_t *info) ...@@ -251,9 +248,10 @@ static int ali_ircc_open(int i, chipio_t *info)
struct ali_ircc_cb *self; struct ali_ircc_cb *self;
struct pm_dev *pmdev; struct pm_dev *pmdev;
int dongle_id; int dongle_id;
int ret;
int err; int err;
IRDA_DEBUG(2, __FUNCTION__ "(), ---------------- Start ----------------\n"); IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);
/* Set FIR FIFO and DMA Threshold */ /* Set FIR FIFO and DMA Threshold */
if ((ali_ircc_setup(info)) == -1) if ((ali_ircc_setup(info)) == -1)
...@@ -263,7 +261,7 @@ static int ali_ircc_open(int i, chipio_t *info) ...@@ -263,7 +261,7 @@ static int ali_ircc_open(int i, chipio_t *info)
self = kmalloc(sizeof(struct ali_ircc_cb), GFP_KERNEL); self = kmalloc(sizeof(struct ali_ircc_cb), GFP_KERNEL);
if (self == NULL) if (self == NULL)
{ {
ERROR(__FUNCTION__ "(), can't allocate memory for control block!\n"); ERROR("%s(), can't allocate memory for control block!\n", __FUNCTION__);
return -ENOMEM; return -ENOMEM;
} }
memset(self, 0, sizeof(struct ali_ircc_cb)); memset(self, 0, sizeof(struct ali_ircc_cb));
...@@ -285,7 +283,7 @@ static int ali_ircc_open(int i, chipio_t *info) ...@@ -285,7 +283,7 @@ static int ali_ircc_open(int i, chipio_t *info)
/* Reserve the ioports that we need */ /* Reserve the ioports that we need */
ret = check_region(self->io.fir_base, self->io.fir_ext); ret = check_region(self->io.fir_base, self->io.fir_ext);
if (ret < 0) { if (ret < 0) {
WARNING(__FUNCTION__ "(), can't get iobase of 0x%03x\n", WARNING("%s(), can't get iobase of 0x%03x\n", __FUNCTION__,
self->io.fir_base); self->io.fir_base);
dev_self[i] = NULL; dev_self[i] = NULL;
kfree(self); kfree(self);
...@@ -339,7 +337,7 @@ static int ali_ircc_open(int i, chipio_t *info) ...@@ -339,7 +337,7 @@ static int ali_ircc_open(int i, chipio_t *info)
self->tx_fifo.tail = self->tx_buff.head; self->tx_fifo.tail = self->tx_buff.head;
if (!(dev = dev_alloc("irda%d", &err))) { if (!(dev = dev_alloc("irda%d", &err))) {
ERROR(__FUNCTION__ "(), dev_alloc() failed!\n"); ERROR("%s(), dev_alloc() failed!\n", __FUNCTION__);
return -ENOMEM; return -ENOMEM;
} }
...@@ -358,14 +356,14 @@ static int ali_ircc_open(int i, chipio_t *info) ...@@ -358,14 +356,14 @@ static int ali_ircc_open(int i, chipio_t *info)
err = register_netdevice(dev); err = register_netdevice(dev);
rtnl_unlock(); rtnl_unlock();
if (err) { if (err) {
ERROR(__FUNCTION__ "(), register_netdev() failed!\n"); ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
return -1; return -1;
} }
MESSAGE("IrDA: Registered device %s\n", dev->name); MESSAGE("IrDA: Registered device %s\n", dev->name);
/* Check dongle id */ /* Check dongle id */
dongle_id = ali_ircc_read_dongle_id(i, info); dongle_id = ali_ircc_read_dongle_id(i, info);
MESSAGE(__FUNCTION__ "(), %s, Found dongle: %s\n", driver_name, dongle_types[dongle_id]); MESSAGE("%s(), %s, Found dongle: %s\n", __FUNCTION__, driver_name, dongle_types[dongle_id]);
self->io.dongle_id = dongle_id; self->io.dongle_id = dongle_id;
...@@ -373,7 +371,7 @@ static int ali_ircc_open(int i, chipio_t *info) ...@@ -373,7 +371,7 @@ static int ali_ircc_open(int i, chipio_t *info)
if (pmdev) if (pmdev)
pmdev->data = self; pmdev->data = self;
IRDA_DEBUG(2, __FUNCTION__ "(), ----------------- End -----------------\n"); IRDA_DEBUG(2, "%s(), ----------------- End -----------------\n", __FUNCTION__);
return 0; return 0;
} }
...@@ -389,7 +387,7 @@ static int __exit ali_ircc_close(struct ali_ircc_cb *self) ...@@ -389,7 +387,7 @@ static int __exit ali_ircc_close(struct ali_ircc_cb *self)
{ {
int iobase; int iobase;
IRDA_DEBUG(4, __FUNCTION__ "(), ---------------- Start ----------------\n"); IRDA_DEBUG(4, "%s(), ---------------- Start ----------------\n", __FUNCTION__);
ASSERT(self != NULL, return -1;); ASSERT(self != NULL, return -1;);
...@@ -403,7 +401,7 @@ static int __exit ali_ircc_close(struct ali_ircc_cb *self) ...@@ -403,7 +401,7 @@ static int __exit ali_ircc_close(struct ali_ircc_cb *self)
} }
/* Release the PORT that this driver is using */ /* Release the PORT that this driver is using */
IRDA_DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", self->io.fir_base); IRDA_DEBUG(4, "%s(), Releasing Region %03x\n", __FUNCTION__, self->io.fir_base);
release_region(self->io.fir_base, self->io.fir_ext); release_region(self->io.fir_base, self->io.fir_ext);
if (self->tx_buff.head) if (self->tx_buff.head)
...@@ -415,7 +413,7 @@ static int __exit ali_ircc_close(struct ali_ircc_cb *self) ...@@ -415,7 +413,7 @@ static int __exit ali_ircc_close(struct ali_ircc_cb *self)
dev_self[self->index] = NULL; dev_self[self->index] = NULL;
kfree(self); kfree(self);
IRDA_DEBUG(2, __FUNCTION__ "(), ----------------- End -----------------\n"); IRDA_DEBUG(2, "%s(), ----------------- End -----------------\n", __FUNCTION__);
return 0; return 0;
} }
...@@ -458,7 +456,7 @@ static int ali_ircc_probe_53(ali_chip_t *chip, chipio_t *info) ...@@ -458,7 +456,7 @@ static int ali_ircc_probe_53(ali_chip_t *chip, chipio_t *info)
int cfg_base = info->cfg_base; int cfg_base = info->cfg_base;
int hi, low, reg; int hi, low, reg;
IRDA_DEBUG(2, __FUNCTION__ "(), ---------------- Start ----------------\n"); IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);
/* Enter Configuration */ /* Enter Configuration */
outb(chip->entr1, cfg_base); outb(chip->entr1, cfg_base);
...@@ -477,13 +475,13 @@ static int ali_ircc_probe_53(ali_chip_t *chip, chipio_t *info) ...@@ -477,13 +475,13 @@ static int ali_ircc_probe_53(ali_chip_t *chip, chipio_t *info)
info->sir_base = info->fir_base; info->sir_base = info->fir_base;
IRDA_DEBUG(2, __FUNCTION__ "(), probing fir_base=0x%03x\n", info->fir_base); IRDA_DEBUG(2, "%s(), probing fir_base=0x%03x\n", __FUNCTION__, info->fir_base);
/* Read IRQ control register */ /* Read IRQ control register */
outb(0x70, cfg_base); outb(0x70, cfg_base);
reg = inb(cfg_base+1); reg = inb(cfg_base+1);
info->irq = reg & 0x0f; info->irq = reg & 0x0f;
IRDA_DEBUG(2, __FUNCTION__ "(), probing irq=%d\n", info->irq); IRDA_DEBUG(2, "%s(), probing irq=%d\n", __FUNCTION__, info->irq);
/* Read DMA channel */ /* Read DMA channel */
outb(0x74, cfg_base); outb(0x74, cfg_base);
...@@ -491,26 +489,26 @@ static int ali_ircc_probe_53(ali_chip_t *chip, chipio_t *info) ...@@ -491,26 +489,26 @@ static int ali_ircc_probe_53(ali_chip_t *chip, chipio_t *info)
info->dma = reg & 0x07; info->dma = reg & 0x07;
if(info->dma == 0x04) if(info->dma == 0x04)
WARNING(__FUNCTION__ "(), No DMA channel assigned !\n"); WARNING("%s(), No DMA channel assigned !\n", __FUNCTION__);
else else
IRDA_DEBUG(2, __FUNCTION__ "(), probing dma=%d\n", info->dma); IRDA_DEBUG(2, "%s(), probing dma=%d\n", __FUNCTION__, info->dma);
/* Read Enabled Status */ /* Read Enabled Status */
outb(0x30, cfg_base); outb(0x30, cfg_base);
reg = inb(cfg_base+1); reg = inb(cfg_base+1);
info->enabled = (reg & 0x80) && (reg & 0x01); info->enabled = (reg & 0x80) && (reg & 0x01);
IRDA_DEBUG(2, __FUNCTION__ "(), probing enabled=%d\n", info->enabled); IRDA_DEBUG(2, "%s(), probing enabled=%d\n", __FUNCTION__, info->enabled);
/* Read Power Status */ /* Read Power Status */
outb(0x22, cfg_base); outb(0x22, cfg_base);
reg = inb(cfg_base+1); reg = inb(cfg_base+1);
info->suspended = (reg & 0x20); info->suspended = (reg & 0x20);
IRDA_DEBUG(2, __FUNCTION__ "(), probing suspended=%d\n", info->suspended); IRDA_DEBUG(2, "%s(), probing suspended=%d\n", __FUNCTION__, info->suspended);
/* Exit configuration */ /* Exit configuration */
outb(0xbb, cfg_base); outb(0xbb, cfg_base);
IRDA_DEBUG(2, __FUNCTION__ "(), ----------------- End -----------------\n"); IRDA_DEBUG(2, "%s(), ----------------- End -----------------\n", __FUNCTION__);
return 0; return 0;
} }
...@@ -528,8 +526,13 @@ static int ali_ircc_setup(chipio_t *info) ...@@ -528,8 +526,13 @@ static int ali_ircc_setup(chipio_t *info)
int version; int version;
int iobase = info->fir_base; int iobase = info->fir_base;
IRDA_DEBUG(2, __FUNCTION__ "(), ---------------- Start ----------------\n"); IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);
/* Locking comments :
* Most operations here need to be protected. We are called before
* the device instance is created in ali_ircc_open(), therefore
* nobody can bother us - Jean II */
/* Switch to FIR space */ /* Switch to FIR space */
SIR2FIR(iobase); SIR2FIR(iobase);
...@@ -584,7 +587,7 @@ static int ali_ircc_setup(chipio_t *info) ...@@ -584,7 +587,7 @@ static int ali_ircc_setup(chipio_t *info)
// outb(UART_IER_RDI, iobase+UART_IER); //benjamin 2000/11/23 01:25PM // outb(UART_IER_RDI, iobase+UART_IER); //benjamin 2000/11/23 01:25PM
// Turn on the interrupts in ali_ircc_net_open // Turn on the interrupts in ali_ircc_net_open
IRDA_DEBUG(2, __FUNCTION__ "(), ----------------- End ------------------\n"); IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__);
return 0; return 0;
} }
...@@ -601,7 +604,7 @@ static int ali_ircc_read_dongle_id (int i, chipio_t *info) ...@@ -601,7 +604,7 @@ static int ali_ircc_read_dongle_id (int i, chipio_t *info)
int dongle_id, reg; int dongle_id, reg;
int cfg_base = info->cfg_base; int cfg_base = info->cfg_base;
IRDA_DEBUG(2, __FUNCTION__ "(), ---------------- Start ----------------\n"); IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);
/* Enter Configuration */ /* Enter Configuration */
outb(chips[i].entr1, cfg_base); outb(chips[i].entr1, cfg_base);
...@@ -615,13 +618,13 @@ static int ali_ircc_read_dongle_id (int i, chipio_t *info) ...@@ -615,13 +618,13 @@ static int ali_ircc_read_dongle_id (int i, chipio_t *info)
outb(0xf0, cfg_base); outb(0xf0, cfg_base);
reg = inb(cfg_base+1); reg = inb(cfg_base+1);
dongle_id = ((reg>>6)&0x02) | ((reg>>5)&0x01); dongle_id = ((reg>>6)&0x02) | ((reg>>5)&0x01);
IRDA_DEBUG(2, __FUNCTION__ "(), probing dongle_id=%d, dongle_types=%s\n", IRDA_DEBUG(2, "%s(), probing dongle_id=%d, dongle_types=%s\n", __FUNCTION__,
dongle_id, dongle_types[dongle_id]); dongle_id, dongle_types[dongle_id]);
/* Exit configuration */ /* Exit configuration */
outb(0xbb, cfg_base); outb(0xbb, cfg_base);
IRDA_DEBUG(2, __FUNCTION__ "(), ----------------- End ------------------\n"); IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__);
return dongle_id; return dongle_id;
} }
...@@ -637,7 +640,7 @@ static void ali_ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -637,7 +640,7 @@ static void ali_ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
struct net_device *dev = (struct net_device *) dev_id; struct net_device *dev = (struct net_device *) dev_id;
struct ali_ircc_cb *self; struct ali_ircc_cb *self;
IRDA_DEBUG(2, __FUNCTION__ "(), ---------------- Start ----------------\n"); IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);
if (!dev) { if (!dev) {
WARNING("%s: irq %d for unknown device.\n", driver_name, irq); WARNING("%s: irq %d for unknown device.\n", driver_name, irq);
...@@ -656,7 +659,7 @@ static void ali_ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -656,7 +659,7 @@ static void ali_ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
spin_unlock(&self->lock); spin_unlock(&self->lock);
IRDA_DEBUG(2, __FUNCTION__ "(), ----------------- End ------------------\n"); IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__);
} }
/* /*
* Function ali_ircc_fir_interrupt(irq, struct ali_ircc_cb *self, regs) * Function ali_ircc_fir_interrupt(irq, struct ali_ircc_cb *self, regs)
...@@ -669,7 +672,7 @@ static void ali_ircc_fir_interrupt(int irq, struct ali_ircc_cb *self, struct pt_ ...@@ -669,7 +672,7 @@ static void ali_ircc_fir_interrupt(int irq, struct ali_ircc_cb *self, struct pt_
__u8 eir, OldMessageCount; __u8 eir, OldMessageCount;
int iobase, tmp; int iobase, tmp;
IRDA_DEBUG(1, __FUNCTION__ "(), ---------------- Start ----------------\n"); IRDA_DEBUG(1, "%s(), ---------------- Start ----------------\n", __FUNCTION__);
iobase = self->io.fir_base; iobase = self->io.fir_base;
...@@ -682,10 +685,10 @@ static void ali_ircc_fir_interrupt(int irq, struct ali_ircc_cb *self, struct pt_ ...@@ -682,10 +685,10 @@ static void ali_ircc_fir_interrupt(int irq, struct ali_ircc_cb *self, struct pt_
//self->ier = inb(iobase+FIR_IER); 2000/12/1 04:32PM //self->ier = inb(iobase+FIR_IER); 2000/12/1 04:32PM
eir = self->InterruptID & self->ier; /* Mask out the interesting ones */ eir = self->InterruptID & self->ier; /* Mask out the interesting ones */
IRDA_DEBUG(1, __FUNCTION__ "(), self->InterruptID = %x\n",self->InterruptID); IRDA_DEBUG(1, "%s(), self->InterruptID = %x\n", __FUNCTION__,self->InterruptID);
IRDA_DEBUG(1, __FUNCTION__ "(), self->LineStatus = %x\n",self->LineStatus); IRDA_DEBUG(1, "%s(), self->LineStatus = %x\n", __FUNCTION__,self->LineStatus);
IRDA_DEBUG(1, __FUNCTION__ "(), self->ier = %x\n",self->ier); IRDA_DEBUG(1, "%s(), self->ier = %x\n", __FUNCTION__,self->ier);
IRDA_DEBUG(1, __FUNCTION__ "(), eir = %x\n",eir); IRDA_DEBUG(1, "%s(), eir = %x\n", __FUNCTION__,eir);
/* Disable interrupts */ /* Disable interrupts */
SetCOMInterrupts(self, FALSE); SetCOMInterrupts(self, FALSE);
...@@ -696,7 +699,7 @@ static void ali_ircc_fir_interrupt(int irq, struct ali_ircc_cb *self, struct pt_ ...@@ -696,7 +699,7 @@ static void ali_ircc_fir_interrupt(int irq, struct ali_ircc_cb *self, struct pt_
{ {
if (self->io.direction == IO_XMIT) /* TX */ if (self->io.direction == IO_XMIT) /* TX */
{ {
IRDA_DEBUG(1, __FUNCTION__ "(), ******* IIR_EOM (Tx) *******\n"); IRDA_DEBUG(1, "%s(), ******* IIR_EOM (Tx) *******\n", __FUNCTION__);
if(ali_ircc_dma_xmit_complete(self)) if(ali_ircc_dma_xmit_complete(self))
{ {
...@@ -715,23 +718,23 @@ static void ali_ircc_fir_interrupt(int irq, struct ali_ircc_cb *self, struct pt_ ...@@ -715,23 +718,23 @@ static void ali_ircc_fir_interrupt(int irq, struct ali_ircc_cb *self, struct pt_
} }
else /* RX */ else /* RX */
{ {
IRDA_DEBUG(1, __FUNCTION__ "(), ******* IIR_EOM (Rx) *******\n"); IRDA_DEBUG(1, "%s(), ******* IIR_EOM (Rx) *******\n", __FUNCTION__);
if(OldMessageCount > ((self->LineStatus+1) & 0x07)) if(OldMessageCount > ((self->LineStatus+1) & 0x07))
{ {
self->rcvFramesOverflow = TRUE; self->rcvFramesOverflow = TRUE;
IRDA_DEBUG(1, __FUNCTION__ "(), ******* self->rcvFramesOverflow = TRUE ******** \n"); IRDA_DEBUG(1, "%s(), ******* self->rcvFramesOverflow = TRUE ******** \n", __FUNCTION__);
} }
if (ali_ircc_dma_receive_complete(self)) if (ali_ircc_dma_receive_complete(self))
{ {
IRDA_DEBUG(1, __FUNCTION__ "(), ******* receive complete ******** \n"); IRDA_DEBUG(1, "%s(), ******* receive complete ******** \n", __FUNCTION__);
self->ier = IER_EOM; self->ier = IER_EOM;
} }
else else
{ {
IRDA_DEBUG(1, __FUNCTION__ "(), ******* Not receive complete ******** \n"); IRDA_DEBUG(1, "%s(), ******* Not receive complete ******** \n", __FUNCTION__);
self->ier = IER_EOM | IER_TIMER; self->ier = IER_EOM | IER_TIMER;
} }
...@@ -744,7 +747,7 @@ static void ali_ircc_fir_interrupt(int irq, struct ali_ircc_cb *self, struct pt_ ...@@ -744,7 +747,7 @@ static void ali_ircc_fir_interrupt(int irq, struct ali_ircc_cb *self, struct pt_
if(OldMessageCount > ((self->LineStatus+1) & 0x07)) if(OldMessageCount > ((self->LineStatus+1) & 0x07))
{ {
self->rcvFramesOverflow = TRUE; self->rcvFramesOverflow = TRUE;
IRDA_DEBUG(1, __FUNCTION__ "(), ******* self->rcvFramesOverflow = TRUE ******* \n"); IRDA_DEBUG(1, "%s(), ******* self->rcvFramesOverflow = TRUE ******* \n", __FUNCTION__);
} }
/* Disable Timer */ /* Disable Timer */
switch_bank(iobase, BANK1); switch_bank(iobase, BANK1);
...@@ -776,7 +779,7 @@ static void ali_ircc_fir_interrupt(int irq, struct ali_ircc_cb *self, struct pt_ ...@@ -776,7 +779,7 @@ static void ali_ircc_fir_interrupt(int irq, struct ali_ircc_cb *self, struct pt_
/* Restore Interrupt */ /* Restore Interrupt */
SetCOMInterrupts(self, TRUE); SetCOMInterrupts(self, TRUE);
IRDA_DEBUG(1, __FUNCTION__ "(), ----------------- End ---------------\n"); IRDA_DEBUG(1, "%s(), ----------------- End ---------------\n", __FUNCTION__);
} }
/* /*
...@@ -790,7 +793,7 @@ static void ali_ircc_sir_interrupt(int irq, struct ali_ircc_cb *self, struct pt_ ...@@ -790,7 +793,7 @@ static void ali_ircc_sir_interrupt(int irq, struct ali_ircc_cb *self, struct pt_
int iobase; int iobase;
int iir, lsr; int iir, lsr;
IRDA_DEBUG(2, __FUNCTION__ "(), ---------------- Start ----------------\n"); IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);
iobase = self->io.sir_base; iobase = self->io.sir_base;
...@@ -799,14 +802,13 @@ static void ali_ircc_sir_interrupt(int irq, struct ali_ircc_cb *self, struct pt_ ...@@ -799,14 +802,13 @@ static void ali_ircc_sir_interrupt(int irq, struct ali_ircc_cb *self, struct pt_
/* Clear interrupt */ /* Clear interrupt */
lsr = inb(iobase+UART_LSR); lsr = inb(iobase+UART_LSR);
IRDA_DEBUG(4, __FUNCTION__ IRDA_DEBUG(4, "%s(), iir=%02x, lsr=%02x, iobase=%#x\n", __FUNCTION__,
"(), iir=%02x, lsr=%02x, iobase=%#x\n",
iir, lsr, iobase); iir, lsr, iobase);
switch (iir) switch (iir)
{ {
case UART_IIR_RLSI: case UART_IIR_RLSI:
IRDA_DEBUG(2, __FUNCTION__ "(), RLSI\n"); IRDA_DEBUG(2, "%s(), RLSI\n", __FUNCTION__);
break; break;
case UART_IIR_RDI: case UART_IIR_RDI:
/* Receive interrupt */ /* Receive interrupt */
...@@ -820,14 +822,14 @@ static void ali_ircc_sir_interrupt(int irq, struct ali_ircc_cb *self, struct pt_ ...@@ -820,14 +822,14 @@ static void ali_ircc_sir_interrupt(int irq, struct ali_ircc_cb *self, struct pt_
} }
break; break;
default: default:
IRDA_DEBUG(0, __FUNCTION__ "(), unhandled IIR=%#x\n", iir); IRDA_DEBUG(0, "%s(), unhandled IIR=%#x\n", __FUNCTION__, iir);
break; break;
} }
} }
IRDA_DEBUG(2, __FUNCTION__ "(), ----------------- End ------------------\n"); IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__);
} }
...@@ -842,7 +844,7 @@ static void ali_ircc_sir_receive(struct ali_ircc_cb *self) ...@@ -842,7 +844,7 @@ static void ali_ircc_sir_receive(struct ali_ircc_cb *self)
int boguscount = 0; int boguscount = 0;
int iobase; int iobase;
IRDA_DEBUG(2, __FUNCTION__ "(), ---------------- Start ----------------\n"); IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);
ASSERT(self != NULL, return;); ASSERT(self != NULL, return;);
iobase = self->io.sir_base; iobase = self->io.sir_base;
...@@ -857,7 +859,7 @@ static void ali_ircc_sir_receive(struct ali_ircc_cb *self) ...@@ -857,7 +859,7 @@ static void ali_ircc_sir_receive(struct ali_ircc_cb *self)
/* Make sure we don't stay here to long */ /* Make sure we don't stay here to long */
if (boguscount++ > 32) { if (boguscount++ > 32) {
IRDA_DEBUG(2,__FUNCTION__ "(), breaking!\n"); IRDA_DEBUG(2,"%s(), breaking!\n", __FUNCTION__);
break; break;
} }
} while (inb(iobase+UART_LSR) & UART_LSR_DR); } while (inb(iobase+UART_LSR) & UART_LSR_DR);
...@@ -937,6 +939,9 @@ static void ali_ircc_change_speed(struct ali_ircc_cb *self, __u32 baud) ...@@ -937,6 +939,9 @@ static void ali_ircc_change_speed(struct ali_ircc_cb *self, __u32 baud)
IRDA_DEBUG(2, __FUNCTION__ "(), setting speed = %d \n", baud); IRDA_DEBUG(2, __FUNCTION__ "(), setting speed = %d \n", baud);
/* This function *must* be called with irq off and spin-lock.
* - Jean II */
iobase = self->io.fir_base; iobase = self->io.fir_base;
SetCOMInterrupts(self, FALSE); // 2000/11/24 11:43AM SetCOMInterrupts(self, FALSE); // 2000/11/24 11:43AM
...@@ -1084,7 +1089,6 @@ static void ali_ircc_change_dongle_speed(struct ali_ircc_cb *priv, int speed) ...@@ -1084,7 +1089,6 @@ static void ali_ircc_change_dongle_speed(struct ali_ircc_cb *priv, int speed)
struct ali_ircc_cb *self = (struct ali_ircc_cb *) priv; struct ali_ircc_cb *self = (struct ali_ircc_cb *) priv;
int iobase,dongle_id; int iobase,dongle_id;
unsigned long flags;
int tmp = 0; int tmp = 0;
IRDA_DEBUG(1, __FUNCTION__ "(), ---------------- Start ----------------\n"); IRDA_DEBUG(1, __FUNCTION__ "(), ---------------- Start ----------------\n");
...@@ -1092,8 +1096,7 @@ static void ali_ircc_change_dongle_speed(struct ali_ircc_cb *priv, int speed) ...@@ -1092,8 +1096,7 @@ static void ali_ircc_change_dongle_speed(struct ali_ircc_cb *priv, int speed)
iobase = self->io.fir_base; /* or iobase = self->io.sir_base; */ iobase = self->io.fir_base; /* or iobase = self->io.sir_base; */
dongle_id = self->io.dongle_id; dongle_id = self->io.dongle_id;
save_flags(flags); /* We are already locked, no need to do it again */
cli();
IRDA_DEBUG(1, __FUNCTION__ "(), Set Speed for %s , Speed = %d\n", dongle_types[dongle_id], speed); IRDA_DEBUG(1, __FUNCTION__ "(), Set Speed for %s , Speed = %d\n", dongle_types[dongle_id], speed);
...@@ -1259,8 +1262,6 @@ static void ali_ircc_change_dongle_speed(struct ali_ircc_cb *priv, int speed) ...@@ -1259,8 +1262,6 @@ static void ali_ircc_change_dongle_speed(struct ali_ircc_cb *priv, int speed)
switch_bank(iobase, BANK0); switch_bank(iobase, BANK0);
restore_flags(flags);
IRDA_DEBUG(1, __FUNCTION__ "(), ----------------- End ------------------\n"); IRDA_DEBUG(1, __FUNCTION__ "(), ----------------- End ------------------\n");
} }
...@@ -1440,20 +1441,26 @@ static int ali_ircc_fir_hard_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -1440,20 +1441,26 @@ static int ali_ircc_fir_hard_xmit(struct sk_buff *skb, struct net_device *dev)
netif_stop_queue(dev); netif_stop_queue(dev);
/* Make sure tests *& speed change are atomic */
spin_lock_irqsave(&self->lock, flags);
/* Note : you should make sure that speed changes are not going
* to corrupt any outgoing frame. Look at nsc-ircc for the gory
* details - Jean II */
/* Check if we need to change the speed */ /* Check if we need to change the speed */
speed = irda_get_next_speed(skb); speed = irda_get_next_speed(skb);
if ((speed != self->io.speed) && (speed != -1)) { if ((speed != self->io.speed) && (speed != -1)) {
/* Check for empty frame */ /* Check for empty frame */
if (!skb->len) { if (!skb->len) {
ali_ircc_change_speed(self, speed); ali_ircc_change_speed(self, speed);
spin_unlock_irqrestore(&self->lock, flags);
dev_kfree_skb(skb); dev_kfree_skb(skb);
return 0; return 0;
} else } else
self->new_speed = speed; self->new_speed = speed;
} }
spin_lock_irqsave(&self->lock, flags);
/* Register and copy this frame to DMA memory */ /* Register and copy this frame to DMA memory */
self->tx_fifo.queue[self->tx_fifo.free].start = self->tx_fifo.tail; self->tx_fifo.queue[self->tx_fifo.free].start = self->tx_fifo.tail;
self->tx_fifo.queue[self->tx_fifo.free].len = skb->len; self->tx_fifo.queue[self->tx_fifo.free].len = skb->len;
...@@ -1651,7 +1658,7 @@ static int ali_ircc_dma_xmit_complete(struct ali_ircc_cb *self) ...@@ -1651,7 +1658,7 @@ static int ali_ircc_dma_xmit_complete(struct ali_ircc_cb *self)
if((inb(iobase+FIR_LSR) & LSR_FRAME_ABORT) == LSR_FRAME_ABORT) if((inb(iobase+FIR_LSR) & LSR_FRAME_ABORT) == LSR_FRAME_ABORT)
{ {
ERROR(__FUNCTION__ "(), ********* LSR_FRAME_ABORT *********\n"); ERROR("%s(), ********* LSR_FRAME_ABORT *********\n", __FUNCTION__);
self->stats.tx_errors++; self->stats.tx_errors++;
self->stats.tx_fifo_errors++; self->stats.tx_fifo_errors++;
} }
...@@ -1898,8 +1905,8 @@ static int ali_ircc_dma_receive_complete(struct ali_ircc_cb *self) ...@@ -1898,8 +1905,8 @@ static int ali_ircc_dma_receive_complete(struct ali_ircc_cb *self)
skb = dev_alloc_skb(len+1); skb = dev_alloc_skb(len+1);
if (skb == NULL) if (skb == NULL)
{ {
WARNING(__FUNCTION__ "(), memory squeeze, " WARNING("%s(), memory squeeze, "
"dropping frame.\n"); "dropping frame.\n", __FUNCTION__);
self->stats.rx_dropped++; self->stats.rx_dropped++;
return FALSE; return FALSE;
...@@ -1957,20 +1964,26 @@ static int ali_ircc_sir_hard_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -1957,20 +1964,26 @@ static int ali_ircc_sir_hard_xmit(struct sk_buff *skb, struct net_device *dev)
netif_stop_queue(dev); netif_stop_queue(dev);
/* Make sure tests *& speed change are atomic */
spin_lock_irqsave(&self->lock, flags);
/* Note : you should make sure that speed changes are not going
* to corrupt any outgoing frame. Look at nsc-ircc for the gory
* details - Jean II */
/* Check if we need to change the speed */ /* Check if we need to change the speed */
speed = irda_get_next_speed(skb); speed = irda_get_next_speed(skb);
if ((speed != self->io.speed) && (speed != -1)) { if ((speed != self->io.speed) && (speed != -1)) {
/* Check for empty frame */ /* Check for empty frame */
if (!skb->len) { if (!skb->len) {
ali_ircc_change_speed(self, speed); ali_ircc_change_speed(self, speed);
spin_unlock_irqrestore(&self->lock, flags);
dev_kfree_skb(skb); dev_kfree_skb(skb);
return 0; return 0;
} else } else
self->new_speed = speed; self->new_speed = speed;
} }
spin_lock_irqsave(&self->lock, flags);
/* Init tx buffer */ /* Init tx buffer */
self->tx_buff.data = self->tx_buff.head; self->tx_buff.data = self->tx_buff.head;
...@@ -2016,10 +2029,6 @@ static int ali_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -2016,10 +2029,6 @@ static int ali_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd); IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
/* Disable interrupts & save flags */
save_flags(flags);
cli();
switch (cmd) { switch (cmd) {
case SIOCSBANDWIDTH: /* Set bandwidth */ case SIOCSBANDWIDTH: /* Set bandwidth */
IRDA_DEBUG(1, __FUNCTION__ "(), SIOCSBANDWIDTH\n"); IRDA_DEBUG(1, __FUNCTION__ "(), SIOCSBANDWIDTH\n");
...@@ -2031,7 +2040,9 @@ static int ali_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -2031,7 +2040,9 @@ static int ali_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
if (!in_interrupt() && !capable(CAP_NET_ADMIN)) if (!in_interrupt() && !capable(CAP_NET_ADMIN))
return -EPERM; return -EPERM;
spin_lock_irqsave(&self->lock, flags);
ali_ircc_change_speed(self, irq->ifr_baudrate); ali_ircc_change_speed(self, irq->ifr_baudrate);
spin_unlock_irqrestore(&self->lock, flags);
break; break;
case SIOCSMEDIABUSY: /* Set media busy */ case SIOCSMEDIABUSY: /* Set media busy */
IRDA_DEBUG(1, __FUNCTION__ "(), SIOCSMEDIABUSY\n"); IRDA_DEBUG(1, __FUNCTION__ "(), SIOCSMEDIABUSY\n");
...@@ -2041,14 +2052,13 @@ static int ali_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -2041,14 +2052,13 @@ static int ali_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
break; break;
case SIOCGRECEIVING: /* Check if we are receiving right now */ case SIOCGRECEIVING: /* Check if we are receiving right now */
IRDA_DEBUG(2, __FUNCTION__ "(), SIOCGRECEIVING\n"); IRDA_DEBUG(2, __FUNCTION__ "(), SIOCGRECEIVING\n");
/* This is protected */
irq->ifr_receiving = ali_ircc_is_receiving(self); irq->ifr_receiving = ali_ircc_is_receiving(self);
break; break;
default: default:
ret = -EOPNOTSUPP; ret = -EOPNOTSUPP;
} }
restore_flags(flags);
IRDA_DEBUG(2, __FUNCTION__ "(), ----------------- End ------------------\n"); IRDA_DEBUG(2, __FUNCTION__ "(), ----------------- End ------------------\n");
return ret; return ret;
...@@ -2219,19 +2229,16 @@ static void SetCOMInterrupts(struct ali_ircc_cb *self , unsigned char enable) ...@@ -2219,19 +2229,16 @@ static void SetCOMInterrupts(struct ali_ircc_cb *self , unsigned char enable)
static void SIR2FIR(int iobase) static void SIR2FIR(int iobase)
{ {
//unsigned char tmp; //unsigned char tmp;
unsigned long flags;
IRDA_DEBUG(1, __FUNCTION__ "(), ---------------- Start ----------------\n"); IRDA_DEBUG(1, __FUNCTION__ "(), ---------------- Start ----------------\n");
save_flags(flags); /* Already protected (change_speed() or setup()), no need to lock.
cli(); * Jean II */
outb(0x28, iobase+UART_MCR); outb(0x28, iobase+UART_MCR);
outb(0x68, iobase+UART_MCR); outb(0x68, iobase+UART_MCR);
outb(0x88, iobase+UART_MCR); outb(0x88, iobase+UART_MCR);
restore_flags(flags);
outb(0x60, iobase+FIR_MCR); /* Master Reset */ outb(0x60, iobase+FIR_MCR); /* Master Reset */
outb(0x20, iobase+FIR_MCR); /* Master Interrupt Enable */ outb(0x20, iobase+FIR_MCR); /* Master Interrupt Enable */
...@@ -2245,12 +2252,11 @@ static void SIR2FIR(int iobase) ...@@ -2245,12 +2252,11 @@ static void SIR2FIR(int iobase)
static void FIR2SIR(int iobase) static void FIR2SIR(int iobase)
{ {
unsigned char val; unsigned char val;
unsigned long flags;
IRDA_DEBUG(1, __FUNCTION__ "(), ---------------- Start ----------------\n"); IRDA_DEBUG(1, __FUNCTION__ "(), ---------------- Start ----------------\n");
save_flags(flags); /* Already protected (change_speed() or setup()), no need to lock.
cli(); * Jean II */
outb(0x20, iobase+FIR_MCR); /* IRQ to low */ outb(0x20, iobase+FIR_MCR); /* IRQ to low */
outb(0x00, iobase+UART_IER); outb(0x00, iobase+UART_IER);
...@@ -2263,8 +2269,6 @@ static void FIR2SIR(int iobase) ...@@ -2263,8 +2269,6 @@ static void FIR2SIR(int iobase)
val = inb(iobase+UART_LSR); val = inb(iobase+UART_LSR);
val = inb(iobase+UART_MSR); val = inb(iobase+UART_MSR);
restore_flags(flags);
IRDA_DEBUG(1, __FUNCTION__ "(), ----------------- End ------------------\n"); IRDA_DEBUG(1, __FUNCTION__ "(), ----------------- End ------------------\n");
} }
......
...@@ -129,7 +129,7 @@ static int girbil_change_speed(struct irda_task *task) ...@@ -129,7 +129,7 @@ static int girbil_change_speed(struct irda_task *task)
} }
break; break;
case IRDA_TASK_CHILD_WAIT: case IRDA_TASK_CHILD_WAIT:
WARNING(__FUNCTION__ "(), resetting dongle timed out!\n"); WARNING("%s(), resetting dongle timed out!\n", __FUNCTION__);
ret = -1; ret = -1;
break; break;
case IRDA_TASK_CHILD_DONE: case IRDA_TASK_CHILD_DONE:
...@@ -168,7 +168,7 @@ static int girbil_change_speed(struct irda_task *task) ...@@ -168,7 +168,7 @@ static int girbil_change_speed(struct irda_task *task)
self->speed_task = NULL; self->speed_task = NULL;
break; break;
default: default:
ERROR(__FUNCTION__ "(), unknown state %d\n", task->state); ERROR("%s(), unknown state %d\n", __FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE); irda_task_next_state(task, IRDA_TASK_DONE);
self->speed_task = NULL; self->speed_task = NULL;
ret = -1; ret = -1;
...@@ -221,7 +221,7 @@ static int girbil_reset(struct irda_task *task) ...@@ -221,7 +221,7 @@ static int girbil_reset(struct irda_task *task)
self->reset_task = NULL; self->reset_task = NULL;
break; break;
default: default:
ERROR(__FUNCTION__ "(), unknown state %d\n", task->state); ERROR("%s(), unknown state %d\n", __FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE); irda_task_next_state(task, IRDA_TASK_DONE);
self->reset_task = NULL; self->reset_task = NULL;
ret = -1; ret = -1;
......
...@@ -1171,7 +1171,7 @@ static inline int irda_usb_open(struct irda_usb_cb *self) ...@@ -1171,7 +1171,7 @@ static inline int irda_usb_open(struct irda_usb_cb *self)
irda_usb_init_qos(self); irda_usb_init_qos(self);
/* Initialise list of skb beeing curently transmitted */ /* Initialise list of skb beeing curently transmitted */
self->tx_list = hashbin_new(HB_GLOBAL); self->tx_list = hashbin_new(HB_NOLOCK); /* unused */
/* Allocate the buffer for speed changes */ /* Allocate the buffer for speed changes */
/* Don't change this buffer size and allocation without doing /* Don't change this buffer size and allocation without doing
......
...@@ -124,7 +124,7 @@ static void __exit irport_cleanup(void) ...@@ -124,7 +124,7 @@ static void __exit irport_cleanup(void)
{ {
int i; int i;
IRDA_DEBUG( 4, __FUNCTION__ "()\n"); IRDA_DEBUG( 4, "%s()\n", __FUNCTION__);
for (i=0; i < 4; i++) { for (i=0; i < 4; i++) {
if (dev_self[i]) if (dev_self[i])
...@@ -140,15 +140,15 @@ irport_open(int i, unsigned int iobase, unsigned int irq) ...@@ -140,15 +140,15 @@ irport_open(int i, unsigned int iobase, unsigned int irq)
void *ret; void *ret;
int err; int err;
IRDA_DEBUG(0, __FUNCTION__ "()\n"); IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
/* /*
* Allocate new instance of the driver * Allocate new instance of the driver
*/ */
self = kmalloc(sizeof(struct irport_cb), GFP_KERNEL); self = kmalloc(sizeof(struct irport_cb), GFP_KERNEL);
if (!self) { if (!self) {
ERROR(__FUNCTION__ "(), can't allocate memory for " ERROR("%s(), can't allocate memory for "
"control block!\n"); "control block!\n", __FUNCTION__);
return NULL; return NULL;
} }
memset(self, 0, sizeof(struct irport_cb)); memset(self, 0, sizeof(struct irport_cb));
...@@ -168,8 +168,8 @@ irport_open(int i, unsigned int iobase, unsigned int irq) ...@@ -168,8 +168,8 @@ irport_open(int i, unsigned int iobase, unsigned int irq)
/* Lock the port that we need */ /* Lock the port that we need */
ret = request_region(self->io.sir_base, self->io.sir_ext, driver_name); ret = request_region(self->io.sir_base, self->io.sir_ext, driver_name);
if (!ret) { if (!ret) {
IRDA_DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n", IRDA_DEBUG(0, "%s(), can't get iobase of 0x%03x\n",
self->io.sir_base); __FUNCTION__, self->io.sir_base);
return NULL; return NULL;
} }
...@@ -212,7 +212,7 @@ irport_open(int i, unsigned int iobase, unsigned int irq) ...@@ -212,7 +212,7 @@ irport_open(int i, unsigned int iobase, unsigned int irq)
self->mode = IRDA_IRLAP; self->mode = IRDA_IRLAP;
if (!(dev = dev_alloc("irda%d", &err))) { if (!(dev = dev_alloc("irda%d", &err))) {
ERROR(__FUNCTION__ "(), dev_alloc() failed!\n"); ERROR("%s(), dev_alloc() failed!\n", __FUNCTION__);
return NULL; return NULL;
} }
self->netdev = dev; self->netdev = dev;
...@@ -240,7 +240,7 @@ irport_open(int i, unsigned int iobase, unsigned int irq) ...@@ -240,7 +240,7 @@ irport_open(int i, unsigned int iobase, unsigned int irq)
err = register_netdevice(dev); err = register_netdevice(dev);
rtnl_unlock(); rtnl_unlock();
if (err) { if (err) {
ERROR(__FUNCTION__ "(), register_netdev() failed!\n"); ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
return NULL; return NULL;
} }
MESSAGE("IrDA: Registered device %s\n", dev->name); MESSAGE("IrDA: Registered device %s\n", dev->name);
...@@ -265,8 +265,8 @@ int irport_close(struct irport_cb *self) ...@@ -265,8 +265,8 @@ int irport_close(struct irport_cb *self)
} }
/* Release the IO-port that this driver is using */ /* Release the IO-port that this driver is using */
IRDA_DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n", IRDA_DEBUG(0 , "%s(), Releasing Region %03x\n",
self->io.sir_base); __FUNCTION__, self->io.sir_base);
release_region(self->io.sir_base, self->io.sir_ext); release_region(self->io.sir_base, self->io.sir_ext);
if (self->tx_buff.head) if (self->tx_buff.head)
...@@ -284,14 +284,13 @@ int irport_close(struct irport_cb *self) ...@@ -284,14 +284,13 @@ int irport_close(struct irport_cb *self)
void irport_start(struct irport_cb *self) void irport_start(struct irport_cb *self)
{ {
unsigned long flags;
int iobase; int iobase;
iobase = self->io.sir_base; iobase = self->io.sir_base;
irport_stop(self); irport_stop(self);
spin_lock_irqsave(&self->lock, flags); /* We can't lock, we may be called from a FIR driver - Jean II */
/* Initialize UART */ /* Initialize UART */
outb(UART_LCR_WLEN8, iobase+UART_LCR); /* Reset DLAB */ outb(UART_LCR_WLEN8, iobase+UART_LCR); /* Reset DLAB */
...@@ -299,26 +298,21 @@ void irport_start(struct irport_cb *self) ...@@ -299,26 +298,21 @@ void irport_start(struct irport_cb *self)
/* Turn on interrups */ /* Turn on interrups */
outb(UART_IER_RLSI | UART_IER_RDI |UART_IER_THRI, iobase+UART_IER); outb(UART_IER_RLSI | UART_IER_RDI |UART_IER_THRI, iobase+UART_IER);
spin_unlock_irqrestore(&self->lock, flags);
} }
void irport_stop(struct irport_cb *self) void irport_stop(struct irport_cb *self)
{ {
unsigned long flags;
int iobase; int iobase;
iobase = self->io.sir_base; iobase = self->io.sir_base;
spin_lock_irqsave(&self->lock, flags); /* We can't lock, we may be called from a FIR driver - Jean II */
/* Reset UART */ /* Reset UART */
outb(0, iobase+UART_MCR); outb(0, iobase+UART_MCR);
/* Turn off interrupts */ /* Turn off interrupts */
outb(0, iobase+UART_IER); outb(0, iobase+UART_IER);
spin_unlock_irqrestore(&self->lock, flags);
} }
/* /*
...@@ -329,7 +323,7 @@ void irport_stop(struct irport_cb *self) ...@@ -329,7 +323,7 @@ void irport_stop(struct irport_cb *self)
*/ */
int irport_probe(int iobase) int irport_probe(int iobase)
{ {
IRDA_DEBUG(4, __FUNCTION__ "(), iobase=%#x\n", iobase); IRDA_DEBUG(4, "%s(), iobase=%#x\n", __FUNCTION__, iobase);
return 0; return 0;
} }
...@@ -339,27 +333,28 @@ int irport_probe(int iobase) ...@@ -339,27 +333,28 @@ int irport_probe(int iobase)
* *
* Set speed of IrDA port to specified baudrate * Set speed of IrDA port to specified baudrate
* *
* This function should be called with irq off and spin-lock.
*/ */
void irport_change_speed(void *priv, __u32 speed) void irport_change_speed(void *priv, __u32 speed)
{ {
struct irport_cb *self = (struct irport_cb *) priv; struct irport_cb *self = (struct irport_cb *) priv;
unsigned long flags;
int iobase; int iobase;
int fcr; /* FIFO control reg */ int fcr; /* FIFO control reg */
int lcr; /* Line control reg */ int lcr; /* Line control reg */
int divisor; int divisor;
IRDA_DEBUG(0, __FUNCTION__ "(), Setting speed to: %d\n", speed);
ASSERT(self != NULL, return;); ASSERT(self != NULL, return;);
IRDA_DEBUG(1, "%s(), Setting speed to: %d - iobase=%#x\n",
__FUNCTION__, speed, self->io.sir_base);
/* We can't lock, we may be called from a FIR driver - Jean II */
iobase = self->io.sir_base; iobase = self->io.sir_base;
/* Update accounting for new speed */ /* Update accounting for new speed */
self->io.speed = speed; self->io.speed = speed;
spin_lock_irqsave(&self->lock, flags);
/* Turn off interrupts */ /* Turn off interrupts */
outb(0, iobase+UART_IER); outb(0, iobase+UART_IER);
...@@ -387,9 +382,9 @@ void irport_change_speed(void *priv, __u32 speed) ...@@ -387,9 +382,9 @@ void irport_change_speed(void *priv, __u32 speed)
outb(fcr, iobase+UART_FCR); /* Enable FIFO's */ outb(fcr, iobase+UART_FCR); /* Enable FIFO's */
/* Turn on interrups */ /* Turn on interrups */
outb(/*UART_IER_RLSI|*/UART_IER_RDI/*|UART_IER_THRI*/, iobase+UART_IER); /* This will generate a fata interrupt storm.
* People calling us will do that properly - Jean II */
spin_unlock_irqrestore(&self->lock, flags); //outb(/*UART_IER_RLSI|*/UART_IER_RDI/*|UART_IER_THRI*/, iobase+UART_IER);
} }
/* /*
...@@ -397,19 +392,33 @@ void irport_change_speed(void *priv, __u32 speed) ...@@ -397,19 +392,33 @@ void irport_change_speed(void *priv, __u32 speed)
* *
* State machine for changing speed of the device. We do it this way since * State machine for changing speed of the device. We do it this way since
* we cannot use schedule_timeout() when we are in interrupt context * we cannot use schedule_timeout() when we are in interrupt context
*
*/ */
int __irport_change_speed(struct irda_task *task) int __irport_change_speed(struct irda_task *task)
{ {
struct irport_cb *self; struct irport_cb *self;
__u32 speed = (__u32) task->param; __u32 speed = (__u32) task->param;
unsigned long flags = 0;
int wasunlocked = 0;
int ret = 0; int ret = 0;
IRDA_DEBUG(2, __FUNCTION__ "(), <%ld>\n", jiffies); IRDA_DEBUG(2, "%s(), <%ld>\n", __FUNCTION__, jiffies);
self = (struct irport_cb *) task->instance; self = (struct irport_cb *) task->instance;
ASSERT(self != NULL, return -1;); ASSERT(self != NULL, return -1;);
/* Locking notes : this function may be called from irq context with
* spinlock, via irport_write_wakeup(), or from non-interrupt without
* spinlock (from the task timer). Yuck !
* This is ugly, and unsafe is the spinlock is not already aquired.
* This will be fixed when irda-task get rewritten.
* Jean II */
if (!spin_is_locked(&self->lock)) {
spin_lock_irqsave(&self->lock, flags);
wasunlocked = 1;
}
switch (task->state) { switch (task->state) {
case IRDA_TASK_INIT: case IRDA_TASK_INIT:
case IRDA_TASK_WAIT: case IRDA_TASK_WAIT:
...@@ -446,8 +455,7 @@ int __irport_change_speed(struct irda_task *task) ...@@ -446,8 +455,7 @@ int __irport_change_speed(struct irda_task *task)
irda_task_next_state(task, IRDA_TASK_CHILD_DONE); irda_task_next_state(task, IRDA_TASK_CHILD_DONE);
break; break;
case IRDA_TASK_CHILD_WAIT: case IRDA_TASK_CHILD_WAIT:
WARNING(__FUNCTION__ WARNING("%s(), changing speed of dongle timed out!\n", __FUNCTION__);
"(), changing speed of dongle timed out!\n");
ret = -1; ret = -1;
break; break;
case IRDA_TASK_CHILD_DONE: case IRDA_TASK_CHILD_DONE:
...@@ -457,11 +465,16 @@ int __irport_change_speed(struct irda_task *task) ...@@ -457,11 +465,16 @@ int __irport_change_speed(struct irda_task *task)
irda_task_next_state(task, IRDA_TASK_DONE); irda_task_next_state(task, IRDA_TASK_DONE);
break; break;
default: default:
ERROR(__FUNCTION__ "(), unknown state %d\n", task->state); ERROR("%s(), unknown state %d\n", __FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE); irda_task_next_state(task, IRDA_TASK_DONE);
ret = -1; ret = -1;
break; break;
} }
/* Put stuff in the sate we found them - Jean II */
if(wasunlocked) {
spin_unlock_irqrestore(&self->lock, flags);
}
return ret; return ret;
} }
...@@ -480,7 +493,7 @@ static void irport_write_wakeup(struct irport_cb *self) ...@@ -480,7 +493,7 @@ static void irport_write_wakeup(struct irport_cb *self)
ASSERT(self != NULL, return;); ASSERT(self != NULL, return;);
IRDA_DEBUG(4, __FUNCTION__ "()\n"); IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
iobase = self->io.sir_base; iobase = self->io.sir_base;
...@@ -491,6 +504,9 @@ static void irport_write_wakeup(struct irport_cb *self) ...@@ -491,6 +504,9 @@ static void irport_write_wakeup(struct irport_cb *self)
self->tx_buff.data, self->tx_buff.len); self->tx_buff.data, self->tx_buff.len);
self->tx_buff.data += actual; self->tx_buff.data += actual;
self->tx_buff.len -= actual; self->tx_buff.len -= actual;
/* Turn on transmit finished interrupt. */
outb(UART_IER_THRI, iobase+UART_IER);
} else { } else {
/* /*
* Now serial buffer is almost free & we can start * Now serial buffer is almost free & we can start
...@@ -498,11 +514,12 @@ static void irport_write_wakeup(struct irport_cb *self) ...@@ -498,11 +514,12 @@ static void irport_write_wakeup(struct irport_cb *self)
* if we need to change the speed of the hardware * if we need to change the speed of the hardware
*/ */
if (self->new_speed) { if (self->new_speed) {
IRDA_DEBUG(5, __FUNCTION__ "(), Changing speed!\n"); IRDA_DEBUG(5, "%s(), Changing speed!\n", __FUNCTION__);
irda_task_execute(self, __irport_change_speed, irda_task_execute(self, __irport_change_speed,
irport_change_speed_complete, irport_change_speed_complete,
NULL, (void *) self->new_speed); NULL, (void *) self->new_speed);
self->new_speed = 0; self->new_speed = 0;
IRDA_DEBUG(5, "%s(), Speed changed!\n", __FUNCTION__ );
} else { } else {
/* Tell network layer that we want more frames */ /* Tell network layer that we want more frames */
netif_wake_queue(self->netdev); netif_wake_queue(self->netdev);
...@@ -538,7 +555,7 @@ static int irport_write(int iobase, int fifo_size, __u8 *buf, int len) ...@@ -538,7 +555,7 @@ static int irport_write(int iobase, int fifo_size, __u8 *buf, int len)
/* Tx FIFO should be empty! */ /* Tx FIFO should be empty! */
if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) { if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
IRDA_DEBUG(0, __FUNCTION__ "(), failed, fifo not empty!\n"); IRDA_DEBUG(0, "%s(), failed, fifo not empty!\n", __FUNCTION__);
return 0; return 0;
} }
...@@ -563,7 +580,7 @@ static int irport_change_speed_complete(struct irda_task *task) ...@@ -563,7 +580,7 @@ static int irport_change_speed_complete(struct irda_task *task)
{ {
struct irport_cb *self; struct irport_cb *self;
IRDA_DEBUG(0, __FUNCTION__ "()\n"); IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
self = (struct irport_cb *) task->instance; self = (struct irport_cb *) task->instance;
...@@ -589,13 +606,19 @@ static void irport_timeout(struct net_device *dev) ...@@ -589,13 +606,19 @@ static void irport_timeout(struct net_device *dev)
{ {
struct irport_cb *self; struct irport_cb *self;
int iobase; int iobase;
unsigned long flags;
self = (struct irport_cb *) dev->priv; self = (struct irport_cb *) dev->priv;
iobase = self->io.sir_base; iobase = self->io.sir_base;
WARNING("%s: transmit timed out\n", dev->name); WARNING("%s: transmit timed out\n", dev->name);
spin_lock_irqsave(&self->lock, flags);
irport_start(self); irport_start(self);
self->change_speed(self->priv, self->io.speed); 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);
spin_unlock_irqrestore(&self->lock, flags);
dev->trans_start = jiffies; dev->trans_start = jiffies;
netif_wake_queue(dev); netif_wake_queue(dev);
} }
...@@ -614,7 +637,7 @@ int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -614,7 +637,7 @@ int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev)
int iobase; int iobase;
s32 speed; s32 speed;
IRDA_DEBUG(0, __FUNCTION__ "()\n"); IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
ASSERT(dev != NULL, return 0;); ASSERT(dev != NULL, return 0;);
...@@ -625,22 +648,25 @@ int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -625,22 +648,25 @@ int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev)
netif_stop_queue(dev); 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 */ /* Check if we need to change the speed */
speed = irda_get_next_speed(skb); speed = irda_get_next_speed(skb);
if ((speed != self->io.speed) && (speed != -1)) { if ((speed != self->io.speed) && (speed != -1)) {
/* Check for empty frame */ /* Check for empty frame */
if (!skb->len) { if (!skb->len) {
/* Better go there already locked - Jean II */
irda_task_execute(self, __irport_change_speed, irda_task_execute(self, __irport_change_speed,
irport_change_speed_complete, irport_change_speed_complete,
NULL, (void *) speed); NULL, (void *) speed);
spin_unlock_irqrestore(&self->lock, flags);
dev_kfree_skb(skb); dev_kfree_skb(skb);
return 0; return 0;
} else } else
self->new_speed = speed; self->new_speed = speed;
} }
spin_lock_irqsave(&self->lock, flags);
/* Init tx buffer */ /* Init tx buffer */
self->tx_buff.data = self->tx_buff.head; self->tx_buff.data = self->tx_buff.head;
...@@ -685,7 +711,7 @@ static void irport_receive(struct irport_cb *self) ...@@ -685,7 +711,7 @@ static void irport_receive(struct irport_cb *self)
/* Make sure we don't stay here to long */ /* Make sure we don't stay here to long */
if (boguscount++ > 32) { if (boguscount++ > 32) {
IRDA_DEBUG(2,__FUNCTION__ "(), breaking!\n"); IRDA_DEBUG(2,"%s(), breaking!\n", __FUNCTION__);
break; break;
} }
} while (inb(iobase+UART_LSR) & UART_LSR_DR); } while (inb(iobase+UART_LSR) & UART_LSR_DR);
...@@ -705,7 +731,7 @@ void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -705,7 +731,7 @@ void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs)
int iir, lsr; int iir, lsr;
if (!dev) { if (!dev) {
WARNING(__FUNCTION__ "() irq %d for unknown device.\n", irq); WARNING("%s() irq %d for unknown device.\n", __FUNCTION__, irq);
return; return;
} }
self = (struct irport_cb *) dev->priv; self = (struct irport_cb *) dev->priv;
...@@ -719,13 +745,12 @@ void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -719,13 +745,12 @@ void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/* Clear interrupt */ /* Clear interrupt */
lsr = inb(iobase+UART_LSR); lsr = inb(iobase+UART_LSR);
IRDA_DEBUG(4, __FUNCTION__ IRDA_DEBUG(4, "%s(), iir=%02x, lsr=%02x, iobase=%#x\n",
"(), iir=%02x, lsr=%02x, iobase=%#x\n", __FUNCTION__, iir, lsr, iobase);
iir, lsr, iobase);
switch (iir) { switch (iir) {
case UART_IIR_RLSI: case UART_IIR_RLSI:
IRDA_DEBUG(2, __FUNCTION__ "(), RLSI\n"); IRDA_DEBUG(2, "%s(), RLSI\n", __FUNCTION__);
break; break;
case UART_IIR_RDI: case UART_IIR_RDI:
/* Receive interrupt */ /* Receive interrupt */
...@@ -737,7 +762,7 @@ void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -737,7 +762,7 @@ void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs)
irport_write_wakeup(self); irport_write_wakeup(self);
break; break;
default: default:
IRDA_DEBUG(0, __FUNCTION__ "(), unhandled IIR=%#x\n", iir); IRDA_DEBUG(0, "%s(), unhandled IIR=%#x\n", __FUNCTION__, iir);
break; break;
} }
...@@ -771,8 +796,9 @@ int irport_net_open(struct net_device *dev) ...@@ -771,8 +796,9 @@ int irport_net_open(struct net_device *dev)
struct irport_cb *self; struct irport_cb *self;
int iobase; int iobase;
char hwname[16]; char hwname[16];
unsigned long flags;
IRDA_DEBUG(0, __FUNCTION__ "()\n"); IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
ASSERT(dev != NULL, return -1;); ASSERT(dev != NULL, return -1;);
self = (struct irport_cb *) dev->priv; self = (struct irport_cb *) dev->priv;
...@@ -781,12 +807,14 @@ int irport_net_open(struct net_device *dev) ...@@ -781,12 +807,14 @@ int irport_net_open(struct net_device *dev)
if (request_irq(self->io.irq, self->interrupt, 0, dev->name, if (request_irq(self->io.irq, self->interrupt, 0, dev->name,
(void *) dev)) { (void *) dev)) {
IRDA_DEBUG(0, __FUNCTION__ "(), unable to allocate irq=%d\n", IRDA_DEBUG(0, "%s(), unable to allocate irq=%d\n",
self->io.irq); __FUNCTION__, self->io.irq);
return -EAGAIN; return -EAGAIN;
} }
spin_lock_irqsave(&self->lock, flags);
irport_start(self); irport_start(self);
spin_unlock_irqrestore(&self->lock, flags);
/* Give self a hardware name */ /* Give self a hardware name */
...@@ -818,8 +846,9 @@ int irport_net_close(struct net_device *dev) ...@@ -818,8 +846,9 @@ int irport_net_close(struct net_device *dev)
{ {
struct irport_cb *self; struct irport_cb *self;
int iobase; int iobase;
unsigned long flags;
IRDA_DEBUG(4, __FUNCTION__ "()\n"); IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
ASSERT(dev != NULL, return -1;); ASSERT(dev != NULL, return -1;);
self = (struct irport_cb *) dev->priv; self = (struct irport_cb *) dev->priv;
...@@ -836,7 +865,9 @@ int irport_net_close(struct net_device *dev) ...@@ -836,7 +865,9 @@ int irport_net_close(struct net_device *dev)
irlap_close(self->irlap); irlap_close(self->irlap);
self->irlap = NULL; self->irlap = NULL;
spin_lock_irqsave(&self->lock, flags);
irport_stop(self); irport_stop(self);
spin_unlock_irqrestore(&self->lock, flags);
free_irq(self->io.irq, dev); free_irq(self->io.irq, dev);
...@@ -860,7 +891,7 @@ void irport_wait_until_sent(struct irport_cb *self) ...@@ -860,7 +891,7 @@ void irport_wait_until_sent(struct irport_cb *self)
/* Wait until Tx FIFO is empty */ /* Wait until Tx FIFO is empty */
while (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) { while (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
IRDA_DEBUG(2, __FUNCTION__ "(), waiting!\n"); IRDA_DEBUG(2, "%s(), waiting!\n", __FUNCTION__);
current->state = TASK_INTERRUPTIBLE; current->state = TASK_INTERRUPTIBLE;
schedule_timeout(MSECS_TO_JIFFIES(60)); schedule_timeout(MSECS_TO_JIFFIES(60));
} }
...@@ -915,7 +946,7 @@ static int irport_raw_write(struct net_device *dev, __u8 *buf, int len) ...@@ -915,7 +946,7 @@ static int irport_raw_write(struct net_device *dev, __u8 *buf, int len)
/* Tx FIFO should be empty! */ /* Tx FIFO should be empty! */
if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) { if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
IRDA_DEBUG( 0, __FUNCTION__ "(), failed, fifo not empty!\n"); IRDA_DEBUG( 0, "%s(), failed, fifo not empty!\n", __FUNCTION__);
return -1; return -1;
} }
...@@ -949,11 +980,7 @@ static int irport_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -949,11 +980,7 @@ static int irport_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
ASSERT(self != NULL, return -1;); ASSERT(self != NULL, return -1;);
IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd); IRDA_DEBUG(2, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__, dev->name, cmd);
/* Disable interrupts & save flags */
save_flags(flags);
cli();
switch (cmd) { switch (cmd) {
case SIOCSBANDWIDTH: /* Set bandwidth */ case SIOCSBANDWIDTH: /* Set bandwidth */
...@@ -979,14 +1006,16 @@ static int irport_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -979,14 +1006,16 @@ static int irport_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
dongle->write = irport_raw_write; dongle->write = irport_raw_write;
dongle->set_dtr_rts = irport_set_dtr_rts; dongle->set_dtr_rts = irport_set_dtr_rts;
self->dongle = dongle;
/* Now initialize the dongle! */ /* Now initialize the dongle! */
dongle->issue->open(dongle, &self->qos); dongle->issue->open(dongle, &self->qos);
/* Reset dongle */ /* Reset dongle */
irda_task_execute(dongle, dongle->issue->reset, NULL, NULL, irda_task_execute(dongle, dongle->issue->reset, NULL, NULL,
NULL); NULL);
/* Make dongle available to driver only now to avoid
* race conditions - Jean II */
self->dongle = dongle;
break; break;
case SIOCSMEDIABUSY: /* Set media busy */ case SIOCSMEDIABUSY: /* Set media busy */
if (!capable(CAP_NET_ADMIN)) { if (!capable(CAP_NET_ADMIN)) {
...@@ -1005,14 +1034,15 @@ static int irport_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -1005,14 +1034,15 @@ static int irport_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
break; break;
} }
/* No real need to lock... */
spin_lock_irqsave(&self->lock, flags);
irport_set_dtr_rts(dev, irq->ifr_dtr, irq->ifr_rts); irport_set_dtr_rts(dev, irq->ifr_dtr, irq->ifr_rts);
spin_unlock_irqrestore(&self->lock, flags);
break; break;
default: default:
ret = -EOPNOTSUPP; ret = -EOPNOTSUPP;
} }
restore_flags(flags);
return ret; return ret;
} }
......
...@@ -74,8 +74,10 @@ char *driver_name = "irtty"; ...@@ -74,8 +74,10 @@ char *driver_name = "irtty";
int __init irtty_init(void) int __init irtty_init(void)
{ {
int status; int status;
irtty = hashbin_new( HB_LOCAL); /* Probably no need to lock here because all operations done in
* open()/close() which are already safe - Jean II */
irtty = hashbin_new( HB_NOLOCK);
if ( irtty == NULL) { if ( irtty == NULL) {
printk( KERN_WARNING "IrDA: Can't allocate irtty hashbin!\n"); printk( KERN_WARNING "IrDA: Can't allocate irtty hashbin!\n");
return -ENOMEM; return -ENOMEM;
...@@ -118,9 +120,8 @@ static void __exit irtty_cleanup(void) ...@@ -118,9 +120,8 @@ static void __exit irtty_cleanup(void)
/* Unregister tty line-discipline */ /* Unregister tty line-discipline */
if ((ret = tty_register_ldisc(N_IRDA, NULL))) { if ((ret = tty_register_ldisc(N_IRDA, NULL))) {
ERROR(__FUNCTION__ ERROR("%s(), can't unregister line discipline (err = %d)\n",
"(), can't unregister line discipline (err = %d)\n", __FUNCTION__, ret);
ret);
} }
/* /*
...@@ -163,6 +164,7 @@ static int irtty_open(struct tty_struct *tty) ...@@ -163,6 +164,7 @@ static int irtty_open(struct tty_struct *tty)
return -ENOMEM; return -ENOMEM;
} }
memset(self, 0, sizeof(struct irtty_cb)); memset(self, 0, sizeof(struct irtty_cb));
spin_lock_init(&self->lock);
self->tty = tty; self->tty = tty;
tty->disc_data = self; tty->disc_data = self;
...@@ -226,7 +228,7 @@ static int irtty_open(struct tty_struct *tty) ...@@ -226,7 +228,7 @@ static int irtty_open(struct tty_struct *tty)
self->rx_buff.data = self->rx_buff.head; self->rx_buff.data = self->rx_buff.head;
if (!(dev = dev_alloc("irda%d", &err))) { if (!(dev = dev_alloc("irda%d", &err))) {
ERROR(__FUNCTION__ "(), dev_alloc() failed!\n"); ERROR("%s(), dev_alloc() failed!\n", __FUNCTION__);
return -ENOMEM; return -ENOMEM;
} }
...@@ -245,7 +247,7 @@ static int irtty_open(struct tty_struct *tty) ...@@ -245,7 +247,7 @@ static int irtty_open(struct tty_struct *tty)
err = register_netdevice(dev); err = register_netdevice(dev);
rtnl_unlock(); rtnl_unlock();
if (err) { if (err) {
ERROR(__FUNCTION__ "(), register_netdev() failed!\n"); ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
return -1; return -1;
} }
...@@ -266,11 +268,12 @@ static int irtty_open(struct tty_struct *tty) ...@@ -266,11 +268,12 @@ static int irtty_open(struct tty_struct *tty)
static void irtty_close(struct tty_struct *tty) static void irtty_close(struct tty_struct *tty)
{ {
struct irtty_cb *self = (struct irtty_cb *) tty->disc_data; struct irtty_cb *self = (struct irtty_cb *) tty->disc_data;
unsigned long flags;
/* First make sure we're connected. */ /* First make sure we're connected. */
ASSERT(self != NULL, return;); ASSERT(self != NULL, return;);
ASSERT(self->magic == IRTTY_MAGIC, return;); ASSERT(self->magic == IRTTY_MAGIC, return;);
/* Stop tty */ /* Stop tty */
tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
tty->disc_data = 0; tty->disc_data = 0;
...@@ -287,6 +290,11 @@ static void irtty_close(struct tty_struct *tty) ...@@ -287,6 +290,11 @@ static void irtty_close(struct tty_struct *tty)
rtnl_unlock(); rtnl_unlock();
} }
self = hashbin_remove(irtty, (int) self, NULL);
/* Protect access to self->task and self->?x_buff - Jean II */
spin_lock_irqsave(&self->lock, flags);
/* Remove speed changing task if any */ /* Remove speed changing task if any */
if (self->task) if (self->task)
irda_task_delete(self->task); irda_task_delete(self->task);
...@@ -294,13 +302,12 @@ static void irtty_close(struct tty_struct *tty) ...@@ -294,13 +302,12 @@ static void irtty_close(struct tty_struct *tty)
self->tty = NULL; self->tty = NULL;
self->magic = 0; self->magic = 0;
self = hashbin_remove(irtty, (int) self, NULL);
if (self->tx_buff.head) if (self->tx_buff.head)
kfree(self->tx_buff.head); kfree(self->tx_buff.head);
if (self->rx_buff.head) if (self->rx_buff.head)
kfree(self->rx_buff.head); kfree(self->rx_buff.head);
spin_unlock_irqrestore(&self->lock, flags);
kfree(self); kfree(self);
...@@ -326,6 +333,7 @@ static void irtty_stop_receiver(struct irtty_cb *self, int stop) ...@@ -326,6 +333,7 @@ static void irtty_stop_receiver(struct irtty_cb *self, int stop)
else else
cflag |= CREAD; cflag |= CREAD;
/* This is unsafe, but currently under discussion - Jean II */
self->tty->termios->c_cflag = cflag; self->tty->termios->c_cflag = cflag;
self->tty->driver.set_termios(self->tty, &old_termios); self->tty->driver.set_termios(self->tty, &old_termios);
} }
...@@ -378,6 +386,7 @@ static void __irtty_change_speed(struct irtty_cb *self, __u32 speed) ...@@ -378,6 +386,7 @@ static void __irtty_change_speed(struct irtty_cb *self, __u32 speed)
break; break;
} }
/* This is unsafe, but currently under discussion - Jean II */
self->tty->termios->c_cflag = cflag; self->tty->termios->c_cflag = cflag;
self->tty->driver.set_termios(self->tty, &old_termios); self->tty->driver.set_termios(self->tty, &old_termios);
...@@ -393,6 +402,7 @@ static void __irtty_change_speed(struct irtty_cb *self, __u32 speed) ...@@ -393,6 +402,7 @@ static void __irtty_change_speed(struct irtty_cb *self, __u32 speed)
static int irtty_change_speed(struct irda_task *task) static int irtty_change_speed(struct irda_task *task)
{ {
struct irtty_cb *self; struct irtty_cb *self;
unsigned long flags;
__u32 speed = (__u32) task->param; __u32 speed = (__u32) task->param;
int ret = 0; int ret = 0;
...@@ -401,12 +411,17 @@ static int irtty_change_speed(struct irda_task *task) ...@@ -401,12 +411,17 @@ static int irtty_change_speed(struct irda_task *task)
self = (struct irtty_cb *) task->instance; self = (struct irtty_cb *) task->instance;
ASSERT(self != NULL, return -1;); ASSERT(self != NULL, return -1;);
/* Protect access to self->task - Jean II */
spin_lock_irqsave(&self->lock, flags);
/* Check if busy */ /* Check if busy */
if (self->task && self->task != task) { if (self->task && self->task != task) {
IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n"); IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n");
spin_unlock_irqrestore(&self->lock, flags);
return MSECS_TO_JIFFIES(10); return MSECS_TO_JIFFIES(10);
} else } else
self->task = task; self->task = task;
spin_unlock_irqrestore(&self->lock, flags);
switch (task->state) { switch (task->state) {
case IRDA_TASK_INIT: case IRDA_TASK_INIT:
...@@ -451,8 +466,7 @@ static int irtty_change_speed(struct irda_task *task) ...@@ -451,8 +466,7 @@ static int irtty_change_speed(struct irda_task *task)
irda_task_next_state(task, IRDA_TASK_CHILD_DONE); irda_task_next_state(task, IRDA_TASK_CHILD_DONE);
break; break;
case IRDA_TASK_CHILD_WAIT: case IRDA_TASK_CHILD_WAIT:
WARNING(__FUNCTION__ WARNING("%s(), changing speed of dongle timed out!\n", __FUNCTION__);
"(), changing speed of dongle timed out!\n");
ret = -1; ret = -1;
break; break;
case IRDA_TASK_CHILD_DONE: case IRDA_TASK_CHILD_DONE:
...@@ -463,7 +477,7 @@ static int irtty_change_speed(struct irda_task *task) ...@@ -463,7 +477,7 @@ static int irtty_change_speed(struct irda_task *task)
self->task = NULL; self->task = NULL;
break; break;
default: default:
ERROR(__FUNCTION__ "(), unknown state %d\n", task->state); ERROR("%s(), unknown state %d\n", __FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE); irda_task_next_state(task, IRDA_TASK_DONE);
self->task = NULL; self->task = NULL;
ret = -1; ret = -1;
...@@ -501,6 +515,7 @@ static int irtty_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg) ...@@ -501,6 +515,7 @@ static int irtty_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
switch (cmd) { switch (cmd) {
case TCGETS: case TCGETS:
case TCGETA: case TCGETA:
/* Unsure about locking here, to check - Jean II */
return n_tty_ioctl(tty, (struct file *) file, cmd, return n_tty_ioctl(tty, (struct file *) file, cmd,
(unsigned long) arg); (unsigned long) arg);
break; break;
...@@ -516,15 +531,16 @@ static int irtty_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg) ...@@ -516,15 +531,16 @@ static int irtty_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
dongle->write = irtty_raw_write; dongle->write = irtty_raw_write;
dongle->set_dtr_rts = irtty_set_dtr_rts; dongle->set_dtr_rts = irtty_set_dtr_rts;
/* Bind dongle */
self->dongle = dongle;
/* Now initialize the dongle! */ /* Now initialize the dongle! */
dongle->issue->open(dongle, &self->qos); dongle->issue->open(dongle, &self->qos);
/* Reset dongle */ /* Reset dongle */
irda_task_execute(dongle, dongle->issue->reset, NULL, NULL, irda_task_execute(dongle, dongle->issue->reset, NULL, NULL,
NULL); NULL);
/* Make dongle available to driver only now to avoid
* race conditions - Jean II */
self->dongle = dongle;
break; break;
case IRTTY_IOCGET: case IRTTY_IOCGET:
ASSERT(self->netdev != NULL, return -1;); ASSERT(self->netdev != NULL, return -1;);
...@@ -559,6 +575,9 @@ static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp, ...@@ -559,6 +575,9 @@ static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
return; return;
} }
// Are we in interrupt context ? What locking is done ? - Jean II
//spin_lock_irqsave(&self->lock, flags);
/* Read the characters out of the buffer */ /* Read the characters out of the buffer */
while (count--) { while (count--) {
/* /*
...@@ -589,6 +608,7 @@ static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp, ...@@ -589,6 +608,7 @@ static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
break; break;
} }
} }
//spin_unlock_irqrestore(&self->lock, flags);
} }
/* /*
...@@ -626,11 +646,13 @@ static int irtty_hard_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -626,11 +646,13 @@ static int irtty_hard_xmit(struct sk_buff *skb, struct net_device *dev)
struct irtty_cb *self; struct irtty_cb *self;
int actual = 0; int actual = 0;
__s32 speed; __s32 speed;
unsigned long flags;
self = (struct irtty_cb *) dev->priv; self = (struct irtty_cb *) dev->priv;
ASSERT(self != NULL, return 0;); ASSERT(self != NULL, return 0;);
/* Lock transmit buffer */ /* Lock transmit buffer
* this serialise operations, no need to spinlock - Jean II */
netif_stop_queue(dev); netif_stop_queue(dev);
/* Check if we need to change the speed */ /* Check if we need to change the speed */
...@@ -647,6 +669,9 @@ static int irtty_hard_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -647,6 +669,9 @@ static int irtty_hard_xmit(struct sk_buff *skb, struct net_device *dev)
self->new_speed = speed; self->new_speed = speed;
} }
/* Protect access to self->tx_buff - Jean II */
spin_lock_irqsave(&self->lock, flags);
/* Init tx buffer*/ /* Init tx buffer*/
self->tx_buff.data = self->tx_buff.head; self->tx_buff.data = self->tx_buff.head;
...@@ -667,6 +692,8 @@ static int irtty_hard_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -667,6 +692,8 @@ static int irtty_hard_xmit(struct sk_buff *skb, struct net_device *dev)
self->tx_buff.data += actual; self->tx_buff.data += actual;
self->tx_buff.len -= actual; self->tx_buff.len -= actual;
spin_unlock_irqrestore(&self->lock, flags);
dev_kfree_skb(skb); dev_kfree_skb(skb);
return 0; return 0;
...@@ -695,6 +722,7 @@ static void irtty_write_wakeup(struct tty_struct *tty) ...@@ -695,6 +722,7 @@ static void irtty_write_wakeup(struct tty_struct *tty)
{ {
struct irtty_cb *self = (struct irtty_cb *) tty->disc_data; struct irtty_cb *self = (struct irtty_cb *) tty->disc_data;
int actual = 0; int actual = 0;
unsigned long flags;
/* /*
* First make sure we're connected. * First make sure we're connected.
...@@ -702,6 +730,11 @@ static void irtty_write_wakeup(struct tty_struct *tty) ...@@ -702,6 +730,11 @@ static void irtty_write_wakeup(struct tty_struct *tty)
ASSERT(self != NULL, return;); ASSERT(self != NULL, return;);
ASSERT(self->magic == IRTTY_MAGIC, return;); ASSERT(self->magic == IRTTY_MAGIC, return;);
/* Protected via netif_stop_queue(dev); - Jean II */
/* Protect access to self->tx_buff - Jean II */
spin_lock_irqsave(&self->lock, flags);
/* Finished with frame? */ /* Finished with frame? */
if (self->tx_buff.len > 0) { if (self->tx_buff.len > 0) {
/* Write data left in transmit buffer */ /* Write data left in transmit buffer */
...@@ -710,6 +743,7 @@ static void irtty_write_wakeup(struct tty_struct *tty) ...@@ -710,6 +743,7 @@ static void irtty_write_wakeup(struct tty_struct *tty)
self->tx_buff.data += actual; self->tx_buff.data += actual;
self->tx_buff.len -= actual; self->tx_buff.len -= actual;
spin_unlock_irqrestore(&self->lock, flags);
} else { } else {
/* /*
* Now serial buffer is almost free & we can start * Now serial buffer is almost free & we can start
...@@ -721,6 +755,9 @@ static void irtty_write_wakeup(struct tty_struct *tty) ...@@ -721,6 +755,9 @@ static void irtty_write_wakeup(struct tty_struct *tty)
tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
/* Don't change speed with irq off */
spin_unlock_irqrestore(&self->lock, flags);
if (self->new_speed) { if (self->new_speed) {
IRDA_DEBUG(5, __FUNCTION__ "(), Changing speed!\n"); IRDA_DEBUG(5, __FUNCTION__ "(), Changing speed!\n");
irda_task_execute(self, irtty_change_speed, irda_task_execute(self, irtty_change_speed,
...@@ -755,12 +792,17 @@ static int irtty_set_dtr_rts(struct net_device *dev, int dtr, int rts) ...@@ -755,12 +792,17 @@ static int irtty_set_dtr_rts(struct net_device *dev, int dtr, int rts)
{ {
struct irtty_cb *self; struct irtty_cb *self;
struct tty_struct *tty; struct tty_struct *tty;
//unsigned long flags;
mm_segment_t fs; mm_segment_t fs;
int arg = 0; int arg = 0;
self = (struct irtty_cb *) dev->priv; self = (struct irtty_cb *) dev->priv;
tty = self->tty; tty = self->tty;
/* Was protected in ioctl handler, but the serial driver doesn't
* like it. This may need to change. - Jean II */
//spin_lock_irqsave(&self->lock, flags);
#ifdef TIOCM_OUT2 /* Not defined for ARM */ #ifdef TIOCM_OUT2 /* Not defined for ARM */
arg = TIOCM_OUT2; arg = TIOCM_OUT2;
#endif #endif
...@@ -780,11 +822,14 @@ static int irtty_set_dtr_rts(struct net_device *dev, int dtr, int rts) ...@@ -780,11 +822,14 @@ static int irtty_set_dtr_rts(struct net_device *dev, int dtr, int rts)
fs = get_fs(); fs = get_fs();
set_fs(get_ds()); set_fs(get_ds());
/* This is probably unsafe, but currently under discussion - Jean II */
if (tty->driver.ioctl(tty, NULL, TIOCMSET, (unsigned long) &arg)) { if (tty->driver.ioctl(tty, NULL, TIOCMSET, (unsigned long) &arg)) {
IRDA_DEBUG(2, __FUNCTION__ "(), error doing ioctl!\n"); IRDA_DEBUG(2, __FUNCTION__ "(), error doing ioctl!\n");
} }
set_fs(fs); set_fs(fs);
//spin_unlock_irqrestore(&self->lock, flags);
return 0; return 0;
} }
...@@ -799,13 +844,17 @@ static int irtty_set_dtr_rts(struct net_device *dev, int dtr, int rts) ...@@ -799,13 +844,17 @@ static int irtty_set_dtr_rts(struct net_device *dev, int dtr, int rts)
int irtty_set_mode(struct net_device *dev, int mode) int irtty_set_mode(struct net_device *dev, int mode)
{ {
struct irtty_cb *self; struct irtty_cb *self;
unsigned long flags;
self = (struct irtty_cb *) dev->priv; self = (struct irtty_cb *) dev->priv;
ASSERT(self != NULL, return -1;); ASSERT(self != NULL, return -1;);
IRDA_DEBUG(2, __FUNCTION__ "(), mode=%s\n", infrared_mode[mode]); IRDA_DEBUG(2, __FUNCTION__ "(), mode=%s\n", infrared_mode[mode]);
/* Protect access to self->rx_buff - Jean II */
spin_lock_irqsave(&self->lock, flags);
/* save status for driver */ /* save status for driver */
self->mode = mode; self->mode = mode;
...@@ -814,6 +863,8 @@ int irtty_set_mode(struct net_device *dev, int mode) ...@@ -814,6 +863,8 @@ int irtty_set_mode(struct net_device *dev, int mode)
self->rx_buff.len = 0; self->rx_buff.len = 0;
self->rx_buff.state = OUTSIDE_FRAME; self->rx_buff.state = OUTSIDE_FRAME;
spin_unlock_irqrestore(&self->lock, flags);
return 0; return 0;
} }
...@@ -955,7 +1006,6 @@ static int irtty_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -955,7 +1006,6 @@ static int irtty_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
struct if_irda_req *irq = (struct if_irda_req *) rq; struct if_irda_req *irq = (struct if_irda_req *) rq;
struct irtty_cb *self; struct irtty_cb *self;
dongle_t *dongle; dongle_t *dongle;
unsigned long flags;
int ret = 0; int ret = 0;
ASSERT(dev != NULL, return -1;); ASSERT(dev != NULL, return -1;);
...@@ -971,8 +1021,7 @@ static int irtty_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -971,8 +1021,7 @@ static int irtty_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
* irda_device_dongle_init() can't be locked. * irda_device_dongle_init() can't be locked.
* irda_task_execute() doesn't need to be locked (but * irda_task_execute() doesn't need to be locked (but
* irtty_change_speed() should protect itself). * irtty_change_speed() should protect itself).
* As this driver doesn't have spinlock protection, keep * Other calls protect themselves.
* old fashion locking :-(
* Jean II * Jean II
*/ */
...@@ -1025,20 +1074,14 @@ static int irtty_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -1025,20 +1074,14 @@ static int irtty_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
if (!capable(CAP_NET_ADMIN)) if (!capable(CAP_NET_ADMIN))
ret = -EPERM; ret = -EPERM;
else { else {
save_flags(flags);
cli();
irtty_set_dtr_rts(dev, irq->ifr_dtr, irq->ifr_rts); irtty_set_dtr_rts(dev, irq->ifr_dtr, irq->ifr_rts);
restore_flags(flags);
} }
break; break;
case SIOCSMODE: case SIOCSMODE:
if (!capable(CAP_NET_ADMIN)) if (!capable(CAP_NET_ADMIN))
ret = -EPERM; ret = -EPERM;
else { else {
save_flags(flags);
cli();
irtty_set_mode(dev, irq->ifr_mode); irtty_set_mode(dev, irq->ifr_mode);
restore_flags(flags);
} }
break; break;
default: default:
......
...@@ -109,7 +109,7 @@ static int mcp2120_change_speed(struct irda_task *task) ...@@ -109,7 +109,7 @@ static int mcp2120_change_speed(struct irda_task *task)
} }
break; break;
case IRDA_TASK_CHILD_WAIT: case IRDA_TASK_CHILD_WAIT:
WARNING(__FUNCTION__ "(), resetting dongle timed out!\n"); WARNING("%s(), resetting dongle timed out!\n", __FUNCTION__);
ret = -1; ret = -1;
break; break;
case IRDA_TASK_CHILD_DONE: case IRDA_TASK_CHILD_DONE:
...@@ -157,7 +157,7 @@ static int mcp2120_change_speed(struct irda_task *task) ...@@ -157,7 +157,7 @@ static int mcp2120_change_speed(struct irda_task *task)
//printk("mcp2120_change_speed irda_task_wait\n"); //printk("mcp2120_change_speed irda_task_wait\n");
break; break;
default: default:
ERROR(__FUNCTION__ "(), unknown state %d\n", task->state); ERROR("%s(), unknown state %d\n", __FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE); irda_task_next_state(task, IRDA_TASK_DONE);
self->speed_task = NULL; self->speed_task = NULL;
ret = -1; ret = -1;
...@@ -212,7 +212,7 @@ static int mcp2120_reset(struct irda_task *task) ...@@ -212,7 +212,7 @@ static int mcp2120_reset(struct irda_task *task)
self->reset_task = NULL; self->reset_task = NULL;
break; break;
default: default:
ERROR(__FUNCTION__ "(), unknown state %d\n", task->state); ERROR("%s(), unknown state %d\n", __FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE); irda_task_next_state(task, IRDA_TASK_DONE);
self->reset_task = NULL; self->reset_task = NULL;
ret = -1; ret = -1;
......
...@@ -161,7 +161,7 @@ int __init nsc_ircc_init(void) ...@@ -161,7 +161,7 @@ int __init nsc_ircc_init(void)
/* Probe for all the NSC chipsets we know about */ /* Probe for all the NSC chipsets we know about */
for (chip=chips; chip->name ; chip++) { for (chip=chips; chip->name ; chip++) {
IRDA_DEBUG(2, __FUNCTION__"(), Probing for %s ...\n", IRDA_DEBUG(2, "%s(), Probing for %s ...\n", __FUNCTION__,
chip->name); chip->name);
/* Try all config registers for this chip */ /* Try all config registers for this chip */
...@@ -179,8 +179,7 @@ int __init nsc_ircc_init(void) ...@@ -179,8 +179,7 @@ int __init nsc_ircc_init(void)
/* Read index register */ /* Read index register */
reg = inb(cfg_base); reg = inb(cfg_base);
if (reg == 0xff) { if (reg == 0xff) {
IRDA_DEBUG(2, __FUNCTION__ IRDA_DEBUG(2, "%s() no chip at 0x%03x\n", __FUNCTION__, cfg_base);
"() no chip at 0x%03x\n", cfg_base);
continue; continue;
} }
...@@ -188,9 +187,8 @@ int __init nsc_ircc_init(void) ...@@ -188,9 +187,8 @@ int __init nsc_ircc_init(void)
outb(chip->cid_index, cfg_base); outb(chip->cid_index, cfg_base);
id = inb(cfg_base+1); id = inb(cfg_base+1);
if ((id & chip->cid_mask) == chip->cid_value) { if ((id & chip->cid_mask) == chip->cid_value) {
IRDA_DEBUG(2, __FUNCTION__ IRDA_DEBUG(2, "%s() Found %s chip, revision=%d\n",
"() Found %s chip, revision=%d\n", __FUNCTION__, chip->name, id & ~chip->cid_mask);
chip->name, id & ~chip->cid_mask);
/* /*
* If the user supplies the base address, then * If the user supplies the base address, then
* we init the chip, if not we probe the values * we init the chip, if not we probe the values
...@@ -205,8 +203,7 @@ int __init nsc_ircc_init(void) ...@@ -205,8 +203,7 @@ int __init nsc_ircc_init(void)
ret = 0; ret = 0;
i++; i++;
} else { } else {
IRDA_DEBUG(2, __FUNCTION__ IRDA_DEBUG(2, "%s(), Wrong chip id=0x%02x\n", __FUNCTION__, id);
"(), Wrong chip id=0x%02x\n", id);
} }
} }
...@@ -247,7 +244,7 @@ static int __init nsc_ircc_open(int i, chipio_t *info) ...@@ -247,7 +244,7 @@ static int __init nsc_ircc_open(int i, chipio_t *info)
void *ret; void *ret;
int err; int err;
IRDA_DEBUG(2, __FUNCTION__ "()\n"); IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
MESSAGE("%s, Found chip at base=0x%03x\n", driver_name, MESSAGE("%s, Found chip at base=0x%03x\n", driver_name,
info->cfg_base); info->cfg_base);
...@@ -260,8 +257,8 @@ static int __init nsc_ircc_open(int i, chipio_t *info) ...@@ -260,8 +257,8 @@ static int __init nsc_ircc_open(int i, chipio_t *info)
/* Allocate new instance of the driver */ /* Allocate new instance of the driver */
self = kmalloc(sizeof(struct nsc_ircc_cb), GFP_KERNEL); self = kmalloc(sizeof(struct nsc_ircc_cb), GFP_KERNEL);
if (self == NULL) { if (self == NULL) {
ERROR(__FUNCTION__ "(), can't allocate memory for " ERROR("%s(), can't allocate memory for "
"control block!\n"); "control block!\n", __FUNCTION__);
return -ENOMEM; return -ENOMEM;
} }
memset(self, 0, sizeof(struct nsc_ircc_cb)); memset(self, 0, sizeof(struct nsc_ircc_cb));
...@@ -282,8 +279,8 @@ static int __init nsc_ircc_open(int i, chipio_t *info) ...@@ -282,8 +279,8 @@ static int __init nsc_ircc_open(int i, chipio_t *info)
/* Reserve the ioports that we need */ /* Reserve the ioports that we need */
ret = request_region(self->io.fir_base, self->io.fir_ext, driver_name); ret = request_region(self->io.fir_base, self->io.fir_ext, driver_name);
if (!ret) { if (!ret) {
WARNING(__FUNCTION__ "(), can't get iobase of 0x%03x\n", WARNING("%s(), can't get iobase of 0x%03x\n",
self->io.fir_base); __FUNCTION__, self->io.fir_base);
dev_self[i] = NULL; dev_self[i] = NULL;
kfree(self); kfree(self);
return -ENODEV; return -ENODEV;
...@@ -333,7 +330,7 @@ static int __init nsc_ircc_open(int i, chipio_t *info) ...@@ -333,7 +330,7 @@ static int __init nsc_ircc_open(int i, chipio_t *info)
self->tx_fifo.tail = self->tx_buff.head; self->tx_fifo.tail = self->tx_buff.head;
if (!(dev = dev_alloc("irda%d", &err))) { if (!(dev = dev_alloc("irda%d", &err))) {
ERROR(__FUNCTION__ "(), dev_alloc() failed!\n"); ERROR("%s(), dev_alloc() failed!\n", __FUNCTION__);
return -ENOMEM; return -ENOMEM;
} }
...@@ -352,7 +349,7 @@ static int __init nsc_ircc_open(int i, chipio_t *info) ...@@ -352,7 +349,7 @@ static int __init nsc_ircc_open(int i, chipio_t *info)
err = register_netdevice(dev); err = register_netdevice(dev);
rtnl_unlock(); rtnl_unlock();
if (err) { if (err) {
ERROR(__FUNCTION__ "(), register_netdev() failed!\n"); ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
return -1; return -1;
} }
MESSAGE("IrDA: Registered device %s\n", dev->name); MESSAGE("IrDA: Registered device %s\n", dev->name);
...@@ -388,7 +385,7 @@ static int __exit nsc_ircc_close(struct nsc_ircc_cb *self) ...@@ -388,7 +385,7 @@ static int __exit nsc_ircc_close(struct nsc_ircc_cb *self)
{ {
int iobase; int iobase;
IRDA_DEBUG(4, __FUNCTION__ "()\n"); IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
ASSERT(self != NULL, return -1;); ASSERT(self != NULL, return -1;);
...@@ -402,8 +399,8 @@ static int __exit nsc_ircc_close(struct nsc_ircc_cb *self) ...@@ -402,8 +399,8 @@ static int __exit nsc_ircc_close(struct nsc_ircc_cb *self)
} }
/* Release the PORT that this driver is using */ /* Release the PORT that this driver is using */
IRDA_DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", IRDA_DEBUG(4, "%s(), Releasing Region %03x\n",
self->io.fir_base); __FUNCTION__, self->io.fir_base);
release_region(self->io.fir_base, self->io.fir_ext); release_region(self->io.fir_base, self->io.fir_ext);
if (self->tx_buff.head) if (self->tx_buff.head)
...@@ -439,7 +436,7 @@ static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info) ...@@ -439,7 +436,7 @@ static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info)
case 0x2e8: outb(0x15, cfg_base+1); break; case 0x2e8: outb(0x15, cfg_base+1); break;
case 0x3f8: outb(0x16, cfg_base+1); break; case 0x3f8: outb(0x16, cfg_base+1); break;
case 0x2f8: outb(0x17, cfg_base+1); break; case 0x2f8: outb(0x17, cfg_base+1); break;
default: ERROR(__FUNCTION__ "(), invalid base_address"); default: ERROR("%s(), invalid base_address", __FUNCTION__);
} }
/* Control Signal Routing Register (CSRT) */ /* Control Signal Routing Register (CSRT) */
...@@ -451,7 +448,7 @@ static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info) ...@@ -451,7 +448,7 @@ static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info)
case 9: temp = 0x05; break; case 9: temp = 0x05; break;
case 11: temp = 0x06; break; case 11: temp = 0x06; break;
case 15: temp = 0x07; break; case 15: temp = 0x07; break;
default: ERROR(__FUNCTION__ "(), invalid irq"); default: ERROR("%s(), invalid irq", __FUNCTION__);
} }
outb(1, cfg_base); outb(1, cfg_base);
...@@ -459,7 +456,7 @@ static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info) ...@@ -459,7 +456,7 @@ static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info)
case 0: outb(0x08+temp, cfg_base+1); break; case 0: outb(0x08+temp, cfg_base+1); break;
case 1: outb(0x10+temp, cfg_base+1); break; case 1: outb(0x10+temp, cfg_base+1); break;
case 3: outb(0x18+temp, cfg_base+1); break; case 3: outb(0x18+temp, cfg_base+1); break;
default: ERROR(__FUNCTION__ "(), invalid dma"); default: ERROR("%s(), invalid dma", __FUNCTION__);
} }
outb(2, cfg_base); /* Mode Control Register (MCTL) */ outb(2, cfg_base); /* Mode Control Register (MCTL) */
...@@ -498,7 +495,7 @@ static int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info) ...@@ -498,7 +495,7 @@ static int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info)
break; break;
} }
info->sir_base = info->fir_base; info->sir_base = info->fir_base;
IRDA_DEBUG(2, __FUNCTION__ "(), probing fir_base=0x%03x\n", IRDA_DEBUG(2, "%s(), probing fir_base=0x%03x\n", __FUNCTION__,
info->fir_base); info->fir_base);
/* Read control signals routing register (CSRT) */ /* Read control signals routing register (CSRT) */
...@@ -531,7 +528,7 @@ static int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info) ...@@ -531,7 +528,7 @@ static int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info)
info->irq = 15; info->irq = 15;
break; break;
} }
IRDA_DEBUG(2, __FUNCTION__ "(), probing irq=%d\n", info->irq); IRDA_DEBUG(2, "%s(), probing irq=%d\n", __FUNCTION__, info->irq);
/* Currently we only read Rx DMA but it will also be used for Tx */ /* Currently we only read Rx DMA but it will also be used for Tx */
switch ((reg >> 3) & 0x03) { switch ((reg >> 3) & 0x03) {
...@@ -548,7 +545,7 @@ static int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info) ...@@ -548,7 +545,7 @@ static int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info)
info->dma = 3; info->dma = 3;
break; break;
} }
IRDA_DEBUG(2, __FUNCTION__ "(), probing dma=%d\n", info->dma); IRDA_DEBUG(2, "%s(), probing dma=%d\n", __FUNCTION__, info->dma);
/* Read mode control register (MCTL) */ /* Read mode control register (MCTL) */
outb(CFG_MCTL, cfg_base); outb(CFG_MCTL, cfg_base);
...@@ -694,8 +691,8 @@ static int nsc_ircc_setup(chipio_t *info) ...@@ -694,8 +691,8 @@ static int nsc_ircc_setup(chipio_t *info)
switch_bank(iobase, BANK3); switch_bank(iobase, BANK3);
version = inb(iobase+MID); version = inb(iobase+MID);
IRDA_DEBUG(2, __FUNCTION__ "() Driver %s Found chip version %02x\n", IRDA_DEBUG(2, "%s() Driver %s Found chip version %02x\n",
driver_name, version); __FUNCTION__, driver_name, version);
/* Should be 0x2? */ /* Should be 0x2? */
if (0x20 != (version & 0xf0)) { if (0x20 != (version & 0xf0)) {
...@@ -797,39 +794,39 @@ static void nsc_ircc_init_dongle_interface (int iobase, int dongle_id) ...@@ -797,39 +794,39 @@ static void nsc_ircc_init_dongle_interface (int iobase, int dongle_id)
switch (dongle_id) { switch (dongle_id) {
case 0x00: /* same as */ case 0x00: /* same as */
case 0x01: /* Differential serial interface */ case 0x01: /* Differential serial interface */
IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n", IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n",
dongle_types[dongle_id]); __FUNCTION__, dongle_types[dongle_id]);
break; break;
case 0x02: /* same as */ case 0x02: /* same as */
case 0x03: /* Reserved */ case 0x03: /* Reserved */
IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n", IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n",
dongle_types[dongle_id]); __FUNCTION__, dongle_types[dongle_id]);
break; break;
case 0x04: /* Sharp RY5HD01 */ case 0x04: /* Sharp RY5HD01 */
break; break;
case 0x05: /* Reserved, but this is what the Thinkpad reports */ case 0x05: /* Reserved, but this is what the Thinkpad reports */
IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n", IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n",
dongle_types[dongle_id]); __FUNCTION__, dongle_types[dongle_id]);
break; break;
case 0x06: /* Single-ended serial interface */ case 0x06: /* Single-ended serial interface */
IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n", IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n",
dongle_types[dongle_id]); __FUNCTION__, dongle_types[dongle_id]);
break; break;
case 0x07: /* Consumer-IR only */ case 0x07: /* Consumer-IR only */
IRDA_DEBUG(0, __FUNCTION__ "(), %s is not for IrDA mode\n", IRDA_DEBUG(0, "%s(), %s is not for IrDA mode\n",
dongle_types[dongle_id]); __FUNCTION__, dongle_types[dongle_id]);
break; break;
case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */ case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */
IRDA_DEBUG(0, __FUNCTION__ "(), %s\n", IRDA_DEBUG(0, "%s(), %s\n",
dongle_types[dongle_id]); __FUNCTION__, dongle_types[dongle_id]);
break; break;
case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */ case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */
outb(0x28, iobase+7); /* Set irsl[0-2] as output */ outb(0x28, iobase+7); /* Set irsl[0-2] as output */
break; break;
case 0x0A: /* same as */ case 0x0A: /* same as */
case 0x0B: /* Reserved */ case 0x0B: /* Reserved */
IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n", IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n",
dongle_types[dongle_id]); __FUNCTION__, dongle_types[dongle_id]);
break; break;
case 0x0C: /* same as */ case 0x0C: /* same as */
case 0x0D: /* HP HSDL-1100/HSDL-2100 */ case 0x0D: /* HP HSDL-1100/HSDL-2100 */
...@@ -843,15 +840,15 @@ static void nsc_ircc_init_dongle_interface (int iobase, int dongle_id) ...@@ -843,15 +840,15 @@ static void nsc_ircc_init_dongle_interface (int iobase, int dongle_id)
outb(0x28, iobase+7); /* Set irsl[0-2] as output */ outb(0x28, iobase+7); /* Set irsl[0-2] as output */
break; break;
case 0x0F: /* No dongle connected */ case 0x0F: /* No dongle connected */
IRDA_DEBUG(0, __FUNCTION__ "(), %s\n", IRDA_DEBUG(0, "%s(), %s\n",
dongle_types[dongle_id]); __FUNCTION__, dongle_types[dongle_id]);
switch_bank(iobase, BANK0); switch_bank(iobase, BANK0);
outb(0x62, iobase+MCR); outb(0x62, iobase+MCR);
break; break;
default: default:
IRDA_DEBUG(0, __FUNCTION__ "(), invalid dongle_id %#x", IRDA_DEBUG(0, "%s(), invalid dongle_id %#x",
dongle_id); __FUNCTION__, dongle_id);
} }
/* IRCFG1: IRSL1 and 2 are set to IrDA mode */ /* IRCFG1: IRSL1 and 2 are set to IrDA mode */
...@@ -870,7 +867,6 @@ static void nsc_ircc_init_dongle_interface (int iobase, int dongle_id) ...@@ -870,7 +867,6 @@ static void nsc_ircc_init_dongle_interface (int iobase, int dongle_id)
*/ */
static void nsc_ircc_change_dongle_speed(int iobase, int speed, int dongle_id) static void nsc_ircc_change_dongle_speed(int iobase, int speed, int dongle_id)
{ {
unsigned long flags;
__u8 bank; __u8 bank;
/* Save current bank */ /* Save current bank */
...@@ -883,31 +879,31 @@ static void nsc_ircc_change_dongle_speed(int iobase, int speed, int dongle_id) ...@@ -883,31 +879,31 @@ static void nsc_ircc_change_dongle_speed(int iobase, int speed, int dongle_id)
switch (dongle_id) { switch (dongle_id) {
case 0x00: /* same as */ case 0x00: /* same as */
case 0x01: /* Differential serial interface */ case 0x01: /* Differential serial interface */
IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n", IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n",
dongle_types[dongle_id]); __FUNCTION__, dongle_types[dongle_id]);
break; break;
case 0x02: /* same as */ case 0x02: /* same as */
case 0x03: /* Reserved */ case 0x03: /* Reserved */
IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n", IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n",
dongle_types[dongle_id]); __FUNCTION__, dongle_types[dongle_id]);
break; break;
case 0x04: /* Sharp RY5HD01 */ case 0x04: /* Sharp RY5HD01 */
break; break;
case 0x05: /* Reserved */ case 0x05: /* Reserved */
IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n", IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n",
dongle_types[dongle_id]); __FUNCTION__, dongle_types[dongle_id]);
break; break;
case 0x06: /* Single-ended serial interface */ case 0x06: /* Single-ended serial interface */
IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n", IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n",
dongle_types[dongle_id]); __FUNCTION__, dongle_types[dongle_id]);
break; break;
case 0x07: /* Consumer-IR only */ case 0x07: /* Consumer-IR only */
IRDA_DEBUG(0, __FUNCTION__ "(), %s is not for IrDA mode\n", IRDA_DEBUG(0, "%s(), %s is not for IrDA mode\n",
dongle_types[dongle_id]); __FUNCTION__, dongle_types[dongle_id]);
break; break;
case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */ case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */
IRDA_DEBUG(0, __FUNCTION__ "(), %s\n", IRDA_DEBUG(0, "%s(), %s\n",
dongle_types[dongle_id]); __FUNCTION__, dongle_types[dongle_id]);
outb(0x00, iobase+4); outb(0x00, iobase+4);
if (speed > 115200) if (speed > 115200)
outb(0x01, iobase+4); outb(0x01, iobase+4);
...@@ -916,11 +912,10 @@ static void nsc_ircc_change_dongle_speed(int iobase, int speed, int dongle_id) ...@@ -916,11 +912,10 @@ static void nsc_ircc_change_dongle_speed(int iobase, int speed, int dongle_id)
outb(0x01, iobase+4); outb(0x01, iobase+4);
if (speed == 4000000) { if (speed == 4000000) {
save_flags(flags); /* There was a cli() there, but we now are already
cli(); * under spin_lock_irqsave() - JeanII */
outb(0x81, iobase+4); outb(0x81, iobase+4);
outb(0x80, iobase+4); outb(0x80, iobase+4);
restore_flags(flags);
} else } else
outb(0x00, iobase+4); outb(0x00, iobase+4);
break; break;
...@@ -1538,8 +1533,8 @@ static int nsc_ircc_dma_receive_complete(struct nsc_ircc_cb *self, int iobase) ...@@ -1538,8 +1533,8 @@ static int nsc_ircc_dma_receive_complete(struct nsc_ircc_cb *self, int iobase)
skb = dev_alloc_skb(len+1); skb = dev_alloc_skb(len+1);
if (skb == NULL) { if (skb == NULL) {
WARNING(__FUNCTION__ "(), memory squeeze, " WARNING("%s(), memory squeeze, "
"dropping frame.\n"); "dropping frame.\n", __FUNCTION__);
self->stats.rx_dropped++; self->stats.rx_dropped++;
/* Restore bank register */ /* Restore bank register */
...@@ -1960,33 +1955,30 @@ static int nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -1960,33 +1955,30 @@ static int nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd); IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
/* Disable interrupts & save flags */
save_flags(flags);
cli();
switch (cmd) { switch (cmd) {
case SIOCSBANDWIDTH: /* Set bandwidth */ case SIOCSBANDWIDTH: /* Set bandwidth */
if (!capable(CAP_NET_ADMIN)) { if (!capable(CAP_NET_ADMIN)) {
ret = -EPERM; ret = -EPERM;
goto out; break;
} }
spin_lock_irqsave(&self->lock, flags);
nsc_ircc_change_speed(self, irq->ifr_baudrate); nsc_ircc_change_speed(self, irq->ifr_baudrate);
spin_unlock_irqrestore(&self->lock, flags);
break; break;
case SIOCSMEDIABUSY: /* Set media busy */ case SIOCSMEDIABUSY: /* Set media busy */
if (!capable(CAP_NET_ADMIN)) { if (!capable(CAP_NET_ADMIN)) {
ret = -EPERM; ret = -EPERM;
goto out; break;
} }
irda_device_set_media_busy(self->netdev, TRUE); irda_device_set_media_busy(self->netdev, TRUE);
break; break;
case SIOCGRECEIVING: /* Check if we are receiving right now */ case SIOCGRECEIVING: /* Check if we are receiving right now */
/* This is already protected */
irq->ifr_receiving = nsc_ircc_is_receiving(self); irq->ifr_receiving = nsc_ircc_is_receiving(self);
break; break;
default: default:
ret = -EOPNOTSUPP; ret = -EOPNOTSUPP;
} }
out:
restore_flags(flags);
return ret; return ret;
} }
......
...@@ -431,6 +431,7 @@ static int __init ircc_open(unsigned int fir_base, unsigned int sir_base) ...@@ -431,6 +431,7 @@ static int __init ircc_open(unsigned int fir_base, unsigned int sir_base)
struct ircc_cb *self; struct ircc_cb *self;
struct irport_cb *irport; struct irport_cb *irport;
unsigned char low, high, chip, config, dma, irq, version; unsigned char low, high, chip, config, dma, irq, version;
unsigned long flags;
IRDA_DEBUG(0, __FUNCTION__ "\n"); IRDA_DEBUG(0, __FUNCTION__ "\n");
...@@ -484,7 +485,6 @@ static int __init ircc_open(unsigned int fir_base, unsigned int sir_base) ...@@ -484,7 +485,6 @@ static int __init ircc_open(unsigned int fir_base, unsigned int sir_base)
return -ENOMEM; return -ENOMEM;
} }
memset(self, 0, sizeof(struct ircc_cb)); memset(self, 0, sizeof(struct ircc_cb));
spin_lock_init(&self->lock);
/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */ /* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
self->rx_buff.truesize = 4000; self->rx_buff.truesize = 4000;
...@@ -555,6 +555,9 @@ static int __init ircc_open(unsigned int fir_base, unsigned int sir_base) ...@@ -555,6 +555,9 @@ static int __init ircc_open(unsigned int fir_base, unsigned int sir_base)
request_region(self->io->fir_base, CHIP_IO_EXTENT, driver_name); request_region(self->io->fir_base, CHIP_IO_EXTENT, driver_name);
/* Don't allow irport to change under us - Jean II */
spin_lock_irqsave(&self->irport->lock, flags);
/* Initialize QoS for this device */ /* Initialize QoS for this device */
irda_init_max_qos_capabilies(&irport->qos); irda_init_max_qos_capabilies(&irport->qos);
...@@ -581,6 +584,7 @@ static int __init ircc_open(unsigned int fir_base, unsigned int sir_base) ...@@ -581,6 +584,7 @@ static int __init ircc_open(unsigned int fir_base, unsigned int sir_base)
self->netdev->stop = &ircc_net_close; self->netdev->stop = &ircc_net_close;
irport_start(self->irport); irport_start(self->irport);
spin_unlock_irqrestore(&self->irport->lock, flags);
self->pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, ircc_pmproc); self->pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, ircc_pmproc);
if (self->pmdev) if (self->pmdev)
...@@ -598,6 +602,7 @@ static int __init ircc_open(unsigned int fir_base, unsigned int sir_base) ...@@ -598,6 +602,7 @@ static int __init ircc_open(unsigned int fir_base, unsigned int sir_base)
* *
* Change the speed of the device * Change the speed of the device
* *
* This function should be called with irq off and spin-lock.
*/ */
static void ircc_change_speed(void *priv, u32 speed) static void ircc_change_speed(void *priv, u32 speed)
{ {
...@@ -658,6 +663,7 @@ static void ircc_change_speed(void *priv, u32 speed) ...@@ -658,6 +663,7 @@ static void ircc_change_speed(void *priv, u32 speed)
/* Make special FIR init if necessary */ /* Make special FIR init if necessary */
if (speed > 115200) { if (speed > 115200) {
/* No need to lock, already locked - Jean II */
irport_stop(self->irport); irport_stop(self->irport);
/* Install FIR transmit handler */ /* Install FIR transmit handler */
...@@ -674,6 +680,7 @@ static void ircc_change_speed(void *priv, u32 speed) ...@@ -674,6 +680,7 @@ static void ircc_change_speed(void *priv, u32 speed)
} else { } else {
/* Install SIR transmit handler */ /* Install SIR transmit handler */
dev->hard_start_xmit = &irport_hard_xmit; dev->hard_start_xmit = &irport_hard_xmit;
/* No need to lock, already locked - Jean II */
irport_start(self->irport); irport_start(self->irport);
IRDA_DEBUG(0, __FUNCTION__ IRDA_DEBUG(0, __FUNCTION__
...@@ -727,20 +734,26 @@ static int ircc_hard_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -727,20 +734,26 @@ static int ircc_hard_xmit(struct sk_buff *skb, struct net_device *dev)
netif_stop_queue(dev); netif_stop_queue(dev);
/* Make sure tests *& speed change are atomic */
spin_lock_irqsave(&self->irport->lock, flags);
/* Note : you should make sure that speed changes are not going
* to corrupt any outgoing frame. Look at nsc-ircc for the gory
* details - Jean II */
/* Check if we need to change the speed after this frame */ /* Check if we need to change the speed after this frame */
speed = irda_get_next_speed(skb); speed = irda_get_next_speed(skb);
if ((speed != self->io->speed) && (speed != -1)) { if ((speed != self->io->speed) && (speed != -1)) {
/* Check for empty frame */ /* Check for empty frame */
if (!skb->len) { if (!skb->len) {
ircc_change_speed(self, speed); ircc_change_speed(self, speed);
spin_unlock_irqrestore(&self->irport->lock, flags);
dev_kfree_skb(skb); dev_kfree_skb(skb);
return 0; return 0;
} else } else
self->new_speed = speed; self->new_speed = speed;
} }
spin_lock_irqsave(&self->lock, flags);
memcpy(self->tx_buff.head, skb->data, skb->len); memcpy(self->tx_buff.head, skb->data, skb->len);
self->tx_buff.len = skb->len; self->tx_buff.len = skb->len;
...@@ -763,7 +776,7 @@ static int ircc_hard_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -763,7 +776,7 @@ static int ircc_hard_xmit(struct sk_buff *skb, struct net_device *dev)
/* Transmit frame */ /* Transmit frame */
ircc_dma_xmit(self, iobase, 0); ircc_dma_xmit(self, iobase, 0);
} }
spin_unlock_irqrestore(&self->lock, flags); spin_unlock_irqrestore(&self->irport->lock, flags);
dev_kfree_skb(skb); dev_kfree_skb(skb);
return 0; return 0;
...@@ -936,14 +949,14 @@ static void ircc_dma_receive_complete(struct ircc_cb *self, int iobase) ...@@ -936,14 +949,14 @@ static void ircc_dma_receive_complete(struct ircc_cb *self, int iobase)
len -= 4; len -= 4;
if ((len < 2) || (len > 2050)) { if ((len < 2) || (len > 2050)) {
WARNING(__FUNCTION__ "(), bogus len=%d\n", len); WARNING("%s(), bogus len=%d\n", __FUNCTION__, len);
return; return;
} }
IRDA_DEBUG(2, __FUNCTION__ ": msgcnt = %d, len=%d\n", msgcnt, len); IRDA_DEBUG(2, __FUNCTION__ ": msgcnt = %d, len=%d\n", msgcnt, len);
skb = dev_alloc_skb(len+1); skb = dev_alloc_skb(len+1);
if (!skb) { if (!skb) {
WARNING(__FUNCTION__ "(), memory squeeze, dropping frame.\n"); WARNING("%s(), memory squeeze, dropping frame.\n", __FUNCTION__);
return; return;
} }
/* Make sure IP header gets aligned */ /* Make sure IP header gets aligned */
...@@ -985,12 +998,13 @@ static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -985,12 +998,13 @@ static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/* Check if we should use the SIR interrupt handler */ /* Check if we should use the SIR interrupt handler */
if (self->io->speed < 576000) { if (self->io->speed < 576000) {
/* Will spinlock itself - Jean II */
irport_interrupt(irq, dev_id, regs); irport_interrupt(irq, dev_id, regs);
return; return;
} }
iobase = self->io->fir_base; iobase = self->io->fir_base;
spin_lock(&self->lock); spin_lock(&self->irport->lock);
register_bank(iobase, 0); register_bank(iobase, 0);
iir = inb(iobase+IRCC_IIR); iir = inb(iobase+IRCC_IIR);
...@@ -1013,7 +1027,7 @@ static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -1013,7 +1027,7 @@ static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
register_bank(iobase, 0); register_bank(iobase, 0);
outb(IRCC_IER_ACTIVE_FRAME|IRCC_IER_EOM, iobase+IRCC_IER); outb(IRCC_IER_ACTIVE_FRAME|IRCC_IER_EOM, iobase+IRCC_IER);
spin_unlock(&self->lock); spin_unlock(&self->irport->lock);
} }
#if 0 /* unused */ #if 0 /* unused */
...@@ -1072,7 +1086,7 @@ static int ircc_net_open(struct net_device *dev) ...@@ -1072,7 +1086,7 @@ static int ircc_net_open(struct net_device *dev)
if (request_dma(self->io->dma, dev->name)) { if (request_dma(self->io->dma, dev->name)) {
irport_net_close(dev); irport_net_close(dev);
WARNING(__FUNCTION__ "(), unable to allocate DMA=%d\n", self->io->dma); WARNING("%s(), unable to allocate DMA=%d\n", __FUNCTION__, self->io->dma);
return -EAGAIN; return -EAGAIN;
} }
...@@ -1093,7 +1107,7 @@ static int ircc_net_close(struct net_device *dev) ...@@ -1093,7 +1107,7 @@ static int ircc_net_close(struct net_device *dev)
struct ircc_cb *self; struct ircc_cb *self;
int iobase; int iobase;
IRDA_DEBUG(0, __FUNCTION__ "\n"); IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
ASSERT(dev != NULL, return -1;); ASSERT(dev != NULL, return -1;);
irport = (struct irport_cb *) dev->priv; irport = (struct irport_cb *) dev->priv;
...@@ -1128,17 +1142,15 @@ static void ircc_suspend(struct ircc_cb *self) ...@@ -1128,17 +1142,15 @@ static void ircc_suspend(struct ircc_cb *self)
static void ircc_wakeup(struct ircc_cb *self) static void ircc_wakeup(struct ircc_cb *self)
{ {
unsigned long flags;
if (!self->io->suspended) if (!self->io->suspended)
return; return;
save_flags(flags); /* The code was doing a "cli()" here, but this can't be right.
cli(); * If you need protection, do it in net_open with a spinlock
* or give a good reason. - Jean II */
ircc_net_open(self->netdev); ircc_net_open(self->netdev);
restore_flags(flags);
MESSAGE("%s, Waking up\n", driver_name); MESSAGE("%s, Waking up\n", driver_name);
} }
...@@ -1174,6 +1186,7 @@ static int __exit ircc_close(struct ircc_cb *self) ...@@ -1174,6 +1186,7 @@ static int __exit ircc_close(struct ircc_cb *self)
iobase = self->irport->io.fir_base; iobase = self->irport->io.fir_base;
/* This will destroy irport */
irport_close(self->irport); irport_close(self->irport);
/* Stop interrupts */ /* Stop interrupts */
...@@ -1187,6 +1200,7 @@ static int __exit ircc_close(struct ircc_cb *self) ...@@ -1187,6 +1200,7 @@ static int __exit ircc_close(struct ircc_cb *self)
outb(IRCC_CFGA_IRDA_SIR_A|IRCC_CFGA_TX_POLARITY, iobase+IRCC_SCE_CFGA); outb(IRCC_CFGA_IRDA_SIR_A|IRCC_CFGA_TX_POLARITY, iobase+IRCC_SCE_CFGA);
outb(IRCC_CFGB_IR, iobase+IRCC_SCE_CFGB); outb(IRCC_CFGB_IR, iobase+IRCC_SCE_CFGB);
#endif #endif
/* Release the PORT that this driver is using */ /* Release the PORT that this driver is using */
IRDA_DEBUG(0, __FUNCTION__ "(), releasing 0x%03x\n", iobase); IRDA_DEBUG(0, __FUNCTION__ "(), releasing 0x%03x\n", iobase);
......
...@@ -161,7 +161,7 @@ static int tekram_change_speed(struct irda_task *task) ...@@ -161,7 +161,7 @@ static int tekram_change_speed(struct irda_task *task)
irda_task_next_state(task, IRDA_TASK_CHILD_DONE); irda_task_next_state(task, IRDA_TASK_CHILD_DONE);
break; break;
case IRDA_TASK_CHILD_WAIT: case IRDA_TASK_CHILD_WAIT:
WARNING(__FUNCTION__ "(), resetting dongle timed out!\n"); WARNING("%s(), resetting dongle timed out!\n", __FUNCTION__);
ret = -1; ret = -1;
break; break;
case IRDA_TASK_CHILD_DONE: case IRDA_TASK_CHILD_DONE:
...@@ -187,7 +187,7 @@ static int tekram_change_speed(struct irda_task *task) ...@@ -187,7 +187,7 @@ static int tekram_change_speed(struct irda_task *task)
self->speed_task = NULL; self->speed_task = NULL;
break; break;
default: default:
ERROR(__FUNCTION__ "(), unknown state %d\n", task->state); ERROR("%s(), unknown state %d\n", __FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE); irda_task_next_state(task, IRDA_TASK_DONE);
self->speed_task = NULL; self->speed_task = NULL;
ret = -1; ret = -1;
...@@ -255,7 +255,7 @@ int tekram_reset(struct irda_task *task) ...@@ -255,7 +255,7 @@ int tekram_reset(struct irda_task *task)
self->reset_task = NULL; self->reset_task = NULL;
break; break;
default: default:
ERROR(__FUNCTION__ "(), unknown state %d\n", task->state); ERROR("%s(), unknown state %d\n", __FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE); irda_task_next_state(task, IRDA_TASK_DONE);
self->reset_task = NULL; self->reset_task = NULL;
ret = -1; ret = -1;
......
...@@ -421,8 +421,8 @@ toshoboe_interrupt (int irq, void *dev_id, struct pt_regs *regs) ...@@ -421,8 +421,8 @@ toshoboe_interrupt (int irq, void *dev_id, struct pt_regs *regs)
} }
else else
{ {
printk (KERN_INFO __FUNCTION__ printk (KERN_INFO
"(), memory squeeze, dropping frame.\n"); "%s(), memory squeeze, dropping frame.\n", __FUNCTION__);
} }
self->taskfile->recv[self->rxs].control = 0x83; self->taskfile->recv[self->rxs].control = 0x83;
...@@ -824,7 +824,7 @@ toshoboe_probe (struct pci_dev *pci_dev, const struct pci_device_id *pdid) ...@@ -824,7 +824,7 @@ toshoboe_probe (struct pci_dev *pci_dev, const struct pci_device_id *pdid)
if (!(dev = dev_alloc("irda%d", &err))) { if (!(dev = dev_alloc("irda%d", &err))) {
ERROR(__FUNCTION__ "(), dev_alloc() failed!\n"); ERROR("%s(), dev_alloc() failed!\n", __FUNCTION__);
err = -ENOMEM; err = -ENOMEM;
goto freebufs; goto freebufs;
} }
...@@ -843,7 +843,7 @@ toshoboe_probe (struct pci_dev *pci_dev, const struct pci_device_id *pdid) ...@@ -843,7 +843,7 @@ toshoboe_probe (struct pci_dev *pci_dev, const struct pci_device_id *pdid)
err = register_netdevice(dev); err = register_netdevice(dev);
rtnl_unlock(); rtnl_unlock();
if (err) { if (err) {
ERROR(__FUNCTION__ "(), register_netdev() failed!\n"); ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
/* XXX there is not freeing for dev? */ /* XXX there is not freeing for dev? */
goto freebufs; goto freebufs;
} }
......
...@@ -175,6 +175,7 @@ int w83977af_open(int i, unsigned int iobase, unsigned int irq, ...@@ -175,6 +175,7 @@ int w83977af_open(int i, unsigned int iobase, unsigned int irq,
return -ENOMEM; return -ENOMEM;
} }
memset(self, 0, sizeof(struct w83977af_ir)); memset(self, 0, sizeof(struct w83977af_ir));
spin_lock_init(&self->lock);
/* Need to store self somewhere */ /* Need to store self somewhere */
dev_self[i] = self; dev_self[i] = self;
...@@ -236,7 +237,7 @@ int w83977af_open(int i, unsigned int iobase, unsigned int irq, ...@@ -236,7 +237,7 @@ int w83977af_open(int i, unsigned int iobase, unsigned int irq,
self->rx_buff.data = self->rx_buff.head; self->rx_buff.data = self->rx_buff.head;
if (!(dev = dev_alloc("irda%d", &err))) { if (!(dev = dev_alloc("irda%d", &err))) {
ERROR(__FUNCTION__ "(), dev_alloc() failed!\n"); ERROR("%s(), dev_alloc() failed!\n", __FUNCTION__);
return -ENOMEM; return -ENOMEM;
} }
dev->priv = (void *) self; dev->priv = (void *) self;
...@@ -254,7 +255,7 @@ int w83977af_open(int i, unsigned int iobase, unsigned int irq, ...@@ -254,7 +255,7 @@ int w83977af_open(int i, unsigned int iobase, unsigned int irq,
err = register_netdevice(dev); err = register_netdevice(dev);
rtnl_unlock(); rtnl_unlock();
if (err) { if (err) {
ERROR(__FUNCTION__ "(), register_netdevice() failed!\n"); ERROR("%s(), register_netdevice() failed!\n", __FUNCTION__);
return -1; return -1;
} }
MESSAGE("IrDA: Registered device %s\n", dev->name); MESSAGE("IrDA: Registered device %s\n", dev->name);
...@@ -603,8 +604,7 @@ static void w83977af_dma_write(struct w83977af_ir *self, int iobase) ...@@ -603,8 +604,7 @@ static void w83977af_dma_write(struct w83977af_ir *self, int iobase)
switch_bank(iobase, SET2); switch_bank(iobase, SET2);
outb(ADCR1_D_CHSW|/*ADCR1_DMA_F|*/ADCR1_ADV_SL, iobase+ADCR1); outb(ADCR1_D_CHSW|/*ADCR1_DMA_F|*/ADCR1_ADV_SL, iobase+ADCR1);
#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS #ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS
save_flags(flags); spin_lock_irqsave(&self->lock, flags);
cli();
disable_dma(self->io.dma); disable_dma(self->io.dma);
clear_dma_ff(self->io.dma); clear_dma_ff(self->io.dma);
...@@ -623,7 +623,7 @@ static void w83977af_dma_write(struct w83977af_ir *self, int iobase) ...@@ -623,7 +623,7 @@ static void w83977af_dma_write(struct w83977af_ir *self, int iobase)
hcr = inb(iobase+HCR); hcr = inb(iobase+HCR);
outb(hcr | HCR_EN_DMA, iobase+HCR); outb(hcr | HCR_EN_DMA, iobase+HCR);
enable_dma(self->io.dma); enable_dma(self->io.dma);
restore_flags(flags); spin_unlock_irqrestore(&self->lock, flags);
#else #else
outb(inb(iobase+HCR) | HCR_EN_DMA | HCR_TX_WT, iobase+HCR); outb(inb(iobase+HCR) | HCR_EN_DMA | HCR_TX_WT, iobase+HCR);
#endif #endif
...@@ -761,8 +761,7 @@ int w83977af_dma_receive(struct w83977af_ir *self) ...@@ -761,8 +761,7 @@ int w83977af_dma_receive(struct w83977af_ir *self)
self->rx_buff.data = self->rx_buff.head; self->rx_buff.data = self->rx_buff.head;
#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS #ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS
save_flags(flags); spin_lock_irqsave(&self->lock, flags);
cli();
disable_dma(self->io.dma); disable_dma(self->io.dma);
clear_dma_ff(self->io.dma); clear_dma_ff(self->io.dma);
...@@ -788,7 +787,7 @@ int w83977af_dma_receive(struct w83977af_ir *self) ...@@ -788,7 +787,7 @@ int w83977af_dma_receive(struct w83977af_ir *self)
hcr = inb(iobase+HCR); hcr = inb(iobase+HCR);
outb(hcr | HCR_EN_DMA, iobase+HCR); outb(hcr | HCR_EN_DMA, iobase+HCR);
enable_dma(self->io.dma); enable_dma(self->io.dma);
restore_flags(flags); spin_unlock_irqrestore(&self->lock, flags);
#else #else
outb(inb(iobase+HCR) | HCR_EN_DMA, iobase+HCR); outb(inb(iobase+HCR) | HCR_EN_DMA, iobase+HCR);
#endif #endif
...@@ -892,8 +891,8 @@ int w83977af_dma_receive_complete(struct w83977af_ir *self) ...@@ -892,8 +891,8 @@ int w83977af_dma_receive_complete(struct w83977af_ir *self)
skb = dev_alloc_skb(len+1); skb = dev_alloc_skb(len+1);
if (skb == NULL) { if (skb == NULL) {
printk(KERN_INFO __FUNCTION__ printk(KERN_INFO
"(), memory squeeze, dropping frame.\n"); "%s(), memory squeeze, dropping frame.\n", __FUNCTION__);
/* Restore set register */ /* Restore set register */
outb(set, iobase+SSR); outb(set, iobase+SSR);
...@@ -1334,10 +1333,8 @@ static int w83977af_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -1334,10 +1333,8 @@ static int w83977af_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd); IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
/* Disable interrupts & save flags */ spin_lock_irqsave(&self->lock, flags);
save_flags(flags);
cli();
switch (cmd) { switch (cmd) {
case SIOCSBANDWIDTH: /* Set bandwidth */ case SIOCSBANDWIDTH: /* Set bandwidth */
if (!capable(CAP_NET_ADMIN)) { if (!capable(CAP_NET_ADMIN)) {
...@@ -1360,7 +1357,7 @@ static int w83977af_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -1360,7 +1357,7 @@ static int w83977af_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
ret = -EOPNOTSUPP; ret = -EOPNOTSUPP;
} }
out: out:
restore_flags(flags); spin_unlock_irqrestore(&self->lock, flags);
return ret; return ret;
} }
......
...@@ -59,7 +59,7 @@ nbd_end_request(struct request *req) ...@@ -59,7 +59,7 @@ nbd_end_request(struct request *req)
blk_finished_io(nsect); blk_finished_io(nsect);
req->bio = bio->bi_next; req->bio = bio->bi_next;
bio->bi_next = NULL; bio->bi_next = NULL;
bio_endio(bio, uptodate); bio_endio(bio, nsect << 9, uptodate ? 0 : -EIO);
} }
blk_put_request(req); blk_put_request(req);
spin_unlock_irqrestore(q->queue_lock, flags); spin_unlock_irqrestore(q->queue_lock, flags);
......
...@@ -55,8 +55,8 @@ struct irda_sock { ...@@ -55,8 +55,8 @@ struct irda_sock {
__u16 mask; /* Hint bits mask */ __u16 mask; /* Hint bits mask */
__u16 hints; /* Hint bits */ __u16 hints; /* Hint bits */
__u32 ckey; /* IrLMP client handle */ void *ckey; /* IrLMP client handle */
__u32 skey; /* IrLMP service handle */ void *skey; /* IrLMP service handle */
struct ias_object *ias_obj; /* Our service name + lsap in IAS */ struct ias_object *ias_obj; /* Our service name + lsap in IAS */
struct iriap_cb *iriap; /* Used to query remote IAS */ struct iriap_cb *iriap; /* Used to query remote IAS */
......
...@@ -86,8 +86,8 @@ struct ircomm_tty_cb { ...@@ -86,8 +86,8 @@ struct ircomm_tty_cb {
struct iriap_cb *iriap; /* Instance used for querying remote IAS */ struct iriap_cb *iriap; /* Instance used for querying remote IAS */
struct ias_object* obj; struct ias_object* obj;
int skey; void *skey;
int ckey; void *ckey;
struct termios normal_termios; struct termios normal_termios;
struct termios callout_termios; struct termios callout_termios;
...@@ -104,6 +104,14 @@ struct ircomm_tty_cb { ...@@ -104,6 +104,14 @@ struct ircomm_tty_cb {
long pgrp; /* pgrp of opening process */ long pgrp; /* pgrp of opening process */
int open_count; int open_count;
int blocked_open; /* # of blocked opens */ int blocked_open; /* # of blocked opens */
/* Protect concurent access to :
* o self->open_count
* o self->ctrl_skb
* o self->tx_skb
* Maybe other things may gain to be protected as well...
* Jean II */
spinlock_t spinlock;
}; };
void ircomm_tty_start(struct tty_struct *tty); void ircomm_tty_start(struct tty_struct *tty);
......
...@@ -183,7 +183,6 @@ struct irlmp_cb { ...@@ -183,7 +183,6 @@ struct irlmp_cb {
hashbin_t *services; hashbin_t *services;
hashbin_t *cachelog; /* Current discovery log */ hashbin_t *cachelog; /* Current discovery log */
spinlock_t log_lock; /* discovery log spinlock */
int running; int running;
...@@ -197,12 +196,12 @@ struct lsap_cb *irlmp_open_lsap(__u8 slsap, notify_t *notify, __u8 pid); ...@@ -197,12 +196,12 @@ struct lsap_cb *irlmp_open_lsap(__u8 slsap, notify_t *notify, __u8 pid);
void irlmp_close_lsap( struct lsap_cb *self); void irlmp_close_lsap( struct lsap_cb *self);
__u16 irlmp_service_to_hint(int service); __u16 irlmp_service_to_hint(int service);
__u32 irlmp_register_service(__u16 hints); void *irlmp_register_service(__u16 hints);
int irlmp_unregister_service(__u32 handle); int irlmp_unregister_service(void *handle);
__u32 irlmp_register_client(__u16 hint_mask, DISCOVERY_CALLBACK1 disco_clb, void *irlmp_register_client(__u16 hint_mask, DISCOVERY_CALLBACK1 disco_clb,
DISCOVERY_CALLBACK1 expir_clb, void *priv); DISCOVERY_CALLBACK1 expir_clb, void *priv);
int irlmp_unregister_client(__u32 handle); int irlmp_unregister_client(void *handle);
int irlmp_update_client(__u32 handle, __u16 hint_mask, int irlmp_update_client(void *handle, __u16 hint_mask,
DISCOVERY_CALLBACK1 disco_clb, DISCOVERY_CALLBACK1 disco_clb,
DISCOVERY_CALLBACK1 expir_clb, void *priv); DISCOVERY_CALLBACK1 expir_clb, void *priv);
...@@ -221,7 +220,7 @@ void irlmp_disconnect_indication(struct lsap_cb *self, LM_REASON reason, ...@@ -221,7 +220,7 @@ void irlmp_disconnect_indication(struct lsap_cb *self, LM_REASON reason,
struct sk_buff *userdata); struct sk_buff *userdata);
int irlmp_disconnect_request(struct lsap_cb *, struct sk_buff *userdata); int irlmp_disconnect_request(struct lsap_cb *, struct sk_buff *userdata);
void irlmp_discovery_confirm(hashbin_t *discovery_log, DISCOVERY_MODE); void irlmp_discovery_confirm(hashbin_t *discovery_log, DISCOVERY_MODE mode);
void irlmp_discovery_request(int nslots); void irlmp_discovery_request(int nslots);
struct irda_device_info *irlmp_get_discoveries(int *pn, __u16 mask, int nslots); struct irda_device_info *irlmp_get_discoveries(int *pn, __u16 mask, int nslots);
void irlmp_do_expiry(void); void irlmp_do_expiry(void);
...@@ -258,8 +257,6 @@ extern int sysctl_discovery; ...@@ -258,8 +257,6 @@ extern int sysctl_discovery;
extern int sysctl_lap_keepalive_time; /* in ms, default is LM_IDLE_TIMEOUT */ extern int sysctl_lap_keepalive_time; /* in ms, default is LM_IDLE_TIMEOUT */
extern struct irlmp_cb *irlmp; extern struct irlmp_cb *irlmp;
static inline hashbin_t *irlmp_get_cachelog(void) { return irlmp->cachelog; }
/* Check if LAP queue is full. /* Check if LAP queue is full.
* Used by IrTTP for low control, see comments in irlap.h - Jean II */ * Used by IrTTP for low control, see comments in irlap.h - Jean II */
static inline int irlmp_lap_tx_queue_full(struct lsap_cb *self) static inline int irlmp_lap_tx_queue_full(struct lsap_cb *self)
......
...@@ -36,12 +36,12 @@ ...@@ -36,12 +36,12 @@
#define NAME_SIZE 32 #define NAME_SIZE 32
/* /*
* Hash types * Hash types (some flags can be xored)
* See comments in irqueue.c for which one to use...
*/ */
#define HB_NOLOCK 0 #define HB_NOLOCK 0 /* No concurent access prevention */
#define HB_GLOBAL 1 #define HB_LOCK 1 /* Prevent concurent write with global lock */
#define HB_LOCAL 2 #define HB_SORTED 4 /* Not yet supported */
#define HB_SORTED 4
/* /*
* Hash defines * Hash defines
...@@ -57,17 +57,12 @@ ...@@ -57,17 +57,12 @@
typedef void (*FREE_FUNC)(void *arg); typedef void (*FREE_FUNC)(void *arg);
/*
* Hashbin
*/
#define GET_HASHBIN(x) ( x & HASHBIN_MASK )
struct irda_queue { struct irda_queue {
struct irda_queue *q_next; struct irda_queue *q_next;
struct irda_queue *q_prev; struct irda_queue *q_prev;
char q_name[NAME_SIZE]; char q_name[NAME_SIZE];
__u32 q_hash; long q_hash; /* Must be able to cast a (void *) */
}; };
typedef struct irda_queue irda_queue_t; typedef struct irda_queue irda_queue_t;
...@@ -75,8 +70,9 @@ typedef struct hashbin_t { ...@@ -75,8 +70,9 @@ typedef struct hashbin_t {
__u32 magic; __u32 magic;
int hb_type; int hb_type;
int hb_size; int hb_size;
spinlock_t hb_mutex[HASHBIN_SIZE] IRDA_ALIGN; spinlock_t hb_spinlock; /* HB_LOCK - Can be used by the user */
irda_queue_t *hb_queue[HASHBIN_SIZE] IRDA_ALIGN;
irda_queue_t* hb_queue[HASHBIN_SIZE] IRDA_ALIGN;
irda_queue_t* hb_current; irda_queue_t* hb_current;
} hashbin_t; } hashbin_t;
...@@ -84,19 +80,18 @@ typedef struct hashbin_t { ...@@ -84,19 +80,18 @@ typedef struct hashbin_t {
hashbin_t *hashbin_new(int type); hashbin_t *hashbin_new(int type);
int hashbin_delete(hashbin_t* hashbin, FREE_FUNC func); int hashbin_delete(hashbin_t* hashbin, FREE_FUNC func);
int hashbin_clear(hashbin_t* hashbin, FREE_FUNC free_func); int hashbin_clear(hashbin_t* hashbin, FREE_FUNC free_func);
void hashbin_insert(hashbin_t* hashbin, irda_queue_t* entry, __u32 hashv, void hashbin_insert(hashbin_t* hashbin, irda_queue_t* entry, long hashv,
char* name); char* name);
void* hashbin_find(hashbin_t* hashbin, __u32 hashv, char* name); void* hashbin_remove(hashbin_t* hashbin, long hashv, char* name);
void* hashbin_remove(hashbin_t* hashbin, __u32 hashv, char* name);
void* hashbin_remove_first(hashbin_t *hashbin); void* hashbin_remove_first(hashbin_t *hashbin);
void* hashbin_remove_this( hashbin_t* hashbin, irda_queue_t* entry); void* hashbin_remove_this( hashbin_t* hashbin, irda_queue_t* entry);
void* hashbin_find(hashbin_t* hashbin, long hashv, char* name);
void* hashbin_lock_find(hashbin_t* hashbin, long hashv, char* name);
void* hashbin_find_next(hashbin_t* hashbin, long hashv, char* name,
void ** pnext);
irda_queue_t *hashbin_get_first(hashbin_t *hashbin); irda_queue_t *hashbin_get_first(hashbin_t *hashbin);
irda_queue_t *hashbin_get_next(hashbin_t *hashbin); irda_queue_t *hashbin_get_next(hashbin_t *hashbin);
void enqueue_last(irda_queue_t **queue, irda_queue_t* element);
void enqueue_first(irda_queue_t **queue, irda_queue_t* element);
irda_queue_t *dequeue_first(irda_queue_t **queue);
#define HASHBIN_GET_SIZE(hashbin) hashbin->hb_size #define HASHBIN_GET_SIZE(hashbin) hashbin->hb_size
#endif #endif
...@@ -62,6 +62,9 @@ struct irtty_cb { ...@@ -62,6 +62,9 @@ struct irtty_cb {
struct qos_info qos; /* QoS capabilities for this device */ struct qos_info qos; /* QoS capabilities for this device */
dongle_t *dongle; /* Dongle driver */ dongle_t *dongle; /* Dongle driver */
spinlock_t lock; /* For serializing operations */
__u32 new_speed; __u32 new_speed;
__u32 flags; /* Interface flags */ __u32 flags; /* Interface flags */
......
...@@ -165,7 +165,9 @@ struct ircc_cb { ...@@ -165,7 +165,9 @@ struct ircc_cb {
struct irport_cb *irport; struct irport_cb *irport;
spinlock_t lock; /* For serializing operations */ /* Locking : half of our operations are done with irport, so we
* use the irport spinlock to make sure *everything* is properly
* synchronised - Jean II */
__u32 new_speed; __u32 new_speed;
__u32 flags; /* Interface flags */ __u32 flags; /* Interface flags */
......
...@@ -179,6 +179,11 @@ struct w83977af_ir { ...@@ -179,6 +179,11 @@ struct w83977af_ir {
chipio_t io; /* IrDA controller information */ chipio_t io; /* IrDA controller information */
iobuff_t tx_buff; /* Transmit buffer */ iobuff_t tx_buff; /* Transmit buffer */
iobuff_t rx_buff; /* Receive buffer */ iobuff_t rx_buff; /* Receive buffer */
/* Note : currently locking is *very* incomplete, but this
* will get you started. Check in nsc-ircc.c for a proper
* locking strategy. - Jean II */
spinlock_t lock; /* For serializing operations */
__u32 flags; /* Interface flags */ __u32 flags; /* Interface flags */
__u32 new_speed; __u32 new_speed;
......
...@@ -61,7 +61,7 @@ void irlmp_add_discovery(hashbin_t *cachelog, discovery_t *new) ...@@ -61,7 +61,7 @@ void irlmp_add_discovery(hashbin_t *cachelog, discovery_t *new)
/* Set time of first discovery if node is new (see below) */ /* Set time of first discovery if node is new (see below) */
new->first_timestamp = new->timestamp; new->first_timestamp = new->timestamp;
spin_lock_irqsave(&irlmp->log_lock, flags); spin_lock_irqsave(&cachelog->hb_spinlock, flags);
/* /*
* Remove all discoveries of devices that has previously been * Remove all discoveries of devices that has previously been
...@@ -95,13 +95,13 @@ void irlmp_add_discovery(hashbin_t *cachelog, discovery_t *new) ...@@ -95,13 +95,13 @@ void irlmp_add_discovery(hashbin_t *cachelog, discovery_t *new)
/* Insert the new and updated version */ /* Insert the new and updated version */
hashbin_insert(cachelog, (irda_queue_t *) new, new->daddr, NULL); hashbin_insert(cachelog, (irda_queue_t *) new, new->daddr, NULL);
spin_unlock_irqrestore(&irlmp->log_lock, flags); spin_unlock_irqrestore(&cachelog->hb_spinlock, flags);
} }
/* /*
* Function irlmp_add_discovery_log (cachelog, log) * Function irlmp_add_discovery_log (cachelog, log)
* *
* Merge a disovery log into the cachlog. * Merge a disovery log into the cachelog.
* *
*/ */
void irlmp_add_discovery_log(hashbin_t *cachelog, hashbin_t *log) void irlmp_add_discovery_log(hashbin_t *cachelog, hashbin_t *log)
...@@ -115,11 +115,17 @@ void irlmp_add_discovery_log(hashbin_t *cachelog, hashbin_t *log) ...@@ -115,11 +115,17 @@ void irlmp_add_discovery_log(hashbin_t *cachelog, hashbin_t *log)
* discovery, so restart discovery again with just the half timeout * discovery, so restart discovery again with just the half timeout
* of the normal one. * of the normal one.
*/ */
/* Well... It means that there was nobody out there - Jean II */
if (log == NULL) { if (log == NULL) {
/* irlmp_start_discovery_timer(irlmp, 150); */ /* irlmp_start_discovery_timer(irlmp, 150); */
return; return;
} }
/*
* Locking : we are the only owner of this discovery log, so
* no need to lock it.
* We just need to lock the global log in irlmp_add_discovery().
*/
discovery = (discovery_t *) hashbin_remove_first(log); discovery = (discovery_t *) hashbin_remove_first(log);
while (discovery != NULL) { while (discovery != NULL) {
irlmp_add_discovery(cachelog, discovery); irlmp_add_discovery(cachelog, discovery);
...@@ -146,7 +152,7 @@ void irlmp_expire_discoveries(hashbin_t *log, __u32 saddr, int force) ...@@ -146,7 +152,7 @@ void irlmp_expire_discoveries(hashbin_t *log, __u32 saddr, int force)
IRDA_DEBUG(4, __FUNCTION__ "()\n"); IRDA_DEBUG(4, __FUNCTION__ "()\n");
spin_lock_irqsave(&irlmp->log_lock, flags); spin_lock_irqsave(&log->hb_spinlock, flags);
discovery = (discovery_t *) hashbin_get_first(log); discovery = (discovery_t *) hashbin_get_first(log);
while (discovery != NULL) { while (discovery != NULL) {
...@@ -169,7 +175,7 @@ void irlmp_expire_discoveries(hashbin_t *log, __u32 saddr, int force) ...@@ -169,7 +175,7 @@ void irlmp_expire_discoveries(hashbin_t *log, __u32 saddr, int force)
} }
} }
spin_unlock_irqrestore(&irlmp->log_lock, flags); spin_unlock_irqrestore(&log->hb_spinlock, flags);
} }
/* /*
...@@ -230,13 +236,13 @@ struct irda_device_info *irlmp_copy_discoveries(hashbin_t *log, int *pn, __u16 m ...@@ -230,13 +236,13 @@ struct irda_device_info *irlmp_copy_discoveries(hashbin_t *log, int *pn, __u16 m
return NULL; return NULL;
/* Save spin lock - spinlock should be discovery specific */ /* Save spin lock - spinlock should be discovery specific */
spin_lock_irqsave(&irlmp->log_lock, flags); spin_lock_irqsave(&log->hb_spinlock, flags);
/* Create the client specific buffer */ /* Create the client specific buffer */
n = HASHBIN_GET_SIZE(log); n = HASHBIN_GET_SIZE(log);
buffer = kmalloc(n * sizeof(struct irda_device_info), GFP_ATOMIC); buffer = kmalloc(n * sizeof(struct irda_device_info), GFP_ATOMIC);
if (buffer == NULL) { if (buffer == NULL) {
spin_unlock_irqrestore(&irlmp->log_lock, flags); spin_unlock_irqrestore(&log->hb_spinlock, flags);
return NULL; return NULL;
} }
...@@ -257,7 +263,7 @@ struct irda_device_info *irlmp_copy_discoveries(hashbin_t *log, int *pn, __u16 m ...@@ -257,7 +263,7 @@ struct irda_device_info *irlmp_copy_discoveries(hashbin_t *log, int *pn, __u16 m
discovery = (discovery_t *) hashbin_get_next(log); discovery = (discovery_t *) hashbin_get_next(log);
} }
spin_unlock_irqrestore(&irlmp->log_lock, flags); spin_unlock_irqrestore(&log->hb_spinlock, flags);
/* Get the actual number of device in the buffer and return */ /* Get the actual number of device in the buffer and return */
*pn = i; *pn = i;
...@@ -276,7 +282,7 @@ __u32 irlmp_find_device(hashbin_t *cachelog, char *name, __u32 *saddr) ...@@ -276,7 +282,7 @@ __u32 irlmp_find_device(hashbin_t *cachelog, char *name, __u32 *saddr)
unsigned long flags; unsigned long flags;
discovery_t *d; discovery_t *d;
spin_lock_irqsave(&irlmp->log_lock, flags); spin_lock_irqsave(&cachelog->hb_spinlock, flags);
/* Look at all discoveries for that link */ /* Look at all discoveries for that link */
d = (discovery_t *) hashbin_get_first(cachelog); d = (discovery_t *) hashbin_get_first(cachelog);
...@@ -288,13 +294,13 @@ __u32 irlmp_find_device(hashbin_t *cachelog, char *name, __u32 *saddr) ...@@ -288,13 +294,13 @@ __u32 irlmp_find_device(hashbin_t *cachelog, char *name, __u32 *saddr)
if (strcmp(name, d->nickname) == 0) { if (strcmp(name, d->nickname) == 0) {
*saddr = d->saddr; *saddr = d->saddr;
spin_unlock_irqrestore(&irlmp->log_lock, flags); spin_unlock_irqrestore(&cachelog->hb_spinlock, flags);
return d->daddr; return d->daddr;
} }
d = (discovery_t *) hashbin_get_next(cachelog); d = (discovery_t *) hashbin_get_next(cachelog);
} }
spin_unlock_irqrestore(&irlmp->log_lock, flags); spin_unlock_irqrestore(&cachelog->hb_spinlock, flags);
return 0; return 0;
} }
...@@ -310,7 +316,7 @@ int discovery_proc_read(char *buf, char **start, off_t offset, int length, ...@@ -310,7 +316,7 @@ int discovery_proc_read(char *buf, char **start, off_t offset, int length,
{ {
discovery_t *discovery; discovery_t *discovery;
unsigned long flags; unsigned long flags;
hashbin_t *cachelog = irlmp_get_cachelog(); hashbin_t *cachelog = irlmp->cachelog;
int len = 0; int len = 0;
if (!irlmp) if (!irlmp)
...@@ -318,7 +324,7 @@ int discovery_proc_read(char *buf, char **start, off_t offset, int length, ...@@ -318,7 +324,7 @@ int discovery_proc_read(char *buf, char **start, off_t offset, int length,
len = sprintf(buf, "IrLMP: Discovery log:\n\n"); len = sprintf(buf, "IrLMP: Discovery log:\n\n");
spin_lock_irqsave(&irlmp->log_lock, flags); spin_lock_irqsave(&cachelog->hb_spinlock, flags);
discovery = (discovery_t *) hashbin_get_first(cachelog); discovery = (discovery_t *) hashbin_get_first(cachelog);
while (( discovery != NULL) && (len < length)) { while (( discovery != NULL) && (len < length)) {
...@@ -362,7 +368,7 @@ int discovery_proc_read(char *buf, char **start, off_t offset, int length, ...@@ -362,7 +368,7 @@ int discovery_proc_read(char *buf, char **start, off_t offset, int length,
discovery = (discovery_t *) hashbin_get_next(cachelog); discovery = (discovery_t *) hashbin_get_next(cachelog);
} }
spin_unlock_irqrestore(&irlmp->log_lock, flags); spin_unlock_irqrestore(&cachelog->hb_spinlock, flags);
return len; return len;
} }
...@@ -61,7 +61,7 @@ hashbin_t *ircomm = NULL; ...@@ -61,7 +61,7 @@ hashbin_t *ircomm = NULL;
int __init ircomm_init(void) int __init ircomm_init(void)
{ {
ircomm = hashbin_new(HB_LOCAL); ircomm = hashbin_new(HB_LOCK);
if (ircomm == NULL) { if (ircomm == NULL) {
ERROR(__FUNCTION__ "(), can't allocate hashbin!\n"); ERROR(__FUNCTION__ "(), can't allocate hashbin!\n");
return -ENOMEM; return -ENOMEM;
...@@ -505,11 +505,10 @@ int ircomm_proc_read(char *buf, char **start, off_t offset, int len) ...@@ -505,11 +505,10 @@ int ircomm_proc_read(char *buf, char **start, off_t offset, int len)
struct ircomm_cb *self; struct ircomm_cb *self;
unsigned long flags; unsigned long flags;
save_flags(flags);
cli();
len = 0; len = 0;
spin_lock_irqsave(&ircomm->hb_spinlock, flags);
self = (struct ircomm_cb *) hashbin_get_first(ircomm); self = (struct ircomm_cb *) hashbin_get_first(ircomm);
while (self != NULL) { while (self != NULL) {
ASSERT(self->magic == IRCOMM_MAGIC, break;); ASSERT(self->magic == IRCOMM_MAGIC, break;);
...@@ -535,7 +534,7 @@ int ircomm_proc_read(char *buf, char **start, off_t offset, int len) ...@@ -535,7 +534,7 @@ int ircomm_proc_read(char *buf, char **start, off_t offset, int len)
self = (struct ircomm_cb *) hashbin_get_next(ircomm); self = (struct ircomm_cb *) hashbin_get_next(ircomm);
} }
restore_flags(flags); spin_unlock_irqrestore(&ircomm->hb_spinlock, flags);
return len; return len;
} }
......
...@@ -177,7 +177,7 @@ void ircomm_lmp_flow_control(struct sk_buff *skb) ...@@ -177,7 +177,7 @@ void ircomm_lmp_flow_control(struct sk_buff *skb)
line = cb->line; line = cb->line;
self = (struct ircomm_cb *) hashbin_find(ircomm, line, NULL); self = (struct ircomm_cb *) hashbin_lock_find(ircomm, line, NULL);
if (!self) { if (!self) {
IRDA_DEBUG(2, __FUNCTION__ "(), didn't find myself\n"); IRDA_DEBUG(2, __FUNCTION__ "(), didn't find myself\n");
return; return;
......
...@@ -99,6 +99,8 @@ pi_param_info_t ircomm_param_info = { pi_major_call_table, 3, 0x0f, 4 }; ...@@ -99,6 +99,8 @@ pi_param_info_t ircomm_param_info = { pi_major_call_table, 3, 0x0f, 4 };
*/ */
int ircomm_param_flush(struct ircomm_tty_cb *self) int ircomm_param_flush(struct ircomm_tty_cb *self)
{ {
/* we should lock here, but I guess this function is unused...
* Jean II */
if (self->ctrl_skb) { if (self->ctrl_skb) {
ircomm_control_request(self->ircomm, self->ctrl_skb); ircomm_control_request(self->ircomm, self->ctrl_skb);
self->ctrl_skb = NULL; self->ctrl_skb = NULL;
...@@ -132,14 +134,13 @@ int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush) ...@@ -132,14 +134,13 @@ int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush)
if (self->service_type == IRCOMM_3_WIRE_RAW) if (self->service_type == IRCOMM_3_WIRE_RAW)
return 0; return 0;
save_flags(flags); spin_lock_irqsave(&self->spinlock, flags);
cli();
skb = self->ctrl_skb; skb = self->ctrl_skb;
if (!skb) { if (!skb) {
skb = dev_alloc_skb(256); skb = dev_alloc_skb(256);
if (!skb) { if (!skb) {
restore_flags(flags); spin_unlock_irqrestore(&self->spinlock, flags);
return -ENOMEM; return -ENOMEM;
} }
...@@ -154,12 +155,12 @@ int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush) ...@@ -154,12 +155,12 @@ int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush)
&ircomm_param_info); &ircomm_param_info);
if (count < 0) { if (count < 0) {
WARNING(__FUNCTION__ "(), no room for parameter!\n"); WARNING(__FUNCTION__ "(), no room for parameter!\n");
restore_flags(flags); spin_unlock_irqrestore(&self->spinlock, flags);
return -1; return -1;
} }
skb_put(skb, count); skb_put(skb, count);
restore_flags(flags); spin_unlock_irqrestore(&self->spinlock, flags);
IRDA_DEBUG(2, __FUNCTION__ "(), skb->len=%d\n", skb->len); IRDA_DEBUG(2, __FUNCTION__ "(), skb->len=%d\n", skb->len);
......
...@@ -90,7 +90,7 @@ hashbin_t *ircomm_tty = NULL; ...@@ -90,7 +90,7 @@ hashbin_t *ircomm_tty = NULL;
*/ */
int __init ircomm_tty_init(void) int __init ircomm_tty_init(void)
{ {
ircomm_tty = hashbin_new(HB_LOCAL); ircomm_tty = hashbin_new(HB_LOCK);
if (ircomm_tty == NULL) { if (ircomm_tty == NULL) {
ERROR(__FUNCTION__ "(), can't allocate hashbin!\n"); ERROR(__FUNCTION__ "(), can't allocate hashbin!\n");
return -ENOMEM; return -ENOMEM;
...@@ -308,22 +308,25 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self, ...@@ -308,22 +308,25 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
IRDA_DEBUG(2, "%s(%d):block_til_ready before block on %s open_count=%d\n", IRDA_DEBUG(2, "%s(%d):block_til_ready before block on %s open_count=%d\n",
__FILE__,__LINE__, tty->driver.name, self->open_count ); __FILE__,__LINE__, tty->driver.name, self->open_count );
save_flags(flags); cli(); /* As far as I can see, we protect open_count - Jean II */
spin_lock_irqsave(&self->spinlock, flags);
if (!tty_hung_up_p(filp)) { if (!tty_hung_up_p(filp)) {
extra_count = 1; extra_count = 1;
self->open_count--; self->open_count--;
} }
restore_flags(flags); spin_unlock_irqrestore(&self->spinlock, flags);
self->blocked_open++; self->blocked_open++;
while (1) { while (1) {
if (!(self->flags & ASYNC_CALLOUT_ACTIVE) && if (!(self->flags & ASYNC_CALLOUT_ACTIVE) &&
(tty->termios->c_cflag & CBAUD)) { (tty->termios->c_cflag & CBAUD)) {
save_flags(flags); cli(); /* Here, we use to lock those two guys, but
* as ircomm_param_request() does it itself,
* I don't see the point (and I see the deadlock).
* Jean II */
self->settings.dte |= IRCOMM_RTS + IRCOMM_DTR; self->settings.dte |= IRCOMM_RTS + IRCOMM_DTR;
ircomm_param_request(self, IRCOMM_DTE, TRUE); ircomm_param_request(self, IRCOMM_DTE, TRUE);
restore_flags(flags);
} }
current->state = TASK_INTERRUPTIBLE; current->state = TASK_INTERRUPTIBLE;
...@@ -361,8 +364,12 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self, ...@@ -361,8 +364,12 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
__set_current_state(TASK_RUNNING); __set_current_state(TASK_RUNNING);
remove_wait_queue(&self->open_wait, &wait); remove_wait_queue(&self->open_wait, &wait);
if (extra_count) if (extra_count) {
/* ++ is not atomic, so this should be protected - Jean II */
spin_lock_irqsave(&self->spinlock, flags);
self->open_count++; self->open_count++;
spin_unlock_irqrestore(&self->spinlock, flags);
}
self->blocked_open--; self->blocked_open--;
IRDA_DEBUG(1, "%s(%d):block_til_ready after blocking on %s open_count=%d\n", IRDA_DEBUG(1, "%s(%d):block_til_ready after blocking on %s open_count=%d\n",
...@@ -385,6 +392,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp) ...@@ -385,6 +392,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
{ {
struct ircomm_tty_cb *self; struct ircomm_tty_cb *self;
unsigned int line; unsigned int line;
unsigned long flags;
int ret; int ret;
IRDA_DEBUG(2, __FUNCTION__ "()\n"); IRDA_DEBUG(2, __FUNCTION__ "()\n");
...@@ -397,7 +405,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp) ...@@ -397,7 +405,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
} }
/* Check if instance already exists */ /* Check if instance already exists */
self = hashbin_find(ircomm_tty, line, NULL); self = hashbin_lock_find(ircomm_tty, line, NULL);
if (!self) { if (!self) {
/* No, so make new instance */ /* No, so make new instance */
self = kmalloc(sizeof(struct ircomm_tty_cb), GFP_KERNEL); self = kmalloc(sizeof(struct ircomm_tty_cb), GFP_KERNEL);
...@@ -423,6 +431,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp) ...@@ -423,6 +431,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
init_timer(&self->watchdog_timer); init_timer(&self->watchdog_timer);
init_waitqueue_head(&self->open_wait); init_waitqueue_head(&self->open_wait);
init_waitqueue_head(&self->close_wait); init_waitqueue_head(&self->close_wait);
spin_lock_init(&self->spinlock);
/* /*
* Force TTY into raw mode by default which is usually what * Force TTY into raw mode by default which is usually what
...@@ -435,10 +444,13 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp) ...@@ -435,10 +444,13 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
/* Insert into hash */ /* Insert into hash */
hashbin_insert(ircomm_tty, (irda_queue_t *) self, line, NULL); hashbin_insert(ircomm_tty, (irda_queue_t *) self, line, NULL);
} }
/* ++ is not atomic, so this should be protected - Jean II */
spin_lock_irqsave(&self->spinlock, flags);
self->open_count++; self->open_count++;
tty->driver_data = self; tty->driver_data = self;
self->tty = tty; self->tty = tty;
spin_unlock_irqrestore(&self->spinlock, flags);
IRDA_DEBUG(1, __FUNCTION__"(), %s%d, count = %d\n", tty->driver.name, IRDA_DEBUG(1, __FUNCTION__"(), %s%d, count = %d\n", tty->driver.name,
self->line, self->open_count); self->line, self->open_count);
...@@ -526,12 +538,11 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp) ...@@ -526,12 +538,11 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
ASSERT(self != NULL, return;); ASSERT(self != NULL, return;);
ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
save_flags(flags); spin_lock_irqsave(&self->spinlock, flags);
cli();
if (tty_hung_up_p(filp)) { if (tty_hung_up_p(filp)) {
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
restore_flags(flags); spin_unlock_irqrestore(&self->spinlock, flags);
IRDA_DEBUG(0, __FUNCTION__ "(), returning 1\n"); IRDA_DEBUG(0, __FUNCTION__ "(), returning 1\n");
return; return;
...@@ -559,13 +570,19 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp) ...@@ -559,13 +570,19 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
} }
if (self->open_count) { if (self->open_count) {
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
restore_flags(flags); spin_unlock_irqrestore(&self->spinlock, flags);
IRDA_DEBUG(0, __FUNCTION__ "(), open count > 0\n"); IRDA_DEBUG(0, __FUNCTION__ "(), open count > 0\n");
return; return;
} }
self->flags |= ASYNC_CLOSING; self->flags |= ASYNC_CLOSING;
/* We need to unlock here (we were unlocking at the end of this
* function), because tty_wait_until_sent() may schedule.
* I don't know if the rest should be locked somehow,
* so someone should check. - Jean II */
spin_unlock_irqrestore(&self->spinlock, flags);
/* /*
* Now we wait for the transmit buffer to clear; and we notify * Now we wait for the transmit buffer to clear; and we notify
* the line discipline to only process XON/XOFF characters. * the line discipline to only process XON/XOFF characters.
...@@ -597,7 +614,6 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp) ...@@ -597,7 +614,6 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
wake_up_interruptible(&self->close_wait); wake_up_interruptible(&self->close_wait);
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
restore_flags(flags);
} }
/* /*
...@@ -645,13 +661,12 @@ static void ircomm_tty_do_softint(void *private_) ...@@ -645,13 +661,12 @@ static void ircomm_tty_do_softint(void *private_)
return; return;
/* Unlink control buffer */ /* Unlink control buffer */
save_flags(flags); spin_lock_irqsave(&self->spinlock, flags);
cli();
ctrl_skb = self->ctrl_skb; ctrl_skb = self->ctrl_skb;
self->ctrl_skb = NULL; self->ctrl_skb = NULL;
restore_flags(flags); spin_unlock_irqrestore(&self->spinlock, flags);
/* Flush control buffer if any */ /* Flush control buffer if any */
if (ctrl_skb && self->flow == FLOW_START) if (ctrl_skb && self->flow == FLOW_START)
...@@ -661,13 +676,12 @@ static void ircomm_tty_do_softint(void *private_) ...@@ -661,13 +676,12 @@ static void ircomm_tty_do_softint(void *private_)
return; return;
/* Unlink transmit buffer */ /* Unlink transmit buffer */
save_flags(flags); spin_lock_irqsave(&self->spinlock, flags);
cli();
skb = self->tx_skb; skb = self->tx_skb;
self->tx_skb = NULL; self->tx_skb = NULL;
restore_flags(flags); spin_unlock_irqrestore(&self->spinlock, flags);
/* Flush transmit buffer if any */ /* Flush transmit buffer if any */
if (skb) if (skb)
...@@ -720,8 +734,7 @@ static int ircomm_tty_write(struct tty_struct *tty, int from_user, ...@@ -720,8 +734,7 @@ static int ircomm_tty_write(struct tty_struct *tty, int from_user,
return len; return len;
} }
save_flags(flags); spin_lock_irqsave(&self->spinlock, flags);
cli();
/* Fetch current transmit buffer */ /* Fetch current transmit buffer */
skb = self->tx_skb; skb = self->tx_skb;
...@@ -768,7 +781,7 @@ static int ircomm_tty_write(struct tty_struct *tty, int from_user, ...@@ -768,7 +781,7 @@ static int ircomm_tty_write(struct tty_struct *tty, int from_user,
skb = dev_alloc_skb(self->max_data_size+ skb = dev_alloc_skb(self->max_data_size+
self->max_header_size); self->max_header_size);
if (!skb) { if (!skb) {
restore_flags(flags); spin_unlock_irqrestore(&self->spinlock, flags);
return -ENOBUFS; return -ENOBUFS;
} }
skb_reserve(skb, self->max_header_size); skb_reserve(skb, self->max_header_size);
...@@ -785,7 +798,7 @@ static int ircomm_tty_write(struct tty_struct *tty, int from_user, ...@@ -785,7 +798,7 @@ static int ircomm_tty_write(struct tty_struct *tty, int from_user,
len += size; len += size;
} }
restore_flags(flags); spin_unlock_irqrestore(&self->spinlock, flags);
/* /*
* Schedule a new thread which will transmit the frame as soon * Schedule a new thread which will transmit the frame as soon
...@@ -824,13 +837,12 @@ static int ircomm_tty_write_room(struct tty_struct *tty) ...@@ -824,13 +837,12 @@ static int ircomm_tty_write_room(struct tty_struct *tty)
(self->max_header_size == IRCOMM_TTY_HDR_UNITIALISED)) (self->max_header_size == IRCOMM_TTY_HDR_UNITIALISED))
ret = 0; ret = 0;
else { else {
save_flags(flags); spin_lock_irqsave(&self->spinlock, flags);
cli();
if (self->tx_skb) if (self->tx_skb)
ret = self->max_data_size - self->tx_skb->len; ret = self->max_data_size - self->tx_skb->len;
else else
ret = self->max_data_size; ret = self->max_data_size;
restore_flags(flags); spin_unlock_irqrestore(&self->spinlock, flags);
} }
IRDA_DEBUG(2, __FUNCTION__ "(), ret=%d\n", ret); IRDA_DEBUG(2, __FUNCTION__ "(), ret=%d\n", ret);
...@@ -946,13 +958,12 @@ static int ircomm_tty_chars_in_buffer(struct tty_struct *tty) ...@@ -946,13 +958,12 @@ static int ircomm_tty_chars_in_buffer(struct tty_struct *tty)
ASSERT(self != NULL, return -1;); ASSERT(self != NULL, return -1;);
ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
save_flags(flags); spin_lock_irqsave(&self->spinlock, flags);
cli();
if (self->tx_skb) if (self->tx_skb)
len = self->tx_skb->len; len = self->tx_skb->len;
restore_flags(flags); spin_unlock_irqrestore(&self->spinlock, flags);
return len; return len;
} }
...@@ -969,8 +980,7 @@ static void ircomm_tty_shutdown(struct ircomm_tty_cb *self) ...@@ -969,8 +980,7 @@ static void ircomm_tty_shutdown(struct ircomm_tty_cb *self)
if (!(self->flags & ASYNC_INITIALIZED)) if (!(self->flags & ASYNC_INITIALIZED))
return; return;
save_flags(flags); spin_lock_irqsave(&self->spinlock, flags);
cli();
del_timer(&self->watchdog_timer); del_timer(&self->watchdog_timer);
...@@ -994,7 +1004,7 @@ static void ircomm_tty_shutdown(struct ircomm_tty_cb *self) ...@@ -994,7 +1004,7 @@ static void ircomm_tty_shutdown(struct ircomm_tty_cb *self)
} }
self->flags &= ~ASYNC_INITIALIZED; self->flags &= ~ASYNC_INITIALIZED;
restore_flags(flags); spin_unlock_irqrestore(&self->spinlock, flags);
} }
/* /*
...@@ -1007,6 +1017,7 @@ static void ircomm_tty_shutdown(struct ircomm_tty_cb *self) ...@@ -1007,6 +1017,7 @@ static void ircomm_tty_shutdown(struct ircomm_tty_cb *self)
static void ircomm_tty_hangup(struct tty_struct *tty) static void ircomm_tty_hangup(struct tty_struct *tty)
{ {
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
unsigned long flags;
IRDA_DEBUG(0, __FUNCTION__"()\n"); IRDA_DEBUG(0, __FUNCTION__"()\n");
...@@ -1019,9 +1030,13 @@ static void ircomm_tty_hangup(struct tty_struct *tty) ...@@ -1019,9 +1030,13 @@ static void ircomm_tty_hangup(struct tty_struct *tty)
/* ircomm_tty_flush_buffer(tty); */ /* ircomm_tty_flush_buffer(tty); */
ircomm_tty_shutdown(self); ircomm_tty_shutdown(self);
/* I guess we need to lock here - Jean II */
spin_lock_irqsave(&self->spinlock, flags);
self->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE); self->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
self->tty = 0; self->tty = 0;
self->open_count = 0; self->open_count = 0;
spin_unlock_irqrestore(&self->spinlock, flags);
wake_up_interruptible(&self->open_wait); wake_up_interruptible(&self->open_wait);
} }
...@@ -1362,11 +1377,14 @@ static int ircomm_tty_read_proc(char *buf, char **start, off_t offset, int len, ...@@ -1362,11 +1377,14 @@ static int ircomm_tty_read_proc(char *buf, char **start, off_t offset, int len,
struct ircomm_tty_cb *self; struct ircomm_tty_cb *self;
int count = 0, l; int count = 0, l;
off_t begin = 0; off_t begin = 0;
unsigned long flags;
spin_lock_irqsave(&ircomm_tty->hb_spinlock, flags);
self = (struct ircomm_tty_cb *) hashbin_get_first(ircomm_tty); self = (struct ircomm_tty_cb *) hashbin_get_first(ircomm_tty);
while ((self != NULL) && (count < 4000)) { while ((self != NULL) && (count < 4000)) {
if (self->magic != IRCOMM_TTY_MAGIC) if (self->magic != IRCOMM_TTY_MAGIC)
return 0; break;
l = ircomm_tty_line_info(self, buf + count); l = ircomm_tty_line_info(self, buf + count);
count += l; count += l;
...@@ -1381,6 +1399,8 @@ static int ircomm_tty_read_proc(char *buf, char **start, off_t offset, int len, ...@@ -1381,6 +1399,8 @@ static int ircomm_tty_read_proc(char *buf, char **start, off_t offset, int len,
} }
*eof = 1; *eof = 1;
done: done:
spin_unlock_irqrestore(&ircomm_tty->hb_spinlock, flags);
if (offset >= count+begin) if (offset >= count+begin)
return 0; return 0;
*start = buf + (offset-begin); *start = buf + (offset-begin);
......
...@@ -331,6 +331,8 @@ static void ircomm_tty_discovery_indication(discovery_t *discovery, ...@@ -331,6 +331,8 @@ static void ircomm_tty_discovery_indication(discovery_t *discovery,
info.daddr = discovery->daddr; info.daddr = discovery->daddr;
info.saddr = discovery->saddr; info.saddr = discovery->saddr;
/* FIXME. We probably need to use hashbin_find_next(), but we first
* need to ensure that "line" is unique. - Jean II */
self = (struct ircomm_tty_cb *) hashbin_get_first(ircomm_tty); self = (struct ircomm_tty_cb *) hashbin_get_first(ircomm_tty);
while (self != NULL) { while (self != NULL) {
ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
......
...@@ -91,13 +91,13 @@ int irda_device_proc_read(char *buf, char **start, off_t offset, int len, ...@@ -91,13 +91,13 @@ int irda_device_proc_read(char *buf, char **start, off_t offset, int len,
int __init irda_device_init( void) int __init irda_device_init( void)
{ {
dongles = hashbin_new(HB_GLOBAL); dongles = hashbin_new(HB_LOCK);
if (dongles == NULL) { if (dongles == NULL) {
printk(KERN_WARNING "IrDA: Can't allocate dongles hashbin!\n"); printk(KERN_WARNING "IrDA: Can't allocate dongles hashbin!\n");
return -ENOMEM; return -ENOMEM;
} }
tasks = hashbin_new(HB_GLOBAL); tasks = hashbin_new(HB_LOCK);
if (tasks == NULL) { if (tasks == NULL) {
printk(KERN_WARNING "IrDA: Can't allocate tasks hashbin!\n"); printk(KERN_WARNING "IrDA: Can't allocate tasks hashbin!\n");
return -ENOMEM; return -ENOMEM;
...@@ -438,7 +438,7 @@ dongle_t *irda_device_dongle_init(struct net_device *dev, int type) ...@@ -438,7 +438,7 @@ dongle_t *irda_device_dongle_init(struct net_device *dev, int type)
} }
#endif #endif
if (!(reg = hashbin_find(dongles, type, NULL))) { if (!(reg = hashbin_lock_find(dongles, type, NULL))) {
ERROR("IrDA: Unable to find requested dongle\n"); ERROR("IrDA: Unable to find requested dongle\n");
return NULL; return NULL;
} }
...@@ -477,7 +477,7 @@ int irda_device_dongle_cleanup(dongle_t *dongle) ...@@ -477,7 +477,7 @@ int irda_device_dongle_cleanup(dongle_t *dongle)
int irda_device_register_dongle(struct dongle_reg *new) int irda_device_register_dongle(struct dongle_reg *new)
{ {
/* Check if this dongle has been registred before */ /* Check if this dongle has been registred before */
if (hashbin_find(dongles, new->type, NULL)) { if (hashbin_lock_find(dongles, new->type, NULL)) {
MESSAGE("%s: Dongle already registered\n", __FUNCTION__); MESSAGE("%s: Dongle already registered\n", __FUNCTION__);
return 0; return 0;
} }
......
...@@ -58,7 +58,7 @@ static const char *ias_charset_types[] = { ...@@ -58,7 +58,7 @@ static const char *ias_charset_types[] = {
#endif /* CONFIG_IRDA_DEBUG */ #endif /* CONFIG_IRDA_DEBUG */
static hashbin_t *iriap = NULL; static hashbin_t *iriap = NULL;
static __u32 service_handle; static void *service_handle;
extern char *lmp_reasons[]; extern char *lmp_reasons[];
...@@ -91,11 +91,12 @@ int __init iriap_init(void) ...@@ -91,11 +91,12 @@ int __init iriap_init(void)
__u16 hints; __u16 hints;
/* Allocate master array */ /* Allocate master array */
iriap = hashbin_new(HB_LOCAL); iriap = hashbin_new(HB_LOCK);
if (!iriap) if (!iriap)
return -ENOMEM; return -ENOMEM;
objects = hashbin_new(HB_LOCAL); /* Object repository - defined in irias_object.c */
objects = hashbin_new(HB_LOCK);
if (!objects) { if (!objects) {
WARNING("%s: Can't allocate objects hashbin!\n", __FUNCTION__); WARNING("%s: Can't allocate objects hashbin!\n", __FUNCTION__);
return -ENOMEM; return -ENOMEM;
...@@ -182,7 +183,7 @@ struct iriap_cb *iriap_open(__u8 slsap_sel, int mode, void *priv, ...@@ -182,7 +183,7 @@ struct iriap_cb *iriap_open(__u8 slsap_sel, int mode, void *priv,
init_timer(&self->watchdog_timer); init_timer(&self->watchdog_timer);
hashbin_insert(iriap, (irda_queue_t *) self, (int) self, NULL); hashbin_insert(iriap, (irda_queue_t *) self, (long) self, NULL);
/* Initialize state machines */ /* Initialize state machines */
iriap_next_client_state(self, S_DISCONNECT); iriap_next_client_state(self, S_DISCONNECT);
...@@ -235,7 +236,7 @@ void iriap_close(struct iriap_cb *self) ...@@ -235,7 +236,7 @@ void iriap_close(struct iriap_cb *self)
self->lsap = NULL; self->lsap = NULL;
} }
entry = (struct iriap_cb *) hashbin_remove(iriap, (int) self, NULL); entry = (struct iriap_cb *) hashbin_remove(iriap, (long) self, NULL);
ASSERT(entry == self, return;); ASSERT(entry == self, return;);
__iriap_close(self); __iriap_close(self);
...@@ -973,13 +974,12 @@ int irias_proc_read(char *buf, char **start, off_t offset, int len) ...@@ -973,13 +974,12 @@ int irias_proc_read(char *buf, char **start, off_t offset, int len)
ASSERT( objects != NULL, return 0;); ASSERT( objects != NULL, return 0;);
save_flags( flags);
cli();
len = 0; len = 0;
len += sprintf(buf+len, "LM-IAS Objects:\n"); len += sprintf(buf+len, "LM-IAS Objects:\n");
spin_lock_irqsave(&objects->hb_spinlock, flags);
/* List all objects */ /* List all objects */
obj = (struct ias_object *) hashbin_get_first(objects); obj = (struct ias_object *) hashbin_get_first(objects);
while ( obj != NULL) { while ( obj != NULL) {
...@@ -989,6 +989,11 @@ int irias_proc_read(char *buf, char **start, off_t offset, int len) ...@@ -989,6 +989,11 @@ int irias_proc_read(char *buf, char **start, off_t offset, int len)
len += sprintf(buf+len, "id=%d", obj->id); len += sprintf(buf+len, "id=%d", obj->id);
len += sprintf(buf+len, "\n"); len += sprintf(buf+len, "\n");
/* Careful for priority inversions here !
* All other uses of attrib spinlock are independant of
* the object spinlock, so we are safe. Jean II */
spin_lock(&obj->attribs->hb_spinlock);
/* List all attributes for this object */ /* List all attributes for this object */
attrib = (struct ias_attrib *) attrib = (struct ias_attrib *)
hashbin_get_first(obj->attribs); hashbin_get_first(obj->attribs);
...@@ -1025,9 +1030,11 @@ int irias_proc_read(char *buf, char **start, off_t offset, int len) ...@@ -1025,9 +1030,11 @@ int irias_proc_read(char *buf, char **start, off_t offset, int len)
attrib = (struct ias_attrib *) attrib = (struct ias_attrib *)
hashbin_get_next(obj->attribs); hashbin_get_next(obj->attribs);
} }
spin_unlock(&obj->attribs->hb_spinlock);
obj = (struct ias_object *) hashbin_get_next(objects); obj = (struct ias_object *) hashbin_get_next(objects);
} }
restore_flags(flags); spin_unlock_irqrestore(&objects->hb_spinlock, flags);
return len; return len;
} }
......
...@@ -93,7 +93,10 @@ struct ias_object *irias_new_object( char *name, int id) ...@@ -93,7 +93,10 @@ struct ias_object *irias_new_object( char *name, int id)
obj->name = strndup(name, IAS_MAX_CLASSNAME); obj->name = strndup(name, IAS_MAX_CLASSNAME);
obj->id = id; obj->id = id;
obj->attribs = hashbin_new(HB_LOCAL); /* Locking notes : the attrib spinlock has lower precendence
* than the objects spinlock. Never grap the objects spinlock
* while holding any attrib spinlock (risk of deadlock). Jean II */
obj->attribs = hashbin_new(HB_LOCK);
return obj; return obj;
} }
...@@ -147,7 +150,7 @@ int irias_delete_object(struct ias_object *obj) ...@@ -147,7 +150,7 @@ int irias_delete_object(struct ias_object *obj)
ASSERT(obj != NULL, return -1;); ASSERT(obj != NULL, return -1;);
ASSERT(obj->magic == IAS_OBJECT_MAGIC, return -1;); ASSERT(obj->magic == IAS_OBJECT_MAGIC, return -1;);
node = hashbin_remove(objects, 0, obj->name); node = hashbin_remove_this(objects, (irda_queue_t *) obj);
if (!node) if (!node)
return 0; /* Already removed */ return 0; /* Already removed */
...@@ -172,7 +175,7 @@ int irias_delete_attrib(struct ias_object *obj, struct ias_attrib *attrib) ...@@ -172,7 +175,7 @@ int irias_delete_attrib(struct ias_object *obj, struct ias_attrib *attrib)
ASSERT(attrib != NULL, return -1;); ASSERT(attrib != NULL, return -1;);
/* Remove attribute from object */ /* Remove attribute from object */
node = hashbin_remove(obj->attribs, 0, attrib->name); node = hashbin_remove_this(obj->attribs, (irda_queue_t *) attrib);
if (!node) if (!node)
return 0; /* Already removed or non-existent */ return 0; /* Already removed or non-existent */
...@@ -211,7 +214,8 @@ struct ias_object *irias_find_object(char *name) ...@@ -211,7 +214,8 @@ struct ias_object *irias_find_object(char *name)
{ {
ASSERT(name != NULL, return NULL;); ASSERT(name != NULL, return NULL;);
return hashbin_find(objects, 0, name); /* Unsafe (locking), object might change */
return hashbin_lock_find(objects, 0, name);
} }
/* /*
...@@ -228,10 +232,11 @@ struct ias_attrib *irias_find_attrib(struct ias_object *obj, char *name) ...@@ -228,10 +232,11 @@ struct ias_attrib *irias_find_attrib(struct ias_object *obj, char *name)
ASSERT(obj->magic == IAS_OBJECT_MAGIC, return NULL;); ASSERT(obj->magic == IAS_OBJECT_MAGIC, return NULL;);
ASSERT(name != NULL, return NULL;); ASSERT(name != NULL, return NULL;);
attrib = hashbin_find(obj->attribs, 0, name); attrib = hashbin_lock_find(obj->attribs, 0, name);
if (attrib == NULL) if (attrib == NULL)
return NULL; return NULL;
/* Unsafe (locking), attrib might change */
return attrib; return attrib;
} }
...@@ -267,26 +272,32 @@ int irias_object_change_attribute(char *obj_name, char *attrib_name, ...@@ -267,26 +272,32 @@ int irias_object_change_attribute(char *obj_name, char *attrib_name,
{ {
struct ias_object *obj; struct ias_object *obj;
struct ias_attrib *attrib; struct ias_attrib *attrib;
unsigned long flags;
/* Find object */ /* Find object */
obj = hashbin_find(objects, 0, obj_name); obj = hashbin_lock_find(objects, 0, obj_name);
if (obj == NULL) { if (obj == NULL) {
WARNING("%s: Unable to find object: %s\n", __FUNCTION__, WARNING("%s: Unable to find object: %s\n", __FUNCTION__,
obj_name); obj_name);
return -1; return -1;
} }
/* Slightly unsafe (obj might get removed under us) */
spin_lock_irqsave(&obj->attribs->hb_spinlock, flags);
/* Find attribute */ /* Find attribute */
attrib = hashbin_find(obj->attribs, 0, attrib_name); attrib = hashbin_find(obj->attribs, 0, attrib_name);
if (attrib == NULL) { if (attrib == NULL) {
WARNING("%s: Unable to find attribute: %s\n", __FUNCTION__, WARNING("%s: Unable to find attribute: %s\n", __FUNCTION__,
attrib_name); attrib_name);
spin_unlock_irqrestore(&obj->attribs->hb_spinlock, flags);
return -1; return -1;
} }
if ( attrib->value->type != new_value->type) { if ( attrib->value->type != new_value->type) {
IRDA_DEBUG( 0, __FUNCTION__ IRDA_DEBUG( 0, __FUNCTION__
"(), changing value type not allowed!\n"); "(), changing value type not allowed!\n");
spin_unlock_irqrestore(&obj->attribs->hb_spinlock, flags);
return -1; return -1;
} }
...@@ -297,6 +308,7 @@ int irias_object_change_attribute(char *obj_name, char *attrib_name, ...@@ -297,6 +308,7 @@ int irias_object_change_attribute(char *obj_name, char *attrib_name,
attrib->value = new_value; attrib->value = new_value;
/* Success */ /* Success */
spin_unlock_irqrestore(&obj->attribs->hb_spinlock, flags);
return 0; return 0;
} }
......
...@@ -124,7 +124,7 @@ int __init irlan_init(void) ...@@ -124,7 +124,7 @@ int __init irlan_init(void)
IRDA_DEBUG(0, __FUNCTION__ "()\n"); IRDA_DEBUG(0, __FUNCTION__ "()\n");
/* Allocate master structure */ /* Allocate master structure */
irlan = hashbin_new(HB_LOCAL); irlan = hashbin_new(HB_LOCK); /* protect from /proc */
if (irlan == NULL) { if (irlan == NULL) {
printk(KERN_WARNING "IrLAN: Can't allocate hashbin!\n"); printk(KERN_WARNING "IrLAN: Can't allocate hashbin!\n");
return -ENOMEM; return -ENOMEM;
...@@ -1089,11 +1089,10 @@ static int irlan_proc_read(char *buf, char **start, off_t offset, int len) ...@@ -1089,11 +1089,10 @@ static int irlan_proc_read(char *buf, char **start, off_t offset, int len)
unsigned long flags; unsigned long flags;
ASSERT(irlan != NULL, return 0;); ASSERT(irlan != NULL, return 0;);
save_flags(flags);
cli();
len = 0; len = 0;
spin_lock_irqsave(&irlan->hb_spinlock, flags);
len += sprintf(buf+len, "IrLAN instances:\n"); len += sprintf(buf+len, "IrLAN instances:\n");
self = (struct irlan_cb *) hashbin_get_first(irlan); self = (struct irlan_cb *) hashbin_get_first(irlan);
...@@ -1129,7 +1128,7 @@ static int irlan_proc_read(char *buf, char **start, off_t offset, int len) ...@@ -1129,7 +1128,7 @@ static int irlan_proc_read(char *buf, char **start, off_t offset, int len)
self = (struct irlan_cb *) hashbin_get_next(irlan); self = (struct irlan_cb *) hashbin_get_next(irlan);
} }
restore_flags(flags); spin_unlock_irqrestore(&irlan->hb_spinlock, flags);
return len; return len;
} }
......
...@@ -80,7 +80,7 @@ int irlap_proc_read(char *, char **, off_t, int); ...@@ -80,7 +80,7 @@ int irlap_proc_read(char *, char **, off_t, int);
int __init irlap_init(void) int __init irlap_init(void)
{ {
/* Allocate master array */ /* Allocate master array */
irlap = hashbin_new(HB_LOCAL); irlap = hashbin_new(HB_LOCK);
if (irlap == NULL) { if (irlap == NULL) {
ERROR("%s: can't allocate irlap hashbin!\n", __FUNCTION__); ERROR("%s: can't allocate irlap hashbin!\n", __FUNCTION__);
return -ENOMEM; return -ENOMEM;
...@@ -139,7 +139,15 @@ struct irlap_cb *irlap_open(struct net_device *dev, struct qos_info *qos, ...@@ -139,7 +139,15 @@ struct irlap_cb *irlap_open(struct net_device *dev, struct qos_info *qos,
skb_queue_head_init(&self->wx_list); skb_queue_head_init(&self->wx_list);
/* My unique IrLAP device address! */ /* My unique IrLAP device address! */
get_random_bytes(&self->saddr, sizeof(self->saddr)); /* We don't want the broadcast address, neither the NULL address
* (most often used to signify "invalid"), and we don't want an
* address already in use (otherwise connect won't be able
* to select the proper link). - Jean II */
do {
get_random_bytes(&self->saddr, sizeof(self->saddr));
} while ((self->saddr == 0x0) || (self->saddr == BROADCAST) ||
(hashbin_lock_find(irlap, self->saddr, NULL)) );
/* Copy to the driver */
memcpy(dev->dev_addr, &self->saddr, 4); memcpy(dev->dev_addr, &self->saddr, 4);
init_timer(&self->slot_timer); init_timer(&self->slot_timer);
...@@ -522,7 +530,8 @@ void irlap_discovery_request(struct irlap_cb *self, discovery_t *discovery) ...@@ -522,7 +530,8 @@ void irlap_discovery_request(struct irlap_cb *self, discovery_t *discovery)
self->discovery_log = NULL; self->discovery_log = NULL;
} }
self->discovery_log= hashbin_new(HB_LOCAL); /* All operations will occur at predictable time, no need to lock */
self->discovery_log= hashbin_new(HB_NOLOCK);
info.S = discovery->nslots; /* Number of slots */ info.S = discovery->nslots; /* Number of slots */
info.s = 0; /* Current slot */ info.s = 0; /* Current slot */
...@@ -1084,15 +1093,14 @@ int irlap_proc_read(char *buf, char **start, off_t offset, int len) ...@@ -1084,15 +1093,14 @@ int irlap_proc_read(char *buf, char **start, off_t offset, int len)
unsigned long flags; unsigned long flags;
int i = 0; int i = 0;
save_flags(flags); spin_lock_irqsave(&irlap->hb_spinlock, flags);
cli();
len = 0; len = 0;
self = (struct irlap_cb *) hashbin_get_first(irlap); self = (struct irlap_cb *) hashbin_get_first(irlap);
while (self != NULL) { while (self != NULL) {
ASSERT(self != NULL, return -ENODEV;); ASSERT(self != NULL, break;);
ASSERT(self->magic == LAP_MAGIC, return -EBADR;); ASSERT(self->magic == LAP_MAGIC, break;);
len += sprintf(buf+len, "irlap%d ", i++); len += sprintf(buf+len, "irlap%d ", i++);
len += sprintf(buf+len, "state: %s\n", len += sprintf(buf+len, "state: %s\n",
...@@ -1164,7 +1172,7 @@ int irlap_proc_read(char *buf, char **start, off_t offset, int len) ...@@ -1164,7 +1172,7 @@ int irlap_proc_read(char *buf, char **start, off_t offset, int len)
self = (struct irlap_cb *) hashbin_get_next(irlap); self = (struct irlap_cb *) hashbin_get_next(irlap);
} }
restore_flags(flags); spin_unlock_irqrestore(&irlap->hb_spinlock, flags);
return len; return len;
} }
......
...@@ -83,13 +83,13 @@ int __init irlmp_init(void) ...@@ -83,13 +83,13 @@ int __init irlmp_init(void)
memset(irlmp, 0, sizeof(struct irlmp_cb)); memset(irlmp, 0, sizeof(struct irlmp_cb));
irlmp->magic = LMP_MAGIC; irlmp->magic = LMP_MAGIC;
spin_lock_init(&irlmp->log_lock);
irlmp->clients = hashbin_new(HB_GLOBAL); irlmp->clients = hashbin_new(HB_LOCK);
irlmp->services = hashbin_new(HB_GLOBAL); irlmp->services = hashbin_new(HB_LOCK);
irlmp->links = hashbin_new(HB_GLOBAL); irlmp->links = hashbin_new(HB_LOCK);
irlmp->unconnected_lsaps = hashbin_new(HB_GLOBAL); irlmp->unconnected_lsaps = hashbin_new(HB_LOCK);
irlmp->cachelog = hashbin_new(HB_GLOBAL); irlmp->cachelog = hashbin_new(HB_NOLOCK);
spin_lock_init(&irlmp->cachelog->hb_spinlock);
irlmp->free_lsap_sel = 0x10; /* Reserved 0x00-0x0f */ irlmp->free_lsap_sel = 0x10; /* Reserved 0x00-0x0f */
strcpy(sysctl_devname, "Linux"); strcpy(sysctl_devname, "Linux");
...@@ -177,8 +177,8 @@ struct lsap_cb *irlmp_open_lsap(__u8 slsap_sel, notify_t *notify, __u8 pid) ...@@ -177,8 +177,8 @@ struct lsap_cb *irlmp_open_lsap(__u8 slsap_sel, notify_t *notify, __u8 pid)
self->lsap_state = LSAP_DISCONNECTED; self->lsap_state = LSAP_DISCONNECTED;
/* Insert into queue of unconnected LSAPs */ /* Insert into queue of unconnected LSAPs */
hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) self, (int) self, hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) self,
NULL); (long) self, NULL);
return self; return self;
} }
...@@ -238,7 +238,7 @@ void irlmp_close_lsap(struct lsap_cb *self) ...@@ -238,7 +238,7 @@ void irlmp_close_lsap(struct lsap_cb *self)
LM_LAP_DISCONNECT_REQUEST, NULL); LM_LAP_DISCONNECT_REQUEST, NULL);
} }
/* Now, remove from the link */ /* Now, remove from the link */
lsap = hashbin_remove(lap->lsaps, (int) self, NULL); lsap = hashbin_remove(lap->lsaps, (long) self, NULL);
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP #ifdef CONFIG_IRDA_CACHE_LAST_LSAP
lap->cache.valid = FALSE; lap->cache.valid = FALSE;
#endif #endif
...@@ -246,7 +246,7 @@ void irlmp_close_lsap(struct lsap_cb *self) ...@@ -246,7 +246,7 @@ void irlmp_close_lsap(struct lsap_cb *self)
self->lap = NULL; self->lap = NULL;
/* Check if we found the LSAP! If not then try the unconnected lsaps */ /* Check if we found the LSAP! If not then try the unconnected lsaps */
if (!lsap) { if (!lsap) {
lsap = hashbin_remove(irlmp->unconnected_lsaps, (int) self, lsap = hashbin_remove(irlmp->unconnected_lsaps, (long) self,
NULL); NULL);
} }
if (!lsap) { if (!lsap) {
...@@ -286,7 +286,7 @@ void irlmp_register_link(struct irlap_cb *irlap, __u32 saddr, notify_t *notify) ...@@ -286,7 +286,7 @@ void irlmp_register_link(struct irlap_cb *irlap, __u32 saddr, notify_t *notify)
lap->magic = LMP_LAP_MAGIC; lap->magic = LMP_LAP_MAGIC;
lap->saddr = saddr; lap->saddr = saddr;
lap->daddr = DEV_ADDR_ANY; lap->daddr = DEV_ADDR_ANY;
lap->lsaps = hashbin_new(HB_GLOBAL); lap->lsaps = hashbin_new(HB_LOCK);
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP #ifdef CONFIG_IRDA_CACHE_LAST_LSAP
lap->cache.valid = FALSE; lap->cache.valid = FALSE;
#endif #endif
...@@ -347,7 +347,6 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel, ...@@ -347,7 +347,6 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel,
struct sk_buff *skb = NULL; struct sk_buff *skb = NULL;
struct lap_cb *lap; struct lap_cb *lap;
struct lsap_cb *lsap; struct lsap_cb *lsap;
discovery_t *discovery;
ASSERT(self != NULL, return -EBADR;); ASSERT(self != NULL, return -EBADR;);
ASSERT(self->magic == LMP_LSAP_MAGIC, return -EBADR;); ASSERT(self->magic == LMP_LSAP_MAGIC, return -EBADR;);
...@@ -388,6 +387,10 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel, ...@@ -388,6 +387,10 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel,
* device with the given daddr * device with the given daddr
*/ */
if ((!saddr) || (saddr == DEV_ADDR_ANY)) { if ((!saddr) || (saddr == DEV_ADDR_ANY)) {
discovery_t *discovery;
unsigned long flags;
spin_lock_irqsave(&irlmp->cachelog->hb_spinlock, flags);
if (daddr != DEV_ADDR_ANY) if (daddr != DEV_ADDR_ANY)
discovery = hashbin_find(irlmp->cachelog, daddr, NULL); discovery = hashbin_find(irlmp->cachelog, daddr, NULL);
else { else {
...@@ -400,8 +403,9 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel, ...@@ -400,8 +403,9 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel,
saddr = discovery->saddr; saddr = discovery->saddr;
daddr = discovery->daddr; daddr = discovery->daddr;
} }
spin_unlock_irqrestore(&irlmp->cachelog->hb_spinlock, flags);
} }
lap = hashbin_find(irlmp->links, saddr, NULL); lap = hashbin_lock_find(irlmp->links, saddr, NULL);
if (lap == NULL) { if (lap == NULL) {
IRDA_DEBUG(1, __FUNCTION__ "(), Unable to find a usable link!\n"); IRDA_DEBUG(1, __FUNCTION__ "(), Unable to find a usable link!\n");
return -EHOSTUNREACH; return -EHOSTUNREACH;
...@@ -411,11 +415,8 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel, ...@@ -411,11 +415,8 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel,
if (lap->daddr == DEV_ADDR_ANY) if (lap->daddr == DEV_ADDR_ANY)
lap->daddr = daddr; lap->daddr = daddr;
else if (lap->daddr != daddr) { else if (lap->daddr != daddr) {
struct lsap_cb *any_lsap;
/* Check if some LSAPs are active on this LAP */ /* Check if some LSAPs are active on this LAP */
any_lsap = (struct lsap_cb *) hashbin_get_first(lap->lsaps); if (HASHBIN_GET_SIZE(lap->lsaps) == 0) {
if (any_lsap == NULL) {
/* No active connection, but LAP hasn't been /* No active connection, but LAP hasn't been
* disconnected yet (waiting for timeout in LAP). * disconnected yet (waiting for timeout in LAP).
* Maybe we could give LAP a bit of help in this case. * Maybe we could give LAP a bit of help in this case.
...@@ -436,14 +437,15 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel, ...@@ -436,14 +437,15 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel,
* Remove LSAP from list of unconnected LSAPs and insert it into the * Remove LSAP from list of unconnected LSAPs and insert it into the
* list of connected LSAPs for the particular link * list of connected LSAPs for the particular link
*/ */
lsap = hashbin_remove(irlmp->unconnected_lsaps, (int) self, NULL); lsap = hashbin_remove(irlmp->unconnected_lsaps, (long) self, NULL);
ASSERT(lsap != NULL, return -1;); ASSERT(lsap != NULL, return -1;);
ASSERT(lsap->magic == LMP_LSAP_MAGIC, return -1;); ASSERT(lsap->magic == LMP_LSAP_MAGIC, return -1;);
ASSERT(lsap->lap != NULL, return -1;); ASSERT(lsap->lap != NULL, return -1;);
ASSERT(lsap->lap->magic == LMP_LAP_MAGIC, return -1;); ASSERT(lsap->lap->magic == LMP_LAP_MAGIC, return -1;);
hashbin_insert(self->lap->lsaps, (irda_queue_t *) self, (int) self, NULL); hashbin_insert(self->lap->lsaps, (irda_queue_t *) self, (long) self,
NULL);
set_bit(0, &self->connected); /* TRUE */ set_bit(0, &self->connected); /* TRUE */
...@@ -574,29 +576,41 @@ void irlmp_connect_confirm(struct lsap_cb *self, struct sk_buff *skb) ...@@ -574,29 +576,41 @@ void irlmp_connect_confirm(struct lsap_cb *self, struct sk_buff *skb)
struct lsap_cb *irlmp_dup(struct lsap_cb *orig, void *instance) struct lsap_cb *irlmp_dup(struct lsap_cb *orig, void *instance)
{ {
struct lsap_cb *new; struct lsap_cb *new;
unsigned long flags;
IRDA_DEBUG(1, __FUNCTION__ "()\n"); IRDA_DEBUG(1, __FUNCTION__ "()\n");
spin_lock_irqsave(&irlmp->unconnected_lsaps->hb_spinlock, flags);
/* Only allowed to duplicate unconnected LSAP's */ /* Only allowed to duplicate unconnected LSAP's */
if (!hashbin_find(irlmp->unconnected_lsaps, (int) orig, NULL)) { if (!hashbin_find(irlmp->unconnected_lsaps, (long) orig, NULL)) {
IRDA_DEBUG(0, __FUNCTION__ "(), unable to find LSAP\n"); IRDA_DEBUG(0, __FUNCTION__ "(), unable to find LSAP\n");
spin_unlock_irqrestore(&irlmp->unconnected_lsaps->hb_spinlock,
flags);
return NULL; return NULL;
} }
/* Allocate a new instance */
new = kmalloc(sizeof(struct lsap_cb), GFP_ATOMIC); new = kmalloc(sizeof(struct lsap_cb), GFP_ATOMIC);
if (!new) { if (!new) {
IRDA_DEBUG(0, __FUNCTION__ "(), unable to kmalloc\n"); IRDA_DEBUG(0, __FUNCTION__ "(), unable to kmalloc\n");
spin_unlock_irqrestore(&irlmp->unconnected_lsaps->hb_spinlock,
flags);
return NULL; return NULL;
} }
/* Dup */ /* Dup */
memcpy(new, orig, sizeof(struct lsap_cb)); memcpy(new, orig, sizeof(struct lsap_cb));
new->notify.instance = instance;
/* new->lap = orig->lap; => done in the memcpy() */ /* new->lap = orig->lap; => done in the memcpy() */
/* new->slsap_sel = orig->slsap_sel; => done in the memcpy() */ /* new->slsap_sel = orig->slsap_sel; => done in the memcpy() */
spin_unlock_irqrestore(&irlmp->unconnected_lsaps->hb_spinlock, flags);
/* Not everything is the same */
new->notify.instance = instance;
init_timer(&new->watchdog_timer); init_timer(&new->watchdog_timer);
hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) new, (int) new, hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) new,
NULL); (long) new, NULL);
/* Make sure that we invalidate the cache */ /* Make sure that we invalidate the cache */
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP #ifdef CONFIG_IRDA_CACHE_LAST_LSAP
...@@ -646,7 +660,7 @@ int irlmp_disconnect_request(struct lsap_cb *self, struct sk_buff *userdata) ...@@ -646,7 +660,7 @@ int irlmp_disconnect_request(struct lsap_cb *self, struct sk_buff *userdata)
ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;); ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
ASSERT(self->lap->lsaps != NULL, return -1;); ASSERT(self->lap->lsaps != NULL, return -1;);
lsap = hashbin_remove(self->lap->lsaps, (int) self, NULL); lsap = hashbin_remove(self->lap->lsaps, (long) self, NULL);
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP #ifdef CONFIG_IRDA_CACHE_LAST_LSAP
self->lap->cache.valid = FALSE; self->lap->cache.valid = FALSE;
#endif #endif
...@@ -655,8 +669,8 @@ int irlmp_disconnect_request(struct lsap_cb *self, struct sk_buff *userdata) ...@@ -655,8 +669,8 @@ int irlmp_disconnect_request(struct lsap_cb *self, struct sk_buff *userdata)
ASSERT(lsap->magic == LMP_LSAP_MAGIC, return -1;); ASSERT(lsap->magic == LMP_LSAP_MAGIC, return -1;);
ASSERT(lsap == self, return -1;); ASSERT(lsap == self, return -1;);
hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) self, (int) self, hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) self,
NULL); (long) self, NULL);
/* Reset some values */ /* Reset some values */
self->dlsap_sel = LSAP_ANY; self->dlsap_sel = LSAP_ANY;
...@@ -699,15 +713,15 @@ void irlmp_disconnect_indication(struct lsap_cb *self, LM_REASON reason, ...@@ -699,15 +713,15 @@ void irlmp_disconnect_indication(struct lsap_cb *self, LM_REASON reason,
ASSERT(self->lap != NULL, return;); ASSERT(self->lap != NULL, return;);
ASSERT(self->lap->lsaps != NULL, return;); ASSERT(self->lap->lsaps != NULL, return;);
lsap = hashbin_remove(self->lap->lsaps, (int) self, NULL); lsap = hashbin_remove(self->lap->lsaps, (long) self, NULL);
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP #ifdef CONFIG_IRDA_CACHE_LAST_LSAP
self->lap->cache.valid = FALSE; self->lap->cache.valid = FALSE;
#endif #endif
ASSERT(lsap != NULL, return;); ASSERT(lsap != NULL, return;);
ASSERT(lsap == self, return;); ASSERT(lsap == self, return;);
hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) lsap, (int) lsap, hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) lsap,
NULL); (long) lsap, NULL);
self->dlsap_sel = LSAP_ANY; self->dlsap_sel = LSAP_ANY;
self->lap = NULL; self->lap = NULL;
...@@ -886,7 +900,7 @@ void irlmp_check_services(discovery_t *discovery) ...@@ -886,7 +900,7 @@ void irlmp_check_services(discovery_t *discovery)
*/ */
while ((service = service_log[i++]) != S_END) { while ((service = service_log[i++]) != S_END) {
IRDA_DEBUG( 4, "service=%02x\n", service); IRDA_DEBUG( 4, "service=%02x\n", service);
client = hashbin_find(irlmp->registry, service, NULL); client = hashbin_lock_find(irlmp->registry, service, NULL);
if (entry && entry->discovery_callback) { if (entry && entry->discovery_callback) {
IRDA_DEBUG( 4, "discovery_callback!\n"); IRDA_DEBUG( 4, "discovery_callback!\n");
...@@ -903,6 +917,7 @@ void irlmp_check_services(discovery_t *discovery) ...@@ -903,6 +917,7 @@ void irlmp_check_services(discovery_t *discovery)
kfree(service_log); kfree(service_log);
} }
#endif #endif
/* /*
* Function irlmp_notify_client (log) * Function irlmp_notify_client (log)
* *
...@@ -930,6 +945,12 @@ irlmp_notify_client(irlmp_client_t *client, ...@@ -930,6 +945,12 @@ irlmp_notify_client(irlmp_client_t *client,
/* /*
* Now, check all discovered devices (if any), and notify client * Now, check all discovered devices (if any), and notify client
* only about the services that the client is interested in * only about the services that the client is interested in
* Note : most often, we will get called immediately following
* a discovery, so the log is not going to expire.
* On the other hand, comming here through irlmp_discovery_request()
* is *very* problematic - Jean II
* Can't use hashbin_find_next(), key is not unique. I'm running
* out of options :-( - Jean II
*/ */
discovery = (discovery_t *) hashbin_get_first(log); discovery = (discovery_t *) hashbin_get_first(log);
while (discovery != NULL) { while (discovery != NULL) {
...@@ -956,6 +977,7 @@ irlmp_notify_client(irlmp_client_t *client, ...@@ -956,6 +977,7 @@ irlmp_notify_client(irlmp_client_t *client,
void irlmp_discovery_confirm(hashbin_t *log, DISCOVERY_MODE mode) void irlmp_discovery_confirm(hashbin_t *log, DISCOVERY_MODE mode)
{ {
irlmp_client_t *client; irlmp_client_t *client;
irlmp_client_t *client_next;
IRDA_DEBUG(3, __FUNCTION__ "()\n"); IRDA_DEBUG(3, __FUNCTION__ "()\n");
...@@ -965,11 +987,12 @@ void irlmp_discovery_confirm(hashbin_t *log, DISCOVERY_MODE mode) ...@@ -965,11 +987,12 @@ void irlmp_discovery_confirm(hashbin_t *log, DISCOVERY_MODE mode)
return; return;
client = (irlmp_client_t *) hashbin_get_first(irlmp->clients); client = (irlmp_client_t *) hashbin_get_first(irlmp->clients);
while (client != NULL) { while (NULL != hashbin_find_next(irlmp->clients, (long) client, NULL,
(void *) &client_next) ) {
/* Check if we should notify client */ /* Check if we should notify client */
irlmp_notify_client(client, log, mode); irlmp_notify_client(client, log, mode);
client = (irlmp_client_t *) hashbin_get_next(irlmp->clients); client = client_next;
} }
} }
...@@ -987,13 +1010,15 @@ void irlmp_discovery_confirm(hashbin_t *log, DISCOVERY_MODE mode) ...@@ -987,13 +1010,15 @@ void irlmp_discovery_confirm(hashbin_t *log, DISCOVERY_MODE mode)
void irlmp_discovery_expiry(discovery_t *expiry) void irlmp_discovery_expiry(discovery_t *expiry)
{ {
irlmp_client_t *client; irlmp_client_t *client;
irlmp_client_t *client_next;
IRDA_DEBUG(3, __FUNCTION__ "()\n"); IRDA_DEBUG(3, __FUNCTION__ "()\n");
ASSERT(expiry != NULL, return;); ASSERT(expiry != NULL, return;);
client = (irlmp_client_t *) hashbin_get_first(irlmp->clients); client = (irlmp_client_t *) hashbin_get_first(irlmp->clients);
while (client != NULL) { while (NULL != hashbin_find_next(irlmp->clients, (long) client, NULL,
(void *) &client_next) ) {
/* Check if we should notify client */ /* Check if we should notify client */
if ((client->expir_callback) && if ((client->expir_callback) &&
(client->hint_mask & expiry->hints.word & 0x7f7f)) (client->hint_mask & expiry->hints.word & 0x7f7f))
...@@ -1001,7 +1026,7 @@ void irlmp_discovery_expiry(discovery_t *expiry) ...@@ -1001,7 +1026,7 @@ void irlmp_discovery_expiry(discovery_t *expiry)
client->priv); client->priv);
/* Next client */ /* Next client */
client = (irlmp_client_t *) hashbin_get_next(irlmp->clients); client = client_next;
} }
} }
...@@ -1196,11 +1221,9 @@ void irlmp_status_indication(struct lap_cb *self, ...@@ -1196,11 +1221,9 @@ void irlmp_status_indication(struct lap_cb *self,
struct lsap_cb *curr; struct lsap_cb *curr;
/* Send status_indication to all LSAPs using this link */ /* Send status_indication to all LSAPs using this link */
next = (struct lsap_cb *) hashbin_get_first( self->lsaps); curr = (struct lsap_cb *) hashbin_get_first( self->lsaps);
while (next != NULL ) { while (NULL != hashbin_find_next(self->lsaps, (long) curr, NULL,
curr = next; (void *) &next) ) {
next = (struct lsap_cb *) hashbin_get_next(self->lsaps);
ASSERT(curr->magic == LMP_LSAP_MAGIC, return;); ASSERT(curr->magic == LMP_LSAP_MAGIC, return;);
/* /*
* Inform service user if he has requested it * Inform service user if he has requested it
...@@ -1210,6 +1233,8 @@ void irlmp_status_indication(struct lap_cb *self, ...@@ -1210,6 +1233,8 @@ void irlmp_status_indication(struct lap_cb *self,
link, lock); link, lock);
else else
IRDA_DEBUG(2, __FUNCTION__ "(), no handler\n"); IRDA_DEBUG(2, __FUNCTION__ "(), no handler\n");
curr = next;
} }
} }
...@@ -1245,29 +1270,15 @@ void irlmp_flow_indication(struct lap_cb *self, LOCAL_FLOW flow) ...@@ -1245,29 +1270,15 @@ void irlmp_flow_indication(struct lap_cb *self, LOCAL_FLOW flow)
(IRLAP_GET_TX_QUEUE_LEN(self->irlap) < LAP_HIGH_THRESHOLD)) { (IRLAP_GET_TX_QUEUE_LEN(self->irlap) < LAP_HIGH_THRESHOLD)) {
/* Try to find the next lsap we should poll. */ /* Try to find the next lsap we should poll. */
next = self->flow_next; next = self->flow_next;
if(next != NULL) {
/* Note that if there is only one LSAP on the LAP
* (most common case), self->flow_next is always NULL,
* so we always avoid this loop. - Jean II */
IRDA_DEBUG(4, __FUNCTION__ "() : searching my LSAP\n");
/* We look again in hashbins, because the lsap
* might have gone away... - Jean II */
curr = (struct lsap_cb *) hashbin_get_first(self->lsaps);
while((curr != NULL ) && (curr != next))
curr = (struct lsap_cb *) hashbin_get_next(self->lsaps);
} else
curr = NULL;
/* If we have no lsap, restart from first one */ /* If we have no lsap, restart from first one */
if(curr == NULL) if(next == NULL)
curr = (struct lsap_cb *) hashbin_get_first(self->lsaps); next = (struct lsap_cb *) hashbin_get_first(self->lsaps);
/* Verify current one and find the next one */
curr = hashbin_find_next(self->lsaps, (long) next, NULL,
(void *) &self->flow_next);
/* Uh-oh... Paranoia */ /* Uh-oh... Paranoia */
if(curr == NULL) if(curr == NULL)
break; break;
/* Next time, we will get the next one (or the first one) */
self->flow_next = (struct lsap_cb *) hashbin_get_next(self->lsaps);
IRDA_DEBUG(4, __FUNCTION__ "() : curr is %p, next was %p and is now %p, still %d to go - queue len = %d\n", curr, next, self->flow_next, lsap_todo, IRLAP_GET_TX_QUEUE_LEN(self->irlap)); IRDA_DEBUG(4, __FUNCTION__ "() : curr is %p, next was %p and is now %p, still %d to go - queue len = %d\n", curr, next, self->flow_next, lsap_todo, IRLAP_GET_TX_QUEUE_LEN(self->irlap));
/* Inform lsap user that it can send one more packet. */ /* Inform lsap user that it can send one more packet. */
...@@ -1414,20 +1425,12 @@ __u16 irlmp_service_to_hint(int service) ...@@ -1414,20 +1425,12 @@ __u16 irlmp_service_to_hint(int service)
* Register local service with IrLMP * Register local service with IrLMP
* *
*/ */
__u32 irlmp_register_service(__u16 hints) void *irlmp_register_service(__u16 hints)
{ {
irlmp_service_t *service; irlmp_service_t *service;
__u32 handle;
IRDA_DEBUG(4, __FUNCTION__ "(), hints = %04x\n", hints); IRDA_DEBUG(4, __FUNCTION__ "(), hints = %04x\n", hints);
/* Get a unique handle for this service */
get_random_bytes(&handle, sizeof(handle));
while (hashbin_find(irlmp->services, handle, NULL) || !handle)
get_random_bytes(&handle, sizeof(handle));
irlmp->hints.word |= hints;
/* Make a new registration */ /* Make a new registration */
service = kmalloc(sizeof(irlmp_service_t), GFP_ATOMIC); service = kmalloc(sizeof(irlmp_service_t), GFP_ATOMIC);
if (!service) { if (!service) {
...@@ -1435,9 +1438,12 @@ __u32 irlmp_register_service(__u16 hints) ...@@ -1435,9 +1438,12 @@ __u32 irlmp_register_service(__u16 hints)
return 0; return 0;
} }
service->hints = hints; service->hints = hints;
hashbin_insert(irlmp->services, (irda_queue_t *) service, handle, NULL); hashbin_insert(irlmp->services, (irda_queue_t *) service,
(long) service, NULL);
irlmp->hints.word |= hints;
return handle; return (void *)service;
} }
/* /*
...@@ -1447,35 +1453,38 @@ __u32 irlmp_register_service(__u16 hints) ...@@ -1447,35 +1453,38 @@ __u32 irlmp_register_service(__u16 hints)
* *
* Returns: 0 on success, -1 on error * Returns: 0 on success, -1 on error
*/ */
int irlmp_unregister_service(__u32 handle) int irlmp_unregister_service(void *handle)
{ {
irlmp_service_t *service; irlmp_service_t *service;
unsigned long flags;
IRDA_DEBUG(4, __FUNCTION__ "()\n"); IRDA_DEBUG(4, __FUNCTION__ "()\n");
if (!handle) if (!handle)
return -1; return -1;
service = hashbin_find(irlmp->services, handle, NULL); /* Caller may call with invalid handle (it's legal) - Jean II */
service = hashbin_lock_find(irlmp->services, (long) handle, NULL);
if (!service) { if (!service) {
IRDA_DEBUG(1, __FUNCTION__ "(), Unknown service!\n"); IRDA_DEBUG(1, __FUNCTION__ "(), Unknown service!\n");
return -1; return -1;
} }
service = hashbin_remove(irlmp->services, handle, NULL); hashbin_remove_this(irlmp->services, (irda_queue_t *) service);
if (service) kfree(service);
kfree(service);
/* Remove old hint bits */ /* Remove old hint bits */
irlmp->hints.word = 0; irlmp->hints.word = 0;
/* Refresh current hint bits */ /* Refresh current hint bits */
spin_lock_irqsave(&irlmp->services->hb_spinlock, flags);
service = (irlmp_service_t *) hashbin_get_first(irlmp->services); service = (irlmp_service_t *) hashbin_get_first(irlmp->services);
while (service) { while (service) {
irlmp->hints.word |= service->hints; irlmp->hints.word |= service->hints;
service = (irlmp_service_t *)hashbin_get_next(irlmp->services); service = (irlmp_service_t *)hashbin_get_next(irlmp->services);
} }
spin_unlock_irqrestore(&irlmp->services->hb_spinlock, flags);
return 0; return 0;
} }
...@@ -1488,20 +1497,14 @@ int irlmp_unregister_service(__u32 handle) ...@@ -1488,20 +1497,14 @@ int irlmp_unregister_service(__u32 handle)
* *
* Returns: handle > 0 on success, 0 on error * Returns: handle > 0 on success, 0 on error
*/ */
__u32 irlmp_register_client(__u16 hint_mask, DISCOVERY_CALLBACK1 disco_clb, void *irlmp_register_client(__u16 hint_mask, DISCOVERY_CALLBACK1 disco_clb,
DISCOVERY_CALLBACK1 expir_clb, void *priv) DISCOVERY_CALLBACK1 expir_clb, void *priv)
{ {
irlmp_client_t *client; irlmp_client_t *client;
__u32 handle;
IRDA_DEBUG(1, __FUNCTION__ "()\n"); IRDA_DEBUG(1, __FUNCTION__ "()\n");
ASSERT(irlmp != NULL, return 0;); ASSERT(irlmp != NULL, return 0;);
/* Get a unique handle for this client */
get_random_bytes(&handle, sizeof(handle));
while (hashbin_find(irlmp->clients, handle, NULL) || !handle)
get_random_bytes(&handle, sizeof(handle));
/* Make a new registration */ /* Make a new registration */
client = kmalloc(sizeof(irlmp_client_t), GFP_ATOMIC); client = kmalloc(sizeof(irlmp_client_t), GFP_ATOMIC);
if (!client) { if (!client) {
...@@ -1515,9 +1518,10 @@ __u32 irlmp_register_client(__u16 hint_mask, DISCOVERY_CALLBACK1 disco_clb, ...@@ -1515,9 +1518,10 @@ __u32 irlmp_register_client(__u16 hint_mask, DISCOVERY_CALLBACK1 disco_clb,
client->expir_callback = expir_clb; client->expir_callback = expir_clb;
client->priv = priv; client->priv = priv;
hashbin_insert(irlmp->clients, (irda_queue_t *) client, handle, NULL); hashbin_insert(irlmp->clients, (irda_queue_t *) client,
(long) client, NULL);
return handle; return (void *) client;
} }
/* /*
...@@ -1528,7 +1532,7 @@ __u32 irlmp_register_client(__u16 hint_mask, DISCOVERY_CALLBACK1 disco_clb, ...@@ -1528,7 +1532,7 @@ __u32 irlmp_register_client(__u16 hint_mask, DISCOVERY_CALLBACK1 disco_clb,
* *
* Returns: 0 on success, -1 on error * Returns: 0 on success, -1 on error
*/ */
int irlmp_update_client(__u32 handle, __u16 hint_mask, int irlmp_update_client(void *handle, __u16 hint_mask,
DISCOVERY_CALLBACK1 disco_clb, DISCOVERY_CALLBACK1 disco_clb,
DISCOVERY_CALLBACK1 expir_clb, void *priv) DISCOVERY_CALLBACK1 expir_clb, void *priv)
{ {
...@@ -1537,7 +1541,7 @@ int irlmp_update_client(__u32 handle, __u16 hint_mask, ...@@ -1537,7 +1541,7 @@ int irlmp_update_client(__u32 handle, __u16 hint_mask,
if (!handle) if (!handle)
return -1; return -1;
client = hashbin_find(irlmp->clients, handle, NULL); client = hashbin_lock_find(irlmp->clients, (long) handle, NULL);
if (!client) { if (!client) {
IRDA_DEBUG(1, __FUNCTION__ "(), Unknown client!\n"); IRDA_DEBUG(1, __FUNCTION__ "(), Unknown client!\n");
return -1; return -1;
...@@ -1557,7 +1561,7 @@ int irlmp_update_client(__u32 handle, __u16 hint_mask, ...@@ -1557,7 +1561,7 @@ int irlmp_update_client(__u32 handle, __u16 hint_mask,
* Returns: 0 on success, -1 on error * Returns: 0 on success, -1 on error
* *
*/ */
int irlmp_unregister_client(__u32 handle) int irlmp_unregister_client(void *handle)
{ {
struct irlmp_client *client; struct irlmp_client *client;
...@@ -1566,16 +1570,16 @@ int irlmp_unregister_client(__u32 handle) ...@@ -1566,16 +1570,16 @@ int irlmp_unregister_client(__u32 handle)
if (!handle) if (!handle)
return -1; return -1;
client = hashbin_find(irlmp->clients, handle, NULL); /* Caller may call with invalid handle (it's legal) - Jean II */
client = hashbin_lock_find(irlmp->clients, (long) handle, NULL);
if (!client) { if (!client) {
IRDA_DEBUG(1, __FUNCTION__ "(), Unknown client!\n"); IRDA_DEBUG(1, __FUNCTION__ "(), Unknown client!\n");
return -1; return -1;
} }
IRDA_DEBUG( 4, __FUNCTION__ "(), removing client!\n"); IRDA_DEBUG( 4, __FUNCTION__ "(), removing client!\n");
client = hashbin_remove( irlmp->clients, handle, NULL); hashbin_remove_this(irlmp->clients, (irda_queue_t *) client);
if (client) kfree(client);
kfree(client);
return 0; return 0;
} }
...@@ -1589,6 +1593,7 @@ int irlmp_slsap_inuse(__u8 slsap_sel) ...@@ -1589,6 +1593,7 @@ int irlmp_slsap_inuse(__u8 slsap_sel)
{ {
struct lsap_cb *self; struct lsap_cb *self;
struct lap_cb *lap; struct lap_cb *lap;
unsigned long flags;
ASSERT(irlmp != NULL, return TRUE;); ASSERT(irlmp != NULL, return TRUE;);
ASSERT(irlmp->magic == LMP_MAGIC, return TRUE;); ASSERT(irlmp->magic == LMP_MAGIC, return TRUE;);
...@@ -1611,10 +1616,16 @@ int irlmp_slsap_inuse(__u8 slsap_sel) ...@@ -1611,10 +1616,16 @@ int irlmp_slsap_inuse(__u8 slsap_sel)
* every IrLAP connection and check every LSAP assosiated with each * every IrLAP connection and check every LSAP assosiated with each
* the connection. * the connection.
*/ */
spin_lock_irqsave(&irlmp->links->hb_spinlock, flags);
lap = (struct lap_cb *) hashbin_get_first(irlmp->links); lap = (struct lap_cb *) hashbin_get_first(irlmp->links);
while (lap != NULL) { while (lap != NULL) {
ASSERT(lap->magic == LMP_LAP_MAGIC, return TRUE;); ASSERT(lap->magic == LMP_LAP_MAGIC, return TRUE;);
/* Careful for priority inversions here !
* All other uses of attrib spinlock are independant of
* the object spinlock, so we are safe. Jean II */
spin_lock(&lap->lsaps->hb_spinlock);
self = (struct lsap_cb *) hashbin_get_first(lap->lsaps); self = (struct lsap_cb *) hashbin_get_first(lap->lsaps);
while (self != NULL) { while (self != NULL) {
ASSERT(self->magic == LMP_LSAP_MAGIC, return TRUE;); ASSERT(self->magic == LMP_LSAP_MAGIC, return TRUE;);
...@@ -1626,8 +1637,11 @@ int irlmp_slsap_inuse(__u8 slsap_sel) ...@@ -1626,8 +1637,11 @@ int irlmp_slsap_inuse(__u8 slsap_sel)
} }
self = (struct lsap_cb*) hashbin_get_next(lap->lsaps); self = (struct lsap_cb*) hashbin_get_next(lap->lsaps);
} }
spin_unlock(&lap->lsaps->hb_spinlock);
/* Next LAP */
lap = (struct lap_cb *) hashbin_get_next(irlmp->links); lap = (struct lap_cb *) hashbin_get_next(irlmp->links);
} }
spin_unlock_irqrestore(&irlmp->links->hb_spinlock, flags);
return FALSE; return FALSE;
} }
...@@ -1736,15 +1750,13 @@ int irlmp_proc_read(char *buf, char **start, off_t offset, int len) ...@@ -1736,15 +1750,13 @@ int irlmp_proc_read(char *buf, char **start, off_t offset, int len)
ASSERT(irlmp != NULL, return 0;); ASSERT(irlmp != NULL, return 0;);
save_flags( flags);
cli();
len = 0; len = 0;
len += sprintf( buf+len, "Unconnected LSAPs:\n"); len += sprintf( buf+len, "Unconnected LSAPs:\n");
spin_lock_irqsave(&irlmp->unconnected_lsaps->hb_spinlock, flags);
self = (struct lsap_cb *) hashbin_get_first( irlmp->unconnected_lsaps); self = (struct lsap_cb *) hashbin_get_first( irlmp->unconnected_lsaps);
while (self != NULL) { while (self != NULL) {
ASSERT(self->magic == LMP_LSAP_MAGIC, return 0;); ASSERT(self->magic == LMP_LSAP_MAGIC, break;);
len += sprintf(buf+len, "lsap state: %s, ", len += sprintf(buf+len, "lsap state: %s, ",
irlsap_state[ self->lsap_state]); irlsap_state[ self->lsap_state]);
len += sprintf(buf+len, len += sprintf(buf+len,
...@@ -1756,9 +1768,10 @@ int irlmp_proc_read(char *buf, char **start, off_t offset, int len) ...@@ -1756,9 +1768,10 @@ int irlmp_proc_read(char *buf, char **start, off_t offset, int len)
self = (struct lsap_cb *) hashbin_get_next( self = (struct lsap_cb *) hashbin_get_next(
irlmp->unconnected_lsaps); irlmp->unconnected_lsaps);
} }
spin_unlock_irqrestore(&irlmp->unconnected_lsaps->hb_spinlock, flags);
len += sprintf(buf+len, "\nRegistred Link Layers:\n"); len += sprintf(buf+len, "\nRegistred Link Layers:\n");
spin_lock_irqsave(&irlmp->links->hb_spinlock, flags);
lap = (struct lap_cb *) hashbin_get_first(irlmp->links); lap = (struct lap_cb *) hashbin_get_first(irlmp->links);
while (lap != NULL) { while (lap != NULL) {
len += sprintf(buf+len, "lap state: %s, ", len += sprintf(buf+len, "lap state: %s, ",
...@@ -1770,10 +1783,15 @@ int irlmp_proc_read(char *buf, char **start, off_t offset, int len) ...@@ -1770,10 +1783,15 @@ int irlmp_proc_read(char *buf, char **start, off_t offset, int len)
HASHBIN_GET_SIZE(lap->lsaps)); HASHBIN_GET_SIZE(lap->lsaps));
len += sprintf(buf+len, "\n"); len += sprintf(buf+len, "\n");
/* Careful for priority inversions here !
* All other uses of attrib spinlock are independant of
* the object spinlock, so we are safe. Jean II */
spin_lock(&lap->lsaps->hb_spinlock);
len += sprintf(buf+len, "\n Connected LSAPs:\n"); len += sprintf(buf+len, "\n Connected LSAPs:\n");
self = (struct lsap_cb *) hashbin_get_first(lap->lsaps); self = (struct lsap_cb *) hashbin_get_first(lap->lsaps);
while (self != NULL) { while (self != NULL) {
ASSERT(self->magic == LMP_LSAP_MAGIC, return 0;); ASSERT(self->magic == LMP_LSAP_MAGIC, break;);
len += sprintf(buf+len, " lsap state: %s, ", len += sprintf(buf+len, " lsap state: %s, ",
irlsap_state[ self->lsap_state]); irlsap_state[ self->lsap_state]);
len += sprintf(buf+len, len += sprintf(buf+len,
...@@ -1785,11 +1803,12 @@ int irlmp_proc_read(char *buf, char **start, off_t offset, int len) ...@@ -1785,11 +1803,12 @@ int irlmp_proc_read(char *buf, char **start, off_t offset, int len)
self = (struct lsap_cb *) hashbin_get_next( self = (struct lsap_cb *) hashbin_get_next(
lap->lsaps); lap->lsaps);
} }
spin_unlock(&lap->lsaps->hb_spinlock);
len += sprintf(buf+len, "\n"); len += sprintf(buf+len, "\n");
lap = (struct lap_cb *) hashbin_get_next(irlmp->links); lap = (struct lap_cb *) hashbin_get_next(irlmp->links);
} }
restore_flags(flags); spin_unlock_irqrestore(&irlmp->links->hb_spinlock, flags);
return len; return len;
} }
......
...@@ -207,6 +207,43 @@ void irlmp_idle_timer_expired(void *data) ...@@ -207,6 +207,43 @@ void irlmp_idle_timer_expired(void *data)
irlmp_do_lap_event(self, LM_LAP_IDLE_TIMEOUT, NULL); irlmp_do_lap_event(self, LM_LAP_IDLE_TIMEOUT, NULL);
} }
/*
* Send an event on all LSAPs attached to this LAP.
*/
static inline void
irlmp_do_all_lsap_event(hashbin_t * lsap_hashbin,
IRLMP_EVENT event)
{
struct lsap_cb *lsap;
struct lsap_cb *lsap_next;
/* Note : this function use the new hashbin_find_next()
* function, instead of the old hashbin_get_next().
* This make sure that we are always pointing one lsap
* ahead, so that if the current lsap is removed as the
* result of sending the event, we don't care.
* Also, as we store the context ourselves, if an enumeration
* of the same lsap hashbin happens as the result of sending the
* event, we don't care.
* The only problem is if the next lsap is removed. In that case,
* hashbin_find_next() will return NULL and we will abort the
* enumeration. - Jean II */
/* Also : we don't accept any skb in input. We can *NOT* pass
* the same skb to multiple clients safely, we would need to
* skb_clone() it. - Jean II */
lsap = (struct lsap_cb *) hashbin_get_first(lsap_hashbin);
while (NULL != hashbin_find_next(lsap_hashbin,
(long) lsap,
NULL,
(void *) &lsap_next) ) {
irlmp_do_lsap_event(lsap, event, NULL);
lsap = lsap_next;
}
}
/********************************************************************* /*********************************************************************
* *
* LAP connection control states * LAP connection control states
...@@ -274,9 +311,6 @@ static void irlmp_state_standby(struct lap_cb *self, IRLMP_EVENT event, ...@@ -274,9 +311,6 @@ static void irlmp_state_standby(struct lap_cb *self, IRLMP_EVENT event,
static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event, static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct lsap_cb *lsap;
struct lsap_cb *lsap_current;
IRDA_DEBUG(2, __FUNCTION__ "(), event=%s\n", irlmp_event[event]); IRDA_DEBUG(2, __FUNCTION__ "(), event=%s\n", irlmp_event[event]);
switch (event) { switch (event) {
...@@ -290,11 +324,9 @@ static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event, ...@@ -290,11 +324,9 @@ static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event,
/* Just accept connection TODO, this should be fixed */ /* Just accept connection TODO, this should be fixed */
irlap_connect_response(self->irlap, skb); irlap_connect_response(self->irlap, skb);
lsap = (struct lsap_cb *) hashbin_get_first(self->lsaps); /* Tell LSAPs that they can start sending data */
while (lsap != NULL) { irlmp_do_all_lsap_event(self->lsaps, LM_LAP_CONNECT_CONFIRM);
irlmp_do_lsap_event(lsap, LM_LAP_CONNECT_CONFIRM, NULL);
lsap = (struct lsap_cb*) hashbin_get_next(self->lsaps);
}
/* Note : by the time we get there (LAP retries and co), /* Note : by the time we get there (LAP retries and co),
* the lsaps may already have gone. This avoid getting stuck * the lsaps may already have gone. This avoid getting stuck
* forever in LAP_ACTIVE state - Jean II */ * forever in LAP_ACTIVE state - Jean II */
...@@ -310,11 +342,9 @@ static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event, ...@@ -310,11 +342,9 @@ static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event,
/* For all lsap_ce E Associated do LS_Connect_confirm */ /* For all lsap_ce E Associated do LS_Connect_confirm */
irlmp_next_lap_state(self, LAP_ACTIVE); irlmp_next_lap_state(self, LAP_ACTIVE);
lsap = (struct lsap_cb *) hashbin_get_first(self->lsaps); /* Tell LSAPs that they can start sending data */
while (lsap != NULL) { irlmp_do_all_lsap_event(self->lsaps, LM_LAP_CONNECT_CONFIRM);
irlmp_do_lsap_event(lsap, LM_LAP_CONNECT_CONFIRM, NULL);
lsap = (struct lsap_cb*) hashbin_get_next(self->lsaps);
}
/* Note : by the time we get there (LAP retries and co), /* Note : by the time we get there (LAP retries and co),
* the lsaps may already have gone. This avoid getting stuck * the lsaps may already have gone. This avoid getting stuck
* forever in LAP_ACTIVE state - Jean II */ * forever in LAP_ACTIVE state - Jean II */
...@@ -328,18 +358,8 @@ static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event, ...@@ -328,18 +358,8 @@ static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event,
irlmp_next_lap_state(self, LAP_STANDBY); irlmp_next_lap_state(self, LAP_STANDBY);
/* Send disconnect event to all LSAPs using this link */ /* Send disconnect event to all LSAPs using this link */
lsap = (struct lsap_cb *) hashbin_get_first( self->lsaps); irlmp_do_all_lsap_event(self->lsaps,
while (lsap != NULL ) { LM_LAP_DISCONNECT_INDICATION);
ASSERT(lsap->magic == LMP_LSAP_MAGIC, return;);
lsap_current = lsap;
/* Be sure to stay one item ahead */
lsap = (struct lsap_cb *) hashbin_get_next(self->lsaps);
irlmp_do_lsap_event(lsap_current,
LM_LAP_DISCONNECT_INDICATION,
NULL);
}
break; break;
case LM_LAP_DISCONNECT_REQUEST: case LM_LAP_DISCONNECT_REQUEST:
IRDA_DEBUG(4, __FUNCTION__ "(), LM_LAP_DISCONNECT_REQUEST\n"); IRDA_DEBUG(4, __FUNCTION__ "(), LM_LAP_DISCONNECT_REQUEST\n");
...@@ -368,9 +388,6 @@ static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event, ...@@ -368,9 +388,6 @@ static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event,
static void irlmp_state_active(struct lap_cb *self, IRLMP_EVENT event, static void irlmp_state_active(struct lap_cb *self, IRLMP_EVENT event,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct lsap_cb *lsap;
struct lsap_cb *lsap_current;
IRDA_DEBUG(4, __FUNCTION__ "()\n"); IRDA_DEBUG(4, __FUNCTION__ "()\n");
switch (event) { switch (event) {
...@@ -383,22 +400,11 @@ static void irlmp_state_active(struct lap_cb *self, IRLMP_EVENT event, ...@@ -383,22 +400,11 @@ static void irlmp_state_active(struct lap_cb *self, IRLMP_EVENT event,
* notify all LSAPs using this LAP, but that should be safe to * notify all LSAPs using this LAP, but that should be safe to
* do anyway. * do anyway.
*/ */
lsap = (struct lsap_cb *) hashbin_get_first(self->lsaps); irlmp_do_all_lsap_event(self->lsaps, LM_LAP_CONNECT_CONFIRM);
while (lsap != NULL) {
irlmp_do_lsap_event(lsap, LM_LAP_CONNECT_CONFIRM, NULL);
lsap = (struct lsap_cb*) hashbin_get_next(self->lsaps);
}
/* Needed by connect indication */ /* Needed by connect indication */
lsap = (struct lsap_cb *) hashbin_get_first(irlmp->unconnected_lsaps); irlmp_do_all_lsap_event(irlmp->unconnected_lsaps,
while (lsap != NULL) { LM_LAP_CONNECT_CONFIRM);
lsap_current = lsap;
/* Be sure to stay one item ahead */
lsap = (struct lsap_cb*) hashbin_get_next(irlmp->unconnected_lsaps);
irlmp_do_lsap_event(lsap_current,
LM_LAP_CONNECT_CONFIRM, NULL);
}
/* Keep state */ /* Keep state */
break; break;
case LM_LAP_DISCONNECT_REQUEST: case LM_LAP_DISCONNECT_REQUEST:
...@@ -447,18 +453,8 @@ static void irlmp_state_active(struct lap_cb *self, IRLMP_EVENT event, ...@@ -447,18 +453,8 @@ static void irlmp_state_active(struct lap_cb *self, IRLMP_EVENT event,
/* /*
* Inform all connected LSAP's using this link * Inform all connected LSAP's using this link
*/ */
lsap = (struct lsap_cb *) hashbin_get_first(self->lsaps); irlmp_do_all_lsap_event(self->lsaps,
while (lsap != NULL ) { LM_LAP_DISCONNECT_INDICATION);
ASSERT(lsap->magic == LMP_LSAP_MAGIC, return;);
lsap_current = lsap;
/* Be sure to stay one item ahead */
lsap = (struct lsap_cb *) hashbin_get_next(self->lsaps);
irlmp_do_lsap_event(lsap_current,
LM_LAP_DISCONNECT_INDICATION,
NULL);
}
/* Force an expiry of the discovery log. /* Force an expiry of the discovery log.
* Now that the LAP is free, the system may attempt to * Now that the LAP is free, the system may attempt to
...@@ -581,15 +577,15 @@ static int irlmp_state_connect(struct lsap_cb *self, IRLMP_EVENT event, ...@@ -581,15 +577,15 @@ static int irlmp_state_connect(struct lsap_cb *self, IRLMP_EVENT event,
* Bind this LSAP to the IrLAP link where the connect was * Bind this LSAP to the IrLAP link where the connect was
* received * received
*/ */
lsap = hashbin_remove(irlmp->unconnected_lsaps, (int) self, lsap = hashbin_remove(irlmp->unconnected_lsaps, (long) self,
NULL); NULL);
ASSERT(lsap == self, return -1;); ASSERT(lsap == self, return -1;);
ASSERT(self->lap != NULL, return -1;); ASSERT(self->lap != NULL, return -1;);
ASSERT(self->lap->lsaps != NULL, return -1;); ASSERT(self->lap->lsaps != NULL, return -1;);
hashbin_insert(self->lap->lsaps, (irda_queue_t *) self, (int) self, hashbin_insert(self->lap->lsaps, (irda_queue_t *) self,
NULL); (long) self, NULL);
irlmp_send_lcf_pdu(self->lap, self->dlsap_sel, irlmp_send_lcf_pdu(self->lap, self->dlsap_sel,
self->slsap_sel, CONNECT_CNF, skb); self->slsap_sel, CONNECT_CNF, skb);
......
...@@ -210,6 +210,7 @@ void irlmp_link_unitdata_indication(struct lap_cb *self, struct sk_buff *skb) ...@@ -210,6 +210,7 @@ void irlmp_link_unitdata_indication(struct lap_cb *self, struct sk_buff *skb)
__u8 dlsap_sel; /* Destination LSAP address */ __u8 dlsap_sel; /* Destination LSAP address */
__u8 pid; /* Protocol identifier */ __u8 pid; /* Protocol identifier */
__u8 *fp; __u8 *fp;
unsigned long flags;
IRDA_DEBUG(4, __FUNCTION__ "()\n"); IRDA_DEBUG(4, __FUNCTION__ "()\n");
...@@ -242,6 +243,8 @@ void irlmp_link_unitdata_indication(struct lap_cb *self, struct sk_buff *skb) ...@@ -242,6 +243,8 @@ void irlmp_link_unitdata_indication(struct lap_cb *self, struct sk_buff *skb)
return; return;
} }
/* Search the connectionless LSAP */
spin_lock_irqsave(&irlmp->unconnected_lsaps->hb_spinlock, flags);
lsap = (struct lsap_cb *) hashbin_get_first(irlmp->unconnected_lsaps); lsap = (struct lsap_cb *) hashbin_get_first(irlmp->unconnected_lsaps);
while (lsap != NULL) { while (lsap != NULL) {
/* /*
...@@ -255,6 +258,8 @@ void irlmp_link_unitdata_indication(struct lap_cb *self, struct sk_buff *skb) ...@@ -255,6 +258,8 @@ void irlmp_link_unitdata_indication(struct lap_cb *self, struct sk_buff *skb)
} }
lsap = (struct lsap_cb *) hashbin_get_next(irlmp->unconnected_lsaps); lsap = (struct lsap_cb *) hashbin_get_next(irlmp->unconnected_lsaps);
} }
spin_unlock_irqrestore(&irlmp->unconnected_lsaps->hb_spinlock, flags);
if (lsap) if (lsap)
irlmp_connless_data_indication(lsap, skb); irlmp_connless_data_indication(lsap, skb);
else { else {
...@@ -374,6 +379,7 @@ void irlmp_link_discovery_indication(struct lap_cb *self, ...@@ -374,6 +379,7 @@ void irlmp_link_discovery_indication(struct lap_cb *self,
ASSERT(self != NULL, return;); ASSERT(self != NULL, return;);
ASSERT(self->magic == LMP_LAP_MAGIC, return;); ASSERT(self->magic == LMP_LAP_MAGIC, return;);
/* Add to main log, cleanup */
irlmp_add_discovery(irlmp->cachelog, discovery); irlmp_add_discovery(irlmp->cachelog, discovery);
/* Just handle it the same way as a discovery confirm, /* Just handle it the same way as a discovery confirm,
...@@ -396,6 +402,7 @@ void irlmp_link_discovery_confirm(struct lap_cb *self, hashbin_t *log) ...@@ -396,6 +402,7 @@ void irlmp_link_discovery_confirm(struct lap_cb *self, hashbin_t *log)
ASSERT(self != NULL, return;); ASSERT(self != NULL, return;);
ASSERT(self->magic == LMP_LAP_MAGIC, return;); ASSERT(self->magic == LMP_LAP_MAGIC, return;);
/* Add to main log, cleanup */
irlmp_add_discovery_log(irlmp->cachelog, log); irlmp_add_discovery_log(irlmp->cachelog, log);
/* Propagate event to various LSAPs registered for it. /* Propagate event to various LSAPs registered for it.
...@@ -411,6 +418,8 @@ void irlmp_link_discovery_confirm(struct lap_cb *self, hashbin_t *log) ...@@ -411,6 +418,8 @@ void irlmp_link_discovery_confirm(struct lap_cb *self, hashbin_t *log)
static inline void irlmp_update_cache(struct lap_cb *lap, static inline void irlmp_update_cache(struct lap_cb *lap,
struct lsap_cb *lsap) struct lsap_cb *lsap)
{ {
/* Prevent concurent read to get garbage */
lap->cache.valid = FALSE;
/* Update cache entry */ /* Update cache entry */
lap->cache.dlsap_sel = lsap->dlsap_sel; lap->cache.dlsap_sel = lsap->dlsap_sel;
lap->cache.slsap_sel = lsap->slsap_sel; lap->cache.slsap_sel = lsap->slsap_sel;
...@@ -441,6 +450,7 @@ static struct lsap_cb *irlmp_find_lsap(struct lap_cb *self, __u8 dlsap_sel, ...@@ -441,6 +450,7 @@ static struct lsap_cb *irlmp_find_lsap(struct lap_cb *self, __u8 dlsap_sel,
hashbin_t *queue) hashbin_t *queue)
{ {
struct lsap_cb *lsap; struct lsap_cb *lsap;
unsigned long flags;
/* /*
* Optimize for the common case. We assume that the last frame * Optimize for the common case. We assume that the last frame
...@@ -455,6 +465,9 @@ static struct lsap_cb *irlmp_find_lsap(struct lap_cb *self, __u8 dlsap_sel, ...@@ -455,6 +465,9 @@ static struct lsap_cb *irlmp_find_lsap(struct lap_cb *self, __u8 dlsap_sel,
return (self->cache.lsap); return (self->cache.lsap);
} }
#endif #endif
spin_lock_irqsave(&queue->hb_spinlock, flags);
lsap = (struct lsap_cb *) hashbin_get_first(queue); lsap = (struct lsap_cb *) hashbin_get_first(queue);
while (lsap != NULL) { while (lsap != NULL) {
/* /*
...@@ -465,29 +478,27 @@ static struct lsap_cb *irlmp_find_lsap(struct lap_cb *self, __u8 dlsap_sel, ...@@ -465,29 +478,27 @@ static struct lsap_cb *irlmp_find_lsap(struct lap_cb *self, __u8 dlsap_sel,
*/ */
if ((status == CONNECT_CMD) && if ((status == CONNECT_CMD) &&
(lsap->slsap_sel == slsap_sel) && (lsap->slsap_sel == slsap_sel) &&
(lsap->dlsap_sel == LSAP_ANY)) (lsap->dlsap_sel == LSAP_ANY)) {
{ /* This is where the dest lsap sel is set on incomming
* lsaps */
lsap->dlsap_sel = dlsap_sel; lsap->dlsap_sel = dlsap_sel;
break;
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
irlmp_update_cache(self, lsap);
#endif
return lsap;
} }
/* /*
* Check if source LSAP and dest LSAP selectors match. * Check if source LSAP and dest LSAP selectors match.
*/ */
if ((lsap->slsap_sel == slsap_sel) && if ((lsap->slsap_sel == slsap_sel) &&
(lsap->dlsap_sel == dlsap_sel)) (lsap->dlsap_sel == dlsap_sel))
{ break;
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
irlmp_update_cache(self, lsap);
#endif
return lsap;
}
lsap = (struct lsap_cb *) hashbin_get_next(queue); lsap = (struct lsap_cb *) hashbin_get_next(queue);
} }
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
if(lsap)
irlmp_update_cache(self, lsap);
#endif
spin_unlock_irqrestore(&queue->hb_spinlock, flags);
/* Sorry not found! */ /* Return what we've found or NULL */
return NULL; return lsap;
} }
...@@ -34,11 +34,412 @@ ...@@ -34,11 +34,412 @@
* *
********************************************************************/ ********************************************************************/
/*
* NOTE :
* There are various problems with this package :
* o the hash function for ints is pathetic (but could be changed)
* o locking is sometime suspicious (especially during enumeration)
* o most users have only a few elements (== overhead)
* o most users never use seach, so don't benefit from hashing
* Problem already fixed :
* o not 64 bit compliant (most users do hashv = (int) self)
* o hashbin_remove() is broken => use hashbin_remove_this()
* I think most users would be better served by a simple linked list
* (like include/linux/list.h) with a global spinlock per list.
* Jean II
*/
/*
* Notes on the concurent access to hashbin and other SMP issues
* -------------------------------------------------------------
* Hashbins are very often in the IrDA stack a global repository of
* information, and therefore used in a very asynchronous manner following
* various events (driver calls, timers, user calls...).
* Therefore, very often it is highly important to consider the
* management of concurent access to the hashbin and how to guarantee the
* consistency of the operations on it.
*
* First, we need to define the objective of locking :
* 1) Protect user data (content pointed by the hashbin)
* 2) Protect hashbin structure itself (linked list in each bin)
*
* OLD LOCKING
* -----------
*
* The previous locking strategy, either HB_LOCAL or HB_GLOBAL were
* both inadequate in *both* aspect.
* o HB_GLOBAL was using a spinlock for each bin (local locking).
* o HB_LOCAL was disabling irq on *all* CPUs, so use a single
* global semaphore.
* The problems were :
* A) Global irq disabling is no longer supported by the kernel
* B) No protection for the hashbin struct global data
* o hashbin_delete()
* o hb_current
* C) No protection for user data in some cases
*
* A) HB_LOCAL use global irq disabling, so doesn't work on kernel
* 2.5.X. Even when it is supported (kernel 2.4.X and earlier), its
* performance is not satisfactory on SMP setups. Most hashbins were
* HB_LOCAL, so (A) definitely need fixing.
* B) HB_LOCAL could be modified to fix (B). However, because HB_GLOBAL
* lock only the individual bins, it will never be able to lock the
* global data, so can't do (B).
* C) Some functions return pointer to data that is still in the
* hashbin :
* o hashbin_find()
* o hashbin_get_first()
* o hashbin_get_next()
* As the data is still in the hashbin, it may be changed or free'd
* while the caller is examinimg the data. In those case, locking can't
* be done within the hashbin, but must include use of the data within
* the caller.
* The caller can easily do this with HB_LOCAL (just disable irqs).
* However, this is impossible with HB_GLOBAL because the caller has no
* way to know the proper bin, so don't know which spinlock to use.
*
* Quick summary : can no longer use HB_LOCAL, and HB_GLOBAL is
* fundamentally broken and will never work.
*
* NEW LOCKING
* -----------
*
* To fix those problems, I've introduce a few changes in the
* hashbin locking :
* 1) New HB_LOCK scheme
* 2) hashbin->hb_spinlock
* 3) New hashbin usage policy
*
* HB_LOCK :
* -------
* HB_LOCK is a locking scheme intermediate between the old HB_LOCAL
* and HB_GLOBAL. It uses a single spinlock to protect the whole content
* of the hashbin. As it is a single spinlock, it can protect the global
* data of the hashbin and not only the bins themselves.
* HB_LOCK can only protect some of the hashbin calls, so it only lock
* call that can be made 100% safe and leave other call unprotected.
* HB_LOCK in theory is slower than HB_GLOBAL, but as the hashbin
* content is always small contention is not high, so it doesn't matter
* much. HB_LOCK is probably faster than HB_LOCAL.
*
* hashbin->hb_spinlock :
* --------------------
* The spinlock that HB_LOCK uses is available for caller, so that
* the caller can protect unprotected calls (see below).
* If the caller want to do entirely its own locking (HB_NOLOCK), he
* can do so and may use safely this spinlock.
* Locking is done like this :
* spin_lock_irqsave(&hashbin->hb_spinlock, flags);
* Releasing the lock :
* spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
*
* Safe & Protected calls :
* ----------------------
* The following calls are safe or protected via HB_LOCK :
* o hashbin_new() -> safe
* o hashbin_delete()
* o hashbin_insert()
* o hashbin_remove_first()
* o hashbin_remove()
* o hashbin_remove_this()
* o HASHBIN_GET_SIZE() -> atomic
*
* The following calls only protect the hashbin itself :
* o hashbin_lock_find()
* o hashbin_find_next()
*
* Unprotected calls :
* -----------------
* The following calls need to be protected by the caller :
* o hashbin_find()
* o hashbin_get_first()
* o hashbin_get_next()
*
* Locking Policy :
* --------------
* If the hashbin is used only in a single thread of execution
* (explicitely or implicitely), you can use HB_NOLOCK
* If the calling module already provide concurent access protection,
* you may use HB_NOLOCK.
*
* In all other cases, you need to use HB_LOCK and lock the hashbin
* everytime before calling one of the unprotected calls. You also must
* use the pointer returned by the unprotected call within the locked
* region.
*
* Extra care for enumeration :
* --------------------------
* hashbin_get_first() and hashbin_get_next() use the hashbin to
* store the current position, in hb_current.
* As long as the hashbin remains locked, this is safe. If you unlock
* the hashbin, the current position may change if anybody else modify
* or enumerate the hashbin.
* Summary : do the full enumeration while locked.
*
* Alternatively, you may use hashbin_find_next(). But, this will
* be slower, is more complex to use and doesn't protect the hashbin
* content. So, care is needed here as well.
*
* Other issues :
* ------------
* I believe that we are overdoing it by using spin_lock_irqsave()
* and we should use only spin_lock_bh() or similar. But, I don't have
* the balls to try it out.
* Don't believe that because hashbin are now (somewhat) SMP safe
* that the rest of the code is. Higher layers tend to be safest,
* but LAP and LMP would need some serious dedicated love.
*
* Jean II
*/
#include <net/irda/irda.h> #include <net/irda/irda.h>
#include <net/irda/irqueue.h> #include <net/irda/irqueue.h>
static irda_queue_t *dequeue_general( irda_queue_t **queue, irda_queue_t* element); /************************ QUEUE SUBROUTINES ************************/
static __u32 hash( char* name);
/*
* Hashbin
*/
#define GET_HASHBIN(x) ( x & HASHBIN_MASK )
/*
* Function hash (name)
*
* This function hash the input string 'name' using the ELF hash
* function for strings.
*/
static __u32 hash( char* name)
{
__u32 h = 0;
__u32 g;
while(*name) {
h = (h<<4) + *name++;
if ((g = (h & 0xf0000000)))
h ^=g>>24;
h &=~g;
}
return h;
}
/*
* Function enqueue_first (queue, proc)
*
* Insert item first in queue.
*
*/
static void enqueue_first(irda_queue_t **queue, irda_queue_t* element)
{
IRDA_DEBUG( 4, __FUNCTION__ "()\n");
/*
* Check if queue is empty.
*/
if ( *queue == NULL ) {
/*
* Queue is empty. Insert one element into the queue.
*/
element->q_next = element->q_prev = *queue = element;
} else {
/*
* Queue is not empty. Insert element into front of queue.
*/
element->q_next = (*queue);
(*queue)->q_prev->q_next = element;
element->q_prev = (*queue)->q_prev;
(*queue)->q_prev = element;
(*queue) = element;
}
}
#ifdef HASHBIN_UNUSED
/*
* Function enqueue_last (queue, proc)
*
* Insert item into end of queue.
*
*/
static void __enqueue_last( irda_queue_t **queue, irda_queue_t* element)
{
IRDA_DEBUG( 4, __FUNCTION__ "()\n");
/*
* Check if queue is empty.
*/
if ( *queue == NULL ) {
/*
* Queue is empty. Insert one element into the queue.
*/
element->q_next = element->q_prev = *queue = element;
} else {
/*
* Queue is not empty. Insert element into end of queue.
*/
element->q_prev = (*queue)->q_prev;
element->q_prev->q_next = element;
(*queue)->q_prev = element;
element->q_next = *queue;
}
}
static inline void enqueue_last( irda_queue_t **queue, irda_queue_t* element)
{
unsigned long flags;
save_flags(flags);
cli();
__enqueue_last( queue, element);
restore_flags(flags);
}
/*
* Function enqueue_queue (queue, list)
*
* Insert a queue (list) into the start of the first queue
*
*/
static void enqueue_queue( irda_queue_t** queue, irda_queue_t** list )
{
irda_queue_t* tmp;
/*
* Check if queue is empty
*/
if ( *queue ) {
(*list)->q_prev->q_next = (*queue);
(*queue)->q_prev->q_next = (*list);
tmp = (*list)->q_prev;
(*list)->q_prev = (*queue)->q_prev;
(*queue)->q_prev = tmp;
} else {
*queue = (*list);
}
(*list) = NULL;
}
/*
* Function enqueue_second (queue, proc)
*
* Insert item behind head of queue.
*
*/
static void enqueue_second(irda_queue_t **queue, irda_queue_t* element)
{
IRDA_DEBUG( 0, "enqueue_second()\n");
/*
* Check if queue is empty.
*/
if ( *queue == NULL ) {
/*
* Queue is empty. Insert one element into the queue.
*/
element->q_next = element->q_prev = *queue = element;
} else {
/*
* Queue is not empty. Insert element into ..
*/
element->q_prev = (*queue);
(*queue)->q_next->q_prev = element;
element->q_next = (*queue)->q_next;
(*queue)->q_next = element;
}
}
#endif /* HASHBIN_UNUSED */
/*
* Function dequeue (queue)
*
* Remove first entry in queue
*
*/
static irda_queue_t *dequeue_first(irda_queue_t **queue)
{
irda_queue_t *ret;
IRDA_DEBUG( 4, "dequeue_first()\n");
/*
* Set return value
*/
ret = *queue;
if ( *queue == NULL ) {
/*
* Queue was empty.
*/
} else if ( (*queue)->q_next == *queue ) {
/*
* Queue only contained a single element. It will now be
* empty.
*/
*queue = NULL;
} else {
/*
* Queue contained several element. Remove the first one.
*/
(*queue)->q_prev->q_next = (*queue)->q_next;
(*queue)->q_next->q_prev = (*queue)->q_prev;
*queue = (*queue)->q_next;
}
/*
* Return the removed entry (or NULL of queue was empty).
*/
return ret;
}
/*
* Function dequeue_general (queue, element)
*
*
*/
static irda_queue_t *dequeue_general(irda_queue_t **queue, irda_queue_t* element)
{
irda_queue_t *ret;
IRDA_DEBUG( 4, "dequeue_general()\n");
/*
* Set return value
*/
ret = *queue;
if ( *queue == NULL ) {
/*
* Queue was empty.
*/
} else if ( (*queue)->q_next == *queue ) {
/*
* Queue only contained a single element. It will now be
* empty.
*/
*queue = NULL;
} else {
/*
* Remove specific element.
*/
element->q_prev->q_next = element->q_next;
element->q_next->q_prev = element->q_prev;
if ( (*queue) == element)
(*queue) = element->q_next;
}
/*
* Return the removed entry (or NULL of queue was empty).
*/
return ret;
}
/************************ HASHBIN MANAGEMENT ************************/
/* /*
* Function hashbin_create ( type, name ) * Function hashbin_create ( type, name )
...@@ -49,7 +450,6 @@ static __u32 hash( char* name); ...@@ -49,7 +450,6 @@ static __u32 hash( char* name);
hashbin_t *hashbin_new(int type) hashbin_t *hashbin_new(int type)
{ {
hashbin_t* hashbin; hashbin_t* hashbin;
int i;
/* /*
* Allocate new hashbin * Allocate new hashbin
...@@ -64,14 +464,17 @@ hashbin_t *hashbin_new(int type) ...@@ -64,14 +464,17 @@ hashbin_t *hashbin_new(int type)
memset(hashbin, 0, sizeof(hashbin_t)); memset(hashbin, 0, sizeof(hashbin_t));
hashbin->hb_type = type; hashbin->hb_type = type;
hashbin->magic = HB_MAGIC; hashbin->magic = HB_MAGIC;
//hashbin->hb_current = NULL;
/* Make sure all spinlock's are unlocked */ /* Make sure all spinlock's are unlocked */
for (i=0;i<HASHBIN_SIZE;i++) if ( hashbin->hb_type & HB_LOCK ) {
hashbin->hb_mutex[i] = SPIN_LOCK_UNLOCKED; spin_lock_init(&hashbin->hb_spinlock);
}
return hashbin; return hashbin;
} }
#ifdef HASHBIN_UNUSED
/* /*
* Function hashbin_clear (hashbin, free_func) * Function hashbin_clear (hashbin, free_func)
* *
...@@ -102,7 +505,7 @@ int hashbin_clear( hashbin_t* hashbin, FREE_FUNC free_func) ...@@ -102,7 +505,7 @@ int hashbin_clear( hashbin_t* hashbin, FREE_FUNC free_func)
return 0; return 0;
} }
#endif /* HASHBIN_UNUSED */
/* /*
* Function hashbin_delete (hashbin, free_func) * Function hashbin_delete (hashbin, free_func)
...@@ -114,11 +517,17 @@ int hashbin_clear( hashbin_t* hashbin, FREE_FUNC free_func) ...@@ -114,11 +517,17 @@ int hashbin_clear( hashbin_t* hashbin, FREE_FUNC free_func)
int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func) int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func)
{ {
irda_queue_t* queue; irda_queue_t* queue;
unsigned long flags = 0;
int i; int i;
ASSERT(hashbin != NULL, return -1;); ASSERT(hashbin != NULL, return -1;);
ASSERT(hashbin->magic == HB_MAGIC, return -1;); ASSERT(hashbin->magic == HB_MAGIC, return -1;);
/* Synchronize */
if ( hashbin->hb_type & HB_LOCK ) {
spin_lock_irqsave(&hashbin->hb_spinlock, flags);
}
/* /*
* Free the entries in the hashbin, TODO: use hashbin_clear when * Free the entries in the hashbin, TODO: use hashbin_clear when
* it has been shown to work * it has been shown to work
...@@ -133,22 +542,32 @@ int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func) ...@@ -133,22 +542,32 @@ int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func)
} }
} }
/* Cleanup local data */
hashbin->hb_current = NULL;
hashbin->magic = ~HB_MAGIC;
/* Release lock */
if ( hashbin->hb_type & HB_LOCK) {
spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
}
/* /*
* Free the hashbin structure * Free the hashbin structure
*/ */
hashbin->magic = ~HB_MAGIC;
kfree(hashbin); kfree(hashbin);
return 0; return 0;
} }
/********************* HASHBIN LIST OPERATIONS *********************/
/* /*
* Function hashbin_insert (hashbin, entry, name) * Function hashbin_insert (hashbin, entry, name)
* *
* Insert an entry into the hashbin * Insert an entry into the hashbin
* *
*/ */
void hashbin_insert(hashbin_t* hashbin, irda_queue_t* entry, __u32 hashv, char* name) void hashbin_insert(hashbin_t* hashbin, irda_queue_t* entry, long hashv, char* name)
{ {
unsigned long flags = 0; unsigned long flags = 0;
int bin; int bin;
...@@ -166,12 +585,8 @@ void hashbin_insert(hashbin_t* hashbin, irda_queue_t* entry, __u32 hashv, char* ...@@ -166,12 +585,8 @@ void hashbin_insert(hashbin_t* hashbin, irda_queue_t* entry, __u32 hashv, char*
bin = GET_HASHBIN( hashv ); bin = GET_HASHBIN( hashv );
/* Synchronize */ /* Synchronize */
if ( hashbin->hb_type & HB_GLOBAL ) { if ( hashbin->hb_type & HB_LOCK ) {
spin_lock_irqsave( &hashbin->hb_mutex[ bin ], flags); spin_lock_irqsave(&hashbin->hb_spinlock, flags);
} else if ( hashbin->hb_type & HB_LOCAL ) {
save_flags(flags);
cli();
} /* Default is no-lock */ } /* Default is no-lock */
/* /*
...@@ -194,102 +609,61 @@ void hashbin_insert(hashbin_t* hashbin, irda_queue_t* entry, __u32 hashv, char* ...@@ -194,102 +609,61 @@ void hashbin_insert(hashbin_t* hashbin, irda_queue_t* entry, __u32 hashv, char*
hashbin->hb_size++; hashbin->hb_size++;
/* Release lock */ /* Release lock */
if ( hashbin->hb_type & HB_GLOBAL) { if ( hashbin->hb_type & HB_LOCK ) {
spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
spin_unlock_irqrestore( &hashbin->hb_mutex[ bin], flags); } /* Default is no-lock */
} else if ( hashbin->hb_type & HB_LOCAL) {
restore_flags( flags);
}
} }
/* /*
* Function hashbin_find (hashbin, hashv, name) * Function hashbin_remove_first (hashbin)
* *
* Find item with the given hashv or name * Remove first entry of the hashbin
* *
* Note : this function no longer use hashbin_remove(), but does things
* similar to hashbin_remove_this(), so can be considered safe.
* Jean II
*/ */
void* hashbin_find( hashbin_t* hashbin, __u32 hashv, char* name ) void *hashbin_remove_first( hashbin_t *hashbin)
{ {
int bin, found = FALSE;
unsigned long flags = 0; unsigned long flags = 0;
irda_queue_t* entry; irda_queue_t *entry = NULL;
IRDA_DEBUG( 4, "hashbin_find()\n");
ASSERT( hashbin != NULL, return NULL;);
ASSERT( hashbin->magic == HB_MAGIC, return NULL;);
/*
* Locate hashbin
*/
if ( name )
hashv = hash( name );
bin = GET_HASHBIN( hashv );
/* Synchronize */ /* Synchronize */
if ( hashbin->hb_type & HB_GLOBAL ) { if ( hashbin->hb_type & HB_LOCK ) {
spin_lock_irqsave( &hashbin->hb_mutex[ bin ], flags); spin_lock_irqsave(&hashbin->hb_spinlock, flags);
} else if ( hashbin->hb_type & HB_LOCAL ) {
save_flags(flags);
cli();
} /* Default is no-lock */ } /* Default is no-lock */
/*
* Search for entry
*/
entry = hashbin->hb_queue[ bin];
if ( entry ) {
do {
/*
* Check for key
*/
if ( entry->q_hash == hashv ) {
/*
* Name compare too?
*/
if ( name ) {
if ( strcmp( entry->q_name, name ) == 0 ) {
found = TRUE;
break;
}
} else {
found = TRUE;
break;
}
}
entry = entry->q_next;
} while ( entry != hashbin->hb_queue[ bin ] );
}
/* Release lock */
if ( hashbin->hb_type & HB_GLOBAL) {
spin_unlock_irqrestore( &hashbin->hb_mutex[ bin], flags);
} else if ( hashbin->hb_type & HB_LOCAL) {
restore_flags( flags);
}
if ( found )
return entry;
else
return NULL;
}
void *hashbin_remove_first( hashbin_t *hashbin) entry = hashbin_get_first( hashbin);
{ if ( entry != NULL) {
unsigned long flags; int bin;
irda_queue_t *entry = NULL; long hashv;
/*
* Locate hashbin
*/
hashv = entry->q_hash;
bin = GET_HASHBIN( hashv );
save_flags(flags); /*
cli(); * Dequeue the entry...
*/
dequeue_general( (irda_queue_t**) &hashbin->hb_queue[ bin ],
(irda_queue_t*) entry );
hashbin->hb_size--;
entry->q_next = NULL;
entry->q_prev = NULL;
entry = hashbin_get_first( hashbin); /*
if ( entry != NULL) * Check if this item is the currently selected item, and in
hashbin_remove( hashbin, entry->q_hash, NULL); * that case we must reset hb_current
*/
if ( entry == hashbin->hb_current)
hashbin->hb_current = NULL;
}
restore_flags( flags); /* Release lock */
if ( hashbin->hb_type & HB_LOCK ) {
spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
} /* Default is no-lock */
return entry; return entry;
} }
...@@ -300,8 +674,16 @@ void *hashbin_remove_first( hashbin_t *hashbin) ...@@ -300,8 +674,16 @@ void *hashbin_remove_first( hashbin_t *hashbin)
* *
* Remove entry with the given name * Remove entry with the given name
* *
* The use of this function is highly discouraged, because the whole
* concept behind hashbin_remove() is broken. In many cases, it's not
* possible to guarantee the unicity of the index (either hashv or name),
* leading to removing the WRONG entry.
* The only simple safe use is :
* hashbin_remove(hasbin, (int) self, NULL);
* In other case, you must think hard to guarantee unicity of the index.
* Jean II
*/ */
void* hashbin_remove( hashbin_t* hashbin, __u32 hashv, char* name) void* hashbin_remove( hashbin_t* hashbin, long hashv, char* name)
{ {
int bin, found = FALSE; int bin, found = FALSE;
unsigned long flags = 0; unsigned long flags = 0;
...@@ -320,12 +702,8 @@ void* hashbin_remove( hashbin_t* hashbin, __u32 hashv, char* name) ...@@ -320,12 +702,8 @@ void* hashbin_remove( hashbin_t* hashbin, __u32 hashv, char* name)
bin = GET_HASHBIN( hashv ); bin = GET_HASHBIN( hashv );
/* Synchronize */ /* Synchronize */
if ( hashbin->hb_type & HB_GLOBAL ) { if ( hashbin->hb_type & HB_LOCK ) {
spin_lock_irqsave( &hashbin->hb_mutex[ bin ], flags); spin_lock_irqsave(&hashbin->hb_spinlock, flags);
} else if ( hashbin->hb_type & HB_LOCAL ) {
save_flags(flags);
cli();
} /* Default is no-lock */ } /* Default is no-lock */
/* /*
...@@ -373,12 +751,9 @@ void* hashbin_remove( hashbin_t* hashbin, __u32 hashv, char* name) ...@@ -373,12 +751,9 @@ void* hashbin_remove( hashbin_t* hashbin, __u32 hashv, char* name)
} }
/* Release lock */ /* Release lock */
if ( hashbin->hb_type & HB_GLOBAL) { if ( hashbin->hb_type & HB_LOCK ) {
spin_unlock_irqrestore( &hashbin->hb_mutex[ bin], flags); spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
} /* Default is no-lock */
} else if ( hashbin->hb_type & HB_LOCAL) {
restore_flags( flags);
}
/* Return */ /* Return */
...@@ -390,7 +765,7 @@ void* hashbin_remove( hashbin_t* hashbin, __u32 hashv, char* name) ...@@ -390,7 +765,7 @@ void* hashbin_remove( hashbin_t* hashbin, __u32 hashv, char* name)
} }
/* /*
* Function hashbin_remove (hashbin, hashv, name) * Function hashbin_remove_this (hashbin, entry)
* *
* Remove entry with the given name * Remove entry with the given name
* *
...@@ -404,7 +779,7 @@ void* hashbin_remove_this( hashbin_t* hashbin, irda_queue_t* entry) ...@@ -404,7 +779,7 @@ void* hashbin_remove_this( hashbin_t* hashbin, irda_queue_t* entry)
{ {
unsigned long flags = 0; unsigned long flags = 0;
int bin; int bin;
__u32 hashv; long hashv;
IRDA_DEBUG( 4, __FUNCTION__ "()\n"); IRDA_DEBUG( 4, __FUNCTION__ "()\n");
...@@ -412,6 +787,11 @@ void* hashbin_remove_this( hashbin_t* hashbin, irda_queue_t* entry) ...@@ -412,6 +787,11 @@ void* hashbin_remove_this( hashbin_t* hashbin, irda_queue_t* entry)
ASSERT( hashbin->magic == HB_MAGIC, return NULL;); ASSERT( hashbin->magic == HB_MAGIC, return NULL;);
ASSERT( entry != NULL, return NULL;); ASSERT( entry != NULL, return NULL;);
/* Synchronize */
if ( hashbin->hb_type & HB_LOCK ) {
spin_lock_irqsave(&hashbin->hb_spinlock, flags);
} /* Default is no-lock */
/* Check if valid and not already removed... */ /* Check if valid and not already removed... */
if((entry->q_next == NULL) || (entry->q_prev == NULL)) if((entry->q_next == NULL) || (entry->q_prev == NULL))
return NULL; return NULL;
...@@ -422,38 +802,148 @@ void* hashbin_remove_this( hashbin_t* hashbin, irda_queue_t* entry) ...@@ -422,38 +802,148 @@ void* hashbin_remove_this( hashbin_t* hashbin, irda_queue_t* entry)
hashv = entry->q_hash; hashv = entry->q_hash;
bin = GET_HASHBIN( hashv ); bin = GET_HASHBIN( hashv );
/* Synchronize */ /*
if ( hashbin->hb_type & HB_GLOBAL ) { * Dequeue the entry...
spin_lock_irqsave( &hashbin->hb_mutex[ bin ], flags); */
dequeue_general( (irda_queue_t**) &hashbin->hb_queue[ bin ],
(irda_queue_t*) entry );
hashbin->hb_size--;
entry->q_next = NULL;
entry->q_prev = NULL;
/*
* Check if this item is the currently selected item, and in
* that case we must reset hb_current
*/
if ( entry == hashbin->hb_current)
hashbin->hb_current = NULL;
/* Release lock */
if ( hashbin->hb_type & HB_LOCK ) {
spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
} /* Default is no-lock */
return entry;
}
/*********************** HASHBIN ENUMERATION ***********************/
/*
* Function hashbin_common_find (hashbin, hashv, name)
*
* Find item with the given hashv or name
*
*/
void* hashbin_find( hashbin_t* hashbin, long hashv, char* name )
{
int bin;
irda_queue_t* entry;
IRDA_DEBUG( 4, "hashbin_find()\n");
ASSERT( hashbin != NULL, return NULL;);
ASSERT( hashbin->magic == HB_MAGIC, return NULL;);
/*
* Locate hashbin
*/
if ( name )
hashv = hash( name );
bin = GET_HASHBIN( hashv );
/*
* Search for entry
*/
entry = hashbin->hb_queue[ bin];
if ( entry ) {
do {
/*
* Check for key
*/
if ( entry->q_hash == hashv ) {
/*
* Name compare too?
*/
if ( name ) {
if ( strcmp( entry->q_name, name ) == 0 ) {
return entry;
}
} else {
return entry;
}
}
entry = entry->q_next;
} while ( entry != hashbin->hb_queue[ bin ] );
}
return NULL;
}
/*
* Function hashbin_lock_find (hashbin, hashv, name)
*
* Find item with the given hashv or name
*
* Same, but with spinlock protection...
* I call it safe, but it's only safe with respect to the hashbin, not its
* content. - Jean II
*/
void* hashbin_lock_find( hashbin_t* hashbin, long hashv, char* name )
{
unsigned long flags = 0;
irda_queue_t* entry;
/* Synchronize */
spin_lock_irqsave(&hashbin->hb_spinlock, flags);
/*
* Search for entry
*/
entry = (irda_queue_t* ) hashbin_find( hashbin, hashv, name );
/* Release lock */
spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
return entry;
}
/*
* Function hashbin_find (hashbin, hashv, name, pnext)
*
* Find an item with the given hashv or name, and its successor
*
* This function allow to do concurent enumerations without the
* need to lock over the whole session, because the caller keep the
* context of the search. On the other hand, it might fail and return
* NULL if the entry is removed. - Jean II
*/
void* hashbin_find_next( hashbin_t* hashbin, long hashv, char* name,
void ** pnext)
{
unsigned long flags = 0;
irda_queue_t* entry;
} else if ( hashbin->hb_type & HB_LOCAL ) { /* Synchronize */
save_flags(flags); spin_lock_irqsave(&hashbin->hb_spinlock, flags);
cli();
} /* Default is no-lock */
/* /*
* Dequeue the entry... * Search for current entry
* This allow to check if the current item is still in the
* hashbin or has been removed.
*/ */
dequeue_general( (irda_queue_t**) &hashbin->hb_queue[ bin ], entry = (irda_queue_t* ) hashbin_find( hashbin, hashv, name );
(irda_queue_t*) entry );
hashbin->hb_size--;
entry->q_next = NULL;
entry->q_prev = NULL;
/* /*
* Check if this item is the currently selected item, and in * Trick hashbin_get_next() to return what we want
* that case we must reset hb_current
*/ */
if ( entry == hashbin->hb_current) if(entry) {
hashbin->hb_current = NULL; hashbin->hb_current = entry;
*pnext = hashbin_get_next( hashbin );
} else
*pnext = NULL;
/* Release lock */ /* Release lock */
if ( hashbin->hb_type & HB_GLOBAL) { spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
spin_unlock_irqrestore( &hashbin->hb_mutex[ bin], flags);
} else if ( hashbin->hb_type & HB_LOCAL) {
restore_flags( flags);
}
return entry; return entry;
} }
...@@ -496,6 +986,8 @@ irda_queue_t *hashbin_get_first( hashbin_t* hashbin) ...@@ -496,6 +986,8 @@ irda_queue_t *hashbin_get_first( hashbin_t* hashbin)
* be started by a call to hashbin_get_first(). The function returns * be started by a call to hashbin_get_first(). The function returns
* NULL when all items have been traversed * NULL when all items have been traversed
* *
* The context of the search is stored within the hashbin, so you must
* protect yourself from concurent enumerations. - Jean II
*/ */
irda_queue_t *hashbin_get_next( hashbin_t *hashbin) irda_queue_t *hashbin_get_next( hashbin_t *hashbin)
{ {
...@@ -543,240 +1035,3 @@ irda_queue_t *hashbin_get_next( hashbin_t *hashbin) ...@@ -543,240 +1035,3 @@ irda_queue_t *hashbin_get_next( hashbin_t *hashbin)
} }
return NULL; return NULL;
} }
/*
* Function enqueue_last (queue, proc)
*
* Insert item into end of queue.
*
*/
static void __enqueue_last( irda_queue_t **queue, irda_queue_t* element)
{
IRDA_DEBUG( 4, __FUNCTION__ "()\n");
/*
* Check if queue is empty.
*/
if ( *queue == NULL ) {
/*
* Queue is empty. Insert one element into the queue.
*/
element->q_next = element->q_prev = *queue = element;
} else {
/*
* Queue is not empty. Insert element into end of queue.
*/
element->q_prev = (*queue)->q_prev;
element->q_prev->q_next = element;
(*queue)->q_prev = element;
element->q_next = *queue;
}
}
inline void enqueue_last( irda_queue_t **queue, irda_queue_t* element)
{
unsigned long flags;
save_flags(flags);
cli();
__enqueue_last( queue, element);
restore_flags(flags);
}
/*
* Function enqueue_first (queue, proc)
*
* Insert item first in queue.
*
*/
void enqueue_first(irda_queue_t **queue, irda_queue_t* element)
{
IRDA_DEBUG( 4, __FUNCTION__ "()\n");
/*
* Check if queue is empty.
*/
if ( *queue == NULL ) {
/*
* Queue is empty. Insert one element into the queue.
*/
element->q_next = element->q_prev = *queue = element;
} else {
/*
* Queue is not empty. Insert element into front of queue.
*/
element->q_next = (*queue);
(*queue)->q_prev->q_next = element;
element->q_prev = (*queue)->q_prev;
(*queue)->q_prev = element;
(*queue) = element;
}
}
/*
* Function enqueue_queue (queue, list)
*
* Insert a queue (list) into the start of the first queue
*
*/
void enqueue_queue( irda_queue_t** queue, irda_queue_t** list )
{
irda_queue_t* tmp;
/*
* Check if queue is empty
*/
if ( *queue ) {
(*list)->q_prev->q_next = (*queue);
(*queue)->q_prev->q_next = (*list);
tmp = (*list)->q_prev;
(*list)->q_prev = (*queue)->q_prev;
(*queue)->q_prev = tmp;
} else {
*queue = (*list);
}
(*list) = NULL;
}
/*
* Function enqueue_second (queue, proc)
*
* Insert item behind head of queue.
*
*/
#if 0
static void enqueue_second(irda_queue_t **queue, irda_queue_t* element)
{
IRDA_DEBUG( 0, "enqueue_second()\n");
/*
* Check if queue is empty.
*/
if ( *queue == NULL ) {
/*
* Queue is empty. Insert one element into the queue.
*/
element->q_next = element->q_prev = *queue = element;
} else {
/*
* Queue is not empty. Insert element into ..
*/
element->q_prev = (*queue);
(*queue)->q_next->q_prev = element;
element->q_next = (*queue)->q_next;
(*queue)->q_next = element;
}
}
#endif
/*
* Function dequeue (queue)
*
* Remove first entry in queue
*
*/
irda_queue_t *dequeue_first(irda_queue_t **queue)
{
irda_queue_t *ret;
IRDA_DEBUG( 4, "dequeue_first()\n");
/*
* Set return value
*/
ret = *queue;
if ( *queue == NULL ) {
/*
* Queue was empty.
*/
} else if ( (*queue)->q_next == *queue ) {
/*
* Queue only contained a single element. It will now be
* empty.
*/
*queue = NULL;
} else {
/*
* Queue contained several element. Remove the first one.
*/
(*queue)->q_prev->q_next = (*queue)->q_next;
(*queue)->q_next->q_prev = (*queue)->q_prev;
*queue = (*queue)->q_next;
}
/*
* Return the removed entry (or NULL of queue was empty).
*/
return ret;
}
/*
* Function dequeue_general (queue, element)
*
*
*/
static irda_queue_t *dequeue_general(irda_queue_t **queue, irda_queue_t* element)
{
irda_queue_t *ret;
IRDA_DEBUG( 4, "dequeue_general()\n");
/*
* Set return value
*/
ret = *queue;
if ( *queue == NULL ) {
/*
* Queue was empty.
*/
} else if ( (*queue)->q_next == *queue ) {
/*
* Queue only contained a single element. It will now be
* empty.
*/
*queue = NULL;
} else {
/*
* Remove specific element.
*/
element->q_prev->q_next = element->q_next;
element->q_next->q_prev = element->q_prev;
if ( (*queue) == element)
(*queue) = element->q_next;
}
/*
* Return the removed entry (or NULL of queue was empty).
*/
return ret;
}
/*
* Function hash (name)
*
* This function hash the input string 'name' using the ELF hash
* function for strings.
*/
static __u32 hash( char* name)
{
__u32 h = 0;
__u32 g;
while(*name) {
h = (h<<4) + *name++;
if ((g = (h & 0xf0000000)))
h ^=g>>24;
h &=~g;
}
return h;
}
...@@ -132,12 +132,14 @@ EXPORT_SYMBOL(irlmp_dup); ...@@ -132,12 +132,14 @@ EXPORT_SYMBOL(irlmp_dup);
EXPORT_SYMBOL(lmp_reasons); EXPORT_SYMBOL(lmp_reasons);
/* Queue */ /* Queue */
EXPORT_SYMBOL(hashbin_find);
EXPORT_SYMBOL(hashbin_new); EXPORT_SYMBOL(hashbin_new);
EXPORT_SYMBOL(hashbin_insert); EXPORT_SYMBOL(hashbin_insert);
EXPORT_SYMBOL(hashbin_delete); EXPORT_SYMBOL(hashbin_delete);
EXPORT_SYMBOL(hashbin_remove); EXPORT_SYMBOL(hashbin_remove);
EXPORT_SYMBOL(hashbin_remove_this); EXPORT_SYMBOL(hashbin_remove_this);
EXPORT_SYMBOL(hashbin_find);
EXPORT_SYMBOL(hashbin_lock_find);
EXPORT_SYMBOL(hashbin_find_next);
EXPORT_SYMBOL(hashbin_get_next); EXPORT_SYMBOL(hashbin_get_next);
EXPORT_SYMBOL(hashbin_get_first); EXPORT_SYMBOL(hashbin_get_first);
...@@ -328,7 +330,8 @@ void __exit irda_cleanup(void) ...@@ -328,7 +330,8 @@ void __exit irda_cleanup(void)
* On the other hand, it needs to be initialised *after* the basic * On the other hand, it needs to be initialised *after* the basic
* networking, the /proc/net filesystem and sysctl module. Those are * networking, the /proc/net filesystem and sysctl module. Those are
* currently initialised in .../init/main.c (before initcalls). * currently initialised in .../init/main.c (before initcalls).
* Also, it needs to be initialised *after* the random number generator. * Also, IrDA drivers needs to be initialised *after* the random number
* generator (main stack and higher layer init don't need it anymore).
* *
* Jean II * Jean II
*/ */
......
...@@ -91,7 +91,7 @@ int __init irttp_init(void) ...@@ -91,7 +91,7 @@ int __init irttp_init(void)
irttp->magic = TTP_MAGIC; irttp->magic = TTP_MAGIC;
irttp->tsaps = hashbin_new(HB_LOCAL); irttp->tsaps = hashbin_new(HB_LOCK);
if (!irttp->tsaps) { if (!irttp->tsaps) {
ERROR("%s: can't allocate IrTTP hashbin!\n", __FUNCTION__); ERROR("%s: can't allocate IrTTP hashbin!\n", __FUNCTION__);
return -ENOMEM; return -ENOMEM;
...@@ -433,7 +433,7 @@ struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify) ...@@ -433,7 +433,7 @@ struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify)
self->notify = *notify; self->notify = *notify;
self->lsap = lsap; self->lsap = lsap;
hashbin_insert(irttp->tsaps, (irda_queue_t *) self, (int) self, NULL); hashbin_insert(irttp->tsaps, (irda_queue_t *) self, (long) self, NULL);
if (credit > TTP_RX_MAX_CREDIT) if (credit > TTP_RX_MAX_CREDIT)
self->initial_credit = TTP_RX_MAX_CREDIT; self->initial_credit = TTP_RX_MAX_CREDIT;
...@@ -503,7 +503,7 @@ int irttp_close_tsap(struct tsap_cb *self) ...@@ -503,7 +503,7 @@ int irttp_close_tsap(struct tsap_cb *self)
return 0; /* Will be back! */ return 0; /* Will be back! */
} }
tsap = hashbin_remove(irttp->tsaps, (int) self, NULL); tsap = hashbin_remove(irttp->tsaps, (long) self, NULL);
ASSERT(tsap == self, return -1;); ASSERT(tsap == self, return -1;);
...@@ -1365,31 +1365,44 @@ int irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size, ...@@ -1365,31 +1365,44 @@ int irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size,
struct tsap_cb *irttp_dup(struct tsap_cb *orig, void *instance) struct tsap_cb *irttp_dup(struct tsap_cb *orig, void *instance)
{ {
struct tsap_cb *new; struct tsap_cb *new;
unsigned long flags;
IRDA_DEBUG(1, __FUNCTION__ "()\n"); IRDA_DEBUG(1, __FUNCTION__ "()\n");
/* Protect our access to the old tsap instance */
spin_lock_irqsave(&irttp->tsaps->hb_spinlock, flags);
/* Find the old instance */
if (!hashbin_find(irttp->tsaps, (int) orig, NULL)) { if (!hashbin_find(irttp->tsaps, (int) orig, NULL)) {
IRDA_DEBUG(0, __FUNCTION__ "(), unable to find TSAP\n"); IRDA_DEBUG(0, __FUNCTION__ "(), unable to find TSAP\n");
spin_unlock_irqrestore(&irttp->tsaps->hb_spinlock, flags);
return NULL; return NULL;
} }
/* Allocate a new instance */
new = kmalloc(sizeof(struct tsap_cb), GFP_ATOMIC); new = kmalloc(sizeof(struct tsap_cb), GFP_ATOMIC);
if (!new) { if (!new) {
IRDA_DEBUG(0, __FUNCTION__ "(), unable to kmalloc\n"); IRDA_DEBUG(0, __FUNCTION__ "(), unable to kmalloc\n");
spin_unlock_irqrestore(&irttp->tsaps->hb_spinlock, flags);
return NULL; return NULL;
} }
/* Dup */ /* Dup */
memcpy(new, orig, sizeof(struct tsap_cb)); memcpy(new, orig, sizeof(struct tsap_cb));
new->notify.instance = instance;
new->lsap = irlmp_dup(orig->lsap, new); /* We don't need the old instance any more */
spin_unlock_irqrestore(&irttp->tsaps->hb_spinlock, flags);
/* Not everything should be copied */ /* Not everything should be copied */
new->notify.instance = instance;
new->lsap = irlmp_dup(orig->lsap, new);
init_timer(&new->todo_timer); init_timer(&new->todo_timer);
skb_queue_head_init(&new->rx_queue); skb_queue_head_init(&new->rx_queue);
skb_queue_head_init(&new->tx_queue); skb_queue_head_init(&new->tx_queue);
skb_queue_head_init(&new->rx_fragments); skb_queue_head_init(&new->rx_fragments);
hashbin_insert(irttp->tsaps, (irda_queue_t *) new, (int) new, NULL); /* This is locked */
hashbin_insert(irttp->tsaps, (irda_queue_t *) new, (long) new, NULL);
return new; return new;
} }
...@@ -1723,8 +1736,8 @@ int irttp_proc_read(char *buf, char **start, off_t offset, int len) ...@@ -1723,8 +1736,8 @@ int irttp_proc_read(char *buf, char **start, off_t offset, int len)
len = 0; len = 0;
save_flags(flags); /* Protect our access to the tsap list */
cli(); spin_lock_irqsave(&irttp->tsaps->hb_spinlock, flags);
self = (struct tsap_cb *) hashbin_get_first(irttp->tsaps); self = (struct tsap_cb *) hashbin_get_first(irttp->tsaps);
while (self != NULL) { while (self != NULL) {
...@@ -1770,7 +1783,7 @@ int irttp_proc_read(char *buf, char **start, off_t offset, int len) ...@@ -1770,7 +1783,7 @@ int irttp_proc_read(char *buf, char **start, off_t offset, int len)
self = (struct tsap_cb *) hashbin_get_next(irttp->tsaps); self = (struct tsap_cb *) hashbin_get_next(irttp->tsaps);
} }
restore_flags(flags); spin_unlock_irqrestore(&irttp->tsaps->hb_spinlock, flags);
return len; return len;
} }
......
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