All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/5] xhci: Fix perceived dead host due to runtime suspend race with event handler
@ 2018-06-21 13:19   ` Mathias Nyman
  0 siblings, 0 replies; 6+ messages in thread
From: Mathias Nyman @ 2018-06-21 13:19 UTC (permalink / raw)
  To: gregkh; +Cc: linux-usb, Mathias Nyman, stable

Don't rely on event interrupt (EINT) bit alone to detect pending port
change in resume. If no change event is detected the host may be suspended
again, oterwise roothubs are resumed.

There is a lag in xHC setting EINT. If we don't notice the pending change
in resume, and the controller is runtime suspeded again, it causes the
event handler to assume host is dead as it will fail to read xHC registers
once PCI puts the controller to D3 state.

[  268.520969] xhci_hcd: xhci_resume: starting port polling.
[  268.520985] xhci_hcd: xhci_hub_status_data: stopping port polling.
[  268.521030] xhci_hcd: xhci_suspend: stopping port polling.
[  268.521040] xhci_hcd: // Setting command ring address to 0x349bd001
[  268.521139] xhci_hcd: Port Status Change Event for port 3
[  268.521149] xhci_hcd: resume root hub
[  268.521163] xhci_hcd: port resume event for port 3
[  268.521168] xhci_hcd: xHC is not running.
[  268.521174] xhci_hcd: handle_port_status: starting port polling.
[  268.596322] xhci_hcd: xhci_hc_died: xHCI host controller not responding, assume dead

The EINT lag is described in a additional note in xhci specs 4.19.2:

"Due to internal xHC scheduling and system delays, there will be a lag
between a change bit being set and the Port Status Change Event that it
generated being written to the Event Ring. If SW reads the PORTSC and
sees a change bit set, there is no guarantee that the corresponding Port
Status Change Event has already been written into the Event Ring."

Cc: <stable@vger.kernel.org>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
---
 drivers/usb/host/xhci.c | 40 +++++++++++++++++++++++++++++++++++++---
 drivers/usb/host/xhci.h |  4 ++++
 2 files changed, 41 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 8c8da2d..f11ec61 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -908,6 +908,41 @@ static void xhci_disable_port_wake_on_bits(struct xhci_hcd *xhci)
 	spin_unlock_irqrestore(&xhci->lock, flags);
 }
 
+static bool xhci_pending_portevent(struct xhci_hcd *xhci)
+{
+	struct xhci_port	**ports;
+	int			port_index;
+	u32			status;
+	u32			portsc;
+
+	status = readl(&xhci->op_regs->status);
+	if (status & STS_EINT)
+		return true;
+	/*
+	 * Checking STS_EINT is not enough as there is a lag between a change
+	 * bit being set and the Port Status Change Event that it generated
+	 * being written to the Event Ring. See note in xhci 1.1 section 4.19.2.
+	 */
+
+	port_index = xhci->usb2_rhub.num_ports;
+	ports = xhci->usb2_rhub.ports;
+	while (port_index--) {
+		portsc = readl(ports[port_index]->addr);
+		if (portsc & PORT_CHANGE_MASK ||
+		    (portsc & PORT_PLS_MASK) == XDEV_RESUME)
+			return true;
+	}
+	port_index = xhci->usb3_rhub.num_ports;
+	ports = xhci->usb3_rhub.ports;
+	while (port_index--) {
+		portsc = readl(ports[port_index]->addr);
+		if (portsc & PORT_CHANGE_MASK ||
+		    (portsc & PORT_PLS_MASK) == XDEV_RESUME)
+			return true;
+	}
+	return false;
+}
+
 /*
  * Stop HC (not bus-specific)
  *
@@ -1009,7 +1044,7 @@ EXPORT_SYMBOL_GPL(xhci_suspend);
  */
 int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
 {
-	u32			command, temp = 0, status;
+	u32			command, temp = 0;
 	struct usb_hcd		*hcd = xhci_to_hcd(xhci);
 	struct usb_hcd		*secondary_hcd;
 	int			retval = 0;
@@ -1134,8 +1169,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
  done:
 	if (retval == 0) {
 		/* Resume root hubs only when have pending events. */
-		status = readl(&xhci->op_regs->status);
-		if (status & STS_EINT) {
+		if (xhci_pending_portevent(xhci)) {
 			usb_hcd_resume_root_hub(xhci->shared_hcd);
 			usb_hcd_resume_root_hub(hcd);
 		}
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 939e2f86..841e89f 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -382,6 +382,10 @@ struct xhci_op_regs {
 #define PORT_PLC	(1 << 22)
 /* port configure error change - port failed to configure its link partner */
 #define PORT_CEC	(1 << 23)
+#define PORT_CHANGE_MASK	(PORT_CSC | PORT_PEC | PORT_WRC | PORT_OCC | \
+				 PORT_RC | PORT_PLC | PORT_CEC)
+
+
 /* Cold Attach Status - xHC can set this bit to report device attached during
  * Sx state. Warm port reset should be perfomed to clear this bit and move port
  * to connected state.
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [1/5] xhci: Fix perceived dead host due to runtime suspend race with event handler
@ 2018-06-21 13:19   ` Mathias Nyman
  0 siblings, 0 replies; 6+ messages in thread
From: Mathias Nyman @ 2018-06-21 13:19 UTC (permalink / raw)
  To: gregkh; +Cc: linux-usb, Mathias Nyman, stable

Don't rely on event interrupt (EINT) bit alone to detect pending port
change in resume. If no change event is detected the host may be suspended
again, oterwise roothubs are resumed.

There is a lag in xHC setting EINT. If we don't notice the pending change
in resume, and the controller is runtime suspeded again, it causes the
event handler to assume host is dead as it will fail to read xHC registers
once PCI puts the controller to D3 state.

[  268.520969] xhci_hcd: xhci_resume: starting port polling.
[  268.520985] xhci_hcd: xhci_hub_status_data: stopping port polling.
[  268.521030] xhci_hcd: xhci_suspend: stopping port polling.
[  268.521040] xhci_hcd: // Setting command ring address to 0x349bd001
[  268.521139] xhci_hcd: Port Status Change Event for port 3
[  268.521149] xhci_hcd: resume root hub
[  268.521163] xhci_hcd: port resume event for port 3
[  268.521168] xhci_hcd: xHC is not running.
[  268.521174] xhci_hcd: handle_port_status: starting port polling.
[  268.596322] xhci_hcd: xhci_hc_died: xHCI host controller not responding, assume dead

The EINT lag is described in a additional note in xhci specs 4.19.2:

"Due to internal xHC scheduling and system delays, there will be a lag
between a change bit being set and the Port Status Change Event that it
generated being written to the Event Ring. If SW reads the PORTSC and
sees a change bit set, there is no guarantee that the corresponding Port
Status Change Event has already been written into the Event Ring."

Cc: <stable@vger.kernel.org>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
---
 drivers/usb/host/xhci.c | 40 +++++++++++++++++++++++++++++++++++++---
 drivers/usb/host/xhci.h |  4 ++++
 2 files changed, 41 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 8c8da2d..f11ec61 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -908,6 +908,41 @@ static void xhci_disable_port_wake_on_bits(struct xhci_hcd *xhci)
 	spin_unlock_irqrestore(&xhci->lock, flags);
 }
 
+static bool xhci_pending_portevent(struct xhci_hcd *xhci)
+{
+	struct xhci_port	**ports;
+	int			port_index;
+	u32			status;
+	u32			portsc;
+
+	status = readl(&xhci->op_regs->status);
+	if (status & STS_EINT)
+		return true;
+	/*
+	 * Checking STS_EINT is not enough as there is a lag between a change
+	 * bit being set and the Port Status Change Event that it generated
+	 * being written to the Event Ring. See note in xhci 1.1 section 4.19.2.
+	 */
+
+	port_index = xhci->usb2_rhub.num_ports;
+	ports = xhci->usb2_rhub.ports;
+	while (port_index--) {
+		portsc = readl(ports[port_index]->addr);
+		if (portsc & PORT_CHANGE_MASK ||
+		    (portsc & PORT_PLS_MASK) == XDEV_RESUME)
+			return true;
+	}
+	port_index = xhci->usb3_rhub.num_ports;
+	ports = xhci->usb3_rhub.ports;
+	while (port_index--) {
+		portsc = readl(ports[port_index]->addr);
+		if (portsc & PORT_CHANGE_MASK ||
+		    (portsc & PORT_PLS_MASK) == XDEV_RESUME)
+			return true;
+	}
+	return false;
+}
+
 /*
  * Stop HC (not bus-specific)
  *
@@ -1009,7 +1044,7 @@ EXPORT_SYMBOL_GPL(xhci_suspend);
  */
 int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
 {
-	u32			command, temp = 0, status;
+	u32			command, temp = 0;
 	struct usb_hcd		*hcd = xhci_to_hcd(xhci);
 	struct usb_hcd		*secondary_hcd;
 	int			retval = 0;
@@ -1134,8 +1169,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
  done:
 	if (retval == 0) {
 		/* Resume root hubs only when have pending events. */
-		status = readl(&xhci->op_regs->status);
-		if (status & STS_EINT) {
+		if (xhci_pending_portevent(xhci)) {
 			usb_hcd_resume_root_hub(xhci->shared_hcd);
 			usb_hcd_resume_root_hub(hcd);
 		}
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 939e2f86..841e89f 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -382,6 +382,10 @@ struct xhci_op_regs {
 #define PORT_PLC	(1 << 22)
 /* port configure error change - port failed to configure its link partner */
 #define PORT_CEC	(1 << 23)
+#define PORT_CHANGE_MASK	(PORT_CSC | PORT_PEC | PORT_WRC | PORT_OCC | \
+				 PORT_RC | PORT_PLC | PORT_CEC)
+
+
 /* Cold Attach Status - xHC can set this bit to report device attached during
  * Sx state. Warm port reset should be perfomed to clear this bit and move port
  * to connected state.

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/5] xhci: Fix kernel oops in trace_xhci_free_virt_device
@ 2018-06-21 13:19   ` Mathias Nyman
  0 siblings, 0 replies; 6+ messages in thread
From: Mathias Nyman @ 2018-06-21 13:19 UTC (permalink / raw)
  To: gregkh; +Cc: linux-usb, Zhengjun Xing, stable, Mathias Nyman

From: Zhengjun Xing <zhengjun.xing@linux.intel.com>

commit 44a182b9d177 ("xhci: Fix use-after-free in xhci_free_virt_device")
set dev->udev pointer to NULL in xhci_free_dev(), it will cause kernel
panic in trace_xhci_free_virt_device. This patch reimplement the trace
function trace_xhci_free_virt_device, remove dev->udev dereference and
added more useful parameters to show in the trace function,it also makes
sure dev->udev is not NULL before calling trace_xhci_free_virt_device.
This issue happened when xhci-hcd trace is enabled and USB devices hot
plug test. Original use-after-free patch went to stable so this needs so
be applied there as well.

[ 1092.022457] usb 2-4: USB disconnect, device number 6
[ 1092.092772] BUG: unable to handle kernel NULL pointer dereference at 0000000000000000
[ 1092.101694] PGD 0 P4D 0
[ 1092.104601] Oops: 0000 [#1] SMP
[ 1092.207734] Workqueue: usb_hub_wq hub_event
[ 1092.212507] RIP: 0010:trace_event_raw_event_xhci_log_virt_dev+0x6c/0xf0
[ 1092.220050] RSP: 0018:ffff8c252e883d28 EFLAGS: 00010086
[ 1092.226024] RAX: ffff8c24af86fa84 RBX: 0000000000000003 RCX: ffff8c25255c2a01
[ 1092.234130] RDX: 0000000000000000 RSI: 00000000aef55009 RDI: ffff8c252e883d28
[ 1092.242242] RBP: ffff8c252550e2c0 R08: ffff8c24af86fa84 R09: 0000000000000a70
[ 1092.250364] R10: 0000000000000a70 R11: 0000000000000000 R12: ffff8c251f21a000
[ 1092.258468] R13: 000000000000000c R14: ffff8c251f21a000 R15: ffff8c251f432f60
[ 1092.266572] FS:  0000000000000000(0000) GS:ffff8c252e880000(0000) knlGS:0000000000000000
[ 1092.275757] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 1092.282281] CR2: 0000000000000000 CR3: 0000000154209001 CR4: 00000000003606e0
[ 1092.290384] Call Trace:
[ 1092.293156]  <IRQ>
[ 1092.295439]  xhci_free_virt_device.part.34+0x182/0x1a0
[ 1092.301288]  handle_cmd_completion+0x7ac/0xfa0
[ 1092.306336]  ? trace_event_raw_event_xhci_log_trb+0x6e/0xa0
[ 1092.312661]  xhci_irq+0x3e8/0x1f60
[ 1092.316524]  __handle_irq_event_percpu+0x75/0x180
[ 1092.321876]  handle_irq_event_percpu+0x20/0x50
[ 1092.326922]  handle_irq_event+0x36/0x60
[ 1092.331273]  handle_edge_irq+0x6d/0x180
[ 1092.335644]  handle_irq+0x16/0x20
[ 1092.339417]  do_IRQ+0x41/0xc0
[ 1092.342782]  common_interrupt+0xf/0xf
[ 1092.346955]  </IRQ>

Fixes: 44a182b9d177 ("xhci: Fix use-after-free in xhci_free_virt_device")
Cc: <stable@vger.kernel.org>
Signed-off-by: Zhengjun Xing <zhengjun.xing@linux.intel.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
---
 drivers/usb/host/xhci-mem.c   |  4 ++--
 drivers/usb/host/xhci-trace.h | 36 +++++++++++++++++++++++++++++++-----
 2 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index acbd3d7..8a62eee 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -886,12 +886,12 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id)
 
 	dev = xhci->devs[slot_id];
 
-	trace_xhci_free_virt_device(dev);
-
 	xhci->dcbaa->dev_context_ptrs[slot_id] = 0;
 	if (!dev)
 		return;
 
+	trace_xhci_free_virt_device(dev);
+
 	if (dev->tt_info)
 		old_active_eps = dev->tt_info->active_eps;
 
diff --git a/drivers/usb/host/xhci-trace.h b/drivers/usb/host/xhci-trace.h
index 410544f..88b4274 100644
--- a/drivers/usb/host/xhci-trace.h
+++ b/drivers/usb/host/xhci-trace.h
@@ -171,6 +171,37 @@ DEFINE_EVENT(xhci_log_trb, xhci_dbc_gadget_ep_queue,
 	TP_ARGS(ring, trb)
 );
 
+DECLARE_EVENT_CLASS(xhci_log_free_virt_dev,
+	TP_PROTO(struct xhci_virt_device *vdev),
+	TP_ARGS(vdev),
+	TP_STRUCT__entry(
+		__field(void *, vdev)
+		__field(unsigned long long, out_ctx)
+		__field(unsigned long long, in_ctx)
+		__field(u8, fake_port)
+		__field(u8, real_port)
+		__field(u16, current_mel)
+
+	),
+	TP_fast_assign(
+		__entry->vdev = vdev;
+		__entry->in_ctx = (unsigned long long) vdev->in_ctx->dma;
+		__entry->out_ctx = (unsigned long long) vdev->out_ctx->dma;
+		__entry->fake_port = (u8) vdev->fake_port;
+		__entry->real_port = (u8) vdev->real_port;
+		__entry->current_mel = (u16) vdev->current_mel;
+		),
+	TP_printk("vdev %p ctx %llx | %llx fake_port %d real_port %d current_mel %d",
+		__entry->vdev, __entry->in_ctx, __entry->out_ctx,
+		__entry->fake_port, __entry->real_port, __entry->current_mel
+	)
+);
+
+DEFINE_EVENT(xhci_log_free_virt_dev, xhci_free_virt_device,
+	TP_PROTO(struct xhci_virt_device *vdev),
+	TP_ARGS(vdev)
+);
+
 DECLARE_EVENT_CLASS(xhci_log_virt_dev,
 	TP_PROTO(struct xhci_virt_device *vdev),
 	TP_ARGS(vdev),
@@ -208,11 +239,6 @@ DEFINE_EVENT(xhci_log_virt_dev, xhci_alloc_virt_device,
 	TP_ARGS(vdev)
 );
 
-DEFINE_EVENT(xhci_log_virt_dev, xhci_free_virt_device,
-	TP_PROTO(struct xhci_virt_device *vdev),
-	TP_ARGS(vdev)
-);
-
 DEFINE_EVENT(xhci_log_virt_dev, xhci_setup_device,
 	TP_PROTO(struct xhci_virt_device *vdev),
 	TP_ARGS(vdev)
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [2/5] xhci: Fix kernel oops in trace_xhci_free_virt_device
@ 2018-06-21 13:19   ` Mathias Nyman
  0 siblings, 0 replies; 6+ messages in thread
From: Mathias Nyman @ 2018-06-21 13:19 UTC (permalink / raw)
  To: gregkh; +Cc: linux-usb, Zhengjun Xing, stable, Mathias Nyman

From: Zhengjun Xing <zhengjun.xing@linux.intel.com>

commit 44a182b9d177 ("xhci: Fix use-after-free in xhci_free_virt_device")
set dev->udev pointer to NULL in xhci_free_dev(), it will cause kernel
panic in trace_xhci_free_virt_device. This patch reimplement the trace
function trace_xhci_free_virt_device, remove dev->udev dereference and
added more useful parameters to show in the trace function,it also makes
sure dev->udev is not NULL before calling trace_xhci_free_virt_device.
This issue happened when xhci-hcd trace is enabled and USB devices hot
plug test. Original use-after-free patch went to stable so this needs so
be applied there as well.

[ 1092.022457] usb 2-4: USB disconnect, device number 6
[ 1092.092772] BUG: unable to handle kernel NULL pointer dereference at 0000000000000000
[ 1092.101694] PGD 0 P4D 0
[ 1092.104601] Oops: 0000 [#1] SMP
[ 1092.207734] Workqueue: usb_hub_wq hub_event
[ 1092.212507] RIP: 0010:trace_event_raw_event_xhci_log_virt_dev+0x6c/0xf0
[ 1092.220050] RSP: 0018:ffff8c252e883d28 EFLAGS: 00010086
[ 1092.226024] RAX: ffff8c24af86fa84 RBX: 0000000000000003 RCX: ffff8c25255c2a01
[ 1092.234130] RDX: 0000000000000000 RSI: 00000000aef55009 RDI: ffff8c252e883d28
[ 1092.242242] RBP: ffff8c252550e2c0 R08: ffff8c24af86fa84 R09: 0000000000000a70
[ 1092.250364] R10: 0000000000000a70 R11: 0000000000000000 R12: ffff8c251f21a000
[ 1092.258468] R13: 000000000000000c R14: ffff8c251f21a000 R15: ffff8c251f432f60
[ 1092.266572] FS:  0000000000000000(0000) GS:ffff8c252e880000(0000) knlGS:0000000000000000
[ 1092.275757] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 1092.282281] CR2: 0000000000000000 CR3: 0000000154209001 CR4: 00000000003606e0
[ 1092.290384] Call Trace:
[ 1092.293156]  <IRQ>
[ 1092.295439]  xhci_free_virt_device.part.34+0x182/0x1a0
[ 1092.301288]  handle_cmd_completion+0x7ac/0xfa0
[ 1092.306336]  ? trace_event_raw_event_xhci_log_trb+0x6e/0xa0
[ 1092.312661]  xhci_irq+0x3e8/0x1f60
[ 1092.316524]  __handle_irq_event_percpu+0x75/0x180
[ 1092.321876]  handle_irq_event_percpu+0x20/0x50
[ 1092.326922]  handle_irq_event+0x36/0x60
[ 1092.331273]  handle_edge_irq+0x6d/0x180
[ 1092.335644]  handle_irq+0x16/0x20
[ 1092.339417]  do_IRQ+0x41/0xc0
[ 1092.342782]  common_interrupt+0xf/0xf
[ 1092.346955]  </IRQ>

Fixes: 44a182b9d177 ("xhci: Fix use-after-free in xhci_free_virt_device")
Cc: <stable@vger.kernel.org>
Signed-off-by: Zhengjun Xing <zhengjun.xing@linux.intel.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
---
 drivers/usb/host/xhci-mem.c   |  4 ++--
 drivers/usb/host/xhci-trace.h | 36 +++++++++++++++++++++++++++++++-----
 2 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index acbd3d7..8a62eee 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -886,12 +886,12 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id)
 
 	dev = xhci->devs[slot_id];
 
-	trace_xhci_free_virt_device(dev);
-
 	xhci->dcbaa->dev_context_ptrs[slot_id] = 0;
 	if (!dev)
 		return;
 
+	trace_xhci_free_virt_device(dev);
+
 	if (dev->tt_info)
 		old_active_eps = dev->tt_info->active_eps;
 
diff --git a/drivers/usb/host/xhci-trace.h b/drivers/usb/host/xhci-trace.h
index 410544f..88b4274 100644
--- a/drivers/usb/host/xhci-trace.h
+++ b/drivers/usb/host/xhci-trace.h
@@ -171,6 +171,37 @@ DEFINE_EVENT(xhci_log_trb, xhci_dbc_gadget_ep_queue,
 	TP_ARGS(ring, trb)
 );
 
+DECLARE_EVENT_CLASS(xhci_log_free_virt_dev,
+	TP_PROTO(struct xhci_virt_device *vdev),
+	TP_ARGS(vdev),
+	TP_STRUCT__entry(
+		__field(void *, vdev)
+		__field(unsigned long long, out_ctx)
+		__field(unsigned long long, in_ctx)
+		__field(u8, fake_port)
+		__field(u8, real_port)
+		__field(u16, current_mel)
+
+	),
+	TP_fast_assign(
+		__entry->vdev = vdev;
+		__entry->in_ctx = (unsigned long long) vdev->in_ctx->dma;
+		__entry->out_ctx = (unsigned long long) vdev->out_ctx->dma;
+		__entry->fake_port = (u8) vdev->fake_port;
+		__entry->real_port = (u8) vdev->real_port;
+		__entry->current_mel = (u16) vdev->current_mel;
+		),
+	TP_printk("vdev %p ctx %llx | %llx fake_port %d real_port %d current_mel %d",
+		__entry->vdev, __entry->in_ctx, __entry->out_ctx,
+		__entry->fake_port, __entry->real_port, __entry->current_mel
+	)
+);
+
+DEFINE_EVENT(xhci_log_free_virt_dev, xhci_free_virt_device,
+	TP_PROTO(struct xhci_virt_device *vdev),
+	TP_ARGS(vdev)
+);
+
 DECLARE_EVENT_CLASS(xhci_log_virt_dev,
 	TP_PROTO(struct xhci_virt_device *vdev),
 	TP_ARGS(vdev),
@@ -208,11 +239,6 @@ DEFINE_EVENT(xhci_log_virt_dev, xhci_alloc_virt_device,
 	TP_ARGS(vdev)
 );
 
-DEFINE_EVENT(xhci_log_virt_dev, xhci_free_virt_device,
-	TP_PROTO(struct xhci_virt_device *vdev),
-	TP_ARGS(vdev)
-);
-
 DEFINE_EVENT(xhci_log_virt_dev, xhci_setup_device,
 	TP_PROTO(struct xhci_virt_device *vdev),
 	TP_ARGS(vdev)

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [1/5] xhci: Fix perceived dead host due to runtime suspend race with event handler
@ 2018-07-12  3:30     ` Kai-Heng Feng
  0 siblings, 0 replies; 6+ messages in thread
From: Kai-Heng Feng @ 2018-07-12  3:30 UTC (permalink / raw)
  To: Mathias Nyman; +Cc: gregkh, linux-usb, stable

Hi Mathias,

at 21:19, Mathias Nyman <mathias.nyman@linux.intel.com> wrote:

> Don't rely on event interrupt (EINT) bit alone to detect pending port
> change in resume. If no change event is detected the host may be suspended
> again, oterwise roothubs are resumed.
>
> There is a lag in xHC setting EINT. If we don't notice the pending change
> in resume, and the controller is runtime suspeded again, it causes the
> event handler to assume host is dead as it will fail to read xHC registers
> once PCI puts the controller to D3 state.
>
> [  268.520969] xhci_hcd: xhci_resume: starting port polling.
> [  268.520985] xhci_hcd: xhci_hub_status_data: stopping port polling.
> [  268.521030] xhci_hcd: xhci_suspend: stopping port polling.
> [  268.521040] xhci_hcd: // Setting command ring address to 0x349bd001
> [  268.521139] xhci_hcd: Port Status Change Event for port 3
> [  268.521149] xhci_hcd: resume root hub
> [  268.521163] xhci_hcd: port resume event for port 3
> [  268.521168] xhci_hcd: xHC is not running.
> [  268.521174] xhci_hcd: handle_port_status: starting port polling.
> [  268.596322] xhci_hcd: xhci_hc_died: xHCI host controller not  
> responding, assume dead
>
> The EINT lag is described in a additional note in xhci specs 4.19.2:
>
> "Due to internal xHC scheduling and system delays, there will be a lag
> between a change bit being set and the Port Status Change Event that it
> generated being written to the Event Ring. If SW reads the PORTSC and
> sees a change bit set, there is no guarantee that the corresponding Port
> Status Change Event has already been written into the Event Ring."
>
> Cc: <stable@vger.kernel.org>


I tried to backport this patch to v4.15, and "xhci: Create new structures  
to store xhci port information" series is a dependency for this patch.

The series brings substantial changes, so I am wondering if you have any  
plan to backport this patch to older kernels?

Kai-Heng


> Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [1/5] xhci: Fix perceived dead host due to runtime suspend race with event handler
@ 2018-07-12  3:30     ` Kai-Heng Feng
  0 siblings, 0 replies; 6+ messages in thread
From: Kai-Heng Feng @ 2018-07-12  3:30 UTC (permalink / raw)
  To: Mathias Nyman; +Cc: gregkh, linux-usb, stable

Hi Mathias,

at 21:19, Mathias Nyman <mathias.nyman@linux.intel.com> wrote:

> Don't rely on event interrupt (EINT) bit alone to detect pending port
> change in resume. If no change event is detected the host may be suspended
> again, oterwise roothubs are resumed.
>
> There is a lag in xHC setting EINT. If we don't notice the pending change
> in resume, and the controller is runtime suspeded again, it causes the
> event handler to assume host is dead as it will fail to read xHC registers
> once PCI puts the controller to D3 state.
>
> [  268.520969] xhci_hcd: xhci_resume: starting port polling.
> [  268.520985] xhci_hcd: xhci_hub_status_data: stopping port polling.
> [  268.521030] xhci_hcd: xhci_suspend: stopping port polling.
> [  268.521040] xhci_hcd: // Setting command ring address to 0x349bd001
> [  268.521139] xhci_hcd: Port Status Change Event for port 3
> [  268.521149] xhci_hcd: resume root hub
> [  268.521163] xhci_hcd: port resume event for port 3
> [  268.521168] xhci_hcd: xHC is not running.
> [  268.521174] xhci_hcd: handle_port_status: starting port polling.
> [  268.596322] xhci_hcd: xhci_hc_died: xHCI host controller not  
> responding, assume dead
>
> The EINT lag is described in a additional note in xhci specs 4.19.2:
>
> "Due to internal xHC scheduling and system delays, there will be a lag
> between a change bit being set and the Port Status Change Event that it
> generated being written to the Event Ring. If SW reads the PORTSC and
> sees a change bit set, there is no guarantee that the corresponding Port
> Status Change Event has already been written into the Event Ring."
>
> Cc: <stable@vger.kernel.org>


I tried to backport this patch to v4.15, and "xhci: Create new structures  
to store xhci port information" series is a dependency for this patch.

The series brings substantial changes, so I am wondering if you have any  
plan to backport this patch to older kernels?

Kai-Heng


> Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
---
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2018-07-12  4:38 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <1529587185-2776-1-git-send-email-mathias.nyman@linux.intel.com>
2018-06-21 13:19 ` [PATCH 1/5] xhci: Fix perceived dead host due to runtime suspend race with event handler Mathias Nyman
2018-06-21 13:19   ` [1/5] " Mathias Nyman
2018-07-12  3:30   ` Kai-Heng Feng
2018-07-12  3:30     ` Kai-Heng Feng
2018-06-21 13:19 ` [PATCH 2/5] xhci: Fix kernel oops in trace_xhci_free_virt_device Mathias Nyman
2018-06-21 13:19   ` [2/5] " Mathias Nyman

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.