Commit a6ca8878 authored by Alexei Potashnik's avatar Alexei Potashnik Committed by Nicholas Bellinger

qla2xxx: delay plogi/prli ack until existing sessions are deleted

- keep qla_tgt_sess object on the session list until it's freed

- modify use of sess->deleted flag to differentiate delayed
  session deletion that can be cancelled from irreversible one:
  QLA_SESS_DELETION_PENDING vs QLA_SESS_DELETION_IN_PROGRESS

- during IN_PROGRESS deletion all newly arrived commands and TMRs will
  be rejected, existing commands and TMRs will be terminated when
  given by the core to the fabric or simply dropped if session logout
  has already happened (logout terminates all existing exchanges)

- new PLOGI will initiate deletion of the following sessions
  (unless deletion is already IN_PROGRESS):
  - with the same port_name (with logout)
  - different port_name, different loop_id but the same port_id
    (with logout)
  - different port_name, different port_id, but the same loop_id
    (without logout)

- additionally each new PLOGI will store imm notify iocb in the
  same port_name session being deleted. When deletion process
  completes this iocb will be acked. Only the most recent PLOGI
  iocb is stored. The older ones will be terminated when replaced.

- new PRLI will initiate deletion of the following sessions
  (unless deletion is already IN_PROGRESS):
  - different port_name, different port_id, but the same loop_id
   (without logout)

Cc: <stable@vger.kernel.org> # v3.18+
Signed-off-by: default avatarAlexei Potashnik <alexei@purestorage.com>
Acked-by: default avatarQuinn Tran <quinn.tran@qlogic.com>
Signed-off-by: default avatarHimanshu Madhani <himanshu.madhani@qlogic.com>
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
parent 8b2f5ff3
...@@ -67,10 +67,10 @@ ...@@ -67,10 +67,10 @@
* | | | 0xd031-0xd0ff | * | | | 0xd031-0xd0ff |
* | | | 0xd101-0xd1fe | * | | | 0xd101-0xd1fe |
* | | | 0xd214-0xd2fe | * | | | 0xd214-0xd2fe |
* | Target Mode | 0xe079 | | * | Target Mode | 0xe080 | |
* | Target Mode Management | 0xf083 | 0xf002 | * | Target Mode Management | 0xf091 | 0xf002 |
* | | | 0xf046-0xf049 | * | | | 0xf046-0xf049 |
* | Target Mode Task Management | 0x1000b | | * | Target Mode Task Management | 0x1000d | |
* ---------------------------------------------------------------------- * ----------------------------------------------------------------------
*/ */
......
...@@ -274,6 +274,7 @@ ...@@ -274,6 +274,7 @@
#define RESPONSE_ENTRY_CNT_FX00 256 /* Number of response entries.*/ #define RESPONSE_ENTRY_CNT_FX00 256 /* Number of response entries.*/
struct req_que; struct req_que;
struct qla_tgt_sess;
/* /*
* (sd.h is not exported, hence local inclusion) * (sd.h is not exported, hence local inclusion)
...@@ -2026,6 +2027,7 @@ typedef struct fc_port { ...@@ -2026,6 +2027,7 @@ typedef struct fc_port {
uint16_t port_id; uint16_t port_id;
unsigned long retry_delay_timestamp; unsigned long retry_delay_timestamp;
struct qla_tgt_sess *tgt_session;
} fc_port_t; } fc_port_t;
#include "qla_mr.h" #include "qla_mr.h"
......
...@@ -115,6 +115,8 @@ qla2x00_async_iocb_timeout(void *data) ...@@ -115,6 +115,8 @@ qla2x00_async_iocb_timeout(void *data)
QLA_LOGIO_LOGIN_RETRIED : 0; QLA_LOGIO_LOGIN_RETRIED : 0;
qla2x00_post_async_login_done_work(fcport->vha, fcport, qla2x00_post_async_login_done_work(fcport->vha, fcport,
lio->u.logio.data); lio->u.logio.data);
} else if (sp->type == SRB_LOGOUT_CMD) {
qlt_logo_completion_handler(fcport, QLA_FUNCTION_TIMEOUT);
} }
} }
...@@ -497,7 +499,10 @@ void ...@@ -497,7 +499,10 @@ void
qla2x00_async_logout_done(struct scsi_qla_host *vha, fc_port_t *fcport, qla2x00_async_logout_done(struct scsi_qla_host *vha, fc_port_t *fcport,
uint16_t *data) uint16_t *data)
{ {
/* Don't re-login in target mode */
if (!fcport->tgt_session)
qla2x00_mark_device_lost(vha, fcport, 1, 0); qla2x00_mark_device_lost(vha, fcport, 1, 0);
qlt_logo_completion_handler(fcport, data[0]);
return; return;
} }
......
...@@ -1943,6 +1943,9 @@ qla24xx_logout_iocb(srb_t *sp, struct logio_entry_24xx *logio) ...@@ -1943,6 +1943,9 @@ qla24xx_logout_iocb(srb_t *sp, struct logio_entry_24xx *logio)
logio->entry_type = LOGINOUT_PORT_IOCB_TYPE; logio->entry_type = LOGINOUT_PORT_IOCB_TYPE;
logio->control_flags = logio->control_flags =
cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO); cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO);
if (!sp->fcport->tgt_session ||
!sp->fcport->tgt_session->keep_nport_handle)
logio->control_flags |= cpu_to_le16(LCF_FREE_NPORT);
logio->nport_handle = cpu_to_le16(sp->fcport->loop_id); logio->nport_handle = cpu_to_le16(sp->fcport->loop_id);
logio->port_id[0] = sp->fcport->d_id.b.al_pa; logio->port_id[0] = sp->fcport->d_id.b.al_pa;
logio->port_id[1] = sp->fcport->d_id.b.area; logio->port_id[1] = sp->fcport->d_id.b.area;
......
This diff is collapsed.
...@@ -167,7 +167,24 @@ struct imm_ntfy_from_isp { ...@@ -167,7 +167,24 @@ struct imm_ntfy_from_isp {
uint32_t srr_rel_offs; uint32_t srr_rel_offs;
uint16_t srr_ui; uint16_t srr_ui;
uint16_t srr_ox_id; uint16_t srr_ox_id;
uint8_t reserved_4[19]; union {
struct {
uint8_t node_name[8];
} plogi; /* PLOGI/ADISC/PDISC */
struct {
/* PRLI word 3 bit 0-15 */
uint16_t wd3_lo;
uint8_t resv0[6];
} prli;
struct {
uint8_t port_id[3];
uint8_t resv1;
uint16_t nport_handle;
uint16_t resv2;
} req_els;
} u;
uint8_t port_name[8];
uint8_t resv3[3];
uint8_t vp_index; uint8_t vp_index;
uint32_t reserved_5; uint32_t reserved_5;
uint8_t port_id[3]; uint8_t port_id[3];
...@@ -234,6 +251,7 @@ struct nack_to_isp { ...@@ -234,6 +251,7 @@ struct nack_to_isp {
uint8_t reserved[2]; uint8_t reserved[2];
uint16_t ox_id; uint16_t ox_id;
} __packed; } __packed;
#define NOTIFY_ACK_FLAGS_TERMINATE BIT_3
#define NOTIFY_ACK_SRR_FLAGS_ACCEPT 0 #define NOTIFY_ACK_SRR_FLAGS_ACCEPT 0
#define NOTIFY_ACK_SRR_FLAGS_REJECT 1 #define NOTIFY_ACK_SRR_FLAGS_REJECT 1
...@@ -878,6 +896,13 @@ struct qla_tgt_sess_op { ...@@ -878,6 +896,13 @@ struct qla_tgt_sess_op {
bool aborted; bool aborted;
}; };
enum qla_sess_deletion {
QLA_SESS_DELETION_NONE = 0,
QLA_SESS_DELETION_PENDING = 1, /* hopefully we can get rid of
* this one */
QLA_SESS_DELETION_IN_PROGRESS = 2,
};
/* /*
* Equivilant to IT Nexus (Initiator-Target) * Equivilant to IT Nexus (Initiator-Target)
*/ */
...@@ -886,8 +911,13 @@ struct qla_tgt_sess { ...@@ -886,8 +911,13 @@ struct qla_tgt_sess {
port_id_t s_id; port_id_t s_id;
unsigned int conf_compl_supported:1; unsigned int conf_compl_supported:1;
unsigned int deleted:1; unsigned int deleted:2;
unsigned int local:1; unsigned int local:1;
unsigned int logout_on_delete:1;
unsigned int plogi_ack_needed:1;
unsigned int keep_nport_handle:1;
unsigned char logout_completed;
struct se_session *se_sess; struct se_session *se_sess;
struct scsi_qla_host *vha; struct scsi_qla_host *vha;
...@@ -899,6 +929,10 @@ struct qla_tgt_sess { ...@@ -899,6 +929,10 @@ struct qla_tgt_sess {
uint8_t port_name[WWN_SIZE]; uint8_t port_name[WWN_SIZE];
struct work_struct free_work; struct work_struct free_work;
union {
struct imm_ntfy_from_isp tm_iocb;
};
}; };
struct qla_tgt_cmd { struct qla_tgt_cmd {
...@@ -1031,6 +1065,10 @@ struct qla_tgt_srr_ctio { ...@@ -1031,6 +1065,10 @@ struct qla_tgt_srr_ctio {
struct qla_tgt_cmd *cmd; struct qla_tgt_cmd *cmd;
}; };
/* Check for Switch reserved address */
#define IS_SW_RESV_ADDR(_s_id) \
((_s_id.b.domain == 0xff) && (_s_id.b.area == 0xfc))
#define QLA_TGT_XMIT_DATA 1 #define QLA_TGT_XMIT_DATA 1
#define QLA_TGT_XMIT_STATUS 2 #define QLA_TGT_XMIT_STATUS 2
#define QLA_TGT_XMIT_ALL (QLA_TGT_XMIT_STATUS|QLA_TGT_XMIT_DATA) #define QLA_TGT_XMIT_ALL (QLA_TGT_XMIT_STATUS|QLA_TGT_XMIT_DATA)
...@@ -1124,5 +1162,6 @@ extern void qlt_stop_phase2(struct qla_tgt *); ...@@ -1124,5 +1162,6 @@ extern void qlt_stop_phase2(struct qla_tgt *);
extern irqreturn_t qla83xx_msix_atio_q(int, void *); extern irqreturn_t qla83xx_msix_atio_q(int, void *);
extern void qlt_83xx_iospace_config(struct qla_hw_data *); extern void qlt_83xx_iospace_config(struct qla_hw_data *);
extern int qlt_free_qfull_cmds(struct scsi_qla_host *); extern int qlt_free_qfull_cmds(struct scsi_qla_host *);
extern void qlt_logo_completion_handler(fc_port_t *, int);
#endif /* __QLA_TARGET_H */ #endif /* __QLA_TARGET_H */
...@@ -1539,6 +1539,10 @@ static void tcm_qla2xxx_update_sess(struct qla_tgt_sess *sess, port_id_t s_id, ...@@ -1539,6 +1539,10 @@ static void tcm_qla2xxx_update_sess(struct qla_tgt_sess *sess, port_id_t s_id,
} }
sess->conf_compl_supported = conf_compl_supported; sess->conf_compl_supported = conf_compl_supported;
/* Reset logout parameters to default */
sess->logout_on_delete = 1;
sess->keep_nport_handle = 0;
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment