]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
scsi: mpi3mr: ioctl timeout when disabling/enabling interrupt
authorRanjan Kumar <ranjan.kumar@broadcom.com>
Tue, 28 Feb 2023 14:08:30 +0000 (06:08 -0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Mon, 6 Mar 2023 23:33:12 +0000 (18:33 -0500)
As part of Task Management handling, the driver will disable and enable the
MSIx index zero which belongs to the Admin reply queue. During this
transition the driver loses some interrupts and this leads to Admin request
and ioctl timeouts.

After enabling the interrupts, poll the Admin reply queue to avoid
timeouts.

Signed-off-by: Ranjan Kumar <ranjan.kumar@broadcom.com>
Signed-off-by: Sreekanth Reddy <sreekanth.reddy@broadcom.com>
Link: https://lore.kernel.org/r/20230228140835.4075-2-ranjan.kumar@broadcom.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/mpi3mr/mpi3mr.h
drivers/scsi/mpi3mr/mpi3mr_fw.c
drivers/scsi/mpi3mr/mpi3mr_os.c

index 23de2603e71fdd3736ceef7ca1d5fb1b91d35240..40f238fa80cc18341b329a7e5eb1a2060a5e70d8 100644 (file)
@@ -902,6 +902,7 @@ struct scmd_priv {
  * @admin_reply_ephase:Admin reply queue expected phase
  * @admin_reply_base: Admin reply queue base virtual address
  * @admin_reply_dma: Admin reply queue base dma address
+ * @admin_reply_q_in_use: Queue is handled by poll/ISR
  * @ready_timeout: Controller ready timeout
  * @intr_info: Interrupt cookie pointer
  * @intr_info_count: Number of interrupt cookies
@@ -1055,6 +1056,7 @@ struct mpi3mr_ioc {
        u8 admin_reply_ephase;
        void *admin_reply_base;
        dma_addr_t admin_reply_dma;
+       atomic_t admin_reply_q_in_use;
 
        u32 ready_timeout;
 
@@ -1390,4 +1392,5 @@ void mpi3mr_add_event_wait_for_device_refresh(struct mpi3mr_ioc *mrioc);
 void mpi3mr_flush_drv_cmds(struct mpi3mr_ioc *mrioc);
 void mpi3mr_flush_cmds_for_unrecovered_controller(struct mpi3mr_ioc *mrioc);
 void mpi3mr_free_enclosure_list(struct mpi3mr_ioc *mrioc);
+int mpi3mr_process_admin_reply_q(struct mpi3mr_ioc *mrioc);
 #endif /*MPI3MR_H_INCLUDED*/
index 758f7ca9e0ee803bad899d35fef7bbd04b222f69..4254e46a20f1a679d829bb737c5a32896f8a27ba 100644 (file)
@@ -415,7 +415,7 @@ out:
                    le64_to_cpu(scsi_reply->sense_data_buffer_address));
 }
 
-static int mpi3mr_process_admin_reply_q(struct mpi3mr_ioc *mrioc)
+int mpi3mr_process_admin_reply_q(struct mpi3mr_ioc *mrioc)
 {
        u32 exp_phase = mrioc->admin_reply_ephase;
        u32 admin_reply_ci = mrioc->admin_reply_ci;
@@ -423,12 +423,17 @@ static int mpi3mr_process_admin_reply_q(struct mpi3mr_ioc *mrioc)
        u64 reply_dma = 0;
        struct mpi3_default_reply_descriptor *reply_desc;
 
+       if (!atomic_add_unless(&mrioc->admin_reply_q_in_use, 1, 1))
+               return 0;
+
        reply_desc = (struct mpi3_default_reply_descriptor *)mrioc->admin_reply_base +
            admin_reply_ci;
 
        if ((le16_to_cpu(reply_desc->reply_flags) &
-           MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) != exp_phase)
+           MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) != exp_phase) {
+               atomic_dec(&mrioc->admin_reply_q_in_use);
                return 0;
+       }
 
        do {
                if (mrioc->unrecoverable)
@@ -454,6 +459,7 @@ static int mpi3mr_process_admin_reply_q(struct mpi3mr_ioc *mrioc)
        writel(admin_reply_ci, &mrioc->sysif_regs->admin_reply_queue_ci);
        mrioc->admin_reply_ci = admin_reply_ci;
        mrioc->admin_reply_ephase = exp_phase;
+       atomic_dec(&mrioc->admin_reply_q_in_use);
 
        return num_admin_replies;
 }
@@ -2605,6 +2611,7 @@ static int mpi3mr_setup_admin_qpair(struct mpi3mr_ioc *mrioc)
        mrioc->admin_reply_ci = 0;
        mrioc->admin_reply_ephase = 1;
        mrioc->admin_reply_base = NULL;
+       atomic_set(&mrioc->admin_reply_q_in_use, 0);
 
        if (!mrioc->admin_req_base) {
                mrioc->admin_req_base = dma_alloc_coherent(&mrioc->pdev->dev,
@@ -4155,6 +4162,7 @@ void mpi3mr_memset_buffers(struct mpi3mr_ioc *mrioc)
                memset(mrioc->admin_req_base, 0, mrioc->admin_req_q_sz);
        if (mrioc->admin_reply_base)
                memset(mrioc->admin_reply_base, 0, mrioc->admin_reply_q_sz);
+       atomic_set(&mrioc->admin_reply_q_in_use, 0);
 
        if (mrioc->init_cmds.reply) {
                memset(mrioc->init_cmds.reply, 0, sizeof(*mrioc->init_cmds.reply));
index 6eaeba41072cb53e4ff2354fa4241815b2c7a24c..a794cc8a1c0b137697624d2e90f3a257e8e7983d 100644 (file)
@@ -3720,6 +3720,7 @@ int mpi3mr_issue_tm(struct mpi3mr_ioc *mrioc, u8 tm_type,
                mpi3mr_poll_pend_io_completions(mrioc);
                mpi3mr_ioc_enable_intr(mrioc);
                mpi3mr_poll_pend_io_completions(mrioc);
+               mpi3mr_process_admin_reply_q(mrioc);
        }
        switch (tm_type) {
        case MPI3_SCSITASKMGMT_TASKTYPE_TARGET_RESET: