Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

soc: aspeed: lpc-snoop: Don't disable channels that aren't enabled

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>

+11
+11
drivers/soc/aspeed/aspeed-lpc-snoop.c
··· 58 58 }; 59 59 60 60 struct aspeed_lpc_snoop_channel { 61 + bool enabled; 61 62 struct kfifo fifo; 62 63 wait_queue_head_t wq; 63 64 struct miscdevice miscdev; ··· 191 190 const struct aspeed_lpc_snoop_model_data *model_data = 192 191 of_device_get_match_data(dev); 193 192 193 + if (WARN_ON(lpc_snoop->chan[channel].enabled)) 194 + return -EBUSY; 195 + 194 196 init_waitqueue_head(&lpc_snoop->chan[channel].wq); 195 197 /* Create FIFO datastructure */ 196 198 rc = kfifo_alloc(&lpc_snoop->chan[channel].fifo, ··· 240 236 regmap_update_bits(lpc_snoop->regmap, HICRB, 241 237 hicrb_en, hicrb_en); 242 238 239 + lpc_snoop->chan[channel].enabled = true; 240 + 243 241 return 0; 244 242 245 243 err_misc_deregister: ··· 254 248 static void aspeed_lpc_disable_snoop(struct aspeed_lpc_snoop *lpc_snoop, 255 249 int channel) 256 250 { 251 + if (!lpc_snoop->chan[channel].enabled) 252 + return; 253 + 257 254 switch (channel) { 258 255 case 0: 259 256 regmap_update_bits(lpc_snoop->regmap, HICR5, ··· 272 263 return; 273 264 } 274 265 266 + lpc_snoop->chan[channel].enabled = false; 267 + /* Consider improving safety wrt concurrent reader(s) */ 275 268 misc_deregister(&lpc_snoop->chan[channel].miscdev); 276 269 kfifo_free(&lpc_snoop->chan[channel].fifo); 277 270 }