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

Configure Feed

Select the types of activity you want to include in your feed.

mei: gsc: fix remove operations order

The mei disconnect should be the last operation in remove flow.
Otherwise the device is used after destruction.
Fix minor free flow that happens after device destruction too.

The fault leads to the following oops in Intel Gfx CI:

<4>[ 267.871331] Oops: general protection fault, probably for non-canonical address 0x6b6b6b6b6b6b6bcb: 0000 [#1] SMP NOPTI
...
<4>[ 267.871410] RIP: 0010:mei_gsc_remove+0x44/0x90 [mei_gsc]
...
<4>[ 267.871555] Call Trace:
<4>[ 267.871562] <TASK>
<4>[ 267.871570] auxiliary_bus_remove+0x1b/0x30
<4>[ 267.871589] device_remove+0x43/0x80
<4>[ 267.871604] device_release_driver_internal+0x215/0x280
<4>[ 267.871619] device_release_driver+0x12/0x20
<4>[ 267.871630] bus_remove_device+0xdc/0x150
<4>[ 267.871645] device_del+0x15f/0x3b0
<4>[ 267.871656] ? bus_unregister_notifier+0x37/0x50
<4>[ 267.871672] gsc_destroy_one.isra.0+0x44/0x210 [i915]
<4>[ 267.872295] intel_gsc_fini+0x28/0x50 [i915]
<4>[ 267.872860] intel_gt_driver_unregister+0x2c/0x80 [i915]
<4>[ 267.873300] i915_driver_remove+0x6e/0x150 [i915]
<4>[ 267.873694] i915_pci_remove+0x1e/0x40 [i915]
<4>[ 267.874095] pci_device_remove+0x3e/0xb0
<4>[ 267.874111] device_remove+0x43/0x80
<4>[ 267.874126] device_release_driver_internal+0x215/0x280
<4>[ 267.874137] ? bus_find_device+0xa5/0xe0
<4>[ 267.874153] device_driver_detach+0x14/0x20
<4>[ 267.874164] unbind_store+0xac/0xc0
<4>[ 267.874178] drv_attr_store+0x21/0x50
<4>[ 267.874190] sysfs_kf_write+0x4a/0x80
<4>[ 267.874204] kernfs_fop_write_iter+0x188/0x240
<4>[ 267.874222] vfs_write+0x283/0x540
<4>[ 267.874241] ksys_write+0x6f/0xf0
<4>[ 267.874253] __x64_sys_write+0x19/0x30
<4>[ 267.874264] x64_sys_call+0x79/0x26a0
<4>[ 267.874277] do_syscall_64+0x93/0xd50
<4>[ 267.874291] ? do_syscall_64+0x1a2/0xd50
<4>[ 267.874301] ? do_syscall_64+0x1a2/0xd50
<4>[ 267.874313] ? do_syscall_64+0x1a2/0xd50
<4>[ 267.874324] ? clear_bhb_loop+0x30/0x80
<4>[ 267.874336] ? clear_bhb_loop+0x30/0x80
<4>[ 267.874349] entry_SYSCALL_64_after_hwframe+0x76/0x7e

Fixes: 7704e6be4ed2 ("mei: hook mei_device on class device")
Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
Link: https://lore.kernel.org/r/20250915124554.2263330-1-alexander.usyskin@intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Alexander Usyskin and committed by
Greg Kroah-Hartman
68be6c43 3ebcd346

+11 -7
+2 -2
drivers/misc/mei/gsc-me.c
··· 150 150 if (mei_me_hw_use_polling(hw)) 151 151 kthread_stop(hw->polling_thread); 152 152 153 - mei_deregister(dev); 154 - 155 153 pm_runtime_disable(&aux_dev->dev); 156 154 157 155 mei_disable_interrupts(dev); 158 156 if (!mei_me_hw_use_polling(hw)) 159 157 devm_free_irq(&aux_dev->dev, hw->irq, dev); 158 + 159 + mei_deregister(dev); 160 160 } 161 161 162 162 static int __maybe_unused mei_gsc_pm_suspend(struct device *device)
+9 -5
drivers/misc/mei/main.c
··· 1208 1208 /** 1209 1209 * mei_minor_free - mark device minor number as free 1210 1210 * 1211 - * @dev: device pointer 1211 + * @minor: minor number to free 1212 1212 */ 1213 - static void mei_minor_free(struct mei_device *dev) 1213 + static void mei_minor_free(int minor) 1214 1214 { 1215 1215 mutex_lock(&mei_minor_lock); 1216 - idr_remove(&mei_idr, dev->minor); 1216 + idr_remove(&mei_idr, minor); 1217 1217 mutex_unlock(&mei_minor_lock); 1218 1218 } 1219 1219 ··· 1225 1225 int mei_register(struct mei_device *dev, struct device *parent) 1226 1226 { 1227 1227 int ret, devno; 1228 + int minor; 1228 1229 1229 1230 ret = mei_minor_get(dev); 1230 1231 if (ret < 0) 1231 1232 return ret; 1233 + 1234 + minor = dev->minor; 1232 1235 1233 1236 /* Fill in the data structures */ 1234 1237 devno = MKDEV(MAJOR(mei_devt), dev->minor); ··· 1282 1279 err_del_cdev: 1283 1280 cdev_del(dev->cdev); 1284 1281 err: 1285 - mei_minor_free(dev); 1282 + mei_minor_free(minor); 1286 1283 return ret; 1287 1284 } 1288 1285 EXPORT_SYMBOL_GPL(mei_register); ··· 1290 1287 void mei_deregister(struct mei_device *dev) 1291 1288 { 1292 1289 int devno; 1290 + int minor = dev->minor; 1293 1291 1294 1292 devno = dev->cdev->dev; 1295 1293 cdev_del(dev->cdev); ··· 1299 1295 1300 1296 device_destroy(&mei_class, devno); 1301 1297 1302 - mei_minor_free(dev); 1298 + mei_minor_free(minor); 1303 1299 } 1304 1300 EXPORT_SYMBOL_GPL(mei_deregister); 1305 1301