]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
soc: aspeed: lpc-snoop: Don't disable channels that aren't enabled
authorAndrew Jeffery <andrew@codeconstruct.com.au>
Mon, 16 Jun 2025 13:13:39 +0000 (22:43 +0930)
committerAndrew Jeffery <andrew@codeconstruct.com.au>
Wed, 2 Jul 2025 01:35:20 +0000 (11:05 +0930)
Mitigate e.g. the following:

    # echo 1e789080.lpc-snoop > /sys/bus/platform/drivers/aspeed-lpc-snoop/unbind
    ...
    [  120.363594] Unable to handle kernel NULL pointer dereference at virtual address 00000004 when write
    [  120.373866] [00000004] *pgd=00000000
    [  120.377910] Internal error: Oops: 805 [#1] SMP ARM
    [  120.383306] CPU: 1 UID: 0 PID: 315 Comm: sh Not tainted 6.15.0-rc1-00009-g926217bc7d7d-dirty #20 NONE
    ...
    [  120.679543] Call trace:
    [  120.679559]  misc_deregister from aspeed_lpc_snoop_remove+0x84/0xac
    [  120.692462]  aspeed_lpc_snoop_remove from platform_remove+0x28/0x38
    [  120.700996]  platform_remove from device_release_driver_internal+0x188/0x200
    ...

Fixes: 9f4f9ae81d0a ("drivers/misc: add Aspeed LPC snoop driver")
Cc: stable@vger.kernel.org
Cc: Jean Delvare <jdelvare@suse.de>
Acked-by: Jean Delvare <jdelvare@suse.de>
Link: https://patch.msgid.link/20250616-aspeed-lpc-snoop-fixes-v2-2-3cdd59c934d3@codeconstruct.com.au
Signed-off-by: Andrew Jeffery <andrew@codeconstruct.com.au>
drivers/soc/aspeed/aspeed-lpc-snoop.c

index 59c18afa649cd672f54f947066f468f2a78c0d5d..fc3a2c41cc10739f5f70ded7ac02baab6468d652 100644 (file)
@@ -58,6 +58,7 @@ struct aspeed_lpc_snoop_model_data {
 };
 
 struct aspeed_lpc_snoop_channel {
+       bool enabled;
        struct kfifo            fifo;
        wait_queue_head_t       wq;
        struct miscdevice       miscdev;
@@ -190,6 +191,9 @@ static int aspeed_lpc_enable_snoop(struct aspeed_lpc_snoop *lpc_snoop,
        const struct aspeed_lpc_snoop_model_data *model_data =
                of_device_get_match_data(dev);
 
+       if (WARN_ON(lpc_snoop->chan[channel].enabled))
+               return -EBUSY;
+
        init_waitqueue_head(&lpc_snoop->chan[channel].wq);
        /* Create FIFO datastructure */
        rc = kfifo_alloc(&lpc_snoop->chan[channel].fifo,
@@ -236,6 +240,8 @@ static int aspeed_lpc_enable_snoop(struct aspeed_lpc_snoop *lpc_snoop,
                regmap_update_bits(lpc_snoop->regmap, HICRB,
                                hicrb_en, hicrb_en);
 
+       lpc_snoop->chan[channel].enabled = true;
+
        return 0;
 
 err_misc_deregister:
@@ -248,6 +254,9 @@ err_free_fifo:
 static void aspeed_lpc_disable_snoop(struct aspeed_lpc_snoop *lpc_snoop,
                                     int channel)
 {
+       if (!lpc_snoop->chan[channel].enabled)
+               return;
+
        switch (channel) {
        case 0:
                regmap_update_bits(lpc_snoop->regmap, HICR5,
@@ -263,6 +272,8 @@ static void aspeed_lpc_disable_snoop(struct aspeed_lpc_snoop *lpc_snoop,
                return;
        }
 
+       lpc_snoop->chan[channel].enabled = false;
+       /* Consider improving safety wrt concurrent reader(s) */
        misc_deregister(&lpc_snoop->chan[channel].miscdev);
        kfifo_free(&lpc_snoop->chan[channel].fifo);
 }