scsi: qla2xxx: edif: Fix dropped IKE message
authorQuinn Tran <qutran@marvell.com>
Wed, 13 Jul 2022 05:20:40 +0000 (22:20 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 19 Jul 2022 02:33:03 +0000 (22:33 -0400)
This patch fixes IKE message being dropped due to error in processing Purex
IOCB and Continuation IOCBs.

Link: https://lore.kernel.org/r/20220713052045.10683-6-njavali@marvell.com
Fixes: fac2807946c1 ("scsi: qla2xxx: edif: Add extraction of auth_els from the wire")
Cc: stable@vger.kernel.org
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
Signed-off-by: Quinn Tran <qutran@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/qla2xxx/qla_isr.c

index 35b425c..76e79f3 100644 (file)
@@ -3720,12 +3720,11 @@ void qla24xx_nvme_ls4_iocb(struct scsi_qla_host *vha,
  * Return: 0 all iocbs has arrived, xx- all iocbs have not arrived.
  */
 static int qla_chk_cont_iocb_avail(struct scsi_qla_host *vha,
-       struct rsp_que *rsp, response_t *pkt)
+       struct rsp_que *rsp, response_t *pkt, u32 rsp_q_in)
 {
-       int start_pkt_ring_index, end_pkt_ring_index, n_ring_index;
-       response_t *end_pkt;
+       int start_pkt_ring_index;
+       u32 iocb_cnt = 0;
        int rc = 0;
-       u32 rsp_q_in;
 
        if (pkt->entry_count == 1)
                return rc;
@@ -3736,34 +3735,18 @@ static int qla_chk_cont_iocb_avail(struct scsi_qla_host *vha,
        else
                start_pkt_ring_index = rsp->ring_index - 1;
 
-       if ((start_pkt_ring_index + pkt->entry_count) >= rsp->length)
-               end_pkt_ring_index = start_pkt_ring_index + pkt->entry_count -
-                       rsp->length - 1;
+       if (rsp_q_in < start_pkt_ring_index)
+               /* q in ptr is wrapped */
+               iocb_cnt = rsp->length - start_pkt_ring_index + rsp_q_in;
        else
-               end_pkt_ring_index = start_pkt_ring_index + pkt->entry_count - 1;
+               iocb_cnt = rsp_q_in - start_pkt_ring_index;
 
-       end_pkt = rsp->ring + end_pkt_ring_index;
-
-       /*  next pkt = end_pkt + 1 */
-       n_ring_index = end_pkt_ring_index + 1;
-       if (n_ring_index >= rsp->length)
-               n_ring_index = 0;
-
-       rsp_q_in = rsp->qpair->use_shadow_reg ? *rsp->in_ptr :
-               rd_reg_dword(rsp->rsp_q_in);
-
-       /* rsp_q_in is either wrapped or pointing beyond endpkt */
-       if ((rsp_q_in < start_pkt_ring_index && rsp_q_in < n_ring_index) ||
-                       rsp_q_in >= n_ring_index)
-               /* all IOCBs arrived. */
-               rc = 0;
-       else
+       if (iocb_cnt < pkt->entry_count)
                rc = -EIO;
 
-       ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x5091,
-           "%s - ring %p pkt %p end pkt %p entry count %#x rsp_q_in %d rc %d\n",
-           __func__, rsp->ring, pkt, end_pkt, pkt->entry_count,
-           rsp_q_in, rc);
+       ql_dbg(ql_dbg_init, vha, 0x5091,
+              "%s - ring %p pkt %p entry count %d iocb_cnt %d rsp_q_in %d rc %d\n",
+              __func__, rsp->ring, pkt, pkt->entry_count, iocb_cnt, rsp_q_in, rc);
 
        return rc;
 }
@@ -3780,7 +3763,7 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
        struct qla_hw_data *ha = vha->hw;
        struct purex_entry_24xx *purex_entry;
        struct purex_item *pure_item;
-       u16 rsp_in = 0;
+       u16 rsp_in = 0, cur_ring_index;
        int follow_inptr, is_shadow_hba;
 
        if (!ha->flags.fw_started)
@@ -3811,6 +3794,7 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
                       (!follow_inptr &&
                        rsp->ring_ptr->signature != RESPONSE_PROCESSED)) {
                pkt = (struct sts_entry_24xx *)rsp->ring_ptr;
+               cur_ring_index = rsp->ring_index;
 
                rsp->ring_index++;
                if (rsp->ring_index == rsp->length) {
@@ -3931,7 +3915,17 @@ process_err:
                                break;
 
                        case ELS_AUTH_ELS:
-                               if (qla_chk_cont_iocb_avail(vha, rsp, (response_t *)pkt)) {
+                               if (qla_chk_cont_iocb_avail(vha, rsp, (response_t *)pkt, rsp_in)) {
+                                       /*
+                                        * ring_ptr and ring_index were
+                                        * pre-incremented above. Reset them
+                                        * back to current. Wait for next
+                                        * interrupt with all IOCBs to arrive
+                                        * and re-process.
+                                        */
+                                       rsp->ring_ptr = (response_t *)pkt;
+                                       rsp->ring_index = cur_ring_index;
+
                                        ql_dbg(ql_dbg_init, vha, 0x5091,
                                            "Defer processing ELS opcode %#x...\n",
                                            purex_entry->els_frame_payload[3]);