diff options
author | Sarah Sharp <sarah.a.sharp@linux.intel.com> | 2009-07-27 15:03:31 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-07-28 17:31:12 -0400 |
commit | 8e595a5d30a5ee4bb745d4da6439d73ed7d91054 (patch) | |
tree | 0050cb2c24643b602a8b3c40adef3e7b73fe81fc /drivers/usb/host/xhci-hcd.c | |
parent | b11069f5f6ce6e359f853e908b0917303fcdec8f (diff) |
USB: xhci: Represent 64-bit addresses with one u64.
There are several xHCI data structures that use two 32-bit fields to
represent a 64-bit address. Since some architectures don't support 64-bit
PCI writes, the fields need to be written in two 32-bit writes. The xHCI
specification says that if a platform is incapable of generating 64-bit
writes, software must write the low 32-bits first, then the high 32-bits.
Hardware that supports 64-bit addressing will wait for the high 32-bit
write before reading the revised value, and hardware that only supports
32-bit writes will ignore the high 32-bit write.
Previous xHCI code represented 64-bit addresses with two u32 values. This
lead to buggy code that would write the 32-bits in the wrong order, or
forget to write the upper 32-bits. Change the two u32s to one u64 and
create a function call to write all 64-bit addresses in the proper order.
This new function could be modified in the future if all platforms support
64-bit writes.
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/xhci-hcd.c')
-rw-r--r-- | drivers/usb/host/xhci-hcd.c | 43 |
1 files changed, 19 insertions, 24 deletions
diff --git a/drivers/usb/host/xhci-hcd.c b/drivers/usb/host/xhci-hcd.c index ff99365cae42..e15773598e4e 100644 --- a/drivers/usb/host/xhci-hcd.c +++ b/drivers/usb/host/xhci-hcd.c | |||
@@ -226,6 +226,7 @@ int xhci_init(struct usb_hcd *hcd) | |||
226 | static void xhci_work(struct xhci_hcd *xhci) | 226 | static void xhci_work(struct xhci_hcd *xhci) |
227 | { | 227 | { |
228 | u32 temp; | 228 | u32 temp; |
229 | u64 temp_64; | ||
229 | 230 | ||
230 | /* | 231 | /* |
231 | * Clear the op reg interrupt status first, | 232 | * Clear the op reg interrupt status first, |
@@ -249,8 +250,8 @@ static void xhci_work(struct xhci_hcd *xhci) | |||
249 | xhci_handle_event(xhci); | 250 | xhci_handle_event(xhci); |
250 | 251 | ||
251 | /* Clear the event handler busy flag; the event ring should be empty. */ | 252 | /* Clear the event handler busy flag; the event ring should be empty. */ |
252 | temp = xhci_readl(xhci, &xhci->ir_set->erst_dequeue[0]); | 253 | temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); |
253 | xhci_writel(xhci, temp & ~ERST_EHB, &xhci->ir_set->erst_dequeue[0]); | 254 | xhci_write_64(xhci, temp_64 & ~ERST_EHB, &xhci->ir_set->erst_dequeue); |
254 | /* Flush posted writes -- FIXME is this necessary? */ | 255 | /* Flush posted writes -- FIXME is this necessary? */ |
255 | xhci_readl(xhci, &xhci->ir_set->irq_pending); | 256 | xhci_readl(xhci, &xhci->ir_set->irq_pending); |
256 | } | 257 | } |
@@ -295,6 +296,7 @@ void xhci_event_ring_work(unsigned long arg) | |||
295 | { | 296 | { |
296 | unsigned long flags; | 297 | unsigned long flags; |
297 | int temp; | 298 | int temp; |
299 | u64 temp_64; | ||
298 | struct xhci_hcd *xhci = (struct xhci_hcd *) arg; | 300 | struct xhci_hcd *xhci = (struct xhci_hcd *) arg; |
299 | int i, j; | 301 | int i, j; |
300 | 302 | ||
@@ -311,9 +313,9 @@ void xhci_event_ring_work(unsigned long arg) | |||
311 | xhci_dbg(xhci, "Event ring:\n"); | 313 | xhci_dbg(xhci, "Event ring:\n"); |
312 | xhci_debug_segment(xhci, xhci->event_ring->deq_seg); | 314 | xhci_debug_segment(xhci, xhci->event_ring->deq_seg); |
313 | xhci_dbg_ring_ptrs(xhci, xhci->event_ring); | 315 | xhci_dbg_ring_ptrs(xhci, xhci->event_ring); |
314 | temp = xhci_readl(xhci, &xhci->ir_set->erst_dequeue[0]); | 316 | temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); |
315 | temp &= ERST_PTR_MASK; | 317 | temp_64 &= ~ERST_PTR_MASK; |
316 | xhci_dbg(xhci, "ERST deq = 0x%x\n", temp); | 318 | xhci_dbg(xhci, "ERST deq = 64'h%0lx\n", (long unsigned int) temp_64); |
317 | xhci_dbg(xhci, "Command ring:\n"); | 319 | xhci_dbg(xhci, "Command ring:\n"); |
318 | xhci_debug_segment(xhci, xhci->cmd_ring->deq_seg); | 320 | xhci_debug_segment(xhci, xhci->cmd_ring->deq_seg); |
319 | xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring); | 321 | xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring); |
@@ -356,6 +358,7 @@ void xhci_event_ring_work(unsigned long arg) | |||
356 | int xhci_run(struct usb_hcd *hcd) | 358 | int xhci_run(struct usb_hcd *hcd) |
357 | { | 359 | { |
358 | u32 temp; | 360 | u32 temp; |
361 | u64 temp_64; | ||
359 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 362 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
360 | void (*doorbell)(struct xhci_hcd *) = NULL; | 363 | void (*doorbell)(struct xhci_hcd *) = NULL; |
361 | 364 | ||
@@ -416,11 +419,9 @@ int xhci_run(struct usb_hcd *hcd) | |||
416 | xhci_dbg(xhci, "Event ring:\n"); | 419 | xhci_dbg(xhci, "Event ring:\n"); |
417 | xhci_debug_ring(xhci, xhci->event_ring); | 420 | xhci_debug_ring(xhci, xhci->event_ring); |
418 | xhci_dbg_ring_ptrs(xhci, xhci->event_ring); | 421 | xhci_dbg_ring_ptrs(xhci, xhci->event_ring); |
419 | temp = xhci_readl(xhci, &xhci->ir_set->erst_dequeue[0]); | 422 | temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); |
420 | temp &= ERST_PTR_MASK; | 423 | temp_64 &= ~ERST_PTR_MASK; |
421 | xhci_dbg(xhci, "ERST deq = 0x%x\n", temp); | 424 | xhci_dbg(xhci, "ERST deq = 64'h%0lx\n", (long unsigned int) temp_64); |
422 | temp = xhci_readl(xhci, &xhci->ir_set->erst_dequeue[1]); | ||
423 | xhci_dbg(xhci, "ERST deq upper = 0x%x\n", temp); | ||
424 | 425 | ||
425 | temp = xhci_readl(xhci, &xhci->op_regs->command); | 426 | temp = xhci_readl(xhci, &xhci->op_regs->command); |
426 | temp |= (CMD_RUN); | 427 | temp |= (CMD_RUN); |
@@ -888,8 +889,7 @@ static void xhci_zero_in_ctx(struct xhci_virt_device *virt_dev) | |||
888 | ep_ctx = &virt_dev->in_ctx->ep[i]; | 889 | ep_ctx = &virt_dev->in_ctx->ep[i]; |
889 | ep_ctx->ep_info = 0; | 890 | ep_ctx->ep_info = 0; |
890 | ep_ctx->ep_info2 = 0; | 891 | ep_ctx->ep_info2 = 0; |
891 | ep_ctx->deq[0] = 0; | 892 | ep_ctx->deq = 0; |
892 | ep_ctx->deq[1] = 0; | ||
893 | ep_ctx->tx_info = 0; | 893 | ep_ctx->tx_info = 0; |
894 | } | 894 | } |
895 | } | 895 | } |
@@ -1165,7 +1165,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) | |||
1165 | struct xhci_virt_device *virt_dev; | 1165 | struct xhci_virt_device *virt_dev; |
1166 | int ret = 0; | 1166 | int ret = 0; |
1167 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 1167 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
1168 | u32 temp; | 1168 | u64 temp_64; |
1169 | 1169 | ||
1170 | if (!udev->slot_id) { | 1170 | if (!udev->slot_id) { |
1171 | xhci_dbg(xhci, "Bad Slot ID %d\n", udev->slot_id); | 1171 | xhci_dbg(xhci, "Bad Slot ID %d\n", udev->slot_id); |
@@ -1227,18 +1227,13 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) | |||
1227 | if (ret) { | 1227 | if (ret) { |
1228 | return ret; | 1228 | return ret; |
1229 | } | 1229 | } |
1230 | temp = xhci_readl(xhci, &xhci->op_regs->dcbaa_ptr[0]); | 1230 | temp_64 = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr); |
1231 | xhci_dbg(xhci, "Op regs DCBAA ptr[0] = %#08x\n", temp); | 1231 | xhci_dbg(xhci, "Op regs DCBAA ptr = %#016llx\n", temp_64); |
1232 | temp = xhci_readl(xhci, &xhci->op_regs->dcbaa_ptr[1]); | 1232 | xhci_dbg(xhci, "Slot ID %d dcbaa entry @%p = %#016llx\n", |
1233 | xhci_dbg(xhci, "Op regs DCBAA ptr[1] = %#08x\n", temp); | ||
1234 | xhci_dbg(xhci, "Slot ID %d dcbaa entry[0] @%p = %#08x\n", | ||
1235 | udev->slot_id, | ||
1236 | &xhci->dcbaa->dev_context_ptrs[2*udev->slot_id], | ||
1237 | xhci->dcbaa->dev_context_ptrs[2*udev->slot_id]); | ||
1238 | xhci_dbg(xhci, "Slot ID %d dcbaa entry[1] @%p = %#08x\n", | ||
1239 | udev->slot_id, | 1233 | udev->slot_id, |
1240 | &xhci->dcbaa->dev_context_ptrs[2*udev->slot_id+1], | 1234 | &xhci->dcbaa->dev_context_ptrs[udev->slot_id], |
1241 | xhci->dcbaa->dev_context_ptrs[2*udev->slot_id+1]); | 1235 | (unsigned long long) |
1236 | xhci->dcbaa->dev_context_ptrs[udev->slot_id]); | ||
1242 | xhci_dbg(xhci, "Output Context DMA address = %#08llx\n", | 1237 | xhci_dbg(xhci, "Output Context DMA address = %#08llx\n", |
1243 | (unsigned long long)virt_dev->out_ctx_dma); | 1238 | (unsigned long long)virt_dev->out_ctx_dma); |
1244 | xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id); | 1239 | xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id); |