summaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorGreg Kroah-Hartman2011-05-10 23:11:19 +0200
committerGreg Kroah-Hartman2011-05-10 23:11:32 +0200
commit8eadef1526886db2a471c432d2c3d154de46f5c6 (patch)
treec11c8c634f172fd234bba68865baf5c48a365551 /drivers/usb
parentMerge branch 2.6.39-rc7 into usb-linus (diff)
parentxHCI 1.0: Max Exit Latency Too Large Error (diff)
downloadkernel-qcow2-linux-8eadef1526886db2a471c432d2c3d154de46f5c6.tar.gz
kernel-qcow2-linux-8eadef1526886db2a471c432d2c3d154de46f5c6.tar.xz
kernel-qcow2-linux-8eadef1526886db2a471c432d2c3d154de46f5c6.zip
Merge branch 'for-usb-next' of git+ssh://master.kernel.org/pub/scm/linux/kernel/git/sarah/xhci into usb-next
* 'for-usb-next' of git+ssh://master.kernel.org/pub/scm/linux/kernel/git/sarah/xhci: xHCI 1.0: Max Exit Latency Too Large Error xHCI 1.0: TT_THINK_TIME set xHCI 1.0: Block Interrupts for Isoch transfer xHCI 1.0: Isoch endpoint CErr field set xHCI 1.0: Control endpoint average TRB length field set xHCI 1.0: Setup Stage TRB Transfer Type flag
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/xhci-mem.c13
-rw-r--r--drivers/usb/host/xhci-ring.c16
-rw-r--r--drivers/usb/host/xhci.c12
-rw-r--r--drivers/usb/host/xhci.h9
4 files changed, 45 insertions, 5 deletions
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index a4fc4d929385..04145740686c 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1190,12 +1190,12 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
/* FIXME dig Mult and streams info out of ep companion desc */
/* Allow 3 retries for everything but isoc;
- * error count = 0 means infinite retries.
+ * CErr shall be set to 0 for Isoch endpoints.
*/
if (!usb_endpoint_xfer_isoc(&ep->desc))
ep_ctx->ep_info2 = cpu_to_le32(ERROR_COUNT(3));
else
- ep_ctx->ep_info2 = cpu_to_le32(ERROR_COUNT(1));
+ ep_ctx->ep_info2 = cpu_to_le32(ERROR_COUNT(0));
ep_ctx->ep_info2 |= cpu_to_le32(xhci_get_endpoint_type(udev, ep));
@@ -1246,8 +1246,15 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
* including link TRBs, No-op TRBs, and Event data TRBs. Since we don't
* use Event Data TRBs, and we don't chain in a link TRB on short
* transfers, we're basically dividing by 1.
+ *
+ * xHCI 1.0 specification indicates that the Average TRB Length should
+ * be set to 8 for control endpoints.
*/
- ep_ctx->tx_info |= cpu_to_le32(AVG_TRB_LENGTH_FOR_EP(max_esit_payload));
+ if (usb_endpoint_xfer_control(&ep->desc) && xhci->hci_version == 0x100)
+ ep_ctx->tx_info |= cpu_to_le32(AVG_TRB_LENGTH_FOR_EP(8));
+ else
+ ep_ctx->tx_info |=
+ cpu_to_le32(AVG_TRB_LENGTH_FOR_EP(max_esit_payload));
/* FIXME Debug endpoint context */
return 0;
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 396f8d2a2e8d..c35058b94de6 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -3053,6 +3053,17 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
field |= TRB_IDT | TRB_TYPE(TRB_SETUP);
if (start_cycle == 0)
field |= 0x1;
+
+ /* xHCI 1.0 6.4.1.2.1: Transfer Type field */
+ if (xhci->hci_version == 0x100) {
+ if (urb->transfer_buffer_length > 0) {
+ if (setup->bRequestType & USB_DIR_IN)
+ field |= TRB_TX_TYPE(TRB_DATA_IN);
+ else
+ field |= TRB_TX_TYPE(TRB_DATA_OUT);
+ }
+ }
+
queue_trb(xhci, ep_ring, false, true,
setup->bRequestType | setup->bRequest << 8 | le16_to_cpu(setup->wValue) << 16,
le16_to_cpu(setup->wIndex) | le16_to_cpu(setup->wLength) << 16,
@@ -3282,6 +3293,11 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
} else {
td->last_trb = ep_ring->enqueue;
field |= TRB_IOC;
+ if (xhci->hci_version == 0x100) {
+ /* Set BEI bit except for the last td */
+ if (i < num_tds - 1)
+ field |= TRB_BEI;
+ }
more_trbs_coming = false;
}
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 6864759c8d1a..013e113b818a 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -1560,6 +1560,11 @@ static int xhci_evaluate_context_result(struct xhci_hcd *xhci,
xhci_dbg_ctx(xhci, virt_dev->out_ctx, 1);
ret = -EINVAL;
break;
+ case COMP_MEL_ERR:
+ /* Max Exit Latency too large error */
+ dev_warn(&udev->dev, "WARN: Max Exit Latency too large\n");
+ ret = -EINVAL;
+ break;
case COMP_SUCCESS:
dev_dbg(&udev->dev, "Successful evaluate context command\n");
ret = 0;
@@ -2699,11 +2704,16 @@ int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
/* Set TT think time - convert from ns to FS bit times.
* 0 = 8 FS bit times, 1 = 16 FS bit times,
* 2 = 24 FS bit times, 3 = 32 FS bit times.
+ *
+ * xHCI 1.0: this field shall be 0 if the device is not a
+ * High-spped hub.
*/
think_time = tt->think_time;
if (think_time != 0)
think_time = (think_time / 666) - 1;
- slot_ctx->tt_info |= cpu_to_le32(TT_THINK_TIME(think_time));
+ if (xhci->hci_version < 0x100 || hdev->speed == USB_SPEED_HIGH)
+ slot_ctx->tt_info |=
+ cpu_to_le32(TT_THINK_TIME(think_time));
} else {
xhci_dbg(xhci, "xHCI version %x doesn't need hub "
"TT think time or number of ports\n",
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index db661543a805..e12db7cfb9bb 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -881,7 +881,9 @@ struct xhci_transfer_event {
#define COMP_STOP_INVAL 27
/* Control Abort Error - Debug Capability - control pipe aborted */
#define COMP_DBG_ABORT 28
-/* TRB type 29 and 30 reserved */
+/* Max Exit Latency Too Large Error */
+#define COMP_MEL_ERR 29
+/* TRB type 30 reserved */
/* Isoc Buffer Overrun - an isoc IN ep sent more data than could fit in TD */
#define COMP_BUFF_OVER 31
/* Event Lost Error - xHC has an "internal event overrun condition" */
@@ -964,9 +966,14 @@ struct xhci_event_cmd {
/* The buffer pointer contains immediate data */
#define TRB_IDT (1<<6)
+/* Block Event Interrupt */
+#define TRB_BEI (1<<9)
/* Control transfer TRB specific fields */
#define TRB_DIR_IN (1<<16)
+#define TRB_TX_TYPE(p) ((p) << 16)
+#define TRB_DATA_OUT 2
+#define TRB_DATA_IN 3
/* Isochronous TRB specific fields */
#define TRB_SIA (1<<31)