return ccp_do_cmd(op, cr, ARRAY_SIZE(cr));
 }
 
+static void ccp_disable_queue_interrupts(struct ccp_device *ccp)
+{
+       iowrite32(0x00, ccp->io_regs + IRQ_MASK_REG);
+}
+
+static void ccp_enable_queue_interrupts(struct ccp_device *ccp)
+{
+       iowrite32(ccp->qim, ccp->io_regs + IRQ_MASK_REG);
+}
+
+static void ccp_irq_bh(unsigned long data)
+{
+       struct ccp_device *ccp = (struct ccp_device *)data;
+       struct ccp_cmd_queue *cmd_q;
+       u32 q_int, status;
+       unsigned int i;
+
+       status = ioread32(ccp->io_regs + IRQ_STATUS_REG);
+
+       for (i = 0; i < ccp->cmd_q_count; i++) {
+               cmd_q = &ccp->cmd_q[i];
+
+               q_int = status & (cmd_q->int_ok | cmd_q->int_err);
+               if (q_int) {
+                       cmd_q->int_status = status;
+                       cmd_q->q_status = ioread32(cmd_q->reg_status);
+                       cmd_q->q_int_status = ioread32(cmd_q->reg_int_status);
+
+                       /* On error, only save the first error value */
+                       if ((q_int & cmd_q->int_err) && !cmd_q->cmd_error)
+                               cmd_q->cmd_error = CMD_Q_ERROR(cmd_q->q_status);
+
+                       cmd_q->int_rcvd = 1;
+
+                       /* Acknowledge the interrupt and wake the kthread */
+                       iowrite32(q_int, ccp->io_regs + IRQ_STATUS_REG);
+                       wake_up_interruptible(&cmd_q->int_queue);
+               }
+       }
+       ccp_enable_queue_interrupts(ccp);
+}
+
+static irqreturn_t ccp_irq_handler(int irq, void *data)
+{
+       struct device *dev = data;
+       struct ccp_device *ccp = dev_get_drvdata(dev);
+
+       ccp_disable_queue_interrupts(ccp);
+       if (ccp->use_tasklet)
+               tasklet_schedule(&ccp->irq_tasklet);
+       else
+               ccp_irq_bh((unsigned long)ccp);
+
+       return IRQ_HANDLED;
+}
+
 static int ccp_init(struct ccp_device *ccp)
 {
        struct device *dev = ccp->dev;
        struct ccp_cmd_queue *cmd_q;
        struct dma_pool *dma_pool;
        char dma_pool_name[MAX_DMAPOOL_NAME_LEN];
-       unsigned int qmr, qim, i;
+       unsigned int qmr, i;
        int ret;
 
        /* Find available queues */
-       qim = 0;
+       ccp->qim = 0;
        qmr = ioread32(ccp->io_regs + Q_MASK_REG);
        for (i = 0; i < MAX_HW_QUEUES; i++) {
                if (!(qmr & (1 << i)))
                init_waitqueue_head(&cmd_q->int_queue);
 
                /* Build queue interrupt mask (two interrupts per queue) */
-               qim |= cmd_q->int_ok | cmd_q->int_err;
+               ccp->qim |= cmd_q->int_ok | cmd_q->int_err;
 
 #ifdef CONFIG_ARM64
                /* For arm64 set the recommended queue cache settings */
        dev_notice(dev, "%u command queues available\n", ccp->cmd_q_count);
 
        /* Disable and clear interrupts until ready */
-       iowrite32(0x00, ccp->io_regs + IRQ_MASK_REG);
+       ccp_disable_queue_interrupts(ccp);
        for (i = 0; i < ccp->cmd_q_count; i++) {
                cmd_q = &ccp->cmd_q[i];
 
                ioread32(cmd_q->reg_int_status);
                ioread32(cmd_q->reg_status);
        }
-       iowrite32(qim, ccp->io_regs + IRQ_STATUS_REG);
+       iowrite32(ccp->qim, ccp->io_regs + IRQ_STATUS_REG);
 
        /* Request an irq */
        ret = ccp->get_irq(ccp);
        init_waitqueue_head(&ccp->sb_queue);
        init_waitqueue_head(&ccp->suspend_queue);
 
+       /* Initialize the ISR tasklet? */
+       if (ccp->use_tasklet)
+               tasklet_init(&ccp->irq_tasklet, ccp_irq_bh,
+                            (unsigned long)ccp);
+
        dev_dbg(dev, "Starting threads...\n");
        /* Create a kthread for each queue */
        for (i = 0; i < ccp->cmd_q_count; i++) {
 
        dev_dbg(dev, "Enabling interrupts...\n");
        /* Enable interrupts */
-       iowrite32(qim, ccp->io_regs + IRQ_MASK_REG);
+       ccp_enable_queue_interrupts(ccp);
 
        dev_dbg(dev, "Registering device...\n");
        ccp_add_device(ccp);
 {
        struct ccp_cmd_queue *cmd_q;
        struct ccp_cmd *cmd;
-       unsigned int qim, i;
+       unsigned int i;
 
        /* Unregister the DMA engine */
        ccp_dmaengine_unregister(ccp);
        /* Remove this device from the list of available units */
        ccp_del_device(ccp);
 
-       /* Build queue interrupt mask (two interrupt masks per queue) */
-       qim = 0;
-       for (i = 0; i < ccp->cmd_q_count; i++) {
-               cmd_q = &ccp->cmd_q[i];
-               qim |= cmd_q->int_ok | cmd_q->int_err;
-       }
-
        /* Disable and clear interrupts */
-       iowrite32(0x00, ccp->io_regs + IRQ_MASK_REG);
+       ccp_disable_queue_interrupts(ccp);
        for (i = 0; i < ccp->cmd_q_count; i++) {
                cmd_q = &ccp->cmd_q[i];
 
                ioread32(cmd_q->reg_int_status);
                ioread32(cmd_q->reg_status);
        }
-       iowrite32(qim, ccp->io_regs + IRQ_STATUS_REG);
+       iowrite32(ccp->qim, ccp->io_regs + IRQ_STATUS_REG);
 
        /* Stop the queue kthreads */
        for (i = 0; i < ccp->cmd_q_count; i++)
        }
 }
 
-static irqreturn_t ccp_irq_handler(int irq, void *data)
-{
-       struct device *dev = data;
-       struct ccp_device *ccp = dev_get_drvdata(dev);
-       struct ccp_cmd_queue *cmd_q;
-       u32 q_int, status;
-       unsigned int i;
-
-       status = ioread32(ccp->io_regs + IRQ_STATUS_REG);
-
-       for (i = 0; i < ccp->cmd_q_count; i++) {
-               cmd_q = &ccp->cmd_q[i];
-
-               q_int = status & (cmd_q->int_ok | cmd_q->int_err);
-               if (q_int) {
-                       cmd_q->int_status = status;
-                       cmd_q->q_status = ioread32(cmd_q->reg_status);
-                       cmd_q->q_int_status = ioread32(cmd_q->reg_int_status);
-
-                       /* On error, only save the first error value */
-                       if ((q_int & cmd_q->int_err) && !cmd_q->cmd_error)
-                               cmd_q->cmd_error = CMD_Q_ERROR(cmd_q->q_status);
-
-                       cmd_q->int_rcvd = 1;
-
-                       /* Acknowledge the interrupt and wake the kthread */
-                       iowrite32(q_int, ccp->io_regs + IRQ_STATUS_REG);
-                       wake_up_interruptible(&cmd_q->int_queue);
-               }
-       }
-
-       return IRQ_HANDLED;
-}
-
 static const struct ccp_actions ccp3_actions = {
        .aes = ccp_perform_aes,
        .xts_aes = ccp_perform_xts_aes,