* [PATCH v3 1/3] usb: host: move EH SINGLE_STEP_SET_FEATURE implementation to core
@ 2021-05-07 6:58 Li Jun
2021-05-07 6:58 ` [PATCH v3 2/3] usb: host: xhci: add EH SINGLE_STEP_SET_FEATURE Test for USB2 Li Jun
2021-05-07 6:58 ` [PATCH v3 3/3] usb: core: hcd: use map_urb_for_dma for single step set feature urb Li Jun
0 siblings, 2 replies; 10+ messages in thread
From: Li Jun @ 2021-05-07 6:58 UTC (permalink / raw)
To: gregkh, stern, mathias.nyman
Cc: peter.chen, jun.li, jackp, linux-usb, linux-imx
From: Peter Chen <peter.chen@nxp.com>
It is needed at USB Certification test for Embedded Host 2.0, and
the detail is at CH6.4.1.1 of On-The-Go and Embedded Host Supplement
to the USB Revision 2.0 Specification. Since other USB 2.0 capable
host like XHCI also need it, so move it to HCD core.
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Peter Chen <peter.chen@nxp.com>
Signed-off-by: Li Jun <jun.li@nxp.com>
---
Change for v3:
- Add Alan's A-b tag.
Change for v2:
- No change.
drivers/usb/core/hcd.c | 134 ++++++++++++++++++++++++++++++++++
drivers/usb/host/ehci-hcd.c | 4 ++
drivers/usb/host/ehci-hub.c | 139 ------------------------------------
drivers/usb/host/ehci-q.c | 2 +-
include/linux/usb/hcd.h | 13 +++-
5 files changed, 151 insertions(+), 141 deletions(-)
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 6119fb41d736..d7eb9f179ca6 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2110,6 +2110,140 @@ int usb_hcd_get_frame_number (struct usb_device *udev)
return hcd->driver->get_frame_number (hcd);
}
+/*-------------------------------------------------------------------------*/
+#ifdef CONFIG_USB_HCD_TEST_MODE
+
+static void usb_ehset_completion(struct urb *urb)
+{
+ struct completion *done = urb->context;
+
+ complete(done);
+}
+/*
+ * Allocate and initialize a control URB. This request will be used by the
+ * EHSET SINGLE_STEP_SET_FEATURE test in which the DATA and STATUS stages
+ * of the GetDescriptor request are sent 15 seconds after the SETUP stage.
+ * Return NULL if failed.
+ */
+static struct urb *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 = (usb_pipein(urb->pipe) ? udev->ep_in : udev->ep_out)
+ [usb_pipeendpoint(urb->pipe)];
+ if (!ep) {
+ usb_free_urb(urb);
+ return NULL;
+ }
+
+ urb->ep = ep;
+ urb->dev = udev;
+ urb->setup_packet = (void *)dr;
+ urb->transfer_buffer = buf;
+ urb->transfer_buffer_length = USB_DT_DEVICE_SIZE;
+ urb->complete = usb_ehset_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);
+ urb->setup_dma = dma_map_single(
+ hcd->self.sysdev,
+ urb->setup_packet,
+ sizeof(struct usb_ctrlrequest),
+ DMA_TO_DEVICE);
+ urb->transfer_dma = dma_map_single(
+ hcd->self.sysdev,
+ urb->transfer_buffer,
+ urb->transfer_buffer_length,
+ DMA_FROM_DEVICE);
+ urb->context = done;
+ return urb;
+}
+
+int ehset_single_step_set_feature(struct usb_hcd *hcd, int port)
+{
+ int retval = -ENOMEM;
+ struct usb_ctrlrequest *dr;
+ struct urb *urb;
+ struct usb_device *udev;
+ struct usb_device_descriptor *buf;
+ DECLARE_COMPLETION_ONSTACK(done);
+
+ /* Obtain udev of the rhub's child port */
+ udev = usb_hub_find_child(hcd->self.root_hub, port);
+ if (!udev) {
+ dev_err(hcd->self.controller, "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 = request_single_step_set_feature_urb(udev, dr, buf, &done);
+ if (!urb)
+ goto cleanup;
+
+ /* Submit just the SETUP stage */
+ retval = hcd->driver->submit_single_step_set_feature(hcd, urb, 1);
+ if (retval)
+ goto out1;
+ if (!wait_for_completion_timeout(&done, msecs_to_jiffies(2000))) {
+ usb_kill_urb(urb);
+ retval = -ETIMEDOUT;
+ dev_err(hcd->self.controller,
+ "%s SETUP stage timed out on ep0\n", __func__);
+ goto out1;
+ }
+ msleep(15 * 1000);
+
+ /* Complete remaining DATA and STATUS stages using the same URB */
+ urb->status = -EINPROGRESS;
+ usb_get_urb(urb);
+ atomic_inc(&urb->use_count);
+ atomic_inc(&urb->dev->urbnum);
+ retval = hcd->driver->submit_single_step_set_feature(hcd, urb, 0);
+ if (!retval && !wait_for_completion_timeout(&done,
+ msecs_to_jiffies(2000))) {
+ usb_kill_urb(urb);
+ retval = -ETIMEDOUT;
+ dev_err(hcd->self.controller,
+ "%s IN stage timed out on ep0\n", __func__);
+ }
+out1:
+ usb_free_urb(urb);
+cleanup:
+ kfree(dr);
+ kfree(buf);
+ return retval;
+}
+EXPORT_SYMBOL_GPL(ehset_single_step_set_feature);
+#endif /* CONFIG_USB_HCD_TEST_MODE */
+
/*-------------------------------------------------------------------------*/
#ifdef CONFIG_PM
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 94b5e64ae9a2..35eec0c0edcd 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1238,6 +1238,10 @@ static const struct hc_driver ehci_hc_driver = {
* device support
*/
.free_dev = ehci_remove_device,
+#ifdef CONFIG_USB_HCD_TEST_MODE
+ /* EH SINGLE_STEP_SET_FEATURE test support */
+ .submit_single_step_set_feature = ehci_submit_single_step_set_feature,
+#endif
};
void ehci_init_driver(struct hc_driver *drv,
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 159cc27b1a36..c4f6a2559a98 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -726,145 +726,6 @@ ehci_hub_descriptor (
desc->wHubCharacteristics = cpu_to_le16(temp);
}
-/*-------------------------------------------------------------------------*/
-#ifdef CONFIG_USB_HCD_TEST_MODE
-
-#define EHSET_TEST_SINGLE_STEP_SET_FEATURE 0x06
-
-static void usb_ehset_completion(struct urb *urb)
-{
- struct completion *done = urb->context;
-
- complete(done);
-}
-static int submit_single_step_set_feature(
- struct usb_hcd *hcd,
- struct urb *urb,
- int is_setup
-);
-
-/*
- * Allocate and initialize a control URB. This request will be used by the
- * EHSET SINGLE_STEP_SET_FEATURE test in which the DATA and STATUS stages
- * of the GetDescriptor request are sent 15 seconds after the SETUP stage.
- * Return NULL if failed.
- */
-static struct urb *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 = (usb_pipein(urb->pipe) ? udev->ep_in : udev->ep_out)
- [usb_pipeendpoint(urb->pipe)];
- if (!ep) {
- usb_free_urb(urb);
- return NULL;
- }
-
- urb->ep = ep;
- urb->dev = udev;
- urb->setup_packet = (void *)dr;
- urb->transfer_buffer = buf;
- urb->transfer_buffer_length = USB_DT_DEVICE_SIZE;
- urb->complete = usb_ehset_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);
- urb->setup_dma = dma_map_single(
- hcd->self.sysdev,
- urb->setup_packet,
- sizeof(struct usb_ctrlrequest),
- DMA_TO_DEVICE);
- urb->transfer_dma = dma_map_single(
- hcd->self.sysdev,
- urb->transfer_buffer,
- urb->transfer_buffer_length,
- DMA_FROM_DEVICE);
- urb->context = done;
- return urb;
-}
-
-static int ehset_single_step_set_feature(struct usb_hcd *hcd, int port)
-{
- int retval = -ENOMEM;
- struct usb_ctrlrequest *dr;
- struct urb *urb;
- struct usb_device *udev;
- struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- struct usb_device_descriptor *buf;
- DECLARE_COMPLETION_ONSTACK(done);
-
- /* Obtain udev of the rhub's child port */
- udev = usb_hub_find_child(hcd->self.root_hub, port);
- if (!udev) {
- ehci_err(ehci, "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 = request_single_step_set_feature_urb(udev, dr, buf, &done);
- if (!urb)
- goto cleanup;
-
- /* Submit just the SETUP stage */
- retval = submit_single_step_set_feature(hcd, urb, 1);
- if (retval)
- goto out1;
- if (!wait_for_completion_timeout(&done, msecs_to_jiffies(2000))) {
- usb_kill_urb(urb);
- retval = -ETIMEDOUT;
- ehci_err(ehci, "%s SETUP stage timed out on ep0\n", __func__);
- goto out1;
- }
- msleep(15 * 1000);
-
- /* Complete remaining DATA and STATUS stages using the same URB */
- urb->status = -EINPROGRESS;
- usb_get_urb(urb);
- atomic_inc(&urb->use_count);
- atomic_inc(&urb->dev->urbnum);
- retval = submit_single_step_set_feature(hcd, urb, 0);
- if (!retval && !wait_for_completion_timeout(&done,
- msecs_to_jiffies(2000))) {
- usb_kill_urb(urb);
- retval = -ETIMEDOUT;
- ehci_err(ehci, "%s IN stage timed out on ep0\n", __func__);
- }
-out1:
- usb_free_urb(urb);
-cleanup:
- kfree(dr);
- kfree(buf);
- return retval;
-}
-#endif /* CONFIG_USB_HCD_TEST_MODE */
/*-------------------------------------------------------------------------*/
int ehci_hub_control(
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index a826715ae9bd..2cbf4f85bff3 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -1165,7 +1165,7 @@ submit_async (
* performed; TRUE - SETUP and FALSE - IN+STATUS
* Returns 0 if success
*/
-static int submit_single_step_set_feature(
+static int ehci_submit_single_step_set_feature(
struct usb_hcd *hcd,
struct urb *urb,
int is_setup
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 96281cd50ff6..22c5d1c0acf3 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -409,7 +409,10 @@ struct hc_driver {
int (*find_raw_port_number)(struct usb_hcd *, int);
/* Call for power on/off the port if necessary */
int (*port_power)(struct usb_hcd *hcd, int portnum, bool enable);
-
+ /* Call for SINGLE_STEP_SET_FEATURE Test for USB2 EH certification */
+#define EHSET_TEST_SINGLE_STEP_SET_FEATURE 0x06
+ int (*submit_single_step_set_feature)(struct usb_hcd *,
+ struct urb *, int);
};
static inline int hcd_giveback_urb_in_bh(struct usb_hcd *hcd)
@@ -474,6 +477,14 @@ int usb_hcd_setup_local_mem(struct usb_hcd *hcd, phys_addr_t phys_addr,
struct platform_device;
extern void usb_hcd_platform_shutdown(struct platform_device *dev);
+#ifdef CONFIG_USB_HCD_TEST_MODE
+extern int ehset_single_step_set_feature(struct usb_hcd *hcd, int port);
+#else
+static inline int ehset_single_step_set_feature(struct usb_hcd *hcd, int port)
+{
+ return 0;
+}
+#endif /* CONFIG_USB_HCD_TEST_MODE */
#ifdef CONFIG_USB_PCI
struct pci_dev;
--
2.25.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v3 2/3] usb: host: xhci: add EH SINGLE_STEP_SET_FEATURE Test for USB2
2021-05-07 6:58 [PATCH v3 1/3] usb: host: move EH SINGLE_STEP_SET_FEATURE implementation to core Li Jun
@ 2021-05-07 6:58 ` Li Jun
2021-06-11 9:18 ` Jun Li
2021-05-07 6:58 ` [PATCH v3 3/3] usb: core: hcd: use map_urb_for_dma for single step set feature urb Li Jun
1 sibling, 1 reply; 10+ messages in thread
From: Li Jun @ 2021-05-07 6:58 UTC (permalink / raw)
To: gregkh, stern, mathias.nyman
Cc: peter.chen, jun.li, jackp, linux-usb, linux-imx
From: Peter Chen <peter.chen@nxp.com>
This function is similar with EHCI's, but implemented using XHCI.
The USB2 host needs to send SETUP packet first, then wait 15
seconds before DATA (IN) + STATUS stage.
Signed-off-by: Peter Chen <peter.chen@nxp.com>
Signed-off-by: Li Jun <jun.li@nxp.com>
---
Change for v3:
- No change.
Change for v2:
- No change.
drivers/usb/host/xhci-hub.c | 10 +++
drivers/usb/host/xhci-ring.c | 123 +++++++++++++++++++++++++++++++++++
drivers/usb/host/xhci.c | 1 +
drivers/usb/host/xhci.h | 10 +++
4 files changed, 144 insertions(+)
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index e9b18fc17617..c64ee95cc89b 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -1511,6 +1511,16 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
/* 4.19.6 Port Test Modes (USB2 Test Mode) */
if (hcd->speed != HCD_USB2)
goto error;
+
+#ifdef CONFIG_USB_HCD_TEST_MODE
+ if (test_mode == EHSET_TEST_SINGLE_STEP_SET_FEATURE) {
+ spin_unlock_irqrestore(&xhci->lock, flags);
+ retval = ehset_single_step_set_feature(hcd,
+ wIndex + 1);
+ spin_lock_irqsave(&xhci->lock, flags);
+ break;
+ }
+#endif
if (test_mode > USB_TEST_FORCE_ENABLE ||
test_mode < USB_TEST_J)
goto error;
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 05c38dd3ee36..87a9c1e3325a 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -3793,6 +3793,129 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
return 0;
}
+#ifdef CONFIG_USB_HCD_TEST_MODE
+/*
+ * This function prepare TRBs and submits them for the
+ * SINGLE_STEP_SET_FEATURE Test.
+ * This is done in two parts: first SETUP req for GetDesc is sent then
+ * 15 seconds later, the IN stage for GetDesc starts to req data from dev
+ *
+ * is_setup : argument decides which of the two stage needs to be
+ * performed; TRUE - SETUP and FALSE - IN+STATUS
+ * Returns 0 if success
+ */
+int xhci_submit_single_step_set_feature(struct usb_hcd *hcd,
+ struct urb *urb, int is_setup)
+{
+ int slot_id;
+ unsigned int ep_index;
+ struct xhci_ring *ep_ring;
+ int ret;
+ 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;
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+
+ /* urb_priv will be free after transcation has completed */
+ urb_priv = kzalloc(sizeof(struct urb_priv) +
+ sizeof(struct xhci_td), GFP_KERNEL);
+ if (!urb_priv)
+ return -ENOMEM;
+
+ td = &urb_priv->td[0];
+ urb_priv->num_tds = 1;
+ urb_priv->num_tds_done = 0;
+ urb->hcpriv = urb_priv;
+
+ ep_ring = xhci_urb_to_transfer_ring(xhci, urb);
+ if (!ep_ring) {
+ ret = -EINVAL;
+ goto free_priv;
+ }
+
+ slot_id = urb->dev->slot_id;
+ ep_index = xhci_get_endpoint_index(&urb->ep->desc);
+
+ setup = (struct usb_ctrlrequest *) urb->setup_packet;
+ if (is_setup) {
+ ret = prepare_transfer(xhci, xhci->devs[slot_id],
+ ep_index, urb->stream_id,
+ 1, urb, 0, GFP_KERNEL);
+ if (ret < 0)
+ goto free_priv;
+
+ start_trb = &ep_ring->enqueue->generic;
+ start_cycle = ep_ring->cycle_state;
+ /* Save the DMA address of the last TRB in the TD */
+ td->last_trb = ep_ring->enqueue;
+ field = TRB_IOC | TRB_IDT | TRB_TYPE(TRB_SETUP) | start_cycle;
+ /* xHCI 1.0/1.1 6.4.1.2.1: Transfer Type field */
+ if ((xhci->hci_version >= 0x100) ||
+ (xhci->quirks & XHCI_MTK_HOST))
+ field |= TRB_TX_TYPE(TRB_DATA_IN);
+
+ 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),
+ /* Immediate data in pointer */
+ field);
+ giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id,
+ start_cycle, start_trb);
+ return 0;
+ }
+
+ ret = prepare_transfer(xhci, xhci->devs[slot_id],
+ ep_index, urb->stream_id,
+ 2, urb, 0, GFP_KERNEL);
+ if (ret < 0)
+ goto free_priv;
+
+ start_trb = &ep_ring->enqueue->generic;
+ start_cycle = ep_ring->cycle_state;
+ field = TRB_ISP | TRB_TYPE(TRB_DATA);
+
+ 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);
+
+ if (urb->transfer_buffer_length > 0) {
+ field |= TRB_DIR_IN;
+ queue_trb(xhci, ep_ring, true,
+ lower_32_bits(urb->transfer_dma),
+ upper_32_bits(urb->transfer_dma),
+ length_field,
+ field | ep_ring->cycle_state);
+ }
+
+ td->last_trb = ep_ring->enqueue;
+ field = TRB_IOC | TRB_TYPE(TRB_STATUS) | ep_ring->cycle_state;
+ queue_trb(xhci, ep_ring, false,
+ 0,
+ 0,
+ TRB_INTR_TARGET(0),
+ field);
+
+ giveback_first_trb(xhci, slot_id, ep_index, 0,
+ start_cycle, start_trb);
+
+ return 0;
+free_priv:
+ xhci_urb_free_priv(urb_priv);
+ return ret;
+}
+#endif /* CONFIG_USB_HCD_TEST_MODE */
+
/*
* 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
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index ca9385d22f68..a27616775845 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -5426,6 +5426,7 @@ static const struct hc_driver xhci_hc_driver = {
.disable_usb3_lpm_timeout = xhci_disable_usb3_lpm_timeout,
.find_raw_port_number = xhci_find_raw_port_number,
.clear_tt_buffer_complete = xhci_clear_tt_buffer_complete,
+ .submit_single_step_set_feature = xhci_submit_single_step_set_feature,
};
void xhci_init_driver(struct hc_driver *drv,
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 2595a8f057c4..f93fc8f59af6 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -2165,6 +2165,16 @@ int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1);
struct xhci_hub *xhci_get_rhub(struct usb_hcd *hcd);
void xhci_hc_died(struct xhci_hcd *xhci);
+#ifdef CONFIG_USB_HCD_TEST_MODE
+int xhci_submit_single_step_set_feature(struct usb_hcd *hcd,
+ struct urb *urb, int is_setup);
+#else
+static inline int xhci_submit_single_step_set_feature(struct usb_hcd *hcd,
+ struct urb *urb, int is_setup)
+{
+ return 0;
+}
+#endif
#ifdef CONFIG_PM
int xhci_bus_suspend(struct usb_hcd *hcd);
--
2.25.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v3 3/3] usb: core: hcd: use map_urb_for_dma for single step set feature urb
2021-05-07 6:58 [PATCH v3 1/3] usb: host: move EH SINGLE_STEP_SET_FEATURE implementation to core Li Jun
2021-05-07 6:58 ` [PATCH v3 2/3] usb: host: xhci: add EH SINGLE_STEP_SET_FEATURE Test for USB2 Li Jun
@ 2021-05-07 6:58 ` Li Jun
2021-05-07 15:42 ` Alan Stern
1 sibling, 1 reply; 10+ messages in thread
From: Li Jun @ 2021-05-07 6:58 UTC (permalink / raw)
To: gregkh, stern, mathias.nyman
Cc: peter.chen, jun.li, jackp, linux-usb, linux-imx
Use map_urb_for_dma() to improve the dma map code for single step
set feature request urb in test mode.
Signed-off-by: Li Jun <jun.li@nxp.com>
---
Change for v3:
- Correct the error handling if map_urb_for_dma() fails.
change for v2:
- Add this new patch to use map_urb_for_dma API to
replace both of dma_map_single() calls, suggested by
Jack Pham.
drivers/usb/core/hcd.c | 15 +++++----------
1 file changed, 5 insertions(+), 10 deletions(-)
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index d7eb9f179ca6..fa72697f4829 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2159,16 +2159,11 @@ static struct urb *request_single_step_set_feature_urb(
usb_get_urb(urb);
atomic_inc(&urb->use_count);
atomic_inc(&urb->dev->urbnum);
- urb->setup_dma = dma_map_single(
- hcd->self.sysdev,
- urb->setup_packet,
- sizeof(struct usb_ctrlrequest),
- DMA_TO_DEVICE);
- urb->transfer_dma = dma_map_single(
- hcd->self.sysdev,
- urb->transfer_buffer,
- urb->transfer_buffer_length,
- DMA_FROM_DEVICE);
+ if (map_urb_for_dma(hcd, urb, GFP_KERNEL)) {
+ usb_put_urb(urb);
+ return NULL;
+ }
+
urb->context = done;
return urb;
}
--
2.25.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v3 3/3] usb: core: hcd: use map_urb_for_dma for single step set feature urb
2021-05-07 6:58 ` [PATCH v3 3/3] usb: core: hcd: use map_urb_for_dma for single step set feature urb Li Jun
@ 2021-05-07 15:42 ` Alan Stern
2021-05-07 16:52 ` Jack Pham
0 siblings, 1 reply; 10+ messages in thread
From: Alan Stern @ 2021-05-07 15:42 UTC (permalink / raw)
To: Li Jun; +Cc: gregkh, mathias.nyman, peter.chen, jackp, linux-usb, linux-imx
On Fri, May 07, 2021 at 02:58:02PM +0800, Li Jun wrote:
> Use map_urb_for_dma() to improve the dma map code for single step
> set feature request urb in test mode.
>
> Signed-off-by: Li Jun <jun.li@nxp.com>
> ---
> Change for v3:
> - Correct the error handling if map_urb_for_dma() fails.
>
> change for v2:
> - Add this new patch to use map_urb_for_dma API to
> replace both of dma_map_single() calls, suggested by
> Jack Pham.
>
> drivers/usb/core/hcd.c | 15 +++++----------
> 1 file changed, 5 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
> index d7eb9f179ca6..fa72697f4829 100644
> --- a/drivers/usb/core/hcd.c
> +++ b/drivers/usb/core/hcd.c
> @@ -2159,16 +2159,11 @@ static struct urb *request_single_step_set_feature_urb(
> usb_get_urb(urb);
> atomic_inc(&urb->use_count);
> atomic_inc(&urb->dev->urbnum);
> - urb->setup_dma = dma_map_single(
> - hcd->self.sysdev,
> - urb->setup_packet,
> - sizeof(struct usb_ctrlrequest),
> - DMA_TO_DEVICE);
> - urb->transfer_dma = dma_map_single(
> - hcd->self.sysdev,
> - urb->transfer_buffer,
> - urb->transfer_buffer_length,
> - DMA_FROM_DEVICE);
> + if (map_urb_for_dma(hcd, urb, GFP_KERNEL)) {
> + usb_put_urb(urb);
You need to call usb_free_urb() here.
Alan Stern
> + return NULL;
> + }
> +
> urb->context = done;
> return urb;
> }
> --
> 2.25.1
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 3/3] usb: core: hcd: use map_urb_for_dma for single step set feature urb
2021-05-07 15:42 ` Alan Stern
@ 2021-05-07 16:52 ` Jack Pham
2021-05-07 17:40 ` Alan Stern
0 siblings, 1 reply; 10+ messages in thread
From: Jack Pham @ 2021-05-07 16:52 UTC (permalink / raw)
To: Alan Stern
Cc: Li Jun, gregkh, mathias.nyman, peter.chen, linux-usb, linux-imx
On Fri, May 07, 2021 at 11:42:29AM -0400, Alan Stern wrote:
> On Fri, May 07, 2021 at 02:58:02PM +0800, Li Jun wrote:
> > Use map_urb_for_dma() to improve the dma map code for single step
> > set feature request urb in test mode.
> >
> > Signed-off-by: Li Jun <jun.li@nxp.com>
> > ---
> > Change for v3:
> > - Correct the error handling if map_urb_for_dma() fails.
> >
> > change for v2:
> > - Add this new patch to use map_urb_for_dma API to
> > replace both of dma_map_single() calls, suggested by
> > Jack Pham.
> >
> > drivers/usb/core/hcd.c | 15 +++++----------
> > 1 file changed, 5 insertions(+), 10 deletions(-)
> >
> > diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
> > index d7eb9f179ca6..fa72697f4829 100644
> > --- a/drivers/usb/core/hcd.c
> > +++ b/drivers/usb/core/hcd.c
> > @@ -2159,16 +2159,11 @@ static struct urb *request_single_step_set_feature_urb(
> > usb_get_urb(urb);
> > atomic_inc(&urb->use_count);
> > atomic_inc(&urb->dev->urbnum);
> > - urb->setup_dma = dma_map_single(
> > - hcd->self.sysdev,
> > - urb->setup_packet,
> > - sizeof(struct usb_ctrlrequest),
> > - DMA_TO_DEVICE);
> > - urb->transfer_dma = dma_map_single(
> > - hcd->self.sysdev,
> > - urb->transfer_buffer,
> > - urb->transfer_buffer_length,
> > - DMA_FROM_DEVICE);
> > + if (map_urb_for_dma(hcd, urb, GFP_KERNEL)) {
> > + usb_put_urb(urb);
>
> You need to call usb_free_urb() here.
Hi Alan,
Aren't usb_put_urb() and usb_free_urb() identical? The former appears
to just be a macro subsitution of the latter.
Jack
> > + return NULL;
> > + }
> > +
> > urb->context = done;
> > return urb;
> > }
> > --
> > 2.25.1
> >
--
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 3/3] usb: core: hcd: use map_urb_for_dma for single step set feature urb
2021-05-07 16:52 ` Jack Pham
@ 2021-05-07 17:40 ` Alan Stern
0 siblings, 0 replies; 10+ messages in thread
From: Alan Stern @ 2021-05-07 17:40 UTC (permalink / raw)
To: Jack Pham; +Cc: Li Jun, gregkh, mathias.nyman, peter.chen, linux-usb, linux-imx
On Fri, May 07, 2021 at 09:52:40AM -0700, Jack Pham wrote:
> On Fri, May 07, 2021 at 11:42:29AM -0400, Alan Stern wrote:
> > On Fri, May 07, 2021 at 02:58:02PM +0800, Li Jun wrote:
> > > Use map_urb_for_dma() to improve the dma map code for single step
> > > set feature request urb in test mode.
> > >
> > > Signed-off-by: Li Jun <jun.li@nxp.com>
> > > ---
> > > Change for v3:
> > > - Correct the error handling if map_urb_for_dma() fails.
> > >
> > > change for v2:
> > > - Add this new patch to use map_urb_for_dma API to
> > > replace both of dma_map_single() calls, suggested by
> > > Jack Pham.
> > >
> > > drivers/usb/core/hcd.c | 15 +++++----------
> > > 1 file changed, 5 insertions(+), 10 deletions(-)
> > >
> > > diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
> > > index d7eb9f179ca6..fa72697f4829 100644
> > > --- a/drivers/usb/core/hcd.c
> > > +++ b/drivers/usb/core/hcd.c
> > > @@ -2159,16 +2159,11 @@ static struct urb *request_single_step_set_feature_urb(
> > > usb_get_urb(urb);
> > > atomic_inc(&urb->use_count);
> > > atomic_inc(&urb->dev->urbnum);
> > > - urb->setup_dma = dma_map_single(
> > > - hcd->self.sysdev,
> > > - urb->setup_packet,
> > > - sizeof(struct usb_ctrlrequest),
> > > - DMA_TO_DEVICE);
> > > - urb->transfer_dma = dma_map_single(
> > > - hcd->self.sysdev,
> > > - urb->transfer_buffer,
> > > - urb->transfer_buffer_length,
> > > - DMA_FROM_DEVICE);
> > > + if (map_urb_for_dma(hcd, urb, GFP_KERNEL)) {
> > > + usb_put_urb(urb);
> >
> > You need to call usb_free_urb() here.
>
> Hi Alan,
>
> Aren't usb_put_urb() and usb_free_urb() identical? The former appears
> to just be a macro subsitution of the latter.
Yes, they are identical, although that's more or less an historical
accident. usb_free_urb was written before the refcount API came along.
The usb_put_urb() call here undoes the usb_get_urb() call at the top of
the patch. You still need one more call to decrease the refcount to 0.
Alan Stern
^ permalink raw reply [flat|nested] 10+ messages in thread
* RE: [PATCH v3 2/3] usb: host: xhci: add EH SINGLE_STEP_SET_FEATURE Test for USB2
2021-05-07 6:58 ` [PATCH v3 2/3] usb: host: xhci: add EH SINGLE_STEP_SET_FEATURE Test for USB2 Li Jun
@ 2021-06-11 9:18 ` Jun Li
2021-07-16 3:12 ` Jun Li
0 siblings, 1 reply; 10+ messages in thread
From: Jun Li @ 2021-06-11 9:18 UTC (permalink / raw)
To: mathias.nyman; +Cc: peter.chen, jackp, linux-usb, dl-linux-imx, gregkh, stern
> -----Original Message-----
> From: Jun Li <jun.li@nxp.com>
> Sent: Friday, May 7, 2021 2:58 PM
> To: gregkh@linuxfoundation.org; stern@rowland.harvard.edu;
> mathias.nyman@intel.com
> Cc: peter.chen@kernel.org; Jun Li <jun.li@nxp.com>; jackp@codeaurora.org;
> linux-usb@vger.kernel.org; dl-linux-imx <linux-imx@nxp.com>
> Subject: [PATCH v3 2/3] usb: host: xhci: add EH SINGLE_STEP_SET_FEATURE Test
> for USB2
>
> From: Peter Chen <peter.chen@nxp.com>
>
> This function is similar with EHCI's, but implemented using XHCI.
> The USB2 host needs to send SETUP packet first, then wait 15 seconds before
> DATA (IN) + STATUS stage.
>
> Signed-off-by: Peter Chen <peter.chen@nxp.com>
> Signed-off-by: Li Jun <jun.li@nxp.com>
> ---
> Change for v3:
> - No change.
>
> Change for v2:
> - No change.
>
> drivers/usb/host/xhci-hub.c | 10 +++
> drivers/usb/host/xhci-ring.c | 123 +++++++++++++++++++++++++++++++++++
> drivers/usb/host/xhci.c | 1 +
> drivers/usb/host/xhci.h | 10 +++
> 4 files changed, 144 insertions(+)
>
> diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
> index e9b18fc17617..c64ee95cc89b 100644
> --- a/drivers/usb/host/xhci-hub.c
> +++ b/drivers/usb/host/xhci-hub.c
> @@ -1511,6 +1511,16 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq,
> u16 wValue,
> /* 4.19.6 Port Test Modes (USB2 Test Mode) */
> if (hcd->speed != HCD_USB2)
> goto error;
> +
> +#ifdef CONFIG_USB_HCD_TEST_MODE
> + if (test_mode == EHSET_TEST_SINGLE_STEP_SET_FEATURE) {
> + spin_unlock_irqrestore(&xhci->lock, flags);
> + retval = ehset_single_step_set_feature(hcd,
> + wIndex + 1);
> + spin_lock_irqsave(&xhci->lock, flags);
> + break;
> + }
> +#endif
> if (test_mode > USB_TEST_FORCE_ENABLE ||
> test_mode < USB_TEST_J)
> goto error;
> diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
> index 05c38dd3ee36..87a9c1e3325a 100644
> --- a/drivers/usb/host/xhci-ring.c
> +++ b/drivers/usb/host/xhci-ring.c
> @@ -3793,6 +3793,129 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t
> mem_flags,
> return 0;
> }
>
> +#ifdef CONFIG_USB_HCD_TEST_MODE
> +/*
> + * This function prepare TRBs and submits them for the
> + * SINGLE_STEP_SET_FEATURE Test.
> + * This is done in two parts: first SETUP req for GetDesc is sent then
> + * 15 seconds later, the IN stage for GetDesc starts to req data from
> +dev
> + *
> + * is_setup : argument decides which of the two stage needs to be
> + * performed; TRUE - SETUP and FALSE - IN+STATUS
> + * Returns 0 if success
> + */
> +int xhci_submit_single_step_set_feature(struct usb_hcd *hcd,
> + struct urb *urb, int is_setup)
> +{
> + int slot_id;
> + unsigned int ep_index;
> + struct xhci_ring *ep_ring;
> + int ret;
> + 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;
> + struct xhci_hcd *xhci = hcd_to_xhci(hcd);
> +
> + /* urb_priv will be free after transcation has completed */
> + urb_priv = kzalloc(sizeof(struct urb_priv) +
> + sizeof(struct xhci_td), GFP_KERNEL);
> + if (!urb_priv)
> + return -ENOMEM;
> +
> + td = &urb_priv->td[0];
> + urb_priv->num_tds = 1;
> + urb_priv->num_tds_done = 0;
> + urb->hcpriv = urb_priv;
> +
> + ep_ring = xhci_urb_to_transfer_ring(xhci, urb);
> + if (!ep_ring) {
> + ret = -EINVAL;
> + goto free_priv;
> + }
> +
> + slot_id = urb->dev->slot_id;
> + ep_index = xhci_get_endpoint_index(&urb->ep->desc);
> +
> + setup = (struct usb_ctrlrequest *) urb->setup_packet;
> + if (is_setup) {
> + ret = prepare_transfer(xhci, xhci->devs[slot_id],
> + ep_index, urb->stream_id,
> + 1, urb, 0, GFP_KERNEL);
> + if (ret < 0)
> + goto free_priv;
> +
> + start_trb = &ep_ring->enqueue->generic;
> + start_cycle = ep_ring->cycle_state;
> + /* Save the DMA address of the last TRB in the TD */
> + td->last_trb = ep_ring->enqueue;
> + field = TRB_IOC | TRB_IDT | TRB_TYPE(TRB_SETUP) | start_cycle;
> + /* xHCI 1.0/1.1 6.4.1.2.1: Transfer Type field */
> + if ((xhci->hci_version >= 0x100) ||
> + (xhci->quirks & XHCI_MTK_HOST))
> + field |= TRB_TX_TYPE(TRB_DATA_IN);
> +
> + 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),
> + /* Immediate data in pointer */
> + field);
> + giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id,
> + start_cycle, start_trb);
> + return 0;
> + }
> +
> + ret = prepare_transfer(xhci, xhci->devs[slot_id],
> + ep_index, urb->stream_id,
> + 2, urb, 0, GFP_KERNEL);
> + if (ret < 0)
> + goto free_priv;
> +
> + start_trb = &ep_ring->enqueue->generic;
> + start_cycle = ep_ring->cycle_state;
> + field = TRB_ISP | TRB_TYPE(TRB_DATA);
> +
> + 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);
> +
> + if (urb->transfer_buffer_length > 0) {
> + field |= TRB_DIR_IN;
> + queue_trb(xhci, ep_ring, true,
> + lower_32_bits(urb->transfer_dma),
> + upper_32_bits(urb->transfer_dma),
> + length_field,
> + field | ep_ring->cycle_state);
> + }
> +
> + td->last_trb = ep_ring->enqueue;
> + field = TRB_IOC | TRB_TYPE(TRB_STATUS) | ep_ring->cycle_state;
> + queue_trb(xhci, ep_ring, false,
> + 0,
> + 0,
> + TRB_INTR_TARGET(0),
> + field);
> +
> + giveback_first_trb(xhci, slot_id, ep_index, 0,
> + start_cycle, start_trb);
> +
> + return 0;
> +free_priv:
> + xhci_urb_free_priv(urb_priv);
> + return ret;
> +}
> +#endif /* CONFIG_USB_HCD_TEST_MODE */
> +
> /*
> * 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
> diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index
> ca9385d22f68..a27616775845 100644
> --- a/drivers/usb/host/xhci.c
> +++ b/drivers/usb/host/xhci.c
> @@ -5426,6 +5426,7 @@ static const struct hc_driver xhci_hc_driver = {
> .disable_usb3_lpm_timeout = xhci_disable_usb3_lpm_timeout,
> .find_raw_port_number = xhci_find_raw_port_number,
> .clear_tt_buffer_complete = xhci_clear_tt_buffer_complete,
> + .submit_single_step_set_feature =
> xhci_submit_single_step_set_feature,
> };
>
> void xhci_init_driver(struct hc_driver *drv, diff --git
> a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index
> 2595a8f057c4..f93fc8f59af6 100644
> --- a/drivers/usb/host/xhci.h
> +++ b/drivers/usb/host/xhci.h
> @@ -2165,6 +2165,16 @@ int xhci_find_raw_port_number(struct usb_hcd *hcd,
> int port1); struct xhci_hub *xhci_get_rhub(struct usb_hcd *hcd);
>
> void xhci_hc_died(struct xhci_hcd *xhci);
> +#ifdef CONFIG_USB_HCD_TEST_MODE
> +int xhci_submit_single_step_set_feature(struct usb_hcd *hcd,
> + struct urb *urb, int is_setup);
> +#else
> +static inline int xhci_submit_single_step_set_feature(struct usb_hcd
> *hcd,
> + struct urb *urb, int is_setup)
> +{
> + return 0;
> +}
> +#endif
>
> #ifdef CONFIG_PM
> int xhci_bus_suspend(struct usb_hcd *hcd);
> --
> 2.25.1
A gentle ping.
Li Jun
^ permalink raw reply [flat|nested] 10+ messages in thread
* RE: [PATCH v3 2/3] usb: host: xhci: add EH SINGLE_STEP_SET_FEATURE Test for USB2
2021-06-11 9:18 ` Jun Li
@ 2021-07-16 3:12 ` Jun Li
2021-07-16 14:35 ` Mathias Nyman
0 siblings, 1 reply; 10+ messages in thread
From: Jun Li @ 2021-07-16 3:12 UTC (permalink / raw)
To: mathias.nyman, Mathias Nyman
Cc: peter.chen, jackp, linux-usb, dl-linux-imx, gregkh, stern
Hi Mathias,
> -----Original Message-----
> From: Jun Li
> Sent: Friday, June 11, 2021 5:19 PM
> To: mathias.nyman@intel.com
> Cc: peter.chen@kernel.org; jackp@codeaurora.org;
> linux-usb@vger.kernel.org; dl-linux-imx <linux-imx@nxp.com>;
> gregkh@linuxfoundation.org; stern@rowland.harvard.edu
> Subject: RE: [PATCH v3 2/3] usb: host: xhci: add EH SINGLE_STEP_SET_FEATURE
> Test for USB2
>
>
>
> > -----Original Message-----
> > From: Jun Li <jun.li@nxp.com>
> > Sent: Friday, May 7, 2021 2:58 PM
> > To: gregkh@linuxfoundation.org; stern@rowland.harvard.edu;
> > mathias.nyman@intel.com
> > Cc: peter.chen@kernel.org; Jun Li <jun.li@nxp.com>;
> > jackp@codeaurora.org; linux-usb@vger.kernel.org; dl-linux-imx
> > <linux-imx@nxp.com>
> > Subject: [PATCH v3 2/3] usb: host: xhci: add EH
> > SINGLE_STEP_SET_FEATURE Test for USB2
> >
> > From: Peter Chen <peter.chen@nxp.com>
> >
> > This function is similar with EHCI's, but implemented using XHCI.
> > The USB2 host needs to send SETUP packet first, then wait 15 seconds
> > before DATA (IN) + STATUS stage.
> >
> > Signed-off-by: Peter Chen <peter.chen@nxp.com>
> > Signed-off-by: Li Jun <jun.li@nxp.com>
> > ---
> > Change for v3:
> > - No change.
> >
> > Change for v2:
> > - No change.
> >
> > drivers/usb/host/xhci-hub.c | 10 +++ drivers/usb/host/xhci-ring.c
> > | 123 +++++++++++++++++++++++++++++++++++
> > drivers/usb/host/xhci.c | 1 +
> > drivers/usb/host/xhci.h | 10 +++
> > 4 files changed, 144 insertions(+)
> >
> > diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
> > index e9b18fc17617..c64ee95cc89b 100644
> > --- a/drivers/usb/host/xhci-hub.c
> > +++ b/drivers/usb/host/xhci-hub.c
> > @@ -1511,6 +1511,16 @@ int xhci_hub_control(struct usb_hcd *hcd, u16
> > typeReq,
> > u16 wValue,
> > /* 4.19.6 Port Test Modes (USB2 Test Mode) */
> > if (hcd->speed != HCD_USB2)
> > goto error;
> > +
> > +#ifdef CONFIG_USB_HCD_TEST_MODE
> > + if (test_mode == EHSET_TEST_SINGLE_STEP_SET_FEATURE) {
> > + spin_unlock_irqrestore(&xhci->lock, flags);
> > + retval = ehset_single_step_set_feature(hcd,
> > + wIndex + 1);
> > + spin_lock_irqsave(&xhci->lock, flags);
> > + break;
> > + }
> > +#endif
> > if (test_mode > USB_TEST_FORCE_ENABLE ||
> > test_mode < USB_TEST_J)
> > goto error;
> > diff --git a/drivers/usb/host/xhci-ring.c
> > b/drivers/usb/host/xhci-ring.c index 05c38dd3ee36..87a9c1e3325a 100644
> > --- a/drivers/usb/host/xhci-ring.c
> > +++ b/drivers/usb/host/xhci-ring.c
> > @@ -3793,6 +3793,129 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci,
> > gfp_t mem_flags,
> > return 0;
> > }
> >
> > +#ifdef CONFIG_USB_HCD_TEST_MODE
> > +/*
> > + * This function prepare TRBs and submits them for the
> > + * SINGLE_STEP_SET_FEATURE Test.
> > + * This is done in two parts: first SETUP req for GetDesc is sent
> > +then
> > + * 15 seconds later, the IN stage for GetDesc starts to req data from
> > +dev
> > + *
> > + * is_setup : argument decides which of the two stage needs to be
> > + * performed; TRUE - SETUP and FALSE - IN+STATUS
> > + * Returns 0 if success
> > + */
> > +int xhci_submit_single_step_set_feature(struct usb_hcd *hcd,
> > + struct urb *urb, int is_setup)
> > +{
> > + int slot_id;
> > + unsigned int ep_index;
> > + struct xhci_ring *ep_ring;
> > + int ret;
> > + 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;
> > + struct xhci_hcd *xhci = hcd_to_xhci(hcd);
> > +
> > + /* urb_priv will be free after transcation has completed */
> > + urb_priv = kzalloc(sizeof(struct urb_priv) +
> > + sizeof(struct xhci_td), GFP_KERNEL);
> > + if (!urb_priv)
> > + return -ENOMEM;
> > +
> > + td = &urb_priv->td[0];
> > + urb_priv->num_tds = 1;
> > + urb_priv->num_tds_done = 0;
> > + urb->hcpriv = urb_priv;
> > +
> > + ep_ring = xhci_urb_to_transfer_ring(xhci, urb);
> > + if (!ep_ring) {
> > + ret = -EINVAL;
> > + goto free_priv;
> > + }
> > +
> > + slot_id = urb->dev->slot_id;
> > + ep_index = xhci_get_endpoint_index(&urb->ep->desc);
> > +
> > + setup = (struct usb_ctrlrequest *) urb->setup_packet;
> > + if (is_setup) {
> > + ret = prepare_transfer(xhci, xhci->devs[slot_id],
> > + ep_index, urb->stream_id,
> > + 1, urb, 0, GFP_KERNEL);
> > + if (ret < 0)
> > + goto free_priv;
> > +
> > + start_trb = &ep_ring->enqueue->generic;
> > + start_cycle = ep_ring->cycle_state;
> > + /* Save the DMA address of the last TRB in the TD */
> > + td->last_trb = ep_ring->enqueue;
> > + field = TRB_IOC | TRB_IDT | TRB_TYPE(TRB_SETUP) | start_cycle;
> > + /* xHCI 1.0/1.1 6.4.1.2.1: Transfer Type field */
> > + if ((xhci->hci_version >= 0x100) ||
> > + (xhci->quirks & XHCI_MTK_HOST))
> > + field |= TRB_TX_TYPE(TRB_DATA_IN);
> > +
> > + 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),
> > + /* Immediate data in pointer */
> > + field);
> > + giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id,
> > + start_cycle, start_trb);
> > + return 0;
> > + }
> > +
> > + ret = prepare_transfer(xhci, xhci->devs[slot_id],
> > + ep_index, urb->stream_id,
> > + 2, urb, 0, GFP_KERNEL);
> > + if (ret < 0)
> > + goto free_priv;
> > +
> > + start_trb = &ep_ring->enqueue->generic;
> > + start_cycle = ep_ring->cycle_state;
> > + field = TRB_ISP | TRB_TYPE(TRB_DATA);
> > +
> > + 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);
> > +
> > + if (urb->transfer_buffer_length > 0) {
> > + field |= TRB_DIR_IN;
> > + queue_trb(xhci, ep_ring, true,
> > + lower_32_bits(urb->transfer_dma),
> > + upper_32_bits(urb->transfer_dma),
> > + length_field,
> > + field | ep_ring->cycle_state);
> > + }
> > +
> > + td->last_trb = ep_ring->enqueue;
> > + field = TRB_IOC | TRB_TYPE(TRB_STATUS) | ep_ring->cycle_state;
> > + queue_trb(xhci, ep_ring, false,
> > + 0,
> > + 0,
> > + TRB_INTR_TARGET(0),
> > + field);
> > +
> > + giveback_first_trb(xhci, slot_id, ep_index, 0,
> > + start_cycle, start_trb);
> > +
> > + return 0;
> > +free_priv:
> > + xhci_urb_free_priv(urb_priv);
> > + return ret;
> > +}
> > +#endif /* CONFIG_USB_HCD_TEST_MODE */
> > +
> > /*
> > * 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 diff --git a/drivers/usb/host/xhci.c
> > b/drivers/usb/host/xhci.c index
> > ca9385d22f68..a27616775845 100644
> > --- a/drivers/usb/host/xhci.c
> > +++ b/drivers/usb/host/xhci.c
> > @@ -5426,6 +5426,7 @@ static const struct hc_driver xhci_hc_driver = {
> > .disable_usb3_lpm_timeout = xhci_disable_usb3_lpm_timeout,
> > .find_raw_port_number = xhci_find_raw_port_number,
> > .clear_tt_buffer_complete = xhci_clear_tt_buffer_complete,
> > + .submit_single_step_set_feature =
> > xhci_submit_single_step_set_feature,
> > };
> >
> > void xhci_init_driver(struct hc_driver *drv, diff --git
> > a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index
> > 2595a8f057c4..f93fc8f59af6 100644
> > --- a/drivers/usb/host/xhci.h
> > +++ b/drivers/usb/host/xhci.h
> > @@ -2165,6 +2165,16 @@ int xhci_find_raw_port_number(struct usb_hcd
> > *hcd, int port1); struct xhci_hub *xhci_get_rhub(struct usb_hcd
> > *hcd);
> >
> > void xhci_hc_died(struct xhci_hcd *xhci);
> > +#ifdef CONFIG_USB_HCD_TEST_MODE
> > +int xhci_submit_single_step_set_feature(struct usb_hcd *hcd,
> > + struct urb *urb, int is_setup);
> > +#else
> > +static inline int xhci_submit_single_step_set_feature(struct usb_hcd
> > *hcd,
> > + struct urb *urb, int is_setup)
> > +{
> > + return 0;
> > +}
> > +#endif
> >
> > #ifdef CONFIG_PM
> > int xhci_bus_suspend(struct usb_hcd *hcd);
> > --
> > 2.25.1
>
> A gentle ping.
Could you please take a look this patch?
Thanks
> Li Jun
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 2/3] usb: host: xhci: add EH SINGLE_STEP_SET_FEATURE Test for USB2
2021-07-16 3:12 ` Jun Li
@ 2021-07-16 14:35 ` Mathias Nyman
2021-08-21 10:34 ` Jun Li
0 siblings, 1 reply; 10+ messages in thread
From: Mathias Nyman @ 2021-07-16 14:35 UTC (permalink / raw)
To: Jun Li, mathias.nyman
Cc: peter.chen, jackp, linux-usb, dl-linux-imx, gregkh, stern
Hi
On 16.7.2021 6.12, Jun Li wrote:
> Hi Mathias,
>
>> -----Original Message-----
>> From: Jun Li
>> Sent: Friday, June 11, 2021 5:19 PM
>> To: mathias.nyman@intel.com
>> Cc: peter.chen@kernel.org; jackp@codeaurora.org;
>> linux-usb@vger.kernel.org; dl-linux-imx <linux-imx@nxp.com>;
>> gregkh@linuxfoundation.org; stern@rowland.harvard.edu
>> Subject: RE: [PATCH v3 2/3] usb: host: xhci: add EH SINGLE_STEP_SET_FEATURE
>> Test for USB2
>>
>>
>>
>>> A gentle ping.
>
> Could you please take a look this patch?
This somehow fell through the cracks, sorry.
I'll be away for two weeks so this will unfortunately be delayed even more.
Sorry about this.
-Mathias
^ permalink raw reply [flat|nested] 10+ messages in thread
* RE: [PATCH v3 2/3] usb: host: xhci: add EH SINGLE_STEP_SET_FEATURE Test for USB2
2021-07-16 14:35 ` Mathias Nyman
@ 2021-08-21 10:34 ` Jun Li
0 siblings, 0 replies; 10+ messages in thread
From: Jun Li @ 2021-08-21 10:34 UTC (permalink / raw)
To: Mathias Nyman, mathias.nyman
Cc: peter.chen, jackp, linux-usb, dl-linux-imx, gregkh, stern
Hi Mathias,
> -----Original Message-----
> From: Mathias Nyman <mathias.nyman@linux.intel.com>
> Sent: Friday, July 16, 2021 10:35 PM
> To: Jun Li <jun.li@nxp.com>; mathias.nyman@intel.com
> Cc: peter.chen@kernel.org; jackp@codeaurora.org;
> linux-usb@vger.kernel.org; dl-linux-imx <linux-imx@nxp.com>;
> gregkh@linuxfoundation.org; stern@rowland.harvard.edu
> Subject: Re: [PATCH v3 2/3] usb: host: xhci: add EH SINGLE_STEP_SET_FEATURE
> Test for USB2
>
> Hi
>
> On 16.7.2021 6.12, Jun Li wrote:
> > Hi Mathias,
> >
> >> -----Original Message-----
> >> From: Jun Li
> >> Sent: Friday, June 11, 2021 5:19 PM
> >> To: mathias.nyman@intel.com
> >> Cc: peter.chen@kernel.org; jackp@codeaurora.org;
> >> linux-usb@vger.kernel.org; dl-linux-imx <linux-imx@nxp.com>;
> >> gregkh@linuxfoundation.org; stern@rowland.harvard.edu
> >> Subject: RE: [PATCH v3 2/3] usb: host: xhci: add EH
> >> SINGLE_STEP_SET_FEATURE Test for USB2
> >>
> >>
> >>
> >>> A gentle ping.
> >
> > Could you please take a look this patch?
>
> This somehow fell through the cracks, sorry.
>
> I'll be away for two weeks so this will unfortunately be delayed even more.
> Sorry about this.
Seems this patch is still missed, ping again.
Li Jun
>
> -Mathias
>
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2021-08-21 10:34 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-07 6:58 [PATCH v3 1/3] usb: host: move EH SINGLE_STEP_SET_FEATURE implementation to core Li Jun
2021-05-07 6:58 ` [PATCH v3 2/3] usb: host: xhci: add EH SINGLE_STEP_SET_FEATURE Test for USB2 Li Jun
2021-06-11 9:18 ` Jun Li
2021-07-16 3:12 ` Jun Li
2021-07-16 14:35 ` Mathias Nyman
2021-08-21 10:34 ` Jun Li
2021-05-07 6:58 ` [PATCH v3 3/3] usb: core: hcd: use map_urb_for_dma for single step set feature urb Li Jun
2021-05-07 15:42 ` Alan Stern
2021-05-07 16:52 ` Jack Pham
2021-05-07 17:40 ` Alan Stern
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.