forked from Minki/linux
xhci: avoid DMA double fetch when reading event trb type.
Instead of re-reading, masking and endianness correcting the same trb several times to get the trb type from an event, just do it once and store it in a local variable. Also pass the trb_type directly to the vendor specific event handler, avoiding one more similar read. In addition to the security benefit this also cleans up the code and helps readability. Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Link: https://lore.kernel.org/r/20210129130044.206855-13-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
55f6153d8c
commit
0353810a04
@ -1564,11 +1564,8 @@ event_handled:
|
||||
}
|
||||
|
||||
static void handle_vendor_event(struct xhci_hcd *xhci,
|
||||
union xhci_trb *event)
|
||||
union xhci_trb *event, u32 trb_type)
|
||||
{
|
||||
u32 trb_type;
|
||||
|
||||
trb_type = TRB_FIELD_TO_TYPE(le32_to_cpu(event->generic.field[3]));
|
||||
xhci_dbg(xhci, "Vendor specific event TRB type = %u\n", trb_type);
|
||||
if (trb_type == TRB_NEC_CMD_COMP && (xhci->quirks & XHCI_NEC_HOST))
|
||||
handle_cmd_completion(xhci, &event->event_cmd);
|
||||
@ -2733,6 +2730,7 @@ static int xhci_handle_event(struct xhci_hcd *xhci)
|
||||
{
|
||||
union xhci_trb *event;
|
||||
int update_ptrs = 1;
|
||||
u32 trb_type;
|
||||
int ret;
|
||||
|
||||
/* Event ring hasn't been allocated yet. */
|
||||
@ -2754,31 +2752,30 @@ static int xhci_handle_event(struct xhci_hcd *xhci)
|
||||
* speculative reads of the event's flags/data below.
|
||||
*/
|
||||
rmb();
|
||||
trb_type = TRB_FIELD_TO_TYPE(le32_to_cpu(event->event_cmd.flags));
|
||||
/* FIXME: Handle more event types. */
|
||||
switch (le32_to_cpu(event->event_cmd.flags) & TRB_TYPE_BITMASK) {
|
||||
case TRB_TYPE(TRB_COMPLETION):
|
||||
|
||||
switch (trb_type) {
|
||||
case TRB_COMPLETION:
|
||||
handle_cmd_completion(xhci, &event->event_cmd);
|
||||
break;
|
||||
case TRB_TYPE(TRB_PORT_STATUS):
|
||||
case TRB_PORT_STATUS:
|
||||
handle_port_status(xhci, event);
|
||||
update_ptrs = 0;
|
||||
break;
|
||||
case TRB_TYPE(TRB_TRANSFER):
|
||||
case TRB_TRANSFER:
|
||||
ret = handle_tx_event(xhci, &event->trans_event);
|
||||
if (ret >= 0)
|
||||
update_ptrs = 0;
|
||||
break;
|
||||
case TRB_TYPE(TRB_DEV_NOTE):
|
||||
case TRB_DEV_NOTE:
|
||||
handle_device_notification(xhci, event);
|
||||
break;
|
||||
default:
|
||||
if ((le32_to_cpu(event->event_cmd.flags) & TRB_TYPE_BITMASK) >=
|
||||
TRB_TYPE(48))
|
||||
handle_vendor_event(xhci, event);
|
||||
if (trb_type >= TRB_VENDOR_DEFINED_LOW)
|
||||
handle_vendor_event(xhci, event, trb_type);
|
||||
else
|
||||
xhci_warn(xhci, "ERROR unknown event type %d\n",
|
||||
TRB_FIELD_TO_TYPE(
|
||||
le32_to_cpu(event->event_cmd.flags)));
|
||||
xhci_warn(xhci, "ERROR unknown event type %d\n", trb_type);
|
||||
}
|
||||
/* Any of the above functions may drop and re-acquire the lock, so check
|
||||
* to make sure a watchdog timer didn't mark the host as non-responsive.
|
||||
|
@ -1419,7 +1419,7 @@ union xhci_trb {
|
||||
/* MFINDEX Wrap Event - microframe counter wrapped */
|
||||
#define TRB_MFINDEX_WRAP 39
|
||||
/* TRB IDs 40-47 reserved, 48-63 is vendor-defined */
|
||||
|
||||
#define TRB_VENDOR_DEFINED_LOW 48
|
||||
/* Nec vendor-specific command completion event. */
|
||||
#define TRB_NEC_CMD_COMP 48
|
||||
/* Get NEC firmware revision. */
|
||||
|
Loading…
Reference in New Issue
Block a user