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:12 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-06-16 00:44:48 -0400
commit0f2a79300a1471cf92ab43af165ea13555c8b0a5 (patch)
treea46c63777a6040708500aefdbc31e0a0404d2e4a /drivers/usb/host/xhci-ring.c
parent7206b00164a1c3ca533e01db285955617e1019f8 (diff)
USB: xhci: Root hub support.
Add functionality for getting port status and hub descriptor for xHCI root hubs. This is WIP because the USB 3.0 hub descriptor is different from the USB 2.0 hub descriptor. For now, we lie about the root hub descriptor because the changes won't effect how the core talks to the root hub. Later we will need to add the USB 3.0 hub descriptor for real hubs, and this code might change. 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.c43
1 files changed, 39 insertions, 4 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index c7e3c7142b9d..9d6bb3d730c4 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -284,9 +284,38 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
284 inc_deq(xhci, xhci->cmd_ring, false); 284 inc_deq(xhci, xhci->cmd_ring, false);
285} 285}
286 286
287static void handle_port_status(struct xhci_hcd *xhci,
288 union xhci_trb *event)
289{
290 u32 port_id;
291
292 /* Port status change events always have a successful completion code */
293 if (GET_COMP_CODE(event->generic.field[2]) != COMP_SUCCESS) {
294 xhci_warn(xhci, "WARN: xHC returned failed port status event\n");
295 xhci->error_bitmask |= 1 << 8;
296 }
297 /* FIXME: core doesn't care about all port link state changes yet */
298 port_id = GET_PORT_ID(event->generic.field[0]);
299 xhci_dbg(xhci, "Port Status Change Event for port %d\n", port_id);
300
301 /* Update event ring dequeue pointer before dropping the lock */
302 inc_deq(xhci, xhci->event_ring, true);
303 set_hc_event_deq(xhci);
304
305 spin_unlock(&xhci->lock);
306 /* Pass this up to the core */
307 usb_hcd_poll_rh_status(xhci_to_hcd(xhci));
308 spin_lock(&xhci->lock);
309}
310
311/*
312 * This function handles all OS-owned events on the event ring. It may drop
313 * xhci->lock between event processing (e.g. to pass up port status changes).
314 */
287void handle_event(struct xhci_hcd *xhci) 315void handle_event(struct xhci_hcd *xhci)
288{ 316{
289 union xhci_trb *event; 317 union xhci_trb *event;
318 int update_ptrs = 1;
290 319
291 if (!xhci->event_ring || !xhci->event_ring->dequeue) { 320 if (!xhci->event_ring || !xhci->event_ring->dequeue) {
292 xhci->error_bitmask |= 1 << 1; 321 xhci->error_bitmask |= 1 << 1;
@@ -301,18 +330,24 @@ void handle_event(struct xhci_hcd *xhci)
301 return; 330 return;
302 } 331 }
303 332
304 /* FIXME: Only handles command completion events. */ 333 /* FIXME: Handle more event types. */
305 switch ((event->event_cmd.flags & TRB_TYPE_BITMASK)) { 334 switch ((event->event_cmd.flags & TRB_TYPE_BITMASK)) {
306 case TRB_TYPE(TRB_COMPLETION): 335 case TRB_TYPE(TRB_COMPLETION):
307 handle_cmd_completion(xhci, &event->event_cmd); 336 handle_cmd_completion(xhci, &event->event_cmd);
308 break; 337 break;
338 case TRB_TYPE(TRB_PORT_STATUS):
339 handle_port_status(xhci, event);
340 update_ptrs = 0;
341 break;
309 default: 342 default:
310 xhci->error_bitmask |= 1 << 3; 343 xhci->error_bitmask |= 1 << 3;
311 } 344 }
312 345
313 /* Update SW and HC event ring dequeue pointer */ 346 if (update_ptrs) {
314 inc_deq(xhci, xhci->event_ring, true); 347 /* Update SW and HC event ring dequeue pointer */
315 set_hc_event_deq(xhci); 348 inc_deq(xhci, xhci->event_ring, true);
349 set_hc_event_deq(xhci);
350 }
316 /* Are there more items on the event ring? */ 351 /* Are there more items on the event ring? */
317 handle_event(xhci); 352 handle_event(xhci);
318} 353}