Skip to content

Commit

Permalink
qla2xxx: Add framework for async fabric discovery
Browse files Browse the repository at this point in the history
Currently code performs a full scan of the fabric for
every RSCN. Its an expensive process in a noisy large SAN.

This patch optimizes expensive fabric discovery process by
scanning switch for the affected port when RSCN is received.

Currently Initiator Mode code makes login/logout decision without
knowledge of target mode. This causes driver and firmware to go
out-of-sync. This framework synchronizes both initiator mode
personality and target mode personality in making login/logout
decision.

This patch adds following capabilities in the driver

- Send Notification Acknowledgement asynchronously.
- Update session/fcport state asynchronously.
- Create a session or fcport struct asynchronously.
- Send GNL asynchronously. The command will ask FW to
  provide a list of FC Port entries FW knows about.
- Send GPDB asynchronously. The command will ask FW to
  provide detail data of an FC Port FW knows about or
  perform ADISC to verify the state of the session.
- Send GPNID asynchronously. The command will ask switch
  to provide WWPN for provided NPort ID.
- Send GPSC asynchronously. The command will ask switch
  to provide registered port speed for provided WWPN.
- Send GIDPN asynchronously. The command will ask the
  switch to provide Nport ID for provided WWPN.
- In driver unload path, schedule all session for deletion
  and wait for deletion to complete before allowing driver
  unload to proceed.

Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
[ bvanassche: fixed spelling in patch description ]
Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
  • Loading branch information
Quinn Tran authored and Nicholas Bellinger committed Feb 9, 2017
1 parent 5d96483 commit 726b854
Show file tree
Hide file tree
Showing 13 changed files with 3,114 additions and 987 deletions.
3 changes: 3 additions & 0 deletions drivers/scsi/qla2xxx/qla_attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -2163,6 +2163,9 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
clear_bit(vha->vp_idx, ha->vp_idx_map);
mutex_unlock(&ha->vport_lock);

dma_free_coherent(&ha->pdev->dev, vha->gnl.size, vha->gnl.l,
vha->gnl.ldma);

if (vha->qpair->vp_idx == vha->vp_idx) {
if (qla2xxx_delete_qpair(vha, vha->qpair) != QLA_SUCCESS)
ql_log(ql_log_warn, vha, 0x7087,
Expand Down
175 changes: 171 additions & 4 deletions drivers/scsi/qla2xxx/qla_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@

#include "qla_settings.h"

#define MODE_DUAL (MODE_TARGET | MODE_INITIATOR)

/*
* Data bit definitions
*/
Expand Down Expand Up @@ -251,6 +253,14 @@

#define MAX_CMDSZ 16 /* SCSI maximum CDB size. */
#include "qla_fw.h"

struct name_list_extended {
struct get_name_list_extended *l;
dma_addr_t ldma;
struct list_head fcports; /* protect by sess_list */
u32 size;
u8 sent;
};
/*
* Timeout timer counts in seconds
*/
Expand Down Expand Up @@ -309,6 +319,17 @@ struct els_logo_payload {
uint8_t wwpn[WWN_SIZE];
};

struct ct_arg {
void *iocb;
u16 nport_handle;
dma_addr_t req_dma;
dma_addr_t rsp_dma;
u32 req_size;
u32 rsp_size;
void *req;
void *rsp;
};

/*
* SRB extensions.
*/
Expand All @@ -320,6 +341,7 @@ struct srb_iocb {
#define SRB_LOGIN_COND_PLOGI BIT_1
#define SRB_LOGIN_SKIP_PRLI BIT_2
uint16_t data[2];
u32 iop[2];
} logio;
struct {
#define ELS_DCMD_TIMEOUT 20
Expand Down Expand Up @@ -372,6 +394,16 @@ struct srb_iocb {
__le16 comp_status;
struct completion comp;
} abt;
struct ct_arg ctarg;
struct {
__le16 in_mb[28]; /* fr fw */
__le16 out_mb[28]; /* to fw */
void *out, *in;
dma_addr_t out_dma, in_dma;
} mbx;
struct {
struct imm_ntfy_from_isp *ntfy;
} nack;
} u;

struct timer_list timer;
Expand All @@ -392,16 +424,24 @@ struct srb_iocb {
#define SRB_FXIOCB_BCMD 11
#define SRB_ABT_CMD 12
#define SRB_ELS_DCMD 13
#define SRB_MB_IOCB 14
#define SRB_CT_PTHRU_CMD 15
#define SRB_NACK_PLOGI 16
#define SRB_NACK_PRLI 17
#define SRB_NACK_LOGO 18

typedef struct srb {
atomic_t ref_count;
struct fc_port *fcport;
void *vha;
uint32_t handle;
uint16_t flags;
uint16_t type;
char *name;
int iocbs;
struct qla_qpair *qpair;
u32 gen1; /* scratch */
u32 gen2; /* scratch */
union {
struct srb_iocb iocb_cmd;
struct bsg_job *bsg_job;
Expand Down Expand Up @@ -2101,6 +2141,18 @@ typedef struct {
#define FC4_TYPE_OTHER 0x0
#define FC4_TYPE_UNKNOWN 0xff

/* mailbox command 4G & above */
struct mbx_24xx_entry {
uint8_t entry_type;
uint8_t entry_count;
uint8_t sys_define1;
uint8_t entry_status;
uint32_t handle;
uint16_t mb[28];
};

#define IOCB_SIZE 64

/*
* Fibre channel port type.
*/
Expand All @@ -2113,6 +2165,12 @@ typedef enum {
FCT_TARGET
} fc_port_type_t;

enum qla_sess_deletion {
QLA_SESS_DELETION_NONE = 0,
QLA_SESS_DELETION_IN_PROGRESS,
QLA_SESS_DELETED,
};

enum qlt_plogi_link_t {
QLT_PLOGI_LINK_SAME_WWN,
QLT_PLOGI_LINK_CONFLICT,
Expand All @@ -2124,6 +2182,48 @@ struct qlt_plogi_ack_t {
struct imm_ntfy_from_isp iocb;
port_id_t id;
int ref_count;
void *fcport;
};

struct ct_sns_desc {
struct ct_sns_pkt *ct_sns;
dma_addr_t ct_sns_dma;
};

enum discovery_state {
DSC_DELETED,
DSC_GID_PN,
DSC_GNL,
DSC_LOGIN_PEND,
DSC_LOGIN_FAILED,
DSC_GPDB,
DSC_GPSC,
DSC_UPD_FCPORT,
DSC_LOGIN_COMPLETE,
DSC_DELETE_PEND,
};

enum login_state { /* FW control Target side */
DSC_LS_LLIOCB_SENT = 2,
DSC_LS_PLOGI_PEND,
DSC_LS_PLOGI_COMP,
DSC_LS_PRLI_PEND,
DSC_LS_PRLI_COMP,
DSC_LS_PORT_UNAVAIL,
DSC_LS_PRLO_PEND = 9,
DSC_LS_LOGO_PEND,
};

enum fcport_mgt_event {
FCME_RELOGIN = 1,
FCME_RSCN,
FCME_GIDPN_DONE,
FCME_PLOGI_DONE, /* Initiator side sent LLIOCB */
FCME_GNL_DONE,
FCME_GPSC_DONE,
FCME_GPDB_DONE,
FCME_GPNID_DONE,
FCME_DELETE_DONE,
};

/*
Expand All @@ -2143,9 +2243,13 @@ typedef struct fc_port {
unsigned int deleted:2;
unsigned int local:1;
unsigned int logout_on_delete:1;
unsigned int logo_ack_needed:1;
unsigned int keep_nport_handle:1;
unsigned int send_els_logo:1;
unsigned int login_pause:1;
unsigned int login_succ:1;

struct fc_port *conflict;
unsigned char logout_completed;
int generation;

Expand Down Expand Up @@ -2186,8 +2290,30 @@ typedef struct fc_port {

unsigned long retry_delay_timestamp;
struct qla_tgt_sess *tgt_session;
struct ct_sns_desc ct_desc;
enum discovery_state disc_state;
enum login_state fw_login_state;
u32 login_gen, last_login_gen;
u32 rscn_gen, last_rscn_gen;
u32 chip_reset;
struct list_head gnl_entry;
struct work_struct del_work;
u8 iocb[IOCB_SIZE];
} fc_port_t;

#define QLA_FCPORT_SCAN 1
#define QLA_FCPORT_FOUND 2

struct event_arg {
enum fcport_mgt_event event;
fc_port_t *fcport;
srb_t *sp;
port_id_t id;
u16 data[2], rc;
u8 port_name[WWN_SIZE];
u32 iop[2];
};

#include "qla_mr.h"

/*
Expand Down Expand Up @@ -2265,6 +2391,10 @@ static const char * const port_state_str[] = {
#define GFT_ID_REQ_SIZE (16 + 4)
#define GFT_ID_RSP_SIZE (16 + 32)

#define GID_PN_CMD 0x121
#define GID_PN_REQ_SIZE (16 + 8)
#define GID_PN_RSP_SIZE (16 + 4)

#define RFT_ID_CMD 0x217
#define RFT_ID_REQ_SIZE (16 + 4 + 32)
#define RFT_ID_RSP_SIZE 16
Expand Down Expand Up @@ -2590,6 +2720,10 @@ struct ct_sns_req {
uint8_t reserved;
uint8_t port_name[3];
} gff_id;

struct {
uint8_t port_name[8];
} gid_pn;
} req;
};

Expand Down Expand Up @@ -2669,6 +2803,10 @@ struct ct_sns_rsp {
struct {
uint8_t fc4_features[128];
} gff_id;
struct {
uint8_t reserved;
uint8_t port_id[3];
} gid_pn;
} rsp;
};

Expand Down Expand Up @@ -2810,11 +2948,11 @@ struct isp_operations {

uint16_t (*calc_req_entries) (uint16_t);
void (*build_iocbs) (srb_t *, cmd_entry_t *, uint16_t);
void * (*prep_ms_iocb) (struct scsi_qla_host *, uint32_t, uint32_t);
void * (*prep_ms_fdmi_iocb) (struct scsi_qla_host *, uint32_t,
void *(*prep_ms_iocb) (struct scsi_qla_host *, struct ct_arg *);
void *(*prep_ms_fdmi_iocb) (struct scsi_qla_host *, uint32_t,
uint32_t);

uint8_t * (*read_nvram) (struct scsi_qla_host *, uint8_t *,
uint8_t *(*read_nvram) (struct scsi_qla_host *, uint8_t *,
uint32_t, uint32_t);
int (*write_nvram) (struct scsi_qla_host *, uint8_t *, uint32_t,
uint32_t);
Expand Down Expand Up @@ -2876,13 +3014,21 @@ enum qla_work_type {
QLA_EVT_AEN,
QLA_EVT_IDC_ACK,
QLA_EVT_ASYNC_LOGIN,
QLA_EVT_ASYNC_LOGIN_DONE,
QLA_EVT_ASYNC_LOGOUT,
QLA_EVT_ASYNC_LOGOUT_DONE,
QLA_EVT_ASYNC_ADISC,
QLA_EVT_ASYNC_ADISC_DONE,
QLA_EVT_UEVENT,
QLA_EVT_AENFX,
QLA_EVT_GIDPN,
QLA_EVT_GPNID,
QLA_EVT_GPNID_DONE,
QLA_EVT_NEW_SESS,
QLA_EVT_GPDB,
QLA_EVT_GPSC,
QLA_EVT_UPD_FCPORT,
QLA_EVT_GNL,
QLA_EVT_NACK,
};


Expand Down Expand Up @@ -2918,6 +3064,23 @@ struct qla_work_evt {
struct {
srb_t *sp;
} iosb;
struct {
port_id_t id;
} gpnid;
struct {
port_id_t id;
u8 port_name[8];
void *pla;
} new_sess;
struct { /*Get PDB, Get Speed, update fcport, gnl, gidpn */
fc_port_t *fcport;
u8 opt;
} fcport;
struct {
fc_port_t *fcport;
u8 iocb[IOCB_SIZE];
int type;
} nack;
} u;
};

Expand Down Expand Up @@ -3899,6 +4062,10 @@ typedef struct scsi_qla_host {
struct qla8044_reset_template reset_tmplt;
struct qla_tgt_counters tgt_counters;
uint16_t bbcr;
struct name_list_extended gnl;
/* Count of active session/fcport */
int fcport_count;
wait_queue_head_t fcport_waitQ;
} scsi_qla_host_t;

struct qla27xx_image_status {
Expand Down
31 changes: 31 additions & 0 deletions drivers/scsi/qla2xxx/qla_fw.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,37 @@ struct port_database_24xx {
uint8_t reserved_3[24];
};

/*
* MB 75h returns a list of DB entries similar to port_database_24xx(64B).
* However, in this case it returns 1st 40 bytes.
*/
struct get_name_list_extended {
__le16 flags;
u8 current_login_state;
u8 last_login_state;
u8 hard_address[3];
u8 reserved_1;
u8 port_id[3];
u8 sequence_id;
__le16 port_timer;
__le16 nport_handle; /* N_PORT handle. */
__le16 receive_data_size;
__le16 reserved_2;

/* PRLI SVC Param are Big endian */
u8 prli_svc_param_word_0[2]; /* Bits 15-0 of word 0 */
u8 prli_svc_param_word_3[2]; /* Bits 15-0 of word 3 */
u8 port_name[WWN_SIZE];
u8 node_name[WWN_SIZE];
};

/* MB 75h: This is the short version of the database */
struct get_name_list {
u8 port_node_name[WWN_SIZE]; /* B7 most sig, B0 least sig */
__le16 nport_handle;
u8 reserved;
};

struct vp_database_24xx {
uint16_t vp_status;
uint8_t options;
Expand Down
Loading

0 comments on commit 726b854

Please sign in to comment.