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: 7704e6be4e ("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>
This commit is contained in:
Alexander Usyskin 2025-09-15 15:45:54 +03:00 committed by Greg Kroah-Hartman
parent 3ebcd3460c
commit 68be6c432c
2 changed files with 11 additions and 7 deletions

View File

@ -150,13 +150,13 @@ static void mei_gsc_remove(struct auxiliary_device *aux_dev)
if (mei_me_hw_use_polling(hw))
kthread_stop(hw->polling_thread);
mei_deregister(dev);
pm_runtime_disable(&aux_dev->dev);
mei_disable_interrupts(dev);
if (!mei_me_hw_use_polling(hw))
devm_free_irq(&aux_dev->dev, hw->irq, dev);
mei_deregister(dev);
}
static int __maybe_unused mei_gsc_pm_suspend(struct device *device)

View File

@ -1208,12 +1208,12 @@ static int mei_minor_get(struct mei_device *dev)
/**
* mei_minor_free - mark device minor number as free
*
* @dev: device pointer
* @minor: minor number to free
*/
static void mei_minor_free(struct mei_device *dev)
static void mei_minor_free(int minor)
{
mutex_lock(&mei_minor_lock);
idr_remove(&mei_idr, dev->minor);
idr_remove(&mei_idr, minor);
mutex_unlock(&mei_minor_lock);
}
@ -1225,11 +1225,14 @@ static void mei_device_release(struct device *dev)
int mei_register(struct mei_device *dev, struct device *parent)
{
int ret, devno;
int minor;
ret = mei_minor_get(dev);
if (ret < 0)
return ret;
minor = dev->minor;
/* Fill in the data structures */
devno = MKDEV(MAJOR(mei_devt), dev->minor);
@ -1279,7 +1282,7 @@ int mei_register(struct mei_device *dev, struct device *parent)
err_del_cdev:
cdev_del(dev->cdev);
err:
mei_minor_free(dev);
mei_minor_free(minor);
return ret;
}
EXPORT_SYMBOL_GPL(mei_register);
@ -1287,6 +1290,7 @@ EXPORT_SYMBOL_GPL(mei_register);
void mei_deregister(struct mei_device *dev)
{
int devno;
int minor = dev->minor;
devno = dev->cdev->dev;
cdev_del(dev->cdev);
@ -1295,7 +1299,7 @@ void mei_deregister(struct mei_device *dev)
device_destroy(&mei_class, devno);
mei_minor_free(dev);
mei_minor_free(minor);
}
EXPORT_SYMBOL_GPL(mei_deregister);