Commit c08e4720 authored by Jeff Garzik's avatar Jeff Garzik

Merge mandrakesoft.com:/home/jgarzik/repo/linus-2.5

into mandrakesoft.com:/home/jgarzik/repo/irda-2.5
parents 343da22d 7567630b
......@@ -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;
......
......@@ -141,12 +141,12 @@ int __init ali_ircc_init(void)
int reg, revision;
int i = 0;
IRDA_DEBUG(2, __FUNCTION__ "(), ---------------- Start ----------------\n");
IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);
/* Probe for all the ALi chipsets we know about */
for (chip= chips; chip->name; chip++, i++)
{
IRDA_DEBUG(2, __FUNCTION__"(), Probing for %s ...\n", chip->name);
IRDA_DEBUG(2, "%s(), Probing for %s ...\n", __FUNCTION__, chip->name);
/* Try all config registers for this chip */
for (cfg=0; cfg<2; cfg++)
......@@ -176,13 +176,11 @@ int __init ali_ircc_init(void)
if (reg == chip->cid_value)
{
IRDA_DEBUG(2, __FUNCTION__
"(), Chip found at 0x%03x\n", cfg_base);
IRDA_DEBUG(2, "%s(), Chip found at 0x%03x\n", __FUNCTION__, cfg_base);
outb(0x1F, cfg_base);
revision = inb(cfg_base+1);
IRDA_DEBUG(2, __FUNCTION__
"(), Found %s chip, revision=%d\n",
IRDA_DEBUG(2, "%s(), Found %s chip, revision=%d\n", __FUNCTION__,
chip->name, revision);
/*
......@@ -205,15 +203,14 @@ int __init ali_ircc_init(void)
}
else
{
IRDA_DEBUG(2, __FUNCTION__
"(), No %s chip at 0x%03x\n", chip->name, cfg_base);
IRDA_DEBUG(2, "%s(), No %s chip at 0x%03x\n", __FUNCTION__, chip->name, cfg_base);
}
/* Exit configuration */
outb(0xbb, cfg_base);
}
}
IRDA_DEBUG(2, __FUNCTION__ "(), ----------------- End -----------------\n");
IRDA_DEBUG(2, "%s(), ----------------- End -----------------\n", __FUNCTION__);
return ret;
}
......@@ -227,7 +224,7 @@ static void __exit ali_ircc_cleanup(void)
{
int i;
IRDA_DEBUG(2, __FUNCTION__ "(), ---------------- Start ----------------\n");
IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);
pm_unregister_all(ali_ircc_pmproc);
......@@ -236,7 +233,7 @@ static void __exit ali_ircc_cleanup(void)
ali_ircc_close(dev_self[i]);
}
IRDA_DEBUG(2, __FUNCTION__ "(), ----------------- End -----------------\n");
IRDA_DEBUG(2, "%s(), ----------------- End -----------------\n", __FUNCTION__);
}
/*
......@@ -251,9 +248,10 @@ static int ali_ircc_open(int i, chipio_t *info)
struct ali_ircc_cb *self;
struct pm_dev *pmdev;
int dongle_id;
int ret;
int err;
IRDA_DEBUG(2, __FUNCTION__ "(), ---------------- Start ----------------\n");
IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);
/* Set FIR FIFO and DMA Threshold */
if ((ali_ircc_setup(info)) == -1)
......@@ -263,7 +261,7 @@ static int ali_ircc_open(int i, chipio_t *info)
self = kmalloc(sizeof(struct ali_ircc_cb), GFP_KERNEL);
if (self == NULL)
{
ERROR(__FUNCTION__ "(), can't allocate memory for control block!\n");
ERROR("%s(), can't allocate memory for control block!\n", __FUNCTION__);
return -ENOMEM;
}
memset(self, 0, sizeof(struct ali_ircc_cb));
......@@ -285,7 +283,7 @@ static int ali_ircc_open(int i, chipio_t *info)
/* Reserve the ioports that we need */
ret = check_region(self->io.fir_base, self->io.fir_ext);
if (ret < 0) {
WARNING(__FUNCTION__ "(), can't get iobase of 0x%03x\n",
WARNING("%s(), can't get iobase of 0x%03x\n", __FUNCTION__,
self->io.fir_base);
dev_self[i] = NULL;
kfree(self);
......@@ -339,7 +337,7 @@ static int ali_ircc_open(int i, chipio_t *info)
self->tx_fifo.tail = self->tx_buff.head;
if (!(dev = dev_alloc("irda%d", &err))) {
ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
ERROR("%s(), dev_alloc() failed!\n", __FUNCTION__);
return -ENOMEM;
}
......@@ -358,14 +356,14 @@ static int ali_ircc_open(int i, chipio_t *info)
err = register_netdevice(dev);
rtnl_unlock();
if (err) {
ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
return -1;
}
MESSAGE("IrDA: Registered device %s\n", dev->name);
/* Check dongle id */
dongle_id = ali_ircc_read_dongle_id(i, info);
MESSAGE(__FUNCTION__ "(), %s, Found dongle: %s\n", driver_name, dongle_types[dongle_id]);
MESSAGE("%s(), %s, Found dongle: %s\n", __FUNCTION__, driver_name, dongle_types[dongle_id]);
self->io.dongle_id = dongle_id;
......@@ -373,7 +371,7 @@ static int ali_ircc_open(int i, chipio_t *info)
if (pmdev)
pmdev->data = self;
IRDA_DEBUG(2, __FUNCTION__ "(), ----------------- End -----------------\n");
IRDA_DEBUG(2, "%s(), ----------------- End -----------------\n", __FUNCTION__);
return 0;
}
......@@ -389,7 +387,7 @@ static int __exit ali_ircc_close(struct ali_ircc_cb *self)
{
int iobase;
IRDA_DEBUG(4, __FUNCTION__ "(), ---------------- Start ----------------\n");
IRDA_DEBUG(4, "%s(), ---------------- Start ----------------\n", __FUNCTION__);
ASSERT(self != NULL, return -1;);
......@@ -403,7 +401,7 @@ static int __exit ali_ircc_close(struct ali_ircc_cb *self)
}
/* Release the PORT that this driver is using */
IRDA_DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", self->io.fir_base);
IRDA_DEBUG(4, "%s(), Releasing Region %03x\n", __FUNCTION__, self->io.fir_base);
release_region(self->io.fir_base, self->io.fir_ext);
if (self->tx_buff.head)
......@@ -415,7 +413,7 @@ static int __exit ali_ircc_close(struct ali_ircc_cb *self)
dev_self[self->index] = NULL;
kfree(self);
IRDA_DEBUG(2, __FUNCTION__ "(), ----------------- End -----------------\n");
IRDA_DEBUG(2, "%s(), ----------------- End -----------------\n", __FUNCTION__);
return 0;
}
......@@ -458,7 +456,7 @@ static int ali_ircc_probe_53(ali_chip_t *chip, chipio_t *info)
int cfg_base = info->cfg_base;
int hi, low, reg;
IRDA_DEBUG(2, __FUNCTION__ "(), ---------------- Start ----------------\n");
IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);
/* Enter Configuration */
outb(chip->entr1, cfg_base);
......@@ -477,13 +475,13 @@ static int ali_ircc_probe_53(ali_chip_t *chip, chipio_t *info)
info->sir_base = info->fir_base;
IRDA_DEBUG(2, __FUNCTION__ "(), probing fir_base=0x%03x\n", info->fir_base);
IRDA_DEBUG(2, "%s(), probing fir_base=0x%03x\n", __FUNCTION__, info->fir_base);
/* Read IRQ control register */
outb(0x70, cfg_base);
reg = inb(cfg_base+1);
info->irq = reg & 0x0f;
IRDA_DEBUG(2, __FUNCTION__ "(), probing irq=%d\n", info->irq);
IRDA_DEBUG(2, "%s(), probing irq=%d\n", __FUNCTION__, info->irq);
/* Read DMA channel */
outb(0x74, cfg_base);
......@@ -491,26 +489,26 @@ static int ali_ircc_probe_53(ali_chip_t *chip, chipio_t *info)
info->dma = reg & 0x07;
if(info->dma == 0x04)
WARNING(__FUNCTION__ "(), No DMA channel assigned !\n");
WARNING("%s(), No DMA channel assigned !\n", __FUNCTION__);
else
IRDA_DEBUG(2, __FUNCTION__ "(), probing dma=%d\n", info->dma);
IRDA_DEBUG(2, "%s(), probing dma=%d\n", __FUNCTION__, info->dma);
/* Read Enabled Status */
outb(0x30, cfg_base);
reg = inb(cfg_base+1);
info->enabled = (reg & 0x80) && (reg & 0x01);
IRDA_DEBUG(2, __FUNCTION__ "(), probing enabled=%d\n", info->enabled);
IRDA_DEBUG(2, "%s(), probing enabled=%d\n", __FUNCTION__, info->enabled);
/* Read Power Status */
outb(0x22, cfg_base);
reg = inb(cfg_base+1);
info->suspended = (reg & 0x20);
IRDA_DEBUG(2, __FUNCTION__ "(), probing suspended=%d\n", info->suspended);
IRDA_DEBUG(2, "%s(), probing suspended=%d\n", __FUNCTION__, info->suspended);
/* Exit configuration */
outb(0xbb, cfg_base);
IRDA_DEBUG(2, __FUNCTION__ "(), ----------------- End -----------------\n");
IRDA_DEBUG(2, "%s(), ----------------- End -----------------\n", __FUNCTION__);
return 0;
}
......@@ -528,7 +526,12 @@ static int ali_ircc_setup(chipio_t *info)
int version;
int iobase = info->fir_base;
IRDA_DEBUG(2, __FUNCTION__ "(), ---------------- Start ----------------\n");
IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);
/* Locking comments :
* Most operations here need to be protected. We are called before
* the device instance is created in ali_ircc_open(), therefore
* nobody can bother us - Jean II */
/* Switch to FIR space */
SIR2FIR(iobase);
......@@ -584,7 +587,7 @@ static int ali_ircc_setup(chipio_t *info)
// outb(UART_IER_RDI, iobase+UART_IER); //benjamin 2000/11/23 01:25PM
// Turn on the interrupts in ali_ircc_net_open
IRDA_DEBUG(2, __FUNCTION__ "(), ----------------- End ------------------\n");
IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__);
return 0;
}
......@@ -601,7 +604,7 @@ static int ali_ircc_read_dongle_id (int i, chipio_t *info)
int dongle_id, reg;
int cfg_base = info->cfg_base;
IRDA_DEBUG(2, __FUNCTION__ "(), ---------------- Start ----------------\n");
IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);
/* Enter Configuration */
outb(chips[i].entr1, cfg_base);
......@@ -615,13 +618,13 @@ static int ali_ircc_read_dongle_id (int i, chipio_t *info)
outb(0xf0, cfg_base);
reg = inb(cfg_base+1);
dongle_id = ((reg>>6)&0x02) | ((reg>>5)&0x01);
IRDA_DEBUG(2, __FUNCTION__ "(), probing dongle_id=%d, dongle_types=%s\n",
IRDA_DEBUG(2, "%s(), probing dongle_id=%d, dongle_types=%s\n", __FUNCTION__,
dongle_id, dongle_types[dongle_id]);
/* Exit configuration */
outb(0xbb, cfg_base);
IRDA_DEBUG(2, __FUNCTION__ "(), ----------------- End ------------------\n");
IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__);
return dongle_id;
}
......@@ -637,7 +640,7 @@ static void ali_ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
struct net_device *dev = (struct net_device *) dev_id;
struct ali_ircc_cb *self;
IRDA_DEBUG(2, __FUNCTION__ "(), ---------------- Start ----------------\n");
IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);
if (!dev) {
WARNING("%s: irq %d for unknown device.\n", driver_name, irq);
......@@ -656,7 +659,7 @@ static void ali_ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
spin_unlock(&self->lock);
IRDA_DEBUG(2, __FUNCTION__ "(), ----------------- End ------------------\n");
IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__);
}
/*
* Function ali_ircc_fir_interrupt(irq, struct ali_ircc_cb *self, regs)
......@@ -669,7 +672,7 @@ static void ali_ircc_fir_interrupt(int irq, struct ali_ircc_cb *self, struct pt_
__u8 eir, OldMessageCount;
int iobase, tmp;
IRDA_DEBUG(1, __FUNCTION__ "(), ---------------- Start ----------------\n");
IRDA_DEBUG(1, "%s(), ---------------- Start ----------------\n", __FUNCTION__);
iobase = self->io.fir_base;
......@@ -682,10 +685,10 @@ static void ali_ircc_fir_interrupt(int irq, struct ali_ircc_cb *self, struct pt_
//self->ier = inb(iobase+FIR_IER); 2000/12/1 04:32PM
eir = self->InterruptID & self->ier; /* Mask out the interesting ones */
IRDA_DEBUG(1, __FUNCTION__ "(), self->InterruptID = %x\n",self->InterruptID);
IRDA_DEBUG(1, __FUNCTION__ "(), self->LineStatus = %x\n",self->LineStatus);
IRDA_DEBUG(1, __FUNCTION__ "(), self->ier = %x\n",self->ier);
IRDA_DEBUG(1, __FUNCTION__ "(), eir = %x\n",eir);
IRDA_DEBUG(1, "%s(), self->InterruptID = %x\n", __FUNCTION__,self->InterruptID);
IRDA_DEBUG(1, "%s(), self->LineStatus = %x\n", __FUNCTION__,self->LineStatus);
IRDA_DEBUG(1, "%s(), self->ier = %x\n", __FUNCTION__,self->ier);
IRDA_DEBUG(1, "%s(), eir = %x\n", __FUNCTION__,eir);
/* Disable interrupts */
SetCOMInterrupts(self, FALSE);
......@@ -696,7 +699,7 @@ static void ali_ircc_fir_interrupt(int irq, struct ali_ircc_cb *self, struct pt_
{
if (self->io.direction == IO_XMIT) /* TX */
{
IRDA_DEBUG(1, __FUNCTION__ "(), ******* IIR_EOM (Tx) *******\n");
IRDA_DEBUG(1, "%s(), ******* IIR_EOM (Tx) *******\n", __FUNCTION__);
if(ali_ircc_dma_xmit_complete(self))
{
......@@ -715,23 +718,23 @@ static void ali_ircc_fir_interrupt(int irq, struct ali_ircc_cb *self, struct pt_
}
else /* RX */
{
IRDA_DEBUG(1, __FUNCTION__ "(), ******* IIR_EOM (Rx) *******\n");
IRDA_DEBUG(1, "%s(), ******* IIR_EOM (Rx) *******\n", __FUNCTION__);
if(OldMessageCount > ((self->LineStatus+1) & 0x07))
{
self->rcvFramesOverflow = TRUE;
IRDA_DEBUG(1, __FUNCTION__ "(), ******* self->rcvFramesOverflow = TRUE ******** \n");
IRDA_DEBUG(1, "%s(), ******* self->rcvFramesOverflow = TRUE ******** \n", __FUNCTION__);
}
if (ali_ircc_dma_receive_complete(self))
{
IRDA_DEBUG(1, __FUNCTION__ "(), ******* receive complete ******** \n");
IRDA_DEBUG(1, "%s(), ******* receive complete ******** \n", __FUNCTION__);
self->ier = IER_EOM;
}
else
{
IRDA_DEBUG(1, __FUNCTION__ "(), ******* Not receive complete ******** \n");
IRDA_DEBUG(1, "%s(), ******* Not receive complete ******** \n", __FUNCTION__);
self->ier = IER_EOM | IER_TIMER;
}
......@@ -744,7 +747,7 @@ static void ali_ircc_fir_interrupt(int irq, struct ali_ircc_cb *self, struct pt_
if(OldMessageCount > ((self->LineStatus+1) & 0x07))
{
self->rcvFramesOverflow = TRUE;
IRDA_DEBUG(1, __FUNCTION__ "(), ******* self->rcvFramesOverflow = TRUE ******* \n");
IRDA_DEBUG(1, "%s(), ******* self->rcvFramesOverflow = TRUE ******* \n", __FUNCTION__);
}
/* Disable Timer */
switch_bank(iobase, BANK1);
......@@ -776,7 +779,7 @@ static void ali_ircc_fir_interrupt(int irq, struct ali_ircc_cb *self, struct pt_
/* Restore Interrupt */
SetCOMInterrupts(self, TRUE);
IRDA_DEBUG(1, __FUNCTION__ "(), ----------------- End ---------------\n");
IRDA_DEBUG(1, "%s(), ----------------- End ---------------\n", __FUNCTION__);
}
/*
......@@ -790,7 +793,7 @@ static void ali_ircc_sir_interrupt(int irq, struct ali_ircc_cb *self, struct pt_
int iobase;
int iir, lsr;
IRDA_DEBUG(2, __FUNCTION__ "(), ---------------- Start ----------------\n");
IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);
iobase = self->io.sir_base;
......@@ -799,14 +802,13 @@ static void ali_ircc_sir_interrupt(int irq, struct ali_ircc_cb *self, struct pt_
/* Clear interrupt */
lsr = inb(iobase+UART_LSR);
IRDA_DEBUG(4, __FUNCTION__
"(), iir=%02x, lsr=%02x, iobase=%#x\n",
IRDA_DEBUG(4, "%s(), iir=%02x, lsr=%02x, iobase=%#x\n", __FUNCTION__,
iir, lsr, iobase);
switch (iir)
{
case UART_IIR_RLSI:
IRDA_DEBUG(2, __FUNCTION__ "(), RLSI\n");
IRDA_DEBUG(2, "%s(), RLSI\n", __FUNCTION__);
break;
case UART_IIR_RDI:
/* Receive interrupt */
......@@ -820,14 +822,14 @@ static void ali_ircc_sir_interrupt(int irq, struct ali_ircc_cb *self, struct pt_
}
break;
default:
IRDA_DEBUG(0, __FUNCTION__ "(), unhandled IIR=%#x\n", iir);
IRDA_DEBUG(0, "%s(), unhandled IIR=%#x\n", __FUNCTION__, iir);
break;
}
}
IRDA_DEBUG(2, __FUNCTION__ "(), ----------------- End ------------------\n");
IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__);
}
......@@ -842,7 +844,7 @@ static void ali_ircc_sir_receive(struct ali_ircc_cb *self)
int boguscount = 0;
int iobase;
IRDA_DEBUG(2, __FUNCTION__ "(), ---------------- Start ----------------\n");
IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);
ASSERT(self != NULL, return;);
iobase = self->io.sir_base;
......@@ -857,7 +859,7 @@ static void ali_ircc_sir_receive(struct ali_ircc_cb *self)
/* Make sure we don't stay here to long */
if (boguscount++ > 32) {
IRDA_DEBUG(2,__FUNCTION__ "(), breaking!\n");
IRDA_DEBUG(2,"%s(), breaking!\n", __FUNCTION__);
break;
}
} while (inb(iobase+UART_LSR) & UART_LSR_DR);
......@@ -937,6 +939,9 @@ static void ali_ircc_change_speed(struct ali_ircc_cb *self, __u32 baud)
IRDA_DEBUG(2, __FUNCTION__ "(), setting speed = %d \n", baud);
/* This function *must* be called with irq off and spin-lock.
* - Jean II */
iobase = self->io.fir_base;
SetCOMInterrupts(self, FALSE); // 2000/11/24 11:43AM
......@@ -1084,7 +1089,6 @@ static void ali_ircc_change_dongle_speed(struct ali_ircc_cb *priv, int speed)
struct ali_ircc_cb *self = (struct ali_ircc_cb *) priv;
int iobase,dongle_id;
unsigned long flags;
int tmp = 0;
IRDA_DEBUG(1, __FUNCTION__ "(), ---------------- Start ----------------\n");
......@@ -1092,8 +1096,7 @@ static void ali_ircc_change_dongle_speed(struct ali_ircc_cb *priv, int speed)
iobase = self->io.fir_base; /* or iobase = self->io.sir_base; */
dongle_id = self->io.dongle_id;
save_flags(flags);
cli();
/* We are already locked, no need to do it again */
IRDA_DEBUG(1, __FUNCTION__ "(), Set Speed for %s , Speed = %d\n", dongle_types[dongle_id], speed);
......@@ -1259,8 +1262,6 @@ static void ali_ircc_change_dongle_speed(struct ali_ircc_cb *priv, int speed)
switch_bank(iobase, BANK0);
restore_flags(flags);
IRDA_DEBUG(1, __FUNCTION__ "(), ----------------- End ------------------\n");
}
......@@ -1440,20 +1441,26 @@ static int ali_ircc_fir_hard_xmit(struct sk_buff *skb, struct net_device *dev)
netif_stop_queue(dev);
/* Make sure tests *& speed change are atomic */
spin_lock_irqsave(&self->lock, flags);
/* Note : you should make sure that speed changes are not going
* to corrupt any outgoing frame. Look at nsc-ircc for the gory
* details - Jean II */
/* Check if we need to change the speed */
speed = irda_get_next_speed(skb);
if ((speed != self->io.speed) && (speed != -1)) {
/* Check for empty frame */
if (!skb->len) {
ali_ircc_change_speed(self, speed);
spin_unlock_irqrestore(&self->lock, flags);
dev_kfree_skb(skb);
return 0;
} else
self->new_speed = speed;
}
spin_lock_irqsave(&self->lock, flags);
/* Register and copy this frame to DMA memory */
self->tx_fifo.queue[self->tx_fifo.free].start = self->tx_fifo.tail;
self->tx_fifo.queue[self->tx_fifo.free].len = skb->len;
......@@ -1651,7 +1658,7 @@ static int ali_ircc_dma_xmit_complete(struct ali_ircc_cb *self)
if((inb(iobase+FIR_LSR) & LSR_FRAME_ABORT) == LSR_FRAME_ABORT)
{
ERROR(__FUNCTION__ "(), ********* LSR_FRAME_ABORT *********\n");
ERROR("%s(), ********* LSR_FRAME_ABORT *********\n", __FUNCTION__);
self->stats.tx_errors++;
self->stats.tx_fifo_errors++;
}
......@@ -1898,8 +1905,8 @@ static int ali_ircc_dma_receive_complete(struct ali_ircc_cb *self)
skb = dev_alloc_skb(len+1);
if (skb == NULL)
{
WARNING(__FUNCTION__ "(), memory squeeze, "
"dropping frame.\n");
WARNING("%s(), memory squeeze, "
"dropping frame.\n", __FUNCTION__);
self->stats.rx_dropped++;
return FALSE;
......@@ -1957,20 +1964,26 @@ static int ali_ircc_sir_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->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 */
speed = irda_get_next_speed(skb);
if ((speed != self->io.speed) && (speed != -1)) {
/* Check for empty frame */
if (!skb->len) {
ali_ircc_change_speed(self, speed);
spin_unlock_irqrestore(&self->lock, flags);
dev_kfree_skb(skb);
return 0;
} else
self->new_speed = speed;
}
spin_lock_irqsave(&self->lock, flags);
/* Init tx buffer */
self->tx_buff.data = self->tx_buff.head;
......@@ -2016,10 +2029,6 @@ static int ali_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
/* Disable interrupts & save flags */
save_flags(flags);
cli();
switch (cmd) {
case SIOCSBANDWIDTH: /* Set bandwidth */
IRDA_DEBUG(1, __FUNCTION__ "(), SIOCSBANDWIDTH\n");
......@@ -2031,7 +2040,9 @@ static int ali_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
if (!in_interrupt() && !capable(CAP_NET_ADMIN))
return -EPERM;
spin_lock_irqsave(&self->lock, flags);
ali_ircc_change_speed(self, irq->ifr_baudrate);
spin_unlock_irqrestore(&self->lock, flags);
break;
case SIOCSMEDIABUSY: /* Set media busy */
IRDA_DEBUG(1, __FUNCTION__ "(), SIOCSMEDIABUSY\n");
......@@ -2041,14 +2052,13 @@ static int ali_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
break;
case SIOCGRECEIVING: /* Check if we are receiving right now */
IRDA_DEBUG(2, __FUNCTION__ "(), SIOCGRECEIVING\n");
/* This is protected */
irq->ifr_receiving = ali_ircc_is_receiving(self);
break;
default:
ret = -EOPNOTSUPP;
}
restore_flags(flags);
IRDA_DEBUG(2, __FUNCTION__ "(), ----------------- End ------------------\n");
return ret;
......@@ -2219,19 +2229,16 @@ static void SetCOMInterrupts(struct ali_ircc_cb *self , unsigned char enable)
static void SIR2FIR(int iobase)
{
//unsigned char tmp;
unsigned long flags;
IRDA_DEBUG(1, __FUNCTION__ "(), ---------------- Start ----------------\n");
save_flags(flags);
cli();
/* Already protected (change_speed() or setup()), no need to lock.
* Jean II */
outb(0x28, iobase+UART_MCR);
outb(0x68, iobase+UART_MCR);
outb(0x88, iobase+UART_MCR);
restore_flags(flags);
outb(0x60, iobase+FIR_MCR); /* Master Reset */
outb(0x20, iobase+FIR_MCR); /* Master Interrupt Enable */
......@@ -2245,12 +2252,11 @@ static void SIR2FIR(int iobase)
static void FIR2SIR(int iobase)
{
unsigned char val;
unsigned long flags;
IRDA_DEBUG(1, __FUNCTION__ "(), ---------------- Start ----------------\n");
save_flags(flags);
cli();
/* Already protected (change_speed() or setup()), no need to lock.
* Jean II */
outb(0x20, iobase+FIR_MCR); /* IRQ to low */
outb(0x00, iobase+UART_IER);
......@@ -2263,8 +2269,6 @@ static void FIR2SIR(int iobase)
val = inb(iobase+UART_LSR);
val = inb(iobase+UART_MSR);
restore_flags(flags);
IRDA_DEBUG(1, __FUNCTION__ "(), ----------------- End ------------------\n");
}
......
......@@ -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
......
......@@ -124,7 +124,7 @@ static void __exit irport_cleanup(void)
{
int i;
IRDA_DEBUG( 4, __FUNCTION__ "()\n");
IRDA_DEBUG( 4, "%s()\n", __FUNCTION__);
for (i=0; i < 4; i++) {
if (dev_self[i])
......@@ -140,15 +140,15 @@ irport_open(int i, unsigned int iobase, unsigned int irq)
void *ret;
int err;
IRDA_DEBUG(0, __FUNCTION__ "()\n");
IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
/*
* Allocate new instance of the driver
*/
self = kmalloc(sizeof(struct irport_cb), GFP_KERNEL);
if (!self) {
ERROR(__FUNCTION__ "(), can't allocate memory for "
"control block!\n");
ERROR("%s(), can't allocate memory for "
"control block!\n", __FUNCTION__);
return NULL;
}
memset(self, 0, sizeof(struct irport_cb));
......@@ -168,8 +168,8 @@ irport_open(int i, unsigned int iobase, unsigned int irq)
/* Lock the port that we need */
ret = request_region(self->io.sir_base, self->io.sir_ext, driver_name);
if (!ret) {
IRDA_DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
self->io.sir_base);
IRDA_DEBUG(0, "%s(), can't get iobase of 0x%03x\n",
__FUNCTION__, self->io.sir_base);
return NULL;
}
......@@ -212,7 +212,7 @@ irport_open(int i, unsigned int iobase, unsigned int irq)
self->mode = IRDA_IRLAP;
if (!(dev = dev_alloc("irda%d", &err))) {
ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
ERROR("%s(), dev_alloc() failed!\n", __FUNCTION__);
return NULL;
}
self->netdev = dev;
......@@ -240,7 +240,7 @@ irport_open(int i, unsigned int iobase, unsigned int irq)
err = register_netdevice(dev);
rtnl_unlock();
if (err) {
ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
return NULL;
}
MESSAGE("IrDA: Registered device %s\n", dev->name);
......@@ -265,8 +265,8 @@ int irport_close(struct irport_cb *self)
}
/* Release the IO-port that this driver is using */
IRDA_DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n",
self->io.sir_base);
IRDA_DEBUG(0 , "%s(), Releasing Region %03x\n",
__FUNCTION__, self->io.sir_base);
release_region(self->io.sir_base, self->io.sir_ext);
if (self->tx_buff.head)
......@@ -284,14 +284,13 @@ int irport_close(struct irport_cb *self)
void irport_start(struct irport_cb *self)
{
unsigned long flags;
int iobase;
iobase = self->io.sir_base;
irport_stop(self);
spin_lock_irqsave(&self->lock, flags);
/* We can't lock, we may be called from a FIR driver - Jean II */
/* Initialize UART */
outb(UART_LCR_WLEN8, iobase+UART_LCR); /* Reset DLAB */
......@@ -299,26 +298,21 @@ void irport_start(struct irport_cb *self)
/* Turn on interrups */
outb(UART_IER_RLSI | UART_IER_RDI |UART_IER_THRI, iobase+UART_IER);
spin_unlock_irqrestore(&self->lock, flags);
}
void irport_stop(struct irport_cb *self)
{
unsigned long flags;
int iobase;
iobase = self->io.sir_base;
spin_lock_irqsave(&self->lock, flags);
/* We can't lock, we may be called from a FIR driver - Jean II */
/* Reset UART */
outb(0, iobase+UART_MCR);
/* Turn off interrupts */
outb(0, iobase+UART_IER);
spin_unlock_irqrestore(&self->lock, flags);
}
/*
......@@ -329,7 +323,7 @@ void irport_stop(struct irport_cb *self)
*/
int irport_probe(int iobase)
{
IRDA_DEBUG(4, __FUNCTION__ "(), iobase=%#x\n", iobase);
IRDA_DEBUG(4, "%s(), iobase=%#x\n", __FUNCTION__, iobase);
return 0;
}
......@@ -339,27 +333,28 @@ int irport_probe(int iobase)
*
* Set speed of IrDA port to specified baudrate
*
* This function should be called with irq off and spin-lock.
*/
void irport_change_speed(void *priv, __u32 speed)
{
struct irport_cb *self = (struct irport_cb *) priv;
unsigned long flags;
int iobase;
int fcr; /* FIFO control reg */
int lcr; /* Line control reg */
int divisor;
IRDA_DEBUG(0, __FUNCTION__ "(), Setting speed to: %d\n", speed);
ASSERT(self != NULL, return;);
IRDA_DEBUG(1, "%s(), Setting speed to: %d - iobase=%#x\n",
__FUNCTION__, speed, self->io.sir_base);
/* We can't lock, we may be called from a FIR driver - Jean II */
iobase = self->io.sir_base;
/* Update accounting for new speed */
self->io.speed = speed;
spin_lock_irqsave(&self->lock, flags);
/* Turn off interrupts */
outb(0, iobase+UART_IER);
......@@ -387,9 +382,9 @@ void irport_change_speed(void *priv, __u32 speed)
outb(fcr, iobase+UART_FCR); /* Enable FIFO's */
/* Turn on interrups */
outb(/*UART_IER_RLSI|*/UART_IER_RDI/*|UART_IER_THRI*/, iobase+UART_IER);
spin_unlock_irqrestore(&self->lock, flags);
/* This will generate a fata interrupt storm.
* People calling us will do that properly - Jean II */
//outb(/*UART_IER_RLSI|*/UART_IER_RDI/*|UART_IER_THRI*/, iobase+UART_IER);
}
/*
......@@ -397,19 +392,33 @@ void irport_change_speed(void *priv, __u32 speed)
*
* State machine for changing speed of the device. We do it this way since
* we cannot use schedule_timeout() when we are in interrupt context
*
*/
int __irport_change_speed(struct irda_task *task)
{
struct irport_cb *self;
__u32 speed = (__u32) task->param;
unsigned long flags = 0;
int wasunlocked = 0;
int ret = 0;
IRDA_DEBUG(2, __FUNCTION__ "(), <%ld>\n", jiffies);
IRDA_DEBUG(2, "%s(), <%ld>\n", __FUNCTION__, jiffies);
self = (struct irport_cb *) task->instance;
ASSERT(self != NULL, return -1;);
/* Locking notes : this function may be called from irq context with
* spinlock, via irport_write_wakeup(), or from non-interrupt without
* spinlock (from the task timer). Yuck !
* This is ugly, and unsafe is the spinlock is not already aquired.
* This will be fixed when irda-task get rewritten.
* Jean II */
if (!spin_is_locked(&self->lock)) {
spin_lock_irqsave(&self->lock, flags);
wasunlocked = 1;
}
switch (task->state) {
case IRDA_TASK_INIT:
case IRDA_TASK_WAIT:
......@@ -446,8 +455,7 @@ int __irport_change_speed(struct irda_task *task)
irda_task_next_state(task, IRDA_TASK_CHILD_DONE);
break;
case IRDA_TASK_CHILD_WAIT:
WARNING(__FUNCTION__
"(), changing speed of dongle timed out!\n");
WARNING("%s(), changing speed of dongle timed out!\n", __FUNCTION__);
ret = -1;
break;
case IRDA_TASK_CHILD_DONE:
......@@ -457,11 +465,16 @@ int __irport_change_speed(struct irda_task *task)
irda_task_next_state(task, IRDA_TASK_DONE);
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);
ret = -1;
break;
}
/* Put stuff in the sate we found them - Jean II */
if(wasunlocked) {
spin_unlock_irqrestore(&self->lock, flags);
}
return ret;
}
......@@ -480,7 +493,7 @@ static void irport_write_wakeup(struct irport_cb *self)
ASSERT(self != NULL, return;);
IRDA_DEBUG(4, __FUNCTION__ "()\n");
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
iobase = self->io.sir_base;
......@@ -491,6 +504,9 @@ static void irport_write_wakeup(struct irport_cb *self)
self->tx_buff.data, self->tx_buff.len);
self->tx_buff.data += actual;
self->tx_buff.len -= actual;
/* Turn on transmit finished interrupt. */
outb(UART_IER_THRI, iobase+UART_IER);
} else {
/*
* Now serial buffer is almost free & we can start
......@@ -498,11 +514,12 @@ static void irport_write_wakeup(struct irport_cb *self)
* if we need to change the speed of the hardware
*/
if (self->new_speed) {
IRDA_DEBUG(5, __FUNCTION__ "(), Changing speed!\n");
IRDA_DEBUG(5, "%s(), Changing speed!\n", __FUNCTION__);
irda_task_execute(self, __irport_change_speed,
irport_change_speed_complete,
NULL, (void *) self->new_speed);
self->new_speed = 0;
IRDA_DEBUG(5, "%s(), Speed changed!\n", __FUNCTION__ );
} else {
/* Tell network layer that we want more frames */
netif_wake_queue(self->netdev);
......@@ -538,7 +555,7 @@ static int irport_write(int iobase, int fifo_size, __u8 *buf, int len)
/* Tx FIFO should be empty! */
if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
IRDA_DEBUG(0, __FUNCTION__ "(), failed, fifo not empty!\n");
IRDA_DEBUG(0, "%s(), failed, fifo not empty!\n", __FUNCTION__);
return 0;
}
......@@ -563,7 +580,7 @@ static int irport_change_speed_complete(struct irda_task *task)
{
struct irport_cb *self;
IRDA_DEBUG(0, __FUNCTION__ "()\n");
IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
self = (struct irport_cb *) task->instance;
......@@ -589,13 +606,19 @@ static void irport_timeout(struct net_device *dev)
{
struct irport_cb *self;
int iobase;
unsigned long flags;
self = (struct irport_cb *) dev->priv;
iobase = self->io.sir_base;
WARNING("%s: transmit timed out\n", dev->name);
spin_lock_irqsave(&self->lock, flags);
irport_start(self);
self->change_speed(self->priv, self->io.speed);
/* This will re-enable irqs */
outb(/*UART_IER_RLSI|*/UART_IER_RDI/*|UART_IER_THRI*/, iobase+UART_IER);
spin_unlock_irqrestore(&self->lock, flags);
dev->trans_start = jiffies;
netif_wake_queue(dev);
}
......@@ -614,7 +637,7 @@ int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev)
int iobase;
s32 speed;
IRDA_DEBUG(0, __FUNCTION__ "()\n");
IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
ASSERT(dev != NULL, return 0;);
......@@ -625,22 +648,25 @@ int irport_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->lock, flags);
/* Check if we need to change the speed */
speed = irda_get_next_speed(skb);
if ((speed != self->io.speed) && (speed != -1)) {
/* Check for empty frame */
if (!skb->len) {
/* Better go there already locked - Jean II */
irda_task_execute(self, __irport_change_speed,
irport_change_speed_complete,
NULL, (void *) speed);
spin_unlock_irqrestore(&self->lock, flags);
dev_kfree_skb(skb);
return 0;
} else
self->new_speed = speed;
}
spin_lock_irqsave(&self->lock, flags);
/* Init tx buffer */
self->tx_buff.data = self->tx_buff.head;
......@@ -685,7 +711,7 @@ static void irport_receive(struct irport_cb *self)
/* Make sure we don't stay here to long */
if (boguscount++ > 32) {
IRDA_DEBUG(2,__FUNCTION__ "(), breaking!\n");
IRDA_DEBUG(2,"%s(), breaking!\n", __FUNCTION__);
break;
}
} while (inb(iobase+UART_LSR) & UART_LSR_DR);
......@@ -705,7 +731,7 @@ void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs)
int iir, lsr;
if (!dev) {
WARNING(__FUNCTION__ "() irq %d for unknown device.\n", irq);
WARNING("%s() irq %d for unknown device.\n", __FUNCTION__, irq);
return;
}
self = (struct irport_cb *) dev->priv;
......@@ -719,13 +745,12 @@ void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/* Clear interrupt */
lsr = inb(iobase+UART_LSR);
IRDA_DEBUG(4, __FUNCTION__
"(), iir=%02x, lsr=%02x, iobase=%#x\n",
iir, lsr, iobase);
IRDA_DEBUG(4, "%s(), iir=%02x, lsr=%02x, iobase=%#x\n",
__FUNCTION__, iir, lsr, iobase);
switch (iir) {
case UART_IIR_RLSI:
IRDA_DEBUG(2, __FUNCTION__ "(), RLSI\n");
IRDA_DEBUG(2, "%s(), RLSI\n", __FUNCTION__);
break;
case UART_IIR_RDI:
/* Receive interrupt */
......@@ -737,7 +762,7 @@ void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs)
irport_write_wakeup(self);
break;
default:
IRDA_DEBUG(0, __FUNCTION__ "(), unhandled IIR=%#x\n", iir);
IRDA_DEBUG(0, "%s(), unhandled IIR=%#x\n", __FUNCTION__, iir);
break;
}
......@@ -771,8 +796,9 @@ int irport_net_open(struct net_device *dev)
struct irport_cb *self;
int iobase;
char hwname[16];
unsigned long flags;
IRDA_DEBUG(0, __FUNCTION__ "()\n");
IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
ASSERT(dev != NULL, return -1;);
self = (struct irport_cb *) dev->priv;
......@@ -781,12 +807,14 @@ int irport_net_open(struct net_device *dev)
if (request_irq(self->io.irq, self->interrupt, 0, dev->name,
(void *) dev)) {
IRDA_DEBUG(0, __FUNCTION__ "(), unable to allocate irq=%d\n",
self->io.irq);
IRDA_DEBUG(0, "%s(), unable to allocate irq=%d\n",
__FUNCTION__, self->io.irq);
return -EAGAIN;
}
spin_lock_irqsave(&self->lock, flags);
irport_start(self);
spin_unlock_irqrestore(&self->lock, flags);
/* Give self a hardware name */
......@@ -818,8 +846,9 @@ int irport_net_close(struct net_device *dev)
{
struct irport_cb *self;
int iobase;
unsigned long flags;
IRDA_DEBUG(4, __FUNCTION__ "()\n");
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
ASSERT(dev != NULL, return -1;);
self = (struct irport_cb *) dev->priv;
......@@ -836,7 +865,9 @@ int irport_net_close(struct net_device *dev)
irlap_close(self->irlap);
self->irlap = NULL;
spin_lock_irqsave(&self->lock, flags);
irport_stop(self);
spin_unlock_irqrestore(&self->lock, flags);
free_irq(self->io.irq, dev);
......@@ -860,7 +891,7 @@ void irport_wait_until_sent(struct irport_cb *self)
/* Wait until Tx FIFO is empty */
while (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
IRDA_DEBUG(2, __FUNCTION__ "(), waiting!\n");
IRDA_DEBUG(2, "%s(), waiting!\n", __FUNCTION__);
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(MSECS_TO_JIFFIES(60));
}
......@@ -915,7 +946,7 @@ static int irport_raw_write(struct net_device *dev, __u8 *buf, int len)
/* Tx FIFO should be empty! */
if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
IRDA_DEBUG( 0, __FUNCTION__ "(), failed, fifo not empty!\n");
IRDA_DEBUG( 0, "%s(), failed, fifo not empty!\n", __FUNCTION__);
return -1;
}
......@@ -949,11 +980,7 @@ static int irport_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
ASSERT(self != NULL, return -1;);
IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
/* Disable interrupts & save flags */
save_flags(flags);
cli();
IRDA_DEBUG(2, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__, dev->name, cmd);
switch (cmd) {
case SIOCSBANDWIDTH: /* Set bandwidth */
......@@ -979,14 +1006,16 @@ static int irport_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
dongle->write = irport_raw_write;
dongle->set_dtr_rts = irport_set_dtr_rts;
self->dongle = dongle;
/* Now initialize the dongle! */
dongle->issue->open(dongle, &self->qos);
/* Reset dongle */
irda_task_execute(dongle, dongle->issue->reset, NULL, NULL,
NULL);
/* Make dongle available to driver only now to avoid
* race conditions - Jean II */
self->dongle = dongle;
break;
case SIOCSMEDIABUSY: /* Set media busy */
if (!capable(CAP_NET_ADMIN)) {
......@@ -1005,14 +1034,15 @@ static int irport_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
break;
}
/* No real need to lock... */
spin_lock_irqsave(&self->lock, flags);
irport_set_dtr_rts(dev, irq->ifr_dtr, irq->ifr_rts);
spin_unlock_irqrestore(&self->lock, flags);
break;
default:
ret = -EOPNOTSUPP;
}
restore_flags(flags);
return ret;
}
......
......@@ -75,7 +75,9 @@ int __init irtty_init(void)
{
int status;
irtty = hashbin_new( HB_LOCAL);
/* Probably no need to lock here because all operations done in
* open()/close() which are already safe - Jean II */
irtty = hashbin_new( HB_NOLOCK);
if ( irtty == NULL) {
printk( KERN_WARNING "IrDA: Can't allocate irtty hashbin!\n");
return -ENOMEM;
......@@ -118,9 +120,8 @@ static void __exit irtty_cleanup(void)
/* Unregister tty line-discipline */
if ((ret = tty_register_ldisc(N_IRDA, NULL))) {
ERROR(__FUNCTION__
"(), can't unregister line discipline (err = %d)\n",
ret);
ERROR("%s(), can't unregister line discipline (err = %d)\n",
__FUNCTION__, ret);
}
/*
......@@ -163,6 +164,7 @@ static int irtty_open(struct tty_struct *tty)
return -ENOMEM;
}
memset(self, 0, sizeof(struct irtty_cb));
spin_lock_init(&self->lock);
self->tty = tty;
tty->disc_data = self;
......@@ -226,7 +228,7 @@ static int irtty_open(struct tty_struct *tty)
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;
}
......@@ -245,7 +247,7 @@ static int irtty_open(struct tty_struct *tty)
err = register_netdevice(dev);
rtnl_unlock();
if (err) {
ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
return -1;
}
......@@ -266,6 +268,7 @@ static int irtty_open(struct tty_struct *tty)
static void irtty_close(struct tty_struct *tty)
{
struct irtty_cb *self = (struct irtty_cb *) tty->disc_data;
unsigned long flags;
/* First make sure we're connected. */
ASSERT(self != NULL, return;);
......@@ -287,6 +290,11 @@ static void irtty_close(struct tty_struct *tty)
rtnl_unlock();
}
self = hashbin_remove(irtty, (int) self, NULL);
/* Protect access to self->task and self->?x_buff - Jean II */
spin_lock_irqsave(&self->lock, flags);
/* Remove speed changing task if any */
if (self->task)
irda_task_delete(self->task);
......@@ -294,13 +302,12 @@ static void irtty_close(struct tty_struct *tty)
self->tty = NULL;
self->magic = 0;
self = hashbin_remove(irtty, (int) self, NULL);
if (self->tx_buff.head)
kfree(self->tx_buff.head);
if (self->rx_buff.head)
kfree(self->rx_buff.head);
spin_unlock_irqrestore(&self->lock, flags);
kfree(self);
......@@ -326,6 +333,7 @@ static void irtty_stop_receiver(struct irtty_cb *self, int stop)
else
cflag |= CREAD;
/* This is unsafe, but currently under discussion - Jean II */
self->tty->termios->c_cflag = cflag;
self->tty->driver.set_termios(self->tty, &old_termios);
}
......@@ -378,6 +386,7 @@ static void __irtty_change_speed(struct irtty_cb *self, __u32 speed)
break;
}
/* This is unsafe, but currently under discussion - Jean II */
self->tty->termios->c_cflag = cflag;
self->tty->driver.set_termios(self->tty, &old_termios);
......@@ -393,6 +402,7 @@ static void __irtty_change_speed(struct irtty_cb *self, __u32 speed)
static int irtty_change_speed(struct irda_task *task)
{
struct irtty_cb *self;
unsigned long flags;
__u32 speed = (__u32) task->param;
int ret = 0;
......@@ -401,12 +411,17 @@ static int irtty_change_speed(struct irda_task *task)
self = (struct irtty_cb *) task->instance;
ASSERT(self != NULL, return -1;);
/* Protect access to self->task - Jean II */
spin_lock_irqsave(&self->lock, flags);
/* Check if busy */
if (self->task && self->task != task) {
IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n");
spin_unlock_irqrestore(&self->lock, flags);
return MSECS_TO_JIFFIES(10);
} else
self->task = task;
spin_unlock_irqrestore(&self->lock, flags);
switch (task->state) {
case IRDA_TASK_INIT:
......@@ -451,8 +466,7 @@ static int irtty_change_speed(struct irda_task *task)
irda_task_next_state(task, IRDA_TASK_CHILD_DONE);
break;
case IRDA_TASK_CHILD_WAIT:
WARNING(__FUNCTION__
"(), changing speed of dongle timed out!\n");
WARNING("%s(), changing speed of dongle timed out!\n", __FUNCTION__);
ret = -1;
break;
case IRDA_TASK_CHILD_DONE:
......@@ -463,7 +477,7 @@ static int irtty_change_speed(struct irda_task *task)
self->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->task = NULL;
ret = -1;
......@@ -501,6 +515,7 @@ static int irtty_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
switch (cmd) {
case TCGETS:
case TCGETA:
/* Unsure about locking here, to check - Jean II */
return n_tty_ioctl(tty, (struct file *) file, cmd,
(unsigned long) arg);
break;
......@@ -516,15 +531,16 @@ static int irtty_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
dongle->write = irtty_raw_write;
dongle->set_dtr_rts = irtty_set_dtr_rts;
/* Bind dongle */
self->dongle = dongle;
/* Now initialize the dongle! */
dongle->issue->open(dongle, &self->qos);
/* Reset dongle */
irda_task_execute(dongle, dongle->issue->reset, NULL, NULL,
NULL);
/* Make dongle available to driver only now to avoid
* race conditions - Jean II */
self->dongle = dongle;
break;
case IRTTY_IOCGET:
ASSERT(self->netdev != NULL, return -1;);
......@@ -559,6 +575,9 @@ static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
return;
}
// Are we in interrupt context ? What locking is done ? - Jean II
//spin_lock_irqsave(&self->lock, flags);
/* Read the characters out of the buffer */
while (count--) {
/*
......@@ -589,6 +608,7 @@ static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
break;
}
}
//spin_unlock_irqrestore(&self->lock, flags);
}
/*
......@@ -626,11 +646,13 @@ static int irtty_hard_xmit(struct sk_buff *skb, struct net_device *dev)
struct irtty_cb *self;
int actual = 0;
__s32 speed;
unsigned long flags;
self = (struct irtty_cb *) dev->priv;
ASSERT(self != NULL, return 0;);
/* Lock transmit buffer */
/* Lock transmit buffer
* this serialise operations, no need to spinlock - Jean II */
netif_stop_queue(dev);
/* Check if we need to change the speed */
......@@ -647,6 +669,9 @@ static int irtty_hard_xmit(struct sk_buff *skb, struct net_device *dev)
self->new_speed = speed;
}
/* Protect access to self->tx_buff - Jean II */
spin_lock_irqsave(&self->lock, flags);
/* Init tx buffer*/
self->tx_buff.data = self->tx_buff.head;
......@@ -667,6 +692,8 @@ static int irtty_hard_xmit(struct sk_buff *skb, struct net_device *dev)
self->tx_buff.data += actual;
self->tx_buff.len -= actual;
spin_unlock_irqrestore(&self->lock, flags);
dev_kfree_skb(skb);
return 0;
......@@ -695,6 +722,7 @@ static void irtty_write_wakeup(struct tty_struct *tty)
{
struct irtty_cb *self = (struct irtty_cb *) tty->disc_data;
int actual = 0;
unsigned long flags;
/*
* First make sure we're connected.
......@@ -702,6 +730,11 @@ static void irtty_write_wakeup(struct tty_struct *tty)
ASSERT(self != NULL, return;);
ASSERT(self->magic == IRTTY_MAGIC, return;);
/* Protected via netif_stop_queue(dev); - Jean II */
/* Protect access to self->tx_buff - Jean II */
spin_lock_irqsave(&self->lock, flags);
/* Finished with frame? */
if (self->tx_buff.len > 0) {
/* Write data left in transmit buffer */
......@@ -710,6 +743,7 @@ static void irtty_write_wakeup(struct tty_struct *tty)
self->tx_buff.data += actual;
self->tx_buff.len -= actual;
spin_unlock_irqrestore(&self->lock, flags);
} else {
/*
* Now serial buffer is almost free & we can start
......@@ -721,6 +755,9 @@ static void irtty_write_wakeup(struct tty_struct *tty)
tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
/* Don't change speed with irq off */
spin_unlock_irqrestore(&self->lock, flags);
if (self->new_speed) {
IRDA_DEBUG(5, __FUNCTION__ "(), Changing speed!\n");
irda_task_execute(self, irtty_change_speed,
......@@ -755,12 +792,17 @@ static int irtty_set_dtr_rts(struct net_device *dev, int dtr, int rts)
{
struct irtty_cb *self;
struct tty_struct *tty;
//unsigned long flags;
mm_segment_t fs;
int arg = 0;
self = (struct irtty_cb *) dev->priv;
tty = self->tty;
/* Was protected in ioctl handler, but the serial driver doesn't
* like it. This may need to change. - Jean II */
//spin_lock_irqsave(&self->lock, flags);
#ifdef TIOCM_OUT2 /* Not defined for ARM */
arg = TIOCM_OUT2;
#endif
......@@ -780,11 +822,14 @@ static int irtty_set_dtr_rts(struct net_device *dev, int dtr, int rts)
fs = get_fs();
set_fs(get_ds());
/* This is probably unsafe, but currently under discussion - Jean II */
if (tty->driver.ioctl(tty, NULL, TIOCMSET, (unsigned long) &arg)) {
IRDA_DEBUG(2, __FUNCTION__ "(), error doing ioctl!\n");
}
set_fs(fs);
//spin_unlock_irqrestore(&self->lock, flags);
return 0;
}
......@@ -799,6 +844,7 @@ static int irtty_set_dtr_rts(struct net_device *dev, int dtr, int rts)
int irtty_set_mode(struct net_device *dev, int mode)
{
struct irtty_cb *self;
unsigned long flags;
self = (struct irtty_cb *) dev->priv;
......@@ -806,6 +852,9 @@ int irtty_set_mode(struct net_device *dev, int mode)
IRDA_DEBUG(2, __FUNCTION__ "(), mode=%s\n", infrared_mode[mode]);
/* Protect access to self->rx_buff - Jean II */
spin_lock_irqsave(&self->lock, flags);
/* save status for driver */
self->mode = mode;
......@@ -814,6 +863,8 @@ int irtty_set_mode(struct net_device *dev, int mode)
self->rx_buff.len = 0;
self->rx_buff.state = OUTSIDE_FRAME;
spin_unlock_irqrestore(&self->lock, flags);
return 0;
}
......@@ -955,7 +1006,6 @@ static int irtty_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
struct if_irda_req *irq = (struct if_irda_req *) rq;
struct irtty_cb *self;
dongle_t *dongle;
unsigned long flags;
int ret = 0;
ASSERT(dev != NULL, return -1;);
......@@ -971,8 +1021,7 @@ static int irtty_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
* irda_device_dongle_init() can't be locked.
* irda_task_execute() doesn't need to be locked (but
* irtty_change_speed() should protect itself).
* As this driver doesn't have spinlock protection, keep
* old fashion locking :-(
* Other calls protect themselves.
* Jean II
*/
......@@ -1025,20 +1074,14 @@ static int irtty_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
if (!capable(CAP_NET_ADMIN))
ret = -EPERM;
else {
save_flags(flags);
cli();
irtty_set_dtr_rts(dev, irq->ifr_dtr, irq->ifr_rts);
restore_flags(flags);
}
break;
case SIOCSMODE:
if (!capable(CAP_NET_ADMIN))
ret = -EPERM;
else {
save_flags(flags);
cli();
irtty_set_mode(dev, irq->ifr_mode);
restore_flags(flags);
}
break;
default:
......
......@@ -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;
......
......@@ -161,7 +161,7 @@ int __init nsc_ircc_init(void)
/* Probe for all the NSC chipsets we know about */
for (chip=chips; chip->name ; chip++) {
IRDA_DEBUG(2, __FUNCTION__"(), Probing for %s ...\n",
IRDA_DEBUG(2, "%s(), Probing for %s ...\n", __FUNCTION__,
chip->name);
/* Try all config registers for this chip */
......@@ -179,8 +179,7 @@ int __init nsc_ircc_init(void)
/* Read index register */
reg = inb(cfg_base);
if (reg == 0xff) {
IRDA_DEBUG(2, __FUNCTION__
"() no chip at 0x%03x\n", cfg_base);
IRDA_DEBUG(2, "%s() no chip at 0x%03x\n", __FUNCTION__, cfg_base);
continue;
}
......@@ -188,9 +187,8 @@ int __init nsc_ircc_init(void)
outb(chip->cid_index, cfg_base);
id = inb(cfg_base+1);
if ((id & chip->cid_mask) == chip->cid_value) {
IRDA_DEBUG(2, __FUNCTION__
"() Found %s chip, revision=%d\n",
chip->name, id & ~chip->cid_mask);
IRDA_DEBUG(2, "%s() Found %s chip, revision=%d\n",
__FUNCTION__, chip->name, id & ~chip->cid_mask);
/*
* If the user supplies the base address, then
* we init the chip, if not we probe the values
......@@ -205,8 +203,7 @@ int __init nsc_ircc_init(void)
ret = 0;
i++;
} else {
IRDA_DEBUG(2, __FUNCTION__
"(), Wrong chip id=0x%02x\n", id);
IRDA_DEBUG(2, "%s(), Wrong chip id=0x%02x\n", __FUNCTION__, id);
}
}
......@@ -247,7 +244,7 @@ static int __init nsc_ircc_open(int i, chipio_t *info)
void *ret;
int err;
IRDA_DEBUG(2, __FUNCTION__ "()\n");
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
MESSAGE("%s, Found chip at base=0x%03x\n", driver_name,
info->cfg_base);
......@@ -260,8 +257,8 @@ static int __init nsc_ircc_open(int i, chipio_t *info)
/* Allocate new instance of the driver */
self = kmalloc(sizeof(struct nsc_ircc_cb), GFP_KERNEL);
if (self == NULL) {
ERROR(__FUNCTION__ "(), can't allocate memory for "
"control block!\n");
ERROR("%s(), can't allocate memory for "
"control block!\n", __FUNCTION__);
return -ENOMEM;
}
memset(self, 0, sizeof(struct nsc_ircc_cb));
......@@ -282,8 +279,8 @@ static int __init nsc_ircc_open(int i, chipio_t *info)
/* Reserve the ioports that we need */
ret = request_region(self->io.fir_base, self->io.fir_ext, driver_name);
if (!ret) {
WARNING(__FUNCTION__ "(), can't get iobase of 0x%03x\n",
self->io.fir_base);
WARNING("%s(), can't get iobase of 0x%03x\n",
__FUNCTION__, self->io.fir_base);
dev_self[i] = NULL;
kfree(self);
return -ENODEV;
......@@ -333,7 +330,7 @@ static int __init nsc_ircc_open(int i, chipio_t *info)
self->tx_fifo.tail = self->tx_buff.head;
if (!(dev = dev_alloc("irda%d", &err))) {
ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
ERROR("%s(), dev_alloc() failed!\n", __FUNCTION__);
return -ENOMEM;
}
......@@ -352,7 +349,7 @@ static int __init nsc_ircc_open(int i, chipio_t *info)
err = register_netdevice(dev);
rtnl_unlock();
if (err) {
ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
return -1;
}
MESSAGE("IrDA: Registered device %s\n", dev->name);
......@@ -388,7 +385,7 @@ static int __exit nsc_ircc_close(struct nsc_ircc_cb *self)
{
int iobase;
IRDA_DEBUG(4, __FUNCTION__ "()\n");
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
ASSERT(self != NULL, return -1;);
......@@ -402,8 +399,8 @@ static int __exit nsc_ircc_close(struct nsc_ircc_cb *self)
}
/* Release the PORT that this driver is using */
IRDA_DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n",
self->io.fir_base);
IRDA_DEBUG(4, "%s(), Releasing Region %03x\n",
__FUNCTION__, self->io.fir_base);
release_region(self->io.fir_base, self->io.fir_ext);
if (self->tx_buff.head)
......@@ -439,7 +436,7 @@ static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info)
case 0x2e8: outb(0x15, cfg_base+1); break;
case 0x3f8: outb(0x16, cfg_base+1); break;
case 0x2f8: outb(0x17, cfg_base+1); break;
default: ERROR(__FUNCTION__ "(), invalid base_address");
default: ERROR("%s(), invalid base_address", __FUNCTION__);
}
/* Control Signal Routing Register (CSRT) */
......@@ -451,7 +448,7 @@ static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info)
case 9: temp = 0x05; break;
case 11: temp = 0x06; break;
case 15: temp = 0x07; break;
default: ERROR(__FUNCTION__ "(), invalid irq");
default: ERROR("%s(), invalid irq", __FUNCTION__);
}
outb(1, cfg_base);
......@@ -459,7 +456,7 @@ static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info)
case 0: outb(0x08+temp, cfg_base+1); break;
case 1: outb(0x10+temp, cfg_base+1); break;
case 3: outb(0x18+temp, cfg_base+1); break;
default: ERROR(__FUNCTION__ "(), invalid dma");
default: ERROR("%s(), invalid dma", __FUNCTION__);
}
outb(2, cfg_base); /* Mode Control Register (MCTL) */
......@@ -498,7 +495,7 @@ static int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info)
break;
}
info->sir_base = info->fir_base;
IRDA_DEBUG(2, __FUNCTION__ "(), probing fir_base=0x%03x\n",
IRDA_DEBUG(2, "%s(), probing fir_base=0x%03x\n", __FUNCTION__,
info->fir_base);
/* Read control signals routing register (CSRT) */
......@@ -531,7 +528,7 @@ static int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info)
info->irq = 15;
break;
}
IRDA_DEBUG(2, __FUNCTION__ "(), probing irq=%d\n", info->irq);
IRDA_DEBUG(2, "%s(), probing irq=%d\n", __FUNCTION__, info->irq);
/* Currently we only read Rx DMA but it will also be used for Tx */
switch ((reg >> 3) & 0x03) {
......@@ -548,7 +545,7 @@ static int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info)
info->dma = 3;
break;
}
IRDA_DEBUG(2, __FUNCTION__ "(), probing dma=%d\n", info->dma);
IRDA_DEBUG(2, "%s(), probing dma=%d\n", __FUNCTION__, info->dma);
/* Read mode control register (MCTL) */
outb(CFG_MCTL, cfg_base);
......@@ -694,8 +691,8 @@ static int nsc_ircc_setup(chipio_t *info)
switch_bank(iobase, BANK3);
version = inb(iobase+MID);
IRDA_DEBUG(2, __FUNCTION__ "() Driver %s Found chip version %02x\n",
driver_name, version);
IRDA_DEBUG(2, "%s() Driver %s Found chip version %02x\n",
__FUNCTION__, driver_name, version);
/* Should be 0x2? */
if (0x20 != (version & 0xf0)) {
......@@ -797,39 +794,39 @@ static void nsc_ircc_init_dongle_interface (int iobase, int dongle_id)
switch (dongle_id) {
case 0x00: /* same as */
case 0x01: /* Differential serial interface */
IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
dongle_types[dongle_id]);
IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n",
__FUNCTION__, dongle_types[dongle_id]);
break;
case 0x02: /* same as */
case 0x03: /* Reserved */
IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
dongle_types[dongle_id]);
IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n",
__FUNCTION__, dongle_types[dongle_id]);
break;
case 0x04: /* Sharp RY5HD01 */
break;
case 0x05: /* Reserved, but this is what the Thinkpad reports */
IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
dongle_types[dongle_id]);
IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n",
__FUNCTION__, dongle_types[dongle_id]);
break;
case 0x06: /* Single-ended serial interface */
IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
dongle_types[dongle_id]);
IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n",
__FUNCTION__, dongle_types[dongle_id]);
break;
case 0x07: /* Consumer-IR only */
IRDA_DEBUG(0, __FUNCTION__ "(), %s is not for IrDA mode\n",
dongle_types[dongle_id]);
IRDA_DEBUG(0, "%s(), %s is not for IrDA mode\n",
__FUNCTION__, dongle_types[dongle_id]);
break;
case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */
IRDA_DEBUG(0, __FUNCTION__ "(), %s\n",
dongle_types[dongle_id]);
IRDA_DEBUG(0, "%s(), %s\n",
__FUNCTION__, dongle_types[dongle_id]);
break;
case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */
outb(0x28, iobase+7); /* Set irsl[0-2] as output */
break;
case 0x0A: /* same as */
case 0x0B: /* Reserved */
IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
dongle_types[dongle_id]);
IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n",
__FUNCTION__, dongle_types[dongle_id]);
break;
case 0x0C: /* same as */
case 0x0D: /* HP HSDL-1100/HSDL-2100 */
......@@ -843,15 +840,15 @@ static void nsc_ircc_init_dongle_interface (int iobase, int dongle_id)
outb(0x28, iobase+7); /* Set irsl[0-2] as output */
break;
case 0x0F: /* No dongle connected */
IRDA_DEBUG(0, __FUNCTION__ "(), %s\n",
dongle_types[dongle_id]);
IRDA_DEBUG(0, "%s(), %s\n",
__FUNCTION__, dongle_types[dongle_id]);
switch_bank(iobase, BANK0);
outb(0x62, iobase+MCR);
break;
default:
IRDA_DEBUG(0, __FUNCTION__ "(), invalid dongle_id %#x",
dongle_id);
IRDA_DEBUG(0, "%s(), invalid dongle_id %#x",
__FUNCTION__, dongle_id);
}
/* IRCFG1: IRSL1 and 2 are set to IrDA mode */
......@@ -870,7 +867,6 @@ static void nsc_ircc_init_dongle_interface (int iobase, int dongle_id)
*/
static void nsc_ircc_change_dongle_speed(int iobase, int speed, int dongle_id)
{
unsigned long flags;
__u8 bank;
/* Save current bank */
......@@ -883,31 +879,31 @@ static void nsc_ircc_change_dongle_speed(int iobase, int speed, int dongle_id)
switch (dongle_id) {
case 0x00: /* same as */
case 0x01: /* Differential serial interface */
IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
dongle_types[dongle_id]);
IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n",
__FUNCTION__, dongle_types[dongle_id]);
break;
case 0x02: /* same as */
case 0x03: /* Reserved */
IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
dongle_types[dongle_id]);
IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n",
__FUNCTION__, dongle_types[dongle_id]);
break;
case 0x04: /* Sharp RY5HD01 */
break;
case 0x05: /* Reserved */
IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
dongle_types[dongle_id]);
IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n",
__FUNCTION__, dongle_types[dongle_id]);
break;
case 0x06: /* Single-ended serial interface */
IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
dongle_types[dongle_id]);
IRDA_DEBUG(0, "%s(), %s not defined by irda yet\n",
__FUNCTION__, dongle_types[dongle_id]);
break;
case 0x07: /* Consumer-IR only */
IRDA_DEBUG(0, __FUNCTION__ "(), %s is not for IrDA mode\n",
dongle_types[dongle_id]);
IRDA_DEBUG(0, "%s(), %s is not for IrDA mode\n",
__FUNCTION__, dongle_types[dongle_id]);
break;
case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */
IRDA_DEBUG(0, __FUNCTION__ "(), %s\n",
dongle_types[dongle_id]);
IRDA_DEBUG(0, "%s(), %s\n",
__FUNCTION__, dongle_types[dongle_id]);
outb(0x00, iobase+4);
if (speed > 115200)
outb(0x01, iobase+4);
......@@ -916,11 +912,10 @@ static void nsc_ircc_change_dongle_speed(int iobase, int speed, int dongle_id)
outb(0x01, iobase+4);
if (speed == 4000000) {
save_flags(flags);
cli();
/* There was a cli() there, but we now are already
* under spin_lock_irqsave() - JeanII */
outb(0x81, iobase+4);
outb(0x80, iobase+4);
restore_flags(flags);
} else
outb(0x00, iobase+4);
break;
......@@ -1538,8 +1533,8 @@ static int nsc_ircc_dma_receive_complete(struct nsc_ircc_cb *self, int iobase)
skb = dev_alloc_skb(len+1);
if (skb == NULL) {
WARNING(__FUNCTION__ "(), memory squeeze, "
"dropping frame.\n");
WARNING("%s(), memory squeeze, "
"dropping frame.\n", __FUNCTION__);
self->stats.rx_dropped++;
/* Restore bank register */
......@@ -1960,33 +1955,30 @@ static int nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
/* Disable interrupts & save flags */
save_flags(flags);
cli();
switch (cmd) {
case SIOCSBANDWIDTH: /* Set bandwidth */
if (!capable(CAP_NET_ADMIN)) {
ret = -EPERM;
goto out;
break;
}
spin_lock_irqsave(&self->lock, flags);
nsc_ircc_change_speed(self, irq->ifr_baudrate);
spin_unlock_irqrestore(&self->lock, flags);
break;
case SIOCSMEDIABUSY: /* Set media busy */
if (!capable(CAP_NET_ADMIN)) {
ret = -EPERM;
goto out;
break;
}
irda_device_set_media_busy(self->netdev, TRUE);
break;
case SIOCGRECEIVING: /* Check if we are receiving right now */
/* This is already protected */
irq->ifr_receiving = nsc_ircc_is_receiving(self);
break;
default:
ret = -EOPNOTSUPP;
}
out:
restore_flags(flags);
return ret;
}
......
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -83,13 +83,13 @@ int __init irlmp_init(void)
memset(irlmp, 0, sizeof(struct irlmp_cb));
irlmp->magic = LMP_MAGIC;
spin_lock_init(&irlmp->log_lock);
irlmp->clients = hashbin_new(HB_GLOBAL);
irlmp->services = hashbin_new(HB_GLOBAL);
irlmp->links = hashbin_new(HB_GLOBAL);
irlmp->unconnected_lsaps = hashbin_new(HB_GLOBAL);
irlmp->cachelog = hashbin_new(HB_GLOBAL);
irlmp->clients = hashbin_new(HB_LOCK);
irlmp->services = hashbin_new(HB_LOCK);
irlmp->links = hashbin_new(HB_LOCK);
irlmp->unconnected_lsaps = hashbin_new(HB_LOCK);
irlmp->cachelog = hashbin_new(HB_NOLOCK);
spin_lock_init(&irlmp->cachelog->hb_spinlock);
irlmp->free_lsap_sel = 0x10; /* Reserved 0x00-0x0f */
strcpy(sysctl_devname, "Linux");
......@@ -177,8 +177,8 @@ struct lsap_cb *irlmp_open_lsap(__u8 slsap_sel, notify_t *notify, __u8 pid)
self->lsap_state = LSAP_DISCONNECTED;
/* Insert into queue of unconnected LSAPs */
hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) self, (int) self,
NULL);
hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) self,
(long) self, NULL);
return self;
}
......@@ -238,7 +238,7 @@ void irlmp_close_lsap(struct lsap_cb *self)
LM_LAP_DISCONNECT_REQUEST, NULL);
}
/* Now, remove from the link */
lsap = hashbin_remove(lap->lsaps, (int) self, NULL);
lsap = hashbin_remove(lap->lsaps, (long) self, NULL);
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
lap->cache.valid = FALSE;
#endif
......@@ -246,7 +246,7 @@ void irlmp_close_lsap(struct lsap_cb *self)
self->lap = NULL;
/* Check if we found the LSAP! If not then try the unconnected lsaps */
if (!lsap) {
lsap = hashbin_remove(irlmp->unconnected_lsaps, (int) self,
lsap = hashbin_remove(irlmp->unconnected_lsaps, (long) self,
NULL);
}
if (!lsap) {
......@@ -286,7 +286,7 @@ void irlmp_register_link(struct irlap_cb *irlap, __u32 saddr, notify_t *notify)
lap->magic = LMP_LAP_MAGIC;
lap->saddr = saddr;
lap->daddr = DEV_ADDR_ANY;
lap->lsaps = hashbin_new(HB_GLOBAL);
lap->lsaps = hashbin_new(HB_LOCK);
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
lap->cache.valid = FALSE;
#endif
......@@ -347,7 +347,6 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel,
struct sk_buff *skb = NULL;
struct lap_cb *lap;
struct lsap_cb *lsap;
discovery_t *discovery;
ASSERT(self != NULL, return -EBADR;);
ASSERT(self->magic == LMP_LSAP_MAGIC, return -EBADR;);
......@@ -388,6 +387,10 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel,
* device with the given daddr
*/
if ((!saddr) || (saddr == DEV_ADDR_ANY)) {
discovery_t *discovery;
unsigned long flags;
spin_lock_irqsave(&irlmp->cachelog->hb_spinlock, flags);
if (daddr != DEV_ADDR_ANY)
discovery = hashbin_find(irlmp->cachelog, daddr, NULL);
else {
......@@ -400,8 +403,9 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel,
saddr = discovery->saddr;
daddr = discovery->daddr;
}
spin_unlock_irqrestore(&irlmp->cachelog->hb_spinlock, flags);
}
lap = hashbin_find(irlmp->links, saddr, NULL);
lap = hashbin_lock_find(irlmp->links, saddr, NULL);
if (lap == NULL) {
IRDA_DEBUG(1, __FUNCTION__ "(), Unable to find a usable link!\n");
return -EHOSTUNREACH;
......@@ -411,11 +415,8 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel,
if (lap->daddr == DEV_ADDR_ANY)
lap->daddr = daddr;
else if (lap->daddr != daddr) {
struct lsap_cb *any_lsap;
/* Check if some LSAPs are active on this LAP */
any_lsap = (struct lsap_cb *) hashbin_get_first(lap->lsaps);
if (any_lsap == NULL) {
if (HASHBIN_GET_SIZE(lap->lsaps) == 0) {
/* No active connection, but LAP hasn't been
* disconnected yet (waiting for timeout in LAP).
* Maybe we could give LAP a bit of help in this case.
......@@ -436,14 +437,15 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel,
* Remove LSAP from list of unconnected LSAPs and insert it into the
* list of connected LSAPs for the particular link
*/
lsap = hashbin_remove(irlmp->unconnected_lsaps, (int) self, NULL);
lsap = hashbin_remove(irlmp->unconnected_lsaps, (long) self, NULL);
ASSERT(lsap != NULL, return -1;);
ASSERT(lsap->magic == LMP_LSAP_MAGIC, return -1;);
ASSERT(lsap->lap != NULL, return -1;);
ASSERT(lsap->lap->magic == LMP_LAP_MAGIC, return -1;);
hashbin_insert(self->lap->lsaps, (irda_queue_t *) self, (int) self, NULL);
hashbin_insert(self->lap->lsaps, (irda_queue_t *) self, (long) self,
NULL);
set_bit(0, &self->connected); /* TRUE */
......@@ -574,29 +576,41 @@ void irlmp_connect_confirm(struct lsap_cb *self, struct sk_buff *skb)
struct lsap_cb *irlmp_dup(struct lsap_cb *orig, void *instance)
{
struct lsap_cb *new;
unsigned long flags;
IRDA_DEBUG(1, __FUNCTION__ "()\n");
spin_lock_irqsave(&irlmp->unconnected_lsaps->hb_spinlock, flags);
/* Only allowed to duplicate unconnected LSAP's */
if (!hashbin_find(irlmp->unconnected_lsaps, (int) orig, NULL)) {
if (!hashbin_find(irlmp->unconnected_lsaps, (long) orig, NULL)) {
IRDA_DEBUG(0, __FUNCTION__ "(), unable to find LSAP\n");
spin_unlock_irqrestore(&irlmp->unconnected_lsaps->hb_spinlock,
flags);
return NULL;
}
/* Allocate a new instance */
new = kmalloc(sizeof(struct lsap_cb), GFP_ATOMIC);
if (!new) {
IRDA_DEBUG(0, __FUNCTION__ "(), unable to kmalloc\n");
spin_unlock_irqrestore(&irlmp->unconnected_lsaps->hb_spinlock,
flags);
return NULL;
}
/* Dup */
memcpy(new, orig, sizeof(struct lsap_cb));
new->notify.instance = instance;
/* new->lap = orig->lap; => done in the memcpy() */
/* new->slsap_sel = orig->slsap_sel; => done in the memcpy() */
spin_unlock_irqrestore(&irlmp->unconnected_lsaps->hb_spinlock, flags);
/* Not everything is the same */
new->notify.instance = instance;
init_timer(&new->watchdog_timer);
hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) new, (int) new,
NULL);
hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) new,
(long) new, NULL);
/* Make sure that we invalidate the cache */
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
......@@ -646,7 +660,7 @@ int irlmp_disconnect_request(struct lsap_cb *self, struct sk_buff *userdata)
ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
ASSERT(self->lap->lsaps != NULL, return -1;);
lsap = hashbin_remove(self->lap->lsaps, (int) self, NULL);
lsap = hashbin_remove(self->lap->lsaps, (long) self, NULL);
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
self->lap->cache.valid = FALSE;
#endif
......@@ -655,8 +669,8 @@ int irlmp_disconnect_request(struct lsap_cb *self, struct sk_buff *userdata)
ASSERT(lsap->magic == LMP_LSAP_MAGIC, return -1;);
ASSERT(lsap == self, return -1;);
hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) self, (int) self,
NULL);
hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) self,
(long) self, NULL);
/* Reset some values */
self->dlsap_sel = LSAP_ANY;
......@@ -699,15 +713,15 @@ void irlmp_disconnect_indication(struct lsap_cb *self, LM_REASON reason,
ASSERT(self->lap != NULL, return;);
ASSERT(self->lap->lsaps != NULL, return;);
lsap = hashbin_remove(self->lap->lsaps, (int) self, NULL);
lsap = hashbin_remove(self->lap->lsaps, (long) self, NULL);
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
self->lap->cache.valid = FALSE;
#endif
ASSERT(lsap != NULL, return;);
ASSERT(lsap == self, return;);
hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) lsap, (int) lsap,
NULL);
hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) lsap,
(long) lsap, NULL);
self->dlsap_sel = LSAP_ANY;
self->lap = NULL;
......@@ -886,7 +900,7 @@ void irlmp_check_services(discovery_t *discovery)
*/
while ((service = service_log[i++]) != S_END) {
IRDA_DEBUG( 4, "service=%02x\n", service);
client = hashbin_find(irlmp->registry, service, NULL);
client = hashbin_lock_find(irlmp->registry, service, NULL);
if (entry && entry->discovery_callback) {
IRDA_DEBUG( 4, "discovery_callback!\n");
......@@ -903,6 +917,7 @@ void irlmp_check_services(discovery_t *discovery)
kfree(service_log);
}
#endif
/*
* Function irlmp_notify_client (log)
*
......@@ -930,6 +945,12 @@ irlmp_notify_client(irlmp_client_t *client,
/*
* Now, check all discovered devices (if any), and notify client
* only about the services that the client is interested in
* Note : most often, we will get called immediately following
* a discovery, so the log is not going to expire.
* On the other hand, comming here through irlmp_discovery_request()
* is *very* problematic - Jean II
* Can't use hashbin_find_next(), key is not unique. I'm running
* out of options :-( - Jean II
*/
discovery = (discovery_t *) hashbin_get_first(log);
while (discovery != NULL) {
......@@ -956,6 +977,7 @@ irlmp_notify_client(irlmp_client_t *client,
void irlmp_discovery_confirm(hashbin_t *log, DISCOVERY_MODE mode)
{
irlmp_client_t *client;
irlmp_client_t *client_next;
IRDA_DEBUG(3, __FUNCTION__ "()\n");
......@@ -965,11 +987,12 @@ void irlmp_discovery_confirm(hashbin_t *log, DISCOVERY_MODE mode)
return;
client = (irlmp_client_t *) hashbin_get_first(irlmp->clients);
while (client != NULL) {
while (NULL != hashbin_find_next(irlmp->clients, (long) client, NULL,
(void *) &client_next) ) {
/* Check if we should notify client */
irlmp_notify_client(client, log, mode);
client = (irlmp_client_t *) hashbin_get_next(irlmp->clients);
client = client_next;
}
}
......@@ -987,13 +1010,15 @@ void irlmp_discovery_confirm(hashbin_t *log, DISCOVERY_MODE mode)
void irlmp_discovery_expiry(discovery_t *expiry)
{
irlmp_client_t *client;
irlmp_client_t *client_next;
IRDA_DEBUG(3, __FUNCTION__ "()\n");
ASSERT(expiry != NULL, return;);
client = (irlmp_client_t *) hashbin_get_first(irlmp->clients);
while (client != NULL) {
while (NULL != hashbin_find_next(irlmp->clients, (long) client, NULL,
(void *) &client_next) ) {
/* Check if we should notify client */
if ((client->expir_callback) &&
(client->hint_mask & expiry->hints.word & 0x7f7f))
......@@ -1001,7 +1026,7 @@ void irlmp_discovery_expiry(discovery_t *expiry)
client->priv);
/* Next client */
client = (irlmp_client_t *) hashbin_get_next(irlmp->clients);
client = client_next;
}
}
......@@ -1196,11 +1221,9 @@ void irlmp_status_indication(struct lap_cb *self,
struct lsap_cb *curr;
/* Send status_indication to all LSAPs using this link */
next = (struct lsap_cb *) hashbin_get_first( self->lsaps);
while (next != NULL ) {
curr = next;
next = (struct lsap_cb *) hashbin_get_next(self->lsaps);
curr = (struct lsap_cb *) hashbin_get_first( self->lsaps);
while (NULL != hashbin_find_next(self->lsaps, (long) curr, NULL,
(void *) &next) ) {
ASSERT(curr->magic == LMP_LSAP_MAGIC, return;);
/*
* Inform service user if he has requested it
......@@ -1210,6 +1233,8 @@ void irlmp_status_indication(struct lap_cb *self,
link, lock);
else
IRDA_DEBUG(2, __FUNCTION__ "(), no handler\n");
curr = next;
}
}
......@@ -1245,29 +1270,15 @@ void irlmp_flow_indication(struct lap_cb *self, LOCAL_FLOW flow)
(IRLAP_GET_TX_QUEUE_LEN(self->irlap) < LAP_HIGH_THRESHOLD)) {
/* Try to find the next lsap we should poll. */
next = self->flow_next;
if(next != NULL) {
/* Note that if there is only one LSAP on the LAP
* (most common case), self->flow_next is always NULL,
* so we always avoid this loop. - Jean II */
IRDA_DEBUG(4, __FUNCTION__ "() : searching my LSAP\n");
/* We look again in hashbins, because the lsap
* might have gone away... - Jean II */
curr = (struct lsap_cb *) hashbin_get_first(self->lsaps);
while((curr != NULL ) && (curr != next))
curr = (struct lsap_cb *) hashbin_get_next(self->lsaps);
} else
curr = NULL;
/* If we have no lsap, restart from first one */
if(curr == NULL)
curr = (struct lsap_cb *) hashbin_get_first(self->lsaps);
if(next == NULL)
next = (struct lsap_cb *) hashbin_get_first(self->lsaps);
/* Verify current one and find the next one */
curr = hashbin_find_next(self->lsaps, (long) next, NULL,
(void *) &self->flow_next);
/* Uh-oh... Paranoia */
if(curr == NULL)
break;
/* Next time, we will get the next one (or the first one) */
self->flow_next = (struct lsap_cb *) hashbin_get_next(self->lsaps);
IRDA_DEBUG(4, __FUNCTION__ "() : curr is %p, next was %p and is now %p, still %d to go - queue len = %d\n", curr, next, self->flow_next, lsap_todo, IRLAP_GET_TX_QUEUE_LEN(self->irlap));
/* Inform lsap user that it can send one more packet. */
......@@ -1414,20 +1425,12 @@ __u16 irlmp_service_to_hint(int service)
* Register local service with IrLMP
*
*/
__u32 irlmp_register_service(__u16 hints)
void *irlmp_register_service(__u16 hints)
{
irlmp_service_t *service;
__u32 handle;
IRDA_DEBUG(4, __FUNCTION__ "(), hints = %04x\n", hints);
/* Get a unique handle for this service */
get_random_bytes(&handle, sizeof(handle));
while (hashbin_find(irlmp->services, handle, NULL) || !handle)
get_random_bytes(&handle, sizeof(handle));
irlmp->hints.word |= hints;
/* Make a new registration */
service = kmalloc(sizeof(irlmp_service_t), GFP_ATOMIC);
if (!service) {
......@@ -1435,9 +1438,12 @@ __u32 irlmp_register_service(__u16 hints)
return 0;
}
service->hints = hints;
hashbin_insert(irlmp->services, (irda_queue_t *) service, handle, NULL);
hashbin_insert(irlmp->services, (irda_queue_t *) service,
(long) service, NULL);
return handle;
irlmp->hints.word |= hints;
return (void *)service;
}
/*
......@@ -1447,35 +1453,38 @@ __u32 irlmp_register_service(__u16 hints)
*
* Returns: 0 on success, -1 on error
*/
int irlmp_unregister_service(__u32 handle)
int irlmp_unregister_service(void *handle)
{
irlmp_service_t *service;
unsigned long flags;
IRDA_DEBUG(4, __FUNCTION__ "()\n");
if (!handle)
return -1;
service = hashbin_find(irlmp->services, handle, NULL);
/* Caller may call with invalid handle (it's legal) - Jean II */
service = hashbin_lock_find(irlmp->services, (long) handle, NULL);
if (!service) {
IRDA_DEBUG(1, __FUNCTION__ "(), Unknown service!\n");
return -1;
}
service = hashbin_remove(irlmp->services, handle, NULL);
if (service)
hashbin_remove_this(irlmp->services, (irda_queue_t *) service);
kfree(service);
/* Remove old hint bits */
irlmp->hints.word = 0;
/* Refresh current hint bits */
spin_lock_irqsave(&irlmp->services->hb_spinlock, flags);
service = (irlmp_service_t *) hashbin_get_first(irlmp->services);
while (service) {
irlmp->hints.word |= service->hints;
service = (irlmp_service_t *)hashbin_get_next(irlmp->services);
}
spin_unlock_irqrestore(&irlmp->services->hb_spinlock, flags);
return 0;
}
......@@ -1488,20 +1497,14 @@ int irlmp_unregister_service(__u32 handle)
*
* Returns: handle > 0 on success, 0 on error
*/
__u32 irlmp_register_client(__u16 hint_mask, DISCOVERY_CALLBACK1 disco_clb,
void *irlmp_register_client(__u16 hint_mask, DISCOVERY_CALLBACK1 disco_clb,
DISCOVERY_CALLBACK1 expir_clb, void *priv)
{
irlmp_client_t *client;
__u32 handle;
IRDA_DEBUG(1, __FUNCTION__ "()\n");
ASSERT(irlmp != NULL, return 0;);
/* Get a unique handle for this client */
get_random_bytes(&handle, sizeof(handle));
while (hashbin_find(irlmp->clients, handle, NULL) || !handle)
get_random_bytes(&handle, sizeof(handle));
/* Make a new registration */
client = kmalloc(sizeof(irlmp_client_t), GFP_ATOMIC);
if (!client) {
......@@ -1515,9 +1518,10 @@ __u32 irlmp_register_client(__u16 hint_mask, DISCOVERY_CALLBACK1 disco_clb,
client->expir_callback = expir_clb;
client->priv = priv;
hashbin_insert(irlmp->clients, (irda_queue_t *) client, handle, NULL);
hashbin_insert(irlmp->clients, (irda_queue_t *) client,
(long) client, NULL);
return handle;
return (void *) client;
}
/*
......@@ -1528,7 +1532,7 @@ __u32 irlmp_register_client(__u16 hint_mask, DISCOVERY_CALLBACK1 disco_clb,
*
* Returns: 0 on success, -1 on error
*/
int irlmp_update_client(__u32 handle, __u16 hint_mask,
int irlmp_update_client(void *handle, __u16 hint_mask,
DISCOVERY_CALLBACK1 disco_clb,
DISCOVERY_CALLBACK1 expir_clb, void *priv)
{
......@@ -1537,7 +1541,7 @@ int irlmp_update_client(__u32 handle, __u16 hint_mask,
if (!handle)
return -1;
client = hashbin_find(irlmp->clients, handle, NULL);
client = hashbin_lock_find(irlmp->clients, (long) handle, NULL);
if (!client) {
IRDA_DEBUG(1, __FUNCTION__ "(), Unknown client!\n");
return -1;
......@@ -1557,7 +1561,7 @@ int irlmp_update_client(__u32 handle, __u16 hint_mask,
* Returns: 0 on success, -1 on error
*
*/
int irlmp_unregister_client(__u32 handle)
int irlmp_unregister_client(void *handle)
{
struct irlmp_client *client;
......@@ -1566,15 +1570,15 @@ int irlmp_unregister_client(__u32 handle)
if (!handle)
return -1;
client = hashbin_find(irlmp->clients, handle, NULL);
/* Caller may call with invalid handle (it's legal) - Jean II */
client = hashbin_lock_find(irlmp->clients, (long) handle, NULL);
if (!client) {
IRDA_DEBUG(1, __FUNCTION__ "(), Unknown client!\n");
return -1;
}
IRDA_DEBUG( 4, __FUNCTION__ "(), removing client!\n");
client = hashbin_remove( irlmp->clients, handle, NULL);
if (client)
hashbin_remove_this(irlmp->clients, (irda_queue_t *) client);
kfree(client);
return 0;
......@@ -1589,6 +1593,7 @@ int irlmp_slsap_inuse(__u8 slsap_sel)
{
struct lsap_cb *self;
struct lap_cb *lap;
unsigned long flags;
ASSERT(irlmp != NULL, return TRUE;);
ASSERT(irlmp->magic == LMP_MAGIC, return TRUE;);
......@@ -1611,10 +1616,16 @@ int irlmp_slsap_inuse(__u8 slsap_sel)
* every IrLAP connection and check every LSAP assosiated with each
* the connection.
*/
spin_lock_irqsave(&irlmp->links->hb_spinlock, flags);
lap = (struct lap_cb *) hashbin_get_first(irlmp->links);
while (lap != NULL) {
ASSERT(lap->magic == LMP_LAP_MAGIC, return TRUE;);
/* Careful for priority inversions here !
* All other uses of attrib spinlock are independant of
* the object spinlock, so we are safe. Jean II */
spin_lock(&lap->lsaps->hb_spinlock);
self = (struct lsap_cb *) hashbin_get_first(lap->lsaps);
while (self != NULL) {
ASSERT(self->magic == LMP_LSAP_MAGIC, return TRUE;);
......@@ -1626,8 +1637,11 @@ int irlmp_slsap_inuse(__u8 slsap_sel)
}
self = (struct lsap_cb*) hashbin_get_next(lap->lsaps);
}
spin_unlock(&lap->lsaps->hb_spinlock);
/* Next LAP */
lap = (struct lap_cb *) hashbin_get_next(irlmp->links);
}
spin_unlock_irqrestore(&irlmp->links->hb_spinlock, flags);
return FALSE;
}
......@@ -1736,15 +1750,13 @@ int irlmp_proc_read(char *buf, char **start, off_t offset, int len)
ASSERT(irlmp != NULL, return 0;);
save_flags( flags);
cli();
len = 0;
len += sprintf( buf+len, "Unconnected LSAPs:\n");
spin_lock_irqsave(&irlmp->unconnected_lsaps->hb_spinlock, flags);
self = (struct lsap_cb *) hashbin_get_first( irlmp->unconnected_lsaps);
while (self != NULL) {
ASSERT(self->magic == LMP_LSAP_MAGIC, return 0;);
ASSERT(self->magic == LMP_LSAP_MAGIC, break;);
len += sprintf(buf+len, "lsap state: %s, ",
irlsap_state[ self->lsap_state]);
len += sprintf(buf+len,
......@@ -1756,9 +1768,10 @@ int irlmp_proc_read(char *buf, char **start, off_t offset, int len)
self = (struct lsap_cb *) hashbin_get_next(
irlmp->unconnected_lsaps);
}
spin_unlock_irqrestore(&irlmp->unconnected_lsaps->hb_spinlock, flags);
len += sprintf(buf+len, "\nRegistred Link Layers:\n");
spin_lock_irqsave(&irlmp->links->hb_spinlock, flags);
lap = (struct lap_cb *) hashbin_get_first(irlmp->links);
while (lap != NULL) {
len += sprintf(buf+len, "lap state: %s, ",
......@@ -1770,10 +1783,15 @@ int irlmp_proc_read(char *buf, char **start, off_t offset, int len)
HASHBIN_GET_SIZE(lap->lsaps));
len += sprintf(buf+len, "\n");
/* Careful for priority inversions here !
* All other uses of attrib spinlock are independant of
* the object spinlock, so we are safe. Jean II */
spin_lock(&lap->lsaps->hb_spinlock);
len += sprintf(buf+len, "\n Connected LSAPs:\n");
self = (struct lsap_cb *) hashbin_get_first(lap->lsaps);
while (self != NULL) {
ASSERT(self->magic == LMP_LSAP_MAGIC, return 0;);
ASSERT(self->magic == LMP_LSAP_MAGIC, break;);
len += sprintf(buf+len, " lsap state: %s, ",
irlsap_state[ self->lsap_state]);
len += sprintf(buf+len,
......@@ -1785,11 +1803,12 @@ int irlmp_proc_read(char *buf, char **start, off_t offset, int len)
self = (struct lsap_cb *) hashbin_get_next(
lap->lsaps);
}
spin_unlock(&lap->lsaps->hb_spinlock);
len += sprintf(buf+len, "\n");
lap = (struct lap_cb *) hashbin_get_next(irlmp->links);
}
restore_flags(flags);
spin_unlock_irqrestore(&irlmp->links->hb_spinlock, flags);
return len;
}
......
......@@ -207,6 +207,43 @@ void irlmp_idle_timer_expired(void *data)
irlmp_do_lap_event(self, LM_LAP_IDLE_TIMEOUT, NULL);
}
/*
* Send an event on all LSAPs attached to this LAP.
*/
static inline void
irlmp_do_all_lsap_event(hashbin_t * lsap_hashbin,
IRLMP_EVENT event)
{
struct lsap_cb *lsap;
struct lsap_cb *lsap_next;
/* Note : this function use the new hashbin_find_next()
* function, instead of the old hashbin_get_next().
* This make sure that we are always pointing one lsap
* ahead, so that if the current lsap is removed as the
* result of sending the event, we don't care.
* Also, as we store the context ourselves, if an enumeration
* of the same lsap hashbin happens as the result of sending the
* event, we don't care.
* The only problem is if the next lsap is removed. In that case,
* hashbin_find_next() will return NULL and we will abort the
* enumeration. - Jean II */
/* Also : we don't accept any skb in input. We can *NOT* pass
* the same skb to multiple clients safely, we would need to
* skb_clone() it. - Jean II */
lsap = (struct lsap_cb *) hashbin_get_first(lsap_hashbin);
while (NULL != hashbin_find_next(lsap_hashbin,
(long) lsap,
NULL,
(void *) &lsap_next) ) {
irlmp_do_lsap_event(lsap, event, NULL);
lsap = lsap_next;
}
}
/*********************************************************************
*
* LAP connection control states
......@@ -274,9 +311,6 @@ static void irlmp_state_standby(struct lap_cb *self, IRLMP_EVENT event,
static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event,
struct sk_buff *skb)
{
struct lsap_cb *lsap;
struct lsap_cb *lsap_current;
IRDA_DEBUG(2, __FUNCTION__ "(), event=%s\n", irlmp_event[event]);
switch (event) {
......@@ -290,11 +324,9 @@ static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event,
/* Just accept connection TODO, this should be fixed */
irlap_connect_response(self->irlap, skb);
lsap = (struct lsap_cb *) hashbin_get_first(self->lsaps);
while (lsap != NULL) {
irlmp_do_lsap_event(lsap, LM_LAP_CONNECT_CONFIRM, NULL);
lsap = (struct lsap_cb*) hashbin_get_next(self->lsaps);
}
/* Tell LSAPs that they can start sending data */
irlmp_do_all_lsap_event(self->lsaps, LM_LAP_CONNECT_CONFIRM);
/* Note : by the time we get there (LAP retries and co),
* the lsaps may already have gone. This avoid getting stuck
* forever in LAP_ACTIVE state - Jean II */
......@@ -310,11 +342,9 @@ static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event,
/* For all lsap_ce E Associated do LS_Connect_confirm */
irlmp_next_lap_state(self, LAP_ACTIVE);
lsap = (struct lsap_cb *) hashbin_get_first(self->lsaps);
while (lsap != NULL) {
irlmp_do_lsap_event(lsap, LM_LAP_CONNECT_CONFIRM, NULL);
lsap = (struct lsap_cb*) hashbin_get_next(self->lsaps);
}
/* Tell LSAPs that they can start sending data */
irlmp_do_all_lsap_event(self->lsaps, LM_LAP_CONNECT_CONFIRM);
/* Note : by the time we get there (LAP retries and co),
* the lsaps may already have gone. This avoid getting stuck
* forever in LAP_ACTIVE state - Jean II */
......@@ -328,18 +358,8 @@ static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event,
irlmp_next_lap_state(self, LAP_STANDBY);
/* Send disconnect event to all LSAPs using this link */
lsap = (struct lsap_cb *) hashbin_get_first( self->lsaps);
while (lsap != NULL ) {
ASSERT(lsap->magic == LMP_LSAP_MAGIC, return;);
lsap_current = lsap;
/* Be sure to stay one item ahead */
lsap = (struct lsap_cb *) hashbin_get_next(self->lsaps);
irlmp_do_lsap_event(lsap_current,
LM_LAP_DISCONNECT_INDICATION,
NULL);
}
irlmp_do_all_lsap_event(self->lsaps,
LM_LAP_DISCONNECT_INDICATION);
break;
case LM_LAP_DISCONNECT_REQUEST:
IRDA_DEBUG(4, __FUNCTION__ "(), LM_LAP_DISCONNECT_REQUEST\n");
......@@ -368,9 +388,6 @@ static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event,
static void irlmp_state_active(struct lap_cb *self, IRLMP_EVENT event,
struct sk_buff *skb)
{
struct lsap_cb *lsap;
struct lsap_cb *lsap_current;
IRDA_DEBUG(4, __FUNCTION__ "()\n");
switch (event) {
......@@ -383,22 +400,11 @@ static void irlmp_state_active(struct lap_cb *self, IRLMP_EVENT event,
* notify all LSAPs using this LAP, but that should be safe to
* do anyway.
*/
lsap = (struct lsap_cb *) hashbin_get_first(self->lsaps);
while (lsap != NULL) {
irlmp_do_lsap_event(lsap, LM_LAP_CONNECT_CONFIRM, NULL);
lsap = (struct lsap_cb*) hashbin_get_next(self->lsaps);
}
irlmp_do_all_lsap_event(self->lsaps, LM_LAP_CONNECT_CONFIRM);
/* Needed by connect indication */
lsap = (struct lsap_cb *) hashbin_get_first(irlmp->unconnected_lsaps);
while (lsap != NULL) {
lsap_current = lsap;
/* Be sure to stay one item ahead */
lsap = (struct lsap_cb*) hashbin_get_next(irlmp->unconnected_lsaps);
irlmp_do_lsap_event(lsap_current,
LM_LAP_CONNECT_CONFIRM, NULL);
}
irlmp_do_all_lsap_event(irlmp->unconnected_lsaps,
LM_LAP_CONNECT_CONFIRM);
/* Keep state */
break;
case LM_LAP_DISCONNECT_REQUEST:
......@@ -447,18 +453,8 @@ static void irlmp_state_active(struct lap_cb *self, IRLMP_EVENT event,
/*
* Inform all connected LSAP's using this link
*/
lsap = (struct lsap_cb *) hashbin_get_first(self->lsaps);
while (lsap != NULL ) {
ASSERT(lsap->magic == LMP_LSAP_MAGIC, return;);
lsap_current = lsap;
/* Be sure to stay one item ahead */
lsap = (struct lsap_cb *) hashbin_get_next(self->lsaps);
irlmp_do_lsap_event(lsap_current,
LM_LAP_DISCONNECT_INDICATION,
NULL);
}
irlmp_do_all_lsap_event(self->lsaps,
LM_LAP_DISCONNECT_INDICATION);
/* Force an expiry of the discovery log.
* Now that the LAP is free, the system may attempt to
......@@ -581,15 +577,15 @@ static int irlmp_state_connect(struct lsap_cb *self, IRLMP_EVENT event,
* Bind this LSAP to the IrLAP link where the connect was
* received
*/
lsap = hashbin_remove(irlmp->unconnected_lsaps, (int) self,
lsap = hashbin_remove(irlmp->unconnected_lsaps, (long) self,
NULL);
ASSERT(lsap == self, return -1;);
ASSERT(self->lap != NULL, return -1;);
ASSERT(self->lap->lsaps != NULL, return -1;);
hashbin_insert(self->lap->lsaps, (irda_queue_t *) self, (int) self,
NULL);
hashbin_insert(self->lap->lsaps, (irda_queue_t *) self,
(long) self, NULL);
irlmp_send_lcf_pdu(self->lap, self->dlsap_sel,
self->slsap_sel, CONNECT_CNF, skb);
......
......@@ -210,6 +210,7 @@ void irlmp_link_unitdata_indication(struct lap_cb *self, struct sk_buff *skb)
__u8 dlsap_sel; /* Destination LSAP address */
__u8 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;
}
......@@ -34,11 +34,412 @@
*
********************************************************************/
/*
* NOTE :
* There are various problems with this package :
* o the hash function for ints is pathetic (but could be changed)
* o locking is sometime suspicious (especially during enumeration)
* o most users have only a few elements (== overhead)
* o most users never use seach, so don't benefit from hashing
* Problem already fixed :
* o not 64 bit compliant (most users do hashv = (int) self)
* o hashbin_remove() is broken => use hashbin_remove_this()
* I think most users would be better served by a simple linked list
* (like include/linux/list.h) with a global spinlock per list.
* Jean II
*/
/*
* Notes on the concurent access to hashbin and other SMP issues
* -------------------------------------------------------------
* Hashbins are very often in the IrDA stack a global repository of
* information, and therefore used in a very asynchronous manner following
* various events (driver calls, timers, user calls...).
* Therefore, very often it is highly important to consider the
* management of concurent access to the hashbin and how to guarantee the
* consistency of the operations on it.
*
* First, we need to define the objective of locking :
* 1) Protect user data (content pointed by the hashbin)
* 2) Protect hashbin structure itself (linked list in each bin)
*
* OLD LOCKING
* -----------
*
* The previous locking strategy, either HB_LOCAL or HB_GLOBAL were
* both inadequate in *both* aspect.
* o HB_GLOBAL was using a spinlock for each bin (local locking).
* o HB_LOCAL was disabling irq on *all* CPUs, so use a single
* global semaphore.
* The problems were :
* A) Global irq disabling is no longer supported by the kernel
* B) No protection for the hashbin struct global data
* o hashbin_delete()
* o hb_current
* C) No protection for user data in some cases
*
* A) HB_LOCAL use global irq disabling, so doesn't work on kernel
* 2.5.X. Even when it is supported (kernel 2.4.X and earlier), its
* performance is not satisfactory on SMP setups. Most hashbins were
* HB_LOCAL, so (A) definitely need fixing.
* B) HB_LOCAL could be modified to fix (B). However, because HB_GLOBAL
* lock only the individual bins, it will never be able to lock the
* global data, so can't do (B).
* C) Some functions return pointer to data that is still in the
* hashbin :
* o hashbin_find()
* o hashbin_get_first()
* o hashbin_get_next()
* As the data is still in the hashbin, it may be changed or free'd
* while the caller is examinimg the data. In those case, locking can't
* be done within the hashbin, but must include use of the data within
* the caller.
* The caller can easily do this with HB_LOCAL (just disable irqs).
* However, this is impossible with HB_GLOBAL because the caller has no
* way to know the proper bin, so don't know which spinlock to use.
*
* Quick summary : can no longer use HB_LOCAL, and HB_GLOBAL is
* fundamentally broken and will never work.
*
* NEW LOCKING
* -----------
*
* To fix those problems, I've introduce a few changes in the
* hashbin locking :
* 1) New HB_LOCK scheme
* 2) hashbin->hb_spinlock
* 3) New hashbin usage policy
*
* HB_LOCK :
* -------
* HB_LOCK is a locking scheme intermediate between the old HB_LOCAL
* and HB_GLOBAL. It uses a single spinlock to protect the whole content
* of the hashbin. As it is a single spinlock, it can protect the global
* data of the hashbin and not only the bins themselves.
* HB_LOCK can only protect some of the hashbin calls, so it only lock
* call that can be made 100% safe and leave other call unprotected.
* HB_LOCK in theory is slower than HB_GLOBAL, but as the hashbin
* content is always small contention is not high, so it doesn't matter
* much. HB_LOCK is probably faster than HB_LOCAL.
*
* hashbin->hb_spinlock :
* --------------------
* The spinlock that HB_LOCK uses is available for caller, so that
* the caller can protect unprotected calls (see below).
* If the caller want to do entirely its own locking (HB_NOLOCK), he
* can do so and may use safely this spinlock.
* Locking is done like this :
* spin_lock_irqsave(&hashbin->hb_spinlock, flags);
* Releasing the lock :
* spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
*
* Safe & Protected calls :
* ----------------------
* The following calls are safe or protected via HB_LOCK :
* o hashbin_new() -> safe
* o hashbin_delete()
* o hashbin_insert()
* o hashbin_remove_first()
* o hashbin_remove()
* o hashbin_remove_this()
* o HASHBIN_GET_SIZE() -> atomic
*
* The following calls only protect the hashbin itself :
* o hashbin_lock_find()
* o hashbin_find_next()
*
* Unprotected calls :
* -----------------
* The following calls need to be protected by the caller :
* o hashbin_find()
* o hashbin_get_first()
* o hashbin_get_next()
*
* Locking Policy :
* --------------
* If the hashbin is used only in a single thread of execution
* (explicitely or implicitely), you can use HB_NOLOCK
* If the calling module already provide concurent access protection,
* you may use HB_NOLOCK.
*
* In all other cases, you need to use HB_LOCK and lock the hashbin
* everytime before calling one of the unprotected calls. You also must
* use the pointer returned by the unprotected call within the locked
* region.
*
* Extra care for enumeration :
* --------------------------
* hashbin_get_first() and hashbin_get_next() use the hashbin to
* store the current position, in hb_current.
* As long as the hashbin remains locked, this is safe. If you unlock
* the hashbin, the current position may change if anybody else modify
* or enumerate the hashbin.
* Summary : do the full enumeration while locked.
*
* Alternatively, you may use hashbin_find_next(). But, this will
* be slower, is more complex to use and doesn't protect the hashbin
* content. So, care is needed here as well.
*
* Other issues :
* ------------
* I believe that we are overdoing it by using spin_lock_irqsave()
* and we should use only spin_lock_bh() or similar. But, I don't have
* the balls to try it out.
* Don't believe that because hashbin are now (somewhat) SMP safe
* that the rest of the code is. Higher layers tend to be safest,
* but LAP and LMP would need some serious dedicated love.
*
* Jean II
*/
#include <net/irda/irda.h>
#include <net/irda/irqueue.h>
static irda_queue_t *dequeue_general( irda_queue_t **queue, irda_queue_t* element);
static __u32 hash( char* name);
/************************ QUEUE SUBROUTINES ************************/
/*
* Hashbin
*/
#define GET_HASHBIN(x) ( x & HASHBIN_MASK )
/*
* Function hash (name)
*
* This function hash the input string 'name' using the ELF hash
* function for strings.
*/
static __u32 hash( char* name)
{
__u32 h = 0;
__u32 g;
while(*name) {
h = (h<<4) + *name++;
if ((g = (h & 0xf0000000)))
h ^=g>>24;
h &=~g;
}
return h;
}
/*
* Function enqueue_first (queue, proc)
*
* Insert item first in queue.
*
*/
static void enqueue_first(irda_queue_t **queue, irda_queue_t* element)
{
IRDA_DEBUG( 4, __FUNCTION__ "()\n");
/*
* Check if queue is empty.
*/
if ( *queue == NULL ) {
/*
* Queue is empty. Insert one element into the queue.
*/
element->q_next = element->q_prev = *queue = element;
} else {
/*
* Queue is not empty. Insert element into front of queue.
*/
element->q_next = (*queue);
(*queue)->q_prev->q_next = element;
element->q_prev = (*queue)->q_prev;
(*queue)->q_prev = element;
(*queue) = element;
}
}
#ifdef HASHBIN_UNUSED
/*
* Function enqueue_last (queue, proc)
*
* Insert item into end of queue.
*
*/
static void __enqueue_last( irda_queue_t **queue, irda_queue_t* element)
{
IRDA_DEBUG( 4, __FUNCTION__ "()\n");
/*
* Check if queue is empty.
*/
if ( *queue == NULL ) {
/*
* Queue is empty. Insert one element into the queue.
*/
element->q_next = element->q_prev = *queue = element;
} else {
/*
* Queue is not empty. Insert element into end of queue.
*/
element->q_prev = (*queue)->q_prev;
element->q_prev->q_next = element;
(*queue)->q_prev = element;
element->q_next = *queue;
}
}
static inline void enqueue_last( irda_queue_t **queue, irda_queue_t* element)
{
unsigned long flags;
save_flags(flags);
cli();
__enqueue_last( queue, element);
restore_flags(flags);
}
/*
* Function enqueue_queue (queue, list)
*
* Insert a queue (list) into the start of the first queue
*
*/
static void enqueue_queue( irda_queue_t** queue, irda_queue_t** list )
{
irda_queue_t* tmp;
/*
* Check if queue is empty
*/
if ( *queue ) {
(*list)->q_prev->q_next = (*queue);
(*queue)->q_prev->q_next = (*list);
tmp = (*list)->q_prev;
(*list)->q_prev = (*queue)->q_prev;
(*queue)->q_prev = tmp;
} else {
*queue = (*list);
}
(*list) = NULL;
}
/*
* Function enqueue_second (queue, proc)
*
* Insert item behind head of queue.
*
*/
static void enqueue_second(irda_queue_t **queue, irda_queue_t* element)
{
IRDA_DEBUG( 0, "enqueue_second()\n");
/*
* Check if queue is empty.
*/
if ( *queue == NULL ) {
/*
* Queue is empty. Insert one element into the queue.
*/
element->q_next = element->q_prev = *queue = element;
} else {
/*
* Queue is not empty. Insert element into ..
*/
element->q_prev = (*queue);
(*queue)->q_next->q_prev = element;
element->q_next = (*queue)->q_next;
(*queue)->q_next = element;
}
}
#endif /* HASHBIN_UNUSED */
/*
* Function dequeue (queue)
*
* Remove first entry in queue
*
*/
static irda_queue_t *dequeue_first(irda_queue_t **queue)
{
irda_queue_t *ret;
IRDA_DEBUG( 4, "dequeue_first()\n");
/*
* Set return value
*/
ret = *queue;
if ( *queue == NULL ) {
/*
* Queue was empty.
*/
} else if ( (*queue)->q_next == *queue ) {
/*
* Queue only contained a single element. It will now be
* empty.
*/
*queue = NULL;
} else {
/*
* Queue contained several element. Remove the first one.
*/
(*queue)->q_prev->q_next = (*queue)->q_next;
(*queue)->q_next->q_prev = (*queue)->q_prev;
*queue = (*queue)->q_next;
}
/*
* Return the removed entry (or NULL of queue was empty).
*/
return ret;
}
/*
* Function dequeue_general (queue, element)
*
*
*/
static irda_queue_t *dequeue_general(irda_queue_t **queue, irda_queue_t* element)
{
irda_queue_t *ret;
IRDA_DEBUG( 4, "dequeue_general()\n");
/*
* Set return value
*/
ret = *queue;
if ( *queue == NULL ) {
/*
* Queue was empty.
*/
} else if ( (*queue)->q_next == *queue ) {
/*
* Queue only contained a single element. It will now be
* empty.
*/
*queue = NULL;
} else {
/*
* Remove specific element.
*/
element->q_prev->q_next = element->q_next;
element->q_next->q_prev = element->q_prev;
if ( (*queue) == element)
(*queue) = element->q_next;
}
/*
* Return the removed entry (or NULL of queue was empty).
*/
return ret;
}
/************************ HASHBIN MANAGEMENT ************************/
/*
* Function hashbin_create ( type, name )
......@@ -49,7 +450,6 @@ static __u32 hash( char* name);
hashbin_t *hashbin_new(int type)
{
hashbin_t* hashbin;
int i;
/*
* Allocate new hashbin
......@@ -64,14 +464,17 @@ hashbin_t *hashbin_new(int type)
memset(hashbin, 0, sizeof(hashbin_t));
hashbin->hb_type = type;
hashbin->magic = HB_MAGIC;
//hashbin->hb_current = NULL;
/* Make sure all spinlock's are unlocked */
for (i=0;i<HASHBIN_SIZE;i++)
hashbin->hb_mutex[i] = SPIN_LOCK_UNLOCKED;
if ( hashbin->hb_type & HB_LOCK ) {
spin_lock_init(&hashbin->hb_spinlock);
}
return hashbin;
}
#ifdef HASHBIN_UNUSED
/*
* Function hashbin_clear (hashbin, free_func)
*
......@@ -102,7 +505,7 @@ int hashbin_clear( hashbin_t* hashbin, FREE_FUNC free_func)
return 0;
}
#endif /* HASHBIN_UNUSED */
/*
* Function hashbin_delete (hashbin, free_func)
......@@ -114,11 +517,17 @@ int hashbin_clear( hashbin_t* hashbin, FREE_FUNC free_func)
int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func)
{
irda_queue_t* queue;
unsigned long flags = 0;
int i;
ASSERT(hashbin != NULL, return -1;);
ASSERT(hashbin->magic == HB_MAGIC, return -1;);
/* Synchronize */
if ( hashbin->hb_type & HB_LOCK ) {
spin_lock_irqsave(&hashbin->hb_spinlock, flags);
}
/*
* Free the entries in the hashbin, TODO: use hashbin_clear when
* it has been shown to work
......@@ -133,22 +542,32 @@ int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func)
}
}
/* Cleanup local data */
hashbin->hb_current = NULL;
hashbin->magic = ~HB_MAGIC;
/* Release lock */
if ( hashbin->hb_type & HB_LOCK) {
spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
}
/*
* Free the hashbin structure
*/
hashbin->magic = ~HB_MAGIC;
kfree(hashbin);
return 0;
}
/********************* HASHBIN LIST OPERATIONS *********************/
/*
* Function hashbin_insert (hashbin, entry, name)
*
* Insert an entry into the hashbin
*
*/
void hashbin_insert(hashbin_t* hashbin, irda_queue_t* entry, __u32 hashv, char* name)
void hashbin_insert(hashbin_t* hashbin, irda_queue_t* entry, long hashv, char* name)
{
unsigned long flags = 0;
int bin;
......@@ -166,12 +585,8 @@ void hashbin_insert(hashbin_t* hashbin, irda_queue_t* entry, __u32 hashv, char*
bin = GET_HASHBIN( hashv );
/* Synchronize */
if ( hashbin->hb_type & HB_GLOBAL ) {
spin_lock_irqsave( &hashbin->hb_mutex[ bin ], flags);
} else if ( hashbin->hb_type & HB_LOCAL ) {
save_flags(flags);
cli();
if ( hashbin->hb_type & HB_LOCK ) {
spin_lock_irqsave(&hashbin->hb_spinlock, flags);
} /* Default is no-lock */
/*
......@@ -194,102 +609,61 @@ void hashbin_insert(hashbin_t* hashbin, irda_queue_t* entry, __u32 hashv, char*
hashbin->hb_size++;
/* Release lock */
if ( hashbin->hb_type & HB_GLOBAL) {
spin_unlock_irqrestore( &hashbin->hb_mutex[ bin], flags);
} else if ( hashbin->hb_type & HB_LOCAL) {
restore_flags( flags);
}
if ( hashbin->hb_type & HB_LOCK ) {
spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
} /* Default is no-lock */
}
/*
* Function hashbin_find (hashbin, hashv, name)
* Function hashbin_remove_first (hashbin)
*
* Find item with the given hashv or name
* Remove first entry of the hashbin
*
* Note : this function no longer use hashbin_remove(), but does things
* similar to hashbin_remove_this(), so can be considered safe.
* Jean II
*/
void* hashbin_find( hashbin_t* hashbin, __u32 hashv, char* name )
void *hashbin_remove_first( hashbin_t *hashbin)
{
int bin, found = FALSE;
unsigned long flags = 0;
irda_queue_t* entry;
IRDA_DEBUG( 4, "hashbin_find()\n");
irda_queue_t *entry = NULL;
ASSERT( hashbin != NULL, return NULL;);
ASSERT( hashbin->magic == HB_MAGIC, return NULL;);
/* Synchronize */
if ( hashbin->hb_type & HB_LOCK ) {
spin_lock_irqsave(&hashbin->hb_spinlock, flags);
} /* Default is no-lock */
entry = hashbin_get_first( hashbin);
if ( entry != NULL) {
int bin;
long hashv;
/*
* Locate hashbin
*/
if ( name )
hashv = hash( name );
hashv = entry->q_hash;
bin = GET_HASHBIN( hashv );
/* Synchronize */
if ( hashbin->hb_type & HB_GLOBAL ) {
spin_lock_irqsave( &hashbin->hb_mutex[ bin ], flags);
} else if ( hashbin->hb_type & HB_LOCAL ) {
save_flags(flags);
cli();
} /* Default is no-lock */
/*
* Search for entry
*/
entry = hashbin->hb_queue[ bin];
if ( entry ) {
do {
/*
* Check for key
* Dequeue the entry...
*/
if ( entry->q_hash == hashv ) {
dequeue_general( (irda_queue_t**) &hashbin->hb_queue[ bin ],
(irda_queue_t*) entry );
hashbin->hb_size--;
entry->q_next = NULL;
entry->q_prev = NULL;
/*
* Name compare too?
* Check if this item is the currently selected item, and in
* that case we must reset hb_current
*/
if ( name ) {
if ( strcmp( entry->q_name, name ) == 0 ) {
found = TRUE;
break;
}
} else {
found = TRUE;
break;
}
}
entry = entry->q_next;
} while ( entry != hashbin->hb_queue[ bin ] );
if ( entry == hashbin->hb_current)
hashbin->hb_current = NULL;
}
/* Release lock */
if ( hashbin->hb_type & HB_GLOBAL) {
spin_unlock_irqrestore( &hashbin->hb_mutex[ bin], flags);
} else if ( hashbin->hb_type & HB_LOCAL) {
restore_flags( flags);
}
if ( found )
return entry;
else
return NULL;
}
void *hashbin_remove_first( hashbin_t *hashbin)
{
unsigned long flags;
irda_queue_t *entry = NULL;
save_flags(flags);
cli();
entry = hashbin_get_first( hashbin);
if ( entry != NULL)
hashbin_remove( hashbin, entry->q_hash, NULL);
restore_flags( flags);
if ( hashbin->hb_type & HB_LOCK ) {
spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
} /* Default is no-lock */
return entry;
}
......@@ -300,8 +674,16 @@ void *hashbin_remove_first( hashbin_t *hashbin)
*
* Remove entry with the given name
*
* The use of this function is highly discouraged, because the whole
* concept behind hashbin_remove() is broken. In many cases, it's not
* possible to guarantee the unicity of the index (either hashv or name),
* leading to removing the WRONG entry.
* The only simple safe use is :
* hashbin_remove(hasbin, (int) self, NULL);
* In other case, you must think hard to guarantee unicity of the index.
* Jean II
*/
void* hashbin_remove( hashbin_t* hashbin, __u32 hashv, char* name)
void* hashbin_remove( hashbin_t* hashbin, long hashv, char* name)
{
int bin, found = FALSE;
unsigned long flags = 0;
......@@ -320,12 +702,8 @@ void* hashbin_remove( hashbin_t* hashbin, __u32 hashv, char* name)
bin = GET_HASHBIN( hashv );
/* Synchronize */
if ( hashbin->hb_type & HB_GLOBAL ) {
spin_lock_irqsave( &hashbin->hb_mutex[ bin ], flags);
} else if ( hashbin->hb_type & HB_LOCAL ) {
save_flags(flags);
cli();
if ( hashbin->hb_type & HB_LOCK ) {
spin_lock_irqsave(&hashbin->hb_spinlock, flags);
} /* Default is no-lock */
/*
......@@ -373,12 +751,9 @@ void* hashbin_remove( hashbin_t* hashbin, __u32 hashv, char* name)
}
/* Release lock */
if ( hashbin->hb_type & HB_GLOBAL) {
spin_unlock_irqrestore( &hashbin->hb_mutex[ bin], flags);
} else if ( hashbin->hb_type & HB_LOCAL) {
restore_flags( flags);
}
if ( hashbin->hb_type & HB_LOCK ) {
spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
} /* Default is no-lock */
/* Return */
......@@ -390,7 +765,7 @@ void* hashbin_remove( hashbin_t* hashbin, __u32 hashv, char* name)
}
/*
* Function hashbin_remove (hashbin, hashv, name)
* Function hashbin_remove_this (hashbin, entry)
*
* Remove entry with the given name
*
......@@ -404,7 +779,7 @@ void* hashbin_remove_this( hashbin_t* hashbin, irda_queue_t* entry)
{
unsigned long flags = 0;
int bin;
__u32 hashv;
long hashv;
IRDA_DEBUG( 4, __FUNCTION__ "()\n");
......@@ -412,6 +787,11 @@ void* hashbin_remove_this( hashbin_t* hashbin, irda_queue_t* entry)
ASSERT( hashbin->magic == HB_MAGIC, return NULL;);
ASSERT( entry != NULL, return NULL;);
/* Synchronize */
if ( hashbin->hb_type & HB_LOCK ) {
spin_lock_irqsave(&hashbin->hb_spinlock, flags);
} /* Default is no-lock */
/* Check if valid and not already removed... */
if((entry->q_next == NULL) || (entry->q_prev == NULL))
return NULL;
......@@ -419,41 +799,151 @@ void* hashbin_remove_this( hashbin_t* hashbin, irda_queue_t* entry)
/*
* Locate hashbin
*/
hashv = entry->q_hash;
bin = GET_HASHBIN( hashv );
hashv = entry->q_hash;
bin = GET_HASHBIN( hashv );
/*
* Dequeue the entry...
*/
dequeue_general( (irda_queue_t**) &hashbin->hb_queue[ bin ],
(irda_queue_t*) entry );
hashbin->hb_size--;
entry->q_next = NULL;
entry->q_prev = NULL;
/*
* Check if this item is the currently selected item, and in
* that case we must reset hb_current
*/
if ( entry == hashbin->hb_current)
hashbin->hb_current = NULL;
/* Release lock */
if ( hashbin->hb_type & HB_LOCK ) {
spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
} /* Default is no-lock */
return entry;
}
/*********************** HASHBIN ENUMERATION ***********************/
/*
* Function hashbin_common_find (hashbin, hashv, name)
*
* Find item with the given hashv or name
*
*/
void* hashbin_find( hashbin_t* hashbin, long hashv, char* name )
{
int bin;
irda_queue_t* entry;
IRDA_DEBUG( 4, "hashbin_find()\n");
ASSERT( hashbin != NULL, return NULL;);
ASSERT( hashbin->magic == HB_MAGIC, return NULL;);
/*
* Locate hashbin
*/
if ( name )
hashv = hash( name );
bin = GET_HASHBIN( hashv );
/*
* Search for entry
*/
entry = hashbin->hb_queue[ bin];
if ( entry ) {
do {
/*
* Check for key
*/
if ( entry->q_hash == hashv ) {
/*
* Name compare too?
*/
if ( name ) {
if ( strcmp( entry->q_name, name ) == 0 ) {
return entry;
}
} else {
return entry;
}
}
entry = entry->q_next;
} while ( entry != hashbin->hb_queue[ bin ] );
}
return NULL;
}
/*
* Function hashbin_lock_find (hashbin, hashv, name)
*
* Find item with the given hashv or name
*
* Same, but with spinlock protection...
* I call it safe, but it's only safe with respect to the hashbin, not its
* content. - Jean II
*/
void* hashbin_lock_find( hashbin_t* hashbin, long hashv, char* name )
{
unsigned long flags = 0;
irda_queue_t* entry;
/* Synchronize */
spin_lock_irqsave(&hashbin->hb_spinlock, flags);
/*
* Search for entry
*/
entry = (irda_queue_t* ) hashbin_find( hashbin, hashv, name );
/* Release lock */
spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
return entry;
}
/*
* Function hashbin_find (hashbin, hashv, name, pnext)
*
* Find an item with the given hashv or name, and its successor
*
* This function allow to do concurent enumerations without the
* need to lock over the whole session, because the caller keep the
* context of the search. On the other hand, it might fail and return
* NULL if the entry is removed. - Jean II
*/
void* hashbin_find_next( hashbin_t* hashbin, long hashv, char* name,
void ** pnext)
{
unsigned long flags = 0;
irda_queue_t* entry;
/* Synchronize */
if ( hashbin->hb_type & HB_GLOBAL ) {
spin_lock_irqsave( &hashbin->hb_mutex[ bin ], flags);
} else if ( hashbin->hb_type & HB_LOCAL ) {
save_flags(flags);
cli();
} /* Default is no-lock */
spin_lock_irqsave(&hashbin->hb_spinlock, flags);
/*
* Dequeue the entry...
* Search for current entry
* This allow to check if the current item is still in the
* hashbin or has been removed.
*/
dequeue_general( (irda_queue_t**) &hashbin->hb_queue[ bin ],
(irda_queue_t*) entry );
hashbin->hb_size--;
entry->q_next = NULL;
entry->q_prev = NULL;
entry = (irda_queue_t* ) hashbin_find( hashbin, hashv, name );
/*
* Check if this item is the currently selected item, and in
* that case we must reset hb_current
* Trick hashbin_get_next() to return what we want
*/
if ( entry == hashbin->hb_current)
hashbin->hb_current = NULL;
if(entry) {
hashbin->hb_current = entry;
*pnext = hashbin_get_next( hashbin );
} else
*pnext = NULL;
/* Release lock */
if ( hashbin->hb_type & HB_GLOBAL) {
spin_unlock_irqrestore( &hashbin->hb_mutex[ bin], flags);
} else if ( hashbin->hb_type & HB_LOCAL) {
restore_flags( flags);
}
spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
return entry;
}
......@@ -496,6 +986,8 @@ irda_queue_t *hashbin_get_first( hashbin_t* hashbin)
* be started by a call to hashbin_get_first(). The function returns
* NULL when all items have been traversed
*
* The context of the search is stored within the hashbin, so you must
* protect yourself from concurent enumerations. - Jean II
*/
irda_queue_t *hashbin_get_next( hashbin_t *hashbin)
{
......@@ -543,240 +1035,3 @@ irda_queue_t *hashbin_get_next( hashbin_t *hashbin)
}
return NULL;
}
/*
* Function enqueue_last (queue, proc)
*
* Insert item into end of queue.
*
*/
static void __enqueue_last( irda_queue_t **queue, irda_queue_t* element)
{
IRDA_DEBUG( 4, __FUNCTION__ "()\n");
/*
* Check if queue is empty.
*/
if ( *queue == NULL ) {
/*
* Queue is empty. Insert one element into the queue.
*/
element->q_next = element->q_prev = *queue = element;
} else {
/*
* Queue is not empty. Insert element into end of queue.
*/
element->q_prev = (*queue)->q_prev;
element->q_prev->q_next = element;
(*queue)->q_prev = element;
element->q_next = *queue;
}
}
inline void enqueue_last( irda_queue_t **queue, irda_queue_t* element)
{
unsigned long flags;
save_flags(flags);
cli();
__enqueue_last( queue, element);
restore_flags(flags);
}
/*
* Function enqueue_first (queue, proc)
*
* Insert item first in queue.
*
*/
void enqueue_first(irda_queue_t **queue, irda_queue_t* element)
{
IRDA_DEBUG( 4, __FUNCTION__ "()\n");
/*
* Check if queue is empty.
*/
if ( *queue == NULL ) {
/*
* Queue is empty. Insert one element into the queue.
*/
element->q_next = element->q_prev = *queue = element;
} else {
/*
* Queue is not empty. Insert element into front of queue.
*/
element->q_next = (*queue);
(*queue)->q_prev->q_next = element;
element->q_prev = (*queue)->q_prev;
(*queue)->q_prev = element;
(*queue) = element;
}
}
/*
* Function enqueue_queue (queue, list)
*
* Insert a queue (list) into the start of the first queue
*
*/
void enqueue_queue( irda_queue_t** queue, irda_queue_t** list )
{
irda_queue_t* tmp;
/*
* Check if queue is empty
*/
if ( *queue ) {
(*list)->q_prev->q_next = (*queue);
(*queue)->q_prev->q_next = (*list);
tmp = (*list)->q_prev;
(*list)->q_prev = (*queue)->q_prev;
(*queue)->q_prev = tmp;
} else {
*queue = (*list);
}
(*list) = NULL;
}
/*
* Function enqueue_second (queue, proc)
*
* Insert item behind head of queue.
*
*/
#if 0
static void enqueue_second(irda_queue_t **queue, irda_queue_t* element)
{
IRDA_DEBUG( 0, "enqueue_second()\n");
/*
* Check if queue is empty.
*/
if ( *queue == NULL ) {
/*
* Queue is empty. Insert one element into the queue.
*/
element->q_next = element->q_prev = *queue = element;
} else {
/*
* Queue is not empty. Insert element into ..
*/
element->q_prev = (*queue);
(*queue)->q_next->q_prev = element;
element->q_next = (*queue)->q_next;
(*queue)->q_next = element;
}
}
#endif
/*
* Function dequeue (queue)
*
* Remove first entry in queue
*
*/
irda_queue_t *dequeue_first(irda_queue_t **queue)
{
irda_queue_t *ret;
IRDA_DEBUG( 4, "dequeue_first()\n");
/*
* Set return value
*/
ret = *queue;
if ( *queue == NULL ) {
/*
* Queue was empty.
*/
} else if ( (*queue)->q_next == *queue ) {
/*
* Queue only contained a single element. It will now be
* empty.
*/
*queue = NULL;
} else {
/*
* Queue contained several element. Remove the first one.
*/
(*queue)->q_prev->q_next = (*queue)->q_next;
(*queue)->q_next->q_prev = (*queue)->q_prev;
*queue = (*queue)->q_next;
}
/*
* Return the removed entry (or NULL of queue was empty).
*/
return ret;
}
/*
* Function dequeue_general (queue, element)
*
*
*/
static irda_queue_t *dequeue_general(irda_queue_t **queue, irda_queue_t* element)
{
irda_queue_t *ret;
IRDA_DEBUG( 4, "dequeue_general()\n");
/*
* Set return value
*/
ret = *queue;
if ( *queue == NULL ) {
/*
* Queue was empty.
*/
} else if ( (*queue)->q_next == *queue ) {
/*
* Queue only contained a single element. It will now be
* empty.
*/
*queue = NULL;
} else {
/*
* Remove specific element.
*/
element->q_prev->q_next = element->q_next;
element->q_next->q_prev = element->q_prev;
if ( (*queue) == element)
(*queue) = element->q_next;
}
/*
* Return the removed entry (or NULL of queue was empty).
*/
return ret;
}
/*
* Function hash (name)
*
* This function hash the input string 'name' using the ELF hash
* function for strings.
*/
static __u32 hash( char* name)
{
__u32 h = 0;
__u32 g;
while(*name) {
h = (h<<4) + *name++;
if ((g = (h & 0xf0000000)))
h ^=g>>24;
h &=~g;
}
return h;
}
......@@ -132,12 +132,14 @@ EXPORT_SYMBOL(irlmp_dup);
EXPORT_SYMBOL(lmp_reasons);
/* Queue */
EXPORT_SYMBOL(hashbin_find);
EXPORT_SYMBOL(hashbin_new);
EXPORT_SYMBOL(hashbin_insert);
EXPORT_SYMBOL(hashbin_delete);
EXPORT_SYMBOL(hashbin_remove);
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_first);
......@@ -328,7 +330,8 @@ void __exit irda_cleanup(void)
* On the other hand, it needs to be initialised *after* the basic
* networking, the /proc/net filesystem and sysctl module. Those are
* 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
*/
......
......@@ -91,7 +91,7 @@ int __init irttp_init(void)
irttp->magic = TTP_MAGIC;
irttp->tsaps = hashbin_new(HB_LOCAL);
irttp->tsaps = hashbin_new(HB_LOCK);
if (!irttp->tsaps) {
ERROR("%s: can't allocate IrTTP hashbin!\n", __FUNCTION__);
return -ENOMEM;
......@@ -433,7 +433,7 @@ struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify)
self->notify = *notify;
self->lsap = lsap;
hashbin_insert(irttp->tsaps, (irda_queue_t *) self, (int) self, NULL);
hashbin_insert(irttp->tsaps, (irda_queue_t *) self, (long) self, NULL);
if (credit > TTP_RX_MAX_CREDIT)
self->initial_credit = TTP_RX_MAX_CREDIT;
......@@ -503,7 +503,7 @@ int irttp_close_tsap(struct tsap_cb *self)
return 0; /* Will be back! */
}
tsap = hashbin_remove(irttp->tsaps, (int) self, NULL);
tsap = hashbin_remove(irttp->tsaps, (long) self, NULL);
ASSERT(tsap == self, return -1;);
......@@ -1365,31 +1365,44 @@ int irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size,
struct tsap_cb *irttp_dup(struct tsap_cb *orig, void *instance)
{
struct tsap_cb *new;
unsigned long flags;
IRDA_DEBUG(1, __FUNCTION__ "()\n");
/* Protect our access to the old tsap instance */
spin_lock_irqsave(&irttp->tsaps->hb_spinlock, flags);
/* Find the old instance */
if (!hashbin_find(irttp->tsaps, (int) orig, NULL)) {
IRDA_DEBUG(0, __FUNCTION__ "(), unable to find TSAP\n");
spin_unlock_irqrestore(&irttp->tsaps->hb_spinlock, flags);
return NULL;
}
/* Allocate a new instance */
new = kmalloc(sizeof(struct tsap_cb), GFP_ATOMIC);
if (!new) {
IRDA_DEBUG(0, __FUNCTION__ "(), unable to kmalloc\n");
spin_unlock_irqrestore(&irttp->tsaps->hb_spinlock, flags);
return NULL;
}
/* Dup */
memcpy(new, orig, sizeof(struct tsap_cb));
new->notify.instance = instance;
new->lsap = irlmp_dup(orig->lsap, new);
/* We don't need the old instance any more */
spin_unlock_irqrestore(&irttp->tsaps->hb_spinlock, flags);
/* Not everything should be copied */
new->notify.instance = instance;
new->lsap = irlmp_dup(orig->lsap, new);
init_timer(&new->todo_timer);
skb_queue_head_init(&new->rx_queue);
skb_queue_head_init(&new->tx_queue);
skb_queue_head_init(&new->rx_fragments);
hashbin_insert(irttp->tsaps, (irda_queue_t *) new, (int) new, NULL);
/* This is locked */
hashbin_insert(irttp->tsaps, (irda_queue_t *) new, (long) new, NULL);
return new;
}
......@@ -1723,8 +1736,8 @@ int irttp_proc_read(char *buf, char **start, off_t offset, int len)
len = 0;
save_flags(flags);
cli();
/* Protect our access to the tsap list */
spin_lock_irqsave(&irttp->tsaps->hb_spinlock, flags);
self = (struct tsap_cb *) hashbin_get_first(irttp->tsaps);
while (self != NULL) {
......@@ -1770,7 +1783,7 @@ int irttp_proc_read(char *buf, char **start, off_t offset, int len)
self = (struct tsap_cb *) hashbin_get_next(irttp->tsaps);
}
restore_flags(flags);
spin_unlock_irqrestore(&irttp->tsaps->hb_spinlock, flags);
return len;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment