mirror of https://gitee.com/openkylin/linux.git
USB: add direction bit to urb->transfer_flags
This patch (as945) adds a bit to urb->transfer_flags for recording the direction of the URB. The bit is set/cleared automatically in usb_submit_urb() so drivers don't have to worry about it (although as a result, it isn't valid until the URB has been submitted). Inline routines are added for easily checking an URB's direction. They replace calls to usb_pipein in the DMA-mapping parts of hcd.c. For non-control endpoints, the direction is determined directly from the endpoint descriptor. However control endpoints are bi-directional; for them the direction is determined from the bRequestType byte and the wLength value in the setup packet. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
bdd016ba64
commit
fea3409112
|
@ -928,7 +928,7 @@ static void urb_unlink(struct usb_hcd *hcd, struct urb *urb)
|
||||||
dma_unmap_single (hcd->self.controller,
|
dma_unmap_single (hcd->self.controller,
|
||||||
urb->transfer_dma,
|
urb->transfer_dma,
|
||||||
urb->transfer_buffer_length,
|
urb->transfer_buffer_length,
|
||||||
usb_pipein (urb->pipe)
|
usb_urb_dir_in(urb)
|
||||||
? DMA_FROM_DEVICE
|
? DMA_FROM_DEVICE
|
||||||
: DMA_TO_DEVICE);
|
: DMA_TO_DEVICE);
|
||||||
}
|
}
|
||||||
|
@ -1014,7 +1014,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
|
||||||
hcd->self.controller,
|
hcd->self.controller,
|
||||||
urb->transfer_buffer,
|
urb->transfer_buffer,
|
||||||
urb->transfer_buffer_length,
|
urb->transfer_buffer_length,
|
||||||
usb_pipein (urb->pipe)
|
usb_urb_dir_in(urb)
|
||||||
? DMA_FROM_DEVICE
|
? DMA_FROM_DEVICE
|
||||||
: DMA_TO_DEVICE);
|
: DMA_TO_DEVICE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -309,7 +309,21 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
|
||||||
* and don't need to duplicate tests
|
* and don't need to duplicate tests
|
||||||
*/
|
*/
|
||||||
xfertype = usb_endpoint_type(&ep->desc);
|
xfertype = usb_endpoint_type(&ep->desc);
|
||||||
is_out = usb_pipeout(urb->pipe);
|
if (xfertype == USB_ENDPOINT_XFER_CONTROL) {
|
||||||
|
struct usb_ctrlrequest *setup =
|
||||||
|
(struct usb_ctrlrequest *) urb->setup_packet;
|
||||||
|
|
||||||
|
if (!setup)
|
||||||
|
return -ENOEXEC;
|
||||||
|
is_out = !(setup->bRequestType & USB_DIR_IN) ||
|
||||||
|
!setup->wLength;
|
||||||
|
} else {
|
||||||
|
is_out = usb_endpoint_dir_out(&ep->desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cache the direction for later use */
|
||||||
|
urb->transfer_flags = (urb->transfer_flags & ~URB_DIR_MASK) |
|
||||||
|
(is_out ? URB_DIR_OUT : URB_DIR_IN);
|
||||||
|
|
||||||
if (xfertype != USB_ENDPOINT_XFER_CONTROL &&
|
if (xfertype != USB_ENDPOINT_XFER_CONTROL &&
|
||||||
dev->state < USB_STATE_CONFIGURED)
|
dev->state < USB_STATE_CONFIGURED)
|
||||||
|
@ -363,7 +377,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
|
||||||
|
|
||||||
/* enforce simple/standard policy */
|
/* enforce simple/standard policy */
|
||||||
allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP |
|
allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP |
|
||||||
URB_NO_INTERRUPT);
|
URB_NO_INTERRUPT | URB_DIR_MASK);
|
||||||
switch (xfertype) {
|
switch (xfertype) {
|
||||||
case USB_ENDPOINT_XFER_BULK:
|
case USB_ENDPOINT_XFER_BULK:
|
||||||
if (is_out)
|
if (is_out)
|
||||||
|
|
|
@ -1021,6 +1021,8 @@ extern int usb_disabled(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* urb->transfer_flags:
|
* urb->transfer_flags:
|
||||||
|
*
|
||||||
|
* Note: URB_DIR_IN/OUT is automatically set in usb_submit_urb().
|
||||||
*/
|
*/
|
||||||
#define URB_SHORT_NOT_OK 0x0001 /* report short reads as errors */
|
#define URB_SHORT_NOT_OK 0x0001 /* report short reads as errors */
|
||||||
#define URB_ISO_ASAP 0x0002 /* iso-only, urb->start_frame
|
#define URB_ISO_ASAP 0x0002 /* iso-only, urb->start_frame
|
||||||
|
@ -1033,6 +1035,10 @@ extern int usb_disabled(void);
|
||||||
* needed */
|
* needed */
|
||||||
#define URB_FREE_BUFFER 0x0100 /* Free transfer buffer with the URB */
|
#define URB_FREE_BUFFER 0x0100 /* Free transfer buffer with the URB */
|
||||||
|
|
||||||
|
#define URB_DIR_IN 0x0200 /* Transfer from device to host */
|
||||||
|
#define URB_DIR_OUT 0
|
||||||
|
#define URB_DIR_MASK URB_DIR_IN
|
||||||
|
|
||||||
struct usb_iso_packet_descriptor {
|
struct usb_iso_packet_descriptor {
|
||||||
unsigned int offset;
|
unsigned int offset;
|
||||||
unsigned int length; /* expected length */
|
unsigned int length; /* expected length */
|
||||||
|
@ -1380,6 +1386,30 @@ extern void usb_unanchor_urb(struct urb *urb);
|
||||||
extern int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor,
|
extern int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor,
|
||||||
unsigned int timeout);
|
unsigned int timeout);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* usb_urb_dir_in - check if an URB describes an IN transfer
|
||||||
|
* @urb: URB to be checked
|
||||||
|
*
|
||||||
|
* Returns 1 if @urb describes an IN transfer (device-to-host),
|
||||||
|
* otherwise 0.
|
||||||
|
*/
|
||||||
|
static inline int usb_urb_dir_in(struct urb *urb)
|
||||||
|
{
|
||||||
|
return (urb->transfer_flags & URB_DIR_MASK) != URB_DIR_OUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* usb_urb_dir_out - check if an URB describes an OUT transfer
|
||||||
|
* @urb: URB to be checked
|
||||||
|
*
|
||||||
|
* Returns 1 if @urb describes an OUT transfer (host-to-device),
|
||||||
|
* otherwise 0.
|
||||||
|
*/
|
||||||
|
static inline int usb_urb_dir_out(struct urb *urb)
|
||||||
|
{
|
||||||
|
return (urb->transfer_flags & URB_DIR_MASK) == URB_DIR_OUT;
|
||||||
|
}
|
||||||
|
|
||||||
void *usb_buffer_alloc (struct usb_device *dev, size_t size,
|
void *usb_buffer_alloc (struct usb_device *dev, size_t size,
|
||||||
gfp_t mem_flags, dma_addr_t *dma);
|
gfp_t mem_flags, dma_addr_t *dma);
|
||||||
void usb_buffer_free (struct usb_device *dev, size_t size,
|
void usb_buffer_free (struct usb_device *dev, size_t size,
|
||||||
|
|
Loading…
Reference in New Issue