From nobody Sat Feb 7 08:27:04 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.13]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 250F62F39DD; Fri, 23 Jan 2026 17:28:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.13 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769189314; cv=none; b=PMem3aPEnQDt0pwyQniVLfxYoYJqMPGfW38wf4Xl+ugXeZs1eDHGv55OjeP1B8fYuU0yaC0mFk4w8Wu3TdJBAexr79E1QZgnP+gngVtkE/REVBBoPIc9OUzc7lDS9FdfKdDqtX1IzFUeYs3KG/20i1ajmozOn1eN00NpYWoB0DU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769189314; c=relaxed/simple; bh=JJY9Kiz0lujnYFWQ8roXs6PVtnuP7SwZ4Adj8KQIgHE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=KUfOwtq9YGWCTUT7E8T07KQAth/mSrgwJhTAUPI+nL3gek15m6eFTK5j8Hug2OkeI/Bfxm+u9xfzhPnCiJct/mxEQG9tMylSWilnnXfef3kwqOSKLufoNPuydqVp+HG7AX+U8PxCI7UAbhvDU9OD2/oaOhVWblxH7ovhccxcoq4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=kDkLcmEe; arc=none smtp.client-ip=192.198.163.13 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="kDkLcmEe" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1769189313; x=1800725313; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=JJY9Kiz0lujnYFWQ8roXs6PVtnuP7SwZ4Adj8KQIgHE=; b=kDkLcmEe8lQsLaglmrfJl4Lo8th2kK2jkVwhYF6l7zP3FwFkRAx36ClI n8+K0yCpCLf3G9GitG1vPwW0ngI6qNiOqfNegkdAxaJ2jj0l7WJByp+LM rA6wAPQ1As3HYL0D9pcJgmSniaMnwPvssdbk21riXSWnhx9197YrvU9PR bSisomXOhpem2emf2MHPEw/xzeFsSCdk1d0BS1K2PfcjgVQQYfOZzD6uX CP7OvvrIWQfnnhuWp5IzM+JZAxrj2Xi9qo8dwOhOSiYEqareLp1sXSMmQ hTIDdLyrzxi+jEPnBmYF3tf6YLzWDeOb3i3eeTg8G7wNsxlHn9orE5OCN w==; X-CSE-ConnectionGUID: Gwn2cEyIQhmazJapwXN+gg== X-CSE-MsgGUID: C31yrZebQDS7HIuVgHQ1OQ== X-IronPort-AV: E=McAfee;i="6800,10657,11680"; a="73034675" X-IronPort-AV: E=Sophos;i="6.21,248,1763452800"; d="scan'208";a="73034675" Received: from orviesa010.jf.intel.com ([10.64.159.150]) by fmvoesa107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Jan 2026 09:28:32 -0800 X-CSE-ConnectionGUID: Un/o/VO/SmuccN7K3Wpa8w== X-CSE-MsgGUID: tM879L9FRaCQY6VPj7tfxw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.21,248,1763452800"; d="scan'208";a="206326603" Received: from ijarvine-mobl1.ger.corp.intel.com (HELO localhost) ([10.245.244.164]) by orviesa010-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Jan 2026 09:28:28 -0800 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= To: Greg Kroah-Hartman , Jiri Slaby , linux-serial@vger.kernel.org, Andy Shevchenko , qianfan Zhao , Adriana Nicolae , =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= , linux-kernel@vger.kernel.org Cc: "Bandal, Shankar" , "Murthy, Shanth" Subject: [PATCH 4/6] serial: 8250_dw: Rework IIR_NO_INT handling to stop interrupt storm Date: Fri, 23 Jan 2026 19:27:37 +0200 Message-Id: <20260123172739.13410-5-ilpo.jarvinen@linux.intel.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20260123172739.13410-1-ilpo.jarvinen@linux.intel.com> References: <20260123172739.13410-1-ilpo.jarvinen@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable INTC10EE UART can end up into an interrupt storm where it reports IIR_NO_INT (0x1). If the storm happens during active UART operation, it is promptly stopped by IIR value change due to Rx or Tx events. However, when there is no activity, either due to idle serial line or due to specific circumstances such as during shutdown that writes IER=3D0, there is nothing to stop the storm. During shutdown the storm is particularly problematic because serial8250_do_shutdown() calls synchronize_irq() that will hang in waiting for the storm to finish which never happens. This problem can also result in triggering a warning: irq 45: nobody cared (try booting with the "irqpoll" option) [...snip...] handlers: serial8250_interrupt Disabling IRQ #45 Normal means to reset interrupt status by reading LSR, MSR, USR, or RX register do not result in the UART deasserting the IRQ. Add a quirk to INTC10EE UARTs to enable Tx interrupts if UART's Tx is currently empty and inactive. Rework IIR_NO_INT to keep track of the number of consecutive IIR_NO_INT, and on third one perform the quirk. Enabling Tx interrupts should change IIR value from IIR_NO_INT to IIR_THRI which has been observed to stop the storm. Reported-by: "Bandal, Shankar" Tested-by: "Bandal, Shankar" Tested-by: "Murthy, Shanth" Signed-off-by: Ilpo J=C3=A4rvinen --- drivers/tty/serial/8250/8250_dw.c | 60 ++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 4 deletions(-) diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/82= 50_dw.c index 7cee89f14179..a40c0851f39c 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -60,6 +60,7 @@ #define DW_UART_QUIRK_IS_DMA_FC BIT(3) #define DW_UART_QUIRK_APMC0D08 BIT(4) #define DW_UART_QUIRK_CPR_VALUE BIT(5) +#define DW_UART_QUIRK_IER_KICK BIT(6) =20 struct dw8250_platform_data { u8 usr_reg; @@ -81,6 +82,8 @@ struct dw8250_data { =20 unsigned int skip_autocfg:1; unsigned int uart_16550_compatible:1; + + u64 no_int_count; }; =20 static inline struct dw8250_data *to_dw8250_data(struct dw8250_port_data *= data) @@ -308,6 +311,29 @@ static u32 dw8250_serial_in32be(struct uart_port *p, u= nsigned int offset) return dw8250_modify_msr(p, offset, value); } =20 +/* + * INTC10EE UART can IRQ storm while reporting IIR_NO_INT. Inducing IIR va= lue + * change has been observed to break the storm. + * + * If Tx is empty (THRE asserted), we use here IER_THRI to cause IIR_NO_IN= T -> + * IIR_THRI transition. + */ +static void dw8250_quirk_ier_kick(struct uart_port *p) +{ + struct uart_8250_port *up =3D up_to_u8250p(p); + u32 lsr; + + if (up->ier & UART_IER_THRI) + return; + + lsr =3D serial_lsr_in(up); + if (!(lsr & UART_LSR_THRE)) + return; + + serial_out(up, UART_IER, up->ier | UART_IER_THRI); + serial_in(up, UART_LCR); /* safe, no side-effects */ + serial_out(up, UART_IER, up->ier); +} =20 static int dw8250_handle_irq(struct uart_port *p) { @@ -318,18 +344,29 @@ static int dw8250_handle_irq(struct uart_port *p) unsigned int quirks =3D d->pdata->quirks; unsigned int status; =20 + guard(uart_port_lock_irqsave)(p); + switch (FIELD_GET(DW_UART_IIR_IID, iir)) { case UART_IIR_NO_INT: + if (d->uart_16550_compatible || up->dma) + return 0; + + d->no_int_count++; + if (d->no_int_count > 2 && quirks & DW_UART_QUIRK_IER_KICK) + dw8250_quirk_ier_kick(p); + return 0; =20 case UART_IIR_BUSY: /* Clear the USR */ serial_port_in(p, d->pdata->usr_reg); =20 + d->no_int_count =3D 0; + return 1; } =20 - guard(uart_port_lock_irqsave)(p); + d->no_int_count =3D 0; =20 /* * There are ways to get Designware-based UARTs into a state where @@ -562,6 +599,14 @@ static void dw8250_reset_control_assert(void *data) reset_control_assert(data); } =20 +static void dw8250_shutdown(struct uart_port *port) +{ + struct dw8250_data *d =3D to_dw8250_data(port->private_data); + + serial8250_do_shutdown(port); + d->no_int_count =3D 0; +} + static int dw8250_probe(struct platform_device *pdev) { struct uart_8250_port uart =3D {}, *up =3D &uart; @@ -685,10 +730,12 @@ static int dw8250_probe(struct platform_device *pdev) dw8250_quirks(p, data); =20 /* If the Busy Functionality is not implemented, don't handle it */ - if (data->uart_16550_compatible) + if (data->uart_16550_compatible) { p->handle_irq =3D NULL; - else if (data->pdata) + } else if (data->pdata) { p->handle_irq =3D dw8250_handle_irq; + p->shutdown =3D dw8250_shutdown; + } =20 dw8250_setup_dma_filter(p, data); =20 @@ -815,6 +862,11 @@ static const struct dw8250_platform_data dw8250_skip_s= et_rate_data =3D { .quirks =3D DW_UART_QUIRK_SKIP_SET_RATE, }; =20 +static const struct dw8250_platform_data dw8250_intc10ee =3D { + .usr_reg =3D DW_UART_USR, + .quirks =3D DW_UART_QUIRK_IER_KICK, +}; + static const struct of_device_id dw8250_of_match[] =3D { { .compatible =3D "snps,dw-apb-uart", .data =3D &dw8250_dw_apb }, { .compatible =3D "cavium,octeon-3860-uart", .data =3D &dw8250_octeon_386= 0_data }, @@ -844,7 +896,7 @@ static const struct acpi_device_id dw8250_acpi_match[] = =3D { { "INT33C5", (kernel_ulong_t)&dw8250_dw_apb }, { "INT3434", (kernel_ulong_t)&dw8250_dw_apb }, { "INT3435", (kernel_ulong_t)&dw8250_dw_apb }, - { "INTC10EE", (kernel_ulong_t)&dw8250_dw_apb }, + { "INTC10EE", (kernel_ulong_t)&dw8250_intc10ee }, { }, }; MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match); --=20 2.39.5