From 642ac9c9ea3ccc7cc7be340bed53aebe0223b941 Mon Sep 17 00:00:00 2001
From: Peter Kosyh
Date: Wed, 10 Oct 2018 09:54:05 +0300
Subject: [PATCH] xhci: GetPortStatus, ClearPortFeature (PS_PLC, PS_WRC) fix
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Fixes #13768.
Change-Id: Ia783e62a15917a2c8f7b3169ee5204a8d8d6f5ef
Reviewed-on: https://review.haiku-os.org/622
Reviewed-by: Jérôme Duval
Reviewed-by: Alexander von Gluck IV
---
src/add-ons/kernel/bus_managers/usb/Hub.cpp | 15 +++++++++++++++
.../kernel/bus_managers/usb/usbspec_private.h | 5 ++++-
src/add-ons/kernel/busses/usb/xhci.cpp | 10 ++++++++--
3 files changed, 27 insertions(+), 3 deletions(-)
diff --git a/src/add-ons/kernel/bus_managers/usb/Hub.cpp b/src/add-ons/kernel/bus_managers/usb/Hub.cpp
index 64bc4516f0..f06712d1de 100644
--- a/src/add-ons/kernel/bus_managers/usb/Hub.cpp
+++ b/src/add-ons/kernel/bus_managers/usb/Hub.cpp
@@ -335,6 +335,21 @@ Hub::Explore(change_item **changeList)
USB_REQUEST_CLEAR_FEATURE, C_PORT_RESET, i + 1,
0, NULL, 0, NULL);
}
+
+ if (fPortStatus[i].change & PORT_CHANGE_LINK_STATE) {
+ TRACE_ALWAYS("port %" B_PRId32 " link state changed\n", i);
+ DefaultPipe()->SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT,
+ USB_REQUEST_CLEAR_FEATURE, C_PORT_LINK_STATE, i + 1,
+ 0, NULL, 0, NULL);
+ }
+
+ if (fPortStatus[i].change & PORT_CHANGE_BH_PORT_RESET) {
+ TRACE_ALWAYS("port %" B_PRId32 " was warm reset\n", i);
+ DefaultPipe()->SendRequest(USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT,
+ USB_REQUEST_CLEAR_FEATURE, C_PORT_BH_PORT_RESET, i + 1,
+ 0, NULL, 0, NULL);
+ }
+
}
// explore down the tree if we have hubs connected
diff --git a/src/add-ons/kernel/bus_managers/usb/usbspec_private.h b/src/add-ons/kernel/bus_managers/usb/usbspec_private.h
index 8123389e8a..c9ca3686b7 100644
--- a/src/add-ons/kernel/bus_managers/usb/usbspec_private.h
+++ b/src/add-ons/kernel/bus_managers/usb/usbspec_private.h
@@ -102,7 +102,7 @@ struct usb_port_status
#define PORT_STATUS_HIGH_SPEED 0x0400
#define PORT_STATUS_TEST 0x0800
#define PORT_STATUS_INDICATOR 0x1000
-// USB 3.0 spec table 10-11
+// USB 3.0 spec table 10-10
#define PORT_STATUS_SS_LINK_STATE 0x01e0
#define PORT_STATUS_SS_POWER 0x0200
#define PORT_STATUS_SS_SPEED 0x1c00
@@ -135,5 +135,8 @@ struct usb_port_status
#define C_PORT_BH_PORT_RESET 29
#define PORT_FORCE_LINKPM_STATE 30
+// USB 3.0 spec table 10-11
+#define PORT_CHANGE_BH_PORT_RESET 0x0020
+#define PORT_CHANGE_LINK_STATE 0x0040
#endif // _USBSPEC_PRIVATE_H
diff --git a/src/add-ons/kernel/busses/usb/xhci.cpp b/src/add-ons/kernel/busses/usb/xhci.cpp
index b70b51c4fb..ea81660619 100644
--- a/src/add-ons/kernel/busses/usb/xhci.cpp
+++ b/src/add-ons/kernel/busses/usb/xhci.cpp
@@ -1789,9 +1789,9 @@ XHCI::GetPortStatus(uint8 index, usb_port_status* status)
if (fPortSpeeds[index] == USB_SPEED_SUPER) {
if (portStatus & PS_PLC)
- status->change |= PORT_LINK_STATE;
+ status->change |= PORT_CHANGE_LINK_STATE;
if (portStatus & PS_WRC)
- status->change |= PORT_BH_PORT_RESET;
+ status->change |= PORT_CHANGE_BH_PORT_RESET;
}
return B_OK;
@@ -1874,6 +1874,12 @@ XHCI::ClearPortFeature(uint8 index, uint16 feature)
case C_PORT_RESET:
WriteOpReg(portRegister, portStatus | PS_PRC);
break;
+ case C_PORT_BH_PORT_RESET:
+ WriteOpReg(portRegister, portStatus | PS_WRC);
+ break;
+ case C_PORT_LINK_STATE:
+ WriteOpReg(portRegister, portStatus | PS_PLC);
+ break;
default:
return B_BAD_VALUE;
}