The only generic interface to execute asynchronously in the BH context is tasklet; however, it's marked deprecated and has some design flaws. To replace tasklets, BH workqueue support was recently added. A BH workqueue behaves similarly to regular workqueues except that the queued work items are executed in the BH context. This patch converts drivers/pci/pci-hyperv.c from tasklet to BH workqueue. Based on the work done by Tejun Heo <tj@xxxxxxxxxx> Branch:https://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git for-6.10 Signed-off-by: Allen Pais <allen.lkml@xxxxxxxxx> --- drivers/pci/controller/pci-hyperv.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c index 5992280e8110..2823fd50a69c 100644 --- a/drivers/pci/controller/pci-hyperv.c +++ b/drivers/pci/controller/pci-hyperv.c @@ -50,6 +50,7 @@ #include <linux/irqdomain.h> #include <linux/acpi.h> #include <linux/sizes.h> +#include <linux/workqueue.h> #include <asm/mshyperv.h> /* @@ -2000,7 +2001,7 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) udelay(100); } - tasklet_enable(&channel->callback_event); + enable_and_queue_work(system_bh_wq, &channel->callback_event); if (comp.comp_pkt.completion_status < 0) { dev_err(&hbus->hdev->device, @@ -2026,7 +2027,7 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) return; enable_tasklet: - tasklet_enable(&channel->callback_event); + enable_and_queue_work(system_bh_wq, &channel->callback_event); /* * The completion packet on the stack becomes invalid after 'return'; * remove the ID from the VMbus requestor if the identifier is still @@ -3890,9 +3891,9 @@ static void hv_pci_remove(struct hv_device *hdev) hbus = hv_get_drvdata(hdev); if (hbus->state == hv_pcibus_installed) { - tasklet_disable(&hdev->channel->callback_event); + disable_work_sync(&hdev->channel->callback_event); hbus->state = hv_pcibus_removing; - tasklet_enable(&hdev->channel->callback_event); + enable_and_queue_work(system_bh_wq, &hdev->channel->callback_event); destroy_workqueue(hbus->wq); hbus->wq = NULL; /* @@ -3948,14 +3949,14 @@ static int hv_pci_suspend(struct hv_device *hdev) * it knows that no new work item can be scheduled, and then it flushes * hbus->wq and safely closes the vmbus channel. */ - tasklet_disable(&hdev->channel->callback_event); + disable_work_sync(&hdev->channel->callback_event); /* Change the hbus state to prevent new work items. */ old_state = hbus->state; if (hbus->state == hv_pcibus_installed) hbus->state = hv_pcibus_removing; - tasklet_enable(&hdev->channel->callback_event); + enable_and_queue_work(system_bh_wq, &hdev->channel->callback_event); if (old_state != hv_pcibus_installed) return -EINVAL; -- 2.17.1