Tasklets have long been deprecated as being too heavy on the system by running in irq context - and this is not a performance critical path. If a higher priority process wants to run, it must wait for the tasklet to finish before doing so. A more suitable equivalent is to converted to threaded irq instead and do the ack sequence in task context. Cc: Kashyap Desai <kashyap.desai@xxxxxxxxxxxx> Cc: Sumit Saxena <sumit.saxena@xxxxxxxxxxxx> Cc: Shivasharan S <shivasharan.srikanteshwara@xxxxxxxxxxxx> Cc: megaraidlinux.pdl@xxxxxxxxxxxx Signed-off-by: Davidlohr Bueso <dave@xxxxxxxxxxxx> --- drivers/scsi/megaraid/mega_common.h | 2 -- drivers/scsi/megaraid/megaraid_mbox.c | 52 ++++++++++----------------- 2 files changed, 19 insertions(+), 35 deletions(-) diff --git a/drivers/scsi/megaraid/mega_common.h b/drivers/scsi/megaraid/mega_common.h index 2ad0aa2f837d..3e56f74061b4 100644 --- a/drivers/scsi/megaraid/mega_common.h +++ b/drivers/scsi/megaraid/mega_common.h @@ -95,7 +95,6 @@ typedef struct { /** * struct adapter_t - driver's initialization structure - * @aram dpc_h : tasklet handle * @pdev : pci configuration pointer for kernel * @host : pointer to host structure of mid-layer * @lock : synchronization lock for mid-layer and driver @@ -149,7 +148,6 @@ typedef struct { #define VERSION_SIZE 16 typedef struct { - struct tasklet_struct dpc_h; struct pci_dev *pdev; struct Scsi_Host *host; spinlock_t lock; diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index 2a339d4a7e9d..b76f67887592 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c @@ -118,8 +118,7 @@ static void megaraid_mbox_prepare_epthru(adapter_t *, scb_t *, struct scsi_cmnd *); static irqreturn_t megaraid_isr(int, void *); - -static void megaraid_mbox_dpc(unsigned long); +static irqreturn_t megaraid_mbox_dpc(int, void *); static ssize_t megaraid_mbox_app_hndl_show(struct device *, struct device_attribute *attr, char *); static ssize_t megaraid_mbox_ld_show(struct device *, struct device_attribute *attr, char *); @@ -764,9 +763,8 @@ megaraid_init_mbox(adapter_t *adapter) */ /* request IRQ and register the interrupt service routine */ - if (request_irq(adapter->irq, megaraid_isr, IRQF_SHARED, "megaraid", - adapter)) { - + if (request_threaded_irq(adapter->irq, megaraid_isr, megaraid_mbox_dpc, + IRQF_SHARED, "megaraid", adapter)) { con_log(CL_ANN, (KERN_WARNING "megaraid: Couldn't register IRQ %d!\n", adapter->irq)); goto out_alloc_cmds; @@ -879,10 +877,6 @@ megaraid_init_mbox(adapter_t *adapter) } } - // setup tasklet for DPC - tasklet_init(&adapter->dpc_h, megaraid_mbox_dpc, - (unsigned long)adapter); - con_log(CL_DLEVEL1, (KERN_INFO "megaraid mbox hba successfully initialized\n")); @@ -917,8 +911,6 @@ megaraid_fini_mbox(adapter_t *adapter) // flush all caches megaraid_mbox_flush_cache(adapter); - tasklet_kill(&adapter->dpc_h); - megaraid_sysfs_free_resources(adapter); megaraid_free_cmd_packets(adapter); @@ -2027,7 +2019,7 @@ megaraid_mbox_prepare_epthru(adapter_t *adapter, scb_t *scb, * * Returns: 1 if the interrupt is valid, 0 otherwise */ -static int +static irqreturn_t megaraid_ack_sequence(adapter_t *adapter) { mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); @@ -2036,7 +2028,7 @@ megaraid_ack_sequence(adapter_t *adapter) uint8_t nstatus; uint8_t completed[MBOX_MAX_FIRMWARE_STATUS]; struct list_head clist; - int handled; + int ret = IRQ_NONE; uint32_t dword; unsigned long flags; int i, j; @@ -2048,7 +2040,6 @@ megaraid_ack_sequence(adapter_t *adapter) INIT_LIST_HEAD(&clist); // loop till F/W has more commands for us to complete - handled = 0; spin_lock_irqsave(MAILBOX_LOCK(raid_dev), flags); do { /* @@ -2056,9 +2047,10 @@ megaraid_ack_sequence(adapter_t *adapter) * interrupt line low. */ dword = RDOUTDOOR(raid_dev); - if (dword != 0x10001234) break; + if (dword != 0x10001234) + break; - handled = 1; + ret = IRQ_WAKE_THREAD; WROUTDOOR(raid_dev, 0x10001234); @@ -2124,12 +2116,7 @@ megaraid_ack_sequence(adapter_t *adapter) spin_unlock_irqrestore(COMPLETED_LIST_LOCK(adapter), flags); - - // schedule the DPC if there is some work for it - if (handled) - tasklet_schedule(&adapter->dpc_h); - - return handled; + return ret; } @@ -2144,29 +2131,27 @@ static irqreturn_t megaraid_isr(int irq, void *devp) { adapter_t *adapter = devp; - int handled; + int ret; - handled = megaraid_ack_sequence(adapter); + ret = megaraid_ack_sequence(adapter); /* Loop through any pending requests */ if (!adapter->quiescent) { megaraid_mbox_runpendq(adapter, NULL); } - return IRQ_RETVAL(handled); + return ret; } /** - * megaraid_mbox_dpc - the tasklet to complete the commands from completed list - * @devp : pointer to HBA soft state + * megaraid_mbox_dpc - complete the commands from completed list * * Pick up the commands from the completed list and send back to the owners. * This is a reentrant function and does not assume any locks are held while - * it is being called. + * it is being called. Runs in process context. */ -static void -megaraid_mbox_dpc(unsigned long devp) +static irqreturn_t megaraid_mbox_dpc(int irq, void *devp) { adapter_t *adapter = (adapter_t *)devp; mraid_device_t *raid_dev; @@ -2188,7 +2173,8 @@ megaraid_mbox_dpc(unsigned long devp) uioc_t *kioc; - if (!adapter) return; + if (!adapter) + goto done; raid_dev = ADAP2RAIDDEV(adapter); @@ -2361,8 +2347,8 @@ megaraid_mbox_dpc(unsigned long devp) // send the scsi packet back to kernel scsi_done(scp); } - - return; +done: + return IRQ_HANDLED; } -- 2.36.1