lkml.org 
[lkml]   [2000]   [Aug]   [5]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectRe: [PATCH] lock troubles in pre6-2
Here is a more complete listing of the issues found by a compiler-based
checker after being filtered by me. The checker essentially checks that
spin locks, interrupts, and bh's are paired up in functions, warning when
the function can exit holding a lock, with interrupts disabled, or while
bh's are disabled. It also tries to check for double locks/unlocks within
the same function, and also restoring of flags not saved within the same
function.

I had to filter out ~250 false positives, the ones here are ones I've
looked at at least briefly so there should be at least a few bugs :)

Issues to be aware of:

1. The context given for each potential bug is incomplete; it's necessary
to consult the source.

2. The version we checked is 2.3.99-? -- I'm not sure exactly which one
but I can verify if needed.

3. Some of the "bugs" are at most poor style, and there are probably false
positives. The checker isn't global so it knows nothing about what goes
on in function calls. It may be made global at some point (suggestions
on how to do this effectively are welcome).

4. If you can verify any of these, please cc mc@cs.stanford.edu.

-Andy

--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/atm/iphase.c:1691:tx_dle_intr: ERROR:LCK:HOLD: leaving function holding lock `(::tx_dle_intr (::atm_dev *)::iadev + 92)'
BUG:DD:ECOND:
static void tx_dle_intr(struct atm_dev *dev)
{
unsigned long flags;
...
==> Lock here
spin_lock_irqsave(&iadev->tx_lock, flags);
while (dle != cur_dle)
{
vcc = ATM_SKB(skb)->vcc;
if (!vcc) {
printk("tx_dle_intr: vcc is null\n");
dev_kfree_skb_any(skb);
==> forgot to unlock
return;
}
iavcc = INPH_IA_VCC(vcc);
if (!iavcc) {
printk("tx_dle_intr: iavcc is null\n");
dev_kfree_skb_any(skb);
==> forgot to unlock
return;
}
spin_unlock_irqrestore(&iadev->tx_lock, flags);
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/char/cyclades.c:1165:cyy_interrupt: ERROR:LCK:2L: relocking lock
BUG:DD:ECOND

static void
cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
do{
had_work = 0;
for ( chip = 0 ; chip < cinfo->num_chips ; chip ++) {
while ( (status = cy_readb(base_addr+(CySVRR<<index))) != 0x00) {
if (status & CySRReceive) { /* reception interrupt */
==> Locking here
spin_lock(&cinfo->card_lock);
if(info->tty == 0){
...
}else{
if ( j == CyIVRRxEx ) { /* exception */
if(data & info->ignore_status_mask){
info->icount.rx++;
==> Forgot to unlock here
continue;
}
if (status & CySRTransmit) { /* transmission interrupt */
spin_lock(&cinfo->card_lock);
...
spin_unlock(&cinfo->card_lock);
}
if (status & CySRModem) {
spin_lock(&cinfo->card_lock);
...
spin_unlock(&cinfo->card_lock);
}
}
}
} while(had_work);
spin_lock(&cinfo->card_lock);
cy_writeb((u_long)card_base_addr + (Cy_ClrIntr<<index), 0);
/* Cy_ClrIntr is 0x1800 */
spin_unlock(&cinfo->card_lock);
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/char/n_r3964.c:990:add_msg: ERROR:INTR:DIS: leaving function with interrupts disabled
BUG:DD:ECOND

static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg,
int error_code, struct r3964_block_header *pBlock)
{
if(pClient->msg_count<R3964_MAX_MSG_COUNT-1)
{
==> Disable interrupts
save_flags(flags);
cli();
pMsg = kmalloc(sizeof(struct r3964_message), GFP_KERNEL);
TRACE_M("add_msg - kmalloc %x",(int)pMsg);
if(pMsg==NULL)
==> Return without restoring flags?
return;
...
restore_flags(flags);
}
else
{
...
}
...
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/char/saa7110.c:76:saa7110_write_block: ERROR:LCK:HOLD: leaving function holding lock `(::saa7110_write_block (::saa7110 *, const unsigned char *, unsigned int)::decoder->::saa7110::bus + 40)'
BUG:DD:ECOND

static
int saa7110_write_block(struct saa7110* decoder, unsigned const char *data, unsigned int len)
{
unsigned subaddr = *data;
==> Calls spin_lock_irqsave
LOCK_I2C_BUS(decoder->bus);
i2c_start(decoder->bus);
i2c_sendbyte(decoder->bus,decoder->addr,I2C_DELAY);
while (len-- > 0) {
if (i2c_sendbyte(decoder->bus,*data,0)) {
i2c_stop(decoder->bus);
==> Forgot to unlock
return -EAGAIN;
}
decoder->reg[subaddr++] = *data++;
}
i2c_stop(decoder->bus);
UNLOCK_I2C_BUS(decoder->bus);
return 0;
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/i2o/i2o_block.c:1412:i2ob_del_device: ERROR:LCK:HOLD: leaving function holding lock `&::io_request_lock'
BUG:DD:ECOND

void i2ob_del_device(struct i2o_controller *c, struct i2o_device *d)
{
==> Lock here
spin_lock_irqsave(&io_request_lock, flags);
if(unit >= MAX_I2OB<<4)
{
printk(KERN_ERR "i2ob_del_device called, but not in dev table!\n");
==> Missing unlock
return;
}
...
spin_unlock_irqrestore(&io_request_lock, flags);
...
return;
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/ide/ide-disk.c:697:set_nowerr: ERROR:FLAGS: restoring flags without saving them
BUG:DD:FLAGARG should not pass flags as arguments?

static int set_nowerr(ide_drive_t *drive, int arg)
{
unsigned long flags;
if (ide_spin_wait_hwgroup(drive, &flags))
return -EBUSY;
drive->nowerr = arg;
drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
spin_unlock_irqrestore(&io_request_lock, flags);
return 0;
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/isdn/hisax/config.c:1063:checkcard: ERROR:INTR:DIS: leaving function with interrupts disabled
BUG:DD:ECOND

HISAX_INITFUNC(static int
checkcard(int cardnr, char *id, int *busy_flag))
{
==> save flags
save_flags(flags);
cli();
...
if (!(cs->rcvbuf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC))) {
printk(KERN_WARNING
"HiSax: No memory for isac rcvbuf\n");
==> not restoring flags
return (1);
}
...
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/isdn/isdn_net.h:174:isdn_net_get_locked_lp: ERROR:LCK:HOLD: leaving function holding lock `(::isdn_net_get_locked_lp (::isdn_net_dev *)::nd->::isdn_net_dev_s::queue + 304)'
BUG:DD:ECOND

static __inline__ isdn_net_local * isdn_net_get_locked_lp(isdn_net_dev *nd)
{
unsigned long flags;
isdn_net_local *lp;
==> Save queue_lock
spin_lock_irqsave(&nd->queue_lock, flags);
lp = nd->queue; /* get lp on top of queue */
spin_lock_bh(&nd->queue->xmit_lock);
while (isdn_net_lp_busy(nd->queue)) {
spin_unlock_bh(&nd->queue->xmit_lock);
nd->queue = nd->queue->next;
if (nd->queue == lp) /* not found -- should never happen */
==> Forgot to restore queue_lock
return 0;
spin_lock_bh(&nd->queue->xmit_lock);
}
lp = nd->queue;
nd->queue = nd->queue->next;
spin_unlock_irqrestore(&nd->queue_lock, flags);
return lp;
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/isdn/isdn_ppp.c:435:isdn_ppp_bind: ERROR:INTR:DIS: leaving function with interrupts disabled
BUG:DD:ECOND

int
isdn_ppp_bind(isdn_net_local * lp)
{
save_flags(flags);
cli();
...
if (unit < 0) {
printk(KERN_ERR "isdn_ppp_bind: illegal interface name %s.\n", lp->name);
return -1;
}
...
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/net/appletalk/cops.c:746:cops_rx: ERROR:INTR:DIS: leaving function with interrupts disabled
BUG:DD:ECOND

static void cops_rx(struct net_device *dev)
{
==> Disable intr
save_flags(flags);
cli(); /* Disable interrupts. */
if(lp->board==DAYNA)
{
outb(0, ioaddr); /* Send out Zero length. */
outb(0, ioaddr);
outb(DATA_READ, ioaddr); /* Send read command out. */
/* Wait for DMA to turn around. */
while(++boguscount<1000000)
{
if((inb(ioaddr+DAYNA_CARD_STATUS)&0x03)==DAYNA_RX_READY)
break;
}
if(boguscount==1000000)
{
printk(KERN_WARNING "%s: DMA timed out.\n",dev->name);
==> Forgot to restore flags
return;
}
}
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/net/de4x5.c:1618:de4x5_interrupt: ERROR:LCK:HOLD: leaving function holding lock `(::de4x5_interrupt (int, void *, ::pt_regs *)::lp + 524)'
BUG:DD:ECOND

static void
de4x5_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
==> Locking here
spin_lock(&lp->lock);
==> Only disables a particular intr
DISABLE_IRQs; /* Ensure non re-entrancy */
for (limit=0; limit<8; limit++) {
...
if (sts & STS_SE) { /* Bus Error */
STOP_DE4X5;
printk("%s: Fatal bus error occurred, sts=%#8x, device stopped.\n",
dev->name, sts);
==> Not unlocking
return;
}
}
...
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/net/de4x5.c:5585:de4x5_ioctl: ERROR:LCK:HOLD: leaving function holding lock `(::de4x5_ioctl (::net_device *, ::ifreq *, int)::lp + 524)'
BUG:DD:ECOND:SLEEP

static int
de4x5_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
switch(ioc->cmd) {
...
case DE4X5_GET_STATS: /* Get the driver statistics */
ioc->len = sizeof(lp->pktStats);
==> Lock here
spin_lock_irqsave(&lp->lock, flags);
==> Not unlocking on error, calling copy_to_user
if (copy_to_user(ioc->data, &lp->pktStats, ioc->len)) return -EFAULT;
spin_unlock_irqrestore(&lp->lock, flags);
break;
...
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/net/hamradio/soundmodem/sm_wss.c:159:wss_set_codec_fmt: ERROR:INTR:DIS: leaving function with interrupts disabled
BUG:DD:ECOND

static int wss_set_codec_fmt(struct net_device *dev, struct sm_state *sm, unsigned char fmt,
unsigned char fmt2, char fdx, char fullcalib)
{
unsigned long time;
unsigned long flags;
==> Save flags, disable intr
save_flags(flags);
cli();
/* Clock and data format register */
write_codec(dev, 0x48, fmt);
if (SCSTATE->crystal) {
write_codec(dev, 0x5c, fmt2 & 0xf0);
/* MCE and interface config reg */
write_codec(dev, 0x49, (fdx ? 0 : 0x4) | (fullcalib ? 0x18 : 0));
} else
/* MCE and interface config reg */
write_codec(dev, 0x49, fdx ? 0x8 : 0xc);
outb(0xb, WSS_CODEC_IA(dev->base_addr)); /* leave MCE */
if (SCSTATE->crystal && !fullcalib)
==> Missing restore flags here
return 0;
/*
* wait for ACI start
*/
time = 1000;
while (!(read_codec(dev, 0x0b) & 0x20))
if (!(--time)) {
printk(KERN_WARNING "%s: ad1848 auto calibration timed out (1)\n",
sm_drvname);
==> Carefully restored here
restore_flags(flags);
return -1;
}
/*
* wait for ACI end
*/
sti();
time = jiffies + HZ/4;
while ((read_codec(dev, 0x0b) & 0x20) && ((signed)(jiffies - time) < 0));
==> Carefully restored here
restore_flags(flags);
if ((signed)(jiffies - time) >= 0) {
printk(KERN_WARNING "%s: ad1848 auto calibration timed out (2)\n",
sm_drvname);
return -1;
}
return 0;
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/net/irda/irport.c:923:irport_net_ioctl: ERROR:INTR:DIS: leaving function with interrupts disabled
Four bugs.

BUG:DD:ECOND
BUG:DD:ECOND
BUG:DD:ECOND
BUG:DD:ECOND

static int irport_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
self = dev->priv;
ASSERT(self != NULL, return -1;);

IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);

/* Disable interrupts & save flags */
==> Save here
save_flags(flags);
cli();
switch (cmd) {
case SIOCSBANDWIDTH: /* Set bandwidth */
if (!capable(CAP_NET_ADMIN))
==> Missing restore
return -EPERM;
irda_task_execute(self, __irport_change_speed, NULL, NULL,
(void *) irq->ifr_baudrate);
break;
case SIOCSDONGLE: /* Set dongle */
if (!capable(CAP_NET_ADMIN))
==> Missing restore
return -EPERM;
/* Initialize dongle */
dongle = irda_device_dongle_init(dev, irq->ifr_dongle);
if (!dongle)
break;
dongle->set_mode = NULL;
dongle->read = NULL;
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);
break;
case SIOCSMEDIABUSY: /* Set media busy */
if (!capable(CAP_NET_ADMIN))
==> Missing restore
return -EPERM;
irda_device_set_media_busy(self->netdev, TRUE);
break;
case SIOCGRECEIVING: /* Check if we are receiving right now */
irq->ifr_receiving = irport_is_receiving(self);
break;
case SIOCSDTRRTS:
if (!capable(CAP_NET_ADMIN))
==> Missing restore
return -EPERM;
irport_set_dtr_rts(dev, irq->ifr_dtr, irq->ifr_rts);
break;
default:
ret = -EOPNOTSUPP;
}
restore_flags(flags);

return ret;
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/net/irda/irtty.c:943:irtty_net_ioctl: ERROR:INTR:DIS: leaving function with interrupts disabled
Similar to the above bugs.

BUG:DD:ECOND
BUG:DD:ECOND
BUG:DD:ECOND
BUG:DD:ECOND
BUG:DD:ECOND

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;);

self = dev->priv;

ASSERT(self != NULL, return -1;);
ASSERT(self->magic == IRTTY_MAGIC, return -1;);

IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);

/* Disable interrupts & save flags */
==> Save flags, disable intr
save_flags(flags);
cli();
switch (cmd) {
case SIOCSBANDWIDTH: /* Set bandwidth */
if (!capable(CAP_NET_ADMIN))
==> Missing restore
return -EPERM;
irda_task_execute(self, irtty_change_speed, NULL, NULL,
(void *) irq->ifr_baudrate);
break;
case SIOCSDONGLE: /* Set dongle */
if (!capable(CAP_NET_ADMIN))
==> Missing restore
return -EPERM;
/* Initialize dongle */
dongle = irda_device_dongle_init(dev, irq->ifr_dongle);
if (!dongle)
break;
dongle->set_mode = irtty_set_mode;
dongle->read = irtty_raw_read;
dongle->write = irtty_raw_write;
dongle->set_dtr_rts = irtty_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);
break;
case SIOCSMEDIABUSY: /* Set media busy */
if (!capable(CAP_NET_ADMIN))
==> Missing restore
return -EPERM;
irda_device_set_media_busy(self->netdev, TRUE);
break;
case SIOCGRECEIVING: /* Check if we are receiving right now */
irq->ifr_receiving = irtty_is_receiving(self);
break;
case SIOCSDTRRTS:
if (!capable(CAP_NET_ADMIN))
==> Missing restore
return -EPERM;
irtty_set_dtr_rts(dev, irq->ifr_dtr, irq->ifr_rts);
break;
case SIOCSMODE:
if (!capable(CAP_NET_ADMIN))
==> Missing restore
return -EPERM;
irtty_set_mode(dev, irq->ifr_mode);
break;
default:
ret = -EOPNOTSUPP;
}
restore_flags(flags);

return ret;
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/net/irda/nsc-ircc.c:1930:nsc_ircc_net_ioctl: ERROR:INTR:DIS: leaving function with interrupts disabled
Similar to bugs above.
BUG:DD:ECOND
BUG:DD:ECOND

static int nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
...
/* Disable interrupts & save flags */
==> Disable here
save_flags(flags);
cli();
switch (cmd) {
case SIOCSBANDWIDTH: /* Set bandwidth */
if (!capable(CAP_NET_ADMIN))
==> Missing restore
return -EPERM;
nsc_ircc_change_speed(self, irq->ifr_baudrate);
break;
case SIOCSMEDIABUSY: /* Set media busy */
if (!capable(CAP_NET_ADMIN))
==> Missing restore
return -EPERM;
irda_device_set_media_busy(self->netdev, TRUE);
break;
case SIOCGRECEIVING: /* Check if we are receiving right now */
irq->ifr_receiving = nsc_ircc_is_receiving(self);
break;
default:
ret = -EOPNOTSUPP;
}
restore_flags(flags);

return ret;
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/net/irda/toshoboe.c:586:toshoboe_net_ioctl: ERROR:INTR:DIS: leaving function with interrupts disabled
Similar to bugs above.

BUG:DD:ECOND
BUG:DD:ECOND

static int toshoboe_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
...
/* Disable interrupts & save flags */
==> Disable here
save_flags(flags);
cli();
switch (cmd) {
case SIOCSBANDWIDTH: /* Set bandwidth */
if (!capable(CAP_NET_ADMIN))
==> Missing restore
return -EPERM;
/* toshoboe_setbaud(self, irq->ifr_baudrate); */
/* Just change speed once - inserted by Paul Bristow */
self->new_speed = irq->ifr_baudrate;
break;
case SIOCSMEDIABUSY: /* Set media busy */
if (!capable(CAP_NET_ADMIN))
==> Missing restore
return -EPERM;
irda_device_set_media_busy(self->netdev, TRUE);
break;
case SIOCGRECEIVING: /* Check if we are receiving right now */
irq->ifr_receiving = 0; /* Can't tell */
break;
default:
ret = -EOPNOTSUPP;
}
restore_flags(flags);

return ret;
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/net/irda/w83977af_ir.c:1315:w83977af_net_ioctl: ERROR:INTR:DIS: leaving function with interrupts disabled
Similar to bugs above.

BUG:DD:ECOND
BUG:DD:ECOND

static int w83977af_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
...
/* Disable interrupts & save flags */
==> Disable here
save_flags(flags);
cli();
switch (cmd) {
case SIOCSBANDWIDTH: /* Set bandwidth */
if (!capable(CAP_NET_ADMIN))
==> Missing restore
return -EPERM;
w83977af_change_speed(self, irq->ifr_baudrate);
break;
case SIOCSMEDIABUSY: /* Set media busy */
if (!capable(CAP_NET_ADMIN))
==> Missing restore
return -EPERM;
irda_device_set_media_busy(self->netdev, TRUE);
break;
case SIOCGRECEIVING: /* Check if we are receiving right now */
irq->ifr_receiving = w83977af_is_receiving(self);
break;
default:
ret = -EOPNOTSUPP;
}
restore_flags(flags);

return ret;
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/net/pcmcia/netwave_cs.c:1164:netwave_hw_xmit: ERROR:INTR:DIS: leaving function with interrupts disabled
BUG:DD:ECOND

static int netwave_hw_xmit(unsigned char* data, int len,
struct net_device* dev) {
/* Disable interrupts & save flags */
==> Disable here
save_flags(flags);
cli();
/* Check if there are transmit buffers available */
wait_WOC(iobase);
if ((inb(iobase+NETWAVE_REG_ASR) & NETWAVE_ASR_TXBA) == 0) {
/* No buffers available */
printk(KERN_DEBUG "netwave_hw_xmit: %s - no xmit buffers available.\n",
dev->name);
==> Missing restore
return 1;
}
...
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/net/pcmcia/nmclan_cs.c:1126:mace_interrupt: ERROR:LCK:HOLD: leaving function holding lock `(::mace_interrupt (int, void *, ::pt_regs *)::lp + 568)'
BUG:DD:ECOND

static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
...
==> Lock here
spin_lock (&lp->lock);
if (lp->tx_irq_disabled) {
printk(
(lp->tx_irq_disabled?
KERN_NOTICE "%s: Interrupt with tx_irq_disabled "
"[isr=%02X, imr=%02X]\n":
KERN_NOTICE "%s: Re-entering the interrupt handler "
"[isr=%02X, imr=%02X]\n"),
dev->name,
inb(ioaddr + AM2150_MACE_BASE + MACE_IR),
inb(ioaddr + AM2150_MACE_BASE + MACE_IMR)
);
/* WARNING: MACE_IR has been read! */
==> Missing unlock
return;
}
if (!netif_device_present(dev)) {
DEBUG(2, "%s: interrupt from dead card\n", dev->name);
goto exception;
}
...
exception:
spin_unlock (&lp->lock);
} /* mace_interrupt */
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/net/pcmcia/smc91c92_cs.c:1499:smc_interrupt: ERROR:LCK:HOLD: leaving function holding lock `(::smc_interrupt (int, void *, ::pt_regs *)::smc + 720)'
BUG:DD:ECOND

static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
==> Lock here
spin_lock (&smc->lock);
if ((saved_bank & 0xff00) != 0x3300) {
/* The device does not exist -- the card could be off-line, or
maybe it has been ejected. */
==> Goto irq_done below
goto irq_done;
}
==> Unlock here skipped!
spin_unlock (&smc->lock);

DEBUG(3, "%s: Exiting interrupt IRQ%d.\n", dev->name, irq);

==> Error jumps to here
irq_done:
...
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/net/pcmcia/wavelan_cs.c:2516:wavelan_get_wireless_stats: ERROR:LCK:HOLD: leaving function holding lock `::wavelan_get_wireless_stats (::device *)::lp'
BUG:DD:ECOND

static iw_stats *
wavelan_get_wireless_stats(device * dev)
{
ioaddr_t base = dev->base_addr;
net_local * lp = (net_local *) dev->priv;
mmr_t m;
iw_stats * wstats;
unsigned long flags;
/* Disable interrupts & save flags */
==> Lock here
spin_lock_irqsave (&lp->lock, flags);
==> Too late to test lp == null!
if(lp == (net_local *) NULL)
==> Impossible return
return (iw_stats *) NULL;
...
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/net/pcmcia/xirc2ps_cs.c:1389:xirc2ps_interrupt: ERROR:LCK:HOLD: leaving function holding lock `(::xirc2ps_interrupt (int, void *, ::pt_regs *)::lp + 704)'
BUG:DD

static void
xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
==> Lock
spin_lock (&lp->lock);
if (!netif_device_present(dev))
==> Missing unlock
return;
...
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/net/sk98lin/skge.c:2389:SkGeChangeMtu: ERROR:LCK:HOLD: leaving function holding lock `((::SkGeChangeMtu (::net_device *, int)::pAC + (+(::SkGeChangeMtu (::net_device *, int)::i * 88))) + 14336)'
BUG:DD: counts as one bug b/c the checker only found a side-effect of the errors

static int SkGeChangeMtu(struct net_device *dev, int NewMtu)
{
...
==> Lock here, save flags
spin_lock_irqsave(&pAC->SlowPathLock, Flags);
SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
SkEventDispatcher(pAC, pAC->IoBase);
for (i=0; i<pAC->GIni.GIMacsFound; i++) {
==> Bogus: Overwrites flags
spin_lock_irqsave(
&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock, Flags);
}
netif_stop_queue(pAC->dev);
...
netif_start_queue(pAC->dev);
for (i=pAC->GIni.GIMacsFound-1; i>=0; i--) {
==> Bogus: leaves intr disabled
spin_unlock_irqrestore(
&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock, Flags);
}
/* enable Interrupts */
SK_OUT32(pAC->IoBase, B0_IMSK, IRQ_MASK);
SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK);
SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
SkEventDispatcher(pAC, pAC->IoBase);

==> Bogus: flags already mucked
spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);

return 0;
} /* SkGeChangeMtu */
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/net/slip.c:1249:sl_ioctl: ERROR:BH:DIS: leaving function with bottom half disabled
BUG:DD:ECOND
BUG:DD:ECOND

There are more bugs in this function, counted below.

static int sl_ioctl(struct net_device *dev,struct ifreq *rq,int cmd)
{
struct slip *sl = (struct slip*)(dev->priv);
if (sl == NULL) /* Allocation failed ?? */
return -ENODEV;
==> Lock here
spin_lock_bh(&sl->lock);
...
switch(cmd){
case SIOCSKEEPALIVE:
/* max for unchar */
if (((unsigned int)((unsigned long)rq->ifr_data)) > 255)
==> Not unlocking
return -EINVAL;
sl->keepalive = (unchar) ((unsigned long)rq->ifr_data);
if (sl->keepalive != 0) {
sl->keepalive_timer.expires=jiffies+sl->keepalive*HZ;
mod_timer(&sl->keepalive_timer, jiffies+sl->keepalive*HZ);
set_bit(SLF_KEEPTEST, &sl->flags);
} else {
del_timer(&sl->keepalive_timer);
}
spin_unlock_bh(&sl->lock);
break;
case SIOCGKEEPALIVE:
rq->ifr_data=(caddr_t)((unsigned long)sl->keepalive);
break;

case SIOCSOUTFILL:
if (((unsigned)((unsigned long)rq->ifr_data)) > 255) /* max for unchar */
==> Not unlocking
return -EINVAL;
if ((sl->outfill = (unchar)((unsigned long) rq->ifr_data)) != 0){
mod_timer(&sl->outfill_timer, jiffies+sl->outfill*HZ);
set_bit(SLF_OUTWAIT, &sl->flags);
} else {
del_timer (&sl->outfill_timer);
}
break;
case SIOCGOUTFILL:
rq->ifr_data=(caddr_t)((unsigned long)sl->outfill);
break;

case SIOCSLEASE:
/* Resolve race condition, when ioctl'ing hanged up
and opened by another process device.
*/
if (sl->tty != current->tty && sl->pid != current->pid) {
spin_unlock_bh(&sl->lock);
return -EPERM;
}
sl->leased = 0;
if ((unsigned long)rq->ifr_data)
sl->leased = 1;
break;
case SIOCGLEASE:
rq->ifr_data=(caddr_t)((unsigned long)sl->leased);
};
spin_unlock_bh(&sl->lock);
return 0;
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/net/slip.c:1313:sl_ioctl: ERROR:LCK:2U: double unlock
Same function as above, different bug:
BUG:DD

static int sl_ioctl(struct net_device *dev,struct ifreq *rq,int cmd)
{
struct slip *sl = (struct slip*)(dev->priv);
==> Lock here
spin_lock_bh(&sl->lock);

switch(cmd){
case SIOCSKEEPALIVE:
/* max for unchar */
if (((unsigned int)((unsigned long)rq->ifr_data)) > 255)
return -EINVAL;
sl->keepalive = (unchar) ((unsigned long)rq->ifr_data);
if (sl->keepalive != 0) {
sl->keepalive_timer.expires=jiffies+sl->keepalive*HZ;
mod_timer(&sl->keepalive_timer, jiffies+sl->keepalive*HZ);
set_bit(SLF_KEEPTEST, &sl->flags);
} else {
del_timer(&sl->keepalive_timer);
}
==> Unlock here
spin_unlock_bh(&sl->lock);
break;
... many buggy cases ...
}
...
==> Double unlock here
spin_unlock_bh(&sl->lock);
return 0;
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/net/tokenring/smctr.c:3578:smctr_open_tr: ERROR:INTR:DIS: leaving function with interrupts disabled
BUG:DD:ECOND: should these count as separate bugs?
BUG:DD:ECOND: should these count as separate bugs?
BUG:DD:ECOND: should these count as separate bugs?
BUG:DD:ECOND: should these count as separate bugs?

/* Interrupt driven open of Token card. */
static int smctr_open_tr(struct net_device *dev)
{
==> Disable intr
save_flags(flags);
cli();
smctr_set_page(dev, (__u8 *)tp->ram_access);

if((err = smctr_issue_resume_rx_fcb_cmd(dev, (short)MAC_QUEUE)))
==> Missing restore
return (err);
if((err = smctr_issue_resume_rx_bdb_cmd(dev, (short)MAC_QUEUE)))
==> Missing restore
return (err);
if((err = smctr_issue_resume_rx_fcb_cmd(dev, (short)NON_MAC_QUEUE)))
==> Missing restore
return (err);
if((err = smctr_issue_resume_rx_bdb_cmd(dev, (short)NON_MAC_QUEUE)))
==> Missing restore
return (err);
...
restore_flags(flags);
return (err);
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/net/tokenring/smctr.c:4596:smctr_rx_frame: ERROR:INTR:DIS: leaving function with interrupts disabled
BUG:DD: suspicious at the very least

static int smctr_rx_frame(struct net_device *dev)
{
struct net_local *tp = (struct net_local *)dev->priv;
__u16 queue, status, rx_size, err = 0;
__u8 *pbuff;
if(smctr_debug > 10)
printk("%s: smctr_rx_frame\n", dev->name);
==> cli
cli();
queue = tp->receive_queue_number;

while((status = tp->rx_fcb_curr[queue]->frame_status) != SUCCESS)
{
err = HARDWARE_FAILED;
if(((status & 0x007f) == 0)
|| ((tp->receive_mask & ACCEPT_ERR_PACKETS) != 0))
{
/* frame length less the CRC (4 bytes) + FS (1 byte) */
rx_size = tp->rx_fcb_curr[queue]->frame_length - 5;
pbuff = smctr_get_rx_pointer(dev, queue);

smctr_set_page(dev, pbuff);
smctr_disable_16bit(dev);

/* pbuff points to addr within one page */
pbuff = (__u8 *)PAGE_POINTER(pbuff);
if(queue == NON_MAC_QUEUE)
{
struct sk_buff *skb;
==> An unrelated bug: skb may be null, accessed in skb_put
skb = dev_alloc_skb(rx_size);
skb_put(skb, rx_size);

memcpy(skb->data, pbuff, rx_size);
==> Enable intr... but then this loop executed with intr's enabled
sti();

/* Update Counters */
tp->MacStat.rx_packets++;
tp->MacStat.rx_bytes += skb->len;
/* Kick the packet on up. */
skb->dev = dev;
skb->protocol = tr_type_trans(skb, dev);
netif_rx(skb);
}
else
smctr_process_rx_packet((MAC_HEADER *)pbuff,
rx_size, dev, status);
}
smctr_enable_16bit(dev);
smctr_set_page(dev, (__u8 *)tp->ram_access);
smctr_update_rx_chain(dev, queue);

if(err != SUCCESS)
break;
}
==> Not restoring interrupt status...
return (err);
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/net/wan/comx-hw-mixcom.c:479:MIXCOM_open: ERROR:INTR:DIS: leaving function with interrupts disabled
BUG:DD:ECOND

static int MIXCOM_open(struct net_device *dev)
{
...
==> Disable intr
save_flags(flags); cli();
if(hw->channel==1) {
request_region(dev->base_addr, MIXCOM_IO_EXTENT, dev->name);
}
if(hw->channel==0 && !(ch->init_status & IRQ_ALLOCATED)) {
if (request_irq(dev->irq, MIXCOM_interrupt, 0,
dev->name, (void *)dev)) {
printk(KERN_ERR "MIXCOM: unable to obtain irq %d\n", dev->irq);
==> Missing restore
return -EAGAIN;
}
ch->init_status|=IRQ_ALLOCATED;
request_region(dev->base_addr, MIXCOM_IO_EXTENT, dev->name);
mixcom_board_on(dev);
}
...
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/net/wan/lmc/lmc_main.c:152:lmc_ioctl: ERROR:LCK:HOLD: leaving function holding lock `(::lmc_ioctl (::net_device *, ::ifreq *, int)::sc + 1872)'
This bug occurs in two macros, though the macros appear many times
BUG:DD:ECOND
BUG:DD:ECOND

int lmc_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) /*fold00*/
{
...
==> Lock, disable intr
spin_lock_irqsave(&sc->lmc_lock, flags);
switch (cmd) {
case LMCIOCGINFO: /*fold01*/
==> This macro causes 2 bugs: copy_to_user and returns if error
LMC_COPY_TO_USER(ifr->ifr_data, &sc->ictl, sizeof (lmc_ctl_t));
ret = 0;
break;
}
==> The broken macro (and also LMC_COPY_FROM_USER) is used in 9 other cases
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/net/wan/lmc/lmc_main.c:650:lmc_watchdog: ERROR:LCK:HOLD: leaving function holding lock `(::lmc_watchdog (long unsigned int)::sc + 1872)'
BUG:DD:ECOND

static void lmc_watchdog (unsigned long data) /*fold00*/
{
...
==> Lock
spin_lock_irqsave(&sc->lmc_lock, flags);
if(sc->check != 0xBEAFCAFE){
printk("LMC: Corrupt net_device stuct, breaking out\n");
==> Not unlocking
return;
}
...
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/net/wavelan.c:3662:wavelan_interrupt: ERROR:LCK:HOLD: leaving function holding lock `(::wavelan_interrupt (int, void *, ::pt_regs *)::lp + 8)'
BUG:DD:ECOND

static void wavelan_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
...
==> Lock
spin_lock(&lp->spinlock);
...
/* Check if not controller interrupt */
if ((hasr & HASR_82586_INTR) == 0) {
#ifdef DEBUG_INTERRUPT_ERROR
printk(KERN_INFO
"%s: wavelan_interrupt(): interrupt not coming from i82586\n",
dev->name);
#endif
==> Missing unlock
return;
}
...
/* Release spinlock here so that wv_hw_reset() can grab it */
spin_unlock (&lp->spinlock);
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/scsi/53c7,8xx.c:4154:process_issue_queue: ERROR:FLAGS: restoring flags without saving them
BUG:DD:FLAGARG passing flags in as argument
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/scsi/aic7xxx.c:7021:do_aic7xxx_isr: ERROR:LCK:HOLD: leaving function holding lock `&::io_request_lock'
BUG:DD

/*+F*************************************************************************
* Function:
* do_aic7xxx_isr
*
* Description:
* This is a gross hack to solve a problem in linux kernels 2.1.85 and
* above. Please, children, do not try this at home, and if you ever see
* anything like it, please inform the Gross Hack Police immediately
*-F*************************************************************************/
static void
do_aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned long cpu_flags;
struct aic7xxx_host *p;
p = (struct aic7xxx_host *)dev_id;
if(!p)
return;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,95)
==> Lock
spin_lock_irqsave(&io_request_lock, cpu_flags);
if(test_and_set_bit(AHC_IN_ISR_BIT, (void *)&p->flags))
{
==> Missing unlock
return;
}
do
{
aic7xxx_isr(irq, dev_id, regs);
} while ( (aic_inb(p, INTSTAT) & INT_PEND) );
aic7xxx_done_cmds_complete(p);
aic7xxx_run_waiting_queues(p);
clear_bit(AHC_IN_ISR_BIT, (void *)&p->flags);
spin_unlock_irqrestore(&io_request_lock, cpu_flags);
#else
if(set_bit(AHC_IN_ISR_BIT, (int *)&p->flags))
{
return;
}
DRIVER_LOCK
do
{
aic7xxx_isr(irq, dev_id, regs);
} while ( (aic_inb(p, INTSTAT) & INT_PEND) );
DRIVER_UNLOCK
aic7xxx_done_cmds_complete(p);
aic7xxx_run_waiting_queues(p);
clear_bit(AHC_IN_ISR_BIT, (int *)&p->flags);
#endif
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/scsi/eata_dma.c:454:eata_queue: ERROR:INTR:DIS: leaving function with interrupts disabled
BUG:DD:ECOND

int eata_queue(Scsi_Cmnd * cmd, void (* done) (Scsi_Cmnd *))
{
...
==> Disable intr
save_flags(flags);
cli();
...
if (cmd->cmnd[0] == REQUEST_SENSE && cmd->sense_buffer[0] != 0) {
DBG(DBG_REQSENSE, printk(KERN_DEBUG "Tried to REQUEST SENSE\n"));
cmd->result = DID_OK << 16;
done(cmd);
==> Missing restore
return(0);
}
...
if (x >= sh->can_queue) {
cmd->result = DID_BUS_BUSY << 16;
DBG(DBG_QUEUE && DBG_ABNORM,
printk(KERN_CRIT "eata_queue pid %ld, HBA QUEUE FULL..., "
"returning DID_BUS_BUSY\n", cmd->pid));
done(cmd);
==> Did the Right Thing here
restore_flags(flags);
return(0);
}
...
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/scsi/qla1280.c:1506:qla1280_intr_handler: ERROR:LCK:HOLD: leaving function holding lock `&::io_request_lock'
BUG:DD

void qla1280_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
{
...
==> Lock, disable intr here
spin_lock_irqsave(&io_request_lock, cpu_flags);
if(test_and_set_bit(QLA1280_IN_ISR_BIT, &ha->flags))
{
COMTRACE('X')
==> Missing unlock
return;
}
...
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/scsi/sg.c:2514:sg_proc_debug_info: ERROR:LCK:HOLD: leaving function holding lock `&::sg_dev_arr_lock'
BUG:DD

static int sg_proc_debug_info(char * buffer, int * len, off_t * begin,
off_t offset, int size)
{
Sg_device * sdp;
const sg_io_hdr_t * hp;
int j, max_dev;
if (NULL == sg_dev_arr) {
PRINT_PROC("sg_dev_arr NULL, driver not initialized\n");
return 1;
}
==> Lock here
read_lock(&sg_dev_arr_lock);
max_dev = sg_last_dev();
PRINT_PROC("dev_max(currently)=%d max_active_device=%d (origin 1)\n",
sg_template.dev_max, max_dev);
PRINT_PROC(" scsi_dma_free_sectors=%u sg_pool_secs_aval=%d "
"def_reserved_size=%d\n",
scsi_dma_free_sectors, sg_pool_secs_avail, sg_big_buff);
for (j = 0; j < max_dev; ++j) {
if ((sdp = sg_dev_arr[j])) {
Sg_fd * fp;
Sg_request * srp;
struct scsi_device * scsidp;
int dev, k, blen, usg;
if (! (scsidp = sdp->device)) {
PRINT_PROC("device %d detached ??\n", j);
continue;
}
dev = MINOR(sdp->i_rdev);
if ((fp = sdp->headfp)) {
PRINT_PROC(" >>> device=%d(sg%d) ", dev, dev);
PRINT_PROC("scsi%d chan=%d id=%d lun=%d em=%d sg_tablesize=%d"
" excl=%d\n", scsidp->host->host_no, scsidp->channel,
scsidp->id, scsidp->lun, scsidp->host->hostt->emulated,
sdp->sg_tablesize, sdp->exclude);
}
for (k = 1; fp; fp = fp->nextfp, ++k) {
PRINT_PROC(" FD(%d): timeout=%d bufflen=%d "
"(res)sgat=%d low_dma=%d\n",
k, fp->timeout, fp->reserve.bufflen,
(int)fp->reserve.k_use_sg, (int)fp->low_dma);
PRINT_PROC(" cmd_q=%d f_packid=%d k_orphan=%d closed=%d\n",
(int)fp->cmd_q, (int)fp->force_packid,
(int)fp->keep_orphan, (int)fp->closed);
srp = fp->headrp;
if (NULL == srp)
PRINT_PROC(" No requests active\n");
while (srp) {
hp = &srp->header;
/* stop indenting so far ... */
PRINT_PROC(srp->res_used ? " rb>> " :
((SG_INFO_DIRECT_IO_MASK & hp->info) ? " dio>> " : " "));
blen = srp->my_cmdp ? srp->my_cmdp->bufflen : srp->data.bufflen;
usg = srp->my_cmdp ? srp->my_cmdp->use_sg : srp->data.k_use_sg;
PRINT_PROC(srp->done ? "rcv: id=%d" : (srp->my_cmdp ? "act: id=%d" :
"prior: id=%d"), srp->header.pack_id);
PRINT_PROC(" blen=%d", blen);
if (srp->done)
PRINT_PROC(" dur=%d", sg_jif_to_ms(hp->duration));
else
PRINT_PROC(" t_o/elap=%d/%d", ((hp->interface_id == '\0') ?
sg_jif_to_ms(fp->timeout) : hp->timeout),
sg_jif_to_ms(hp->duration ? (jiffies - hp->duration) : 0));
PRINT_PROC(" sgat=%d op=0x%02x\n", usg, (int)srp->data.cmd_opcode);
srp = srp->nextrp;
/* reset indenting */
}
}
}
}
==> Unlock here
read_unlock(&sg_dev_arr_lock);
return 1;
}
Didn't see the bug? Look at this:

#define PRINT_PROC(fmt,args...) \
do { \
*len += sprintf(buffer + *len, fmt, ##args); \
if (*begin + *len > offset + size) \
==> Here we go
return 0; \
if (*begin + *len < offset) { \
*begin += *len; \
*len = 0; \
} \
} while(0)

--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/scsi/sg.c:2594:sg_proc_dev_info: ERROR:LCK:HOLD: leaving function holding lock `&::sg_dev_arr_lock'
BUG:DD

static int sg_proc_dev_info(char * buffer, int * len, off_t * begin,
off_t offset, int size)
{
Sg_device * sdp;
int j, max_dev;
struct scsi_device * scsidp;
==> Lock here
read_lock(&sg_dev_arr_lock);
max_dev = sg_last_dev();
for (j = 0; j < max_dev; ++j) {
sdp = sg_dev_arr[j];
if (sdp && (scsidp = sdp->device))
==> See above macro
PRINT_PROC("%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
scsidp->host->host_no, scsidp->channel, scsidp->id,
scsidp->lun, (int)scsidp->type, (int)scsidp->disconnect,
(int)scsidp->queue_depth, (int)scsidp->tagged_queue);
else
==> See above macro
PRINT_PROC("-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\n");
}
read_unlock(&sg_dev_arr_lock);
return 1;
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/scsi/sg.c:2632:sg_proc_devstrs_info: ERROR:LCK:HOLD: leaving function holding lock `&::sg_dev_arr_lock'
BUG:DD

static int sg_proc_devstrs_info(char * buffer, int * len, off_t * begin,
off_t offset, int size)
{
Sg_device * sdp;
int j, max_dev;
struct scsi_device * scsidp;
==> Lock here
read_lock(&sg_dev_arr_lock);
max_dev = sg_last_dev();
for (j = 0; j < max_dev; ++j) {
sdp = sg_dev_arr[j];
if (sdp && (scsidp = sdp->device))
==> See above macro
PRINT_PROC("%8.8s\t%16.16s\t%4.4s\n",
scsidp->vendor, scsidp->model, scsidp->rev);
else
==> See above macro
PRINT_PROC("<no active device>\n");
}
read_unlock(&sg_dev_arr_lock);
return 1;
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/scsi/sim710.c:1256:process_issue_queue: ERROR:FLAGS: restoring flags without saving them
BUG:DD:FLAGARG flags used as argument...
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/sound/ad1848.c:2724:ad1848_resume: ERROR:INTR:DIS: leaving function with interrupts disabled
BUG:DD:ECOND

static int ad1848_resume(ad1848_info *devc)
{
==> Disable intr
save_flags(flags);
cli();
if (!devc->subtype) {
...
if (bits == -1) {
printk(KERN_ERR "MSS: Bad IRQ %d\n", devc->irq);
==> Missing restore
return -1;
}
...
}
...
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/sound/gus_wave.c:637:start_release: ERROR:FLAGS: restoring flags without saving them
BUG:DD:FLAGARG: flags passed as argument
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/sound/i810_audio.c:919:i810_interrupt: ERROR:LCK:HOLD: leaving function holding lock `(::i810_interrupt (int, void *, ::pt_regs *)::card + 824)'
BUG:DD

static void i810_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct i810_card *card = (struct i810_card *)dev_id;
u32 status;
==> Lock
spin_lock(&card->lock);

status = inl(card->iobase + GLOB_STA);
if(!(status & INT_MASK))
==> Missing unlock
return; /* not for us */
// printk("Interrupt %X: ", status);
if(status & (INT_PO|INT_PI|INT_MC))
i810_channel_interrupt(card);
/* clear 'em */
outl(status & INT_MASK, card->iobase + GLOB_STA);
spin_unlock(&card->lock);
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/sound/sscape.c:938:sscape_pnp_upload_file: ERROR:INTR:DIS: leaving function with interrupts disabled
BUG:DD

static int sscape_pnp_upload_file(sscape_info* devc, char* fn)
{
...
==> Disable intr
save_flags(flags);
cli();
while ( len > 0 ) {
==> Missing restore
if (sscape_pnp_wait_dma ( devc, 0 ) == 0) return 0;
}
restore_flags(flags);
...
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/drivers/usb/usb-ohci.c:886:ep_add_ed: ERROR:LCK:HOLD: leaving function holding lock `&::usb_ed_lock'
really two bugs

BUG:DD
BUG:DD:ECOND

static ed_t * ep_add_ed (struct usb_device * usb_dev, unsigned int pipe, int interval, int load)
{
...
==> Lock
spin_lock (&usb_ed_lock);
if((ed->state & ED_DEL) || (ed->state & ED_URB_DEL))
==> Missing unlock 1
return NULL; /* pending delete request */
if (ed->state == ED_NEW) {
ed->hwINFO = cpu_to_le32 (OHCI_ED_SKIP); /* skip ed */
OHCI_ALLOC (td, sizeof (*td)); /* dummy td; end of td list for ed */
==> Missing unlock 2
if(!td) return NULL; /* out of memory */
...
}
...
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/net/ipv4/netfilter/ip_queue.c:258:ipq_receive_peer: ERROR:BH:DIS: leaving function with bottom half disabled
BUG:NET:ECOND: I think...

static int ipq_receive_peer(ipq_queue_t *q, ipq_peer_msg_t *m,
unsigned char type, unsigned int len)
{
==> Locking here
spin_lock_bh(&q->lock);
if (q->terminate || q->flushing)
==> Missing unlock?
return -EBUSY;
spin_unlock_bh(&q->lock);
...
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/net/ipv4/netfilter/ip_queue.c:258:ipq_receive_peer: ERROR:LCK:HOLD: leaving function holding lock `(::ipq_receive_peer (::ipq_queue_t *, ::ipq_peer_msg_t *, unsigned char, unsigned int)::q + 20)'
BUG:NET:ECOND: same as above
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/net/ipv6/ip6_flowlabel.c:405:ipv6_flowlabel_opt: ERROR:BH:DIS: leaving function with bottom half disabled
BUG:NET

int ipv6_flowlabel_opt(struct sock *sk, char *optval, int optlen)
{
switch (freq.flr_action) {
...
case IPV6_FL_A_RENEW:
==> Lock here, disable BH
read_lock_bh(&ip6_sk_fl_lock);
for (sfl = np->ipv6_fl_list; sfl; sfl = sfl->next) {
if (sfl->fl->label == freq.flr_label)
==> Missing unlock, reenable
return fl6_renew(sfl->fl, freq.flr_linger, freq.flr_expires);
}
read_unlock_bh(&ip6_sk_fl_lock);
if (freq.flr_share == IPV6_FL_S_NONE && capable(CAP_NET_ADMIN)) {
fl = fl_lookup(freq.flr_label);
if (fl) {
err = fl6_renew(fl, freq.flr_linger, freq.flr_expires);
fl_release(fl);
return err;
}
}
return -ESRCH;
...
}
...
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/net/ipv6/ip6_flowlabel.c:405:ipv6_flowlabel_opt: ERROR:LCK:HOLD: leaving function holding lock `&::ip6_sk_fl_lock'
BUG:NET: same as above
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/net/ipx/af_spx.c:427:spx_transmit: ERROR:INTR:DIS: leaving function with interrupts disabled
BUG:NET:ECOND

static int spx_transmit(struct sock *sk, struct sk_buff *skb, int type, int len)
{
...
if(skb == NULL)
{
...
==> Disable intr
save_flags(flags);
cli();
skb = sock_alloc_send_skb(sk, size, 1, 0, &err);
if(skb == NULL)
==> Missing restore
return (-ENOMEM);
skb_reserve(skb, offset);
skb->h.raw = skb->nh.raw = skb_put(skb,sizeof(struct ipxspxhdr));
restore_flags(flags);
}
...
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/net/ipx/af_spx.c:728:spx_sendmsg: ERROR:INTR:DIS: leaving function with interrupts disabled
BUG:NET:ECOND

static int spx_sendmsg(struct socket *sock, struct msghdr *msg, int len,
struct scm_cookie *scm)
{
...
==> Disable intr
cli();
skb = sock_alloc_send_skb(sk, size, 0, flags&MSG_DONTWAIT, &err);
if(skb == NULL)
==> Missing enable
return (err);
sti();
...
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/net/irda/ircomm/ircomm_core.c:490:ircomm_proc_read: ERROR:INTR:DIS: leaving function with interrupts disabled
BUG:NET:ECOND

int ircomm_proc_read(char *buf, char **start, off_t offset, int len)
{
struct ircomm_cb *self;
unsigned long flags;
int i=0;
==> Disable intr
save_flags(flags);
cli();

len = 0;

len += sprintf(buf+len, "Instance %d:\n", i++);

self = (struct ircomm_cb *) hashbin_get_first(ircomm);
while (self != NULL) {
==> Missing restore
ASSERT(self->magic == IRCOMM_MAGIC, return len;);
self = (struct ircomm_cb *) hashbin_get_next(ircomm);
}
restore_flags(flags);
return len;
}
The macro-expanded version of the above ASSERT is:

if(!( self->magic == 0x98347298 )) {
printk( "Assertion failed! %s,%s,%s,line=%d\n",
"self->magic == IRCOMM_MAGIC",
"ircomm_core.c","" ,504);
return len;
} ;
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/net/irda/ircomm/ircomm_tty.c:499:ircomm_tty_close: ERROR:INTR:DIS: leaving function with interrupts disabled
BUG:NET:ECOND
BUG:NET:ECOND

static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
{
...
==> Disable intr
save_flags(flags);
cli();
==> Missing restore
ASSERT(self != NULL, return;);
==> Missing restore
ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
...
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/net/irda/iriap.c:971:irias_proc_read: ERROR:INTR:DIS: leaving function with interrupts disabled
BUG:NET:ECOND
BUG:NET:ECOND

int irias_proc_read(char *buf, char **start, off_t offset, int len)
{
==> Disable intr
save_flags( flags);
cli();
while ( obj != NULL) {
==> Missing restore
ASSERT(obj->magic == IAS_OBJECT_MAGIC, return 0;);
...
while (attrib != NULL) {
==> Missing restore
ASSERT(attrib->magic == IAS_ATTRIB_MAGIC, return 0;);
...
}
}
...
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/net/irda/irlan/irlan_common.c:1158:irlan_proc_read: ERROR:INTR:DIS: leaving function with interrupts disabled
BUG:NET:ECOND

static int irlan_proc_read(char *buf, char **start, off_t offset, int len)
{
struct irlan_cb *self;
unsigned long flags;
==> Disable intr
save_flags(flags);
cli();

while (self != NULL) {
==> Missing restore
ASSERT(self->magic == IRLAN_MAGIC, return len;);
...
}
restore_flags(flags);
return len;
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/net/irda/irlap.c:1134:irlap_proc_read: ERROR:INTR:DIS: leaving function with interrupts disabled
BUG:NET:ECOND
BUG:NET:ECOND

int irlap_proc_read(char *buf, char **start, off_t offset, int len)
{
struct irlap_cb *self;
unsigned long flags;
int i = 0;
==> Disable intr
save_flags(flags);
cli();

len = 0;

self = (struct irlap_cb *) hashbin_get_first(irlap);
while (self != NULL) {
==> Missing restore
ASSERT(self != NULL, return -ENODEV;);
==> Missing restore
ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
}
...
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/net/irda/irlmp.c:1498:irlmp_proc_read: ERROR:INTR:DIS: leaving function with interrupts disabled
BUG:NET:ECOND
BUG:NET:ECOND

int irlmp_proc_read(char *buf, char **start, off_t offset, int len)
{
==> Disable intr
save_flags( flags);
cli();
...
while (self != NULL) {
==> Missing restore
ASSERT(self->magic == LMP_LSAP_MAGIC, return 0;);
...
}
while (lap != NULL) {
...
while (self != NULL) {
==> Missing restore
ASSERT(self->magic == LMP_LSAP_MAGIC, return 0;);
...
}
...
}
restore_flags(flags);
return len;
}
--------------------------------------------------------------------------------
/home/acc/linux-2.3.99/net/irda/irttp.c:1507:irttp_proc_read: ERROR:INTR:DIS: leaving function with interrupts disabled
BUG:NET

int irttp_proc_read(char *buf, char **start, off_t offset, int len)
{
...
==> Disable intr
save_flags(flags);
cli();
while (self != NULL) {
if (!self || self->magic != TTP_TSAP_MAGIC)
==> Missing restore
return len;
...
}
...
}
\
 
 \ /
  Last update: 2005-03-22 13:58    [from the cache]
©2003-2011 Jasper Spaans