* [PATCH v2 1/2] usb: typec: tcpci: fix NULL pointer issue on shared irq case
@ 2024-12-12 12:24 Xu Yang
2024-12-12 12:24 ` [PATCH v2 2/2] usb: typec: tcpci: write ALERT_MASK after devm_request_threaded_irq() Xu Yang
0 siblings, 1 reply; 5+ messages in thread
From: Xu Yang @ 2024-12-12 12:24 UTC (permalink / raw)
To: heikki.krogerus, gregkh, andre.draszik, rdbabiera, m.felsch,
dan.carpenter, emanuele.ghidoli, parth.pancholi,
francesco.dolcini, u.kleine-koenig
Cc: linux-usb, imx, jun.li
The tcpci_irq() may meet below NULL pointer dereference issue:
[ 2.641851] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000010
[ 2.641951] status 0x1, 0x37f
[ 2.650659] Mem abort info:
[ 2.656490] ESR = 0x0000000096000004
[ 2.660230] EC = 0x25: DABT (current EL), IL = 32 bits
[ 2.665532] SET = 0, FnV = 0
[ 2.668579] EA = 0, S1PTW = 0
[ 2.671715] FSC = 0x04: level 0 translation fault
[ 2.676584] Data abort info:
[ 2.679459] ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000
[ 2.684936] CM = 0, WnR = 0, TnD = 0, TagAccess = 0
[ 2.689980] GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
[ 2.695284] [0000000000000010] user address but active_mm is swapper
[ 2.701632] Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP
[ 2.707883] Modules linked in:
[ 2.710936] CPU: 1 UID: 0 PID: 87 Comm: irq/111-2-0051 Not tainted 6.12.0-rc6-06316-g7f63786ad3d1-dirty #4
[ 2.720570] Hardware name: NXP i.MX93 11X11 EVK board (DT)
[ 2.726040] pstate: 60400009 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[ 2.732989] pc : tcpci_irq+0x38/0x318
[ 2.736647] lr : _tcpci_irq+0x14/0x20
[ 2.740295] sp : ffff80008324bd30
[ 2.743597] x29: ffff80008324bd70 x28: ffff800080107894 x27: ffff800082198f70
[ 2.750721] x26: ffff0000050e6680 x25: ffff000004d172ac x24: ffff0000050f0000
[ 2.757845] x23: ffff000004d17200 x22: 0000000000000001 x21: ffff0000050f0000
[ 2.764969] x20: ffff000004d17200 x19: 0000000000000000 x18: 0000000000000001
[ 2.772093] x17: 0000000000000000 x16: ffff80008183d8a0 x15: ffff00007fbab040
[ 2.779217] x14: ffff00007fb918c0 x13: 0000000000000000 x12: 000000000000017a
[ 2.786341] x11: 0000000000000001 x10: 0000000000000a90 x9 : ffff80008324bd00
[ 2.793465] x8 : ffff0000050f0af0 x7 : ffff00007fbaa840 x6 : 0000000000000031
[ 2.800589] x5 : 000000000000017a x4 : 0000000000000002 x3 : 0000000000000002
[ 2.807713] x2 : ffff80008324bd3a x1 : 0000000000000010 x0 : 0000000000000000
[ 2.814838] Call trace:
[ 2.817273] tcpci_irq+0x38/0x318
[ 2.820583] _tcpci_irq+0x14/0x20
[ 2.823885] irq_thread_fn+0x2c/0xa8
[ 2.827456] irq_thread+0x16c/0x2f4
[ 2.830940] kthread+0x110/0x114
[ 2.834164] ret_from_fork+0x10/0x20
[ 2.837738] Code: f9426420 f9001fe0 d2800000 52800201 (f9400a60)
This may happen on shared irq case. Such as two Type-C ports share one
irq. After the first port finished tcpci_register_port(), it may trigger
interrupt. However, if the interrupt comes by chance the 2nd port finishes
devm_request_threaded_irq(), the 2nd port interrupt handler may be run at
first. Then the above issue may happen.
devm_request_threaded_irq()
<-- port1 irq comes
disable_irq(client->irq);
tcpci_register_port()
This will restore the logic to the state before commit (77e85107a771 "usb:
typec: tcpci: support edge irq").
Fixes: 77e85107a771 ("usb: typec: tcpci: support edge irq")
Cc: stable@vger.kernel.org
Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
---
Changes in v2:
- no changes
---
drivers/usb/typec/tcpm/tcpci.c | 18 ++++++++----------
1 file changed, 8 insertions(+), 10 deletions(-)
diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c
index 2f15734a5043..db42f4bf3632 100644
--- a/drivers/usb/typec/tcpm/tcpci.c
+++ b/drivers/usb/typec/tcpm/tcpci.c
@@ -923,22 +923,20 @@ static int tcpci_probe(struct i2c_client *client)
chip->data.set_orientation = err;
+ chip->tcpci = tcpci_register_port(&client->dev, &chip->data);
+ if (IS_ERR(chip->tcpci))
+ return PTR_ERR(chip->tcpci);
+
err = devm_request_threaded_irq(&client->dev, client->irq, NULL,
_tcpci_irq,
IRQF_SHARED | IRQF_ONESHOT,
dev_name(&client->dev), chip);
- if (err < 0)
+ if (err < 0) {
+ tcpci_unregister_port(chip->tcpci);
return err;
+ }
- /*
- * Disable irq while registering port. If irq is configured as an edge
- * irq this allow to keep track and process the irq as soon as it is enabled.
- */
- disable_irq(client->irq);
- chip->tcpci = tcpci_register_port(&client->dev, &chip->data);
- enable_irq(client->irq);
-
- return PTR_ERR_OR_ZERO(chip->tcpci);
+ return 0;
}
static void tcpci_remove(struct i2c_client *client)
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH v2 2/2] usb: typec: tcpci: write ALERT_MASK after devm_request_threaded_irq()
2024-12-12 12:24 [PATCH v2 1/2] usb: typec: tcpci: fix NULL pointer issue on shared irq case Xu Yang
@ 2024-12-12 12:24 ` Xu Yang
2024-12-16 18:55 ` Francesco Dolcini
0 siblings, 1 reply; 5+ messages in thread
From: Xu Yang @ 2024-12-12 12:24 UTC (permalink / raw)
To: heikki.krogerus, gregkh, andre.draszik, rdbabiera, m.felsch,
dan.carpenter, emanuele.ghidoli, parth.pancholi,
francesco.dolcini, u.kleine-koenig
Cc: linux-usb, imx, jun.li
With edge irq support, the ALERT event may be missed currently. The reason
is that ALERT_MASK register is written before devm_request_threaded_irq().
If ALERT event happens in this time gap, it will be missed and ALERT line
will not recover to high level. However, we can't meet this issue with
level irq. To avoid the issue, this will add a flag set_alert_mask. So
ALERT_MASK can be written after devm_request_threaded_irq() is called. The
behavior of tcpm_init() keeps unchanged.
Fixes: 77e85107a771 ("usb: typec: tcpci: support edge irq")
Cc: stable@vger.kernel.org
Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
---
Changes in v2:
- new patch
---
drivers/usb/typec/tcpm/tcpci.c | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c
index db42f4bf3632..836f6d54d267 100644
--- a/drivers/usb/typec/tcpm/tcpci.c
+++ b/drivers/usb/typec/tcpm/tcpci.c
@@ -37,6 +37,7 @@ struct tcpci {
unsigned int alert_mask;
bool controls_vbus;
+ bool set_alert_mask;
struct tcpc_dev tcpc;
struct tcpci_data *data;
@@ -700,7 +701,10 @@ static int tcpci_init(struct tcpc_dev *tcpc)
tcpci->alert_mask = reg;
- return tcpci_write16(tcpci, TCPC_ALERT_MASK, reg);
+ if (tcpci->set_alert_mask)
+ ret = tcpci_write16(tcpci, TCPC_ALERT_MASK, reg);
+
+ return ret;
}
irqreturn_t tcpci_irq(struct tcpci *tcpci)
@@ -931,12 +935,20 @@ static int tcpci_probe(struct i2c_client *client)
_tcpci_irq,
IRQF_SHARED | IRQF_ONESHOT,
dev_name(&client->dev), chip);
- if (err < 0) {
- tcpci_unregister_port(chip->tcpci);
- return err;
- }
+ if (err < 0)
+ goto unregister_port;
+ /* Enable the interrupt on chip at last */
+ err = tcpci_write16(chip->tcpci, TCPC_ALERT_MASK, chip->tcpci->alert_mask);
+ if (err < 0)
+ goto unregister_port;
+
+ chip->tcpci->set_alert_mask = true;
return 0;
+
+unregister_port:
+ tcpci_unregister_port(chip->tcpci);
+ return err;
}
static void tcpci_remove(struct i2c_client *client)
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH v2 2/2] usb: typec: tcpci: write ALERT_MASK after devm_request_threaded_irq()
2024-12-12 12:24 ` [PATCH v2 2/2] usb: typec: tcpci: write ALERT_MASK after devm_request_threaded_irq() Xu Yang
@ 2024-12-16 18:55 ` Francesco Dolcini
2024-12-17 8:54 ` Xu Yang
0 siblings, 1 reply; 5+ messages in thread
From: Francesco Dolcini @ 2024-12-16 18:55 UTC (permalink / raw)
To: Xu Yang
Cc: heikki.krogerus, gregkh, andre.draszik, rdbabiera, m.felsch,
dan.carpenter, emanuele.ghidoli, parth.pancholi,
francesco.dolcini, u.kleine-koenig, linux-usb, imx, jun.li
On Thu, Dec 12, 2024 at 08:24:09PM +0800, Xu Yang wrote:
> With edge irq support, the ALERT event may be missed currently. The reason
> is that ALERT_MASK register is written before devm_request_threaded_irq().
> If ALERT event happens in this time gap, it will be missed and ALERT line
> will not recover to high level. However, we can't meet this issue with
> level irq. To avoid the issue, this will add a flag set_alert_mask. So
> ALERT_MASK can be written after devm_request_threaded_irq() is called. The
> behavior of tcpm_init() keeps unchanged.
>
> Fixes: 77e85107a771 ("usb: typec: tcpci: support edge irq")
> Cc: stable@vger.kernel.org
> Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
I wonder if this should be squashed together with the first commit,
given you re-introduce an issue with the previous commit.
>
> ---
> Changes in v2:
> - new patch
> ---
> drivers/usb/typec/tcpm/tcpci.c | 22 +++++++++++++++++-----
> 1 file changed, 17 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c
> index db42f4bf3632..836f6d54d267 100644
> --- a/drivers/usb/typec/tcpm/tcpci.c
> +++ b/drivers/usb/typec/tcpm/tcpci.c
> @@ -37,6 +37,7 @@ struct tcpci {
> unsigned int alert_mask;
>
> bool controls_vbus;
> + bool set_alert_mask;
>
> struct tcpc_dev tcpc;
> struct tcpci_data *data;
> @@ -700,7 +701,10 @@ static int tcpci_init(struct tcpc_dev *tcpc)
>
> tcpci->alert_mask = reg;
>
> - return tcpci_write16(tcpci, TCPC_ALERT_MASK, reg);
> + if (tcpci->set_alert_mask)
> + ret = tcpci_write16(tcpci, TCPC_ALERT_MASK, reg);
> +
> + return ret;
> }
>
> irqreturn_t tcpci_irq(struct tcpci *tcpci)
> @@ -931,12 +935,20 @@ static int tcpci_probe(struct i2c_client *client)
> _tcpci_irq,
> IRQF_SHARED | IRQF_ONESHOT,
> dev_name(&client->dev), chip);
> - if (err < 0) {
> - tcpci_unregister_port(chip->tcpci);
> - return err;
> - }
> + if (err < 0)
> + goto unregister_port;
>
> + /* Enable the interrupt on chip at last */
> + err = tcpci_write16(chip->tcpci, TCPC_ALERT_MASK, chip->tcpci->alert_mask);
what's the content of alert_mask here?
I am not fully understanding why this flag is needed, can't we just ensure
that within probe the alert mask is set to 0, after probe return with
success we have the interrupt handler enabled and we can just write the
alert mask unconditionally.
Or I am just misunderstanding all of it?
If you disable the interrupt in the porbe
Francesco
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH v2 2/2] usb: typec: tcpci: write ALERT_MASK after devm_request_threaded_irq()
2024-12-16 18:55 ` Francesco Dolcini
@ 2024-12-17 8:54 ` Xu Yang
2024-12-17 9:20 ` Francesco Dolcini
0 siblings, 1 reply; 5+ messages in thread
From: Xu Yang @ 2024-12-17 8:54 UTC (permalink / raw)
To: Francesco Dolcini
Cc: heikki.krogerus, gregkh, andre.draszik, rdbabiera, m.felsch,
dan.carpenter, emanuele.ghidoli, parth.pancholi,
francesco.dolcini, u.kleine-koenig, linux-usb, imx, jun.li
On Mon, Dec 16, 2024 at 07:55:40PM +0100, Francesco Dolcini wrote:
> On Thu, Dec 12, 2024 at 08:24:09PM +0800, Xu Yang wrote:
> > With edge irq support, the ALERT event may be missed currently. The reason
> > is that ALERT_MASK register is written before devm_request_threaded_irq().
> > If ALERT event happens in this time gap, it will be missed and ALERT line
> > will not recover to high level. However, we can't meet this issue with
> > level irq. To avoid the issue, this will add a flag set_alert_mask. So
> > ALERT_MASK can be written after devm_request_threaded_irq() is called. The
> > behavior of tcpm_init() keeps unchanged.
> >
> > Fixes: 77e85107a771 ("usb: typec: tcpci: support edge irq")
> > Cc: stable@vger.kernel.org
> > Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
>
> I wonder if this should be squashed together with the first commit,
> given you re-introduce an issue with the previous commit.
No. One patch normally should do one thing. To support edge irq, commit
77e85107a771 cause NULL ponter issue so path 1 fix it, it also didn't
handle irq or alert_mask correctly, then patch 2 is needed.
>
>
> >
> > ---
> > Changes in v2:
> > - new patch
> > ---
> > drivers/usb/typec/tcpm/tcpci.c | 22 +++++++++++++++++-----
> > 1 file changed, 17 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c
> > index db42f4bf3632..836f6d54d267 100644
> > --- a/drivers/usb/typec/tcpm/tcpci.c
> > +++ b/drivers/usb/typec/tcpm/tcpci.c
> > @@ -37,6 +37,7 @@ struct tcpci {
> > unsigned int alert_mask;
> >
> > bool controls_vbus;
> > + bool set_alert_mask;
> >
> > struct tcpc_dev tcpc;
> > struct tcpci_data *data;
> > @@ -700,7 +701,10 @@ static int tcpci_init(struct tcpc_dev *tcpc)
> >
> > tcpci->alert_mask = reg;
> >
> > - return tcpci_write16(tcpci, TCPC_ALERT_MASK, reg);
> > + if (tcpci->set_alert_mask)
> > + ret = tcpci_write16(tcpci, TCPC_ALERT_MASK, reg);
> > +
> > + return ret;
> > }
> >
> > irqreturn_t tcpci_irq(struct tcpci *tcpci)
> > @@ -931,12 +935,20 @@ static int tcpci_probe(struct i2c_client *client)
> > _tcpci_irq,
> > IRQF_SHARED | IRQF_ONESHOT,
> > dev_name(&client->dev), chip);
> > - if (err < 0) {
> > - tcpci_unregister_port(chip->tcpci);
> > - return err;
> > - }
> > + if (err < 0)
> > + goto unregister_port;
> >
> > + /* Enable the interrupt on chip at last */
> > + err = tcpci_write16(chip->tcpci, TCPC_ALERT_MASK, chip->tcpci->alert_mask);
> what's the content of alert_mask here?
tcpci_register_port()
tcpm_register_port()
tcpm_init()
tcpci_init()
tcpci->alert_mask = reg;
After tcpci_register_port() completed, alert_mask is assigned a specific value.
For example:
reg = TCPC_ALERT_TX_SUCCESS | TCPC_ALERT_TX_FAILED |
TCPC_ALERT_TX_DISCARDED | TCPC_ALERT_RX_STATUS |
TCPC_ALERT_RX_HARD_RST | TCPC_ALERT_CC_STATUS;
>
> I am not fully understanding why this flag is needed, can't we just ensure
> that within probe the alert mask is set to 0, after probe return with
> success we have the interrupt handler enabled and we can just write the
> alert mask unconditionally.
I wrongly thought ALERT_MASK is firstly reset and set again in tcpci_init().
Actually it's not reset, so the flag is not needed. I'll change it later.
Thanks,
Xu Yang
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH v2 2/2] usb: typec: tcpci: write ALERT_MASK after devm_request_threaded_irq()
2024-12-17 8:54 ` Xu Yang
@ 2024-12-17 9:20 ` Francesco Dolcini
0 siblings, 0 replies; 5+ messages in thread
From: Francesco Dolcini @ 2024-12-17 9:20 UTC (permalink / raw)
To: Xu Yang
Cc: Francesco Dolcini, heikki.krogerus, gregkh, andre.draszik,
rdbabiera, m.felsch, dan.carpenter, emanuele.ghidoli,
parth.pancholi, francesco.dolcini, u.kleine-koenig, linux-usb,
imx, jun.li
On Tue, Dec 17, 2024 at 04:54:07PM +0800, Xu Yang wrote:
> On Mon, Dec 16, 2024 at 07:55:40PM +0100, Francesco Dolcini wrote:
> > On Thu, Dec 12, 2024 at 08:24:09PM +0800, Xu Yang wrote:
> > > With edge irq support, the ALERT event may be missed currently. The reason
> > > is that ALERT_MASK register is written before devm_request_threaded_irq().
> > > If ALERT event happens in this time gap, it will be missed and ALERT line
> > > will not recover to high level. However, we can't meet this issue with
> > > level irq. To avoid the issue, this will add a flag set_alert_mask. So
> > > ALERT_MASK can be written after devm_request_threaded_irq() is called. The
> > > behavior of tcpm_init() keeps unchanged.
> > >
> > > Fixes: 77e85107a771 ("usb: typec: tcpci: support edge irq")
> > > Cc: stable@vger.kernel.org
> > > Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
> >
> > I wonder if this should be squashed together with the first commit,
> > given you re-introduce an issue with the previous commit.
>
> No. One patch normally should do one thing. To support edge irq, commit
> 77e85107a771 cause NULL ponter issue so path 1 fix it, it also didn't
> handle irq or alert_mask correctly, then patch 2 is needed.
Sure. And you also want your commit to be bi-sectable, your first patch
introduce a bug to fix another one, and than you fix it in the second one.
In any case, Greg will tell if he wants something different here or not.
Francesco
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2024-12-17 9:20 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-12-12 12:24 [PATCH v2 1/2] usb: typec: tcpci: fix NULL pointer issue on shared irq case Xu Yang
2024-12-12 12:24 ` [PATCH v2 2/2] usb: typec: tcpci: write ALERT_MASK after devm_request_threaded_irq() Xu Yang
2024-12-16 18:55 ` Francesco Dolcini
2024-12-17 8:54 ` Xu Yang
2024-12-17 9:20 ` Francesco Dolcini
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox