Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 726b8548 authored by Quinn Tran's avatar Quinn Tran Committed by Nicholas Bellinger
Browse files

qla2xxx: Add framework for async fabric discovery



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: default avatarQuinn Tran <quinn.tran@cavium.com>
Signed-off-by: default avatarHimanshu Madhani <himanshu.madhani@cavium.com>
[ bvanassche: fixed spelling in patch description ]
Signed-off-by: default avatarBart Van Assche <bart.vanassche@sandisk.com>
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
parent 5d964837
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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,
+171 −4
Original line number Diff line number Diff line
@@ -55,6 +55,8 @@

#include "qla_settings.h"

#define MODE_DUAL (MODE_TARGET | MODE_INITIATOR)

/*
 * Data bit definitions
 */
@@ -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
 */
@@ -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.
 */
@@ -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
@@ -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;
@@ -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;
@@ -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.
 */
@@ -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,
@@ -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,
};

/*
@@ -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;

@@ -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"

/*
@@ -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
@@ -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;
};

@@ -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;
};

@@ -2810,7 +2948,7 @@ 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_iocb) (struct scsi_qla_host *, struct ct_arg *);
	void *(*prep_ms_fdmi_iocb) (struct scsi_qla_host *, uint32_t,
	    uint32_t);

@@ -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,
};


@@ -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;
};

@@ -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 {
+31 −0
Original line number Diff line number Diff line
@@ -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;
+49 −7
Original line number Diff line number Diff line
@@ -73,6 +73,10 @@ extern void qla2x00_async_logout_done(struct scsi_qla_host *, fc_port_t *,
    uint16_t *);
extern void qla2x00_async_adisc_done(struct scsi_qla_host *, fc_port_t *,
    uint16_t *);
struct qla_work_evt *qla2x00_alloc_work(struct scsi_qla_host *,
    enum qla_work_type);
extern int qla24xx_async_gnl(struct scsi_qla_host *, fc_port_t *);
int qla2x00_post_work(struct scsi_qla_host *vha, struct qla_work_evt *e);
extern void *qla2x00_alloc_iocbs(struct scsi_qla_host *, srb_t *);
extern void *qla2x00_alloc_iocbs_ready(struct scsi_qla_host *, srb_t *);
extern int qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *, fc_port_t *);
@@ -94,6 +98,13 @@ extern uint8_t qla27xx_find_valid_image(struct scsi_qla_host *);
extern struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *,
	int, int);
extern int qla2xxx_delete_qpair(struct scsi_qla_host *, struct qla_qpair *);
void qla2x00_fcport_event_handler(scsi_qla_host_t *, struct event_arg *);
int qla24xx_async_gpdb(struct scsi_qla_host *, fc_port_t *, u8);
int qla24xx_async_notify_ack(scsi_qla_host_t *, fc_port_t *,
	struct imm_ntfy_from_isp *, int);
int qla24xx_post_newsess_work(struct scsi_qla_host *, port_id_t *, u8 *,
    void *);
int qla24xx_fcport_handle_login(struct scsi_qla_host *, fc_port_t *);

/*
 * Global Data in qla_os.c source file.
@@ -135,8 +146,6 @@ extern int qla2x00_post_aen_work(struct scsi_qla_host *, enum
extern int qla2x00_post_idc_ack_work(struct scsi_qla_host *, uint16_t *);
extern int qla2x00_post_async_login_work(struct scsi_qla_host *, fc_port_t *,
    uint16_t *);
extern int qla2x00_post_async_login_done_work(struct scsi_qla_host *,
    fc_port_t *, uint16_t *);
extern int qla2x00_post_async_logout_work(struct scsi_qla_host *, fc_port_t *,
    uint16_t *);
extern int qla2x00_post_async_logout_done_work(struct scsi_qla_host *,
@@ -179,6 +188,10 @@ extern void qla2x00_disable_board_on_pci_error(struct work_struct *);
extern void qla2x00_sp_compl(void *, void *, int);
extern void qla2xxx_qpair_sp_free_dma(void *, void *);
extern void qla2xxx_qpair_sp_compl(void *, void *, int);
extern int qla24xx_post_upd_fcport_work(struct scsi_qla_host *, fc_port_t *);
void qla2x00_handle_login_done_event(struct scsi_qla_host *, fc_port_t *,
	uint16_t *);
int qla24xx_post_gnl_work(struct scsi_qla_host *, fc_port_t *);

/*
 * Global Functions in qla_mid.c source file.
@@ -301,9 +314,6 @@ qla2x00_get_retry_cnt(scsi_qla_host_t *, uint8_t *, uint8_t *, uint16_t *);
extern int
qla2x00_init_firmware(scsi_qla_host_t *, uint16_t);

extern int
qla2x00_get_node_name_list(scsi_qla_host_t *, void **, int *);

extern int
qla2x00_get_port_database(scsi_qla_host_t *, fc_port_t *, uint8_t);

@@ -483,6 +493,9 @@ qla2x00_process_completed_request(struct scsi_qla_host *, struct req_que *,
	uint32_t);
extern irqreturn_t
qla2xxx_msix_rsp_q(int irq, void *dev_id);
fc_port_t *qla2x00_find_fcport_by_loopid(scsi_qla_host_t *, uint16_t);
fc_port_t *qla2x00_find_fcport_by_wwpn(scsi_qla_host_t *, u8 *, u8);
fc_port_t *qla2x00_find_fcport_by_nportid(scsi_qla_host_t *, port_id_t *, u8);

/*
 * Global Function Prototypes in qla_sup.c source file.
@@ -574,8 +587,8 @@ extern void qla2xxx_dump_post_process(scsi_qla_host_t *, int);
/*
 * Global Function Prototypes in qla_gs.c source file.
 */
extern void *qla2x00_prep_ms_iocb(scsi_qla_host_t *, uint32_t, uint32_t);
extern void *qla24xx_prep_ms_iocb(scsi_qla_host_t *, uint32_t, uint32_t);
extern void *qla2x00_prep_ms_iocb(scsi_qla_host_t *, struct ct_arg *);
extern void *qla24xx_prep_ms_iocb(scsi_qla_host_t *, struct ct_arg *);
extern int qla2x00_ga_nxt(scsi_qla_host_t *, fc_port_t *);
extern int qla2x00_gid_pt(scsi_qla_host_t *, sw_info_t *);
extern int qla2x00_gpn_id(scsi_qla_host_t *, sw_info_t *);
@@ -591,6 +604,23 @@ extern int qla2x00_fdmi_register(scsi_qla_host_t *);
extern int qla2x00_gfpn_id(scsi_qla_host_t *, sw_info_t *);
extern int qla2x00_gpsc(scsi_qla_host_t *, sw_info_t *);
extern void qla2x00_get_sym_node_name(scsi_qla_host_t *, uint8_t *, size_t);
extern int qla2x00_chk_ms_status(scsi_qla_host_t *, ms_iocb_entry_t *,
	struct ct_sns_rsp *, const char *);
extern void qla2x00_async_iocb_timeout(void *data);
extern int qla24xx_async_gidpn(scsi_qla_host_t *, fc_port_t *);
int qla24xx_post_gidpn_work(struct scsi_qla_host *, fc_port_t *);
void qla24xx_handle_gidpn_event(scsi_qla_host_t *, struct event_arg *);

extern void qla2x00_free_fcport(fc_port_t *);

extern int qla24xx_post_gpnid_work(struct scsi_qla_host *, port_id_t *);
extern int qla24xx_async_gpnid(scsi_qla_host_t *, port_id_t *);
void qla24xx_async_gpnid_done(scsi_qla_host_t *, srb_t*);
void qla24xx_handle_gpnid_event(scsi_qla_host_t *, struct event_arg *);

int qla24xx_post_gpsc_work(struct scsi_qla_host *, fc_port_t *);
int qla24xx_async_gpsc(scsi_qla_host_t *, fc_port_t *);
int qla2x00_mgmt_svr_login(scsi_qla_host_t *);

/*
 * Global Function Prototypes in qla_attr.c source file.
@@ -803,4 +833,16 @@ extern int qla_get_exchoffld_status(scsi_qla_host_t *, uint16_t *, uint16_t *);
extern int qla_set_exchoffld_mem_cfg(scsi_qla_host_t *, dma_addr_t);
extern void qlt_handle_abts_recv(struct scsi_qla_host *, response_t *);

int qla24xx_async_notify_ack(scsi_qla_host_t *, fc_port_t *,
	struct imm_ntfy_from_isp *, int);
void qla24xx_do_nack_work(struct scsi_qla_host *, struct qla_work_evt *);
void qlt_plogi_ack_link(struct scsi_qla_host *, struct qlt_plogi_ack_t *,
	struct fc_port *, enum qlt_plogi_link_t);
void qlt_plogi_ack_unref(struct scsi_qla_host *, struct qlt_plogi_ack_t *);
extern void qlt_schedule_sess_for_deletion(struct fc_port *, bool);
extern void qlt_schedule_sess_for_deletion_lock(struct fc_port *);
extern struct fc_port *qlt_find_sess_invalidate_other(scsi_qla_host_t *,
	uint64_t wwn, port_id_t port_id, uint16_t loop_id, struct fc_port **);
void qla24xx_delete_sess_fn(struct work_struct *);

#endif /* _QLA_GBL_H */
+653 −71

File changed.

Preview size limit exceeded, changes collapsed.

Loading