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)
mii_reg1 = mdio_read(dev, vp->phys[0], 1);
mii_reg5 = mdio_read(dev, vp->phys[0], 5);
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 {
mii_reg5 &= vp->advertising;
if ((mii_reg5 & 0x0100) != 0 /* 100baseTx-FD */
|| (mii_reg5 & 0x00C0) == 0x0040) /* 10T-FD, but not 100-HD */
vp->full_duplex = 1;
netif_carrier_on(dev);
}
vp->partner_flow_ctrl = ((mii_reg5 & 0x0400) != 0);
if (vortex_debug > 1)
......@@ -1692,13 +1693,16 @@ vortex_timer(unsigned long data)
switch (dev->if_port) {
case XCVR_10baseT: case XCVR_100baseTx: case XCVR_100baseFx:
if (media_status & Media_LnkBeat) {
netif_carrier_on(dev);
ok = 1;
if (vortex_debug > 1)
printk(KERN_DEBUG "%s: Media %s has link beat, %x.\n",
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",
dev->name, media_tbl[dev->if_port].name, media_status);
}
break;
case XCVR_MII: case XCVR_NWAY:
{
......@@ -1707,7 +1711,7 @@ vortex_timer(unsigned long data)
if (vortex_debug > 2)
printk(KERN_DEBUG "%s: MII transceiver has status %4.4x.\n",
dev->name, mii_status);
if (mii_status & 0x0004) {
if (mii_status & BMSR_LSTATUS) {
int mii_reg5 = mdio_read(dev, vp->phys[0], 5);
if (! vp->force_fd && mii_reg5 != 0xffff) {
int duplex;
......@@ -1731,6 +1735,9 @@ vortex_timer(unsigned long data)
/* AKPM: bug: should reset Tx and Rx after setting Duplex. Page 180 */
}
}
netif_carrier_on(dev);
} else {
netif_carrier_off(dev);
}
}
break;
......
......@@ -1226,17 +1226,6 @@ CONFIG_NATSEMI
More specific information and updates are available from
<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
If you have a network (Ethernet) card of this type, say Y and read
the Ethernet-HOWTO, available from
......
......@@ -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 ' Myson MTD-8xx PCI Ethernet support' CONFIG_FEALNX $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 ' 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
......
......@@ -158,7 +158,7 @@ static int act200l_change_speed(struct irda_task *task)
}
break;
case IRDA_TASK_CHILD_WAIT:
WARNING(__FUNCTION__ "(), resetting dongle timed out!\n");
WARNING("%s(), resetting dongle timed out!\n", __FUNCTION__);
ret = -1;
break;
case IRDA_TASK_CHILD_DONE:
......@@ -203,7 +203,7 @@ static int act200l_change_speed(struct irda_task *task)
self->speed_task = NULL;
break;
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);
self->speed_task = NULL;
ret = -1;
......@@ -269,7 +269,7 @@ static int act200l_reset(struct irda_task *task)
self->reset_task = NULL;
break;
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);
self->reset_task = NULL;
ret = -1;
......
......@@ -259,7 +259,7 @@ static int actisys_reset(struct irda_task *task)
self->speed = 9600; /* That's the default */
break;
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);
self->reset_task = NULL;
ret = -1;
......
This diff is collapsed.
......@@ -129,7 +129,7 @@ static int girbil_change_speed(struct irda_task *task)
}
break;
case IRDA_TASK_CHILD_WAIT:
WARNING(__FUNCTION__ "(), resetting dongle timed out!\n");
WARNING("%s(), resetting dongle timed out!\n", __FUNCTION__);
ret = -1;
break;
case IRDA_TASK_CHILD_DONE:
......@@ -168,7 +168,7 @@ static int girbil_change_speed(struct irda_task *task)
self->speed_task = NULL;
break;
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);
self->speed_task = NULL;
ret = -1;
......@@ -221,7 +221,7 @@ static int girbil_reset(struct irda_task *task)
self->reset_task = NULL;
break;
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);
self->reset_task = NULL;
ret = -1;
......
......@@ -1171,7 +1171,7 @@ static inline int irda_usb_open(struct irda_usb_cb *self)
irda_usb_init_qos(self);
/* 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 */
/* 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)
}
break;
case IRDA_TASK_CHILD_WAIT:
WARNING(__FUNCTION__ "(), resetting dongle timed out!\n");
WARNING("%s(), resetting dongle timed out!\n", __FUNCTION__);
ret = -1;
break;
case IRDA_TASK_CHILD_DONE:
......@@ -157,7 +157,7 @@ static int mcp2120_change_speed(struct irda_task *task)
//printk("mcp2120_change_speed irda_task_wait\n");
break;
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);
self->speed_task = NULL;
ret = -1;
......@@ -212,7 +212,7 @@ static int mcp2120_reset(struct irda_task *task)
self->reset_task = NULL;
break;
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);
self->reset_task = NULL;
ret = -1;
......
This diff is collapsed.
......@@ -431,6 +431,7 @@ static int __init ircc_open(unsigned int fir_base, unsigned int sir_base)
struct ircc_cb *self;
struct irport_cb *irport;
unsigned char low, high, chip, config, dma, irq, version;
unsigned long flags;
IRDA_DEBUG(0, __FUNCTION__ "\n");
......@@ -484,7 +485,6 @@ static int __init ircc_open(unsigned int fir_base, unsigned int sir_base)
return -ENOMEM;
}
memset(self, 0, sizeof(struct ircc_cb));
spin_lock_init(&self->lock);
/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
self->rx_buff.truesize = 4000;
......@@ -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);
/* Don't allow irport to change under us - Jean II */
spin_lock_irqsave(&self->irport->lock, flags);
/* Initialize QoS for this device */
irda_init_max_qos_capabilies(&irport->qos);
......@@ -581,6 +584,7 @@ static int __init ircc_open(unsigned int fir_base, unsigned int sir_base)
self->netdev->stop = &ircc_net_close;
irport_start(self->irport);
spin_unlock_irqrestore(&self->irport->lock, flags);
self->pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, ircc_pmproc);
if (self->pmdev)
......@@ -598,6 +602,7 @@ static int __init ircc_open(unsigned int fir_base, unsigned int sir_base)
*
* 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)
{
......@@ -658,6 +663,7 @@ static void ircc_change_speed(void *priv, u32 speed)
/* Make special FIR init if necessary */
if (speed > 115200) {
/* No need to lock, already locked - Jean II */
irport_stop(self->irport);
/* Install FIR transmit handler */
......@@ -674,6 +680,7 @@ static void ircc_change_speed(void *priv, u32 speed)
} else {
/* Install SIR transmit handler */
dev->hard_start_xmit = &irport_hard_xmit;
/* No need to lock, already locked - Jean II */
irport_start(self->irport);
IRDA_DEBUG(0, __FUNCTION__
......@@ -727,20 +734,26 @@ static int ircc_hard_xmit(struct sk_buff *skb, struct net_device *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 */
speed = irda_get_next_speed(skb);
if ((speed != self->io->speed) && (speed != -1)) {
/* Check for empty frame */
if (!skb->len) {
ircc_change_speed(self, speed);
spin_unlock_irqrestore(&self->irport->lock, flags);
dev_kfree_skb(skb);
return 0;
} else
self->new_speed = speed;
}
spin_lock_irqsave(&self->lock, flags);
memcpy(self->tx_buff.head, skb->data, 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)
/* Transmit frame */
ircc_dma_xmit(self, iobase, 0);
}
spin_unlock_irqrestore(&self->lock, flags);
spin_unlock_irqrestore(&self->irport->lock, flags);
dev_kfree_skb(skb);
return 0;
......@@ -936,14 +949,14 @@ static void ircc_dma_receive_complete(struct ircc_cb *self, int iobase)
len -= 4;
if ((len < 2) || (len > 2050)) {
WARNING(__FUNCTION__ "(), bogus len=%d\n", len);
WARNING("%s(), bogus len=%d\n", __FUNCTION__, len);
return;
}
IRDA_DEBUG(2, __FUNCTION__ ": msgcnt = %d, len=%d\n", msgcnt, len);
skb = dev_alloc_skb(len+1);
if (!skb) {
WARNING(__FUNCTION__ "(), memory squeeze, dropping frame.\n");
WARNING("%s(), memory squeeze, dropping frame.\n", __FUNCTION__);
return;
}
/* Make sure IP header gets aligned */
......@@ -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 */
if (self->io->speed < 576000) {
/* Will spinlock itself - Jean II */
irport_interrupt(irq, dev_id, regs);
return;
}
iobase = self->io->fir_base;
spin_lock(&self->lock);
spin_lock(&self->irport->lock);
register_bank(iobase, 0);
iir = inb(iobase+IRCC_IIR);
......@@ -1013,7 +1027,7 @@ static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
register_bank(iobase, 0);
outb(IRCC_IER_ACTIVE_FRAME|IRCC_IER_EOM, iobase+IRCC_IER);
spin_unlock(&self->lock);
spin_unlock(&self->irport->lock);
}
#if 0 /* unused */
......@@ -1072,7 +1086,7 @@ static int ircc_net_open(struct net_device *dev)
if (request_dma(self->io->dma, dev->name)) {
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;
}
......@@ -1093,7 +1107,7 @@ static int ircc_net_close(struct net_device *dev)
struct ircc_cb *self;
int iobase;
IRDA_DEBUG(0, __FUNCTION__ "\n");
IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
ASSERT(dev != NULL, return -1;);
irport = (struct irport_cb *) dev->priv;
......@@ -1128,17 +1142,15 @@ static void ircc_suspend(struct ircc_cb *self)
static void ircc_wakeup(struct ircc_cb *self)
{
unsigned long flags;
if (!self->io->suspended)
return;
save_flags(flags);
cli();
/* The code was doing a "cli()" here, but this can't be right.
* If you need protection, do it in net_open with a spinlock
* or give a good reason. - Jean II */
ircc_net_open(self->netdev);
restore_flags(flags);
MESSAGE("%s, Waking up\n", driver_name);
}
......@@ -1174,6 +1186,7 @@ static int __exit ircc_close(struct ircc_cb *self)
iobase = self->irport->io.fir_base;
/* This will destroy irport */
irport_close(self->irport);
/* Stop interrupts */
......@@ -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_CFGB_IR, iobase+IRCC_SCE_CFGB);
#endif
/* Release the PORT that this driver is using */
IRDA_DEBUG(0, __FUNCTION__ "(), releasing 0x%03x\n", iobase);
......
......@@ -161,7 +161,7 @@ static int tekram_change_speed(struct irda_task *task)
irda_task_next_state(task, IRDA_TASK_CHILD_DONE);
break;
case IRDA_TASK_CHILD_WAIT:
WARNING(__FUNCTION__ "(), resetting dongle timed out!\n");
WARNING("%s(), resetting dongle timed out!\n", __FUNCTION__);
ret = -1;
break;
case IRDA_TASK_CHILD_DONE:
......@@ -187,7 +187,7 @@ static int tekram_change_speed(struct irda_task *task)
self->speed_task = NULL;
break;
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);
self->speed_task = NULL;
ret = -1;
......@@ -255,7 +255,7 @@ int tekram_reset(struct irda_task *task)
self->reset_task = NULL;
break;
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);
self->reset_task = NULL;
ret = -1;
......
......@@ -421,8 +421,8 @@ toshoboe_interrupt (int irq, void *dev_id, struct pt_regs *regs)
}
else
{
printk (KERN_INFO __FUNCTION__
"(), memory squeeze, dropping frame.\n");
printk (KERN_INFO
"%s(), memory squeeze, dropping frame.\n", __FUNCTION__);
}
self->taskfile->recv[self->rxs].control = 0x83;
......@@ -824,7 +824,7 @@ toshoboe_probe (struct pci_dev *pci_dev, const struct pci_device_id *pdid)
if (!(dev = dev_alloc("irda%d", &err))) {
ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
ERROR("%s(), dev_alloc() failed!\n", __FUNCTION__);
err = -ENOMEM;
goto freebufs;
}
......@@ -843,7 +843,7 @@ toshoboe_probe (struct pci_dev *pci_dev, const struct pci_device_id *pdid)
err = register_netdevice(dev);
rtnl_unlock();
if (err) {
ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
/* XXX there is not freeing for dev? */
goto freebufs;
}
......
......@@ -175,6 +175,7 @@ int w83977af_open(int i, unsigned int iobase, unsigned int irq,
return -ENOMEM;
}
memset(self, 0, sizeof(struct w83977af_ir));
spin_lock_init(&self->lock);
/* Need to store self somewhere */
dev_self[i] = self;
......@@ -236,7 +237,7 @@ int w83977af_open(int i, unsigned int iobase, unsigned int irq,
self->rx_buff.data = self->rx_buff.head;
if (!(dev = dev_alloc("irda%d", &err))) {
ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
ERROR("%s(), dev_alloc() failed!\n", __FUNCTION__);
return -ENOMEM;
}
dev->priv = (void *) self;
......@@ -254,7 +255,7 @@ int w83977af_open(int i, unsigned int iobase, unsigned int irq,
err = register_netdevice(dev);
rtnl_unlock();
if (err) {
ERROR(__FUNCTION__ "(), register_netdevice() failed!\n");
ERROR("%s(), register_netdevice() failed!\n", __FUNCTION__);
return -1;
}
MESSAGE("IrDA: Registered device %s\n", dev->name);
......@@ -603,8 +604,7 @@ static void w83977af_dma_write(struct w83977af_ir *self, int iobase)
switch_bank(iobase, SET2);
outb(ADCR1_D_CHSW|/*ADCR1_DMA_F|*/ADCR1_ADV_SL, iobase+ADCR1);
#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS
save_flags(flags);
cli();
spin_lock_irqsave(&self->lock, flags);
disable_dma(self->io.dma);
clear_dma_ff(self->io.dma);
......@@ -623,7 +623,7 @@ static void w83977af_dma_write(struct w83977af_ir *self, int iobase)
hcr = inb(iobase+HCR);
outb(hcr | HCR_EN_DMA, iobase+HCR);
enable_dma(self->io.dma);
restore_flags(flags);
spin_unlock_irqrestore(&self->lock, flags);
#else
outb(inb(iobase+HCR) | HCR_EN_DMA | HCR_TX_WT, iobase+HCR);
#endif
......@@ -761,8 +761,7 @@ int w83977af_dma_receive(struct w83977af_ir *self)
self->rx_buff.data = self->rx_buff.head;
#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS
save_flags(flags);
cli();
spin_lock_irqsave(&self->lock, flags);
disable_dma(self->io.dma);
clear_dma_ff(self->io.dma);
......@@ -788,7 +787,7 @@ int w83977af_dma_receive(struct w83977af_ir *self)
hcr = inb(iobase+HCR);
outb(hcr | HCR_EN_DMA, iobase+HCR);
enable_dma(self->io.dma);
restore_flags(flags);
spin_unlock_irqrestore(&self->lock, flags);
#else
outb(inb(iobase+HCR) | HCR_EN_DMA, iobase+HCR);
#endif
......@@ -892,8 +891,8 @@ int w83977af_dma_receive_complete(struct w83977af_ir *self)
skb = dev_alloc_skb(len+1);
if (skb == NULL) {
printk(KERN_INFO __FUNCTION__
"(), memory squeeze, dropping frame.\n");
printk(KERN_INFO
"%s(), memory squeeze, dropping frame.\n", __FUNCTION__);
/* Restore set register */
outb(set, iobase+SSR);
......@@ -1334,9 +1333,7 @@ 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);
/* Disable interrupts & save flags */
save_flags(flags);
cli();
spin_lock_irqsave(&self->lock, flags);
switch (cmd) {
case SIOCSBANDWIDTH: /* Set bandwidth */
......@@ -1360,7 +1357,7 @@ static int w83977af_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
ret = -EOPNOTSUPP;
}
out:
restore_flags(flags);
spin_unlock_irqrestore(&self->lock, flags);
return ret;
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -59,7 +59,7 @@ nbd_end_request(struct request *req)
blk_finished_io(nsect);
req->bio = bio->bi_next;
bio->bi_next = NULL;
bio_endio(bio, uptodate);
bio_endio(bio, nsect << 9, uptodate ? 0 : -EIO);
}
blk_put_request(req);
spin_unlock_irqrestore(q->queue_lock, flags);
......
......@@ -691,6 +691,8 @@ enum {
NETIF_MSG_TX_DONE = 0x0400,
NETIF_MSG_RX_STATUS = 0x0800,
NETIF_MSG_PKTDATA = 0x1000,
NETIF_MSG_HW = 0x2000,
NETIF_MSG_WOL = 0x4000,
};
#define netif_msg_drv(p) ((p)->msg_enable & NETIF_MSG_DRV)
......@@ -706,6 +708,8 @@ enum {
#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_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? */
......
......@@ -55,8 +55,8 @@ struct irda_sock {
__u16 mask; /* Hint bits mask */
__u16 hints; /* Hint bits */
__u32 ckey; /* IrLMP client handle */
__u32 skey; /* IrLMP service handle */
void *ckey; /* IrLMP client handle */
void *skey; /* IrLMP service handle */
struct ias_object *ias_obj; /* Our service name + lsap in IAS */
struct iriap_cb *iriap; /* Used to query remote IAS */
......
......@@ -86,8 +86,8 @@ struct ircomm_tty_cb {
struct iriap_cb *iriap; /* Instance used for querying remote IAS */
struct ias_object* obj;
int skey;
int ckey;
void *skey;
void *ckey;
struct termios normal_termios;
struct termios callout_termios;
......@@ -104,6 +104,14 @@ struct ircomm_tty_cb {
long pgrp; /* pgrp of opening process */
int open_count;
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);
......
......@@ -183,7 +183,6 @@ struct irlmp_cb {
hashbin_t *services;
hashbin_t *cachelog; /* Current discovery log */
spinlock_t log_lock; /* discovery log spinlock */
int running;
......@@ -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);
__u16 irlmp_service_to_hint(int service);
__u32 irlmp_register_service(__u16 hints);
int irlmp_unregister_service(__u32 handle);
__u32 irlmp_register_client(__u16 hint_mask, DISCOVERY_CALLBACK1 disco_clb,
void *irlmp_register_service(__u16 hints);
int irlmp_unregister_service(void *handle);
void *irlmp_register_client(__u16 hint_mask, DISCOVERY_CALLBACK1 disco_clb,
DISCOVERY_CALLBACK1 expir_clb, void *priv);
int irlmp_unregister_client(__u32 handle);
int irlmp_update_client(__u32 handle, __u16 hint_mask,
int irlmp_unregister_client(void *handle);
int irlmp_update_client(void *handle, __u16 hint_mask,
DISCOVERY_CALLBACK1 disco_clb,
DISCOVERY_CALLBACK1 expir_clb, void *priv);
......@@ -221,7 +220,7 @@ void irlmp_disconnect_indication(struct lsap_cb *self, LM_REASON reason,
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);
struct irda_device_info *irlmp_get_discoveries(int *pn, __u16 mask, int nslots);
void irlmp_do_expiry(void);
......@@ -258,8 +257,6 @@ extern int sysctl_discovery;
extern int sysctl_lap_keepalive_time; /* in ms, default is LM_IDLE_TIMEOUT */
extern struct irlmp_cb *irlmp;
static inline hashbin_t *irlmp_get_cachelog(void) { return irlmp->cachelog; }
/* Check if LAP queue is full.
* 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)
......
......@@ -36,12 +36,12 @@
#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_GLOBAL 1
#define HB_LOCAL 2
#define HB_SORTED 4
#define HB_NOLOCK 0 /* No concurent access prevention */
#define HB_LOCK 1 /* Prevent concurent write with global lock */
#define HB_SORTED 4 /* Not yet supported */
/*
* Hash defines
......@@ -57,17 +57,12 @@
typedef void (*FREE_FUNC)(void *arg);
/*
* Hashbin
*/
#define GET_HASHBIN(x) ( x & HASHBIN_MASK )
struct irda_queue {
struct irda_queue *q_next;
struct irda_queue *q_prev;
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;
......@@ -75,8 +70,9 @@ typedef struct hashbin_t {
__u32 magic;
int hb_type;
int hb_size;
spinlock_t hb_mutex[HASHBIN_SIZE] IRDA_ALIGN;
irda_queue_t *hb_queue[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_current;
} hashbin_t;
......@@ -84,19 +80,18 @@ typedef struct hashbin_t {
hashbin_t *hashbin_new(int type);
int hashbin_delete(hashbin_t* hashbin, FREE_FUNC 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);
void* hashbin_find(hashbin_t* hashbin, __u32 hashv, char* name);
void* hashbin_remove(hashbin_t* hashbin, __u32 hashv, char* name);
void* hashbin_remove(hashbin_t* hashbin, long hashv, char* name);
void* hashbin_remove_first(hashbin_t *hashbin);
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_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
#endif
......@@ -62,6 +62,9 @@ struct irtty_cb {
struct qos_info qos; /* QoS capabilities for this device */
dongle_t *dongle; /* Dongle driver */
spinlock_t lock; /* For serializing operations */
__u32 new_speed;
__u32 flags; /* Interface flags */
......
......@@ -165,7 +165,9 @@ struct ircc_cb {
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 flags; /* Interface flags */
......
......@@ -180,6 +180,11 @@ struct w83977af_ir {
iobuff_t tx_buff; /* Transmit 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 new_speed;
};
......
......@@ -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) */
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
......@@ -95,13 +95,13 @@ void irlmp_add_discovery(hashbin_t *cachelog, discovery_t *new)
/* Insert the new and updated version */
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)
*
* 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)
......@@ -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
* of the normal one.
*/
/* Well... It means that there was nobody out there - Jean II */
if (log == NULL) {
/* irlmp_start_discovery_timer(irlmp, 150); */
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);
while (discovery != NULL) {
irlmp_add_discovery(cachelog, discovery);
......@@ -146,7 +152,7 @@ void irlmp_expire_discoveries(hashbin_t *log, __u32 saddr, int force)
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);
while (discovery != NULL) {
......@@ -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
return NULL;
/* 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 */
n = HASHBIN_GET_SIZE(log);
buffer = kmalloc(n * sizeof(struct irda_device_info), GFP_ATOMIC);
if (buffer == NULL) {
spin_unlock_irqrestore(&irlmp->log_lock, flags);
spin_unlock_irqrestore(&log->hb_spinlock, flags);
return NULL;
}
......@@ -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);
}
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 */
*pn = i;
......@@ -276,7 +282,7 @@ __u32 irlmp_find_device(hashbin_t *cachelog, char *name, __u32 *saddr)
unsigned long flags;
discovery_t *d;
spin_lock_irqsave(&irlmp->log_lock, flags);
spin_lock_irqsave(&cachelog->hb_spinlock, flags);
/* Look at all discoveries for that link */
d = (discovery_t *) hashbin_get_first(cachelog);
......@@ -288,13 +294,13 @@ __u32 irlmp_find_device(hashbin_t *cachelog, char *name, __u32 *saddr)
if (strcmp(name, d->nickname) == 0) {
*saddr = d->saddr;
spin_unlock_irqrestore(&irlmp->log_lock, flags);
spin_unlock_irqrestore(&cachelog->hb_spinlock, flags);
return d->daddr;
}
d = (discovery_t *) hashbin_get_next(cachelog);
}
spin_unlock_irqrestore(&irlmp->log_lock, flags);
spin_unlock_irqrestore(&cachelog->hb_spinlock, flags);
return 0;
}
......@@ -310,7 +316,7 @@ int discovery_proc_read(char *buf, char **start, off_t offset, int length,
{
discovery_t *discovery;
unsigned long flags;
hashbin_t *cachelog = irlmp_get_cachelog();
hashbin_t *cachelog = irlmp->cachelog;
int len = 0;
if (!irlmp)
......@@ -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");
spin_lock_irqsave(&irlmp->log_lock, flags);
spin_lock_irqsave(&cachelog->hb_spinlock, flags);
discovery = (discovery_t *) hashbin_get_first(cachelog);
while (( discovery != NULL) && (len < 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);
}
spin_unlock_irqrestore(&irlmp->log_lock, flags);
spin_unlock_irqrestore(&cachelog->hb_spinlock, flags);
return len;
}
......@@ -61,7 +61,7 @@ hashbin_t *ircomm = NULL;
int __init ircomm_init(void)
{
ircomm = hashbin_new(HB_LOCAL);
ircomm = hashbin_new(HB_LOCK);
if (ircomm == NULL) {
ERROR(__FUNCTION__ "(), can't allocate hashbin!\n");
return -ENOMEM;
......@@ -505,11 +505,10 @@ int ircomm_proc_read(char *buf, char **start, off_t offset, int len)
struct ircomm_cb *self;
unsigned long flags;
save_flags(flags);
cli();
len = 0;
spin_lock_irqsave(&ircomm->hb_spinlock, flags);
self = (struct ircomm_cb *) hashbin_get_first(ircomm);
while (self != NULL) {
ASSERT(self->magic == IRCOMM_MAGIC, break;);
......@@ -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);
}
restore_flags(flags);
spin_unlock_irqrestore(&ircomm->hb_spinlock, flags);
return len;
}
......
......@@ -177,7 +177,7 @@ void ircomm_lmp_flow_control(struct sk_buff *skb)
line = cb->line;
self = (struct ircomm_cb *) hashbin_find(ircomm, line, NULL);
self = (struct ircomm_cb *) hashbin_lock_find(ircomm, line, NULL);
if (!self) {
IRDA_DEBUG(2, __FUNCTION__ "(), didn't find myself\n");
return;
......
......@@ -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)
{
/* we should lock here, but I guess this function is unused...
* Jean II */
if (self->ctrl_skb) {
ircomm_control_request(self->ircomm, self->ctrl_skb);
self->ctrl_skb = NULL;
......@@ -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)
return 0;
save_flags(flags);
cli();
spin_lock_irqsave(&self->spinlock, flags);
skb = self->ctrl_skb;
if (!skb) {
skb = dev_alloc_skb(256);
if (!skb) {
restore_flags(flags);
spin_unlock_irqrestore(&self->spinlock, flags);
return -ENOMEM;
}
......@@ -154,12 +155,12 @@ int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush)
&ircomm_param_info);
if (count < 0) {
WARNING(__FUNCTION__ "(), no room for parameter!\n");
restore_flags(flags);
spin_unlock_irqrestore(&self->spinlock, flags);
return -1;
}
skb_put(skb, count);
restore_flags(flags);
spin_unlock_irqrestore(&self->spinlock, flags);
IRDA_DEBUG(2, __FUNCTION__ "(), skb->len=%d\n", skb->len);
......
......@@ -90,7 +90,7 @@ hashbin_t *ircomm_tty = NULL;
*/
int __init ircomm_tty_init(void)
{
ircomm_tty = hashbin_new(HB_LOCAL);
ircomm_tty = hashbin_new(HB_LOCK);
if (ircomm_tty == NULL) {
ERROR(__FUNCTION__ "(), can't allocate hashbin!\n");
return -ENOMEM;
......@@ -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",
__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)) {
extra_count = 1;
self->open_count--;
}
restore_flags(flags);
spin_unlock_irqrestore(&self->spinlock, flags);
self->blocked_open++;
while (1) {
if (!(self->flags & ASYNC_CALLOUT_ACTIVE) &&
(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;
ircomm_param_request(self, IRCOMM_DTE, TRUE);
restore_flags(flags);
}
current->state = TASK_INTERRUPTIBLE;
......@@ -361,8 +364,12 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
__set_current_state(TASK_RUNNING);
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++;
spin_unlock_irqrestore(&self->spinlock, flags);
}
self->blocked_open--;
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)
{
struct ircomm_tty_cb *self;
unsigned int line;
unsigned long flags;
int ret;
IRDA_DEBUG(2, __FUNCTION__ "()\n");
......@@ -397,7 +405,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
}
/* Check if instance already exists */
self = hashbin_find(ircomm_tty, line, NULL);
self = hashbin_lock_find(ircomm_tty, line, NULL);
if (!self) {
/* No, so make new instance */
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)
init_timer(&self->watchdog_timer);
init_waitqueue_head(&self->open_wait);
init_waitqueue_head(&self->close_wait);
spin_lock_init(&self->spinlock);
/*
* 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)
/* Insert into hash */
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++;
tty->driver_data = self;
self->tty = tty;
spin_unlock_irqrestore(&self->spinlock, flags);
IRDA_DEBUG(1, __FUNCTION__"(), %s%d, count = %d\n", tty->driver.name,
self->line, self->open_count);
......@@ -526,12 +538,11 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
ASSERT(self != NULL, return;);
ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
save_flags(flags);
cli();
spin_lock_irqsave(&self->spinlock, flags);
if (tty_hung_up_p(filp)) {
MOD_DEC_USE_COUNT;
restore_flags(flags);
spin_unlock_irqrestore(&self->spinlock, flags);
IRDA_DEBUG(0, __FUNCTION__ "(), returning 1\n");
return;
......@@ -559,13 +570,19 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
}
if (self->open_count) {
MOD_DEC_USE_COUNT;
restore_flags(flags);
spin_unlock_irqrestore(&self->spinlock, flags);
IRDA_DEBUG(0, __FUNCTION__ "(), open count > 0\n");
return;
}
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
* 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)
wake_up_interruptible(&self->close_wait);
MOD_DEC_USE_COUNT;
restore_flags(flags);
}
/*
......@@ -645,13 +661,12 @@ static void ircomm_tty_do_softint(void *private_)
return;
/* Unlink control buffer */
save_flags(flags);
cli();
spin_lock_irqsave(&self->spinlock, flags);
ctrl_skb = self->ctrl_skb;
self->ctrl_skb = NULL;
restore_flags(flags);
spin_unlock_irqrestore(&self->spinlock, flags);
/* Flush control buffer if any */
if (ctrl_skb && self->flow == FLOW_START)
......@@ -661,13 +676,12 @@ static void ircomm_tty_do_softint(void *private_)
return;
/* Unlink transmit buffer */
save_flags(flags);
cli();
spin_lock_irqsave(&self->spinlock, flags);
skb = self->tx_skb;
self->tx_skb = NULL;
restore_flags(flags);
spin_unlock_irqrestore(&self->spinlock, flags);
/* Flush transmit buffer if any */
if (skb)
......@@ -720,8 +734,7 @@ static int ircomm_tty_write(struct tty_struct *tty, int from_user,
return len;
}
save_flags(flags);
cli();
spin_lock_irqsave(&self->spinlock, flags);
/* Fetch current transmit buffer */
skb = self->tx_skb;
......@@ -768,7 +781,7 @@ static int ircomm_tty_write(struct tty_struct *tty, int from_user,
skb = dev_alloc_skb(self->max_data_size+
self->max_header_size);
if (!skb) {
restore_flags(flags);
spin_unlock_irqrestore(&self->spinlock, flags);
return -ENOBUFS;
}
skb_reserve(skb, self->max_header_size);
......@@ -785,7 +798,7 @@ static int ircomm_tty_write(struct tty_struct *tty, int from_user,
len += size;
}
restore_flags(flags);
spin_unlock_irqrestore(&self->spinlock, flags);
/*
* 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)
(self->max_header_size == IRCOMM_TTY_HDR_UNITIALISED))
ret = 0;
else {
save_flags(flags);
cli();
spin_lock_irqsave(&self->spinlock, flags);
if (self->tx_skb)
ret = self->max_data_size - self->tx_skb->len;
else
ret = self->max_data_size;
restore_flags(flags);
spin_unlock_irqrestore(&self->spinlock, flags);
}
IRDA_DEBUG(2, __FUNCTION__ "(), ret=%d\n", ret);
......@@ -946,13 +958,12 @@ static int ircomm_tty_chars_in_buffer(struct tty_struct *tty)
ASSERT(self != NULL, return -1;);
ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
save_flags(flags);
cli();
spin_lock_irqsave(&self->spinlock, flags);
if (self->tx_skb)
len = self->tx_skb->len;
restore_flags(flags);
spin_unlock_irqrestore(&self->spinlock, flags);
return len;
}
......@@ -969,8 +980,7 @@ static void ircomm_tty_shutdown(struct ircomm_tty_cb *self)
if (!(self->flags & ASYNC_INITIALIZED))
return;
save_flags(flags);
cli();
spin_lock_irqsave(&self->spinlock, flags);
del_timer(&self->watchdog_timer);
......@@ -994,7 +1004,7 @@ static void ircomm_tty_shutdown(struct ircomm_tty_cb *self)
}
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)
static void ircomm_tty_hangup(struct tty_struct *tty)
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
unsigned long flags;
IRDA_DEBUG(0, __FUNCTION__"()\n");
......@@ -1019,9 +1030,13 @@ static void ircomm_tty_hangup(struct tty_struct *tty)
/* ircomm_tty_flush_buffer(tty); */
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->tty = 0;
self->open_count = 0;
spin_unlock_irqrestore(&self->spinlock, flags);
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,
struct ircomm_tty_cb *self;
int count = 0, l;
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);
while ((self != NULL) && (count < 4000)) {
if (self->magic != IRCOMM_TTY_MAGIC)
return 0;
break;
l = ircomm_tty_line_info(self, buf + count);
count += l;
......@@ -1381,6 +1399,8 @@ static int ircomm_tty_read_proc(char *buf, char **start, off_t offset, int len,
}
*eof = 1;
done:
spin_unlock_irqrestore(&ircomm_tty->hb_spinlock, flags);
if (offset >= count+begin)
return 0;
*start = buf + (offset-begin);
......
......@@ -331,6 +331,8 @@ static void ircomm_tty_discovery_indication(discovery_t *discovery,
info.daddr = discovery->daddr;
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);
while (self != NULL) {
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,
int __init irda_device_init( void)
{
dongles = hashbin_new(HB_GLOBAL);
dongles = hashbin_new(HB_LOCK);
if (dongles == NULL) {
printk(KERN_WARNING "IrDA: Can't allocate dongles hashbin!\n");
return -ENOMEM;
}
tasks = hashbin_new(HB_GLOBAL);
tasks = hashbin_new(HB_LOCK);
if (tasks == NULL) {
printk(KERN_WARNING "IrDA: Can't allocate tasks hashbin!\n");
return -ENOMEM;
......@@ -438,7 +438,7 @@ dongle_t *irda_device_dongle_init(struct net_device *dev, int type)
}
#endif
if (!(reg = hashbin_find(dongles, type, NULL))) {
if (!(reg = hashbin_lock_find(dongles, type, NULL))) {
ERROR("IrDA: Unable to find requested dongle\n");
return NULL;
}
......@@ -477,7 +477,7 @@ int irda_device_dongle_cleanup(dongle_t *dongle)
int irda_device_register_dongle(struct dongle_reg *new)
{
/* 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__);
return 0;
}
......
......@@ -58,7 +58,7 @@ static const char *ias_charset_types[] = {
#endif /* CONFIG_IRDA_DEBUG */
static hashbin_t *iriap = NULL;
static __u32 service_handle;
static void *service_handle;
extern char *lmp_reasons[];
......@@ -91,11 +91,12 @@ int __init iriap_init(void)
__u16 hints;
/* Allocate master array */
iriap = hashbin_new(HB_LOCAL);
iriap = hashbin_new(HB_LOCK);
if (!iriap)
return -ENOMEM;
objects = hashbin_new(HB_LOCAL);
/* Object repository - defined in irias_object.c */
objects = hashbin_new(HB_LOCK);
if (!objects) {
WARNING("%s: Can't allocate objects hashbin!\n", __FUNCTION__);
return -ENOMEM;
......@@ -182,7 +183,7 @@ struct iriap_cb *iriap_open(__u8 slsap_sel, int mode, void *priv,
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 */
iriap_next_client_state(self, S_DISCONNECT);
......@@ -235,7 +236,7 @@ void iriap_close(struct iriap_cb *self)
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;);
__iriap_close(self);
......@@ -973,13 +974,12 @@ int irias_proc_read(char *buf, char **start, off_t offset, int len)
ASSERT( objects != NULL, return 0;);
save_flags( flags);
cli();
len = 0;
len += sprintf(buf+len, "LM-IAS Objects:\n");
spin_lock_irqsave(&objects->hb_spinlock, flags);
/* List all objects */
obj = (struct ias_object *) hashbin_get_first(objects);
while ( obj != NULL) {
......@@ -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, "\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 */
attrib = (struct ias_attrib *)
hashbin_get_first(obj->attribs);
......@@ -1025,9 +1030,11 @@ int irias_proc_read(char *buf, char **start, off_t offset, int len)
attrib = (struct ias_attrib *)
hashbin_get_next(obj->attribs);
}
spin_unlock(&obj->attribs->hb_spinlock);
obj = (struct ias_object *) hashbin_get_next(objects);
}
restore_flags(flags);
spin_unlock_irqrestore(&objects->hb_spinlock, flags);
return len;
}
......
......@@ -93,7 +93,10 @@ struct ias_object *irias_new_object( char *name, int id)
obj->name = strndup(name, IAS_MAX_CLASSNAME);
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;
}
......@@ -147,7 +150,7 @@ int irias_delete_object(struct ias_object *obj)
ASSERT(obj != NULL, 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)
return 0; /* Already removed */
......@@ -172,7 +175,7 @@ int irias_delete_attrib(struct ias_object *obj, struct ias_attrib *attrib)
ASSERT(attrib != NULL, return -1;);
/* Remove attribute from object */
node = hashbin_remove(obj->attribs, 0, attrib->name);
node = hashbin_remove_this(obj->attribs, (irda_queue_t *) attrib);
if (!node)
return 0; /* Already removed or non-existent */
......@@ -211,7 +214,8 @@ struct ias_object *irias_find_object(char *name)
{
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)
ASSERT(obj->magic == IAS_OBJECT_MAGIC, 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)
return NULL;
/* Unsafe (locking), attrib might change */
return attrib;
}
......@@ -267,26 +272,32 @@ int irias_object_change_attribute(char *obj_name, char *attrib_name,
{
struct ias_object *obj;
struct ias_attrib *attrib;
unsigned long flags;
/* Find object */
obj = hashbin_find(objects, 0, obj_name);
obj = hashbin_lock_find(objects, 0, obj_name);
if (obj == NULL) {
WARNING("%s: Unable to find object: %s\n", __FUNCTION__,
obj_name);
return -1;
}
/* Slightly unsafe (obj might get removed under us) */
spin_lock_irqsave(&obj->attribs->hb_spinlock, flags);
/* Find attribute */
attrib = hashbin_find(obj->attribs, 0, attrib_name);
if (attrib == NULL) {
WARNING("%s: Unable to find attribute: %s\n", __FUNCTION__,
attrib_name);
spin_unlock_irqrestore(&obj->attribs->hb_spinlock, flags);
return -1;
}
if ( attrib->value->type != new_value->type) {
IRDA_DEBUG( 0, __FUNCTION__
"(), changing value type not allowed!\n");
spin_unlock_irqrestore(&obj->attribs->hb_spinlock, flags);
return -1;
}
......@@ -297,6 +308,7 @@ int irias_object_change_attribute(char *obj_name, char *attrib_name,
attrib->value = new_value;
/* Success */
spin_unlock_irqrestore(&obj->attribs->hb_spinlock, flags);
return 0;
}
......
......@@ -124,7 +124,7 @@ int __init irlan_init(void)
IRDA_DEBUG(0, __FUNCTION__ "()\n");
/* Allocate master structure */
irlan = hashbin_new(HB_LOCAL);
irlan = hashbin_new(HB_LOCK); /* protect from /proc */
if (irlan == NULL) {
printk(KERN_WARNING "IrLAN: Can't allocate hashbin!\n");
return -ENOMEM;
......@@ -1089,11 +1089,10 @@ static int irlan_proc_read(char *buf, char **start, off_t offset, int len)
unsigned long flags;
ASSERT(irlan != NULL, return 0;);
save_flags(flags);
cli();
len = 0;
spin_lock_irqsave(&irlan->hb_spinlock, flags);
len += sprintf(buf+len, "IrLAN instances:\n");
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)
self = (struct irlan_cb *) hashbin_get_next(irlan);
}
restore_flags(flags);
spin_unlock_irqrestore(&irlan->hb_spinlock, flags);
return len;
}
......
......@@ -80,7 +80,7 @@ int irlap_proc_read(char *, char **, off_t, int);
int __init irlap_init(void)
{
/* Allocate master array */
irlap = hashbin_new(HB_LOCAL);
irlap = hashbin_new(HB_LOCK);
if (irlap == NULL) {
ERROR("%s: can't allocate irlap hashbin!\n", __FUNCTION__);
return -ENOMEM;
......@@ -139,7 +139,15 @@ struct irlap_cb *irlap_open(struct net_device *dev, struct qos_info *qos,
skb_queue_head_init(&self->wx_list);
/* My unique IrLAP device address! */
/* 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);
init_timer(&self->slot_timer);
......@@ -522,7 +530,8 @@ void irlap_discovery_request(struct irlap_cb *self, discovery_t *discovery)
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 = 0; /* Current slot */
......@@ -1084,15 +1093,14 @@ int irlap_proc_read(char *buf, char **start, off_t offset, int len)
unsigned long flags;
int i = 0;
save_flags(flags);
cli();
spin_lock_irqsave(&irlap->hb_spinlock, flags);
len = 0;
self = (struct irlap_cb *) hashbin_get_first(irlap);
while (self != NULL) {
ASSERT(self != NULL, return -ENODEV;);
ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
ASSERT(self != NULL, break;);
ASSERT(self->magic == LAP_MAGIC, break;);
len += sprintf(buf+len, "irlap%d ", i++);
len += sprintf(buf+len, "state: %s\n",
......@@ -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);
}
restore_flags(flags);
spin_unlock_irqrestore(&irlap->hb_spinlock, flags);
return len;
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -210,6 +210,7 @@ void irlmp_link_unitdata_indication(struct lap_cb *self, struct sk_buff *skb)
__u8 dlsap_sel; /* Destination LSAP address */
__u8 pid; /* Protocol identifier */
__u8 *fp;
unsigned long flags;
IRDA_DEBUG(4, __FUNCTION__ "()\n");
......@@ -242,6 +243,8 @@ void irlmp_link_unitdata_indication(struct lap_cb *self, struct sk_buff *skb)
return;
}
/* Search the connectionless LSAP */
spin_lock_irqsave(&irlmp->unconnected_lsaps->hb_spinlock, flags);
lsap = (struct lsap_cb *) hashbin_get_first(irlmp->unconnected_lsaps);
while (lsap != NULL) {
/*
......@@ -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);
}
spin_unlock_irqrestore(&irlmp->unconnected_lsaps->hb_spinlock, flags);
if (lsap)
irlmp_connless_data_indication(lsap, skb);
else {
......@@ -374,6 +379,7 @@ void irlmp_link_discovery_indication(struct lap_cb *self,
ASSERT(self != NULL, return;);
ASSERT(self->magic == LMP_LAP_MAGIC, return;);
/* Add to main log, cleanup */
irlmp_add_discovery(irlmp->cachelog, discovery);
/* 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)
ASSERT(self != NULL, return;);
ASSERT(self->magic == LMP_LAP_MAGIC, return;);
/* Add to main log, cleanup */
irlmp_add_discovery_log(irlmp->cachelog, log);
/* Propagate event to various LSAPs registered for it.
......@@ -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,
struct lsap_cb *lsap)
{
/* Prevent concurent read to get garbage */
lap->cache.valid = FALSE;
/* Update cache entry */
lap->cache.dlsap_sel = lsap->dlsap_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,
hashbin_t *queue)
{
struct lsap_cb *lsap;
unsigned long flags;
/*
* 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,
return (self->cache.lsap);
}
#endif
spin_lock_irqsave(&queue->hb_spinlock, flags);
lsap = (struct lsap_cb *) hashbin_get_first(queue);
while (lsap != NULL) {
/*
......@@ -465,29 +478,27 @@ static struct lsap_cb *irlmp_find_lsap(struct lap_cb *self, __u8 dlsap_sel,
*/
if ((status == CONNECT_CMD) &&
(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;
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
irlmp_update_cache(self, lsap);
#endif
return lsap;
break;
}
/*
* Check if source LSAP and dest LSAP selectors match.
*/
if ((lsap->slsap_sel == slsap_sel) &&
(lsap->dlsap_sel == dlsap_sel))
{
break;
lsap = (struct lsap_cb *) hashbin_get_next(queue);
}
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
if(lsap)
irlmp_update_cache(self, lsap);
#endif
return lsap;
}
lsap = (struct lsap_cb *) hashbin_get_next(queue);
}
spin_unlock_irqrestore(&queue->hb_spinlock, flags);
/* Sorry not found! */
return NULL;
/* Return what we've found or NULL */
return lsap;
}
This diff is collapsed.
This diff is collapsed.
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