Commit 54de58e9 authored by Linus Torvalds's avatar Linus Torvalds

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

into home.transmeta.com:/home/torvalds/v2.5/linux
parents cff20aab 801783b6
...@@ -1483,12 +1483,13 @@ vortex_up(struct net_device *dev) ...@@ -1483,12 +1483,13 @@ vortex_up(struct net_device *dev)
mii_reg1 = mdio_read(dev, vp->phys[0], 1); mii_reg1 = mdio_read(dev, vp->phys[0], 1);
mii_reg5 = mdio_read(dev, vp->phys[0], 5); mii_reg5 = mdio_read(dev, vp->phys[0], 5);
if (mii_reg5 == 0xffff || mii_reg5 == 0x0000) { if (mii_reg5 == 0xffff || mii_reg5 == 0x0000) {
; /* No MII device or no link partner report */ netif_carrier_off(dev); /* No MII device or no link partner report */
} else { } else {
mii_reg5 &= vp->advertising; mii_reg5 &= vp->advertising;
if ((mii_reg5 & 0x0100) != 0 /* 100baseTx-FD */ if ((mii_reg5 & 0x0100) != 0 /* 100baseTx-FD */
|| (mii_reg5 & 0x00C0) == 0x0040) /* 10T-FD, but not 100-HD */ || (mii_reg5 & 0x00C0) == 0x0040) /* 10T-FD, but not 100-HD */
vp->full_duplex = 1; vp->full_duplex = 1;
netif_carrier_on(dev);
} }
vp->partner_flow_ctrl = ((mii_reg5 & 0x0400) != 0); vp->partner_flow_ctrl = ((mii_reg5 & 0x0400) != 0);
if (vortex_debug > 1) if (vortex_debug > 1)
...@@ -1692,13 +1693,16 @@ vortex_timer(unsigned long data) ...@@ -1692,13 +1693,16 @@ vortex_timer(unsigned long data)
switch (dev->if_port) { switch (dev->if_port) {
case XCVR_10baseT: case XCVR_100baseTx: case XCVR_100baseFx: case XCVR_10baseT: case XCVR_100baseTx: case XCVR_100baseFx:
if (media_status & Media_LnkBeat) { if (media_status & Media_LnkBeat) {
netif_carrier_on(dev);
ok = 1; ok = 1;
if (vortex_debug > 1) if (vortex_debug > 1)
printk(KERN_DEBUG "%s: Media %s has link beat, %x.\n", printk(KERN_DEBUG "%s: Media %s has link beat, %x.\n",
dev->name, media_tbl[dev->if_port].name, media_status); dev->name, media_tbl[dev->if_port].name, media_status);
} else if (vortex_debug > 1) } else if (vortex_debug > 1) {
netif_carrier_off(dev);
printk(KERN_DEBUG "%s: Media %s has no link beat, %x.\n", printk(KERN_DEBUG "%s: Media %s has no link beat, %x.\n",
dev->name, media_tbl[dev->if_port].name, media_status); dev->name, media_tbl[dev->if_port].name, media_status);
}
break; break;
case XCVR_MII: case XCVR_NWAY: case XCVR_MII: case XCVR_NWAY:
{ {
...@@ -1707,7 +1711,7 @@ vortex_timer(unsigned long data) ...@@ -1707,7 +1711,7 @@ vortex_timer(unsigned long data)
if (vortex_debug > 2) if (vortex_debug > 2)
printk(KERN_DEBUG "%s: MII transceiver has status %4.4x.\n", printk(KERN_DEBUG "%s: MII transceiver has status %4.4x.\n",
dev->name, mii_status); dev->name, mii_status);
if (mii_status & 0x0004) { if (mii_status & BMSR_LSTATUS) {
int mii_reg5 = mdio_read(dev, vp->phys[0], 5); int mii_reg5 = mdio_read(dev, vp->phys[0], 5);
if (! vp->force_fd && mii_reg5 != 0xffff) { if (! vp->force_fd && mii_reg5 != 0xffff) {
int duplex; int duplex;
...@@ -1731,6 +1735,9 @@ vortex_timer(unsigned long data) ...@@ -1731,6 +1735,9 @@ vortex_timer(unsigned long data)
/* AKPM: bug: should reset Tx and Rx after setting Duplex. Page 180 */ /* AKPM: bug: should reset Tx and Rx after setting Duplex. Page 180 */
} }
} }
netif_carrier_on(dev);
} else {
netif_carrier_off(dev);
} }
} }
break; break;
......
...@@ -1226,17 +1226,6 @@ CONFIG_NATSEMI ...@@ -1226,17 +1226,6 @@ CONFIG_NATSEMI
More specific information and updates are available from More specific information and updates are available from
<http://www.scyld.com/network/natsemi.html>. <http://www.scyld.com/network/natsemi.html>.
CONFIG_NATSEMI_CABLE_MAGIC
Some systems see lots of errors with NatSemi ethernet controllers
on certain cables. If you are seeing lots of errors, try turning
this option on. Some boards have incorrect values for supporting
resistors that can cause this change to break. If you turn this
option on and your network suddenly stops working, turn this
option off.
Say N unless you are certain you need this option.
Vendors should not enable this option by default.
CONFIG_SK_G16 CONFIG_SK_G16
If you have a network (Ethernet) card of this type, say Y and read If you have a network (Ethernet) card of this type, say Y and read
the Ethernet-HOWTO, available from the Ethernet-HOWTO, available from
......
...@@ -165,9 +165,6 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then ...@@ -165,9 +165,6 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
dep_tristate ' Mylex EISA LNE390A/B support (EXPERIMENTAL)' CONFIG_LNE390 $CONFIG_EISA $CONFIG_EXPERIMENTAL dep_tristate ' Mylex EISA LNE390A/B support (EXPERIMENTAL)' CONFIG_LNE390 $CONFIG_EISA $CONFIG_EXPERIMENTAL
dep_tristate ' Myson MTD-8xx PCI Ethernet support' CONFIG_FEALNX $CONFIG_PCI dep_tristate ' Myson MTD-8xx PCI Ethernet support' CONFIG_FEALNX $CONFIG_PCI
dep_tristate ' National Semiconductor DP8381x series PCI Ethernet support' CONFIG_NATSEMI $CONFIG_PCI dep_tristate ' National Semiconductor DP8381x series PCI Ethernet support' CONFIG_NATSEMI $CONFIG_PCI
if [ "$CONFIG_NATSEMI" = "y" -o "$CONFIG_NATSEMI" = "m" ]; then
bool ' NatSemi workaround for high errors' CONFIG_NATSEMI_CABLE_MAGIC
fi
dep_tristate ' PCI NE2000 and clones support (see help)' CONFIG_NE2K_PCI $CONFIG_PCI dep_tristate ' PCI NE2000 and clones support (see help)' CONFIG_NE2K_PCI $CONFIG_PCI
dep_tristate ' Novell/Eagle/Microdyne NE3210 EISA support (EXPERIMENTAL)' CONFIG_NE3210 $CONFIG_EISA $CONFIG_EXPERIMENTAL dep_tristate ' Novell/Eagle/Microdyne NE3210 EISA support (EXPERIMENTAL)' CONFIG_NE3210 $CONFIG_EISA $CONFIG_EXPERIMENTAL
dep_tristate ' Racal-Interlan EISA ES3210 support (EXPERIMENTAL)' CONFIG_ES3210 $CONFIG_EISA $CONFIG_EXPERIMENTAL dep_tristate ' Racal-Interlan EISA ES3210 support (EXPERIMENTAL)' CONFIG_ES3210 $CONFIG_EISA $CONFIG_EXPERIMENTAL
......
...@@ -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;
} }
......
This diff is collapsed.
This diff is collapsed.
...@@ -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);
......
...@@ -691,6 +691,8 @@ enum { ...@@ -691,6 +691,8 @@ enum {
NETIF_MSG_TX_DONE = 0x0400, NETIF_MSG_TX_DONE = 0x0400,
NETIF_MSG_RX_STATUS = 0x0800, NETIF_MSG_RX_STATUS = 0x0800,
NETIF_MSG_PKTDATA = 0x1000, NETIF_MSG_PKTDATA = 0x1000,
NETIF_MSG_HW = 0x2000,
NETIF_MSG_WOL = 0x4000,
}; };
#define netif_msg_drv(p) ((p)->msg_enable & NETIF_MSG_DRV) #define netif_msg_drv(p) ((p)->msg_enable & NETIF_MSG_DRV)
...@@ -706,6 +708,8 @@ enum { ...@@ -706,6 +708,8 @@ enum {
#define netif_msg_tx_done(p) ((p)->msg_enable & NETIF_MSG_TX_DONE) #define netif_msg_tx_done(p) ((p)->msg_enable & NETIF_MSG_TX_DONE)
#define netif_msg_rx_status(p) ((p)->msg_enable & NETIF_MSG_RX_STATUS) #define netif_msg_rx_status(p) ((p)->msg_enable & NETIF_MSG_RX_STATUS)
#define netif_msg_pktdata(p) ((p)->msg_enable & NETIF_MSG_PKTDATA) #define netif_msg_pktdata(p) ((p)->msg_enable & NETIF_MSG_PKTDATA)
#define netif_msg_hw(p) ((p)->msg_enable & NETIF_MSG_HW)
#define netif_msg_wol(p) ((p)->msg_enable & NETIF_MSG_WOL)
/* Schedule rx intr now? */ /* Schedule rx intr now? */
......
...@@ -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.
This diff is collapsed.
This diff is collapsed.
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
*/ */
......
This diff is collapsed.
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