forked from luck/tmp_suning_uos_patched
usb: core: setup dma_pfn_offset for USB devices and, interfaces
If dma_pfn_offset is not inherited correctly from the host controller, it might result in sub-optimal configuration as bounce buffer limit might be set to less than optimal level. Consider the mass storage device case. USB storage driver creates a scsi host for the mass storage interface in drivers/usb/storage/usb.c The scsi host parent device is nothing but the the USB interface device. Now, __scsi_init_queue() calls scsi_calculate_bounce_limit() to find out and set the block layer bounce limit. scsi_calculate_bounce_limit() uses dma_max_pfn(host_dev) to get the bounce_limit. host_dev is nothing but the device representing the mass storage interface. If that device doesn't have the right dma_pfn_offset, then dma_max_pfn() is messed up and the bounce buffer limit is wrong. e.g. On Keystone 2 systems, dma_max_pfn() is 0x87FFFF and dma_mask_pfn is 0xFFFFF. Consider a mass storage use case: Without this patch, usb scsi host device (usb-storage) will get a dma_pfn_offset of 0 resulting in a dma_max_pfn() of 0xFFFFF within the scsi layer (scsi_calculate_bounce_limit()). This will result in bounce buffers being unnecessarily used. Hint: On 32-bit ARM platforms dma_max_pfn() = dma_mask_pfn + dma_pfn_offset Signed-off-by: Roger Quadros <rogerq@ti.com> Acked-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
9cdd8e11c2
commit
b44bbc46a8
|
@ -1859,7 +1859,12 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
|
|||
intf->dev.bus = &usb_bus_type;
|
||||
intf->dev.type = &usb_if_device_type;
|
||||
intf->dev.groups = usb_interface_groups;
|
||||
/*
|
||||
* Please refer to usb_alloc_dev() to see why we set
|
||||
* dma_mask and dma_pfn_offset.
|
||||
*/
|
||||
intf->dev.dma_mask = dev->dev.dma_mask;
|
||||
intf->dev.dma_pfn_offset = dev->dev.dma_pfn_offset;
|
||||
INIT_WORK(&intf->reset_ws, __usb_queue_reset_device);
|
||||
intf->minor = -1;
|
||||
device_initialize(&intf->dev);
|
||||
|
|
|
@ -440,7 +440,18 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
|
|||
dev->dev.bus = &usb_bus_type;
|
||||
dev->dev.type = &usb_device_type;
|
||||
dev->dev.groups = usb_device_groups;
|
||||
/*
|
||||
* Fake a dma_mask/offset for the USB device:
|
||||
* We cannot really use the dma-mapping API (dma_alloc_* and
|
||||
* dma_map_*) for USB devices but instead need to use
|
||||
* usb_alloc_coherent and pass data in 'urb's, but some subsystems
|
||||
* manually look into the mask/offset pair to determine whether
|
||||
* they need bounce buffers.
|
||||
* Note: calling dma_set_mask() on a USB device would set the
|
||||
* mask for the entire HCD, so don't do that.
|
||||
*/
|
||||
dev->dev.dma_mask = bus->controller->dma_mask;
|
||||
dev->dev.dma_pfn_offset = bus->controller->dma_pfn_offset;
|
||||
set_dev_node(&dev->dev, dev_to_node(bus->controller));
|
||||
dev->state = USB_STATE_ATTACHED;
|
||||
dev->lpm_disable_count = 1;
|
||||
|
|
Loading…
Reference in New Issue
Block a user