mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Rahul Pon <theflyingrahul@gmail.com>
To: Bjorn Andersson <andersson@kernel.org>,
	Konrad Dybcio <konradybcio@kernel.org>
Cc: linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH] soc: qcom: pmic_glink_altmode: acknowledge notifications on undescribed ports
Date: Wed, 30 Sep 2026 16:46:56 +0530	[thread overview]
Message-ID: <20260930111657.1147-1-theflyingrahul@gmail.com> (raw)

The driver enables port notifications from the firmware (ALTMODE_PAN_EN)
for every port, but only acknowledges them (ALTMODE_PAN_ACK) from the
worker of a port that has a connector node. A notification for any other
port is logged at debug level and dropped without an acknowledgment.

On an HP OmniBook 5 (Snapdragon X2, Mahua) whose device tree does not
yet describe the USB-C connectors, the firmware kept charging on the
connector that was plugged in, but once a notification had gone
unacknowledged (on unplug), its UCSI connector status reported no
connection on either port through repeated replugs, and no charging
session started again. The firmware also reports more UCSI connectors
than a board may describe to this driver (here a third, USB Standard-A,
port).

Acknowledge notifications for ports without a connector node from a
work item, as pmic_glink_altmode_request() sleeps and the notification
callback must not.

Assisted-by: LLM
Signed-off-by: Rahul Pon <theflyingrahul@gmail.com>
---
 drivers/soc/qcom/pmic_glink_altmode.c | 42 +++++++++++++++++++++++++--
 1 file changed, 40 insertions(+), 2 deletions(-)

diff --git a/drivers/soc/qcom/pmic_glink_altmode.c b/drivers/soc/qcom/pmic_glink_altmode.c
index 13c434f8d0..24ee9ecc42 100644
--- a/drivers/soc/qcom/pmic_glink_altmode.c
+++ b/drivers/soc/qcom/pmic_glink_altmode.c
@@ -6,6 +6,7 @@
 #include <linux/auxiliary_bus.h>
 #include <linux/bitfield.h>
 #include <linux/cleanup.h>
+#include <linux/devm-helpers.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -138,6 +139,10 @@ struct pmic_glink_altmode {
 
 	struct work_struct enable_work;
 
+	/* Ports without a connector node with a notification to acknowledge */
+	struct work_struct ack_work;
+	unsigned long ack_pending;
+
 	struct pmic_glink_altmode_port ports[PMIC_GLINK_MAX_PORTS];
 };
 
@@ -393,6 +398,35 @@ static void pmic_glink_altmode_worker(struct work_struct *work)
 	pmic_glink_altmode_request(altmode, ALTMODE_PAN_ACK, alt_port->index);
 }
 
+/*
+ * The firmware expects every port notification to be acknowledged, also for
+ * ports that have no connector node and are otherwise ignored here; one left
+ * unacknowledged can keep it from reporting further connections. Acknowledge
+ * those from process context, as pmic_glink_altmode_request() sleeps.
+ */
+static void pmic_glink_altmode_ack_worker(struct work_struct *work)
+{
+	struct pmic_glink_altmode *altmode = container_of(work, struct pmic_glink_altmode,
+							  ack_work);
+	unsigned int port;
+
+	for (port = 0; port < BITS_PER_LONG; port++) {
+		if (test_and_clear_bit(port, &altmode->ack_pending))
+			pmic_glink_altmode_request(altmode, ALTMODE_PAN_ACK, port);
+	}
+}
+
+static void pmic_glink_altmode_ack_undefined(struct pmic_glink_altmode *altmode, u8 port)
+{
+	dev_dbg(altmode->dev, "notification on undefined port %d\n", port);
+
+	if (port >= BITS_PER_LONG)
+		return;
+
+	set_bit(port, &altmode->ack_pending);
+	schedule_work(&altmode->ack_work);
+}
+
 static enum typec_orientation pmic_glink_altmode_orientation(unsigned int orientation)
 {
 	if (orientation == 0)
@@ -441,7 +475,7 @@ static void pmic_glink_altmode_sc8180xp_notify(struct pmic_glink_altmode *altmod
 	svid = mux == 2 ? USB_TYPEC_DP_SID : 0;
 
 	if (port >= ARRAY_SIZE(altmode->ports) || !altmode->ports[port].altmode) {
-		dev_dbg(altmode->dev, "notification on undefined port %d\n", port);
+		pmic_glink_altmode_ack_undefined(altmode, port);
 		return;
 	}
 
@@ -480,7 +514,7 @@ static void pmic_glink_altmode_sc8280xp_notify(struct pmic_glink_altmode *altmod
 	orientation = notify->orientation;
 
 	if (port >= ARRAY_SIZE(altmode->ports) || !altmode->ports[port].altmode) {
-		dev_dbg(altmode->dev, "notification on undefined port %d\n", port);
+		pmic_glink_altmode_ack_undefined(altmode, port);
 		return;
 	}
 
@@ -593,6 +627,10 @@ static int pmic_glink_altmode_probe(struct auxiliary_device *adev,
 	init_completion(&altmode->pan_ack);
 	mutex_init(&altmode->lock);
 
+	ret = devm_work_autocancel(dev, &altmode->ack_work, pmic_glink_altmode_ack_worker);
+	if (ret)
+		return ret;
+
 	device_for_each_child_node(dev, fwnode) {
 		ret = fwnode_property_read_u32(fwnode, "reg", &port);
 		if (ret < 0) {

base-commit: 551c722f40809618230001baccf219193e22fc5a
-- 
2.53.0


                 reply	other threads:[~2026-09-30 11:17 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260930111657.1147-1-theflyingrahul@gmail.com \
    --to=theflyingrahul@gmail.com \
    --cc=andersson@kernel.org \
    --cc=konradybcio@kernel.org \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®