Kaynağa Gözat

[xhci] Undo PCH-specific quirk fixes when removing device

Restore the original values of XUSB2PR and USB3PSSEN, in case we are
booting an OS with no support for xHCI.

Suggested-by: Dan Ellis <Dan.Ellis@displaylink.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 9 yıl önce
ebeveyn
işleme
e905cdcce3
2 değiştirilmiş dosya ile 51 ekleme ve 17 silme
  1. 25
    2
      src/drivers/usb/xhci.c
  2. 26
    15
      src/drivers/usb/xhci.h

+ 25
- 2
src/drivers/usb/xhci.c Dosyayı Görüntüle

@@ -3019,7 +3019,8 @@ static struct usb_host_operations xhci_operations = {
3019 3019
  * @v xhci		xHCI device
3020 3020
  * @v pci		PCI device
3021 3021
  */
3022
-static void xhci_pch ( struct xhci_device *xhci, struct pci_device *pci ) {
3022
+static void xhci_pch_fix ( struct xhci_device *xhci, struct pci_device *pci ) {
3023
+	struct xhci_pch *pch = &xhci->pch;
3023 3024
 	uint32_t xusb2pr;
3024 3025
 	uint32_t xusb2prm;
3025 3026
 	uint32_t usb3pssen;
@@ -3034,6 +3035,7 @@ static void xhci_pch ( struct xhci_device *xhci, struct pci_device *pci ) {
3034 3035
 		DBGC ( xhci, "XHCI %p enabling SuperSpeed on ports %08x\n",
3035 3036
 		       xhci, ( usb3prm & ~usb3pssen ) );
3036 3037
 	}
3038
+	pch->usb3pssen = usb3pssen;
3037 3039
 	usb3pssen |= usb3prm;
3038 3040
 	pci_write_config_dword ( pci, XHCI_PCH_USB3PSSEN, usb3pssen );
3039 3041
 
@@ -3044,10 +3046,27 @@ static void xhci_pch ( struct xhci_device *xhci, struct pci_device *pci ) {
3044 3046
 		DBGC ( xhci, "XHCI %p routing ports %08x from EHCI to xHCI\n",
3045 3047
 		       xhci, ( xusb2prm & ~xusb2pr ) );
3046 3048
 	}
3049
+	pch->xusb2pr = xusb2pr;
3047 3050
 	xusb2pr |= xusb2prm;
3048 3051
 	pci_write_config_dword ( pci, XHCI_PCH_XUSB2PR, xusb2pr );
3049 3052
 }
3050 3053
 
3054
+/**
3055
+ * Undo Intel PCH-specific quirk fixes
3056
+ *
3057
+ * @v xhci		xHCI device
3058
+ * @v pci		PCI device
3059
+ */
3060
+static void xhci_pch_undo ( struct xhci_device *xhci, struct pci_device *pci ) {
3061
+	struct xhci_pch *pch = &xhci->pch;
3062
+
3063
+	/* Restore USB2 port routing to original state */
3064
+	pci_write_config_dword ( pci, XHCI_PCH_XUSB2PR, pch->xusb2pr );
3065
+
3066
+	/* Restore SuperSpeed capability to original state */
3067
+	pci_write_config_dword ( pci, XHCI_PCH_USB3PSSEN, pch->usb3pssen );
3068
+}
3069
+
3051 3070
 /**
3052 3071
  * Probe PCI device
3053 3072
  *
@@ -3091,7 +3110,7 @@ static int xhci_probe ( struct pci_device *pci ) {
3091 3110
 
3092 3111
 	/* Fix Intel PCH-specific quirks, if applicable */
3093 3112
 	if ( pci->id->driver_data & XHCI_PCH )
3094
-		xhci_pch ( xhci, pci );
3113
+		xhci_pch_fix ( xhci, pci );
3095 3114
 
3096 3115
 	/* Reset device */
3097 3116
 	if ( ( rc = xhci_reset ( xhci ) ) != 0 )
@@ -3126,6 +3145,8 @@ static int xhci_probe ( struct pci_device *pci ) {
3126 3145
  err_alloc_bus:
3127 3146
 	xhci_reset ( xhci );
3128 3147
  err_reset:
3148
+	if ( pci->id->driver_data & XHCI_PCH )
3149
+		xhci_pch_undo ( xhci, pci );
3129 3150
 	xhci_legacy_release ( xhci );
3130 3151
  err_legacy_claim:
3131 3152
 	iounmap ( xhci->regs );
@@ -3147,6 +3168,8 @@ static void xhci_remove ( struct pci_device *pci ) {
3147 3168
 	unregister_usb_bus ( bus );
3148 3169
 	free_usb_bus ( bus );
3149 3170
 	xhci_reset ( xhci );
3171
+	if ( pci->id->driver_data & XHCI_PCH )
3172
+		xhci_pch_undo ( xhci, pci );
3150 3173
 	xhci_legacy_release ( xhci );
3151 3174
 	iounmap ( xhci->regs );
3152 3175
 	free ( xhci );

+ 26
- 15
src/drivers/usb/xhci.h Dosyayı Görüntüle

@@ -1004,6 +1004,29 @@ xhci_ring_consumed ( struct xhci_trb_ring *ring ) {
1004 1004
  */
1005 1005
 #define XHCI_PORT_RESET_MAX_WAIT_MS 500
1006 1006
 
1007
+/** Intel PCH quirk */
1008
+struct xhci_pch {
1009
+	/** USB2 port routing register original value */
1010
+	uint32_t xusb2pr;
1011
+	/** USB3 port SuperSpeed enable register original value */
1012
+	uint32_t usb3pssen;
1013
+};
1014
+
1015
+/** Intel PCH quirk flag */
1016
+#define XHCI_PCH 0x0001
1017
+
1018
+/** Intel PCH USB2 port routing register */
1019
+#define XHCI_PCH_XUSB2PR 0xd0
1020
+
1021
+/** Intel PCH USB2 port routing mask register */
1022
+#define XHCI_PCH_XUSB2PRM 0xd4
1023
+
1024
+/** Intel PCH SuperSpeed enable register */
1025
+#define XHCI_PCH_USB3PSSEN 0xd8
1026
+
1027
+/** Intel PCH USB3 port routing mask register */
1028
+#define XHCI_PCH_USB3PRM 0xdc
1029
+
1007 1030
 /** An xHCI device */
1008 1031
 struct xhci_device {
1009 1032
 	/** Registers */
@@ -1061,6 +1084,9 @@ struct xhci_device {
1061 1084
 
1062 1085
 	/** USB bus */
1063 1086
 	struct usb_bus *bus;
1087
+
1088
+	/** Intel PCH quirk */
1089
+	struct xhci_pch pch;
1064 1090
 };
1065 1091
 
1066 1092
 /** An xHCI device slot */
@@ -1103,19 +1129,4 @@ struct xhci_endpoint {
1103 1129
 	struct xhci_trb_ring ring;
1104 1130
 };
1105 1131
 
1106
-/** Intel PCH quirk */
1107
-#define XHCI_PCH 0x0001
1108
-
1109
-/** Intel PCH USB2 port routing register */
1110
-#define XHCI_PCH_XUSB2PR 0xd0
1111
-
1112
-/** Intel PCH USB2 port routing mask register */
1113
-#define XHCI_PCH_XUSB2PRM 0xd4
1114
-
1115
-/** Intel PCH USB3 port SuperSpeed enable register */
1116
-#define XHCI_PCH_USB3PSSEN 0xd8
1117
-
1118
-/** Intel PCH USB3 port routing mask register */
1119
-#define XHCI_PCH_USB3PRM 0xdc
1120
-
1121 1132
 #endif /* _IPXE_XHCI_H */

Loading…
İptal
Kaydet