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.

mfd: ezx-pcap: Avoid rescheduling after destroying workqueue

Driver allocates workqueue and then registers additional interrupt
handler with devm interface. This means that device removal will not
use a reversed order, but first destroy workqueue and then, via devm
release handlers, free the interrupt.

The interrupt handler registered with devm does not directly
use/schedule work items on the workqueue and the remove() function
correctly removes other IRQs handlers, however the code mixing devm and
non-devm interfaces is difficult to analyze and read.

Make the code flow much more obvious by using devm interface for
allocating the workqueue, so it will be freed with the rest of devm
resources.

Change is not equivalent in the workqueue itself: use non-legacy API
which does not set (__WQ_LEGACY | WQ_MEM_RECLAIM). The workqueue is
used to update device registers, thus there is no point to run it for
memory reclaim.

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: https://patch.msgid.link/20260305-workqueue-devm-v2-9-66a38741c652@oss.qualcomm.com
Signed-off-by: Lee Jones <lee@kernel.org>

authored by

Krzysztof Kozlowski and committed by
Lee Jones
30eedf24 ef5a54c5

+2 -6
+2 -6
drivers/mfd/ezx-pcap.c
··· 375 375 /* cleanup irqchip */ 376 376 for (i = pcap->irq_base; i < (pcap->irq_base + PCAP_NIRQS); i++) 377 377 irq_set_chip_and_handler(i, NULL, NULL); 378 - 379 - destroy_workqueue(pcap->workqueue); 380 378 } 381 379 382 380 static int ezx_pcap_probe(struct spi_device *spi) ··· 409 411 410 412 /* setup irq */ 411 413 pcap->irq_base = pdata->irq_base; 412 - pcap->workqueue = create_singlethread_workqueue("pcapd"); 414 + pcap->workqueue = devm_alloc_ordered_workqueue(&spi->dev, "pcapd", 0); 413 415 if (!pcap->workqueue) 414 416 return -ENOMEM; 415 417 ··· 461 463 free_irqchip: 462 464 for (i = pcap->irq_base; i < (pcap->irq_base + PCAP_NIRQS); i++) 463 465 irq_set_chip_and_handler(i, NULL, NULL); 464 - /* destroy_workqueue: */ 465 - destroy_workqueue(pcap->workqueue); 466 - ret: 466 + 467 467 return ret; 468 468 } 469 469