Skip to content

Commit 33f9cff

Browse files
virtuosogregkh
authored andcommitted
intel_th: Fix a deadlock in modprobing
commit a36aa80f3cb2540fb1dbad6240852de4365a2e82 upstream. Driver initialization tries to request a hub (GTH) driver module from its probe callback, resulting in a deadlock. This patch solves the problem by adding a deferred work for requesting the hub module. Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent c800964 commit 33f9cff

2 files changed

Lines changed: 37 additions & 1 deletion

File tree

drivers/hwtracing/intel_th/core.c

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,38 @@ static struct intel_th_subdevice {
419419
},
420420
};
421421

422+
#ifdef CONFIG_MODULES
423+
static void __intel_th_request_hub_module(struct work_struct *work)
424+
{
425+
struct intel_th *th = container_of(work, struct intel_th,
426+
request_module_work);
427+
428+
request_module("intel_th_%s", th->hub->name);
429+
}
430+
431+
static int intel_th_request_hub_module(struct intel_th *th)
432+
{
433+
INIT_WORK(&th->request_module_work, __intel_th_request_hub_module);
434+
schedule_work(&th->request_module_work);
435+
436+
return 0;
437+
}
438+
439+
static void intel_th_request_hub_module_flush(struct intel_th *th)
440+
{
441+
flush_work(&th->request_module_work);
442+
}
443+
#else
444+
static inline int intel_th_request_hub_module(struct intel_th *th)
445+
{
446+
return -EINVAL;
447+
}
448+
449+
static inline void intel_th_request_hub_module_flush(struct intel_th *th)
450+
{
451+
}
452+
#endif /* CONFIG_MODULES */
453+
422454
static int intel_th_populate(struct intel_th *th, struct resource *devres,
423455
unsigned int ndevres, int irq)
424456
{
@@ -488,7 +520,7 @@ static int intel_th_populate(struct intel_th *th, struct resource *devres,
488520
/* need switch driver to be loaded to enumerate the rest */
489521
if (subdev->type == INTEL_TH_SWITCH && !req) {
490522
th->hub = thdev;
491-
err = request_module("intel_th_%s", subdev->name);
523+
err = intel_th_request_hub_module(th);
492524
if (!err)
493525
req++;
494526
}
@@ -603,6 +635,7 @@ void intel_th_free(struct intel_th *th)
603635
{
604636
int i;
605637

638+
intel_th_request_hub_module_flush(th);
606639
for (i = 0; i < TH_SUBDEVICE_MAX; i++)
607640
if (th->thdev[i] != th->hub)
608641
intel_th_device_remove(th->thdev[i]);

drivers/hwtracing/intel_th/intel_th.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,9 @@ struct intel_th {
197197

198198
int id;
199199
int major;
200+
#ifdef CONFIG_MODULES
201+
struct work_struct request_module_work;
202+
#endif /* CONFIG_MODULES */
200203
#ifdef CONFIG_INTEL_TH_DEBUG
201204
struct dentry *dbg;
202205
#endif

0 commit comments

Comments
 (0)