tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
xhci patch for nick-nhusb branch
Hello,
Here are some xhci patches for nick-nhusb branch.
nh-xhci-cos.diff
+ Add comments. Some cosmetic changes.
nh-xhci-clearhalt.diff
+ Don't abuse pipe->up_async_task for
xhci_clear_endpoint_stall_async_task.
Add member struct usb_task xp_async_task to struct xhci_pipe.
nh-xhci-slot.diff
+ Fix slot leak when address_device fails.
+ Eliminate device_xname().
nh-xhci-chkxfer.diff
+ Add some sanity checks for xfer.
nh-xhci-trberr.diff
+ Rewrite if-else-if chains with switch-case.
nh-xhci-ss.diff
+ Eliminate confusing UPS_SUPER_SPEED flag and introduce
UPS_OTHER_SPEED flag that indicates ud_speed of device is
super speed (or more).
uhub shall set this flag if ud_speed is super speed (or more).
+ Add the macro that checks ud_speed is super speed.
The codes shall use this macro to check ud_speed is super speed.
+ Add speed type conversion functions.
+ Include port link status in port_status if port is super speed.
nh-xhci-quirks.diff
+ Add patch for intel chips quirk from ryoon@ in
https://mail-index.netbsd.org/netbsd-bugs/2014/08/31/msg038109.html
slightly modified to set quirks before calling xhci_init.
+ Set special IMOD value and route ports to xhci for intel chips.
--
t-hash
--- src/sys/dev/usb/xhci.c.orig 2015-04-07 17:55:43.000000000 +0900
+++ src/sys/dev/usb/xhci.c 2015-05-25 20:33:49.000000000 +0900
@@ -26,6 +26,15 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/*
+ * USB rev 3.1 specification
+ * http://www.usb.org/developers/docs/usb_31_040315.zip
+ * USB rev 2.0 specification
+ * http://www.usb.org/developers/docs/usb20_docs/usb_20_031815.zip
+ * xHCI rev 1.1 specification
+ * http://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/extensible-host-controler-interface-usb-xhci.pdf
+ */
+
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.28.2.20 2015/04/07 06:52:03 skrll Exp $");
@@ -1374,7 +1383,7 @@ xhci_stop_endpoint(struct usbd_pipe *pip
/*
* Set TR Dequeue Pointer.
* xCHI 1.1 4.6.10 6.4.3.9
- * Purge all of transfer requests in ring.
+ * Purge all of transfer requests on ring.
* EPSTATE of endpoint must be ERROR or STOPPED, or CONTEXT_STATE error.
*/
static usbd_status
@@ -1578,7 +1587,13 @@ xhci_abort_xfer(struct usbd_xfer *xfer,
}
#if 1 /* XXX experimental */
-/* issue reset_ep and set_dequeue in thread context */
+/*
+ * Recover STALLed endpoint.
+ * xHCI 1.1 sect 4.10.2.1
+ * Issue RESET_EP to recover halt condition and SET_TR_DEQUEUE to remove
+ * all transfers on transfer ring.
+ * These are done in thread context asynchronously.
+ */
static void
xhci_clear_endpoint_stall_async_task(void *cookie)
{
@@ -1624,7 +1639,6 @@ xhci_clear_endpoint_stall_async(struct u
}
#endif /* XXX experimental */
-
/*
* Notify roothub port status/change to uhub_intr.
*/
@@ -2765,8 +2779,7 @@ xhci_roothub_ctrl(struct usbd_bus *bus,
break;
case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE):
break;
- case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER):
- {
+ case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER): {
int optval = (index >> 8) & 0xff;
index &= 0xff;
if (index < 1 || index > sc->sc_maxports) {
--- src/sys/dev/usb/xhci.c.orig 2015-05-25 20:33:49.000000000 +0900
+++ src/sys/dev/usb/xhci.c 2015-05-25 20:48:51.000000000 +0900
@@ -116,6 +116,7 @@ fail:
struct xhci_pipe {
struct usbd_pipe xp_pipe;
+ struct usb_task xp_async_task;
};
#define XHCI_COMMAND_RING_TRBS 256
@@ -1620,6 +1621,7 @@ static usbd_status
xhci_clear_endpoint_stall_async(struct usbd_xfer *xfer)
{
struct xhci_softc * const sc = xfer->ux_pipe->up_dev->ud_bus->ub_hcpriv;
+ struct xhci_pipe * const xp = (struct xhci_pipe *)xfer->ux_pipe;
XHCIHIST_FUNC(); XHCIHIST_CALLED();
DPRINTFN(4, "xfer %p", xfer, 0, 0, 0);
@@ -1628,11 +1630,9 @@ xhci_clear_endpoint_stall_async(struct u
return USBD_IOERROR;
}
- /* XXX never use up_async_task for incompatible type of function */
- usb_init_task(&xfer->ux_pipe->up_async_task,
+ usb_init_task(&xp->xp_async_task,
xhci_clear_endpoint_stall_async_task, xfer, USB_TASKQ_MPSAFE);
- usb_add_task(xfer->ux_pipe->up_dev, &xfer->ux_pipe->up_async_task,
- USB_TASKQ_HC);
+ usb_add_task(xfer->ux_pipe->up_dev, &xp->xp_async_task, USB_TASKQ_HC);
DPRINTFN(4, "ends", 0, 0, 0, 0);
return USBD_NORMAL_COMPLETION;
--- src/sys/dev/usb/xhci.c.orig 2015-05-25 20:48:51.000000000 +0900
+++ src/sys/dev/usb/xhci.c 2015-05-25 21:00:05.000000000 +0900
@@ -2064,6 +2064,14 @@ xhci_new_device(device_t parent, struct
err = xhci_init_slot(dev, slot, route, rhport);
if (err) {
dev->ud_hcpriv = NULL;
+ /*
+ * We have to disable_slot here because
+ * xs->xs_idx == 0 when xhci_init_slot fails,
+ * in that case usbd_remove_dev won't work.
+ */
+ mutex_enter(&sc->sc_lock);
+ xhci_disable_slot(sc, slot);
+ mutex_exit(&sc->sc_lock);
goto bad;
}
@@ -2087,9 +2095,9 @@ xhci_new_device(device_t parent, struct
/* 4.8.2.1 */
if (speed == USB_SPEED_SUPER) {
if (dd->bMaxPacketSize != 9) {
- printf("%s: invalid mps 2^%u for SS ep0,"
+ printf("xhci%d: invalid mps 2^%u for SS ep0,"
" using 512\n",
- device_xname(sc->sc_dev),
+ device_unit(sc->sc_dev),
dd->bMaxPacketSize);
dd->bMaxPacketSize = 9;
}
--- src/sys/dev/usb/xhci.c.orig 2015-05-25 21:00:05.000000000 +0900
+++ src/sys/dev/usb/xhci.c 2015-05-25 21:16:40.000000000 +0900
@@ -1701,7 +1701,10 @@ xhci_handle_event(struct xhci_softc * co
xs = &sc->sc_slots[slot];
xr = &xs->xs_ep[dci].xe_tr;
/* sanity check */
- KASSERT(xs->xs_idx != 0);
+ if (xs->xs_idx == 0 || xs->xs_idx >= sc->sc_maxslots) {
+ DPRINTFN(1, "invalid slot %u", xs->xs_idx, 0, 0, 0);
+ break;
+ }
if ((trb_3 & XHCI_TRB_3_ED_BIT) == 0) {
bus_addr_t trbp = xhci_ring_trbp(xr, 0);
@@ -1721,8 +1724,24 @@ xhci_handle_event(struct xhci_softc * co
} else {
xx = (void *)(uintptr_t)(trb_0 & ~0x3);
}
+ /* XXX this may not happen */
+ if (xx == NULL) {
+ DPRINTFN(1, "xfer done: xx is NULL", 0, 0, 0, 0);
+ break;
+ }
xfer = &xx->xx_xfer;
+ /* XXX this may happen when detaching */
+ if (xfer == NULL) {
+ DPRINTFN(1, "xfer done: xfer is NULL", 0, 0, 0, 0);
+ break;
+ }
DPRINTFN(14, "xfer %p", xfer, 0, 0, 0);
+ /* XXX I dunno why this happens */
+ if (!xfer->ux_pipe->up_repeat &&
+ SIMPLEQ_EMPTY(&xfer->ux_pipe->up_queue)) {
+ DPRINTFN(1, "xfer done: xfer not started", 0, 0, 0, 0);
+ break;
+ }
if ((trb_3 & XHCI_TRB_3_ED_BIT) != 0) {
DPRINTFN(14, "transfer event data: "
--- src/sys/dev/usb/xhci.c.orig 2015-05-25 21:16:40.000000000 +0900
+++ src/sys/dev/usb/xhci.c 2015-05-25 21:23:00.000000000 +0900
@@ -1753,17 +1753,19 @@ xhci_handle_event(struct xhci_softc * co
}
}
- if (trberr == XHCI_TRB_ERROR_SUCCESS ||
- trberr == XHCI_TRB_ERROR_SHORT_PKT) {
+ switch (trberr) {
+ case XHCI_TRB_ERROR_SHORT_PKT:
+ case XHCI_TRB_ERROR_SUCCESS:
xfer->ux_actlen =
xfer->ux_length - XHCI_TRB_2_REM_GET(trb_2);
err = USBD_NORMAL_COMPLETION;
- } else if (trberr == XHCI_TRB_ERROR_STALL ||
- trberr == XHCI_TRB_ERROR_BABBLE) {
- err = USBD_STALLED;
- xr->is_halted = true;
+ break;
+ case XHCI_TRB_ERROR_STALL:
+ case XHCI_TRB_ERROR_BABBLE:
DPRINTFN(1, "evh: xfer done: ERR %u slot %u dci %u",
trberr, slot, dci, 0);
+ xr->is_halted = true;
+ err = USBD_STALLED;
#if 1 /* XXX experimental */
/*
* Stalled endpoints can be recoverd by issuing
@@ -1780,12 +1782,22 @@ xhci_handle_event(struct xhci_softc * co
*/
xfer->ux_status = err;
xhci_clear_endpoint_stall_async(xfer);
+ return;
+#else
break;
#endif
- } else {
+ case XHCI_TRB_ERROR_CMD_ABORTED:
+ case XHCI_TRB_ERROR_STOPPED:
+ err = USBD_CANCELLED;
+ break;
+ case XHCI_TRB_ERROR_NO_SLOTS:
+ err = USBD_NO_ADDR;
+ break;
+ default:
DPRINTFN(1, "evh: xfer done: ERR %u slot %u dci %u",
trberr, slot, dci, 0);
err = USBD_IOERROR;
+ break;
}
xfer->ux_status = err;
--- src/sys/dev/usb/xhci.c.orig 2015-05-25 21:23:00.000000000 +0900
+++ src/sys/dev/usb/xhci.c 2015-05-25 21:33:48.000000000 +0900
@@ -1010,31 +1010,52 @@ xhci_intr1(struct xhci_softc * const sc)
* ioctl interface uses these values too.
* port_status speed
* definition: UPS_*_SPEED in usb.h
- * They are used in usb_port_status_t.
- * Some 3.0 values overlap with 2.0 values.
+ * They are used in usb_port_status_t and valid only for USB 2.0.
+ * Speed value is 0 for Super Speed or more.
+ * Note that some 3.0 values overlap with 2.0 values.
* (e.g. 0x200 means UPS_POER_POWER_SS in SS and
* means UPS_LOW_SPEED in HS.)
* port status sent from hub also uses these values.
- * (but I've never seen UPS_SUPER_SPEED in port_status from hub.)
* xspeed:
* definition: Protocol Speed ID (PSI) (xHCI 1.1 7.2.1)
* They are used in only slot context and PORTSC reg of xhci.
- * The difference between usbdi speed and them are that
- * FS and LS values are swapped.
+ * The difference between usbdi speed and xspeed is
+ * that FS and LS values are swapped.
*/
+/* convert usbdi speed to xspeed */
static int
xhci_speed2xspeed(int speed)
{
switch (speed) {
case USB_SPEED_LOW: return 2;
case USB_SPEED_FULL: return 1;
- case USB_SPEED_HIGH: return 3;
- case USB_SPEED_SUPER: return 4;
- default:
- break;
+ default: return speed;
+ }
+}
+
+/* convert xspeed to usbdi speed */
+static int
+xhci_xspeed2speed(int xspeed)
+{
+ switch (xspeed) {
+ case 1: return USB_SPEED_FULL;
+ case 2: return USB_SPEED_LOW;
+ default: return xspeed;
+ }
+}
+
+/* convert xspeed to port status speed */
+static int
+xhci_xspeed2psspeed(int xspeed)
+{
+ switch (xspeed) {
+ case 0: return 0;
+ case 1: return UPS_FULL_SPEED;
+ case 2: return UPS_LOW_SPEED;
+ case 3: return UPS_HIGH_SPEED;
+ default: return UPS_OTHER_SPEED;
}
- return 0;
}
/* construct slot context */
@@ -1185,7 +1206,7 @@ xhci_configure_endpoint(struct usbd_pipe
if (xfertype != UE_ISOCHRONOUS)
cp[1] |= htole32(XHCI_EPCTX_1_CERR_SET(3));
- if (speed == USB_SPEED_SUPER) {
+ if (USB_IS_SS(speed)) {
usbd_desc_iter_t iter;
const usb_cdc_descriptor_t *cdcd;
const usb_endpoint_ss_comp_descriptor_t * esscd = NULL;
@@ -1239,7 +1260,7 @@ xhci_configure_endpoint(struct usbd_pipe
} else {
ival = ival > 15 ? 15 : ival;
}
- if (speed == USB_SPEED_SUPER) {
+ if (USB_IS_SS(speed)) {
if (maxb > 0)
mps = 1024;
} else {
@@ -1252,7 +1273,7 @@ xhci_configure_endpoint(struct usbd_pipe
);
break;
case UE_CONTROL:
- if (speed == USB_SPEED_SUPER)
+ if (USB_IS_SS(speed))
mps = 512;
else
mps = mps ? mps : 8;
@@ -1267,7 +1288,7 @@ xhci_configure_endpoint(struct usbd_pipe
} else {
ival = ival > 15 ? 15 : ival;
}
- if (speed == USB_SPEED_SUPER) {
+ if (USB_IS_SS(speed)) {
mps = 1024;
} else {
mps = mps ? mps : 1024;
@@ -1277,7 +1298,7 @@ xhci_configure_endpoint(struct usbd_pipe
break;
#endif
default:
- if (speed == USB_SPEED_SUPER)
+ if (USB_IS_SS(speed))
mps = 1024;
else
mps = mps ? mps : 512;
@@ -1990,10 +2011,10 @@ xhci_new_device(device_t parent, struct
dev->ud_ep0desc.bEndpointAddress = USB_CONTROL_ENDPOINT;
dev->ud_ep0desc.bmAttributes = UE_CONTROL;
/* 4.3, 4.8.2.1 */
- switch (speed) {
- case USB_SPEED_SUPER:
+ if (USB_IS_SS(speed)) {
USETW(dev->ud_ep0desc.wMaxPacketSize, USB_3_MAX_CTRL_PACKET);
- break;
+ } else
+ switch (speed) {
case USB_SPEED_FULL:
/* XXX using 64 as initial mps of ep0 in FS */
case USB_SPEED_HIGH:
@@ -2124,7 +2145,7 @@ xhci_new_device(device_t parent, struct
if (err)
goto bad;
/* 4.8.2.1 */
- if (speed == USB_SPEED_SUPER) {
+ if (USB_IS_SS(speed)) {
if (dd->bMaxPacketSize != 9) {
printf("xhci%d: invalid mps 2^%u for SS ep0,"
" using 512\n",
@@ -2771,34 +2792,20 @@ xhci_roothub_ctrl(struct usbd_bus *bus,
}
v = xhci_op_read_4(sc, XHCI_PORTSC(index));
DPRINTFN(4, "getrhportsc %d %08x", index, v, 0, 0);
- switch (XHCI_PS_SPEED_GET(v)) {
- case 1:
- i = UPS_FULL_SPEED;
- break;
- case 2:
- i = UPS_LOW_SPEED;
- break;
- case 3:
- i = UPS_HIGH_SPEED;
- break;
- case 4:
- i = UPS_SUPER_SPEED;
- break;
- default:
- i = 0;
- break;
- }
+ i = xhci_xspeed2psspeed(XHCI_PS_SPEED_GET(v));
if (v & XHCI_PS_CCS) i |= UPS_CURRENT_CONNECT_STATUS;
if (v & XHCI_PS_PED) i |= UPS_PORT_ENABLED;
if (v & XHCI_PS_OCA) i |= UPS_OVERCURRENT_INDICATOR;
//if (v & XHCI_PS_SUSP) i |= UPS_SUSPEND;
if (v & XHCI_PS_PR) i |= UPS_RESET;
if (v & XHCI_PS_PP) {
- if (i & UPS_SUPER_SPEED)
+ if (i & UPS_OTHER_SPEED)
i |= UPS_PORT_POWER_SS;
else
i |= UPS_PORT_POWER;
}
+ if (i & UPS_OTHER_SPEED)
+ i |= UPS_PORT_LS_SET(XHCI_PS_PLS_GET(v));
USETW(ps.wPortStatus, i);
i = 0;
if (v & XHCI_PS_CSC) i |= UPS_C_CONNECT_STATUS;
@@ -2858,7 +2865,7 @@ xhci_roothub_ctrl(struct usbd_bus *bus,
xhci_op_write_4(sc, port, v | XHCI_PS_PRC);
break;
case UHF_PORT_U1_TIMEOUT:
- if (XHCI_PS_SPEED_GET(v) != 4) {
+ if (USB_IS_SS(xhci_xspeed2speed(XHCI_PS_SPEED_GET(v)))){
return -1;
}
port = XHCI_PORTPMSC(index);
@@ -2868,7 +2875,7 @@ xhci_roothub_ctrl(struct usbd_bus *bus,
xhci_op_write_4(sc, port, v);
break;
case UHF_PORT_U2_TIMEOUT:
- if (XHCI_PS_SPEED_GET(v) != 4) {
+ if (USB_IS_SS(xhci_xspeed2speed(XHCI_PS_SPEED_GET(v)))){
return -1;
}
port = XHCI_PORTPMSC(index);
--- src/sys/dev/usb/usb.h.orig 2015-04-07 01:29:01.000000000 +0900
+++ src/sys/dev/usb/usb.h 2015-05-14 08:05:42.000000000 +0900
@@ -561,7 +561,9 @@
#define UPS_OVERCURRENT_INDICATOR 0x0008
#define UPS_RESET 0x0010
#define UPS_PORT_L1 0x0020
-#define UPS_PORT_LS_GET(x) __SHIFTOUT(x, __BITS(8,5))
+#define UPS_PORT_LS_MASK __BITS(8,5)
+#define UPS_PORT_LS_GET(x) __SHIFTOUT(x, UPS_PORT_LS_MASK)
+#define UPS_PORT_LS_SET(x) __SHIFTIN(x, UPS_PORT_LS_MASK)
#define UPS_PORT_LS_U0 0x00
#define UPS_PORT_LS_U1 0x01
#define UPS_PORT_LS_U2 0x02
@@ -580,9 +582,9 @@
#define UPS_FULL_SPEED 0x0000 /* for completeness */
#define UPS_LOW_SPEED 0x0200
#define UPS_HIGH_SPEED 0x0400
-#define UPS_SUPER_SPEED 0x0800
#define UPS_PORT_TEST 0x0800
#define UPS_PORT_INDICATOR 0x1000
+#define UPS_OTHER_SPEED 0x2000 /* currently NetBSD specific */
uWord wPortChange;
#define UPS_C_CONNECT_STATUS 0x0001
#define UPS_C_PORT_ENABLED 0x0002
@@ -852,6 +854,7 @@
#define USB_SPEED_FULL 2
#define USB_SPEED_HIGH 3
#define USB_SPEED_SUPER 4
+#define USB_IS_SS(X) ((X) == USB_SPEED_SUPER)
int udi_power; /* power consumption in mA, 0 if selfpowered */
int udi_nports;
char udi_devnames[USB_MAX_DEVNAMES][USB_MAX_DEVNAMELEN];
--- src/sys/dev/pci/xhci_pci.c.orig 2015-04-07 01:28:57.000000000 +0900
+++ src/sys/dev/pci/xhci_pci.c 2015-05-24 00:23:37.000000000 +0900
@@ -1,4 +1,5 @@
/* $NetBSD: xhci_pci.c,v 1.4.2.2 2015/04/06 12:17:30 skrll Exp $ */
+/* OpenBSD: xhci_pci.c,v 1.4 2014/07/12 17:38:51 yuo Exp */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -43,6 +44,7 @@ __KERNEL_RCSID(0, "$NetBSD: xhci_pci.c,v
#include <sys/bus.h>
#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
@@ -52,6 +54,17 @@ __KERNEL_RCSID(0, "$NetBSD: xhci_pci.c,v
#include <dev/usb/xhcireg.h>
#include <dev/usb/xhcivar.h>
+struct xhci_pci_quirk {
+ pci_vendor_id_t vendor;
+ pci_product_id_t product;
+ int quirks;
+};
+
+static const struct xhci_pci_quirk xhci_pci_quirks[] = {
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_CORE4G_M_XHCI,
+ XHCI_QUIRK_FORCE_INTR },
+};
+
struct xhci_pci_softc {
struct xhci_softc sc_xhci;
pci_chipset_tag_t sc_pc;
@@ -59,6 +72,18 @@ struct xhci_pci_softc {
};
static int
+xhci_pci_has_quirk(pci_vendor_id_t vendor, pci_product_id_t product)
+{
+ int i;
+
+ for (i = 0; i < __arraycount(xhci_pci_quirks); i++)
+ if (vendor == xhci_pci_quirks[i].vendor &&
+ product == xhci_pci_quirks[i].product)
+ return xhci_pci_quirks[i].quirks;
+ return 0;
+}
+
+static int
xhci_pci_match(device_t parent, cfdata_t match, void *aux)
{
struct pci_attach_args *pa = (struct pci_attach_args *) aux;
@@ -71,6 +96,42 @@ xhci_pci_match(device_t parent, cfdata_t
return 0;
}
+static int
+xhci_pci_port_route(struct xhci_pci_softc *psc)
+{
+ struct xhci_softc * const sc = &psc->sc_xhci;
+
+ pcireg_t val;
+
+ /*
+ * Check USB3 Port Routing Mask register that indicates the ports
+ * can be changed from OS, and turn on by USB3 Port SS Enable register.
+ */
+ val = pci_conf_read(psc->sc_pc, psc->sc_tag, PCI_XHCI_INTEL_USB3PRM);
+ aprint_debug_dev(sc->sc_dev,
+ "USB3PRM / USB3.0 configurable ports: 0x%08x\n", val);
+
+ pci_conf_write(psc->sc_pc, psc->sc_tag, PCI_XHCI_INTEL_USB3_PSSEN, val);
+ val = pci_conf_read(psc->sc_pc, psc->sc_tag,PCI_XHCI_INTEL_USB3_PSSEN);
+ aprint_debug_dev(sc->sc_dev,
+ "USB3_PSSEN / Enabled USB3.0 ports under xHCI: 0x%08x\n", val);
+
+ /*
+ * Check USB2 Port Routing Mask register that indicates the USB2.0
+ * ports to be controlled by xHCI HC, and switch them to xHCI HC.
+ */
+ val = pci_conf_read(psc->sc_pc, psc->sc_tag, PCI_XHCI_INTEL_USB2PRM);
+ aprint_debug_dev(sc->sc_dev,
+ "XUSB2PRM / USB2.0 ports can switch from EHCI to xHCI:"
+ "0x%08x\n", val);
+ pci_conf_write(psc->sc_pc, psc->sc_tag, PCI_XHCI_INTEL_XUSB2PR, val);
+ val = pci_conf_read(psc->sc_pc, psc->sc_tag, PCI_XHCI_INTEL_XUSB2PR);
+ aprint_debug_dev(sc->sc_dev,
+ "XUSB2PR / USB2.0 ports under xHCI: 0x%08x\n", val);
+
+ return 0;
+}
+
static void
xhci_pci_attach(device_t parent, device_t self, void *aux)
{
@@ -92,6 +153,10 @@ xhci_pci_attach(device_t parent, device_
pci_aprint_devinfo(pa, "USB Controller");
+ /* Check for quirks */
+ sc->sc_quirks = xhci_pci_has_quirk(PCI_VENDOR(pa->pa_id),
+ PCI_PRODUCT(pa->pa_id));
+
/* check if memory space access is enabled */
csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
#ifdef DEBUG
@@ -122,9 +187,9 @@ xhci_pci_attach(device_t parent, device_
psc->sc_pc = pc;
psc->sc_tag = tag;
- hccparams = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 0x10);
+ hccparams = bus_space_read_4(sc->sc_iot, sc->sc_ioh, XHCI_HCCPARAMS);
- if (pci_dma64_available(pa) && ((hccparams&1)==1))
+ if (pci_dma64_available(pa) && (XHCI_HCC_AC64(hccparams) != 0))
sc->sc_bus.ub_dmatag = pa->pa_dmat64;
else
sc->sc_bus.ub_dmatag = pa->pa_dmat;
@@ -160,12 +225,24 @@ xhci_pci_attach(device_t parent, device_
sc->sc_id_vendor);
#endif
+ /* Intel chipset requires SuperSpeed enable and USB2 port routing */
+ switch (PCI_VENDOR(pa->pa_id)) {
+ case PCI_VENDOR_INTEL:
+ sc->sc_quirks |= XHCI_QUIRK_INTEL;
+ break;
+ default:
+ break;
+ }
+
err = xhci_init(sc);
if (err) {
aprint_error_dev(self, "init failed, error=%d\n", err);
goto fail;
}
+ if ((sc->sc_quirks & XHCI_QUIRK_INTEL) != 0)
+ xhci_pci_port_route(psc);
+
if (!pmf_device_register1(self, xhci_suspend, xhci_resume,
xhci_shutdown))
aprint_error_dev(self, "couldn't establish power handler\n");
--- src/sys/dev/usb/xhci.c.orig 2015-05-25 21:33:48.000000000 +0900
+++ src/sys/dev/usb/xhci.c 2015-05-25 21:37:09.000000000 +0900
@@ -910,13 +910,13 @@ xhci_init(struct xhci_softc *sc)
#endif
xhci_rt_write_4(sc, XHCI_IMAN(0), XHCI_IMAN_INTR_ENA);
-#ifdef XHCI_QUIRK_INTEL
if ((sc->sc_quirks & XHCI_QUIRK_INTEL) != 0)
/* Intel xhci needs interrupt rate moderated. */
xhci_rt_write_4(sc, XHCI_IMOD(0), XHCI_IMOD_DEFAULT_LP);
else
-#endif /* XHCI_QUIRK_INTEL */
xhci_rt_write_4(sc, XHCI_IMOD(0), 0);
+ aprint_debug_dev(sc->sc_dev, "setting IMOD %u\n",
+ xhci_rt_read_4(sc, XHCI_IMOD(0)));
xhci_op_write_4(sc, XHCI_USBCMD, XHCI_CMD_INTE|XHCI_CMD_RS); /* Go! */
aprint_debug_dev(sc->sc_dev, "USBCMD %08"PRIx32"\n",
@@ -977,7 +977,6 @@ xhci_intr1(struct xhci_softc * const sc)
iman = xhci_rt_read_4(sc, XHCI_IMAN(0));
DPRINTFN(16, "IMAN0 %08x", iman, 0, 0, 0);
-#ifdef XHCI_QUIRK_FORCE_INTR
if (!(sc->sc_quirks & XHCI_QUIRK_FORCE_INTR)) {
if ((iman & XHCI_IMAN_INTR_PEND) == 0) {
@@ -985,11 +984,6 @@ xhci_intr1(struct xhci_softc * const sc)
}
}
-#else
- if ((iman & XHCI_IMAN_INTR_PEND) == 0) {
- return 0;
- }
-#endif /* XHCI_QUIRK_FORCE_INTR */
xhci_rt_write_4(sc, XHCI_IMAN(0), iman);
iman = xhci_rt_read_4(sc, XHCI_IMAN(0));
DPRINTFN(16, "IMAN0 %08x", iman, 0, 0, 0);
Home |
Main Index |
Thread Index |
Old Index