Skip to content

Commit 913a8a3

Browse files
Sarah Sharpgregkh
authored andcommitted
USB: xhci: Change how xHCI commands are handled.
Some commands to the xHCI hardware cannot be allowed to fail due to out of memory issues or the command ring being full. Add a way to reserve a TRB on the command ring, and make all command queueing functions indicate whether they are using a reserved TRB. Add a way to pre-allocate all the memory a command might need. A command needs an input context, a variable to store the status, and (optionally) a completion for the caller to wait on. Change all code that assumes the input device context, status, and completion for a command is stored in the xhci virtual USB device structure (xhci_virt_device). Store pending completions in a FIFO in xhci_virt_device. Make the event handler for a configure endpoint command check to see whether a pending command in the list has completed. We need to use separate input device contexts for some configure endpoint commands, since multiple drivers can submit requests at the same time that require a configure endpoint command. Signed-off-by: Sarah Sharp <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 5270b95 commit 913a8a3

File tree

4 files changed

+186
-53
lines changed

4 files changed

+186
-53
lines changed

drivers/usb/host/xhci-hcd.c

Lines changed: 52 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -612,8 +612,8 @@ int xhci_check_args(struct usb_hcd *hcd, struct usb_device *udev,
612612
}
613613

614614
static int xhci_configure_endpoint(struct xhci_hcd *xhci,
615-
struct usb_device *udev, struct xhci_virt_device *virt_dev,
616-
bool ctx_change);
615+
struct usb_device *udev, struct xhci_command *command,
616+
bool ctx_change, bool must_succeed);
617617

618618
/*
619619
* Full speed devices may have a max packet size greater than 8 bytes, but the
@@ -645,7 +645,8 @@ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id,
645645
xhci_dbg(xhci, "Issuing evaluate context command.\n");
646646

647647
/* Set up the modified control endpoint 0 */
648-
xhci_endpoint_copy(xhci, xhci->devs[slot_id], ep_index);
648+
xhci_endpoint_copy(xhci, xhci->devs[slot_id]->in_ctx,
649+
xhci->devs[slot_id]->out_ctx, ep_index);
649650
in_ctx = xhci->devs[slot_id]->in_ctx;
650651
ep_ctx = xhci_get_ep_ctx(xhci, in_ctx, ep_index);
651652
ep_ctx->ep_info2 &= ~MAX_PACKET_MASK;
@@ -664,8 +665,8 @@ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id,
664665
xhci_dbg(xhci, "Slot %d output context\n", slot_id);
665666
xhci_dbg_ctx(xhci, out_ctx, ep_index);
666667

667-
ret = xhci_configure_endpoint(xhci, urb->dev,
668-
xhci->devs[slot_id], true);
668+
ret = xhci_configure_endpoint(xhci, urb->dev, NULL,
669+
true, false);
669670

670671
/* Clean up the input context for later use by bandwidth
671672
* functions.
@@ -1038,11 +1039,11 @@ static void xhci_zero_in_ctx(struct xhci_hcd *xhci, struct xhci_virt_device *vir
10381039
}
10391040

10401041
static int xhci_configure_endpoint_result(struct xhci_hcd *xhci,
1041-
struct usb_device *udev, struct xhci_virt_device *virt_dev)
1042+
struct usb_device *udev, int *cmd_status)
10421043
{
10431044
int ret;
10441045

1045-
switch (virt_dev->cmd_status) {
1046+
switch (*cmd_status) {
10461047
case COMP_ENOMEM:
10471048
dev_warn(&udev->dev, "Not enough host controller resources "
10481049
"for new device state.\n");
@@ -1068,19 +1069,20 @@ static int xhci_configure_endpoint_result(struct xhci_hcd *xhci,
10681069
break;
10691070
default:
10701071
xhci_err(xhci, "ERROR: unexpected command completion "
1071-
"code 0x%x.\n", virt_dev->cmd_status);
1072+
"code 0x%x.\n", *cmd_status);
10721073
ret = -EINVAL;
10731074
break;
10741075
}
10751076
return ret;
10761077
}
10771078

10781079
static int xhci_evaluate_context_result(struct xhci_hcd *xhci,
1079-
struct usb_device *udev, struct xhci_virt_device *virt_dev)
1080+
struct usb_device *udev, int *cmd_status)
10801081
{
10811082
int ret;
1083+
struct xhci_virt_device *virt_dev = xhci->devs[udev->slot_id];
10821084

1083-
switch (virt_dev->cmd_status) {
1085+
switch (*cmd_status) {
10841086
case COMP_EINVAL:
10851087
dev_warn(&udev->dev, "WARN: xHCI driver setup invalid evaluate "
10861088
"context command.\n");
@@ -1101,7 +1103,7 @@ static int xhci_evaluate_context_result(struct xhci_hcd *xhci,
11011103
break;
11021104
default:
11031105
xhci_err(xhci, "ERROR: unexpected command completion "
1104-
"code 0x%x.\n", virt_dev->cmd_status);
1106+
"code 0x%x.\n", *cmd_status);
11051107
ret = -EINVAL;
11061108
break;
11071109
}
@@ -1112,19 +1114,37 @@ static int xhci_evaluate_context_result(struct xhci_hcd *xhci,
11121114
* and wait for it to finish.
11131115
*/
11141116
static int xhci_configure_endpoint(struct xhci_hcd *xhci,
1115-
struct usb_device *udev, struct xhci_virt_device *virt_dev,
1116-
bool ctx_change)
1117+
struct usb_device *udev,
1118+
struct xhci_command *command,
1119+
bool ctx_change, bool must_succeed)
11171120
{
11181121
int ret;
11191122
int timeleft;
11201123
unsigned long flags;
1124+
struct xhci_container_ctx *in_ctx;
1125+
struct completion *cmd_completion;
1126+
int *cmd_status;
1127+
struct xhci_virt_device *virt_dev;
11211128

11221129
spin_lock_irqsave(&xhci->lock, flags);
1130+
virt_dev = xhci->devs[udev->slot_id];
1131+
if (command) {
1132+
in_ctx = command->in_ctx;
1133+
cmd_completion = command->completion;
1134+
cmd_status = &command->status;
1135+
command->command_trb = xhci->cmd_ring->enqueue;
1136+
list_add_tail(&command->cmd_list, &virt_dev->cmd_list);
1137+
} else {
1138+
in_ctx = virt_dev->in_ctx;
1139+
cmd_completion = &virt_dev->cmd_completion;
1140+
cmd_status = &virt_dev->cmd_status;
1141+
}
1142+
11231143
if (!ctx_change)
1124-
ret = xhci_queue_configure_endpoint(xhci, virt_dev->in_ctx->dma,
1125-
udev->slot_id);
1144+
ret = xhci_queue_configure_endpoint(xhci, in_ctx->dma,
1145+
udev->slot_id, must_succeed);
11261146
else
1127-
ret = xhci_queue_evaluate_context(xhci, virt_dev->in_ctx->dma,
1147+
ret = xhci_queue_evaluate_context(xhci, in_ctx->dma,
11281148
udev->slot_id);
11291149
if (ret < 0) {
11301150
spin_unlock_irqrestore(&xhci->lock, flags);
@@ -1136,7 +1156,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
11361156

11371157
/* Wait for the configure endpoint command to complete */
11381158
timeleft = wait_for_completion_interruptible_timeout(
1139-
&virt_dev->cmd_completion,
1159+
cmd_completion,
11401160
USB_CTRL_SET_TIMEOUT);
11411161
if (timeleft <= 0) {
11421162
xhci_warn(xhci, "%s while waiting for %s command\n",
@@ -1149,8 +1169,8 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
11491169
}
11501170

11511171
if (!ctx_change)
1152-
return xhci_configure_endpoint_result(xhci, udev, virt_dev);
1153-
return xhci_evaluate_context_result(xhci, udev, virt_dev);
1172+
return xhci_configure_endpoint_result(xhci, udev, cmd_status);
1173+
return xhci_evaluate_context_result(xhci, udev, cmd_status);
11541174
}
11551175

11561176
/* Called after one or more calls to xhci_add_endpoint() or
@@ -1196,7 +1216,8 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
11961216
xhci_dbg_ctx(xhci, virt_dev->in_ctx,
11971217
LAST_CTX_TO_EP_NUM(slot_ctx->dev_info));
11981218

1199-
ret = xhci_configure_endpoint(xhci, udev, virt_dev, false);
1219+
ret = xhci_configure_endpoint(xhci, udev, NULL,
1220+
false, false);
12001221
if (ret) {
12011222
/* Callee should call reset_bandwidth() */
12021223
return ret;
@@ -1248,19 +1269,19 @@ void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
12481269
}
12491270

12501271
static void xhci_setup_input_ctx_for_config_ep(struct xhci_hcd *xhci,
1251-
unsigned int slot_id, u32 add_flags, u32 drop_flags)
1272+
struct xhci_container_ctx *in_ctx,
1273+
struct xhci_container_ctx *out_ctx,
1274+
u32 add_flags, u32 drop_flags)
12521275
{
12531276
struct xhci_input_control_ctx *ctrl_ctx;
1254-
ctrl_ctx = xhci_get_input_control_ctx(xhci,
1255-
xhci->devs[slot_id]->in_ctx);
1277+
ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
12561278
ctrl_ctx->add_flags = add_flags;
12571279
ctrl_ctx->drop_flags = drop_flags;
1258-
xhci_slot_copy(xhci, xhci->devs[slot_id]);
1280+
xhci_slot_copy(xhci, in_ctx, out_ctx);
12591281
ctrl_ctx->add_flags |= SLOT_FLAG;
12601282

1261-
xhci_dbg(xhci, "Slot ID %d Input Context:\n", slot_id);
1262-
xhci_dbg_ctx(xhci, xhci->devs[slot_id]->in_ctx,
1263-
xhci_last_valid_endpoint(add_flags));
1283+
xhci_dbg(xhci, "Input Context:\n");
1284+
xhci_dbg_ctx(xhci, in_ctx, xhci_last_valid_endpoint(add_flags));
12641285
}
12651286

12661287
void xhci_setup_input_ctx_for_quirk(struct xhci_hcd *xhci,
@@ -1272,7 +1293,8 @@ void xhci_setup_input_ctx_for_quirk(struct xhci_hcd *xhci,
12721293
u32 added_ctxs;
12731294
dma_addr_t addr;
12741295

1275-
xhci_endpoint_copy(xhci, xhci->devs[slot_id], ep_index);
1296+
xhci_endpoint_copy(xhci, xhci->devs[slot_id]->in_ctx,
1297+
xhci->devs[slot_id]->out_ctx, ep_index);
12761298
in_ctx = xhci->devs[slot_id]->in_ctx;
12771299
ep_ctx = xhci_get_ep_ctx(xhci, in_ctx, ep_index);
12781300
addr = xhci_trb_virt_to_dma(deq_state->new_deq_seg,
@@ -1288,8 +1310,8 @@ void xhci_setup_input_ctx_for_quirk(struct xhci_hcd *xhci,
12881310
ep_ctx->deq = addr | deq_state->new_cycle_state;
12891311

12901312
added_ctxs = xhci_get_endpoint_flag_from_index(ep_index);
1291-
xhci_setup_input_ctx_for_config_ep(xhci, slot_id,
1292-
added_ctxs, added_ctxs);
1313+
xhci_setup_input_ctx_for_config_ep(xhci, xhci->devs[slot_id]->in_ctx,
1314+
xhci->devs[slot_id]->out_ctx, added_ctxs, added_ctxs);
12931315
}
12941316

12951317
void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci,

drivers/usb/host/xhci-mem.c

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
319319
goto fail;
320320

321321
init_completion(&dev->cmd_completion);
322+
INIT_LIST_HEAD(&dev->cmd_list);
322323

323324
/* Point to output device context in dcbaa. */
324325
xhci->dcbaa->dev_context_ptrs[slot_id] = dev->out_ctx->dma;
@@ -624,13 +625,15 @@ void xhci_endpoint_zero(struct xhci_hcd *xhci,
624625
* issue a configure endpoint command.
625626
*/
626627
void xhci_endpoint_copy(struct xhci_hcd *xhci,
627-
struct xhci_virt_device *vdev, unsigned int ep_index)
628+
struct xhci_container_ctx *in_ctx,
629+
struct xhci_container_ctx *out_ctx,
630+
unsigned int ep_index)
628631
{
629632
struct xhci_ep_ctx *out_ep_ctx;
630633
struct xhci_ep_ctx *in_ep_ctx;
631634

632-
out_ep_ctx = xhci_get_ep_ctx(xhci, vdev->out_ctx, ep_index);
633-
in_ep_ctx = xhci_get_ep_ctx(xhci, vdev->in_ctx, ep_index);
635+
out_ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index);
636+
in_ep_ctx = xhci_get_ep_ctx(xhci, in_ctx, ep_index);
634637

635638
in_ep_ctx->ep_info = out_ep_ctx->ep_info;
636639
in_ep_ctx->ep_info2 = out_ep_ctx->ep_info2;
@@ -643,13 +646,15 @@ void xhci_endpoint_copy(struct xhci_hcd *xhci,
643646
* issue a configure endpoint command. Only the context entries field matters,
644647
* but we'll copy the whole thing anyway.
645648
*/
646-
void xhci_slot_copy(struct xhci_hcd *xhci, struct xhci_virt_device *vdev)
649+
void xhci_slot_copy(struct xhci_hcd *xhci,
650+
struct xhci_container_ctx *in_ctx,
651+
struct xhci_container_ctx *out_ctx)
647652
{
648653
struct xhci_slot_ctx *in_slot_ctx;
649654
struct xhci_slot_ctx *out_slot_ctx;
650655

651-
in_slot_ctx = xhci_get_slot_ctx(xhci, vdev->in_ctx);
652-
out_slot_ctx = xhci_get_slot_ctx(xhci, vdev->out_ctx);
656+
in_slot_ctx = xhci_get_slot_ctx(xhci, in_ctx);
657+
out_slot_ctx = xhci_get_slot_ctx(xhci, out_ctx);
653658

654659
in_slot_ctx->dev_info = out_slot_ctx->dev_info;
655660
in_slot_ctx->dev_info2 = out_slot_ctx->dev_info2;
@@ -754,6 +759,44 @@ static void scratchpad_free(struct xhci_hcd *xhci)
754759
xhci->scratchpad = NULL;
755760
}
756761

762+
struct xhci_command *xhci_alloc_command(struct xhci_hcd *xhci,
763+
bool allocate_completion, gfp_t mem_flags)
764+
{
765+
struct xhci_command *command;
766+
767+
command = kzalloc(sizeof(*command), mem_flags);
768+
if (!command)
769+
return NULL;
770+
771+
command->in_ctx =
772+
xhci_alloc_container_ctx(xhci, XHCI_CTX_TYPE_INPUT, mem_flags);
773+
if (!command->in_ctx)
774+
return NULL;
775+
776+
if (allocate_completion) {
777+
command->completion =
778+
kzalloc(sizeof(struct completion), mem_flags);
779+
if (!command->completion) {
780+
xhci_free_container_ctx(xhci, command->in_ctx);
781+
return NULL;
782+
}
783+
init_completion(command->completion);
784+
}
785+
786+
command->status = 0;
787+
INIT_LIST_HEAD(&command->cmd_list);
788+
return command;
789+
}
790+
791+
void xhci_free_command(struct xhci_hcd *xhci,
792+
struct xhci_command *command)
793+
{
794+
xhci_free_container_ctx(xhci,
795+
command->in_ctx);
796+
kfree(command->completion);
797+
kfree(command);
798+
}
799+
757800
void xhci_mem_cleanup(struct xhci_hcd *xhci)
758801
{
759802
struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);

0 commit comments

Comments
 (0)