]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
nvme: apple: fix device reference counting
authorKeith Busch <kbusch@kernel.org>
Tue, 4 Jun 2024 18:59:04 +0000 (11:59 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 14 Aug 2024 13:34:06 +0000 (15:34 +0200)
[ Upstream commit b9ecbfa45516182cd062fecd286db7907ba84210 ]

Drivers must call nvme_uninit_ctrl after a successful nvme_init_ctrl.
Split the allocation side out to make the error handling boundary easier
to navigate. The apple driver had been doing this wrong, leaking the
controller device memory on a tagset failure.

Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>
Signed-off-by: Keith Busch <kbusch@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/nvme/host/apple.c

index 0cfa39361d3b60598612bd4df2147a9657c1f30d..25ecc1a005c5a78779f520dff753bfddc491ea5a 100644 (file)
@@ -1388,7 +1388,7 @@ static void devm_apple_nvme_mempool_destroy(void *data)
        mempool_destroy(data);
 }
 
-static int apple_nvme_probe(struct platform_device *pdev)
+static struct apple_nvme *apple_nvme_alloc(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct apple_nvme *anv;
@@ -1396,7 +1396,7 @@ static int apple_nvme_probe(struct platform_device *pdev)
 
        anv = devm_kzalloc(dev, sizeof(*anv), GFP_KERNEL);
        if (!anv)
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
 
        anv->dev = get_device(dev);
        anv->adminq.is_adminq = true;
@@ -1516,10 +1516,26 @@ static int apple_nvme_probe(struct platform_device *pdev)
                goto put_dev;
        }
 
+       return anv;
+put_dev:
+       put_device(anv->dev);
+       return ERR_PTR(ret);
+}
+
+static int apple_nvme_probe(struct platform_device *pdev)
+{
+       struct apple_nvme *anv;
+       int ret;
+
+       anv = apple_nvme_alloc(pdev);
+       if (IS_ERR(anv))
+               return PTR_ERR(anv);
+
        anv->ctrl.admin_q = blk_mq_alloc_queue(&anv->admin_tagset, NULL, NULL);
        if (IS_ERR(anv->ctrl.admin_q)) {
                ret = -ENOMEM;
-               goto put_dev;
+               anv->ctrl.admin_q = NULL;
+               goto out_uninit_ctrl;
        }
 
        nvme_reset_ctrl(&anv->ctrl);
@@ -1527,8 +1543,9 @@ static int apple_nvme_probe(struct platform_device *pdev)
 
        return 0;
 
-put_dev:
-       put_device(anv->dev);
+out_uninit_ctrl:
+       nvme_uninit_ctrl(&anv->ctrl);
+       nvme_put_ctrl(&anv->ctrl);
        return ret;
 }