aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci-ring.c
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2009-04-27 22:57:38 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-06-16 00:44:49 -0400
commit3ffbba9511b4148cbe1f6b6238686adaeaca8feb (patch)
treef69e42d07d596039e049fe2b14b720ddc6be2694 /drivers/usb/host/xhci-ring.c
parentc6515272b858742962c1de0f3bf497a048b9abd7 (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.c34
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)
252static void handle_cmd_completion(struct xhci_hcd *xhci, 252static 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 */
417int 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 */
424int 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}