xhci: Make xHCI driver endian-safe
This patch changes the struct members defining access to xHCI device-visible memory to use __le32/__le64 where appropriate, and then adds swaps where required. Checked with sparse that all accesses are correct. MMIO accesses use readl/writel so already are performed LE, but prototypes now reflect this with __le*. There were a couple of (debug) instances of DMA pointers being truncated to 32bits which have been fixed too. Signed-off-by: Matt Evans <matt@ozlabs.org> Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
This commit is contained in:
parent
7fc2a61638
commit
28ccd2962c
6 changed files with 360 additions and 341 deletions
|
@ -973,8 +973,8 @@ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id,
|
|||
|
||||
out_ctx = xhci->devs[slot_id]->out_ctx;
|
||||
ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index);
|
||||
hw_max_packet_size = MAX_PACKET_DECODED(ep_ctx->ep_info2);
|
||||
max_packet_size = urb->dev->ep0.desc.wMaxPacketSize;
|
||||
hw_max_packet_size = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2));
|
||||
max_packet_size = le16_to_cpu(urb->dev->ep0.desc.wMaxPacketSize);
|
||||
if (hw_max_packet_size != max_packet_size) {
|
||||
xhci_dbg(xhci, "Max Packet Size for ep 0 changed.\n");
|
||||
xhci_dbg(xhci, "Max packet size in usb_device = %d\n",
|
||||
|
@ -988,15 +988,15 @@ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id,
|
|||
xhci->devs[slot_id]->out_ctx, ep_index);
|
||||
in_ctx = xhci->devs[slot_id]->in_ctx;
|
||||
ep_ctx = xhci_get_ep_ctx(xhci, in_ctx, ep_index);
|
||||
ep_ctx->ep_info2 &= ~MAX_PACKET_MASK;
|
||||
ep_ctx->ep_info2 |= MAX_PACKET(max_packet_size);
|
||||
ep_ctx->ep_info2 &= cpu_to_le32(~MAX_PACKET_MASK);
|
||||
ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet_size));
|
||||
|
||||
/* Set up the input context flags for the command */
|
||||
/* FIXME: This won't work if a non-default control endpoint
|
||||
* changes max packet sizes.
|
||||
*/
|
||||
ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
|
||||
ctrl_ctx->add_flags = EP0_FLAG;
|
||||
ctrl_ctx->add_flags = cpu_to_le32(EP0_FLAG);
|
||||
ctrl_ctx->drop_flags = 0;
|
||||
|
||||
xhci_dbg(xhci, "Slot %d input context\n", slot_id);
|
||||
|
@ -1010,7 +1010,7 @@ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id,
|
|||
/* Clean up the input context for later use by bandwidth
|
||||
* functions.
|
||||
*/
|
||||
ctrl_ctx->add_flags = SLOT_FLAG;
|
||||
ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -1331,27 +1331,30 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
|
|||
/* If the HC already knows the endpoint is disabled,
|
||||
* or the HCD has noted it is disabled, ignore this request
|
||||
*/
|
||||
if ((ep_ctx->ep_info & EP_STATE_MASK) == EP_STATE_DISABLED ||
|
||||
ctrl_ctx->drop_flags & xhci_get_endpoint_flag(&ep->desc)) {
|
||||
if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) ==
|
||||
EP_STATE_DISABLED ||
|
||||
le32_to_cpu(ctrl_ctx->drop_flags) &
|
||||
xhci_get_endpoint_flag(&ep->desc)) {
|
||||
xhci_warn(xhci, "xHCI %s called with disabled ep %p\n",
|
||||
__func__, ep);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctrl_ctx->drop_flags |= drop_flag;
|
||||
new_drop_flags = ctrl_ctx->drop_flags;
|
||||
ctrl_ctx->drop_flags |= cpu_to_le32(drop_flag);
|
||||
new_drop_flags = le32_to_cpu(ctrl_ctx->drop_flags);
|
||||
|
||||
ctrl_ctx->add_flags &= ~drop_flag;
|
||||
new_add_flags = ctrl_ctx->add_flags;
|
||||
ctrl_ctx->add_flags &= cpu_to_le32(~drop_flag);
|
||||
new_add_flags = le32_to_cpu(ctrl_ctx->add_flags);
|
||||
|
||||
last_ctx = xhci_last_valid_endpoint(ctrl_ctx->add_flags);
|
||||
last_ctx = xhci_last_valid_endpoint(le32_to_cpu(ctrl_ctx->add_flags));
|
||||
slot_ctx = xhci_get_slot_ctx(xhci, in_ctx);
|
||||
/* Update the last valid endpoint context, if we deleted the last one */
|
||||
if ((slot_ctx->dev_info & LAST_CTX_MASK) > LAST_CTX(last_ctx)) {
|
||||
slot_ctx->dev_info &= ~LAST_CTX_MASK;
|
||||
slot_ctx->dev_info |= LAST_CTX(last_ctx);
|
||||
if ((le32_to_cpu(slot_ctx->dev_info) & LAST_CTX_MASK) >
|
||||
LAST_CTX(last_ctx)) {
|
||||
slot_ctx->dev_info &= cpu_to_le32(~LAST_CTX_MASK);
|
||||
slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(last_ctx));
|
||||
}
|
||||
new_slot_info = slot_ctx->dev_info;
|
||||
new_slot_info = le32_to_cpu(slot_ctx->dev_info);
|
||||
|
||||
xhci_endpoint_zero(xhci, xhci->devs[udev->slot_id], ep);
|
||||
|
||||
|
@ -1419,7 +1422,8 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
|
|||
/* If the HCD has already noted the endpoint is enabled,
|
||||
* ignore this request.
|
||||
*/
|
||||
if (ctrl_ctx->add_flags & xhci_get_endpoint_flag(&ep->desc)) {
|
||||
if (le32_to_cpu(ctrl_ctx->add_flags) &
|
||||
xhci_get_endpoint_flag(&ep->desc)) {
|
||||
xhci_warn(xhci, "xHCI %s called with enabled ep %p\n",
|
||||
__func__, ep);
|
||||
return 0;
|
||||
|
@ -1437,8 +1441,8 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ctrl_ctx->add_flags |= added_ctxs;
|
||||
new_add_flags = ctrl_ctx->add_flags;
|
||||
ctrl_ctx->add_flags |= cpu_to_le32(added_ctxs);
|
||||
new_add_flags = le32_to_cpu(ctrl_ctx->add_flags);
|
||||
|
||||
/* If xhci_endpoint_disable() was called for this endpoint, but the
|
||||
* xHC hasn't been notified yet through the check_bandwidth() call,
|
||||
|
@ -1446,15 +1450,16 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
|
|||
* descriptors. We must drop and re-add this endpoint, so we leave the
|
||||
* drop flags alone.
|
||||
*/
|
||||
new_drop_flags = ctrl_ctx->drop_flags;
|
||||
new_drop_flags = le32_to_cpu(ctrl_ctx->drop_flags);
|
||||
|
||||
slot_ctx = xhci_get_slot_ctx(xhci, in_ctx);
|
||||
/* Update the last valid endpoint context, if we just added one past */
|
||||
if ((slot_ctx->dev_info & LAST_CTX_MASK) < LAST_CTX(last_ctx)) {
|
||||
slot_ctx->dev_info &= ~LAST_CTX_MASK;
|
||||
slot_ctx->dev_info |= LAST_CTX(last_ctx);
|
||||
if ((le32_to_cpu(slot_ctx->dev_info) & LAST_CTX_MASK) <
|
||||
LAST_CTX(last_ctx)) {
|
||||
slot_ctx->dev_info &= cpu_to_le32(~LAST_CTX_MASK);
|
||||
slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(last_ctx));
|
||||
}
|
||||
new_slot_info = slot_ctx->dev_info;
|
||||
new_slot_info = le32_to_cpu(slot_ctx->dev_info);
|
||||
|
||||
/* Store the usb_device pointer for later use */
|
||||
ep->hcpriv = udev;
|
||||
|
@ -1484,9 +1489,9 @@ static void xhci_zero_in_ctx(struct xhci_hcd *xhci, struct xhci_virt_device *vir
|
|||
ctrl_ctx->drop_flags = 0;
|
||||
ctrl_ctx->add_flags = 0;
|
||||
slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
|
||||
slot_ctx->dev_info &= ~LAST_CTX_MASK;
|
||||
slot_ctx->dev_info &= cpu_to_le32(~LAST_CTX_MASK);
|
||||
/* Endpoint 0 is always valid */
|
||||
slot_ctx->dev_info |= LAST_CTX(1);
|
||||
slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1));
|
||||
for (i = 1; i < 31; ++i) {
|
||||
ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, i);
|
||||
ep_ctx->ep_info = 0;
|
||||
|
@ -1581,7 +1586,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
|
|||
unsigned long flags;
|
||||
struct xhci_container_ctx *in_ctx;
|
||||
struct completion *cmd_completion;
|
||||
int *cmd_status;
|
||||
u32 *cmd_status;
|
||||
struct xhci_virt_device *virt_dev;
|
||||
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
|
@ -1595,8 +1600,8 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
|
|||
/* Enqueue pointer can be left pointing to the link TRB,
|
||||
* we must handle that
|
||||
*/
|
||||
if ((command->command_trb->link.control & TRB_TYPE_BITMASK)
|
||||
== TRB_TYPE(TRB_LINK))
|
||||
if ((le32_to_cpu(command->command_trb->link.control)
|
||||
& TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK))
|
||||
command->command_trb =
|
||||
xhci->cmd_ring->enq_seg->next->trbs;
|
||||
|
||||
|
@ -1672,14 +1677,13 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
|
|||
|
||||
/* See section 4.6.6 - A0 = 1; A1 = D0 = D1 = 0 */
|
||||
ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
|
||||
ctrl_ctx->add_flags |= SLOT_FLAG;
|
||||
ctrl_ctx->add_flags &= ~EP0_FLAG;
|
||||
ctrl_ctx->drop_flags &= ~SLOT_FLAG;
|
||||
ctrl_ctx->drop_flags &= ~EP0_FLAG;
|
||||
ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG);
|
||||
ctrl_ctx->add_flags &= cpu_to_le32(~EP0_FLAG);
|
||||
ctrl_ctx->drop_flags &= cpu_to_le32(~(SLOT_FLAG | EP0_FLAG));
|
||||
xhci_dbg(xhci, "New Input Control Context:\n");
|
||||
slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
|
||||
xhci_dbg_ctx(xhci, virt_dev->in_ctx,
|
||||
LAST_CTX_TO_EP_NUM(slot_ctx->dev_info));
|
||||
LAST_CTX_TO_EP_NUM(le32_to_cpu(slot_ctx->dev_info)));
|
||||
|
||||
ret = xhci_configure_endpoint(xhci, udev, NULL,
|
||||
false, false);
|
||||
|
@ -1690,7 +1694,7 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
|
|||
|
||||
xhci_dbg(xhci, "Output context after successful config ep cmd:\n");
|
||||
xhci_dbg_ctx(xhci, virt_dev->out_ctx,
|
||||
LAST_CTX_TO_EP_NUM(slot_ctx->dev_info));
|
||||
LAST_CTX_TO_EP_NUM(le32_to_cpu(slot_ctx->dev_info)));
|
||||
|
||||
xhci_zero_in_ctx(xhci, virt_dev);
|
||||
/* Install new rings and free or cache any old rings */
|
||||
|
@ -1740,10 +1744,10 @@ static void xhci_setup_input_ctx_for_config_ep(struct xhci_hcd *xhci,
|
|||
{
|
||||
struct xhci_input_control_ctx *ctrl_ctx;
|
||||
ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
|
||||
ctrl_ctx->add_flags = add_flags;
|
||||
ctrl_ctx->drop_flags = drop_flags;
|
||||
ctrl_ctx->add_flags = cpu_to_le32(add_flags);
|
||||
ctrl_ctx->drop_flags = cpu_to_le32(drop_flags);
|
||||
xhci_slot_copy(xhci, in_ctx, out_ctx);
|
||||
ctrl_ctx->add_flags |= SLOT_FLAG;
|
||||
ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG);
|
||||
|
||||
xhci_dbg(xhci, "Input Context:\n");
|
||||
xhci_dbg_ctx(xhci, in_ctx, xhci_last_valid_endpoint(add_flags));
|
||||
|
@ -1772,7 +1776,7 @@ static void xhci_setup_input_ctx_for_quirk(struct xhci_hcd *xhci,
|
|||
deq_state->new_deq_ptr);
|
||||
return;
|
||||
}
|
||||
ep_ctx->deq = addr | deq_state->new_cycle_state;
|
||||
ep_ctx->deq = cpu_to_le64(addr | deq_state->new_cycle_state);
|
||||
|
||||
added_ctxs = xhci_get_endpoint_flag_from_index(ep_index);
|
||||
xhci_setup_input_ctx_for_config_ep(xhci, xhci->devs[slot_id]->in_ctx,
|
||||
|
@ -2327,8 +2331,8 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
|
|||
/* Enqueue pointer can be left pointing to the link TRB,
|
||||
* we must handle that
|
||||
*/
|
||||
if ((reset_device_cmd->command_trb->link.control & TRB_TYPE_BITMASK)
|
||||
== TRB_TYPE(TRB_LINK))
|
||||
if ((le32_to_cpu(reset_device_cmd->command_trb->link.control)
|
||||
& TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK))
|
||||
reset_device_cmd->command_trb =
|
||||
xhci->cmd_ring->enq_seg->next->trbs;
|
||||
|
||||
|
@ -2609,10 +2613,10 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
|
|||
temp_64 = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr);
|
||||
xhci_dbg(xhci, "Op regs DCBAA ptr = %#016llx\n", temp_64);
|
||||
xhci_dbg(xhci, "Slot ID %d dcbaa entry @%p = %#016llx\n",
|
||||
udev->slot_id,
|
||||
&xhci->dcbaa->dev_context_ptrs[udev->slot_id],
|
||||
(unsigned long long)
|
||||
xhci->dcbaa->dev_context_ptrs[udev->slot_id]);
|
||||
udev->slot_id,
|
||||
&xhci->dcbaa->dev_context_ptrs[udev->slot_id],
|
||||
(unsigned long long)
|
||||
le64_to_cpu(xhci->dcbaa->dev_context_ptrs[udev->slot_id]));
|
||||
xhci_dbg(xhci, "Output Context DMA address = %#08llx\n",
|
||||
(unsigned long long)virt_dev->out_ctx->dma);
|
||||
xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id);
|
||||
|
@ -2626,7 +2630,8 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
|
|||
slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx);
|
||||
/* Use kernel assigned address for devices; store xHC assigned
|
||||
* address locally. */
|
||||
virt_dev->address = (slot_ctx->dev_state & DEV_ADDR_MASK) + 1;
|
||||
virt_dev->address = (le32_to_cpu(slot_ctx->dev_state) & DEV_ADDR_MASK)
|
||||
+ 1;
|
||||
/* Zero the input context control for later use */
|
||||
ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
|
||||
ctrl_ctx->add_flags = 0;
|
||||
|
@ -2670,16 +2675,16 @@ int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
|
|||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
xhci_slot_copy(xhci, config_cmd->in_ctx, vdev->out_ctx);
|
||||
ctrl_ctx = xhci_get_input_control_ctx(xhci, config_cmd->in_ctx);
|
||||
ctrl_ctx->add_flags |= SLOT_FLAG;
|
||||
ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG);
|
||||
slot_ctx = xhci_get_slot_ctx(xhci, config_cmd->in_ctx);
|
||||
slot_ctx->dev_info |= DEV_HUB;
|
||||
slot_ctx->dev_info |= cpu_to_le32(DEV_HUB);
|
||||
if (tt->multi)
|
||||
slot_ctx->dev_info |= DEV_MTT;
|
||||
slot_ctx->dev_info |= cpu_to_le32(DEV_MTT);
|
||||
if (xhci->hci_version > 0x95) {
|
||||
xhci_dbg(xhci, "xHCI version %x needs hub "
|
||||
"TT think time and number of ports\n",
|
||||
(unsigned int) xhci->hci_version);
|
||||
slot_ctx->dev_info2 |= XHCI_MAX_PORTS(hdev->maxchild);
|
||||
slot_ctx->dev_info2 |= cpu_to_le32(XHCI_MAX_PORTS(hdev->maxchild));
|
||||
/* Set TT think time - convert from ns to FS bit times.
|
||||
* 0 = 8 FS bit times, 1 = 16 FS bit times,
|
||||
* 2 = 24 FS bit times, 3 = 32 FS bit times.
|
||||
|
@ -2687,7 +2692,7 @@ int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
|
|||
think_time = tt->think_time;
|
||||
if (think_time != 0)
|
||||
think_time = (think_time / 666) - 1;
|
||||
slot_ctx->tt_info |= TT_THINK_TIME(think_time);
|
||||
slot_ctx->tt_info |= cpu_to_le32(TT_THINK_TIME(think_time));
|
||||
} else {
|
||||
xhci_dbg(xhci, "xHCI version %x doesn't need hub "
|
||||
"TT think time or number of ports\n",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue