]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
i2c: qcom-cci: Fix NULL pointer dereference in cci_remove()
authorVladimir Zapolskiy <vladimir.zapolskiy@linaro.org>
Fri, 15 May 2026 23:41:18 +0000 (02:41 +0300)
committerAndi Shyti <andi.shyti@kernel.org>
Mon, 8 Jun 2026 18:31:46 +0000 (20:31 +0200)
On all modern platforms Qualcomm CCI controller provides two I2C masters,
and on particular boards only one I2C master may be initialized, and in
such cases the device unbinding or driver removal causes a NULL pointer
dereference, because cci_halt() is called for all two I2C masters, but
a completion is initialized only for the single enabled master:

    % rmmod i2c-qcom-cci
    Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
    <snip>
    Call trace:
    __wait_for_common+0x194/0x1a8 (P)
    wait_for_completion_timeout+0x20/0x2c
    cci_remove+0xc4/0x138 [i2c_qcom_cci]
    platform_remove+0x20/0x30
    device_remove+0x4c/0x80
    device_release_driver_internal+0x1c8/0x224
    driver_detach+0x50/0x98
    bus_remove_driver+0x6c/0xbc
    driver_unregister+0x30/0x60
    platform_driver_unregister+0x14/0x20
    qcom_cci_driver_exit+0x18/0x1008 [i2c_qcom_cci]
    ....

Fixes: e517526195de ("i2c: Add Qualcomm CCI I2C driver")
Signed-off-by: Vladimir Zapolskiy <vladimir.zapolskiy@linaro.org>
Cc: <stable@vger.kernel.org> # v5.8+
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
Link: https://lore.kernel.org/r/20260515234121.1607425-2-vladimir.zapolskiy@linaro.org
drivers/i2c/busses/i2c-qcom-cci.c

index f3ccfbbc4bea25a66e120342afc2540d775989a8..01e440b6585dbb7ee31fa89afd6aee13ed5847d9 100644 (file)
@@ -660,8 +660,8 @@ static void cci_remove(struct platform_device *pdev)
                if (cci->master[i].cci) {
                        i2c_del_adapter(&cci->master[i].adap);
                        of_node_put(cci->master[i].adap.dev.of_node);
+                       cci_halt(cci, i);
                }
-               cci_halt(cci, i);
        }
 
        disable_irq(cci->irq);