* [PATCH 1/2] usb: host: move EH SINGLE_STEP_SET_FEATURE implementation to core
@ 2021-04-12 7:22 Li Jun
2021-04-12 7:22 ` [PATCH 2/2] usb: host: xhci: add EH SINGLE_STEP_SET_FEATURE Test for USB2 Li Jun
2021-04-12 18:22 ` [PATCH 1/2] usb: host: move EH SINGLE_STEP_SET_FEATURE implementation to core Jack Pham
0 siblings, 2 replies; 4+ messages in thread
From: Li Jun @ 2021-04-12 7:22 UTC (permalink / raw)
To: gregkh, stern, mathias.nyman; +Cc: peter.chen, jun.li, 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.
Signed-off-by: Peter Chen <peter.chen@nxp.com>
Signed-off-by: Jun Li <jun.li@nxp.com>
---
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] 4+ messages in thread
* [PATCH 2/2] usb: host: xhci: add EH SINGLE_STEP_SET_FEATURE Test for USB2
2021-04-12 7:22 [PATCH 1/2] usb: host: move EH SINGLE_STEP_SET_FEATURE implementation to core Li Jun
@ 2021-04-12 7:22 ` Li Jun
2021-04-12 18:22 ` [PATCH 1/2] usb: host: move EH SINGLE_STEP_SET_FEATURE implementation to core Jack Pham
1 sibling, 0 replies; 4+ messages in thread
From: Li Jun @ 2021-04-12 7:22 UTC (permalink / raw)
To: gregkh, stern, mathias.nyman; +Cc: peter.chen, jun.li, 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: Jun Li <jun.li@nxp.com>
---
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 1eee60ac518f..8b63ee7fb299 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -3797,6 +3797,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 5d9fc3cd07a5..13d95418db70 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -5414,6 +5414,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] 4+ messages in thread
* Re: [PATCH 1/2] usb: host: move EH SINGLE_STEP_SET_FEATURE implementation to core
2021-04-12 7:22 [PATCH 1/2] usb: host: move EH SINGLE_STEP_SET_FEATURE implementation to core Li Jun
2021-04-12 7:22 ` [PATCH 2/2] usb: host: xhci: add EH SINGLE_STEP_SET_FEATURE Test for USB2 Li Jun
@ 2021-04-12 18:22 ` Jack Pham
2021-04-22 8:46 ` Greg KH
1 sibling, 1 reply; 4+ messages in thread
From: Jack Pham @ 2021-04-12 18:22 UTC (permalink / raw)
To: Li Jun, peter.chen; +Cc: gregkh, stern, mathias.nyman, linux-usb, linux-imx
Hi Jun & Peter,
On Mon, Apr 12, 2021 at 03:22:13PM +0800, Li Jun wrote:
> 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.
>
> Signed-off-by: Peter Chen <peter.chen@nxp.com>
> Signed-off-by: Jun Li <jun.li@nxp.com>
> ---
> 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);
Maybe better to replace both of these dma_map_single() calls with
one call to usb_hcd_map_urb_for_dma(hcd, urb, GFP_KERNEL)?
> + urb->context = done;
> + return urb;
> +}
Thanks,
Jack
--
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 1/2] usb: host: move EH SINGLE_STEP_SET_FEATURE implementation to core
2021-04-12 18:22 ` [PATCH 1/2] usb: host: move EH SINGLE_STEP_SET_FEATURE implementation to core Jack Pham
@ 2021-04-22 8:46 ` Greg KH
0 siblings, 0 replies; 4+ messages in thread
From: Greg KH @ 2021-04-22 8:46 UTC (permalink / raw)
To: Jack Pham; +Cc: Li Jun, peter.chen, stern, mathias.nyman, linux-usb, linux-imx
On Mon, Apr 12, 2021 at 11:22:16AM -0700, Jack Pham wrote:
> Hi Jun & Peter,
>
> On Mon, Apr 12, 2021 at 03:22:13PM +0800, Li Jun wrote:
> > 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.
> >
> > Signed-off-by: Peter Chen <peter.chen@nxp.com>
> > Signed-off-by: Jun Li <jun.li@nxp.com>
> > ---
> > 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);
>
> Maybe better to replace both of these dma_map_single() calls with
> one call to usb_hcd_map_urb_for_dma(hcd, urb, GFP_KERNEL)?
In later patches, yes. Not in this one that only moves code around.
thanks,
greg k-h
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2021-04-22 8:46 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-12 7:22 [PATCH 1/2] usb: host: move EH SINGLE_STEP_SET_FEATURE implementation to core Li Jun
2021-04-12 7:22 ` [PATCH 2/2] usb: host: xhci: add EH SINGLE_STEP_SET_FEATURE Test for USB2 Li Jun
2021-04-12 18:22 ` [PATCH 1/2] usb: host: move EH SINGLE_STEP_SET_FEATURE implementation to core Jack Pham
2021-04-22 8:46 ` Greg KH
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).