From nobody Fri Sep 12 02:32:13 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 72545C05027 for ; Tue, 14 Feb 2023 12:57:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232117AbjBNM5f (ORCPT ); Tue, 14 Feb 2023 07:57:35 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41618 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230263AbjBNM5d (ORCPT ); Tue, 14 Feb 2023 07:57:33 -0500 Received: from szxga02-in.huawei.com (szxga02-in.huawei.com [45.249.212.188]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 114192203F for ; Tue, 14 Feb 2023 04:57:31 -0800 (PST) Received: from canpemm500005.china.huawei.com (unknown [172.30.72.54]) by szxga02-in.huawei.com (SkyGuard) with ESMTP id 4PGLmH3FXPzJsN4; Tue, 14 Feb 2023 20:55:43 +0800 (CST) Received: from localhost.huawei.com (10.175.126.31) by canpemm500005.china.huawei.com (7.192.104.229) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.17; Tue, 14 Feb 2023 20:57:29 +0800 From: Su Weifeng To: , CC: , , , , , Weifeng Su Subject: [PATCH] uio:uio_pci_generic:Don't clear master bit when the process does not exit Date: Tue, 14 Feb 2023 21:21:57 +0800 Message-ID: <20230214132157.472753-1-suweifeng1@huawei.com> X-Mailer: git-send-email 2.33.0 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Originating-IP: [10.175.126.31] X-ClientProxiedBy: dggems706-chm.china.huawei.com (10.3.19.183) To canpemm500005.china.huawei.com (7.192.104.229) X-CFilter-Loop: Reflected Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Weifeng Su The /dev/uioX device is used by multiple processes. The current behavior is to clear the master bit when a process exits. This affects other processes that use the device, resulting in command suspension and timeout. This behavior cannot be sensed by the process itself. The solution is to add the reference counting. The reference count is self-incremented and self-decremented each time when the device open and close. The master bit is cleared only when the last process exited. Signed-off-by: Weifeng Su --- drivers/uio/uio_pci_generic.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/uio/uio_pci_generic.c b/drivers/uio/uio_pci_generic.c index e03f9b532..d36d3e08e 100644 --- a/drivers/uio/uio_pci_generic.c +++ b/drivers/uio/uio_pci_generic.c @@ -31,6 +31,7 @@ struct uio_pci_generic_dev { struct uio_info info; struct pci_dev *pdev; + refcount_t dev_refc; }; =20 static inline struct uio_pci_generic_dev * @@ -39,10 +40,22 @@ to_uio_pci_generic_dev(struct uio_info *info) return container_of(info, struct uio_pci_generic_dev, info); } =20 +static int open(struct uio_info *info, struct inode *inode) +{ + struct uio_pci_generic_dev *gdev =3D to_uio_pci_generic_dev(info); + + if (gdev) + refcount_inc(&gdev->dev_refc); + return 0; +} + static int release(struct uio_info *info, struct inode *inode) { struct uio_pci_generic_dev *gdev =3D to_uio_pci_generic_dev(info); =20 + if (gdev && refcount_dec_not_one(&gdev->dev_refc)) + return 0; + /* * This driver is insecure when used with devices doing DMA, but some =C2=A0* people (mis)use it with such devices. @@ -51,7 +64,8 @@ static int release(struct uio_info *info, struct inode *i= node) =C2=A0* Note that there's a non-zero chance doing this will wedge the dev= ice =C2=A0* at least until reset. */ - pci_clear_master(gdev->pdev); + if (refcount_read(&gdev->dev_refc) =3D=3D 1) + pci_clear_master(gdev->pdev); return 0; } =20 @@ -93,7 +107,9 @@ static int probe(struct pci_dev *pdev, gdev->info.name =3D "uio_pci_generic"; gdev->info.version =3D DRIVER_VERSION; gdev->info.release =3D release; + gdev->info.open =3D open; gdev->pdev =3D pdev; + refcount_set(&gdev->dev_refc, 1); if (pdev->irq && (pdev->irq !=3D IRQ_NOTCONNECTED)) { gdev->info.irq =3D pdev->irq; gdev->info.irq_flags =3D IRQF_SHARED; --=20 2.33.0