lkml.org 
[lkml]   [2007]   [Jul]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    SubjectRe: [linux-usb-devel] 2.6.22+: BUG: sleeping function called from invalid context at /home/jeremy/hg/xen/paravirt/linux/drivers/usb/core/urb.c:524, in_atomic():1, irqs_disabled():0
    Date

    > Clearly there's a bug in
    > drivers/usb/serial/usb-serial.c:usb_serial_put(). It shouldn't call
    > kref_put() while holding a spinlock.

    As I was reminded, I polluted the namespace. Here's a better
    version. Does it fix your problem?

    Regards
    Oliver
    Signed-off-by: Oliver Neukum <oneukum@suse.de>
    ---

    --- a/drivers/usb/serial/usb-serial.c 2007-07-23 08:47:35.000000000 +0200
    +++ b/drivers/usb/serial/usb-serial.c 2007-07-24 15:07:05.000000000 +0200
    @@ -60,19 +60,19 @@ static struct usb_driver usb_serial_driv

    static int debug;
    static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL */
    -static spinlock_t table_lock;
    +static DEFINE_MUTEX(table_lock);
    static LIST_HEAD(usb_serial_driver_list);

    struct usb_serial *usb_serial_get_by_index(unsigned index)
    {
    struct usb_serial *serial;

    - spin_lock(&table_lock);
    + mutex_lock(&table_lock);
    serial = serial_table[index];

    if (serial)
    kref_get(&serial->kref);
    - spin_unlock(&table_lock);
    + mutex_unlock(&table_lock);
    return serial;
    }

    @@ -84,7 +84,7 @@ static struct usb_serial *get_free_seria
    dbg("%s %d", __FUNCTION__, num_ports);

    *minor = 0;
    - spin_lock(&table_lock);
    + mutex_lock(&table_lock);
    for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
    if (serial_table[i])
    continue;
    @@ -106,10 +106,10 @@ static struct usb_serial *get_free_seria
    serial_table[i] = serial;
    serial->port[j++]->number = i;
    }
    - spin_unlock(&table_lock);
    + mutex_unlock(&table_lock);
    return serial;
    }
    - spin_unlock(&table_lock);
    + mutex_unlock(&table_lock);
    return NULL;
    }

    @@ -172,9 +172,9 @@ static void destroy_serial(struct kref *

    void usb_serial_put(struct usb_serial *serial)
    {
    - spin_lock(&table_lock);
    + mutex_lock(&table_lock);
    kref_put(&serial->kref, destroy_serial);
    - spin_unlock(&table_lock);
    + mutex_unlock(&table_lock);
    }

    /*****************************************************************************
    @@ -1128,7 +1128,6 @@ static int __init usb_serial_init(void)
    return -ENOMEM;

    /* Initialize our global data */
    - spin_lock_init(&table_lock);
    for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
    serial_table[i] = NULL;
    }
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/
    \
     
     \ /
      Last update: 2007-07-24 15:15    [W:0.035 / U:1.156 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site