hrev47483 adds 1 changeset to branch 'master' old head: 74e1a530f88029d2933619301c56f23bf31e96a1 new head: 192f01c669102651bdc81273811079e90e0a29e5 overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=192f01c+%5E74e1a53 ---------------------------------------------------------------------------- 192f01c: XHCI USB: Some more fixes. * Fix device speed identification. * Fix Max Packet Size for Full-Speed devices. * Fix IRQ rate. * Update slot context for LS/FS devices connected to non-root HS hub. * Fix typo. Signed-off-by: Jérôme Duval <jerome.duval@xxxxxxxxx> [ Akshay Jaggi <akshay1994.leo@xxxxxxxxx> ] ---------------------------------------------------------------------------- Revision: hrev47483 Commit: 192f01c669102651bdc81273811079e90e0a29e5 URL: http://cgit.haiku-os.org/haiku/commit/?id=192f01c Author: Akshay Jaggi <akshay1994.leo@xxxxxxxxx> Date: Fri Jul 11 22:07:14 2014 UTC Committer: Jérôme Duval <jerome.duval@xxxxxxxxx> Commit-Date: Fri Jul 11 22:11:39 2014 UTC ---------------------------------------------------------------------------- 3 files changed, 62 insertions(+), 23 deletions(-) src/add-ons/kernel/bus_managers/usb/Hub.cpp | 5 +- src/add-ons/kernel/busses/usb/xhci.cpp | 78 +++++++++++++++++------ src/add-ons/kernel/busses/usb/xhci_hardware.h | 2 +- ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/bus_managers/usb/Hub.cpp b/src/add-ons/kernel/bus_managers/usb/Hub.cpp index 3190018..229786d 100644 --- a/src/add-ons/kernel/bus_managers/usb/Hub.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Hub.cpp @@ -258,6 +258,9 @@ Hub::Explore(change_item **changeList) } usb_speed speed = USB_SPEED_FULLSPEED; + // Hack - We currently do not support USB3.0 Hubs + // This is for XHCI, which anyway rechecks the port speed + // This will in no way work for non-root USB3.0 Hubs if (fDeviceDescriptor.usb_version == 0x300) speed = USB_SPEED_SUPER; else if (fPortStatus[i].status & PORT_STATUS_LOW_SPEED) @@ -327,7 +330,7 @@ Hub::Explore(change_item **changeList) } if (fPortStatus[i].change & PORT_STATUS_RESET) { - TRACE_ALWAYS("port %" B_PRId32 "was reset\n", i); + TRACE_ALWAYS("port %" B_PRId32 " was reset\n", i); DefaultPipe()->SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT, USB_REQUEST_CLEAR_FEATURE, C_PORT_RESET, i + 1, 0, NULL, 0, NULL); diff --git a/src/add-ons/kernel/busses/usb/xhci.cpp b/src/add-ons/kernel/busses/usb/xhci.cpp index 50b11ef..dbfd2b4 100644 --- a/src/add-ons/kernel/busses/usb/xhci.cpp +++ b/src/add-ons/kernel/busses/usb/xhci.cpp @@ -501,7 +501,16 @@ XHCI::Start() fCmdRing[XHCI_MAX_COMMANDS - 1].qwtrb0 = dmaAddress; TRACE("setting interrupt rate\n"); - WriteRunReg32(XHCI_IMOD(0), 160); // 25000 irq/s + + // Setting IMOD below 0x3F8 on Intel Lynx Point can cause IRQ lockups + if (fPCIInfo->vendor_id == PCI_VENDOR_INTEL + && (fPCIInfo->device_id == PCI_DEVICE_INTEL_PANTHER_POINT_XHCI + || fPCIInfo->device_id == PCI_DEVICE_INTEL_LYNX_POINT_XHCI + || fPCIInfo->device_id == PCI_DEVICE_INTEL_LYNX_POINT_LP_XHCI)) { + WriteRunReg32(XHCI_IMOD(0), 0x000003f8); // 4000 irq/s + } else { + WriteRunReg32(XHCI_IMOD(0), 0x000001f4); // 8000 irq/s + } TRACE("enabling interrupt\n"); WriteRunReg32(XHCI_IMAN(0), ReadRunReg32(XHCI_IMAN(0)) | IMAN_INTR_ENA); @@ -1017,8 +1026,6 @@ XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort, { TRACE("AllocateDevice hubAddress %d hubPort %d speed %d\n", hubAddress, hubPort, speed); - GetPortSpeed(hubPort - 1, &speed); - TRACE("speed %d\n", speed); uint8 slot = XHCI_MAX_SLOTS; if (EnableSlot(&slot) != B_OK) { @@ -1072,6 +1079,13 @@ XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort, routePort = hubDevice->HubPort(); } + // Get speed of port, only if device connected to root hub port + // else we have to rely on value reported by the Hub Explore thread + if (route == 0) { + GetPortSpeed(hubPort - 1, &speed); + TRACE("speed updated %d\n", speed); + } + device->input_ctx->slot.dwslot0 = SLOT_0_NUM_ENTRIES(1) | SLOT_0_ROUTE(route); // add the speed @@ -1095,8 +1109,16 @@ XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort, device->input_ctx->slot.dwslot1 = SLOT_1_RH_PORT(rhPort); // TODO enable power save device->input_ctx->slot.dwslot2 = SLOT_2_IRQ_TARGET(0); - if (0) + + // If LS/FS device connected to non-root HS device + if (route != 0 && parent->Speed() == USB_SPEED_HIGHSPEED + && (speed == USB_SPEED_LOWSPEED || speed == USB_SPEED_FULLSPEED)) { + struct xhci_device *parenthub = (struct xhci_device *) + parent->ControllerCookie(); device->input_ctx->slot.dwslot2 |= SLOT_2_PORT_NUM(hubPort); + device->input_ctx->slot.dwslot2 |= SLOT_2_TT_HUB_SLOT(parenthub->slot); + } + device->input_ctx->slot.dwslot3 = SLOT_3_SLOT_STATE(0) | SLOT_3_DEVICE_ADDRESS(0); @@ -1226,6 +1248,17 @@ XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort, TRACE("device_class: %d device_subclass %d device_protocol %d\n", deviceDescriptor.device_class, deviceDescriptor.device_subclass, deviceDescriptor.device_protocol); + + if (speed == USB_SPEED_FULLSPEED && deviceDescriptor.max_packet_size_0 != 8) { + TRACE("Full speed device with different max packet size for Endpoint 0\n"); + device->input_ctx->endpoints[0].dwendpoint1 &= + ~ENDPOINT_1_MAXPACKETSIZE(0xffff); + device->input_ctx->endpoints[0].dwendpoint1 |= + ENDPOINT_1_MAXPACKETSIZE(deviceDescriptor.max_packet_size_0); + device->input_ctx->input.dropFlags = 0; + device->input_ctx->input.addFlags = (1 << 1); + EvaluateContext(device->input_ctx_addr, device->slot); + } Device *deviceObject = NULL; if (deviceDescriptor.device_class == 0x09) { @@ -1547,25 +1580,28 @@ XHCI::ConfigureEndpoint(uint8 slot, uint8 number, uint8 type, uint64 ringAddr, u status_t XHCI::GetPortSpeed(uint8 index, usb_speed *speed) { - if (fPortSpeeds[index] == USB_SPEED_SUPER) - *speed = USB_SPEED_SUPER; - else { - uint32 portStatus = ReadOpReg(XHCI_PORTSC(index)); + uint32 portStatus = ReadOpReg(XHCI_PORTSC(index)); - switch (PS_SPEED_GET(portStatus)) { - case 3: - *speed = USB_SPEED_HIGHSPEED; - break; - case 2: - *speed = USB_SPEED_LOWSPEED; - break; - case 1: - *speed = USB_SPEED_FULLSPEED; - break; - default: - *speed = USB_SPEED_SUPER; - } + switch (PS_SPEED_GET(portStatus)) { + case 3: + *speed = USB_SPEED_HIGHSPEED; + break; + case 2: + *speed = USB_SPEED_LOWSPEED; + break; + case 1: + *speed = USB_SPEED_FULLSPEED; + break; + case 4: + *speed = USB_SPEED_SUPER; + break; + default: + TRACE("Non Standard Port Speed\n"); + TRACE("Assuming Superspeed\n"); + *speed = USB_SPEED_SUPER; + break; } + return B_OK; } diff --git a/src/add-ons/kernel/busses/usb/xhci_hardware.h b/src/add-ons/kernel/busses/usb/xhci_hardware.h index 05904d8..669c569 100644 --- a/src/add-ons/kernel/busses/usb/xhci_hardware.h +++ b/src/add-ons/kernel/busses/usb/xhci_hardware.h @@ -344,7 +344,7 @@ struct xhci_slot_ctx { #define SLOT_1_NUM_PORTS_GET(x) (((x) >> 24) & 0xFF) #define SLOT_2_TT_HUB_SLOT(x) ((x) & 0xFF) -#define SLOT_2_TT_HUB_SLOT(x) ((x) & 0xFF) +#define SLOT_2_TT_HUB_SLOT_GET(x) ((x) & 0xFF) #define SLOT_2_PORT_NUM(x) (((x) & 0xFF) << 8) #define SLOT_2_PORT_NUM_GET(x) (((x) >> 8) & 0xFF) #define SLOT_2_TT_TIME(x) (((x) & 0x3) << 16)