Commit 0353810a authored by Mathias Nyman's avatar Mathias Nyman Committed by Greg Kroah-Hartman

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: default avatarMathias Nyman <mathias.nyman@linux.intel.com>
Link: https://lore.kernel.org/r/20210129130044.206855-13-mathias.nyman@linux.intel.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 55f6153d
...@@ -1564,11 +1564,8 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, ...@@ -1564,11 +1564,8 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
} }
static void handle_vendor_event(struct xhci_hcd *xhci, 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); xhci_dbg(xhci, "Vendor specific event TRB type = %u\n", trb_type);
if (trb_type == TRB_NEC_CMD_COMP && (xhci->quirks & XHCI_NEC_HOST)) if (trb_type == TRB_NEC_CMD_COMP && (xhci->quirks & XHCI_NEC_HOST))
handle_cmd_completion(xhci, &event->event_cmd); handle_cmd_completion(xhci, &event->event_cmd);
...@@ -2733,6 +2730,7 @@ static int xhci_handle_event(struct xhci_hcd *xhci) ...@@ -2733,6 +2730,7 @@ static int xhci_handle_event(struct xhci_hcd *xhci)
{ {
union xhci_trb *event; union xhci_trb *event;
int update_ptrs = 1; int update_ptrs = 1;
u32 trb_type;
int ret; int ret;
/* Event ring hasn't been allocated yet. */ /* Event ring hasn't been allocated yet. */
...@@ -2754,31 +2752,30 @@ static int xhci_handle_event(struct xhci_hcd *xhci) ...@@ -2754,31 +2752,30 @@ static int xhci_handle_event(struct xhci_hcd *xhci)
* speculative reads of the event's flags/data below. * speculative reads of the event's flags/data below.
*/ */
rmb(); rmb();
trb_type = TRB_FIELD_TO_TYPE(le32_to_cpu(event->event_cmd.flags));
/* FIXME: Handle more event types. */ /* 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); handle_cmd_completion(xhci, &event->event_cmd);
break; break;
case TRB_TYPE(TRB_PORT_STATUS): case TRB_PORT_STATUS:
handle_port_status(xhci, event); handle_port_status(xhci, event);
update_ptrs = 0; update_ptrs = 0;
break; break;
case TRB_TYPE(TRB_TRANSFER): case TRB_TRANSFER:
ret = handle_tx_event(xhci, &event->trans_event); ret = handle_tx_event(xhci, &event->trans_event);
if (ret >= 0) if (ret >= 0)
update_ptrs = 0; update_ptrs = 0;
break; break;
case TRB_TYPE(TRB_DEV_NOTE): case TRB_DEV_NOTE:
handle_device_notification(xhci, event); handle_device_notification(xhci, event);
break; break;
default: default:
if ((le32_to_cpu(event->event_cmd.flags) & TRB_TYPE_BITMASK) >= if (trb_type >= TRB_VENDOR_DEFINED_LOW)
TRB_TYPE(48)) handle_vendor_event(xhci, event, trb_type);
handle_vendor_event(xhci, event);
else else
xhci_warn(xhci, "ERROR unknown event type %d\n", xhci_warn(xhci, "ERROR unknown event type %d\n", trb_type);
TRB_FIELD_TO_TYPE(
le32_to_cpu(event->event_cmd.flags)));
} }
/* Any of the above functions may drop and re-acquire the lock, so check /* 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. * to make sure a watchdog timer didn't mark the host as non-responsive.
......
...@@ -1419,7 +1419,7 @@ union xhci_trb { ...@@ -1419,7 +1419,7 @@ union xhci_trb {
/* MFINDEX Wrap Event - microframe counter wrapped */ /* MFINDEX Wrap Event - microframe counter wrapped */
#define TRB_MFINDEX_WRAP 39 #define TRB_MFINDEX_WRAP 39
/* TRB IDs 40-47 reserved, 48-63 is vendor-defined */ /* TRB IDs 40-47 reserved, 48-63 is vendor-defined */
#define TRB_VENDOR_DEFINED_LOW 48
/* Nec vendor-specific command completion event. */ /* Nec vendor-specific command completion event. */
#define TRB_NEC_CMD_COMP 48 #define TRB_NEC_CMD_COMP 48
/* Get NEC firmware revision. */ /* Get NEC firmware revision. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment