scsi: qla2xxx: edif: Flush stale events and msgs on session down
authorQuinn Tran <qutran@marvell.com>
Tue, 26 Oct 2021 11:54:05 +0000 (04:54 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Wed, 27 Oct 2021 03:51:59 +0000 (23:51 -0400)
On session down, driver will flush all stale messages and doorbell
events. This prevents authentication application from having to process
stale data.

Link: https://lore.kernel.org/r/20211026115412.27691-7-njavali@marvell.com
Fixes: 4de067e5df12 ("scsi: qla2xxx: edif: Add N2N support for EDIF")
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
Co-developed-by: Karunakara Merugu <kmerugu@marvell.com>
Signed-off-by: Karunakara Merugu <kmerugu@marvell.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_edif.c
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_target.c

index cf62f26ce27d95a2c3c1583e096b7b93b18f33ab..3931bae3222b36aa0cfc346c0141cf696d9f7b31 100644 (file)
@@ -1593,6 +1593,40 @@ qla_enode_stop(scsi_qla_host_t *vha)
        spin_unlock_irqrestore(&vha->pur_cinfo.pur_lock, flags);
 }
 
+static void qla_enode_clear(scsi_qla_host_t *vha, port_id_t portid)
+{
+       unsigned    long flags;
+       struct enode    *e, *tmp;
+       struct purexevent   *purex;
+       LIST_HEAD(enode_list);
+
+       if (vha->pur_cinfo.enode_flags != ENODE_ACTIVE) {
+               ql_dbg(ql_dbg_edif, vha, 0x09102,
+                      "%s enode not active\n", __func__);
+               return;
+       }
+       spin_lock_irqsave(&vha->pur_cinfo.pur_lock, flags);
+       list_for_each_entry_safe(e, tmp, &vha->pur_cinfo.head, list) {
+               purex = &e->u.purexinfo;
+               if (purex->pur_info.pur_sid.b24 == portid.b24) {
+                       ql_dbg(ql_dbg_edif, vha, 0x911d,
+                           "%s free ELS sid=%06x. xchg %x, nb=%xh\n",
+                           __func__, portid.b24,
+                           purex->pur_info.pur_rx_xchg_address,
+                           purex->pur_info.pur_bytes_rcvd);
+
+                       list_del_init(&e->list);
+                       list_add_tail(&e->list, &enode_list);
+               }
+       }
+       spin_unlock_irqrestore(&vha->pur_cinfo.pur_lock, flags);
+
+       list_for_each_entry_safe(e, tmp, &enode_list, list) {
+               list_del_init(&e->list);
+               qla_enode_free(vha, e);
+       }
+}
+
 /*
  *  allocate enode struct and populate buffer
  *  returns: enode pointer with buffers
@@ -1792,6 +1826,57 @@ qla_edb_node_free(scsi_qla_host_t *vha, struct edb_node *node)
        node->ntype = N_UNDEF;
 }
 
+static void qla_edb_clear(scsi_qla_host_t *vha, port_id_t portid)
+{
+       unsigned long flags;
+       struct edb_node *e, *tmp;
+       port_id_t sid;
+       LIST_HEAD(edb_list);
+
+       if (vha->e_dbell.db_flags != EDB_ACTIVE) {
+               /* doorbell list not enabled */
+               ql_dbg(ql_dbg_edif, vha, 0x09102,
+                      "%s doorbell not enabled\n", __func__);
+               return;
+       }
+
+       /* grab lock so list doesn't move */
+       spin_lock_irqsave(&vha->e_dbell.db_lock, flags);
+       list_for_each_entry_safe(e, tmp, &vha->e_dbell.head, list) {
+               switch (e->ntype) {
+               case VND_CMD_AUTH_STATE_NEEDED:
+               case VND_CMD_AUTH_STATE_SESSION_SHUTDOWN:
+                       sid = e->u.plogi_did;
+                       break;
+               case VND_CMD_AUTH_STATE_ELS_RCVD:
+                       sid = e->u.els_sid;
+                       break;
+               case VND_CMD_AUTH_STATE_SAUPDATE_COMPL:
+                       /* app wants to see this  */
+                       continue;
+               default:
+                       ql_log(ql_log_warn, vha, 0x09102,
+                              "%s unknown node type: %x\n", __func__, e->ntype);
+                       sid.b24 = 0;
+                       break;
+               }
+               if (sid.b24 == portid.b24) {
+                       ql_dbg(ql_dbg_edif, vha, 0x910f,
+                              "%s free doorbell event : node type = %x %p\n",
+                              __func__, e->ntype, e);
+                       list_del_init(&e->list);
+                       list_add_tail(&e->list, &edb_list);
+               }
+       }
+       spin_unlock_irqrestore(&vha->e_dbell.db_lock, flags);
+
+       list_for_each_entry_safe(e, tmp, &edb_list, list) {
+               qla_edb_node_free(vha, e);
+               list_del_init(&e->list);
+               kfree(e);
+       }
+}
+
 /* function called when app is stopping */
 
 void
@@ -2378,7 +2463,7 @@ void qla24xx_auth_els(scsi_qla_host_t *vha, void **pkt, struct rsp_que **rsp)
        ql_dbg(ql_dbg_edif, host, 0x0910c,
            "%s COMPLETE purex->pur_info.pur_bytes_rcvd =%xh s:%06x -> d:%06x xchg=%xh\n",
            __func__, purex->pur_info.pur_bytes_rcvd, purex->pur_info.pur_sid.b24,
-           purex->pur_info.pur_did.b24, p->rx_xchg_addr);
+           purex->pur_info.pur_did.b24, purex->pur_info.pur_rx_xchg_address);
 
        qla_edb_eventcreate(host, VND_CMD_AUTH_STATE_ELS_RCVD, sid, 0, NULL);
 }
@@ -3401,3 +3486,12 @@ void qla_edif_sess_down(struct scsi_qla_host *vha, struct fc_port *sess)
                qla2x00_post_aen_work(vha, FCH_EVT_PORT_OFFLINE, sess->d_id.b24);
        }
 }
+
+void qla_edif_clear_appdata(struct scsi_qla_host *vha, struct fc_port *fcport)
+{
+       if (!(fcport->flags & FCF_FCSP_DEVICE))
+               return;
+
+       qla_edb_clear(vha, fcport->d_id);
+       qla_enode_clear(vha, fcport->d_id);
+}
index 4fd59e29cbd39a3744707c9a7c109fade1a58602..8d8503a2847909f3aa83e32a078eff511930ddef 100644 (file)
@@ -142,6 +142,8 @@ void qlt_chk_edif_rx_sa_delete_pending(scsi_qla_host_t *vha, fc_port_t *fcport,
 void qla2x00_release_all_sadb(struct scsi_qla_host *vha, struct fc_port *fcport);
 int qla_edif_process_els(scsi_qla_host_t *vha, struct bsg_job *bsgjob);
 void qla_edif_sess_down(struct scsi_qla_host *vha, struct fc_port *sess);
+void qla_edif_clear_appdata(struct scsi_qla_host *vha,
+                           struct fc_port *fcport);
 const char *sc_to_str(uint16_t cmd);
 
 /*
index b3478ed9b12e8076fe333555c1e499a7b08cd8c9..edc34e69d75bb7035e19bac397d68e3e22805ea3 100644 (file)
@@ -1003,6 +1003,7 @@ void qlt_free_session_done(struct work_struct *work)
                                        "%s bypassing release_all_sadb\n",
                                        __func__);
                        }
+                       qla_edif_clear_appdata(vha, sess);
                        qla_edif_sess_down(vha, sess);
                }
                qla2x00_mark_device_lost(vha, sess, 0);