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

qla2xxx: Wait for all conflicts before ack'ing PLOGI

Until now ack'ing of a new PLOGI has only been delayed if there
was an existing session for the same WWN. Ack was released when
the session deletion completed.

If there was another WWN session with the same fc_id/loop_id pair
(aka "conflicting session"), PLOGI was still ack'ed immediately.
This potentially caused a problem when old session deletion logged
fc_id/loop_id out of FW after new session has been established.

Two work-arounds were attempted before:
1. Dropping PLOGIs until conflicting session goes away.
2. Detecting initiator being logged out of FW and issuing LOGO
to force re-login.

This patch introduces proper solution to the problem where PLOGI
is held until either existing session with same WWN or any
conflicting session goes away. Mechanism supports one session holding
two PLOGI acks as well as one PLOGI ack being held by many sessions.
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>
Reviewed-by: default avatarHannes Reinecke <hare@suse.com>
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
parent 71cdc079
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
* | | | 0x3036,0x3038 | * | | | 0x3036,0x3038 |
* | | | 0x303a | * | | | 0x303a |
* | DPC Thread | 0x4023 | 0x4002,0x4013 | * | DPC Thread | 0x4023 | 0x4002,0x4013 |
* | Async Events | 0x508a | 0x502b-0x502f | * | Async Events | 0x5089 | 0x502b-0x502f |
* | | | 0x5084,0x5075 | * | | | 0x5084,0x5075 |
* | | | 0x503d,0x5044 | * | | | 0x503d,0x5044 |
* | | | 0x507b,0x505f | * | | | 0x507b,0x505f |
...@@ -63,7 +63,7 @@ ...@@ -63,7 +63,7 @@
* | | | 0xd101-0xd1fe | * | | | 0xd101-0xd1fe |
* | | | 0xd214-0xd2fe | * | | | 0xd214-0xd2fe |
* | Target Mode | 0xe080 | | * | Target Mode | 0xe080 | |
* | Target Mode Management | 0xf096 | 0xf002 | * | Target Mode Management | 0xf09b | 0xf002 |
* | | | 0xf046-0xf049 | * | | | 0xf046-0xf049 |
* | Target Mode Task Management | 0x1000d | | * | Target Mode Task Management | 0x1000d | |
* ---------------------------------------------------------------------- * ----------------------------------------------------------------------
......
...@@ -3654,6 +3654,8 @@ typedef struct scsi_qla_host { ...@@ -3654,6 +3654,8 @@ typedef struct scsi_qla_host {
int total_fcport_update_gen; int total_fcport_update_gen;
/* List of pending LOGOs, protected by tgt_mutex */ /* List of pending LOGOs, protected by tgt_mutex */
struct list_head logo_list; struct list_head logo_list;
/* List of pending PLOGI acks, protected by hw lock */
struct list_head plogi_ack_list;
uint32_t vp_abort_cnt; uint32_t vp_abort_cnt;
......
...@@ -3921,6 +3921,7 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht, ...@@ -3921,6 +3921,7 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
INIT_LIST_HEAD(&vha->qla_cmd_list); INIT_LIST_HEAD(&vha->qla_cmd_list);
INIT_LIST_HEAD(&vha->qla_sess_op_cmd_list); INIT_LIST_HEAD(&vha->qla_sess_op_cmd_list);
INIT_LIST_HEAD(&vha->logo_list); INIT_LIST_HEAD(&vha->logo_list);
INIT_LIST_HEAD(&vha->plogi_ack_list);
spin_lock_init(&vha->work_lock); spin_lock_init(&vha->work_lock);
spin_lock_init(&vha->cmd_list_lock); spin_lock_init(&vha->cmd_list_lock);
......
This diff is collapsed.
...@@ -896,6 +896,19 @@ enum qla_sess_deletion { ...@@ -896,6 +896,19 @@ enum qla_sess_deletion {
QLA_SESS_DELETION_IN_PROGRESS = 2, QLA_SESS_DELETION_IN_PROGRESS = 2,
}; };
typedef enum {
QLT_PLOGI_LINK_SAME_WWN,
QLT_PLOGI_LINK_CONFLICT,
QLT_PLOGI_LINK_MAX
} qlt_plogi_link_t;
typedef struct {
struct list_head list;
struct imm_ntfy_from_isp iocb;
port_id_t id;
int ref_count;
} qlt_plogi_ack_t;
/* /*
* Equivilant to IT Nexus (Initiator-Target) * Equivilant to IT Nexus (Initiator-Target)
*/ */
...@@ -907,7 +920,6 @@ struct qla_tgt_sess { ...@@ -907,7 +920,6 @@ struct qla_tgt_sess {
unsigned int deleted:2; unsigned int deleted:2;
unsigned int local:1; unsigned int local:1;
unsigned int logout_on_delete:1; unsigned int logout_on_delete:1;
unsigned int plogi_ack_needed:1;
unsigned int keep_nport_handle:1; unsigned int keep_nport_handle:1;
unsigned int send_els_logo:1; unsigned int send_els_logo:1;
...@@ -926,9 +938,7 @@ struct qla_tgt_sess { ...@@ -926,9 +938,7 @@ 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 { qlt_plogi_ack_t *plogi_link[QLT_PLOGI_LINK_MAX];
struct imm_ntfy_from_isp tm_iocb;
};
}; };
struct qla_tgt_cmd { struct qla_tgt_cmd {
......
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