if (mtip_check_surprise_removal(dd->pdev))
                return NULL;
 
-       rq = blk_mq_alloc_request(dd->queue, 0, BLK_MQ_REQ_RESERVED);
+       rq = blk_mq_alloc_request(dd->queue, REQ_OP_DRV_IN, BLK_MQ_REQ_RESERVED);
        if (IS_ERR(rq))
                return NULL;
 
        return -EFAULT;
 }
 
+struct mtip_int_cmd {
+       int fis_len;
+       dma_addr_t buffer;
+       int buf_len;
+       u32 opts;
+};
+
 /*
  * Execute an internal command and wait for the completion.
  *
                                        u32 opts,
                                        unsigned long timeout)
 {
-       struct mtip_cmd_sg *command_sg;
        DECLARE_COMPLETION_ONSTACK(wait);
        struct mtip_cmd *int_cmd;
        struct driver_data *dd = port->dd;
+       struct request *rq;
+       struct mtip_int_cmd icmd = {
+               .fis_len = fis_len,
+               .buffer = buffer,
+               .buf_len = buf_len,
+               .opts = opts
+       };
        int rv = 0;
        unsigned long start;
 
                dbg_printk(MTIP_DRV_NAME "Unable to allocate tag for PIO cmd\n");
                return -EFAULT;
        }
+       rq = blk_mq_rq_from_pdu(int_cmd);
+       rq->end_io_data = &icmd;
 
        set_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags);
 
        /* Copy the command to the command table */
        memcpy(int_cmd->command, fis, fis_len*4);
 
-       /* Populate the SG list */
-       int_cmd->command_header->opts =
-                __force_bit2int cpu_to_le32(opts | fis_len);
-       if (buf_len) {
-               command_sg = int_cmd->command + AHCI_CMD_TBL_HDR_SZ;
-
-               command_sg->info =
-                       __force_bit2int cpu_to_le32((buf_len-1) & 0x3FFFFF);
-               command_sg->dba =
-                       __force_bit2int cpu_to_le32(buffer & 0xFFFFFFFF);
-               command_sg->dba_upper =
-                       __force_bit2int cpu_to_le32((buffer >> 16) >> 16);
-
-               int_cmd->command_header->opts |=
-                       __force_bit2int cpu_to_le32((1 << 16));
-       }
-
-       /* Populate the command header */
-       int_cmd->command_header->byte_count = 0;
-
        start = jiffies;
+       rq->timeout = timeout;
 
-       /* Issue the command to the hardware */
-       mtip_issue_non_ncq_command(port, MTIP_TAG_INTERNAL);
+       /* insert request and run queue */
+       blk_execute_rq_nowait(rq->q, NULL, rq, true, NULL);
+
+       wait_for_completion(&wait);
+       rv = int_cmd->status;
 
-       /* Wait for the command to complete or timeout. */
-       rv = wait_for_completion_interruptible_timeout(&wait,
-                               msecs_to_jiffies(timeout));
-       if (rv <= 0) {
+       if (rv < 0) {
                if (rv == -ERESTARTSYS) { /* interrupted */
                        dev_err(&dd->pdev->dev,
                                "Internal command [%02X] was interrupted after %u ms\n",
                goto exec_ic_exit;
        }
 
-       rv = 0;
        if (readl(port->cmd_issue[MTIP_TAG_INTERNAL])
                        & (1 << MTIP_TAG_INTERNAL)) {
                rv = -ENXIO;
        return false;
 }
 
+static int mtip_issue_reserved_cmd(struct blk_mq_hw_ctx *hctx,
+                                  struct request *rq)
+{
+       struct driver_data *dd = hctx->queue->queuedata;
+       struct mtip_int_cmd *icmd = rq->end_io_data;
+       struct mtip_cmd *cmd = blk_mq_rq_to_pdu(rq);
+       struct mtip_cmd_sg *command_sg;
+
+       if (mtip_commands_active(dd->port))
+               return BLK_MQ_RQ_QUEUE_BUSY;
+
+       rq->end_io_data = NULL;
+
+       /* Populate the SG list */
+       cmd->command_header->opts =
+                __force_bit2int cpu_to_le32(icmd->opts | icmd->fis_len);
+       if (icmd->buf_len) {
+               command_sg = cmd->command + AHCI_CMD_TBL_HDR_SZ;
+
+               command_sg->info =
+                       __force_bit2int cpu_to_le32((icmd->buf_len-1) & 0x3FFFFF);
+               command_sg->dba =
+                       __force_bit2int cpu_to_le32(icmd->buffer & 0xFFFFFFFF);
+               command_sg->dba_upper =
+                       __force_bit2int cpu_to_le32((icmd->buffer >> 16) >> 16);
+
+               cmd->command_header->opts |=
+                       __force_bit2int cpu_to_le32((1 << 16));
+       }
+
+       /* Populate the command header */
+       cmd->command_header->byte_count = 0;
+
+       blk_mq_start_request(rq);
+       mtip_issue_non_ncq_command(dd->port, rq->tag);
+       return BLK_MQ_RQ_QUEUE_OK;
+}
+
 static int mtip_queue_rq(struct blk_mq_hw_ctx *hctx,
                         const struct blk_mq_queue_data *bd)
 {
 
        mtip_init_cmd_header(rq);
 
+       if (blk_rq_is_passthrough(rq))
+               return mtip_issue_reserved_cmd(hctx, rq);
+
        if (unlikely(mtip_check_unal_depth(hctx, rq)))
                return BLK_MQ_RQ_QUEUE_BUSY;
 
 {
        struct driver_data *dd = req->q->queuedata;
 
-       if (reserved)
+       if (reserved) {
+               struct mtip_cmd *cmd = blk_mq_rq_to_pdu(req);
+
+               cmd->status = -ETIME;
+               if (cmd->comp_func)
+                       cmd->comp_func(dd->port, MTIP_TAG_INTERNAL, cmd, -ETIME);
                goto exit_handler;
+       }
 
        if (test_bit(req->tag, dd->port->cmds_to_issue))
                goto exit_handler;
        } else if (test_bit(MTIP_PF_IC_ACTIVE_BIT, &dd->port->flags)) {
 
                cmd = mtip_cmd_from_tag(dd, MTIP_TAG_INTERNAL);
+               cmd->status = -ENODEV;
                if (cmd->comp_func)
                        cmd->comp_func(dd->port, MTIP_TAG_INTERNAL,
                                        cmd, -ENODEV);