usb_bulk_msg kernel hangs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,
I am seeing a very strange kernel crashing issue with my linux driver.
The strange thing is most of the time the driver works fine. I can
read and write my USB device with no issues. Then usually one day a
week, seeming to be on a rotating schedule of every 8 days or so,
every time I try to read from the device with usb_bulk_msg() the
kernel crashes hard. There is no response to anything. Removing the
USB device does nothing. Magic SysRq commands do nothing. The only way
to recover is turning off the power. This will happen for the full
day. The next day reads work fine.

I have seen this on 3 different computers. Two laptops running Kubuntu
9.10, kernel version 2.6.31-20 and a desktop running OpenSuse 11.0,
kernel version 2.6.25.16. The HCD is EHCI. The host vendors are Intel
82801I (ICH9) and Intel ICH10. These are all 64-bit SMP systems.

I have traced the position of the crash to be somewhere inside
usb_bulk_msg(). I am working on tracing through that code but as the
crash comes and goes I have not had the chance yet. One thing about my
usage of usb_bulk_msg(). The read size is larger than the maximum
packet size. This is to increase the efficiency of the read which is
usually MBs in size. My review of source code shows that this is not
usually done, but I have not seen any documentation that specifically
forbids it. I could submit the URB myself but I would be just
duplicating the code inside usb_bulk_msg().  Is there any reason the
max packet size can not be exceeded with this function?

Here's the code for the read operation.

#define MYDEV_TIMEOUT 250
#define BUF_SIZE_IN 3110400+10
static ssize_t mydev_read (struct file *file, char __user *buf, size_t
count, loff_t *ppos)
{
    struct mydev *dev = (struct mydev *)file->private_data;
    ssize_t retval = 0;
    int actual;

    if (dev == NULL)
        return -ENODEV;

    if (count > BUF_SIZE_IN) {
        printk(KERN_INFO "count %zd too large, trimmed to %d\n",
count, BUF_SIZE_IN);
        count = BUF_SIZE_IN;
    }

    mutex_lock(&dev->io_mutex);
    retval = usb_bulk_msg(dev->udev,
            usb_rcvbulkpipe(dev->udev, dev->bulk_in),
            dev->inbuf, count+2, &actual, MYDEV_TIMEOUT);
    mutex_unlock(&dev->io_mutex);

    if (retval < 0)
        return retval;

    if (actual > 0) {
        int framing = dev->inbuf[actual-1];

        if (framing > actual)
            return -EIO;

        actual -= framing;
    }

    if (copy_to_user(buf, dev->inbuf, actual))
        return -EFAULT;

    return actual;
}

Thanks!
Jeremy
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux