using cacheable buffer for descriptor

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

 



 
Hello All,
 
I'm working on a TI OMAP based device running linux kernel 2.6.29. I
encountered a problem with the USB host driver and would like to get
some advice on a safe solution.
 
The problem happens within the following code of function "int
usb_get_configuration(struct usb_device *dev)" in
drivers/usb/core/config.c
 
------ snip ------
  /* Now that we know the length, get the whole thing */
  bigbuffer = kmalloc(length, GFP_KERNEL);
  if (!bigbuffer) {
   result = -ENOMEM;
   goto err;
  }
  result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,
      bigbuffer, length);
  if (result < 0) {
   dev_err(ddev, "unable to read config index %d "
       "descriptor/%s\n", cfgno, "all");
   kfree(bigbuffer);
   goto err;
  }
  if (result < length) {
   dev_warn(ddev, "config index %d descriptor too short "
       "(expected %i, got %i)\n", cfgno, length, result);
   length = result;
  }
 
  dev->rawdescriptors[cfgno] = bigbuffer;
 
  result = usb_parse_configuration(&dev->dev, cfgno,
      &dev->config[cfgno], bigbuffer, length);
------ snip ------
 
bigbuffer is a cacheable buffer holding the device configuration
descriptor. Sometimes the function usb_parse_configuration complains
"config 1 has an invalid descriptor of length 0, skipping remainder of
the config", because the bLength field of that descriptor is 0. This
error results in enumeration failure for that interface. The issue is
not 100% reproducible, and the worst occurrence rate I have seen is
about 50%.
 
After some debugging, I think the problem is probably caused by
inconsistency between cache and physical memory, the CPU is reading
values from cache while the host controller DMA the descriptors directly
to the physical memory. Based on this analysis, I added
"dma_cache_maint(bigbuffer, length, DMA_FROM_DEVICE);" before calling
usb_parse_configuration, and that seems to fix the problem. But this is
just part of the analysis, answer to the following questions would
greatly help on finding the right solution.
 
1. I see dma_cache_maint is called by usb_submit_urb before starting
data transfer, this would guarantee the integrity of OUT data. But for
IN data, is the cache consistency taken care of by this driver?
2. Is it possible that this issue is caused by some other settings in
the system, such as clock settings, cache configuration or the host
controller settings? (we are using a EHCI controller)
3. Are we able to disable DMA for all EP0 transactions? As the amount of
data is relatively less, DMA is not really necessary.
 
 
Thanks,
Fei
--
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