From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-eopbgr720090.outbound.protection.outlook.com ([40.107.72.90]:59680 "EHLO NAM05-CO1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728317AbeIOGst (ORCPT ); Sat, 15 Sep 2018 02:48:49 -0400 From: Sasha Levin To: "stable@vger.kernel.org" , "linux-kernel@vger.kernel.org" CC: Hans de Goede , Carlo Caione , Mark Brown , Sasha Levin Subject: [PATCH AUTOSEL 4.18 76/92] ASoC: rt5651: Fix workqueue cancel vs irq free race on remove Date: Sat, 15 Sep 2018 01:30:43 +0000 Message-ID: <20180915012944.179481-75-alexander.levin@microsoft.com> References: <20180915012944.179481-1-alexander.levin@microsoft.com> In-Reply-To: <20180915012944.179481-1-alexander.levin@microsoft.com> Content-Language: en-US Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Sender: stable-owner@vger.kernel.org List-ID: From: Hans de Goede [ Upstream commit 8d2d7bcdc1645dc243f7735278675b083c0e506c ] On removal we must free the IRQ *before* cancelling the jack-detect work, so that the jack-detect work cannot be rescheduled by the IRQ. Before this commit we were cancelling the jack-detect work from the driver remove callback, while relying on devm to free the IRQ, which happens after the remove callback. This is the wrong order. This commit uses a devm-action to register a devm callback which cancels the work, before requesting the IRQ (devm tears things down in reverse order). This also allows us to remove the now empty remove driver callback. Cc: Carlo Caione Signed-off-by: Hans de Goede Signed-off-by: Mark Brown Signed-off-by: Sasha Levin --- sound/soc/codecs/rt5651.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c index 6b5669f3e85d..39d2c67cd064 100644 --- a/sound/soc/codecs/rt5651.c +++ b/sound/soc/codecs/rt5651.c @@ -1696,6 +1696,13 @@ static irqreturn_t rt5651_irq(int irq, void *data) return IRQ_HANDLED; } =20 +static void rt5651_cancel_work(void *data) +{ + struct rt5651_priv *rt5651 =3D data; + + cancel_work_sync(&rt5651->jack_detect_work); +} + static int rt5651_set_jack(struct snd_soc_component *component, struct snd_soc_jack *hp_jack, void *data) { @@ -2036,6 +2043,11 @@ static int rt5651_i2c_probe(struct i2c_client *i2c, =20 INIT_WORK(&rt5651->jack_detect_work, rt5651_jack_detect_work); =20 + /* Make sure work is stopped on probe-error / remove */ + ret =3D devm_add_action_or_reset(&i2c->dev, rt5651_cancel_work, rt5651); + if (ret) + return ret; + ret =3D devm_snd_soc_register_component(&i2c->dev, &soc_component_dev_rt5651, rt5651_dai, ARRAY_SIZE(rt5651_dai)); @@ -2043,15 +2055,6 @@ static int rt5651_i2c_probe(struct i2c_client *i2c, return ret; } =20 -static int rt5651_i2c_remove(struct i2c_client *i2c) -{ - struct rt5651_priv *rt5651 =3D i2c_get_clientdata(i2c); - - cancel_work_sync(&rt5651->jack_detect_work); - - return 0; -} - static struct i2c_driver rt5651_i2c_driver =3D { .driver =3D { .name =3D "rt5651", @@ -2059,7 +2062,6 @@ static struct i2c_driver rt5651_i2c_driver =3D { .of_match_table =3D of_match_ptr(rt5651_of_match), }, .probe =3D rt5651_i2c_probe, - .remove =3D rt5651_i2c_remove, .id_table =3D rt5651_i2c_id, }; module_i2c_driver(rt5651_i2c_driver); --=20 2.17.1