summaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci-hub.c
diff options
context:
space:
mode:
authorMathias Nyman <mathias.nyman@linux.intel.com>2014-05-08 19:26:00 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-05-20 10:03:25 +0900
commitddba5cd0aeff5bbed92ebdf4b1223300b0541e78 (patch)
treedf3c979cd4ee80815538dc2f86cb4bfb451e7c43 /drivers/usb/host/xhci-hub.c
parentbe9820383b10984d77abe1abc26e2b7029e78e21 (diff)
downloadblackbird-op-linux-ddba5cd0aeff5bbed92ebdf4b1223300b0541e78.tar.gz
blackbird-op-linux-ddba5cd0aeff5bbed92ebdf4b1223300b0541e78.zip
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 @@
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/gfp.h>
+
+#include <linux/slab.h>
#include <asm/unaligned.h>
#include "xhci.h"
@@ -284,12 +285,22 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend)
spin_lock_irqsave(&xhci->lock, flags);
for (i = LAST_EP_INDEX; i > 0; i--) {
- if (virt_dev->eps[i].ring && virt_dev->eps[i].ring->dequeue)
- xhci_queue_stop_endpoint(xhci, slot_id, i, suspend);
+ if (virt_dev->eps[i].ring && virt_dev->eps[i].ring->dequeue) {
+ struct xhci_command *command;
+ command = xhci_alloc_command(xhci, false, false,
+ GFP_NOIO);
+ if (!command) {
+ spin_unlock_irqrestore(&xhci->lock, flags);
+ xhci_free_command(xhci, cmd);
+ return -ENOMEM;
+
+ }
+ xhci_queue_stop_endpoint(xhci, command, slot_id, i,
+ suspend);
+ }
}
- cmd->command_trb = xhci_find_next_enqueue(xhci->cmd_ring);
list_add_tail(&cmd->cmd_list, &virt_dev->cmd_list);
- xhci_queue_stop_endpoint(xhci, slot_id, 0, suspend);
+ xhci_queue_stop_endpoint(xhci, cmd, slot_id, 0, suspend);
xhci_ring_cmd_db(xhci);
spin_unlock_irqrestore(&xhci->lock, flags);
OpenPOWER on IntegriCloud