aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci-hub.c
diff options
context:
space:
mode:
authorMathias Nyman <mathias.nyman@linux.intel.com>2014-05-08 12:26:00 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-05-19 21:03:25 -0400
commitddba5cd0aeff5bbed92ebdf4b1223300b0541e78 (patch)
treedf3c979cd4ee80815538dc2f86cb4bfb451e7c43 /drivers/usb/host/xhci-hub.c
parentbe9820383b10984d77abe1abc26e2b7029e78e21 (diff)
xhci: Use command structures when queuing commands on the command ring
To create a global command queue we require that each command put on the command ring is submitted with a command structure. Functions that queue commands and wait for completion need to allocate a command before submitting it, and free it once completed. The following command queuing functions need to be modified. xhci_configure_endpoint() xhci_address_device() xhci_queue_slot_control() xhci_queue_stop_endpoint() xhci_queue_new_dequeue_state() xhci_queue_reset_ep() xhci_configure_endpoint() xhci_configure_endpoint() could already be called with a command structure, and only xhci_check_maxpacket and xhci_check_bandwidth did not do so. These are changed and a command structure is now required. This change also simplifies the configure endpoint command completion handling and the "goto bandwidth_change" handling code can be removed. In some cases the command queuing function is called in interrupt context. These commands needs to be allocated atomically, and they can't wait for completion. These commands will in this patch be freed directly after queuing, but freeing will be moved to the command completion event handler in a later patch once we get the global command queue up.(Just so that we won't leak memory in the middle of the patch set) Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/host/xhci-hub.c')
-rw-r--r--drivers/usb/host/xhci-hub.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 1ad6bc1951c7..3ce9c0ac2614 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -20,7 +20,8 @@
20 * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */ 21 */
22 22
23#include <linux/gfp.h> 23
24#include <linux/slab.h>
24#include <asm/unaligned.h> 25#include <asm/unaligned.h>
25 26
26#include "xhci.h" 27#include "xhci.h"
@@ -284,12 +285,22 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend)
284 285
285 spin_lock_irqsave(&xhci->lock, flags); 286 spin_lock_irqsave(&xhci->lock, flags);
286 for (i = LAST_EP_INDEX; i > 0; i--) { 287 for (i = LAST_EP_INDEX; i > 0; i--) {
287 if (virt_dev->eps[i].ring && virt_dev->eps[i].ring->dequeue) 288 if (virt_dev->eps[i].ring && virt_dev->eps[i].ring->dequeue) {
288 xhci_queue_stop_endpoint(xhci, slot_id, i, suspend); 289 struct xhci_command *command;
290 command = xhci_alloc_command(xhci, false, false,
291 GFP_NOIO);
292 if (!command) {
293 spin_unlock_irqrestore(&xhci->lock, flags);
294 xhci_free_command(xhci, cmd);
295 return -ENOMEM;
296
297 }
298 xhci_queue_stop_endpoint(xhci, command, slot_id, i,
299 suspend);
300 }
289 } 301 }
290 cmd->command_trb = xhci_find_next_enqueue(xhci->cmd_ring);
291 list_add_tail(&cmd->cmd_list, &virt_dev->cmd_list); 302 list_add_tail(&cmd->cmd_list, &virt_dev->cmd_list);
292 xhci_queue_stop_endpoint(xhci, slot_id, 0, suspend); 303 xhci_queue_stop_endpoint(xhci, cmd, slot_id, 0, suspend);
293 xhci_ring_cmd_db(xhci); 304 xhci_ring_cmd_db(xhci);
294 spin_unlock_irqrestore(&xhci->lock, flags); 305 spin_unlock_irqrestore(&xhci->lock, flags);
295 306