Loading drivers/usb/host/xhci-hub.c +151 −1 Original line number Diff line number Diff line Loading @@ -20,7 +20,7 @@ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <linux/gfp.h> #include <linux/slab.h> #include <asm/unaligned.h> Loading Loading @@ -872,6 +872,151 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, return status; } static void xhci_single_step_completion(struct urb *urb) { struct completion *done = urb->context; complete(done); } /* * Allocate a URB and initialize the various fields of it. * This API is used by the single_step_set_feature test of * EHSET where IN packet of the GetDescriptor request is * sent 15secs after the SETUP packet. * Return NULL if failed. */ static struct urb *xhci_request_single_step_set_feature_urb( struct usb_device *udev, void *dr, void *buf, struct completion *done) { struct urb *urb; struct usb_hcd *hcd = bus_to_hcd(udev->bus); struct usb_host_endpoint *ep; urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) return NULL; urb->pipe = usb_rcvctrlpipe(udev, 0); ep = udev->ep_in[usb_pipeendpoint(urb->pipe)]; if (!ep) { usb_free_urb(urb); return NULL; } /* * Initialize the various URB fields as these are used by the HCD * driver to queue it and as well as when completion happens. */ urb->ep = ep; urb->dev = udev; urb->setup_packet = dr; urb->transfer_buffer = buf; urb->transfer_buffer_length = USB_DT_DEVICE_SIZE; urb->complete = xhci_single_step_completion; urb->status = -EINPROGRESS; urb->actual_length = 0; urb->transfer_flags = URB_DIR_IN; usb_get_urb(urb); atomic_inc(&urb->use_count); atomic_inc(&urb->dev->urbnum); usb_hcd_map_urb_for_dma(hcd, urb, GFP_KERNEL); urb->context = done; return urb; } /* * This function implements the USB_PORT_FEAT_TEST handling of the * SINGLE_STEP_SET_FEATURE test mode as defined in the Embedded * High-Speed Electrical Test (EHSET) specification. This simply * issues a GetDescriptor control transfer, with an inserted 15-second * delay after the end of the SETUP stage and before the IN token of * the DATA stage is set. The idea is that this gives the test operator * enough time to configure the oscilloscope to perform a measurement * of the response time between the DATA and ACK packets that follow. */ static int xhci_ehset_single_step_set_feature(struct usb_hcd *hcd, int port) { int retval; struct usb_ctrlrequest *dr; struct urb *urb; struct usb_device *udev; struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct usb_device_descriptor *buf; unsigned long flags; DECLARE_COMPLETION_ONSTACK(done); /* Obtain udev of the rhub's child port */ udev = usb_hub_find_child(hcd->self.root_hub, port); if (!udev) { xhci_err(xhci, "No device attached to the RootHub\n"); return -ENODEV; } buf = kmalloc(USB_DT_DEVICE_SIZE, GFP_KERNEL); if (!buf) return -ENOMEM; dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); if (!dr) { kfree(buf); return -ENOMEM; } /* Fill Setup packet for GetDescriptor */ dr->bRequestType = USB_DIR_IN; dr->bRequest = USB_REQ_GET_DESCRIPTOR; dr->wValue = cpu_to_le16(USB_DT_DEVICE << 8); dr->wIndex = 0; dr->wLength = cpu_to_le16(USB_DT_DEVICE_SIZE); urb = xhci_request_single_step_set_feature_urb(udev, dr, buf, &done); if (!urb) { retval = -ENOMEM; goto cleanup; } /* Now complete just the SETUP stage */ spin_lock_irqsave(&xhci->lock, flags); retval = xhci_submit_single_step_set_feature(hcd, urb, 1); spin_unlock_irqrestore(&xhci->lock, flags); if (retval) goto out1; if (!wait_for_completion_timeout(&done, msecs_to_jiffies(2000))) { usb_kill_urb(urb); retval = -ETIMEDOUT; xhci_err(xhci, "%s SETUP stage timed out on ep0\n", __func__); goto out1; } /* Sleep for 15 seconds; HC will send SOFs during this period */ msleep(15 * 1000); /* Complete remaining DATA and status stages. Re-use same URB */ urb->status = -EINPROGRESS; usb_get_urb(urb); atomic_inc(&urb->use_count); atomic_inc(&urb->dev->urbnum); spin_lock_irqsave(&xhci->lock, flags); retval = xhci_submit_single_step_set_feature(hcd, urb, 0); spin_unlock_irqrestore(&xhci->lock, flags); if (!retval && !wait_for_completion_timeout(&done, msecs_to_jiffies(2000))) { usb_kill_urb(urb); retval = -ETIMEDOUT; xhci_err(xhci, "%s IN stage timed out on ep0\n", __func__); } out1: usb_free_urb(urb); cleanup: kfree(dr); kfree(buf); return retval; } int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) { Loading Loading @@ -1152,6 +1297,11 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, PORTPMSC); /* to make sure above write goes through */ mb(); } else if (test_mode == 6) { spin_unlock_irqrestore(&xhci->lock, flags); retval = xhci_ehset_single_step_set_feature(hcd, wIndex); spin_lock_irqsave(&xhci->lock, flags); } else { goto error; } Loading drivers/usb/host/xhci-ring.c +150 −0 Original line number Diff line number Diff line Loading @@ -3485,6 +3485,156 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, return 0; } /* * Variant of xhci_queue_ctrl_tx() used to implement EHSET * SINGLE_STEP_SET_FEATURE test mode. It differs in that the control * transfer is broken up so that the SETUP stage can happen and call * the URB's completion handler before the DATA/STATUS stages are * executed by the xHC hardware. This assumes the control transfer is a * GetDescriptor, with a DATA stage in the IN direction, and an OUT * STATUS stage. * * This function is called twice, usually with a 15-second delay in between. * - with is_setup==true, the SETUP stage for the control request * (GetDescriptor) is queued in the TRB ring and sent to HW immediately * - with is_setup==false, the DATA and STATUS TRBs are queued and exceuted * * Caller must have locked xhci->lock */ int xhci_submit_single_step_set_feature(struct usb_hcd *hcd, struct urb *urb, int is_setup) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct xhci_ring *ep_ring; int num_trbs; int ret; unsigned int slot_id, ep_index; struct usb_ctrlrequest *setup; struct xhci_generic_trb *start_trb; int start_cycle; u32 field, length_field, remainder; struct urb_priv *urb_priv; struct xhci_td *td; ep_ring = xhci_urb_to_transfer_ring(xhci, urb); if (!ep_ring) return -EINVAL; /* Need buffer for data stage */ if (urb->transfer_buffer_length <= 0) return -EINVAL; /* * Need to copy setup packet into setup TRB, so we can't use the setup * DMA address. */ if (!urb->setup_packet) return -EINVAL; setup = (struct usb_ctrlrequest *) urb->setup_packet; slot_id = urb->dev->slot_id; ep_index = xhci_get_endpoint_index(&urb->ep->desc); urb_priv = kzalloc(sizeof(struct urb_priv) + sizeof(struct xhci_td *), GFP_ATOMIC); if (!urb_priv) return -ENOMEM; td = urb_priv->td[0] = kzalloc(sizeof(struct xhci_td), GFP_ATOMIC); if (!td) { kfree(urb_priv); return -ENOMEM; } urb_priv->length = 1; urb_priv->td_cnt = 0; urb->hcpriv = urb_priv; num_trbs = is_setup ? 1 : 2; ret = prepare_transfer(xhci, xhci->devs[slot_id], ep_index, urb->stream_id, num_trbs, urb, 0, GFP_ATOMIC); if (ret < 0) { kfree(td); kfree(urb_priv); return ret; } /* * Don't give the first TRB to the hardware (by toggling the cycle bit) * until we've finished creating all the other TRBs. The ring's cycle * state may change as we enqueue the other TRBs, so save it too. */ start_trb = &ep_ring->enqueue->generic; start_cycle = ep_ring->cycle_state; if (is_setup) { /* Queue only the setup TRB */ field = TRB_IDT | TRB_IOC | TRB_TYPE(TRB_SETUP); if (start_cycle == 0) field |= 0x1; /* xHCI 1.0/1.1 6.4.1.2.1: Transfer Type field */ if (xhci->hci_version >= 0x100) { if (setup->bRequestType & USB_DIR_IN) field |= TRB_TX_TYPE(TRB_DATA_IN); else field |= TRB_TX_TYPE(TRB_DATA_OUT); } /* Save the DMA address of the last TRB in the TD */ td->last_trb = ep_ring->enqueue; queue_trb(xhci, ep_ring, false, setup->bRequestType | setup->bRequest << 8 | le16_to_cpu(setup->wValue) << 16, le16_to_cpu(setup->wIndex) | le16_to_cpu(setup->wLength) << 16, TRB_LEN(8) | TRB_INTR_TARGET(0), field); } else { /* Queue data TRB */ field = TRB_ISP | TRB_TYPE(TRB_DATA); if (start_cycle == 0) field |= 0x1; if (setup->bRequestType & USB_DIR_IN) field |= TRB_DIR_IN; remainder = xhci_td_remainder(xhci, 0, urb->transfer_buffer_length, urb->transfer_buffer_length, urb, 1); length_field = TRB_LEN(urb->transfer_buffer_length) | TRB_TD_SIZE(remainder) | TRB_INTR_TARGET(0); queue_trb(xhci, ep_ring, true, lower_32_bits(urb->transfer_dma), upper_32_bits(urb->transfer_dma), length_field, field); /* Save the DMA address of the last TRB in the TD */ td->last_trb = ep_ring->enqueue; /* Queue status TRB */ field = TRB_IOC | TRB_TYPE(TRB_STATUS); if (!(setup->bRequestType & USB_DIR_IN)) field |= TRB_DIR_IN; queue_trb(xhci, ep_ring, false, 0, 0, TRB_INTR_TARGET(0), field | ep_ring->cycle_state); } giveback_first_trb(xhci, slot_id, ep_index, 0, start_cycle, start_trb); return 0; } /* * The transfer burst count field of the isochronous TRB defines the number of * bursts that are required to move all packets in this TD. Only SuperSpeed Loading drivers/usb/host/xhci.h +4 −0 Original line number Diff line number Diff line Loading @@ -1991,4 +1991,8 @@ static inline struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci, urb->stream_id); } /* EHSET */ int xhci_submit_single_step_set_feature(struct usb_hcd *hcd, struct urb *urb, int is_setup); #endif /* __LINUX_XHCI_HCD_H */ Loading
drivers/usb/host/xhci-hub.c +151 −1 Original line number Diff line number Diff line Loading @@ -20,7 +20,7 @@ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <linux/gfp.h> #include <linux/slab.h> #include <asm/unaligned.h> Loading Loading @@ -872,6 +872,151 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, return status; } static void xhci_single_step_completion(struct urb *urb) { struct completion *done = urb->context; complete(done); } /* * Allocate a URB and initialize the various fields of it. * This API is used by the single_step_set_feature test of * EHSET where IN packet of the GetDescriptor request is * sent 15secs after the SETUP packet. * Return NULL if failed. */ static struct urb *xhci_request_single_step_set_feature_urb( struct usb_device *udev, void *dr, void *buf, struct completion *done) { struct urb *urb; struct usb_hcd *hcd = bus_to_hcd(udev->bus); struct usb_host_endpoint *ep; urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) return NULL; urb->pipe = usb_rcvctrlpipe(udev, 0); ep = udev->ep_in[usb_pipeendpoint(urb->pipe)]; if (!ep) { usb_free_urb(urb); return NULL; } /* * Initialize the various URB fields as these are used by the HCD * driver to queue it and as well as when completion happens. */ urb->ep = ep; urb->dev = udev; urb->setup_packet = dr; urb->transfer_buffer = buf; urb->transfer_buffer_length = USB_DT_DEVICE_SIZE; urb->complete = xhci_single_step_completion; urb->status = -EINPROGRESS; urb->actual_length = 0; urb->transfer_flags = URB_DIR_IN; usb_get_urb(urb); atomic_inc(&urb->use_count); atomic_inc(&urb->dev->urbnum); usb_hcd_map_urb_for_dma(hcd, urb, GFP_KERNEL); urb->context = done; return urb; } /* * This function implements the USB_PORT_FEAT_TEST handling of the * SINGLE_STEP_SET_FEATURE test mode as defined in the Embedded * High-Speed Electrical Test (EHSET) specification. This simply * issues a GetDescriptor control transfer, with an inserted 15-second * delay after the end of the SETUP stage and before the IN token of * the DATA stage is set. The idea is that this gives the test operator * enough time to configure the oscilloscope to perform a measurement * of the response time between the DATA and ACK packets that follow. */ static int xhci_ehset_single_step_set_feature(struct usb_hcd *hcd, int port) { int retval; struct usb_ctrlrequest *dr; struct urb *urb; struct usb_device *udev; struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct usb_device_descriptor *buf; unsigned long flags; DECLARE_COMPLETION_ONSTACK(done); /* Obtain udev of the rhub's child port */ udev = usb_hub_find_child(hcd->self.root_hub, port); if (!udev) { xhci_err(xhci, "No device attached to the RootHub\n"); return -ENODEV; } buf = kmalloc(USB_DT_DEVICE_SIZE, GFP_KERNEL); if (!buf) return -ENOMEM; dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); if (!dr) { kfree(buf); return -ENOMEM; } /* Fill Setup packet for GetDescriptor */ dr->bRequestType = USB_DIR_IN; dr->bRequest = USB_REQ_GET_DESCRIPTOR; dr->wValue = cpu_to_le16(USB_DT_DEVICE << 8); dr->wIndex = 0; dr->wLength = cpu_to_le16(USB_DT_DEVICE_SIZE); urb = xhci_request_single_step_set_feature_urb(udev, dr, buf, &done); if (!urb) { retval = -ENOMEM; goto cleanup; } /* Now complete just the SETUP stage */ spin_lock_irqsave(&xhci->lock, flags); retval = xhci_submit_single_step_set_feature(hcd, urb, 1); spin_unlock_irqrestore(&xhci->lock, flags); if (retval) goto out1; if (!wait_for_completion_timeout(&done, msecs_to_jiffies(2000))) { usb_kill_urb(urb); retval = -ETIMEDOUT; xhci_err(xhci, "%s SETUP stage timed out on ep0\n", __func__); goto out1; } /* Sleep for 15 seconds; HC will send SOFs during this period */ msleep(15 * 1000); /* Complete remaining DATA and status stages. Re-use same URB */ urb->status = -EINPROGRESS; usb_get_urb(urb); atomic_inc(&urb->use_count); atomic_inc(&urb->dev->urbnum); spin_lock_irqsave(&xhci->lock, flags); retval = xhci_submit_single_step_set_feature(hcd, urb, 0); spin_unlock_irqrestore(&xhci->lock, flags); if (!retval && !wait_for_completion_timeout(&done, msecs_to_jiffies(2000))) { usb_kill_urb(urb); retval = -ETIMEDOUT; xhci_err(xhci, "%s IN stage timed out on ep0\n", __func__); } out1: usb_free_urb(urb); cleanup: kfree(dr); kfree(buf); return retval; } int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) { Loading Loading @@ -1152,6 +1297,11 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, PORTPMSC); /* to make sure above write goes through */ mb(); } else if (test_mode == 6) { spin_unlock_irqrestore(&xhci->lock, flags); retval = xhci_ehset_single_step_set_feature(hcd, wIndex); spin_lock_irqsave(&xhci->lock, flags); } else { goto error; } Loading
drivers/usb/host/xhci-ring.c +150 −0 Original line number Diff line number Diff line Loading @@ -3485,6 +3485,156 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, return 0; } /* * Variant of xhci_queue_ctrl_tx() used to implement EHSET * SINGLE_STEP_SET_FEATURE test mode. It differs in that the control * transfer is broken up so that the SETUP stage can happen and call * the URB's completion handler before the DATA/STATUS stages are * executed by the xHC hardware. This assumes the control transfer is a * GetDescriptor, with a DATA stage in the IN direction, and an OUT * STATUS stage. * * This function is called twice, usually with a 15-second delay in between. * - with is_setup==true, the SETUP stage for the control request * (GetDescriptor) is queued in the TRB ring and sent to HW immediately * - with is_setup==false, the DATA and STATUS TRBs are queued and exceuted * * Caller must have locked xhci->lock */ int xhci_submit_single_step_set_feature(struct usb_hcd *hcd, struct urb *urb, int is_setup) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct xhci_ring *ep_ring; int num_trbs; int ret; unsigned int slot_id, ep_index; struct usb_ctrlrequest *setup; struct xhci_generic_trb *start_trb; int start_cycle; u32 field, length_field, remainder; struct urb_priv *urb_priv; struct xhci_td *td; ep_ring = xhci_urb_to_transfer_ring(xhci, urb); if (!ep_ring) return -EINVAL; /* Need buffer for data stage */ if (urb->transfer_buffer_length <= 0) return -EINVAL; /* * Need to copy setup packet into setup TRB, so we can't use the setup * DMA address. */ if (!urb->setup_packet) return -EINVAL; setup = (struct usb_ctrlrequest *) urb->setup_packet; slot_id = urb->dev->slot_id; ep_index = xhci_get_endpoint_index(&urb->ep->desc); urb_priv = kzalloc(sizeof(struct urb_priv) + sizeof(struct xhci_td *), GFP_ATOMIC); if (!urb_priv) return -ENOMEM; td = urb_priv->td[0] = kzalloc(sizeof(struct xhci_td), GFP_ATOMIC); if (!td) { kfree(urb_priv); return -ENOMEM; } urb_priv->length = 1; urb_priv->td_cnt = 0; urb->hcpriv = urb_priv; num_trbs = is_setup ? 1 : 2; ret = prepare_transfer(xhci, xhci->devs[slot_id], ep_index, urb->stream_id, num_trbs, urb, 0, GFP_ATOMIC); if (ret < 0) { kfree(td); kfree(urb_priv); return ret; } /* * Don't give the first TRB to the hardware (by toggling the cycle bit) * until we've finished creating all the other TRBs. The ring's cycle * state may change as we enqueue the other TRBs, so save it too. */ start_trb = &ep_ring->enqueue->generic; start_cycle = ep_ring->cycle_state; if (is_setup) { /* Queue only the setup TRB */ field = TRB_IDT | TRB_IOC | TRB_TYPE(TRB_SETUP); if (start_cycle == 0) field |= 0x1; /* xHCI 1.0/1.1 6.4.1.2.1: Transfer Type field */ if (xhci->hci_version >= 0x100) { if (setup->bRequestType & USB_DIR_IN) field |= TRB_TX_TYPE(TRB_DATA_IN); else field |= TRB_TX_TYPE(TRB_DATA_OUT); } /* Save the DMA address of the last TRB in the TD */ td->last_trb = ep_ring->enqueue; queue_trb(xhci, ep_ring, false, setup->bRequestType | setup->bRequest << 8 | le16_to_cpu(setup->wValue) << 16, le16_to_cpu(setup->wIndex) | le16_to_cpu(setup->wLength) << 16, TRB_LEN(8) | TRB_INTR_TARGET(0), field); } else { /* Queue data TRB */ field = TRB_ISP | TRB_TYPE(TRB_DATA); if (start_cycle == 0) field |= 0x1; if (setup->bRequestType & USB_DIR_IN) field |= TRB_DIR_IN; remainder = xhci_td_remainder(xhci, 0, urb->transfer_buffer_length, urb->transfer_buffer_length, urb, 1); length_field = TRB_LEN(urb->transfer_buffer_length) | TRB_TD_SIZE(remainder) | TRB_INTR_TARGET(0); queue_trb(xhci, ep_ring, true, lower_32_bits(urb->transfer_dma), upper_32_bits(urb->transfer_dma), length_field, field); /* Save the DMA address of the last TRB in the TD */ td->last_trb = ep_ring->enqueue; /* Queue status TRB */ field = TRB_IOC | TRB_TYPE(TRB_STATUS); if (!(setup->bRequestType & USB_DIR_IN)) field |= TRB_DIR_IN; queue_trb(xhci, ep_ring, false, 0, 0, TRB_INTR_TARGET(0), field | ep_ring->cycle_state); } giveback_first_trb(xhci, slot_id, ep_index, 0, start_cycle, start_trb); return 0; } /* * The transfer burst count field of the isochronous TRB defines the number of * bursts that are required to move all packets in this TD. Only SuperSpeed Loading
drivers/usb/host/xhci.h +4 −0 Original line number Diff line number Diff line Loading @@ -1991,4 +1991,8 @@ static inline struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci, urb->stream_id); } /* EHSET */ int xhci_submit_single_step_set_feature(struct usb_hcd *hcd, struct urb *urb, int is_setup); #endif /* __LINUX_XHCI_HCD_H */