potential kernel deadlocks and races

From: Seth Andrew Hallem (shallem@Stanford.EDU)
Date: Tue Aug 08 2000 - 20:39:45 EST


Hi,

I am working with Dawson Engler at Stanford. We have
another g++ extension which checks that potentially sleeping
functions are not called with interrupts off or spinlocks held. The
check uses a list of sleeping function from Rusty's "Unreliable Guide
to Linux Kernel Hacking" which includes kmalloc without the flag
GFP_ATOMIC and all the user space functions.
We were wondering if anyone could confirm the potential bugs we have
found. I have included a slimmed down list of what I found
below. Each error indicates where the error occurred, a code snippet
showing the context, and a small comment about why we thought
it could be an error. Any help would be much appreciated.
We were also wondering if anyone could provide an answer to why
functions should not sleep with spinlocks held. It is easy to see
that this can potentially lead to deadlock, but we are unsure as to
why the "Unreliable Guide" said that you should never do this.

Thank you,

Seth Hallem

Error list:
======================================================================

In cases where the same code snippet appeared to have several errors,
I have only reported one of the errors. All of the errors are marked
with line numbers in the code snippets.

linux-2.3.99/drivers/block/cpqarray.c:1109:do_ida_intr: ERROR:
Calling blocking fn with spin lock held in fn: do_ida_request. [SPIN]
[NOTE: do_ida_request is defined on line 877. It calls cmd_alloc,
defined on line 1301. cmd_alloc calls kmalloc with flag GFP_KERNEL.]
{
        spin_lock_irqsave(&io_request_lock, flags);
        ...
        do_ida_request(h->ctlr);
        spin_unlock_irqrestore(&io_request_lock, flags);
        
}

linux-2.3.99/drivers/char/joystick/joystick.c:336:js_read: ERROR:
Calling blocking fn with spin lock held in fn: copy_to_user. [SPIN]
{
        Calls copy_to_user with a spin lock held:
        if (count != sizeof(struct JS_DATA_TYPE)) {
        ...
        /*
         * Lock it.
         */
                spin_lock_irqsave(&js_lock, flags);
        /*
         * Handle (non)blocking i/o.
         */
        ....
        /* returns at end of this block if successful.
           spin locks still held. */
                
        while (curl->startup < jd->num_axes + jd->num_buttons
                && written < blocks && !retval) {
                struct js_event tmpevent;
                ...
                /* play with tmpevent. shouldn't have
                anything to do with spinlocks. */
                        
                /* DIE 336 */
                if (copy_to_user(&buff[written], &tmpevent,
                        sizeof(struct js_event)))
                        retval = -EFAULT;
                        ...
                }
        /*
         * Buffer data.
          */
        while ((jd->bhead != (new_tail = GOF(curl->tail))) &&
                (written < blocks) && !retval) {
                /* DIE 349 */
                if (copy_to_user(&buff[written],
                &jd->buff[new_tail], sizeof(struct js_event)))
                        retval = -EFAULT;
                /* DIE 351 */
                if (put_user((__u32)(jd->buff[new_tail].time * (1000/HZ)),
                        &buff[written].time))
                        retval = -EFAULT;
                        ...
                }
        
        else
        /*
          * Handle version 0.x compatibility.
          */
        {
                struct JS_DATA_TYPE data;
                /* screw with data */
                ...
                
                retval =
                copy_to_user(buf, &data, sizeof(struct JS_DATA_TYPE))
                        ? -EFAULT : 0;
                ...
        }
}

linux-2.3.99/drivers/net/pcmcia/netwave_cs.c:696:netwave_ioctl:
ERROR: Calling blocking fn with interrupts disabled in fn:
copy_to_user. [INTERRUPTS] {
            /* disable interrupts */
        save_flags(flags);
        cli();
        /* Look what is the request */
        switch(cmd) {
        
        ...
        #if WIRELESS_EXT > 8 /* Note : The API did change... */
            case SIOCGIWENCODE:
        
        /* Get scramble key */
        if(wrq->u.encoding.pointer != (caddr_t) 0)
696: if(copy_to_user(wrq->u.encoding.pointer, key, 2))
                        ret = -EFAULT;
        case SIOCSIWENCODE:
        /* Set scramble key */
        if(wrq->u.encoding.pointer != (caddr_t) 0)
705: if(copy_from_user(key, wrq->u.encoding.pointer, 2))
                {
                        ret = -EFAULT;
                        break;
                      }
        
        case SIOCGIWRANGE:
        /* Basic checking... */
               if(wrq->u.data.pointer != (caddr_t) 0) {
                ...
                /* Copy structure to the user buffer */
773: if(copy_to_user(wrq->u.data.pointer, &range,
                        sizeof(struct iw_range)))
                             ret = -EFAULT;
        case SIOCGIWPRIV:
        /* Basic checking... */
        if(wrq->u.data.pointer != (caddr_t) 0) {
                /* Copy structure to the user buffer */
792: if(copy_to_user(wrq->u.data.pointer, (u_char *) priv,
                         sizeof(priv)))
                        ret = -EFAULT;
        case SIOCGIPSNAP:
        if(wrq->u.data.pointer != (caddr_t) 0) {
                /* Copy structure to the user buffer */
803: if(copy_to_user(wrq->u.data.pointer,
                         (u_char *) &priv->nss,
                         sizeof( struct site_survey)))
                      {
                        printk(KERN_DEBUG "Bad buffer!\n");
                        break;
                      }
        /* ReEnable interrupts & restore flags */
            restore_flags(flags);
}

linux-2.3.99/drivers/net/pcmcia/wavelan_cs.c:2040:wavelan_ioctl:
ERROR: Calling blocking fn with spin lock held in fn: copy_from_user.
[SPIN] {
        /* Disable interrupts & save flags */
          spin_lock_irqsave (&lp->lock, flags);
        #if WIRELESS_EXT > 8
        case SIOCSIWENCODE:
        
        /* Basic checking... */
        if(wrq->u.encoding.pointer != (caddr_t) 0)
                ...
                /* Copy the key in the driver */
2040: i f(copy_from_user(psa.psa_encryption_key, wrq->u.encoding.pointer,
                                wrq->u.encoding.length))
                    {
                              ret = -EFAULT;
                              break;
                    }
        case SIOCGIWENCODE:
        ...
        if(wrq->u.encoding.pointer != (caddr_t) 0)
                /* Copy the key to the user buffer */
                wrq->u.encoding.length = 8;
2099: if(copy_to_user(wrq->u.encoding.pointer,
                psa.psa_encryption_key, 8))
                        ret = -EFAULT;
        #endif /* WIRELESS_EXT > 8 */
        ...
        case SIOCGIWRANGE:
        /* Basic checking... */
        if(wrq->u.data.pointer != (caddr_t) 0)
                ...
                /* Copy structure to the user buffer */ 2281:
                if(copy_to_user(wrq->u.data.pointer, &range,
                        sizeof(struct iw_range)))
                            ret = -EFAULT;
        case SIOCGIWPRIV:
        /* Basic checking... */
        if(wrq->u.data.pointer != (caddr_t) )
                /* Copy structure to the user buffer */ 2305:
                if(copy_to_user(wrq->u.data.pointer, (u_char *) priv,
                        sizeof(priv)))
                        ret = -EFAULT;
        #ifdef WIRELESS_SPY
        case SIOCSIWSPY:
                ...
                /* If there is some addresses to copy */
                if(lp->spy_number > 0)
                /* Copy addresses to the driver */ 2330:
                if(copy_from_user(address, wrq->u.data.pointer,
                        sizeof(struct sockaddr) * lp->spy_number))
                           {
                                      ret = -EFAULT;
                                      break;
                            }
                        ...
        case SIOCGIWSPY:
                ...
                if((lp->spy_number > 0) &&
                        (wrq->u.data.pointer != (caddr_t) 0))
                        /* Copy addresses to the user buffer */
2383: if(copy_to_user(wrq->u.data.pointer, address,
                               sizeof(struct sockaddr) * lp->spy_number))
                            {
                                      ret = -EFAULT;
                                      break;
                            }
                        /* Copy stats to the user buffer (just after)
*/
2391: if(copy_to_user(wrq->u.data.pointer +
                                       (sizeof(struct sockaddr) *
                                lp->spy_number),
                                       lp->spy_stat, sizeof(iw_qual) *
                                lp->spy_number))
                            {
                                      ret = -EFAULT;
                                      break;
                            }
                        ...
        #endif /* WIRELESS_SPY */
        /* ReEnable interrupts & restore flags */
        spin_unlock_irqrestore (&lp->lock, flags);
}

linux-2.3.99/drivers/net/irda/irport.c:953:irport_net_ioctl: ERROR:
Calling blocking fn with interrupts disabled in fn:
irda_device_dongle_init. [INTERRUPTS] [NOTE: defined in
linux-2.3.99/net/irda/irda_device.c. Calls kmalloc with GFP_KERNEL.]
{
        /* Disable interrupts & save flags */
        save_flags(flags);
        cli();
        switch (cmd) {
        ...
        case SIOCSDONGLE: /* Set dongle */
                if (!capable(CAP_NET_ADMIN))
                        return -EPERM;
                /* Initialize dongle */ 953: dongle =
                irda_device_dongle_init(dev, irq->ifr_dongle);
                ...
        }
        restore_flags(flags);
}

linux-2.3.99/drivers/net/irda/irtty.c:974:irtty_net_ioctl: ERROR:
Calling blocking fn with interrupts disabled in fn:
irda_device_dongle_init. [INTERRUPTS]
{
        /* Disable interrupts & save flags */
        save_flags(flags);
        cli();
        
        switch (cmd) {
        ...
        case SIOCSDONGLE: /* Set dongle */
                if (!capable(CAP_NET_ADMIN))
                        return -EPERM;
                /* Initialize dongle */
                dongle = irda_device_dongle_init(dev,
                irq->ifr_dongle);
        ...
        }
}

linux-2.3.99/drivers/net/irda/smc-ircc.c:1016:ircc_wakeup: ERROR:
Calling blocking fn with interrupts disabled in fn: ircc_net_open.
[INTERRUPTS] [NOTES: ircc_net_open is defined in smc_ircc.c, line
925. This in turn calls irport_net_open, defined in the same
directory, irpot.c line 762. This calls request_irq defined in
linux-2.3.99/arch/i386/kernel/irq.c. This in turn calls kmalloc with
GFP_KERNEL]
{
        save_flags(flags);
        cli();
        ircc_net_open(self->netdev);
        
        restore_flags(flags);
}

linux-2.3.99/drivers/net/wan/lmc/lmc_main.c:179:lmc_ioctl: ERROR:
Calling blocking fn with spin lock held in fn: copy_to_user. [SPIN]
{
        /*
        * Most functions mess with the structure
        * Disable interupts while we do the polling
        */
        spin_lock_irqsave(&sc->lmc_lock, flags);
        switch (cmd) {
        case LMCIOCGINFO: /*fold01*/
                /* macro: reduces to copy_to_user */ 179:
        LMC_COPY_TO_USER(ifr->ifr_data, &sc->ictl, sizeof (lmc_ctl_t));
        case LMCIOCSINFO: /*fold01*/
                ...
                /* macro: reduces to copy_from_user */ 195:
        LMC_COPY_FROM_USER(&ctl, ifr->ifr_data, sizeof (lmc_ctl_t));
                ...
        case LMCIOCIFTYPE: /*fold01*/
                ...
225: LMC_COPY_FROM_USER(&new_type, ifr->ifr_data,
        sizeof(u_int16_t));
                ...
        case LMCIOCGETXINFO: /*fold01*/
                ...
        
262: LMC_COPY_TO_USER(ifr->ifr_data, &sc->lmc_xinfo,
                        sizeof (struct lmc_xinfo));
                
                ...
        case LMCIOCGETLMCSTATS: /*fold01*/
                ...
293: LMC_COPY_TO_USER(ifr->ifr_data, &sc->stats,
                sizeof (struct lmc_statistics));
        
                ...
        case LMCIOCSETCIRCUIT: /*fold01*/
                ...
324: LMC_COPY_FROM_USER(&ctl, ifr->ifr_data, sizeof (lmc_ctl_t));
                
                ...
        case LMCIOCXILINX: /*fold01*/
                ...
                
375: LMC_COPY_FROM_USER(&xc, ifr->ifr_data,
                sizeof (struct lmc_xilinx_control));
                
                ...
                switch(xc.command){
                        ...
                        
                        case lmc_xilinx_load: /*fold02*/
                                ...
                
511: data = kmalloc(xc.len, GFP_KERNEL);
        
                                ...
                
518: LMC_COPY_FROM_USER(data, xc.data, xc.len);
        ...
        spin_unlock_irqrestore(&sc->lmc_lock, flags); /*fold01*/
}

linux-2.3.99/drivers/net/wan/comx.c:629:comx_write_proc: ERROR:
Calling blocking fn with interrupts disabled in fn: kmalloc.
[INTERRUPTS]
{
        save_flags(flags); cli();
        if (ch->debug_area) kfree(ch->debug_area);
        if ((ch->debug_area = kmalloc(ch->debug_size = i,
                GFP_KERNEL)) == NULL) {
                ret = -ENOMEM;
        }
        ch->debug_start = ch->debug_end = 0;
        restore_flags(flags);
}

linux-2.3.99/drivers/net/wan/comx.c:822:comx_debug_read: ERROR:
Calling blocking fn with interrupts disabled in fn: copy_to_user.
[INTERRUPTS] {
        save_flags(flags); cli();
        // We may run into trouble when debug_area is filled
        // from irq inside read. no problem if the buffer is
        // large enough
        while (count > 0 && ch->debug_start != ch->debug_end) {
                int len;
                len = min( (ch->debug_end - ch->debug_start +
                        ch->debug_size)
                        %ch->debug_size, min (ch->debug_size -
                        ch->debug_start, count));
                if (len) copy_to_user(buffer + copied,
                        ch->debug_area + ch->debug_start, len);
                ch->debug_start = (ch->debug_start + len) %
                        ch->debug_size;
                de->size -= len;
                count -= len;
                copied += len;
        }
        restore_flags(flags);
}

linux-2.3.99/drivers/net/wan/comx-hw-locomx.c:208:LOCOMX_open: ERROR:
Calling blocking fn with interrupts disabled in fn:
z8530_sync_dma_open. [INTERRUPTS] [NOTES: z8530_sync_dma_open is
defined in z85230.c line 843. It calls get_free_page with GFP_KERNEL
| GFP_DMA, not GFP_ATOMIC, so it can block. ]
{
        save_flags(flags);
        cli();
        ...
        if((ret=z8530_sync_dma_open(dev, &hw->board.chanA))!=0) {
                goto z8530_fail;
        }
        restore_flags(flags);
}

linux-2.3.99/drivers/net/wan/comx-hw-mixcom.c:515:MIXCOM_open: ERROR:
Calling blocking fn with interrupts disabled in fn: request_irq.
[INTERRUPTS] [NOTES: request_irq is defined in

linux-2.3.99/arch/i386/kernel/irq.c. Independent of the args. passed
to it, it calls kmalloc with flag GFP_KERNEL. request_region is a
macro for __request_region defined in linux-2.3.99/kernel/resource.c.
__request_region calls kmalloc with GFP_KERNEL on the very first
line.]
{
        save_flags(flags); cli();
        if(hw->channel==1) {
511: request_region(dev->base_addr, MIXCOM_IO_EXTENT, dev->name);
        }
        if(hw->channel==0 && !(ch->init_status & IRQ_ALLOCATED)) {
515: if (request_irq(dev->irq, MIXCOM_interrupt, 0,
                    dev->name, (void *)dev)) {
                        printk(KERN_ERR "MIXCOM: unable to obtain irq%d\n",
                        dev->irq);
                        return -EAGAIN;
                }
                ch->init_status|=IRQ_ALLOCATED;
521: request_region(dev->base_addr, MIXCOM_IO_EXTENT, dev->name);
                mixcom_board_on(dev);
        }
        ...
        restore_flags(flags);
}

linux-2.3.99/drivers/sound/nm256_audio.c:271:nm256_startRecording:
ERROR: Calling blocking fn with interrupts disabled in fn:
nm256_grabInterrupt. [INTERRUPTS] [NOTES: nm256_grabInterrupt is
defined in the same file, line 719. It calls request_irq.]
{
    save_flags (flags);
    cli ();
    /*
     * If we're not currently recording, set up the start and end
registers
     * for the recording engine.
     */
    if (! card->recording) {
        card->recording = 1; 271:if (nm256_grabInterrupt (card) == 0)
        {
        ....
        }
        ...
    restore_flags (flags);
}

linux-2.3.99/drivers/sound/nm256_audio.c:417:nm256_write_block:
ERROR: Calling blocking fn with interrupts disabled in fn: startPlay.
[INTERRUPTS] [NOTES: startPlay is defined in the same file, line 217.
It calls nm256_grabInterrupts.]
{
    save_flags (flags);
    cli ();
        ...
        if (! card->playing)
        startPlay (card);
    restore_flags (flags);
}

linux-2.3.99/drivers/sound/midibuf.c:305:MIDIbuf_write: ERROR:
Calling blocking fn with interrupts disabled in fn: copy_from_user.
[INTERRUPTS] [NOTE: this one is actually COMMENTED as broken because
it can't be done with cli()]
{
        save_flags(flags);
        cli();
        while (c < count)
                for (i = 0; i < n; i++)
                {
                        /* BROKE BROKE BROKE - CANT DO THIS WITH CLI!! */
305: copy_from_user((char *) &tmp_data, &(buf)[c], 1);
                        QUEUE_BYTE(midi_out_buf[dev], tmp_data);
                        c++;
                }
        }
        restore_flags(flags);
}

linux-2.3.99/drivers/sound/midibuf.c:354:MIDIbuf_read: ERROR: Calling
blocking fn with interrupts disabled in fn: copy_to_user.
[INTERRUPTS]
{
        save_flags(flags);
        cli();
        if (c == 0 && DATA_AVAIL(midi_in_buf[dev]))
                ...
                while (c < n)
                        ...
                        /* BROKE BROKE BROKE */
                        copy_to_user(&(buf)[c], fixit, 1);
                        ...
        restore_flags(flags);
}

linux-2.3.99/drivers/sound/sequencer.c:122:sequencer_read: ERROR:
Calling blocking fn with interrupts disabled in fn: copy_to_user.
[INTERRUPTS]
{
        save_flags(flags);
        cli();
        while (iqlen && c >= ev_len)
                ...
        
                copy_to_user(&(buf)[p], fixit, ev_len);
                ...

        restore_flags(flags);
}

linux-2.3.99/drivers/i2o/i2o_core.c:453:i2o_install_controller:
ERROR: Calling blocking fn with spin lock held in fn: kmalloc. [SPIN]
{
        spin_lock(&i2o_configuration_lock);
        for(i=0;i<MAX_I2O_CONTROLLERS;i++)
        if(i2o_controllers[i]==NULL)
                ...
        
453: c->dlct = (i2o_lct*)kmalloc(8192, GFP_KERNEL);
        ...
        spin_unlock(&i2o_configuration_lock);
        return 0;
        
        spin_unlock(&i2o_configuration_lock);
}

[[ META-NOTE: The
following fns all eventually call fn. i2o_post_wait or i2o_status_get
which contain the follwing code fragments. ]]
{
        /* i2o_post_wait */
        ...
        struct i2o_post_wait_data *p1, *p2;
        struct i2o_post_wait_data *wait_data =
        kmalloc(sizeof(struct i2o_post_wait_data), GFP_KERNEL);
        ...
}

{
        /* i2o_status_get */
        if (c->status_block == NULL)
                c->status_block = (i2o_status_block *)
                        
        kmalloc(sizeof(i2o_status_block),GFP_KERNEL);
        ...
}

linux-2.3.99/drivers/i2o/i2o_core.c:527:i2o_delete_controller: ERROR:
Calling blocking fn with spin lock held in fn: i2o_clear_controller.
[SPIN] [NOTE: i2o_clear_controller calls both i2o_post_wait AND
i2o_status_get]
{
        ...
        spin_lock(&i2o_configuration_lock);
        ...
        while(*p)
        {
                if(*p==c)
                {
                /* Ask the IOP to switch to HOLD state */
527: if (i2o_clear_controller(c) < 0)
                        printk(KERN_ERR "Unable to cleariop%d\n", c->unit);
                /* Release IRQ */
                c->destructor(c);
                *p=c->next;
                spin_unlock(&i2o_configuration_lock);
                ...
                }
        }
}

linux-2.3.99/drivers/i2o/i2o_core.c:596:i2o_claim_device:
ERROR: Calling blocking fn with spin lock held in fn:
i2o_issue_claim. [SPIN] [NOTE: i2o_issue_claim calls i2o_post_wait]
{
        spin_lock(&i2o_configuration_lock);
        ...
        if(i2o_issue_claim(d->controller,d->lct_data.tid, h->context,
                1, I2O_CLAIM_PRIMARY))
        {
                spin_unlock(&i2o_configuration_lock);
                return -EBUSY;
        }
        ...
        spin_unlock(&i2o_configuration_lock);
}

linux-2.3.99/drivers/i2o/i2o_core.c:622:i2o_release_device: ERROR:
Calling blocking fn with spin lock held in fn: i2o_issue_claim.
[SPIN]
{
        spin_lock(&i2o_configuration_lock);
        ...
        if(i2o_issue_claim(d->controller, d->lct_data.tid,
                        h->context, 0,
                        I2O_CLAIM_PRIMARY))
                ...
        ...
        spin_unlock(&i2o_configuration_lock);
        ...
}

linux-2.3.99/drivers/i2o/i2o_proc.c:556:i2o_proc_read_status: ERROR:
Calling blocking fn with spin lock held in fn: i2o_status_get.
[POTENTIAL] [SPIN] [NOTE: depends on value of c->status_block. If
null, this is a bug. Comment suggests this is NOT a bug.]
{
        spin_lock(&i2o_proc_lock);
        len = 0;
        i2o_status_get(c); // reread the status block
        len += sprintf(buf+len,"Organization ID : %0#6x\n",
                                c->status_block->org_id);
        ...
        spin_unlock(&i2o_proc_lock);
}

linux-2.3.99/drivers/i2o/i2o_proc.c:772:i2o_proc_read_hw: ERROR:
Calling blocking fn with spin lock held in fn: i2o_query_scalar.
[SPIN] [NOTE: i2o_query_scalar is in i2o_core.c. Calls
i2o_issue_params which, in turn, calls i2o_post_wait.] {
        spin_lock(&i2o_proc_lock);
        
        len = 0; 772: token = i2o_query_scalar(d->controller,
                                d->lct_data.tid,
                                0xF103, -1,
                                &work32, sizeof(work32));
        if (token < 0) {
                len += i2o_report_query_status(buf+len, token,
                        "0xF103 SGL Operating Limits");
                spin_unlock(&i2o_proc_lock);
                return len;
        }
        ...
        spin_unlock(&i2o_proc_lock);
}

linux-2.3.99/drivers/i2o/i2o_proc.c:851:i2o_proc_read_ddm_table:
ERROR: Calling blocking fn with spin lock held in fn:
i2o_query_table. [SPIN] [NOTE: i2o_query_table is in i2o_core.c.
Calls kmalloc with GFP_KERNEL directly.]
{
        spin_lock(&i2o_proc_lock);
        len = 0; 851: token = i2o_query_table(I2O_PARAMS_TABLE_GET,
                                d->controller, d->lct_data.tid,
                                0xF000, -1, NULL, 0,
                                &result, sizeof(result));
        if (token < 0) {
                len = i2o_report_query_status(buf+len, token,
                        "0xF000 Params Descriptor");
                spin_unlock(&i2o_proc_lock);
                return len;
        }
        ...
        spin_unlock(&i2o_proc_lock);
        
}

linux-2.3.99/drivers/i2o/i2o_proc.c:905:i2o_proc_read_driver_store:
ERROR: Calling blocking fn with spin lock held in fn:
i2o_query_scalar. [SPIN]
{
        spin_lock(&i2o_proc_lock);
        len = 0; 905: token = i2o_query_scalar(c, ADAPTER_TID,
                        0x0004, -1, &work32, sizeof(work32));
        if (token < 0) {
                len += i2o_report_query_status(buf+len, token,
                        "0x0004 Driver Store");
                spin_unlock(&i2o_proc_lock);
                return len;
        }
        ...
        spin_unlock(&i2o_proc_lock);
        ...
}

linux-2.3.99/drivers/i2o/i2o_proc.c:965:i2o_proc_read_drivers_stored:
ERROR: Calling blocking fn with spin lock held in fn:
i2o_query_table. [SPIN]
{
        spin_lock(&i2o_proc_lock);
        len = 0;
965: token = i2o_query_table(I2O_PARAMS_TABLE_GET,
                                c, ADAPTER_TID, 0x0005, -1, NULL, 0,
                                &result, sizeof(result));
        if (token < 0) {
                len += i2o_report_query_status(buf+len, token,
                        "0x0005 DRIVER STORE TABLE");
                spin_unlock(&i2o_proc_lock);
                return len;
        }
        ...
        spin_unlock(&i2o_proc_lock);
        ...
}
        
linux-2.3.99/drivers/ide/ide-probe.c:646:init_irq: ERROR: Calling
blocking fn with interrupts disabled in fn: request_irq. [INTERRUPTS]
[NOTES: ide_request_irq is defined as request_irq in

linux-2.3.99/include/asm-i386/ide.h, line 99. request_irq is defined
in linux-2.3.99/arch/i386/kernel/irq.c. Independent of the args.
passed to it, it calls kmalloc with flag GFP_KERNEL. request_region
is a macro for __request_region defined in

linux-2.3.99/kernel/resource.c. __request_region calls kmalloc with
GFP_KERNEL on the very first line.]
{
        save_flags(flags); /* all CPUs */
        cli(); /* all CPUs */
                /*
         * If we are still without a hwgroup, then form a new one
         */
        if (match) {
                hwgroup = match->hwgroup;
        } else {
625: hwgroup = kmalloc(sizeof(ide_hwgroup_t),
                        GFP_KERNEL);
                memset(hwgroup, 0, sizeof(ide_hwgroup_t));
                hwgroup->hwif = hwif->next = hwif;
                hwgroup->rq = NULL;
                hwgroup->handler = NULL;
                hwgroup->drive = NULL;
                hwgroup->busy = 0;
                init_timer(&hwgroup->timer);
                hwgroup->timer.function = &ide_timer_expiry;
                hwgroup->timer.data = (unsigned long) hwgroup;
        }
        ...
        /*
         * Allocate the irq, if not already obtained for another hwif
         */
        if (!match || match->irq != hwif->irq) {
646: if (ide_request_irq(hwif->irq, &ide_intr, sa, hwif->name,
                        hwgroup)) {
                        if (!match)
                                kfree(hwgroup);
                        restore_flags(flags); /* all CPUs */
                        return 1;
                }
        }
        ...
        restore_flags(flags);
        /* all CPUs; safe now that hwif->hwgroup is set up */
        
        ...
}

linux-2.3.99/drivers/scsi/aha152x.c:1266:aha152x_detect: ERROR:
Calling blocking fn with spin lock held and interrupts disabled in
fn: request_irq. [SPIN] [NOTES: see comment above regarding
request_irq and __request_region.]
{
        for (i=0; i<setup_count; i++) {
1260: request_region(shpnt->io_port, IO_RANGE, "aha152x");
                /* not expecting any interrupts */
                SETPORT(SIMODE0, 0);
                SETPORT(SIMODE1, 0);
1266: ok = request_irq(shpnt->irq, swintr, SA_INTERRUPT,
                        "aha152x", shpnt);
                ...
                spin_unlock_irq(&io_request_lock);
                mdelay(1000);
                spin_lock_irq(&io_request_lock);
                ...
ERROR: if (request_irq(shpnt->irq, intr, SA_INTERRUPT, "aha152x",
                        shpnt) < 0) {
                        ...
                }
                ...
        }
}

linux-2.3.99/drivers/scsi/aha1542.c:1216:aha1542_detect:
ERROR: Calling blocking fn with interrupts disabled in fn:
request_irq. [INTERRUPTS] [NOTES: see above note regarding
request_irq.]
{
        save_flags(flags);
        cli();
1216: if (request_irq(irq_level, do_aha1542_intr_handle, 0,
                        "aha1542", NULL)) {
                printk(KERN_ERR "Unable to allocate IRQ for adaptec
                        controller.\n");
                        restore_flags(flags);
                ...
}

linux-2.3.99/drivers/scsi/atp870u.c:1686:atp870u_detect: ERROR:
Calling blocking fn with interrupts disabled in fn: request_irq.
[INTERRUPTS] [NOTES: see request_irq note above.]
{
        save_flags(flags); 1686: cli();
        if (request_irq(irq, atp870u_intr_handle, SA_SHIRQ,
                "atp870u", dev)) {
                printk(KERN_ERR "Unable to allocate IRQ for
                        Acard controller.\n");
                goto unregister;
        }
}

linux-2.3.99/drivers/scsi/psi240i.c:603:Psi240i_Detect: ERROR:
Calling blocking fn with interrupts disabled in fn: request_irq.
[INTERRUPTS] [NOTES: see request_irq note above.]
{
        save_flags (flags);
        cli ();
603: if ( request_irq (chipConfig.irq, do_Irq_Handler, 0, "psi240i",
                NULL) )
        {
                printk ("Unable to allocate IRQ for PSI-240I controller.\n");
                restore_flags (flags);
                goto unregister;
        }
}

linux-2.3.99/drivers/scsi/sym53c416.c:683:sym53c416_detect: ERROR:
Calling blocking fn with interrupts disabled in fn: request_irq.
[INTERRUPTS] [NOTES: request_irq is defined in

linux-2.3.99/arch/i386/kernel/irq.c. Independent of the args. passed
to it, it calls kmalloc with flag GFP_KERNEL. request_region is a
macro for __request_region defined in linux-2.3.99/kernel/resource.c.
__request_region calls kmalloc with GFP_KERNEL on the very first
line.]
{
        /* sym53c416_detect */
        /* Now we register and set up each host adapter found... */
          for(count = 0, i = 0; i < host_index; i++)
            if(!sym53c416_test(hosts[i].base))
                ...
        else
                ...
        if(hosts[i].irq && !check_region(hosts[i].base, IO_RANGE))
        {
                shpnt = scsi_register(tpnt, 0);
                save_flags(flags);
                       cli();
                /* Request for specified IRQ */
683: if(request_irq(hosts[i].irq, sym53c416_intr_handle, 0, ID,
                        NULL))
                        restore_flags(flags);
                        ...
                else
                        /* Inform the kernel of our IO range */
692: request_region(hosts[i].base, IO_RANGE, ID);
                ...
                restore_flags(flags);
        }
}

linux-2.3.99/drivers/isdn/hisax/config.c:1026:init_card: ERROR:
Calling blocking fn with interrupts disabled in fn: request_irq.
[INTERRUPTS] [NOTES: See above note about request_irq.]
{
        ...
        save_flags(flags);
        cli();
        ...
1026: if (request_irq(cs->irq, cs->irq_func, cs->irq_flags, "HiSax",
                cs)) {
                printk(KERN_WARNING "HiSax: couldn't get interrupt %d\n",
                        cs->irq);
        restore_flags(flags);
        ...
}

linux-2.3.99/drivers/isdn/hisax/config.c:1296:checkcard: ERROR:
Calling blocking fn with interrupts disabled in fn: setup_w6692.
[INTERRUPTS] [NOTES: setup_w6692 is defined in w6692.c, line 994.
It calls check region and request_region, both of which call
kmalloc(..., GFP_KERNEL).]
{
        save_flags(flags);
        cli();
        ....
        if ((card->typ > 0) && (card->typ <= ISDN_CTYPE_COUNT)) {
                ....
                switch (card->typ) {
                ....
                #if CARD_W6692
                case ISDN_CTYPE_W6692:
                        ret = setup_w6692(card);
                        break;
                #endif
                default:
                        printk(KERN_WARNING
                                "HiSax: Support for %s Card not
selected\n",
                                CardType[card->typ]);
                        ll_unload(cs);
                        restore_flags(flags);
                        return (0);
                }
        ....
        }
}

linux-2.3.99/drivers/isdn/hisax/config.c:1337:checkcard:
ERROR: Calling blocking fn with interrupts disabled in fn: init_card.
[INTERRUPTS] [NOTES: Calls init_card with interrupts off which calls
request_irq with interrupts off which calls kmalloc with interrupts
off. Also double disables interrupts!]

linux-2.3.99/drivers/isdn/hisax/gazel.c:513:reserve_regions: ERROR:
Calling blocking fn with interrupts disabled in fn: __check_region.
[INTERRUPTS] [NOTE: __check_region is also defined in

linux-2.3.99/kernel/resource.c. It calls __request_region without
messing with interrupts. As noted above, __request_region calls
kmalloc with argument GFP_KERNEL on very first line.]
{
        save_flags(flags);
        cli();
        switch (cs->subtyp) {
                case R647:
                base = cs->hw.gazel.hscx[0];
                for (i = 0x0000; i < 0xC000; i += 0x1000) {
480: if (check_region(adr = (i + base), len = 16))
                                goto error;
                }
483: if (check_region(adr = (0xC000 + base), len = 1))
                        goto error;
                for (i = 0x0000; i < 0xC000; i += 0x1000)
487: request_region(i + base, 16, "gazel");
488: request_region(0xC000 + base, 1, "gazel");
                break;
                case R685:
493: if (check_region(adr = cs->hw.gazel.hscx[0], len = 0x100))
                        goto error;
495: if (check_region(adr = cs->hw.gazel.cfg_reg, len = 0x80))
                        goto error;
498: request_region(cs->hw.gazel.hscx[0], 0x100, "gazel");
499: request_region(cs->hw.gazel.cfg_reg, 0x80, "gazel");
                break;
                case R753:
503: if (check_region(adr = cs->hw.gazel.ipac, len = 0x8))
                        goto error;
505: if (check_region(adr = cs->hw.gazel.cfg_reg, len = 0x80))
                        goto error;
508: request_region(cs->hw.gazel.ipac, 0x8, "gazel"); 509:
                request_region(cs->hw.gazel.cfg_reg, 0x80, "gazel");
                break;
                case R742:
513: if (check_region(adr = cs->hw.gazel.ipac, len = 0x8))
                        goto error; 515:
                request_region(cs->hw.gazel.ipac, 0x8, "gazel");
                break;
        }
        restore_flags(flags);
        return 0;
        ...
}

linux-2.3.99/drivers/isdn/icn/icn.c:1061:icn_loadboot:
ERROR: Calling blocking fn with interrupts disabled in fn:
__check_region. [INTERRUPTS] [NOTES: Appears in code as check_shmem.
Actually calls to __check_region.]

linux-2.3.99/drivers/isdn/icn/icn.c:1068:icn_loadboot: ERROR: Calling
blocking fn with interrupts disabled in fn: __request_region.
[INTERRUPTS] [NOTES: Appears in code as request_shmem. Actually
calls __request_region.]
{
        save_flags(flags);
        cli();
        if (!card->rvalid) { 1045: if (check_region(card->port,
ICN_PORTLEN)) {
                printk(KERN_WARNING
                        "icn: (%s) ports 0x%03x-0x%03x in use.\n",
                         CID,
                         card->port,
                         card->port + ICN_PORTLEN);
                restore_flags(flags);
                kfree(codebuf);
                        ...
                }
1055: request_region(card->port, ICN_PORTLEN, card->regname);
                ...
        }
        ...
        if (!dev.mvalid) {
                1061: if (check_shmem((ulong) dev.shmem, 0x4000)) {
                        printk(KERN_WARNING
                               "icn: memory at 0x%08lx in use.\n",
                               (ulong) dev.shmem);
                        restore_flags(flags);
                        return -EBUSY;
                }
1068: request_shmem((ulong) dev.shmem, 0x4000, "icn");
                dev.mvalid = 1;
        }
        restore_flags(flags);
        ...
}

linux-2.3.99/drivers/isdn/icn/icn.c:1284:icn_writecmd:
ERROR: Calling blocking fn with interrupts disabled in fn:
copy_from_user. [INTERRUPTS]
{
        while (len) {
                save_flags(flags);
                cli();
                lastmap_card = dev.mcard;
                lastmap_channel = dev.channel;
                icn_map_channel(card, mch);
                avail = cmd_free;
                count = MIN(avail, len);
                if (user) 1284: copy_from_user(msg, buf, count);
                ...
                restore_flags(flags);
        }
}

linux-2.3.99/drivers/isdn/icn/icn.c:1369:icn_disable_cards: ERROR:
Calling blocking fn with interrupts disabled in fn: __check_region.
[INTERRUPTS] [NOTES: See note regarding __check_region above.]
{
        save_flags(flags);
        cli();
        while (card) { 1369: if (check_region(card->port,
                ICN_PORTLEN)) {
                        ...
                }
        }
        restore_flags(flags);
}

linux-2.3.99/drivers/isdn/icn/icn.c:1831:icn_addcard: ERROR: Calling
blocking fn with interrupts disabled in fn: icn_initcard.
[INTERRUPTS] [NOTES: icn_initcard is defined in icn.c. The first
thing it does is call kmalloc with flag GFP_KERNEL.] {
        save_flags(flags);
        cli();
        if (!(card = icn_initcard(port, id1))) { 1831:
restore_flags(flags);
                ...
        }
        ...
        if (!(card2 = icn_initcard(port, id2))) {
1842: restore_flags(flags);
                ...
        }
        ...
}

linux-2.3.99/drivers/isdn/act2000/act2000_isa.c:129:act2000_isa_detect:
ERROR: Calling blocking fn with interrupts disabled in fn:
__check_region. [INTERRUPTS] [NOTES: See __check_region note above.]
{
        save_flags(flags);
        cli();
129: if (!check_region(portbase, ISA_REGION))
                ret = act2000_isa_reset(portbase);
        restore_flags(flags);
}

linux-2.3.99/drivers/isdn/act2000/act2000_isa.c:235:act2000_isa_config_irq:
ERROR: Calling blocking fn with interrupts disabled in fn:
request_irq. [INTERRUPTS] [NOTES: See above note regarding
request_irq.]
{
        save_flags(flags);
        cli();
        if (irq == -1) {
                /* Auto select */
                for (i = 0; i < ISA_NRIRQS; i++) {
226: if(!request_irq(act2000_isa_irqs[i], &act2000_isa_interrupt, 0,
                        card->regname, NULL)) {
                                card->irq = act2000_isa_irqs[i];
                                irq2card_map[card->irq] = card;
                                card->flags |= ACT2000_FLAGS_IVALID;
                                break;
                        }
                }
        } else {
                /* Fixed irq */
235: if (!request_irq(irq, &act2000_isa_interrupt, 0,
card->regname, NULL)) {
                        card->irq = irq;
                        irq2card_map[card->irq] = card;
                        card->flags |= ACT2000_FLAGS_IVALID;
                }
        }
        restore_flags(flags);
}

linux-2.3.99/drivers/isdn/eicon/eicon_mod.c:806:if_readstatus: ERROR:
Calling blocking fn with interrupts disabled in fn: copy_to_user.
[INTERRUPTS]
{
        save_flags(flags);
        cli();
        while((skb = skb_dequeue(&card->statq))) {
                ...
                if (user) 806: copy_to_user(p, skb->data, cnt);
                ...
        }
        restore_flags(flags);
}

linux-2.3.99/drivers/atm/idt77105.c:152:fetch_stats: ERROR: Calling
blocking fn with interrupts disabled in fn: copy_to_user.
[INTERRUPTS]
{
        save_flags(flags);
        cli();
        if (arg)
                error = copy_to_user(arg,&PRIV(dev)->stats,
                    sizeof(struct idt77105_stats));
        if (zero && !error)
                memset(&PRIV(dev)->stats,0,sizeof(struct idt77105_stats));
        restore_flags(flags);
}

linux-2.3.99/drivers/atm/uPD98402.c:94:get_sense: ERROR: Calling
blocking fn with interrupts disabled in fn: put_user. [INTERRUPTS]
{
        save_flags(flags);
        cli();
        error = put_user(GET(C11R),arg) ||
                put_user(GET(C12R),arg+1) ||
                    put_user(GET(C13R),arg+2);
        restore_flags(flags);
}

linux-2.3.99/drivers/atm/iphase.c:3222:ia_detect: ERROR: Calling
blocking fn with spin lock held in fn: ia_start. [SPIN] [NOTES:
ia_start calls request_irq, which, as noted above, calls kmalloc
(..., GFP_KERNEL). ia_start defined in iphase.c, line 2480.
{
        ...
        while((iadev->pci = pci_find_device(PCI_VENDOR_ID_IPHASE,
                        PCI_DEVICE_ID_IPHASE_5575, prev_dev))) {
             spin_lock_init(&iadev->misc_lock);
          spin_lock_irqsave(&iadev->misc_lock, flags);
          if (ia_init(dev) || ia_start(dev)) {
                        ....
}

linux-2.3.99/drivers/atm/zatm.c:1688:zatm_ioctl: ERROR: Calling
blocking fn with interrupts disabled in fn: copy_to_user.
[INTERRUPTS]
{
#ifdef CONFIG_ATM_ZATM_EXACT_TS
        case ZATM_GETTHIST:
        {
        int i;
        save_flags(flags);
        cli();
        for (i = 0; i < ZATM_TIMER_HISTORY_SIZE; i++) {
                if (!copy_to_user((struct zatm_t_hist *) arg+i,
                        &zatm_dev->timer_history[(zatm_dev->th_curr+i) &
                                (ZATM_TIMER_HISTORY_SIZE-1)],
                        sizeof(structzatm_t_hist)))
                        continue;
                restore_flags(flags);
                return -EFAULT;
        }
        restore_flags(flags);
        return 0;
        }
#endif
}

linux-2.3.99/net/irda/ircomm/ircomm_tty.c:748:ircomm_tty_write:
ERROR: Calling blocking fn with interrupts disabled in fn:
copy_from_user. [INTERRUPTS]

{
        save_flags(flags);
        cli();
        ...
        while (count) {
                ...
                /* Copy data */
                if (from_user)
                        copy_from_user(skb_put(skb,size), buf+len,
size);
                else
                        memcpy(skb_put(skb,size), buf+len, size);
                
                count -= size;
                len += size;
        }
        restore_flags(flags);
        ... }

linux-2.3.99/arch/i386/kernel/traps.c:237:die: ERROR:
Calling blocking fn with spin lock held and interrupts disabled in
fn: show_registers. [INTERRUPTS] [NOTES: show_registers is defined
at traps.c, line 179. It can potentially call __get_user.]
{
        spin_lock_irq(&die_lock);
        printk("%s: %04lx\n", str, err & 0xffff);
        show_registers(regs);
        spin_unlock_irq(&die_lock);
}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Tue Aug 15 2000 - 21:00:16 EST