Skip to content

Commit 68be6c4

Browse files
ausyskingregkh
authored andcommitted
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: 7704e6b ("mei: hook mei_device on class device") Signed-off-by: Alexander Usyskin <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 3ebcd34 commit 68be6c4

File tree

2 files changed

+11
-7
lines changed

2 files changed

+11
-7
lines changed

drivers/misc/mei/gsc-me.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,13 +150,13 @@ static void mei_gsc_remove(struct auxiliary_device *aux_dev)
150150
if (mei_me_hw_use_polling(hw))
151151
kthread_stop(hw->polling_thread);
152152

153-
mei_deregister(dev);
154-
155153
pm_runtime_disable(&aux_dev->dev);
156154

157155
mei_disable_interrupts(dev);
158156
if (!mei_me_hw_use_polling(hw))
159157
devm_free_irq(&aux_dev->dev, hw->irq, dev);
158+
159+
mei_deregister(dev);
160160
}
161161

162162
static int __maybe_unused mei_gsc_pm_suspend(struct device *device)

drivers/misc/mei/main.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1208,12 +1208,12 @@ static int mei_minor_get(struct mei_device *dev)
12081208
/**
12091209
* mei_minor_free - mark device minor number as free
12101210
*
1211-
* @dev: device pointer
1211+
* @minor: minor number to free
12121212
*/
1213-
static void mei_minor_free(struct mei_device *dev)
1213+
static void mei_minor_free(int minor)
12141214
{
12151215
mutex_lock(&mei_minor_lock);
1216-
idr_remove(&mei_idr, dev->minor);
1216+
idr_remove(&mei_idr, minor);
12171217
mutex_unlock(&mei_minor_lock);
12181218
}
12191219

@@ -1225,11 +1225,14 @@ static void mei_device_release(struct device *dev)
12251225
int mei_register(struct mei_device *dev, struct device *parent)
12261226
{
12271227
int ret, devno;
1228+
int minor;
12281229

12291230
ret = mei_minor_get(dev);
12301231
if (ret < 0)
12311232
return ret;
12321233

1234+
minor = dev->minor;
1235+
12331236
/* Fill in the data structures */
12341237
devno = MKDEV(MAJOR(mei_devt), dev->minor);
12351238

@@ -1279,14 +1282,15 @@ int mei_register(struct mei_device *dev, struct device *parent)
12791282
err_del_cdev:
12801283
cdev_del(dev->cdev);
12811284
err:
1282-
mei_minor_free(dev);
1285+
mei_minor_free(minor);
12831286
return ret;
12841287
}
12851288
EXPORT_SYMBOL_GPL(mei_register);
12861289

12871290
void mei_deregister(struct mei_device *dev)
12881291
{
12891292
int devno;
1293+
int minor = dev->minor;
12901294

12911295
devno = dev->cdev->dev;
12921296
cdev_del(dev->cdev);
@@ -1295,7 +1299,7 @@ void mei_deregister(struct mei_device *dev)
12951299

12961300
device_destroy(&mei_class, devno);
12971301

1298-
mei_minor_free(dev);
1302+
mei_minor_free(minor);
12991303
}
13001304
EXPORT_SYMBOL_GPL(mei_deregister);
13011305

0 commit comments

Comments
 (0)