diff options
author | Sarah Sharp <sarah.a.sharp@linux.intel.com> | 2009-04-27 22:57:38 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-06-16 00:44:49 -0400 |
commit | 3ffbba9511b4148cbe1f6b6238686adaeaca8feb (patch) | |
tree | f69e42d07d596039e049fe2b14b720ddc6be2694 /drivers/usb/host/xhci-ring.c | |
parent | c6515272b858742962c1de0f3bf497a048b9abd7 (diff) |
USB: xhci: Allocate and address USB devices
xHCI needs to get a "Slot ID" from the host controller and allocate other
data structures for every USB device. Make usb_alloc_dev() and
usb_release_dev() allocate and free these device structures. After
setting up the xHC device structures, usb_alloc_dev() must wait for the
hardware to respond to an Enable Slot command. usb_alloc_dev() fires off
a Disable Slot command and does not wait for it to complete.
When the USB core wants to choose an address for the device, the xHCI
driver must issue a Set Address command and wait for an event for that
command.
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-ring.c')
-rw-r--r-- | drivers/usb/host/xhci-ring.c | 34 |
1 files changed, 30 insertions, 4 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 9d6bb3d730c4..901ce70b30b8 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c | |||
@@ -252,13 +252,10 @@ void ring_cmd_db(struct xhci_hcd *xhci) | |||
252 | static void handle_cmd_completion(struct xhci_hcd *xhci, | 252 | static void handle_cmd_completion(struct xhci_hcd *xhci, |
253 | struct xhci_event_cmd *event) | 253 | struct xhci_event_cmd *event) |
254 | { | 254 | { |
255 | int slot_id = TRB_TO_SLOT_ID(event->flags); | ||
255 | u64 cmd_dma; | 256 | u64 cmd_dma; |
256 | dma_addr_t cmd_dequeue_dma; | 257 | dma_addr_t cmd_dequeue_dma; |
257 | 258 | ||
258 | /* Check completion code */ | ||
259 | if (GET_COMP_CODE(event->status) != COMP_SUCCESS) | ||
260 | xhci_dbg(xhci, "WARN: unsuccessful no-op command\n"); | ||
261 | |||
262 | cmd_dma = (((u64) event->cmd_trb[1]) << 32) + event->cmd_trb[0]; | 259 | cmd_dma = (((u64) event->cmd_trb[1]) << 32) + event->cmd_trb[0]; |
263 | cmd_dequeue_dma = trb_virt_to_dma(xhci->cmd_ring->deq_seg, | 260 | cmd_dequeue_dma = trb_virt_to_dma(xhci->cmd_ring->deq_seg, |
264 | xhci->cmd_ring->dequeue); | 261 | xhci->cmd_ring->dequeue); |
@@ -273,6 +270,21 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, | |||
273 | return; | 270 | return; |
274 | } | 271 | } |
275 | switch (xhci->cmd_ring->dequeue->generic.field[3] & TRB_TYPE_BITMASK) { | 272 | switch (xhci->cmd_ring->dequeue->generic.field[3] & TRB_TYPE_BITMASK) { |
273 | case TRB_TYPE(TRB_ENABLE_SLOT): | ||
274 | if (GET_COMP_CODE(event->status) == COMP_SUCCESS) | ||
275 | xhci->slot_id = slot_id; | ||
276 | else | ||
277 | xhci->slot_id = 0; | ||
278 | complete(&xhci->addr_dev); | ||
279 | break; | ||
280 | case TRB_TYPE(TRB_DISABLE_SLOT): | ||
281 | if (xhci->devs[slot_id]) | ||
282 | xhci_free_virt_device(xhci, slot_id); | ||
283 | break; | ||
284 | case TRB_TYPE(TRB_ADDR_DEV): | ||
285 | xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(event->status); | ||
286 | complete(&xhci->addr_dev); | ||
287 | break; | ||
276 | case TRB_TYPE(TRB_CMD_NOOP): | 288 | case TRB_TYPE(TRB_CMD_NOOP): |
277 | ++xhci->noops_handled; | 289 | ++xhci->noops_handled; |
278 | break; | 290 | break; |
@@ -400,3 +412,17 @@ void *setup_one_noop(struct xhci_hcd *xhci) | |||
400 | xhci->noops_submitted++; | 412 | xhci->noops_submitted++; |
401 | return ring_cmd_db; | 413 | return ring_cmd_db; |
402 | } | 414 | } |
415 | |||
416 | /* Queue a slot enable or disable request on the command ring */ | ||
417 | int queue_slot_control(struct xhci_hcd *xhci, u32 trb_type, u32 slot_id) | ||
418 | { | ||
419 | return queue_command(xhci, 0, 0, 0, | ||
420 | TRB_TYPE(trb_type) | SLOT_ID_FOR_TRB(slot_id)); | ||
421 | } | ||
422 | |||
423 | /* Queue an address device command TRB */ | ||
424 | int queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, u32 slot_id) | ||
425 | { | ||
426 | return queue_command(xhci, in_ctx_ptr, 0, 0, | ||
427 | TRB_TYPE(TRB_ADDR_DEV) | SLOT_ID_FOR_TRB(slot_id)); | ||
428 | } | ||