All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] thunderbolt: Power cycle the router if NVM authentication fails
@ 2019-11-12  9:24 Mika Westerberg
  2019-11-15 11:56 ` Mika Westerberg
  0 siblings, 1 reply; 2+ messages in thread
From: Mika Westerberg @ 2019-11-12  9:24 UTC (permalink / raw)
  To: linux-kernel
  Cc: Andreas Noever, Michael Jamet, Yehezkel Bernat, Lukas Wunner,
	Mario.Limonciello, Christian Kellner, zang, Mika Westerberg

On zang's Dell XPS 13 9370 after Thunderbolt NVM firmware upgrade the
Thunderbolt controller did not come back as expected. Only after the
system was rebooted it became available again. It is not entirely clear
what happened but I suspect the new NVM firmware image authentication
failed for some reason. Regardless of this the router needs to be power
cycled if NVM authentication fails in order to get it fully functional
again.

This modifies the driver to issue a power cycle in case the NVM
authentication fails immediately when dma_port_flash_update_auth()
returns. We also need to call tb_switch_set_uuid() earlier to be able to
fetch possible NVM authentication failure when DMA port is added.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=205457
Reported-by: zang <dump@tzib.net>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
This applies on top of my thunderbolt.git/next.

 drivers/thunderbolt/switch.c | 54 ++++++++++++++++++++++++++++--------
 1 file changed, 42 insertions(+), 12 deletions(-)

diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c
index 3f477df2730a..ca86a8e09c77 100644
--- a/drivers/thunderbolt/switch.c
+++ b/drivers/thunderbolt/switch.c
@@ -168,7 +168,7 @@ static int nvm_validate_and_write(struct tb_switch *sw)
 
 static int nvm_authenticate_host(struct tb_switch *sw)
 {
-	int ret;
+	int ret = 0;
 
 	/*
 	 * Root switch NVM upgrade requires that we disconnect the
@@ -176,6 +176,8 @@ static int nvm_authenticate_host(struct tb_switch *sw)
 	 * already).
 	 */
 	if (!sw->safe_mode) {
+		u32 status;
+
 		ret = tb_domain_disconnect_all_paths(sw->tb);
 		if (ret)
 			return ret;
@@ -184,7 +186,16 @@ static int nvm_authenticate_host(struct tb_switch *sw)
 		 * everything goes well so getting timeout is expected.
 		 */
 		ret = dma_port_flash_update_auth(sw->dma_port);
-		return ret == -ETIMEDOUT ? 0 : ret;
+		if (!ret || ret == -ETIMEDOUT)
+			return 0;
+
+		/*
+		 * Any error from update auth operation requires power
+		 * cycling of the host router.
+		 */
+		tb_sw_warn(sw, "failed to authenticate NVM, power cycling\n");
+		if (dma_port_flash_update_auth_status(sw->dma_port, &status) > 0)
+			nvm_set_auth_status(sw, status);
 	}
 
 	/*
@@ -192,7 +203,7 @@ static int nvm_authenticate_host(struct tb_switch *sw)
 	 * switch.
 	 */
 	dma_port_power_cycle(sw->dma_port);
-	return 0;
+	return ret;
 }
 
 static int nvm_authenticate_device(struct tb_switch *sw)
@@ -200,8 +211,16 @@ static int nvm_authenticate_device(struct tb_switch *sw)
 	int ret, retries = 10;
 
 	ret = dma_port_flash_update_auth(sw->dma_port);
-	if (ret && ret != -ETIMEDOUT)
+	switch (ret) {
+	case 0:
+	case -ETIMEDOUT:
+	case -EACCES:
+	case -EINVAL:
+		/* Power cycle is required */
+		break;
+	default:
 		return ret;
+	}
 
 	/*
 	 * Poll here for the authentication status. It takes some time
@@ -1420,8 +1439,6 @@ static ssize_t nvm_authenticate_store(struct device *dev,
 			 */
 			nvm_authenticate_start(sw);
 			ret = nvm_authenticate_host(sw);
-			if (ret)
-				nvm_authenticate_complete(sw);
 		} else {
 			ret = nvm_authenticate_device(sw);
 		}
@@ -1876,13 +1893,16 @@ static int tb_switch_add_dma_port(struct tb_switch *sw)
 	int ret;
 
 	switch (sw->generation) {
-	case 3:
-		break;
-
 	case 2:
 		/* Only root switch can be upgraded */
 		if (tb_route(sw))
 			return 0;
+
+		/* fallthrough */
+	case 3:
+		ret = tb_switch_set_uuid(sw);
+		if (ret)
+			return ret;
 		break;
 
 	default:
@@ -1906,6 +1926,19 @@ static int tb_switch_add_dma_port(struct tb_switch *sw)
 	if (sw->no_nvm_upgrade)
 		return 0;
 
+	/*
+	 * If there is status already set then authentication failed
+	 * when the dma_port_flash_update_auth() returned. Power cycling
+	 * is not needed (it was done already) so only thing we do here
+	 * is to unblock runtime PM of the root port.
+	 */
+	nvm_get_auth_status(sw, &status);
+	if (status) {
+		if (!tb_route(sw))
+			nvm_authenticate_complete(sw);
+		return 0;
+	}
+
 	/*
 	 * Check status of the previous flash authentication. If there
 	 * is one we need to power cycle the switch in any case to make
@@ -1921,9 +1954,6 @@ static int tb_switch_add_dma_port(struct tb_switch *sw)
 
 	if (status) {
 		tb_sw_info(sw, "switch flash authentication failed\n");
-		ret = tb_switch_set_uuid(sw);
-		if (ret)
-			return ret;
 		nvm_set_auth_status(sw, status);
 	}
 
-- 
2.24.0


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

* Re: [PATCH] thunderbolt: Power cycle the router if NVM authentication fails
  2019-11-12  9:24 [PATCH] thunderbolt: Power cycle the router if NVM authentication fails Mika Westerberg
@ 2019-11-15 11:56 ` Mika Westerberg
  0 siblings, 0 replies; 2+ messages in thread
From: Mika Westerberg @ 2019-11-15 11:56 UTC (permalink / raw)
  To: linux-kernel
  Cc: Andreas Noever, Michael Jamet, Yehezkel Bernat, Lukas Wunner,
	Mario.Limonciello, Christian Kellner, zang

On Tue, Nov 12, 2019 at 12:24:52PM +0300, Mika Westerberg wrote:
> On zang's Dell XPS 13 9370 after Thunderbolt NVM firmware upgrade the
> Thunderbolt controller did not come back as expected. Only after the
> system was rebooted it became available again. It is not entirely clear
> what happened but I suspect the new NVM firmware image authentication
> failed for some reason. Regardless of this the router needs to be power
> cycled if NVM authentication fails in order to get it fully functional
> again.
> 
> This modifies the driver to issue a power cycle in case the NVM
> authentication fails immediately when dma_port_flash_update_auth()
> returns. We also need to call tb_switch_set_uuid() earlier to be able to
> fetch possible NVM authentication failure when DMA port is added.
> 
> Link: https://bugzilla.kernel.org/show_bug.cgi?id=205457
> Reported-by: zang <dump@tzib.net>
> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> ---
> This applies on top of my thunderbolt.git/next.

Applied to thunderbolt.git/next.

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

end of thread, other threads:[~2019-11-15 11:56 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-12  9:24 [PATCH] thunderbolt: Power cycle the router if NVM authentication fails Mika Westerberg
2019-11-15 11:56 ` Mika Westerberg

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.