aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorTom Rini2024-04-14 15:58:31 -0600
committerTom Rini2024-04-14 15:58:31 -0600
commitb03b49046af5dfca599d2ce8f0aafed89b97aa91 (patch)
tree36f06c2f124f8181549bc57a59777976ed1eaee1 /drivers
parent57cb92de7a9d01be1ce72af003651efc80ac67e2 (diff)
parent63f6a449bffe46beca89580d3efa48e5d041025c (diff)
Merge https://source.denx.de/u-boot/custodians/u-boot-usb
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/host/xhci-ring.c5
-rw-r--r--drivers/usb/host/xhci.c126
2 files changed, 85 insertions, 46 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index b60661fe05e..910c5f3352b 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -685,6 +685,9 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe,
reset_ep(udev, ep_index);
ring = virt_dev->eps[ep_index].ring;
+ if (!ring)
+ return -EINVAL;
+
/*
* How much data is (potentially) left before the 64KB boundary?
* XHCI Spec puts restriction( TABLE 49 and 6.4.1 section of XHCI Spec)
@@ -871,6 +874,8 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe,
ep_index = usb_pipe_ep_index(pipe);
ep_ring = virt_dev->eps[ep_index].ring;
+ if (!ep_ring)
+ return -EINVAL;
/*
* Check to see if the max packet size for the default control
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index d13cbff9b37..741e186ee05 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -475,67 +475,34 @@ static int xhci_configure_endpoints(struct usb_device *udev, bool ctx_change)
}
/**
- * Configure the endpoint, programming the device contexts.
+ * Fill endpoint contexts for interface descriptor ifdesc.
*
- * @param udev pointer to the USB device structure
- * Return: returns the status of the xhci_configure_endpoints
+ * @param udev pointer to the USB device structure
+ * @param ctrl pointer to the xhci pravte device structure
+ * @param virt_dev pointer to the xhci virtual device structure
+ * @param ifdesc pointer to the USB interface config descriptor
+ * Return: returns the status of xhci_init_ep_contexts_if
*/
-static int xhci_set_configuration(struct usb_device *udev)
+static int xhci_init_ep_contexts_if(struct usb_device *udev,
+ struct xhci_ctrl *ctrl,
+ struct xhci_virt_device *virt_dev,
+ struct usb_interface *ifdesc
+ )
{
- struct xhci_container_ctx *in_ctx;
- struct xhci_container_ctx *out_ctx;
- struct xhci_input_control_ctx *ctrl_ctx;
- struct xhci_slot_ctx *slot_ctx;
struct xhci_ep_ctx *ep_ctx[MAX_EP_CTX_NUM];
int cur_ep;
- int max_ep_flag = 0;
int ep_index;
unsigned int dir;
unsigned int ep_type;
- struct xhci_ctrl *ctrl = xhci_get_ctrl(udev);
- int num_of_ep;
- int ep_flag = 0;
u64 trb_64 = 0;
- int slot_id = udev->slot_id;
- struct xhci_virt_device *virt_dev = ctrl->devs[slot_id];
- struct usb_interface *ifdesc;
u32 max_esit_payload;
unsigned int interval;
unsigned int mult;
unsigned int max_burst;
unsigned int avg_trb_len;
unsigned int err_count = 0;
+ int num_of_ep = ifdesc->no_of_ep;
- out_ctx = virt_dev->out_ctx;
- in_ctx = virt_dev->in_ctx;
-
- num_of_ep = udev->config.if_desc[0].no_of_ep;
- ifdesc = &udev->config.if_desc[0];
-
- ctrl_ctx = xhci_get_input_control_ctx(in_ctx);
- /* Initialize the input context control */
- ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG);
- ctrl_ctx->drop_flags = 0;
-
- /* EP_FLAG gives values 1 & 4 for EP1OUT and EP2IN */
- for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) {
- ep_flag = xhci_get_ep_index(&ifdesc->ep_desc[cur_ep]);
- ctrl_ctx->add_flags |= cpu_to_le32(1 << (ep_flag + 1));
- if (max_ep_flag < ep_flag)
- max_ep_flag = ep_flag;
- }
-
- xhci_inval_cache((uintptr_t)out_ctx->bytes, out_ctx->size);
-
- /* slot context */
- xhci_slot_copy(ctrl, in_ctx, out_ctx);
- slot_ctx = xhci_get_slot_ctx(ctrl, in_ctx);
- slot_ctx->dev_info &= ~(cpu_to_le32(LAST_CTX_MASK));
- slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(max_ep_flag + 1) | 0);
-
- xhci_endpoint_copy(ctrl, in_ctx, out_ctx, 0);
-
- /* filling up ep contexts */
for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) {
struct usb_endpoint_descriptor *endpt_desc = NULL;
struct usb_ss_ep_comp_descriptor *ss_ep_comp_desc = NULL;
@@ -561,7 +528,8 @@ static int xhci_set_configuration(struct usb_device *udev)
avg_trb_len = max_esit_payload;
ep_index = xhci_get_ep_index(endpt_desc);
- ep_ctx[ep_index] = xhci_get_ep_ctx(ctrl, in_ctx, ep_index);
+ ep_ctx[ep_index] = xhci_get_ep_ctx(ctrl, virt_dev->in_ctx,
+ ep_index);
/* Allocate the ep rings */
virt_dev->eps[ep_index].ring = xhci_ring_alloc(ctrl, 1, true);
@@ -614,6 +582,72 @@ static int xhci_set_configuration(struct usb_device *udev)
}
}
+ return 0;
+}
+
+/**
+ * Configure the endpoint, programming the device contexts.
+ *
+ * @param udev pointer to the USB device structure
+ * Return: returns the status of the xhci_configure_endpoints
+ */
+static int xhci_set_configuration(struct usb_device *udev)
+{
+ struct xhci_container_ctx *out_ctx;
+ struct xhci_container_ctx *in_ctx;
+ struct xhci_input_control_ctx *ctrl_ctx;
+ struct xhci_slot_ctx *slot_ctx;
+ int err;
+ int cur_ep;
+ int max_ep_flag = 0;
+ struct xhci_ctrl *ctrl = xhci_get_ctrl(udev);
+ int num_of_ep;
+ int ep_flag = 0;
+ int slot_id = udev->slot_id;
+ struct xhci_virt_device *virt_dev = ctrl->devs[slot_id];
+ struct usb_interface *ifdesc;
+ unsigned int ifnum;
+ unsigned int max_ifnum = min((unsigned int)USB_MAX_ACTIVE_INTERFACES,
+ (unsigned int)udev->config.no_of_if);
+
+ out_ctx = virt_dev->out_ctx;
+ in_ctx = virt_dev->in_ctx;
+
+ ctrl_ctx = xhci_get_input_control_ctx(in_ctx);
+ /* Initialize the input context control */
+ ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG);
+ ctrl_ctx->drop_flags = 0;
+
+ for (ifnum = 0; ifnum < max_ifnum; ifnum++) {
+ ifdesc = &udev->config.if_desc[ifnum];
+ num_of_ep = ifdesc->no_of_ep;
+ /* EP_FLAG gives values 1 & 4 for EP1OUT and EP2IN */
+ for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) {
+ ep_flag = xhci_get_ep_index(&ifdesc->ep_desc[cur_ep]);
+ ctrl_ctx->add_flags |= cpu_to_le32(1 << (ep_flag + 1));
+ if (max_ep_flag < ep_flag)
+ max_ep_flag = ep_flag;
+ }
+ }
+
+ xhci_inval_cache((uintptr_t)out_ctx->bytes, out_ctx->size);
+
+ /* slot context */
+ xhci_slot_copy(ctrl, in_ctx, out_ctx);
+ slot_ctx = xhci_get_slot_ctx(ctrl, in_ctx);
+ slot_ctx->dev_info &= ~(cpu_to_le32(LAST_CTX_MASK));
+ slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(max_ep_flag + 1) | 0);
+
+ xhci_endpoint_copy(ctrl, in_ctx, out_ctx, 0);
+
+ /* filling up ep contexts */
+ for (ifnum = 0; ifnum < max_ifnum; ifnum++) {
+ ifdesc = &udev->config.if_desc[ifnum];
+ err = xhci_init_ep_contexts_if(udev, ctrl, virt_dev, ifdesc);
+ if (err < 0)
+ return err;
+ }
+
return xhci_configure_endpoints(udev, false);
}