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;
......
This diff is collapsed.
...@@ -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
......
This diff is collapsed.
This diff is collapsed.
...@@ -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;
......
This diff is collapsed.
...@@ -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;
} }
......
This diff is collapsed.
...@@ -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;
} }
This diff is collapsed.
...@@ -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