mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	scsi: qla2xxx: Add switch command to simplify fabric discovery
- add "async" gpn_ft, gnn_ft, gfpn_id, gnn_id switch commands. - For 8G and newer adapters, use async commands when it comes to fabric scan to reduce bottle neck. Signed-off-by: Quinn Tran <quinn.tran@cavium.com> Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
		
							parent
							
								
									1429f0446a
								
							
						
					
					
						commit
						a4239945b8
					
				
					 9 changed files with 1105 additions and 123 deletions
				
			
		| 
						 | 
					@ -2170,6 +2170,8 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
 | 
				
			||||||
	dma_free_coherent(&ha->pdev->dev, vha->gnl.size, vha->gnl.l,
 | 
						dma_free_coherent(&ha->pdev->dev, vha->gnl.size, vha->gnl.l,
 | 
				
			||||||
	    vha->gnl.ldma);
 | 
						    vha->gnl.ldma);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						vfree(vha->scan.l);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (vha->qpair && vha->qpair->vp_idx == vha->vp_idx) {
 | 
						if (vha->qpair && vha->qpair->vp_idx == vha->vp_idx) {
 | 
				
			||||||
		if (qla2xxx_delete_qpair(vha, vha->qpair) != QLA_SUCCESS)
 | 
							if (qla2xxx_delete_qpair(vha, vha->qpair) != QLA_SUCCESS)
 | 
				
			||||||
			ql_log(ql_log_warn, vha, 0x7087,
 | 
								ql_log(ql_log_warn, vha, 0x7087,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2270,11 +2270,13 @@ struct ct_sns_desc {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum discovery_state {
 | 
					enum discovery_state {
 | 
				
			||||||
	DSC_DELETED,
 | 
						DSC_DELETED,
 | 
				
			||||||
 | 
						DSC_GNN_ID,
 | 
				
			||||||
	DSC_GID_PN,
 | 
						DSC_GID_PN,
 | 
				
			||||||
	DSC_GNL,
 | 
						DSC_GNL,
 | 
				
			||||||
	DSC_LOGIN_PEND,
 | 
						DSC_LOGIN_PEND,
 | 
				
			||||||
	DSC_LOGIN_FAILED,
 | 
						DSC_LOGIN_FAILED,
 | 
				
			||||||
	DSC_GPDB,
 | 
						DSC_GPDB,
 | 
				
			||||||
 | 
						DSC_GFPN_ID,
 | 
				
			||||||
	DSC_GPSC,
 | 
						DSC_GPSC,
 | 
				
			||||||
	DSC_UPD_FCPORT,
 | 
						DSC_UPD_FCPORT,
 | 
				
			||||||
	DSC_LOGIN_COMPLETE,
 | 
						DSC_LOGIN_COMPLETE,
 | 
				
			||||||
| 
						 | 
					@ -2304,8 +2306,9 @@ enum fcport_mgt_event {
 | 
				
			||||||
	FCME_GPDB_DONE,
 | 
						FCME_GPDB_DONE,
 | 
				
			||||||
	FCME_GPNID_DONE,
 | 
						FCME_GPNID_DONE,
 | 
				
			||||||
	FCME_GFFID_DONE,
 | 
						FCME_GFFID_DONE,
 | 
				
			||||||
	FCME_DELETE_DONE,
 | 
					 | 
				
			||||||
	FCME_ADISC_DONE,
 | 
						FCME_ADISC_DONE,
 | 
				
			||||||
 | 
						FCME_GNNID_DONE,
 | 
				
			||||||
 | 
						FCME_GFPNID_DONE,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum rscn_addr_format {
 | 
					enum rscn_addr_format {
 | 
				
			||||||
| 
						 | 
					@ -2338,6 +2341,7 @@ typedef struct fc_port {
 | 
				
			||||||
	unsigned int login_pause:1;
 | 
						unsigned int login_pause:1;
 | 
				
			||||||
	unsigned int login_succ:1;
 | 
						unsigned int login_succ:1;
 | 
				
			||||||
	unsigned int query:1;
 | 
						unsigned int query:1;
 | 
				
			||||||
 | 
						unsigned int id_changed:1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct work_struct nvme_del_work;
 | 
						struct work_struct nvme_del_work;
 | 
				
			||||||
	struct completion nvme_del_done;
 | 
						struct completion nvme_del_done;
 | 
				
			||||||
| 
						 | 
					@ -2485,6 +2489,11 @@ static const char * const port_state_str[] = {
 | 
				
			||||||
#define	GA_NXT_REQ_SIZE	(16 + 4)
 | 
					#define	GA_NXT_REQ_SIZE	(16 + 4)
 | 
				
			||||||
#define	GA_NXT_RSP_SIZE	(16 + 620)
 | 
					#define	GA_NXT_RSP_SIZE	(16 + 620)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define	GPN_FT_CMD	0x172
 | 
				
			||||||
 | 
					#define	GPN_FT_REQ_SIZE	(16 + 4)
 | 
				
			||||||
 | 
					#define	GNN_FT_CMD	0x173
 | 
				
			||||||
 | 
					#define	GNN_FT_REQ_SIZE	(16 + 4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define	GID_PT_CMD	0x1A1
 | 
					#define	GID_PT_CMD	0x1A1
 | 
				
			||||||
#define	GID_PT_REQ_SIZE	(16 + 4)
 | 
					#define	GID_PT_REQ_SIZE	(16 + 4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2739,6 +2748,13 @@ struct ct_sns_req {
 | 
				
			||||||
			uint8_t port_id[3];
 | 
								uint8_t port_id[3];
 | 
				
			||||||
		} port_id;
 | 
							} port_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							struct {
 | 
				
			||||||
 | 
								uint8_t reserved;
 | 
				
			||||||
 | 
								uint8_t domain;
 | 
				
			||||||
 | 
								uint8_t area;
 | 
				
			||||||
 | 
								uint8_t port_type;
 | 
				
			||||||
 | 
							} gpn_ft;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		struct {
 | 
							struct {
 | 
				
			||||||
			uint8_t port_type;
 | 
								uint8_t port_type;
 | 
				
			||||||
			uint8_t domain;
 | 
								uint8_t domain;
 | 
				
			||||||
| 
						 | 
					@ -2852,6 +2868,27 @@ struct ct_sns_gid_pt_data {
 | 
				
			||||||
	uint8_t port_id[3];
 | 
						uint8_t port_id[3];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* It's the same for both GPN_FT and GNN_FT */
 | 
				
			||||||
 | 
					struct ct_sns_gpnft_rsp {
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							struct ct_cmd_hdr header;
 | 
				
			||||||
 | 
							uint16_t response;
 | 
				
			||||||
 | 
							uint16_t residual;
 | 
				
			||||||
 | 
							uint8_t fragment_id;
 | 
				
			||||||
 | 
							uint8_t reason_code;
 | 
				
			||||||
 | 
							uint8_t explanation_code;
 | 
				
			||||||
 | 
							uint8_t vendor_unique;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						/* Assume the largest number of targets for the union */
 | 
				
			||||||
 | 
						struct ct_sns_gpn_ft_data {
 | 
				
			||||||
 | 
							u8 control_byte;
 | 
				
			||||||
 | 
							u8 port_id[3];
 | 
				
			||||||
 | 
							u32 reserved;
 | 
				
			||||||
 | 
							u8 port_name[8];
 | 
				
			||||||
 | 
						} entries[1];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* CT command response */
 | 
				
			||||||
struct ct_sns_rsp {
 | 
					struct ct_sns_rsp {
 | 
				
			||||||
	struct ct_rsp_hdr header;
 | 
						struct ct_rsp_hdr header;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2927,6 +2964,24 @@ struct ct_sns_pkt {
 | 
				
			||||||
	} p;
 | 
						} p;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ct_sns_gpnft_pkt {
 | 
				
			||||||
 | 
						union {
 | 
				
			||||||
 | 
							struct ct_sns_req req;
 | 
				
			||||||
 | 
							struct ct_sns_gpnft_rsp rsp;
 | 
				
			||||||
 | 
						} p;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct fab_scan_rp {
 | 
				
			||||||
 | 
						port_id_t id;
 | 
				
			||||||
 | 
						u8 port_name[8];
 | 
				
			||||||
 | 
						u8 node_name[8];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct fab_scan {
 | 
				
			||||||
 | 
						struct fab_scan_rp *l;
 | 
				
			||||||
 | 
						u32 size;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * SNS command structures -- for 2200 compatibility.
 | 
					 * SNS command structures -- for 2200 compatibility.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -3143,6 +3198,11 @@ enum qla_work_type {
 | 
				
			||||||
	QLA_EVT_RELOGIN,
 | 
						QLA_EVT_RELOGIN,
 | 
				
			||||||
	QLA_EVT_ASYNC_PRLO,
 | 
						QLA_EVT_ASYNC_PRLO,
 | 
				
			||||||
	QLA_EVT_ASYNC_PRLO_DONE,
 | 
						QLA_EVT_ASYNC_PRLO_DONE,
 | 
				
			||||||
 | 
						QLA_EVT_GPNFT,
 | 
				
			||||||
 | 
						QLA_EVT_GPNFT_DONE,
 | 
				
			||||||
 | 
						QLA_EVT_GNNFT_DONE,
 | 
				
			||||||
 | 
						QLA_EVT_GNNID,
 | 
				
			||||||
 | 
						QLA_EVT_GFPNID,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3184,7 +3244,9 @@ struct qla_work_evt {
 | 
				
			||||||
		struct {
 | 
							struct {
 | 
				
			||||||
			port_id_t id;
 | 
								port_id_t id;
 | 
				
			||||||
			u8 port_name[8];
 | 
								u8 port_name[8];
 | 
				
			||||||
 | 
								u8 node_name[8];
 | 
				
			||||||
			void *pla;
 | 
								void *pla;
 | 
				
			||||||
 | 
								u8 fc4_type;
 | 
				
			||||||
		} new_sess;
 | 
							} new_sess;
 | 
				
			||||||
		struct { /*Get PDB, Get Speed, update fcport, gnl, gidpn */
 | 
							struct { /*Get PDB, Get Speed, update fcport, gnl, gidpn */
 | 
				
			||||||
			fc_port_t *fcport;
 | 
								fc_port_t *fcport;
 | 
				
			||||||
| 
						 | 
					@ -3195,6 +3257,9 @@ struct qla_work_evt {
 | 
				
			||||||
			u8 iocb[IOCB_SIZE];
 | 
								u8 iocb[IOCB_SIZE];
 | 
				
			||||||
			int type;
 | 
								int type;
 | 
				
			||||||
		} nack;
 | 
							} nack;
 | 
				
			||||||
 | 
							struct {
 | 
				
			||||||
 | 
								u8 fc4_type;
 | 
				
			||||||
 | 
							} gpnft;
 | 
				
			||||||
	 } u;
 | 
						 } u;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3729,6 +3794,8 @@ struct qla_hw_data {
 | 
				
			||||||
	(IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha))
 | 
						(IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha))
 | 
				
			||||||
#define IS_EXLOGIN_OFFLD_CAPABLE(ha) \
 | 
					#define IS_EXLOGIN_OFFLD_CAPABLE(ha) \
 | 
				
			||||||
	(IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha))
 | 
						(IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha))
 | 
				
			||||||
 | 
					#define USE_ASYNC_SCAN(ha) (IS_QLA25XX(ha) || IS_QLA81XX(ha) ||\
 | 
				
			||||||
 | 
						IS_QLA83XX(ha) || IS_QLA27XX(ha))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* HBA serial number */
 | 
						/* HBA serial number */
 | 
				
			||||||
	uint8_t		serial0;
 | 
						uint8_t		serial0;
 | 
				
			||||||
| 
						 | 
					@ -3811,7 +3878,7 @@ struct qla_hw_data {
 | 
				
			||||||
	int		exchoffld_size;
 | 
						int		exchoffld_size;
 | 
				
			||||||
	int 		exchoffld_count;
 | 
						int 		exchoffld_count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void		*swl;
 | 
						void            *swl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* These are used by mailbox operations. */
 | 
						/* These are used by mailbox operations. */
 | 
				
			||||||
	uint16_t mailbox_out[MAILBOX_REGISTER_COUNT];
 | 
						uint16_t mailbox_out[MAILBOX_REGISTER_COUNT];
 | 
				
			||||||
| 
						 | 
					@ -4271,6 +4338,7 @@ typedef struct scsi_qla_host {
 | 
				
			||||||
	uint8_t n2n_port_name[WWN_SIZE];
 | 
						uint8_t n2n_port_name[WWN_SIZE];
 | 
				
			||||||
	uint16_t	n2n_id;
 | 
						uint16_t	n2n_id;
 | 
				
			||||||
	struct list_head gpnid_list;
 | 
						struct list_head gpnid_list;
 | 
				
			||||||
 | 
						struct fab_scan scan;
 | 
				
			||||||
} scsi_qla_host_t;
 | 
					} scsi_qla_host_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct qla27xx_image_status {
 | 
					struct qla27xx_image_status {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -105,8 +105,8 @@ int qla24xx_async_gpdb(struct scsi_qla_host *, fc_port_t *, u8);
 | 
				
			||||||
int qla24xx_async_prli(struct scsi_qla_host *, fc_port_t *);
 | 
					int qla24xx_async_prli(struct scsi_qla_host *, fc_port_t *);
 | 
				
			||||||
int qla24xx_async_notify_ack(scsi_qla_host_t *, fc_port_t *,
 | 
					int qla24xx_async_notify_ack(scsi_qla_host_t *, fc_port_t *,
 | 
				
			||||||
	struct imm_ntfy_from_isp *, int);
 | 
						struct imm_ntfy_from_isp *, int);
 | 
				
			||||||
int qla24xx_post_newsess_work(struct scsi_qla_host *, port_id_t *, u8 *,
 | 
					int qla24xx_post_newsess_work(struct scsi_qla_host *, port_id_t *, u8 *, u8*,
 | 
				
			||||||
    void *);
 | 
					    void *, u8);
 | 
				
			||||||
int qla24xx_fcport_handle_login(struct scsi_qla_host *, fc_port_t *);
 | 
					int qla24xx_fcport_handle_login(struct scsi_qla_host *, fc_port_t *);
 | 
				
			||||||
int qla24xx_detect_sfp(scsi_qla_host_t *vha);
 | 
					int qla24xx_detect_sfp(scsi_qla_host_t *vha);
 | 
				
			||||||
int qla24xx_post_gpdb_work(struct scsi_qla_host *, fc_port_t *, u8);
 | 
					int qla24xx_post_gpdb_work(struct scsi_qla_host *, fc_port_t *, u8);
 | 
				
			||||||
| 
						 | 
					@ -655,9 +655,20 @@ 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_post_gpsc_work(struct scsi_qla_host *, fc_port_t *);
 | 
				
			||||||
int qla24xx_async_gpsc(scsi_qla_host_t *, fc_port_t *);
 | 
					int qla24xx_async_gpsc(scsi_qla_host_t *, fc_port_t *);
 | 
				
			||||||
 | 
					void qla24xx_handle_gpsc_event(scsi_qla_host_t *, struct event_arg *);
 | 
				
			||||||
int qla2x00_mgmt_svr_login(scsi_qla_host_t *);
 | 
					int qla2x00_mgmt_svr_login(scsi_qla_host_t *);
 | 
				
			||||||
void qla24xx_handle_gffid_event(scsi_qla_host_t *vha, struct event_arg *ea);
 | 
					void qla24xx_handle_gffid_event(scsi_qla_host_t *vha, struct event_arg *ea);
 | 
				
			||||||
int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport);
 | 
					int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport);
 | 
				
			||||||
 | 
					int qla24xx_async_gpnft(scsi_qla_host_t *, u8);
 | 
				
			||||||
 | 
					void qla24xx_async_gpnft_done(scsi_qla_host_t *, srb_t *);
 | 
				
			||||||
 | 
					void qla24xx_async_gnnft_done(scsi_qla_host_t *, srb_t *);
 | 
				
			||||||
 | 
					int qla24xx_async_gnnid(scsi_qla_host_t *, fc_port_t *);
 | 
				
			||||||
 | 
					void qla24xx_handle_gnnid_event(scsi_qla_host_t *, struct event_arg *);
 | 
				
			||||||
 | 
					int qla24xx_post_gnnid_work(struct scsi_qla_host *, fc_port_t *);
 | 
				
			||||||
 | 
					int qla24xx_post_gfpnid_work(struct scsi_qla_host *, fc_port_t *);
 | 
				
			||||||
 | 
					int qla24xx_async_gfpnid(scsi_qla_host_t *, fc_port_t *);
 | 
				
			||||||
 | 
					void qla24xx_handle_gfpnid_event(scsi_qla_host_t *, struct event_arg *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Global Function Prototypes in qla_attr.c source file.
 | 
					 * Global Function Prototypes in qla_attr.c source file.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2796,6 +2796,9 @@ void qla24xx_handle_gidpn_event(scsi_qla_host_t *vha, struct event_arg *ea)
 | 
				
			||||||
	    "%s %8phC login state %d\n",
 | 
						    "%s %8phC login state %d\n",
 | 
				
			||||||
	    __func__, fcport->port_name, fcport->fw_login_state);
 | 
						    __func__, fcport->port_name, fcport->fw_login_state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (fcport->disc_state == DSC_DELETE_PEND)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ea->sp->gen2 != fcport->login_gen) {
 | 
						if (ea->sp->gen2 != fcport->login_gen) {
 | 
				
			||||||
		/* PLOGI/PRLI/LOGO came in while cmd was out.*/
 | 
							/* PLOGI/PRLI/LOGO came in while cmd was out.*/
 | 
				
			||||||
		ql_dbg(ql_dbg_disc, vha, 0x201e,
 | 
							ql_dbg(ql_dbg_disc, vha, 0x201e,
 | 
				
			||||||
| 
						 | 
					@ -2814,7 +2817,21 @@ void qla24xx_handle_gidpn_event(scsi_qla_host_t *vha, struct event_arg *ea)
 | 
				
			||||||
				/* cable plugged into the same place */
 | 
									/* cable plugged into the same place */
 | 
				
			||||||
				switch (vha->host->active_mode) {
 | 
									switch (vha->host->active_mode) {
 | 
				
			||||||
				case MODE_TARGET:
 | 
									case MODE_TARGET:
 | 
				
			||||||
					/* NOOP. let the other guy login to us.*/
 | 
										if (fcport->fw_login_state ==
 | 
				
			||||||
 | 
										    DSC_LS_PRLI_COMP) {
 | 
				
			||||||
 | 
											u16 data[2];
 | 
				
			||||||
 | 
											/*
 | 
				
			||||||
 | 
											 * Late RSCN was delivered.
 | 
				
			||||||
 | 
											 * Remote port already login'ed.
 | 
				
			||||||
 | 
											 */
 | 
				
			||||||
 | 
											ql_dbg(ql_dbg_disc, vha, 0x201f,
 | 
				
			||||||
 | 
											    "%s %d %8phC post adisc\n",
 | 
				
			||||||
 | 
											    __func__, __LINE__,
 | 
				
			||||||
 | 
											    fcport->port_name);
 | 
				
			||||||
 | 
											data[0] = data[1] = 0;
 | 
				
			||||||
 | 
											qla2x00_post_async_adisc_work(
 | 
				
			||||||
 | 
											    vha, fcport, data);
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case MODE_INITIATOR:
 | 
									case MODE_INITIATOR:
 | 
				
			||||||
				case MODE_DUAL:
 | 
									case MODE_DUAL:
 | 
				
			||||||
| 
						 | 
					@ -2840,6 +2857,7 @@ void qla24xx_handle_gidpn_event(scsi_qla_host_t *vha, struct event_arg *ea)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			} else { /* fcport->d_id.b24 != ea->id.b24 */
 | 
								} else { /* fcport->d_id.b24 != ea->id.b24 */
 | 
				
			||||||
				fcport->d_id.b24 = ea->id.b24;
 | 
									fcport->d_id.b24 = ea->id.b24;
 | 
				
			||||||
 | 
									fcport->id_changed = 1;
 | 
				
			||||||
				if (fcport->deleted != QLA_SESS_DELETED) {
 | 
									if (fcport->deleted != QLA_SESS_DELETED) {
 | 
				
			||||||
					ql_dbg(ql_dbg_disc, vha, 0x2021,
 | 
										ql_dbg(ql_dbg_disc, vha, 0x2021,
 | 
				
			||||||
					    "%s %d %8phC post del sess\n",
 | 
										    "%s %d %8phC post del sess\n",
 | 
				
			||||||
| 
						 | 
					@ -3009,6 +3027,38 @@ int qla24xx_post_gpsc_work(struct scsi_qla_host *vha, fc_port_t *fcport)
 | 
				
			||||||
	return qla2x00_post_work(vha, e);
 | 
						return qla2x00_post_work(vha, e);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void qla24xx_handle_gpsc_event(scsi_qla_host_t *vha, struct event_arg *ea)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct fc_port *fcport = ea->fcport;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ql_dbg(ql_dbg_disc, vha, 0x20d8,
 | 
				
			||||||
 | 
						    "%s %8phC DS %d LS %d rscn %d|%d login %d|%d lid %d\n",
 | 
				
			||||||
 | 
						    __func__, fcport->port_name, fcport->disc_state,
 | 
				
			||||||
 | 
						    fcport->fw_login_state, fcport->last_rscn_gen, fcport->rscn_gen,
 | 
				
			||||||
 | 
						    fcport->last_login_gen, fcport->login_gen,
 | 
				
			||||||
 | 
						    fcport->loop_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (fcport->disc_state == DSC_DELETE_PEND)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ea->sp->gen2 != fcport->login_gen) {
 | 
				
			||||||
 | 
							/* target side must have changed it. */
 | 
				
			||||||
 | 
							ql_dbg(ql_dbg_disc, vha, 0x20d3,
 | 
				
			||||||
 | 
							    "%s %8phC generation changed rscn %d|%d login %d|%d\n",
 | 
				
			||||||
 | 
							    __func__, fcport->port_name, fcport->last_rscn_gen,
 | 
				
			||||||
 | 
							    fcport->rscn_gen, fcport->last_login_gen,
 | 
				
			||||||
 | 
							    fcport->login_gen);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						} else if (ea->sp->gen1 != fcport->rscn_gen) {
 | 
				
			||||||
 | 
							ql_dbg(ql_dbg_disc, vha, 0x20d4, "%s %d %8phC post gidpn\n",
 | 
				
			||||||
 | 
							    __func__, __LINE__, fcport->port_name);
 | 
				
			||||||
 | 
							qla24xx_post_gidpn_work(vha, fcport);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						qla24xx_post_upd_fcport_work(vha, ea->fcport);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void qla24xx_async_gpsc_sp_done(void *s, int res)
 | 
					static void qla24xx_async_gpsc_sp_done(void *s, int res)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct srb *sp = s;
 | 
						struct srb *sp = s;
 | 
				
			||||||
| 
						 | 
					@ -3075,6 +3125,7 @@ static void qla24xx_async_gpsc_sp_done(void *s, int res)
 | 
				
			||||||
	ea.event = FCME_GPSC_DONE;
 | 
						ea.event = FCME_GPSC_DONE;
 | 
				
			||||||
	ea.rc = res;
 | 
						ea.rc = res;
 | 
				
			||||||
	ea.fcport = fcport;
 | 
						ea.fcport = fcport;
 | 
				
			||||||
 | 
						ea.sp = sp;
 | 
				
			||||||
	qla2x00_fcport_event_handler(vha, &ea);
 | 
						qla2x00_fcport_event_handler(vha, &ea);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sp->free(sp);
 | 
						sp->free(sp);
 | 
				
			||||||
| 
						 | 
					@ -3305,7 +3356,7 @@ void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
 | 
				
			||||||
			    "%s %d %8phC post new sess\n",
 | 
								    "%s %d %8phC post new sess\n",
 | 
				
			||||||
			    __func__, __LINE__, ea->port_name);
 | 
								    __func__, __LINE__, ea->port_name);
 | 
				
			||||||
			qla24xx_post_newsess_work(vha, &ea->id,
 | 
								qla24xx_post_newsess_work(vha, &ea->id,
 | 
				
			||||||
			    ea->port_name, NULL);
 | 
								    ea->port_name, NULL, NULL, FC4_TYPE_UNKNOWN);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -3595,3 +3646,659 @@ int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport)
 | 
				
			||||||
	fcport->flags &= ~FCF_ASYNC_SENT;
 | 
						fcport->flags &= ~FCF_ASYNC_SENT;
 | 
				
			||||||
	return rval;
 | 
						return rval;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* GPN_FT + GNN_FT*/
 | 
				
			||||||
 | 
					static int qla2x00_is_a_vp(scsi_qla_host_t *vha, u64 wwn)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct qla_hw_data *ha = vha->hw;
 | 
				
			||||||
 | 
						scsi_qla_host_t *vp;
 | 
				
			||||||
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
						u64 twwn;
 | 
				
			||||||
 | 
						int rc = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!ha->num_vhosts)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_irqsave(&ha->vport_slock, flags);
 | 
				
			||||||
 | 
						list_for_each_entry(vp, &ha->vp_list, list) {
 | 
				
			||||||
 | 
							twwn = wwn_to_u64(vp->port_name);
 | 
				
			||||||
 | 
							if (wwn == twwn) {
 | 
				
			||||||
 | 
								rc = 1;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						spin_unlock_irqrestore(&ha->vport_slock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return rc;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						fc_port_t *fcport;
 | 
				
			||||||
 | 
						u32 i, rc;
 | 
				
			||||||
 | 
						bool found;
 | 
				
			||||||
 | 
						u8 fc4type = sp->gen2;
 | 
				
			||||||
 | 
						struct fab_scan_rp *rp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ql_dbg(ql_dbg_disc, vha, 0xffff,
 | 
				
			||||||
 | 
						    "%s enter\n", __func__);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (sp->gen1 != vha->hw->base_qpair->chip_reset) {
 | 
				
			||||||
 | 
							ql_dbg(ql_dbg_disc, vha, 0xffff,
 | 
				
			||||||
 | 
							    "%s scan stop due to chip reset %x/%x\n",
 | 
				
			||||||
 | 
							    sp->name, sp->gen1, vha->hw->base_qpair->chip_reset);
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rc = sp->rc;
 | 
				
			||||||
 | 
						if (rc) {
 | 
				
			||||||
 | 
							ql_dbg(ql_dbg_disc, vha, 0xffff,
 | 
				
			||||||
 | 
							    "GPNFT failed. FC4type %x. Rescanning.\n",
 | 
				
			||||||
 | 
							    fc4type);
 | 
				
			||||||
 | 
							set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list_for_each_entry(fcport, &vha->vp_fcports, list)
 | 
				
			||||||
 | 
							fcport->scan_state = QLA_FCPORT_SCAN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < vha->hw->max_fibre_devices; i++) {
 | 
				
			||||||
 | 
							u64 wwn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							rp = &vha->scan.l[i];
 | 
				
			||||||
 | 
							found = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							wwn = wwn_to_u64(rp->port_name);
 | 
				
			||||||
 | 
							if (wwn == 0)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!memcmp(rp->port_name, vha->port_name, WWN_SIZE))
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Bypass reserved domain fields. */
 | 
				
			||||||
 | 
							if ((rp->id.b.domain & 0xf0) == 0xf0)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Bypass virtual ports of the same host. */
 | 
				
			||||||
 | 
							if (qla2x00_is_a_vp(vha, wwn))
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							list_for_each_entry(fcport, &vha->vp_fcports, list) {
 | 
				
			||||||
 | 
								if (memcmp(rp->port_name, fcport->port_name, WWN_SIZE))
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								fcport->scan_state = QLA_FCPORT_FOUND;
 | 
				
			||||||
 | 
								fcport->d_id.b24 = rp->id.b24;
 | 
				
			||||||
 | 
								found = true;
 | 
				
			||||||
 | 
								/*
 | 
				
			||||||
 | 
								 * If device was not a fabric device before.
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
 | 
								if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) {
 | 
				
			||||||
 | 
									qla2x00_clear_loop_id(fcport);
 | 
				
			||||||
 | 
									fcport->flags |= FCF_FABRIC_DEVICE;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!found) {
 | 
				
			||||||
 | 
								ql_dbg(ql_dbg_disc, vha, 0xffff,
 | 
				
			||||||
 | 
								    "%s %d %8phC post new sess\n",
 | 
				
			||||||
 | 
								    __func__, __LINE__, rp->port_name);
 | 
				
			||||||
 | 
								qla24xx_post_newsess_work(vha, &rp->id, rp->port_name,
 | 
				
			||||||
 | 
								    rp->node_name, NULL, fc4type);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Logout all previous fabric dev marked lost, except FCP2 devices.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						list_for_each_entry(fcport, &vha->vp_fcports, list) {
 | 
				
			||||||
 | 
							if ((fcport->flags & FCF_FABRIC_DEVICE) == 0)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (fcport->scan_state == QLA_FCPORT_SCAN) {
 | 
				
			||||||
 | 
								if ((qla_dual_mode_enabled(vha) ||
 | 
				
			||||||
 | 
									qla_ini_mode_enabled(vha)) &&
 | 
				
			||||||
 | 
								    atomic_read(&fcport->state) == FCS_ONLINE) {
 | 
				
			||||||
 | 
									qla2x00_mark_device_lost(vha, fcport,
 | 
				
			||||||
 | 
									    ql2xplogiabsentdevice, 0);
 | 
				
			||||||
 | 
									if (fcport->loop_id != FC_NO_LOOP_ID &&
 | 
				
			||||||
 | 
									    (fcport->flags & FCF_FCP2_DEVICE) == 0 &&
 | 
				
			||||||
 | 
									    fcport->port_type != FCT_INITIATOR &&
 | 
				
			||||||
 | 
									    fcport->port_type != FCT_BROADCAST) {
 | 
				
			||||||
 | 
										ql_dbg(ql_dbg_disc, vha, 0x20f0,
 | 
				
			||||||
 | 
										    "%s %d %8phC post del sess\n",
 | 
				
			||||||
 | 
										    __func__, __LINE__,
 | 
				
			||||||
 | 
										    fcport->port_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										qlt_schedule_sess_for_deletion_lock
 | 
				
			||||||
 | 
											(fcport);
 | 
				
			||||||
 | 
										continue;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (fcport->scan_state == QLA_FCPORT_FOUND)
 | 
				
			||||||
 | 
								qla24xx_fcport_handle_login(vha, fcport);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					out:
 | 
				
			||||||
 | 
						/* re-use gpnid_done to free resource */
 | 
				
			||||||
 | 
						qla24xx_async_gpnid_done(vha, sp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void qla2x00_async_gpnft_gnnft_sp_done(void *s, int res)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct srb *sp = s;
 | 
				
			||||||
 | 
						struct scsi_qla_host *vha = sp->vha;
 | 
				
			||||||
 | 
						struct qla_work_evt *e;
 | 
				
			||||||
 | 
						struct ct_sns_req *ct_req =
 | 
				
			||||||
 | 
							(struct ct_sns_req *)sp->u.iocb_cmd.u.ctarg.req;
 | 
				
			||||||
 | 
						struct ct_sns_gpnft_rsp *ct_rsp =
 | 
				
			||||||
 | 
							(struct ct_sns_gpnft_rsp *)sp->u.iocb_cmd.u.ctarg.rsp;
 | 
				
			||||||
 | 
						struct ct_sns_gpn_ft_data *d = &ct_rsp->entries[0];
 | 
				
			||||||
 | 
						struct fab_scan_rp *rp;
 | 
				
			||||||
 | 
						int i, j, k;
 | 
				
			||||||
 | 
						u16 cmd = be16_to_cpu(ct_req->command);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* gen2 field is holding the fc4type */
 | 
				
			||||||
 | 
						ql_dbg(ql_dbg_disc, vha, 0xffff,
 | 
				
			||||||
 | 
						    "Async done-%s res %x FC4Type %x\n",
 | 
				
			||||||
 | 
						    sp->name, res, sp->gen2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!res) {
 | 
				
			||||||
 | 
							port_id_t id;
 | 
				
			||||||
 | 
							u64 wwn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							j = 0;
 | 
				
			||||||
 | 
							for (i = 0; i < vha->hw->max_fibre_devices; i++) {
 | 
				
			||||||
 | 
								d  = &ct_rsp->entries[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								id.b.rsvd_1 = 0;
 | 
				
			||||||
 | 
								id.b.domain = d->port_id[0];
 | 
				
			||||||
 | 
								id.b.area   = d->port_id[1];
 | 
				
			||||||
 | 
								id.b.al_pa  = d->port_id[2];
 | 
				
			||||||
 | 
								wwn = wwn_to_u64(d->port_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (id.b24 == 0 || wwn == 0)
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (cmd == GPN_FT_CMD) {
 | 
				
			||||||
 | 
									rp = &vha->scan.l[j];
 | 
				
			||||||
 | 
									rp->id = id;
 | 
				
			||||||
 | 
									memcpy(rp->port_name, d->port_name, 8);
 | 
				
			||||||
 | 
									j++;
 | 
				
			||||||
 | 
								} else {/* GNN_FT_CMD */
 | 
				
			||||||
 | 
									for (k = 0; k < vha->hw->max_fibre_devices;
 | 
				
			||||||
 | 
									    k++) {
 | 
				
			||||||
 | 
										rp = &vha->scan.l[k];
 | 
				
			||||||
 | 
										if (id.b24 == rp->id.b24) {
 | 
				
			||||||
 | 
											memcpy(rp->node_name,
 | 
				
			||||||
 | 
											    d->port_name, 8);
 | 
				
			||||||
 | 
											break;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (cmd == GPN_FT_CMD)
 | 
				
			||||||
 | 
							e = qla2x00_alloc_work(vha, QLA_EVT_GPNFT_DONE);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							e = qla2x00_alloc_work(vha, QLA_EVT_GNNFT_DONE);
 | 
				
			||||||
 | 
						if (!e) {
 | 
				
			||||||
 | 
							/* please ignore kernel warning. Otherwise, we have mem leak. */
 | 
				
			||||||
 | 
							if (sp->u.iocb_cmd.u.ctarg.req) {
 | 
				
			||||||
 | 
								dma_free_coherent(&vha->hw->pdev->dev,
 | 
				
			||||||
 | 
								    sizeof(struct ct_sns_pkt),
 | 
				
			||||||
 | 
								    sp->u.iocb_cmd.u.ctarg.req,
 | 
				
			||||||
 | 
								    sp->u.iocb_cmd.u.ctarg.req_dma);
 | 
				
			||||||
 | 
								sp->u.iocb_cmd.u.ctarg.req = NULL;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (sp->u.iocb_cmd.u.ctarg.rsp) {
 | 
				
			||||||
 | 
								dma_free_coherent(&vha->hw->pdev->dev,
 | 
				
			||||||
 | 
								    sizeof(struct ct_sns_pkt),
 | 
				
			||||||
 | 
								    sp->u.iocb_cmd.u.ctarg.rsp,
 | 
				
			||||||
 | 
								    sp->u.iocb_cmd.u.ctarg.rsp_dma);
 | 
				
			||||||
 | 
								sp->u.iocb_cmd.u.ctarg.rsp = NULL;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ql_dbg(ql_dbg_disc, vha, 0xffff,
 | 
				
			||||||
 | 
							    "Async done-%s unable to alloc work element\n",
 | 
				
			||||||
 | 
							    sp->name);
 | 
				
			||||||
 | 
							sp->free(sp);
 | 
				
			||||||
 | 
							set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sp->rc = res;
 | 
				
			||||||
 | 
						e->u.iosb.sp = sp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						qla2x00_post_work(vha, e);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Get WWNN list for fc4_type
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * It is assumed the same SRB is re-used from GPNFT to avoid
 | 
				
			||||||
 | 
					 * mem free & re-alloc
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int qla24xx_async_gnnft(scsi_qla_host_t *vha, struct srb *sp,
 | 
				
			||||||
 | 
					    u8 fc4_type)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int rval = QLA_FUNCTION_FAILED;
 | 
				
			||||||
 | 
						struct ct_sns_req *ct_req;
 | 
				
			||||||
 | 
						struct ct_sns_pkt *ct_sns;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!vha->flags.online)
 | 
				
			||||||
 | 
							goto done_free_sp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!sp->u.iocb_cmd.u.ctarg.req || !sp->u.iocb_cmd.u.ctarg.rsp) {
 | 
				
			||||||
 | 
							ql_log(ql_log_warn, vha, 0xffff,
 | 
				
			||||||
 | 
							    "%s: req %p rsp %p are not setup\n",
 | 
				
			||||||
 | 
							    __func__, sp->u.iocb_cmd.u.ctarg.req,
 | 
				
			||||||
 | 
							    sp->u.iocb_cmd.u.ctarg.rsp);
 | 
				
			||||||
 | 
							WARN_ON(1);
 | 
				
			||||||
 | 
							goto done_free_sp;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						sp->type = SRB_CT_PTHRU_CMD;
 | 
				
			||||||
 | 
						sp->name = "gnnft";
 | 
				
			||||||
 | 
						sp->gen1 = vha->hw->base_qpair->chip_reset;
 | 
				
			||||||
 | 
						sp->gen2 = fc4_type;
 | 
				
			||||||
 | 
						qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset(sp->u.iocb_cmd.u.ctarg.rsp, 0, sp->u.iocb_cmd.u.ctarg.rsp_size);
 | 
				
			||||||
 | 
						memset(sp->u.iocb_cmd.u.ctarg.req, 0, sp->u.iocb_cmd.u.ctarg.req_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;
 | 
				
			||||||
 | 
						/* CT_IU preamble  */
 | 
				
			||||||
 | 
						ct_req = qla2x00_prep_ct_req(ct_sns, GNN_FT_CMD,
 | 
				
			||||||
 | 
						    sp->u.iocb_cmd.u.ctarg.rsp_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* GPN_FT req */
 | 
				
			||||||
 | 
						ct_req->req.gpn_ft.port_type = fc4_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sp->u.iocb_cmd.u.ctarg.req_size = GNN_FT_REQ_SIZE;
 | 
				
			||||||
 | 
						sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
 | 
				
			||||||
 | 
						sp->done = qla2x00_async_gpnft_gnnft_sp_done;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rval = qla2x00_start_sp(sp);
 | 
				
			||||||
 | 
						if (rval != QLA_SUCCESS)
 | 
				
			||||||
 | 
							goto done_free_sp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ql_dbg(ql_dbg_disc, vha, 0xffff,
 | 
				
			||||||
 | 
						    "Async-%s hdl=%x FC4Type %x.\n", sp->name,
 | 
				
			||||||
 | 
						    sp->handle, ct_req->req.gpn_ft.port_type);
 | 
				
			||||||
 | 
						return rval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					done_free_sp:
 | 
				
			||||||
 | 
						if (sp->u.iocb_cmd.u.ctarg.req) {
 | 
				
			||||||
 | 
							dma_free_coherent(&vha->hw->pdev->dev,
 | 
				
			||||||
 | 
							    sizeof(struct ct_sns_pkt),
 | 
				
			||||||
 | 
							    sp->u.iocb_cmd.u.ctarg.req,
 | 
				
			||||||
 | 
							    sp->u.iocb_cmd.u.ctarg.req_dma);
 | 
				
			||||||
 | 
							sp->u.iocb_cmd.u.ctarg.req = NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (sp->u.iocb_cmd.u.ctarg.rsp) {
 | 
				
			||||||
 | 
							dma_free_coherent(&vha->hw->pdev->dev,
 | 
				
			||||||
 | 
							    sizeof(struct ct_sns_pkt),
 | 
				
			||||||
 | 
							    sp->u.iocb_cmd.u.ctarg.rsp,
 | 
				
			||||||
 | 
							    sp->u.iocb_cmd.u.ctarg.rsp_dma);
 | 
				
			||||||
 | 
							sp->u.iocb_cmd.u.ctarg.rsp = NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sp->free(sp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return rval;
 | 
				
			||||||
 | 
					} /* GNNFT */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void qla24xx_async_gpnft_done(scsi_qla_host_t *vha, srb_t *sp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						ql_dbg(ql_dbg_disc, vha, 0xffff,
 | 
				
			||||||
 | 
						    "%s enter\n", __func__);
 | 
				
			||||||
 | 
						del_timer(&sp->u.iocb_cmd.timer);
 | 
				
			||||||
 | 
						qla24xx_async_gnnft(vha, sp, sp->gen2);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Get WWPN list for certain fc4_type */
 | 
				
			||||||
 | 
					int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int rval = QLA_FUNCTION_FAILED;
 | 
				
			||||||
 | 
						struct ct_sns_req       *ct_req;
 | 
				
			||||||
 | 
						srb_t *sp;
 | 
				
			||||||
 | 
						struct ct_sns_pkt *ct_sns;
 | 
				
			||||||
 | 
						u32 rspsz;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!vha->flags.online)
 | 
				
			||||||
 | 
							return rval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!sp)
 | 
				
			||||||
 | 
							return rval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sp->type = SRB_CT_PTHRU_CMD;
 | 
				
			||||||
 | 
						sp->name = "gpnft";
 | 
				
			||||||
 | 
						sp->gen1 = vha->hw->base_qpair->chip_reset;
 | 
				
			||||||
 | 
						sp->gen2 = fc4_type;
 | 
				
			||||||
 | 
						qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sp->u.iocb_cmd.u.ctarg.req = dma_zalloc_coherent(&vha->hw->pdev->dev,
 | 
				
			||||||
 | 
						    sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,
 | 
				
			||||||
 | 
						    GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!sp->u.iocb_cmd.u.ctarg.req) {
 | 
				
			||||||
 | 
							ql_log(ql_log_warn, vha, 0xffff,
 | 
				
			||||||
 | 
							    "Failed to allocate ct_sns request.\n");
 | 
				
			||||||
 | 
							goto done_free_sp;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rspsz = sizeof(struct ct_sns_gpnft_rsp) +
 | 
				
			||||||
 | 
							((vha->hw->max_fibre_devices - 1) *
 | 
				
			||||||
 | 
							    sizeof(struct ct_sns_gpn_ft_data));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sp->u.iocb_cmd.u.ctarg.rsp = dma_zalloc_coherent(&vha->hw->pdev->dev,
 | 
				
			||||||
 | 
						    rspsz, &sp->u.iocb_cmd.u.ctarg.rsp_dma, GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!sp->u.iocb_cmd.u.ctarg.rsp) {
 | 
				
			||||||
 | 
							ql_log(ql_log_warn, vha, 0xffff,
 | 
				
			||||||
 | 
							    "Failed to allocate ct_sns request.\n");
 | 
				
			||||||
 | 
							goto done_free_sp;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset(vha->scan.l, 0, vha->scan.size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;
 | 
				
			||||||
 | 
						/* CT_IU preamble  */
 | 
				
			||||||
 | 
						ct_req = qla2x00_prep_ct_req(ct_sns, GPN_FT_CMD, rspsz);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* GPN_FT req */
 | 
				
			||||||
 | 
						ct_req->req.gpn_ft.port_type = fc4_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sp->u.iocb_cmd.u.ctarg.req_size = GPN_FT_REQ_SIZE;
 | 
				
			||||||
 | 
						sp->u.iocb_cmd.u.ctarg.rsp_size = rspsz;
 | 
				
			||||||
 | 
						sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
 | 
				
			||||||
 | 
						sp->done = qla2x00_async_gpnft_gnnft_sp_done;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rval = qla2x00_start_sp(sp);
 | 
				
			||||||
 | 
						if (rval != QLA_SUCCESS)
 | 
				
			||||||
 | 
							goto done_free_sp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ql_dbg(ql_dbg_disc, vha, 0xffff,
 | 
				
			||||||
 | 
						    "Async-%s hdl=%x FC4Type %x.\n", sp->name,
 | 
				
			||||||
 | 
						    sp->handle, ct_req->req.gpn_ft.port_type);
 | 
				
			||||||
 | 
						return rval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					done_free_sp:
 | 
				
			||||||
 | 
						if (sp->u.iocb_cmd.u.ctarg.req) {
 | 
				
			||||||
 | 
							dma_free_coherent(&vha->hw->pdev->dev,
 | 
				
			||||||
 | 
							    sizeof(struct ct_sns_pkt),
 | 
				
			||||||
 | 
							    sp->u.iocb_cmd.u.ctarg.req,
 | 
				
			||||||
 | 
							    sp->u.iocb_cmd.u.ctarg.req_dma);
 | 
				
			||||||
 | 
							sp->u.iocb_cmd.u.ctarg.req = NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (sp->u.iocb_cmd.u.ctarg.rsp) {
 | 
				
			||||||
 | 
							dma_free_coherent(&vha->hw->pdev->dev,
 | 
				
			||||||
 | 
							    sizeof(struct ct_sns_pkt),
 | 
				
			||||||
 | 
							    sp->u.iocb_cmd.u.ctarg.rsp,
 | 
				
			||||||
 | 
							    sp->u.iocb_cmd.u.ctarg.rsp_dma);
 | 
				
			||||||
 | 
							sp->u.iocb_cmd.u.ctarg.rsp = NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sp->free(sp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return rval;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* GNN_ID */
 | 
				
			||||||
 | 
					void qla24xx_handle_gnnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						qla24xx_post_gnl_work(vha, ea->fcport);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void qla2x00_async_gnnid_sp_done(void *s, int res)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct srb *sp = s;
 | 
				
			||||||
 | 
						struct scsi_qla_host *vha = sp->vha;
 | 
				
			||||||
 | 
						fc_port_t *fcport = sp->fcport;
 | 
				
			||||||
 | 
						u8 *node_name = fcport->ct_desc.ct_sns->p.rsp.rsp.gnn_id.node_name;
 | 
				
			||||||
 | 
						struct event_arg ea;
 | 
				
			||||||
 | 
						u64 wwnn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fcport->flags &= ~FCF_ASYNC_SENT;
 | 
				
			||||||
 | 
						wwnn = wwn_to_u64(node_name);
 | 
				
			||||||
 | 
						if (wwnn)
 | 
				
			||||||
 | 
							memcpy(fcport->node_name, node_name, WWN_SIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset(&ea, 0, sizeof(ea));
 | 
				
			||||||
 | 
						ea.fcport = fcport;
 | 
				
			||||||
 | 
						ea.sp = sp;
 | 
				
			||||||
 | 
						ea.rc = res;
 | 
				
			||||||
 | 
						ea.event = FCME_GNNID_DONE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ql_dbg(ql_dbg_disc, vha, 0x204f,
 | 
				
			||||||
 | 
						    "Async done-%s res %x, WWPN %8phC %8phC\n",
 | 
				
			||||||
 | 
						    sp->name, res, fcport->port_name, fcport->node_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						qla2x00_fcport_event_handler(vha, &ea);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sp->free(sp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int qla24xx_async_gnnid(scsi_qla_host_t *vha, fc_port_t *fcport)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int rval = QLA_FUNCTION_FAILED;
 | 
				
			||||||
 | 
						struct ct_sns_req       *ct_req;
 | 
				
			||||||
 | 
						srb_t *sp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!vha->flags.online)
 | 
				
			||||||
 | 
							goto done;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fcport->flags |= FCF_ASYNC_SENT;
 | 
				
			||||||
 | 
						fcport->disc_state = DSC_GNN_ID;
 | 
				
			||||||
 | 
						sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
 | 
				
			||||||
 | 
						if (!sp)
 | 
				
			||||||
 | 
							goto done;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sp->type = SRB_CT_PTHRU_CMD;
 | 
				
			||||||
 | 
						sp->name = "gnnid";
 | 
				
			||||||
 | 
						sp->gen1 = fcport->rscn_gen;
 | 
				
			||||||
 | 
						sp->gen2 = fcport->login_gen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* CT_IU preamble  */
 | 
				
			||||||
 | 
						ct_req = qla2x00_prep_ct_req(fcport->ct_desc.ct_sns, GNN_ID_CMD,
 | 
				
			||||||
 | 
						    GNN_ID_RSP_SIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* GNN_ID req */
 | 
				
			||||||
 | 
						ct_req->req.port_id.port_id[0] = fcport->d_id.b.domain;
 | 
				
			||||||
 | 
						ct_req->req.port_id.port_id[1] = fcport->d_id.b.area;
 | 
				
			||||||
 | 
						ct_req->req.port_id.port_id[2] = fcport->d_id.b.al_pa;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* req & rsp use the same buffer */
 | 
				
			||||||
 | 
						sp->u.iocb_cmd.u.ctarg.req = fcport->ct_desc.ct_sns;
 | 
				
			||||||
 | 
						sp->u.iocb_cmd.u.ctarg.req_dma = fcport->ct_desc.ct_sns_dma;
 | 
				
			||||||
 | 
						sp->u.iocb_cmd.u.ctarg.rsp = fcport->ct_desc.ct_sns;
 | 
				
			||||||
 | 
						sp->u.iocb_cmd.u.ctarg.rsp_dma = fcport->ct_desc.ct_sns_dma;
 | 
				
			||||||
 | 
						sp->u.iocb_cmd.u.ctarg.req_size = GNN_ID_REQ_SIZE;
 | 
				
			||||||
 | 
						sp->u.iocb_cmd.u.ctarg.rsp_size = GNN_ID_RSP_SIZE;
 | 
				
			||||||
 | 
						sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
 | 
				
			||||||
 | 
						sp->done = qla2x00_async_gnnid_sp_done;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rval = qla2x00_start_sp(sp);
 | 
				
			||||||
 | 
						if (rval != QLA_SUCCESS)
 | 
				
			||||||
 | 
							goto done_free_sp;
 | 
				
			||||||
 | 
						ql_dbg(ql_dbg_disc, vha, 0xffff,
 | 
				
			||||||
 | 
						    "Async-%s - %8phC hdl=%x loopid=%x portid %06x.\n",
 | 
				
			||||||
 | 
						    sp->name, fcport->port_name,
 | 
				
			||||||
 | 
						    sp->handle, fcport->loop_id, fcport->d_id.b24);
 | 
				
			||||||
 | 
						return rval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					done_free_sp:
 | 
				
			||||||
 | 
						sp->free(sp);
 | 
				
			||||||
 | 
					done:
 | 
				
			||||||
 | 
						fcport->flags &= ~FCF_ASYNC_SENT;
 | 
				
			||||||
 | 
						return rval;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int qla24xx_post_gnnid_work(struct scsi_qla_host *vha, fc_port_t *fcport)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct qla_work_evt *e;
 | 
				
			||||||
 | 
						int ls;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ls = atomic_read(&vha->loop_state);
 | 
				
			||||||
 | 
						if (((ls != LOOP_READY) && (ls != LOOP_UP)) ||
 | 
				
			||||||
 | 
							test_bit(UNLOADING, &vha->dpc_flags))
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						e = qla2x00_alloc_work(vha, QLA_EVT_GNNID);
 | 
				
			||||||
 | 
						if (!e)
 | 
				
			||||||
 | 
							return QLA_FUNCTION_FAILED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						e->u.fcport.fcport = fcport;
 | 
				
			||||||
 | 
						return qla2x00_post_work(vha, e);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* GPFN_ID */
 | 
				
			||||||
 | 
					void qla24xx_handle_gfpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						fc_port_t *fcport = ea->fcport;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ql_dbg(ql_dbg_disc, vha, 0xffff,
 | 
				
			||||||
 | 
						    "%s %d %8phC post gpsc fcp_cnt %d\n",
 | 
				
			||||||
 | 
						    __func__, __LINE__, fcport->port_name,
 | 
				
			||||||
 | 
						    vha->fcport_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (fcport->disc_state == DSC_DELETE_PEND)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ea->sp->gen2 != fcport->login_gen) {
 | 
				
			||||||
 | 
							/* target side must have changed it. */
 | 
				
			||||||
 | 
							ql_dbg(ql_dbg_disc, vha, 0x20d3,
 | 
				
			||||||
 | 
							    "%s %8phC generation changed rscn %d|%d login %d|%d\n",
 | 
				
			||||||
 | 
							    __func__, fcport->port_name, fcport->last_rscn_gen,
 | 
				
			||||||
 | 
							    fcport->rscn_gen, fcport->last_login_gen,
 | 
				
			||||||
 | 
							    fcport->login_gen);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						} else if (ea->sp->gen1 != fcport->rscn_gen) {
 | 
				
			||||||
 | 
							ql_dbg(ql_dbg_disc, vha, 0x20d4, "%s %d %8phC post gidpn\n",
 | 
				
			||||||
 | 
							    __func__, __LINE__, fcport->port_name);
 | 
				
			||||||
 | 
							qla24xx_post_gidpn_work(vha, fcport);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						qla24xx_post_gpsc_work(vha, fcport);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void qla2x00_async_gfpnid_sp_done(void *s, int res)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct srb *sp = s;
 | 
				
			||||||
 | 
						struct scsi_qla_host *vha = sp->vha;
 | 
				
			||||||
 | 
						fc_port_t *fcport = sp->fcport;
 | 
				
			||||||
 | 
						u8 *fpn = fcport->ct_desc.ct_sns->p.rsp.rsp.gfpn_id.port_name;
 | 
				
			||||||
 | 
						struct event_arg ea;
 | 
				
			||||||
 | 
						u64 wwn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fcport->flags &= ~FCF_ASYNC_SENT;
 | 
				
			||||||
 | 
						wwn = wwn_to_u64(fpn);
 | 
				
			||||||
 | 
						if (wwn)
 | 
				
			||||||
 | 
							memcpy(fcport->fabric_port_name, fpn, WWN_SIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset(&ea, 0, sizeof(ea));
 | 
				
			||||||
 | 
						ea.fcport = fcport;
 | 
				
			||||||
 | 
						ea.sp = sp;
 | 
				
			||||||
 | 
						ea.rc = res;
 | 
				
			||||||
 | 
						ea.event = FCME_GFPNID_DONE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ql_dbg(ql_dbg_disc, vha, 0x204f,
 | 
				
			||||||
 | 
						    "Async done-%s res %x, WWPN %8phC %8phC\n",
 | 
				
			||||||
 | 
						    sp->name, res, fcport->port_name, fcport->fabric_port_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						qla2x00_fcport_event_handler(vha, &ea);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sp->free(sp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int qla24xx_async_gfpnid(scsi_qla_host_t *vha, fc_port_t *fcport)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int rval = QLA_FUNCTION_FAILED;
 | 
				
			||||||
 | 
						struct ct_sns_req       *ct_req;
 | 
				
			||||||
 | 
						srb_t *sp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!vha->flags.online)
 | 
				
			||||||
 | 
							goto done;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fcport->flags |= FCF_ASYNC_SENT;
 | 
				
			||||||
 | 
						fcport->disc_state = DSC_GFPN_ID;
 | 
				
			||||||
 | 
						sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
 | 
				
			||||||
 | 
						if (!sp)
 | 
				
			||||||
 | 
							goto done;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sp->type = SRB_CT_PTHRU_CMD;
 | 
				
			||||||
 | 
						sp->name = "gfpnid";
 | 
				
			||||||
 | 
						sp->gen1 = fcport->rscn_gen;
 | 
				
			||||||
 | 
						sp->gen2 = fcport->login_gen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* CT_IU preamble  */
 | 
				
			||||||
 | 
						ct_req = qla2x00_prep_ct_req(fcport->ct_desc.ct_sns, GFPN_ID_CMD,
 | 
				
			||||||
 | 
						    GFPN_ID_RSP_SIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* GFPN_ID req */
 | 
				
			||||||
 | 
						ct_req->req.port_id.port_id[0] = fcport->d_id.b.domain;
 | 
				
			||||||
 | 
						ct_req->req.port_id.port_id[1] = fcport->d_id.b.area;
 | 
				
			||||||
 | 
						ct_req->req.port_id.port_id[2] = fcport->d_id.b.al_pa;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* req & rsp use the same buffer */
 | 
				
			||||||
 | 
						sp->u.iocb_cmd.u.ctarg.req = fcport->ct_desc.ct_sns;
 | 
				
			||||||
 | 
						sp->u.iocb_cmd.u.ctarg.req_dma = fcport->ct_desc.ct_sns_dma;
 | 
				
			||||||
 | 
						sp->u.iocb_cmd.u.ctarg.rsp = fcport->ct_desc.ct_sns;
 | 
				
			||||||
 | 
						sp->u.iocb_cmd.u.ctarg.rsp_dma = fcport->ct_desc.ct_sns_dma;
 | 
				
			||||||
 | 
						sp->u.iocb_cmd.u.ctarg.req_size = GFPN_ID_REQ_SIZE;
 | 
				
			||||||
 | 
						sp->u.iocb_cmd.u.ctarg.rsp_size = GFPN_ID_RSP_SIZE;
 | 
				
			||||||
 | 
						sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
 | 
				
			||||||
 | 
						sp->done = qla2x00_async_gfpnid_sp_done;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rval = qla2x00_start_sp(sp);
 | 
				
			||||||
 | 
						if (rval != QLA_SUCCESS)
 | 
				
			||||||
 | 
							goto done_free_sp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ql_dbg(ql_dbg_disc, vha, 0xffff,
 | 
				
			||||||
 | 
						    "Async-%s - %8phC hdl=%x loopid=%x portid %06x.\n",
 | 
				
			||||||
 | 
						    sp->name, fcport->port_name,
 | 
				
			||||||
 | 
						    sp->handle, fcport->loop_id, fcport->d_id.b24);
 | 
				
			||||||
 | 
						return rval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					done_free_sp:
 | 
				
			||||||
 | 
						sp->free(sp);
 | 
				
			||||||
 | 
					done:
 | 
				
			||||||
 | 
						fcport->flags &= ~FCF_ASYNC_SENT;
 | 
				
			||||||
 | 
						return rval;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int qla24xx_post_gfpnid_work(struct scsi_qla_host *vha, fc_port_t *fcport)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct qla_work_evt *e;
 | 
				
			||||||
 | 
						int ls;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ls = atomic_read(&vha->loop_state);
 | 
				
			||||||
 | 
						if (((ls != LOOP_READY) && (ls != LOOP_UP)) ||
 | 
				
			||||||
 | 
							test_bit(UNLOADING, &vha->dpc_flags))
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						e = qla2x00_alloc_work(vha, QLA_EVT_GFPNID);
 | 
				
			||||||
 | 
						if (!e)
 | 
				
			||||||
 | 
							return QLA_FUNCTION_FAILED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						e->u.fcport.fcport = fcport;
 | 
				
			||||||
 | 
						return qla2x00_post_work(vha, e);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,7 +41,7 @@ static void qla24xx_handle_plogi_done_event(struct scsi_qla_host *,
 | 
				
			||||||
    struct event_arg *);
 | 
					    struct event_arg *);
 | 
				
			||||||
static void qla24xx_handle_prli_done_event(struct scsi_qla_host *,
 | 
					static void qla24xx_handle_prli_done_event(struct scsi_qla_host *,
 | 
				
			||||||
    struct event_arg *);
 | 
					    struct event_arg *);
 | 
				
			||||||
static void qla24xx_handle_gpdb_event(scsi_qla_host_t *, struct event_arg *);
 | 
					static void __qla24xx_handle_gpdb_event(scsi_qla_host_t *, struct event_arg *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* SRB Extensions ---------------------------------------------------------- */
 | 
					/* SRB Extensions ---------------------------------------------------------- */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -188,8 +188,11 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
 | 
				
			||||||
	fcport->flags |= FCF_ASYNC_SENT;
 | 
						fcport->flags |= FCF_ASYNC_SENT;
 | 
				
			||||||
	fcport->logout_completed = 0;
 | 
						fcport->logout_completed = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fcport->disc_state = DSC_LOGIN_PEND;
 | 
				
			||||||
	sp->type = SRB_LOGIN_CMD;
 | 
						sp->type = SRB_LOGIN_CMD;
 | 
				
			||||||
	sp->name = "login";
 | 
						sp->name = "login";
 | 
				
			||||||
 | 
						sp->gen1 = fcport->rscn_gen;
 | 
				
			||||||
 | 
						sp->gen2 = fcport->login_gen;
 | 
				
			||||||
	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
 | 
						qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	lio = &sp->u.iocb_cmd;
 | 
						lio = &sp->u.iocb_cmd;
 | 
				
			||||||
| 
						 | 
					@ -336,7 +339,36 @@ qla2x00_async_prlo(struct scsi_qla_host *vha, fc_port_t *fcport)
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, struct event_arg *ea)
 | 
					void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, struct event_arg *ea)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	qla24xx_handle_gpdb_event(vha, ea);
 | 
						if (ea->rc) {
 | 
				
			||||||
 | 
							ql_dbg(ql_dbg_disc, vha, 0x2066,
 | 
				
			||||||
 | 
							    "%s %8phC: adisc fail: post delete\n",
 | 
				
			||||||
 | 
							    __func__, ea->fcport->port_name);
 | 
				
			||||||
 | 
							qlt_schedule_sess_for_deletion(ea->fcport, 1);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ql_dbg(ql_dbg_disc, vha, 0x20d2,
 | 
				
			||||||
 | 
						    "%s %8phC DS %d LS %d\n", __func__, ea->fcport->port_name,
 | 
				
			||||||
 | 
						    ea->fcport->disc_state, ea->fcport->fw_login_state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ea->fcport->disc_state == DSC_DELETE_PEND)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ea->sp->gen2 != ea->fcport->login_gen) {
 | 
				
			||||||
 | 
							/* target side must have changed it. */
 | 
				
			||||||
 | 
							ql_dbg(ql_dbg_disc, vha, 0x20d3,
 | 
				
			||||||
 | 
							    "%s %8phC generation changed rscn %d|%d login %d|%d\n",
 | 
				
			||||||
 | 
							    __func__, ea->fcport->port_name, ea->fcport->last_rscn_gen,
 | 
				
			||||||
 | 
							    ea->fcport->rscn_gen, ea->fcport->last_login_gen,
 | 
				
			||||||
 | 
							    ea->fcport->login_gen);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						} else if (ea->sp->gen1 != ea->fcport->rscn_gen) {
 | 
				
			||||||
 | 
							ql_dbg(ql_dbg_disc, vha, 0x20d4, "%s %d %8phC post gidpn\n",
 | 
				
			||||||
 | 
							    __func__, __LINE__, ea->fcport->port_name);
 | 
				
			||||||
 | 
							qla24xx_post_gidpn_work(vha, ea->fcport);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						__qla24xx_handle_gpdb_event(vha, ea);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
| 
						 | 
					@ -409,10 +441,14 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
 | 
				
			||||||
	u16 i, n, found = 0, loop_id;
 | 
						u16 i, n, found = 0, loop_id;
 | 
				
			||||||
	port_id_t id;
 | 
						port_id_t id;
 | 
				
			||||||
	u64 wwn;
 | 
						u64 wwn;
 | 
				
			||||||
	u8 opt = 0, current_login_state;
 | 
						u16 data[2];
 | 
				
			||||||
 | 
						u8 current_login_state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fcport = ea->fcport;
 | 
						fcport = ea->fcport;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (fcport->disc_state == DSC_DELETE_PEND)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ea->rc) { /* rval */
 | 
						if (ea->rc) { /* rval */
 | 
				
			||||||
		if (fcport->login_retry == 0) {
 | 
							if (fcport->login_retry == 0) {
 | 
				
			||||||
			fcport->login_retry = vha->hw->login_retry_count;
 | 
								fcport->login_retry = vha->hw->login_retry_count;
 | 
				
			||||||
| 
						 | 
					@ -506,8 +542,14 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
 | 
				
			||||||
			ql_dbg(ql_dbg_disc, vha, 0x20e4,
 | 
								ql_dbg(ql_dbg_disc, vha, 0x20e4,
 | 
				
			||||||
			    "%s %d %8phC post gpdb\n",
 | 
								    "%s %d %8phC post gpdb\n",
 | 
				
			||||||
			    __func__, __LINE__, fcport->port_name);
 | 
								    __func__, __LINE__, fcport->port_name);
 | 
				
			||||||
			opt = PDO_FORCE_ADISC;
 | 
					
 | 
				
			||||||
			qla24xx_post_gpdb_work(vha, fcport, opt);
 | 
								if ((e->prli_svc_param_word_3[0] & BIT_4) == 0)
 | 
				
			||||||
 | 
									fcport->port_type = FCT_INITIATOR;
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									fcport->port_type = FCT_TARGET;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								data[0] = data[1] = 0;
 | 
				
			||||||
 | 
								qla2x00_post_async_adisc_work(vha, fcport, data);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case DSC_LS_PORT_UNAVAIL:
 | 
							case DSC_LS_PORT_UNAVAIL:
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
| 
						 | 
					@ -572,6 +614,7 @@ qla24xx_async_gnl_sp_done(void *s, int res)
 | 
				
			||||||
	struct get_name_list_extended *e;
 | 
						struct get_name_list_extended *e;
 | 
				
			||||||
	u64 wwn;
 | 
						u64 wwn;
 | 
				
			||||||
	struct list_head h;
 | 
						struct list_head h;
 | 
				
			||||||
 | 
						bool found = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ql_dbg(ql_dbg_disc, vha, 0x20e7,
 | 
						ql_dbg(ql_dbg_disc, vha, 0x20e7,
 | 
				
			||||||
	    "Async done-%s res %x mb[1]=%x mb[2]=%x \n",
 | 
						    "Async done-%s res %x mb[1]=%x mb[2]=%x \n",
 | 
				
			||||||
| 
						 | 
					@ -621,6 +664,38 @@ qla24xx_async_gnl_sp_done(void *s, int res)
 | 
				
			||||||
		qla2x00_fcport_event_handler(vha, &ea);
 | 
							qla2x00_fcport_event_handler(vha, &ea);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* create new fcport if fw has knowledge of new sessions */
 | 
				
			||||||
 | 
						for (i = 0; i < n; i++) {
 | 
				
			||||||
 | 
							port_id_t id;
 | 
				
			||||||
 | 
							u64 wwnn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							e = &vha->gnl.l[i];
 | 
				
			||||||
 | 
							wwn = wwn_to_u64(e->port_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							found = false;
 | 
				
			||||||
 | 
							list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) {
 | 
				
			||||||
 | 
								if (!memcmp((u8 *)&wwn, fcport->port_name,
 | 
				
			||||||
 | 
								    WWN_SIZE)) {
 | 
				
			||||||
 | 
									found = true;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							id.b.domain = e->port_id[0];
 | 
				
			||||||
 | 
							id.b.area = e->port_id[1];
 | 
				
			||||||
 | 
							id.b.al_pa = e->port_id[2];
 | 
				
			||||||
 | 
							id.b.rsvd_1 = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!found && wwn && !IS_SW_RESV_ADDR(id)) {
 | 
				
			||||||
 | 
								ql_dbg(ql_dbg_disc, vha, 0x2065,
 | 
				
			||||||
 | 
								    "%s %d %8phC post new sess\n",
 | 
				
			||||||
 | 
								    __func__, __LINE__, (u8 *)&wwn);
 | 
				
			||||||
 | 
								wwnn = wwn_to_u64(e->node_name);
 | 
				
			||||||
 | 
								qla24xx_post_newsess_work(vha, &id, (u8 *)&wwn,
 | 
				
			||||||
 | 
								    (u8 *)&wwnn, NULL, FC4_TYPE_UNKNOWN);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
 | 
						spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sp->free(sp);
 | 
						sp->free(sp);
 | 
				
			||||||
| 
						 | 
					@ -715,10 +790,8 @@ void qla24xx_async_gpdb_sp_done(void *s, int res)
 | 
				
			||||||
	struct srb *sp = s;
 | 
						struct srb *sp = s;
 | 
				
			||||||
	struct scsi_qla_host *vha = sp->vha;
 | 
						struct scsi_qla_host *vha = sp->vha;
 | 
				
			||||||
	struct qla_hw_data *ha = vha->hw;
 | 
						struct qla_hw_data *ha = vha->hw;
 | 
				
			||||||
	struct port_database_24xx *pd;
 | 
					 | 
				
			||||||
	fc_port_t *fcport = sp->fcport;
 | 
						fc_port_t *fcport = sp->fcport;
 | 
				
			||||||
	u16 *mb = sp->u.iocb_cmd.u.mbx.in_mb;
 | 
						u16 *mb = sp->u.iocb_cmd.u.mbx.in_mb;
 | 
				
			||||||
	int rval = QLA_SUCCESS;
 | 
					 | 
				
			||||||
	struct event_arg ea;
 | 
						struct event_arg ea;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ql_dbg(ql_dbg_disc, vha, 0x20db,
 | 
						ql_dbg(ql_dbg_disc, vha, 0x20db,
 | 
				
			||||||
| 
						 | 
					@ -727,19 +800,8 @@ void qla24xx_async_gpdb_sp_done(void *s, int res)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fcport->flags &= ~FCF_ASYNC_SENT;
 | 
						fcport->flags &= ~FCF_ASYNC_SENT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (res) {
 | 
					 | 
				
			||||||
		rval = res;
 | 
					 | 
				
			||||||
		goto gpd_error_out;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pd = (struct port_database_24xx *)sp->u.iocb_cmd.u.mbx.in;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	rval = __qla24xx_parse_gpdb(vha, fcport, pd);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
gpd_error_out:
 | 
					 | 
				
			||||||
	memset(&ea, 0, sizeof(ea));
 | 
						memset(&ea, 0, sizeof(ea));
 | 
				
			||||||
	ea.event = FCME_GPDB_DONE;
 | 
						ea.event = FCME_GPDB_DONE;
 | 
				
			||||||
	ea.rc = rval;
 | 
					 | 
				
			||||||
	ea.fcport = fcport;
 | 
						ea.fcport = fcport;
 | 
				
			||||||
	ea.sp = sp;
 | 
						ea.sp = sp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -934,41 +996,10 @@ int qla24xx_async_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
 | 
					void __qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int rval = ea->rc;
 | 
					 | 
				
			||||||
	fc_port_t *fcport = ea->fcport;
 | 
					 | 
				
			||||||
	unsigned long flags;
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fcport->flags &= ~FCF_ASYNC_SENT;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ql_dbg(ql_dbg_disc, vha, 0x20d2,
 | 
					 | 
				
			||||||
	    "%s %8phC DS %d LS %d rval %d\n", __func__, fcport->port_name,
 | 
					 | 
				
			||||||
	    fcport->disc_state, fcport->fw_login_state, rval);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (ea->sp->gen2 != fcport->login_gen) {
 | 
					 | 
				
			||||||
		/* target side must have changed it. */
 | 
					 | 
				
			||||||
		ql_dbg(ql_dbg_disc, vha, 0x20d3,
 | 
					 | 
				
			||||||
		    "%s %8phC generation changed rscn %d|%d login %d|%d \n",
 | 
					 | 
				
			||||||
		    __func__, fcport->port_name, fcport->last_rscn_gen,
 | 
					 | 
				
			||||||
		    fcport->rscn_gen, fcport->last_login_gen,
 | 
					 | 
				
			||||||
		    fcport->login_gen);
 | 
					 | 
				
			||||||
		set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	} else if (ea->sp->gen1 != fcport->rscn_gen) {
 | 
					 | 
				
			||||||
		ql_dbg(ql_dbg_disc, vha, 0x20d4, "%s %d %8phC post gidpn\n",
 | 
					 | 
				
			||||||
		    __func__, __LINE__, fcport->port_name);
 | 
					 | 
				
			||||||
		qla24xx_post_gidpn_work(vha, fcport);
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (rval != QLA_SUCCESS) {
 | 
					 | 
				
			||||||
		ql_dbg(ql_dbg_disc, vha, 0x20d5, "%s %d %8phC post del sess\n",
 | 
					 | 
				
			||||||
		    __func__, __LINE__, fcport->port_name);
 | 
					 | 
				
			||||||
		qlt_schedule_sess_for_deletion_lock(fcport);
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
 | 
						spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
 | 
				
			||||||
	ea->fcport->login_gen++;
 | 
						ea->fcport->login_gen++;
 | 
				
			||||||
	ea->fcport->deleted = 0;
 | 
						ea->fcport->deleted = 0;
 | 
				
			||||||
| 
						 | 
					@ -982,32 +1013,81 @@ void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
 | 
				
			||||||
		    !vha->hw->flags.gpsc_supported) {
 | 
							    !vha->hw->flags.gpsc_supported) {
 | 
				
			||||||
			ql_dbg(ql_dbg_disc, vha, 0x20d6,
 | 
								ql_dbg(ql_dbg_disc, vha, 0x20d6,
 | 
				
			||||||
			    "%s %d %8phC post upd_fcport fcp_cnt %d\n",
 | 
								    "%s %d %8phC post upd_fcport fcp_cnt %d\n",
 | 
				
			||||||
			    __func__, __LINE__, fcport->port_name,
 | 
								    __func__, __LINE__,  ea->fcport->port_name,
 | 
				
			||||||
			    vha->fcport_count);
 | 
								    vha->fcport_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			qla24xx_post_upd_fcport_work(vha, fcport);
 | 
								qla24xx_post_upd_fcport_work(vha, ea->fcport);
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			ql_dbg(ql_dbg_disc, vha, 0x20d7,
 | 
								if (ea->fcport->id_changed) {
 | 
				
			||||||
			    "%s %d %8phC post gpsc fcp_cnt %d\n",
 | 
									ea->fcport->id_changed = 0;
 | 
				
			||||||
			    __func__, __LINE__, fcport->port_name,
 | 
									ql_dbg(ql_dbg_disc, vha, 0x20d7,
 | 
				
			||||||
			    vha->fcport_count);
 | 
									    "%s %d %8phC post gfpnid fcp_cnt %d\n",
 | 
				
			||||||
 | 
									    __func__, __LINE__, ea->fcport->port_name,
 | 
				
			||||||
			qla24xx_post_gpsc_work(vha, fcport);
 | 
									    vha->fcport_count);
 | 
				
			||||||
 | 
									qla24xx_post_gfpnid_work(vha, ea->fcport);
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									ql_dbg(ql_dbg_disc, vha, 0x20d7,
 | 
				
			||||||
 | 
									    "%s %d %8phC post gpsc fcp_cnt %d\n",
 | 
				
			||||||
 | 
									    __func__, __LINE__, ea->fcport->port_name,
 | 
				
			||||||
 | 
									    vha->fcport_count);
 | 
				
			||||||
 | 
									qla24xx_post_gpsc_work(vha, ea->fcport);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else if (ea->fcport->login_succ) {
 | 
						} else if (ea->fcport->login_succ) {
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * We have an existing session. A late RSCN delivery
 | 
							 * We have an existing session. A late RSCN delivery
 | 
				
			||||||
		 * must have triggered the session to be re-validate.
 | 
							 * must have triggered the session to be re-validate.
 | 
				
			||||||
		 * session is still valid.
 | 
							 * Session is still valid.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		ql_dbg(ql_dbg_disc, vha, 0x20d6,
 | 
							ql_dbg(ql_dbg_disc, vha, 0x20d6,
 | 
				
			||||||
		    "%s %d %8phC session revalidate success\n",
 | 
							    "%s %d %8phC session revalidate success\n",
 | 
				
			||||||
		    __func__, __LINE__, fcport->port_name);
 | 
							    __func__, __LINE__, ea->fcport->port_name);
 | 
				
			||||||
		fcport->disc_state = DSC_LOGIN_COMPLETE;
 | 
							 ea->fcport->disc_state = DSC_LOGIN_COMPLETE;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
 | 
						spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
 | 
				
			||||||
} /* gpdb event */
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
 | 
					void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int rval = ea->rc;
 | 
				
			||||||
 | 
						fc_port_t *fcport = ea->fcport;
 | 
				
			||||||
 | 
						struct port_database_24xx *pd;
 | 
				
			||||||
 | 
						struct srb *sp = ea->sp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pd = (struct port_database_24xx *)sp->u.iocb_cmd.u.mbx.in;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fcport->flags &= ~FCF_ASYNC_SENT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ql_dbg(ql_dbg_disc, vha, 0x20d2,
 | 
				
			||||||
 | 
						    "%s %8phC DS %d LS %d rval %d\n", __func__, fcport->port_name,
 | 
				
			||||||
 | 
						    fcport->disc_state, pd->current_login_state, rval);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (fcport->disc_state == DSC_DELETE_PEND)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (pd->current_login_state) {
 | 
				
			||||||
 | 
						case PDS_PRLI_COMPLETE:
 | 
				
			||||||
 | 
							__qla24xx_parse_gpdb(vha, fcport, pd);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case PDS_PLOGI_PENDING:
 | 
				
			||||||
 | 
						case PDS_PLOGI_COMPLETE:
 | 
				
			||||||
 | 
						case PDS_PRLI_PENDING:
 | 
				
			||||||
 | 
						case PDS_PRLI2_PENDING:
 | 
				
			||||||
 | 
							ql_dbg(ql_dbg_disc, vha, 0x20d5, "%s %d %8phC relogin needed\n",
 | 
				
			||||||
 | 
							    __func__, __LINE__, fcport->port_name);
 | 
				
			||||||
 | 
							set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						case PDS_LOGO_PENDING:
 | 
				
			||||||
 | 
						case PDS_PORT_UNAVAILABLE:
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							ql_dbg(ql_dbg_disc, vha, 0x20d5, "%s %d %8phC post del sess\n",
 | 
				
			||||||
 | 
							    __func__, __LINE__, fcport->port_name);
 | 
				
			||||||
 | 
							qlt_schedule_sess_for_deletion_lock(fcport);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						__qla24xx_handle_gpdb_event(vha, ea);
 | 
				
			||||||
 | 
					} /* gpdb event */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void qla_chk_n2n_b4_login(struct scsi_qla_host *vha, fc_port_t *fcport)
 | 
					static void qla_chk_n2n_b4_login(struct scsi_qla_host *vha, fc_port_t *fcport)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -1048,22 +1128,22 @@ static void qla_chk_n2n_b4_login(struct scsi_qla_host *vha, fc_port_t *fcport)
 | 
				
			||||||
int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
 | 
					int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	u16 data[2];
 | 
						u16 data[2];
 | 
				
			||||||
 | 
						u64 wwn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ql_dbg(ql_dbg_disc, vha, 0x20d8,
 | 
				
			||||||
 | 
						    "%s %8phC DS %d LS %d P %d fl %x confl %p rscn %d|%d login %d|%d retry %d lid %d scan %d\n",
 | 
				
			||||||
 | 
						    __func__, fcport->port_name, fcport->disc_state,
 | 
				
			||||||
 | 
						    fcport->fw_login_state, fcport->login_pause, fcport->flags,
 | 
				
			||||||
 | 
						    fcport->conflict, fcport->last_rscn_gen, fcport->rscn_gen,
 | 
				
			||||||
 | 
						    fcport->last_login_gen, fcport->login_gen, fcport->login_retry,
 | 
				
			||||||
 | 
						    fcport->loop_id, fcport->scan_state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (fcport->login_retry == 0)
 | 
						if (fcport->login_retry == 0)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (fcport->scan_state != QLA_FCPORT_FOUND)
 | 
						if (fcport->scan_state != QLA_FCPORT_FOUND)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ql_dbg(ql_dbg_disc, vha, 0x20d8,
 | 
					 | 
				
			||||||
	    "%s %8phC DS %d LS %d P %d fl %x confl %p rscn %d|%d login %d|%d retry %d lid %d\n",
 | 
					 | 
				
			||||||
	    __func__, fcport->port_name, fcport->disc_state,
 | 
					 | 
				
			||||||
	    fcport->fw_login_state, fcport->login_pause, fcport->flags,
 | 
					 | 
				
			||||||
	    fcport->conflict, fcport->last_rscn_gen, fcport->rscn_gen,
 | 
					 | 
				
			||||||
	    fcport->last_login_gen, fcport->login_gen, fcport->login_retry,
 | 
					 | 
				
			||||||
	    fcport->loop_id);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	fcport->login_retry--;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
 | 
						if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
 | 
				
			||||||
	    (fcport->fw_login_state == DSC_LS_PRLI_PEND))
 | 
						    (fcport->fw_login_state == DSC_LS_PRLI_PEND))
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
| 
						 | 
					@ -1084,9 +1164,17 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fcport->login_retry--;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (fcport->disc_state) {
 | 
						switch (fcport->disc_state) {
 | 
				
			||||||
	case DSC_DELETED:
 | 
						case DSC_DELETED:
 | 
				
			||||||
		if (fcport->loop_id == FC_NO_LOOP_ID) {
 | 
							wwn = wwn_to_u64(fcport->node_name);
 | 
				
			||||||
 | 
							if (wwn == 0) {
 | 
				
			||||||
 | 
								ql_dbg(ql_dbg_disc, vha, 0xffff,
 | 
				
			||||||
 | 
								    "%s %d %8phC post GNNID\n",
 | 
				
			||||||
 | 
								    __func__, __LINE__, fcport->port_name);
 | 
				
			||||||
 | 
								qla24xx_post_gnnid_work(vha, fcport);
 | 
				
			||||||
 | 
							} else if (fcport->loop_id == FC_NO_LOOP_ID) {
 | 
				
			||||||
			ql_dbg(ql_dbg_disc, vha, 0x20bd,
 | 
								ql_dbg(ql_dbg_disc, vha, 0x20bd,
 | 
				
			||||||
			    "%s %d %8phC post gnl\n",
 | 
								    "%s %d %8phC post gnl\n",
 | 
				
			||||||
			    __func__, __LINE__, fcport->port_name);
 | 
								    __func__, __LINE__, fcport->port_name);
 | 
				
			||||||
| 
						 | 
					@ -1157,7 +1245,7 @@ void qla24xx_handle_rscn_event(fc_port_t *fcport, struct event_arg *ea)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int qla24xx_post_newsess_work(struct scsi_qla_host *vha, port_id_t *id,
 | 
					int qla24xx_post_newsess_work(struct scsi_qla_host *vha, port_id_t *id,
 | 
				
			||||||
	u8 *port_name, void *pla)
 | 
					    u8 *port_name, u8 *node_name, void *pla, u8 fc4_type)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct qla_work_evt *e;
 | 
						struct qla_work_evt *e;
 | 
				
			||||||
	e = qla2x00_alloc_work(vha, QLA_EVT_NEW_SESS);
 | 
						e = qla2x00_alloc_work(vha, QLA_EVT_NEW_SESS);
 | 
				
			||||||
| 
						 | 
					@ -1166,36 +1254,14 @@ int qla24xx_post_newsess_work(struct scsi_qla_host *vha, port_id_t *id,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	e->u.new_sess.id = *id;
 | 
						e->u.new_sess.id = *id;
 | 
				
			||||||
	e->u.new_sess.pla = pla;
 | 
						e->u.new_sess.pla = pla;
 | 
				
			||||||
 | 
						e->u.new_sess.fc4_type = fc4_type;
 | 
				
			||||||
	memcpy(e->u.new_sess.port_name, port_name, WWN_SIZE);
 | 
						memcpy(e->u.new_sess.port_name, port_name, WWN_SIZE);
 | 
				
			||||||
 | 
						if (node_name)
 | 
				
			||||||
 | 
							memcpy(e->u.new_sess.node_name, node_name, WWN_SIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return qla2x00_post_work(vha, e);
 | 
						return qla2x00_post_work(vha, e);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static
 | 
					 | 
				
			||||||
int qla24xx_handle_delete_done_event(scsi_qla_host_t *vha,
 | 
					 | 
				
			||||||
	struct event_arg *ea)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	fc_port_t *fcport = ea->fcport;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (test_bit(UNLOADING, &vha->dpc_flags))
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch (vha->host->active_mode) {
 | 
					 | 
				
			||||||
	case MODE_INITIATOR:
 | 
					 | 
				
			||||||
	case MODE_DUAL:
 | 
					 | 
				
			||||||
		if (fcport->scan_state == QLA_FCPORT_FOUND)
 | 
					 | 
				
			||||||
			qla24xx_fcport_handle_login(vha, fcport);
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case MODE_TARGET:
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		/* no-op */
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static
 | 
					static
 | 
				
			||||||
void qla24xx_handle_relogin_event(scsi_qla_host_t *vha,
 | 
					void qla24xx_handle_relogin_event(scsi_qla_host_t *vha,
 | 
				
			||||||
	struct event_arg *ea)
 | 
						struct event_arg *ea)
 | 
				
			||||||
| 
						 | 
					@ -1261,6 +1327,7 @@ void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea)
 | 
				
			||||||
	case FCME_GIDPN_DONE:
 | 
						case FCME_GIDPN_DONE:
 | 
				
			||||||
	case FCME_GPSC_DONE:
 | 
						case FCME_GPSC_DONE:
 | 
				
			||||||
	case FCME_GPNID_DONE:
 | 
						case FCME_GPNID_DONE:
 | 
				
			||||||
 | 
						case FCME_GNNID_DONE:
 | 
				
			||||||
		if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags) ||
 | 
							if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags) ||
 | 
				
			||||||
		    test_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags))
 | 
							    test_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags))
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
| 
						 | 
					@ -1337,7 +1404,7 @@ void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea)
 | 
				
			||||||
		qla24xx_handle_gnl_done_event(vha, ea);
 | 
							qla24xx_handle_gnl_done_event(vha, ea);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case FCME_GPSC_DONE:
 | 
						case FCME_GPSC_DONE:
 | 
				
			||||||
		qla24xx_post_upd_fcport_work(vha, ea->fcport);
 | 
							qla24xx_handle_gpsc_event(vha, ea);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case FCME_PLOGI_DONE:	/* Initiator side sent LLIOCB */
 | 
						case FCME_PLOGI_DONE:	/* Initiator side sent LLIOCB */
 | 
				
			||||||
		qla24xx_handle_plogi_done_event(vha, ea);
 | 
							qla24xx_handle_plogi_done_event(vha, ea);
 | 
				
			||||||
| 
						 | 
					@ -1354,12 +1421,15 @@ void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea)
 | 
				
			||||||
	case FCME_GFFID_DONE:
 | 
						case FCME_GFFID_DONE:
 | 
				
			||||||
		qla24xx_handle_gffid_event(vha, ea);
 | 
							qla24xx_handle_gffid_event(vha, ea);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case FCME_DELETE_DONE:
 | 
					 | 
				
			||||||
		qla24xx_handle_delete_done_event(vha, ea);
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case FCME_ADISC_DONE:
 | 
						case FCME_ADISC_DONE:
 | 
				
			||||||
		qla24xx_handle_adisc_event(vha, ea);
 | 
							qla24xx_handle_adisc_event(vha, ea);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
						case FCME_GNNID_DONE:
 | 
				
			||||||
 | 
							qla24xx_handle_gnnid_event(vha, ea);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case FCME_GFPNID_DONE:
 | 
				
			||||||
 | 
							qla24xx_handle_gfpnid_event(vha, ea);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		BUG_ON(1);
 | 
							BUG_ON(1);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
| 
						 | 
					@ -1568,6 +1638,33 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
 | 
				
			||||||
	u16 lid;
 | 
						u16 lid;
 | 
				
			||||||
	struct fc_port *conflict_fcport;
 | 
						struct fc_port *conflict_fcport;
 | 
				
			||||||
	unsigned long flags;
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
						struct fc_port *fcport = ea->fcport;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
 | 
				
			||||||
 | 
						    (fcport->fw_login_state == DSC_LS_PRLI_PEND)) {
 | 
				
			||||||
 | 
							ql_dbg(ql_dbg_disc, vha, 0x20ea,
 | 
				
			||||||
 | 
							    "%s %d %8phC Remote is trying to login\n",
 | 
				
			||||||
 | 
							    __func__, __LINE__, fcport->port_name);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (fcport->disc_state == DSC_DELETE_PEND)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ea->sp->gen2 != fcport->login_gen) {
 | 
				
			||||||
 | 
							/* target side must have changed it. */
 | 
				
			||||||
 | 
							ql_dbg(ql_dbg_disc, vha, 0x20d3,
 | 
				
			||||||
 | 
							    "%s %8phC generation changed rscn %d|%d login %d|%d\n",
 | 
				
			||||||
 | 
							    __func__, fcport->port_name, fcport->last_rscn_gen,
 | 
				
			||||||
 | 
							    fcport->rscn_gen, fcport->last_login_gen,
 | 
				
			||||||
 | 
							    fcport->login_gen);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						} else if (ea->sp->gen1 != fcport->rscn_gen) {
 | 
				
			||||||
 | 
							ql_dbg(ql_dbg_disc, vha, 0x20d4, "%s %d %8phC post gidpn\n",
 | 
				
			||||||
 | 
							    __func__, __LINE__, fcport->port_name);
 | 
				
			||||||
 | 
							qla24xx_post_gidpn_work(vha, fcport);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (ea->data[0]) {
 | 
						switch (ea->data[0]) {
 | 
				
			||||||
	case MBS_COMMAND_COMPLETE:
 | 
						case MBS_COMMAND_COMPLETE:
 | 
				
			||||||
| 
						 | 
					@ -5124,7 +5221,14 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
 | 
				
			||||||
		 * will be newer than discovery_gen. */
 | 
							 * will be newer than discovery_gen. */
 | 
				
			||||||
		qlt_do_generation_tick(vha, &discovery_gen);
 | 
							qlt_do_generation_tick(vha, &discovery_gen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		rval = qla2x00_find_all_fabric_devs(vha);
 | 
							if (USE_ASYNC_SCAN(ha)) {
 | 
				
			||||||
 | 
								rval = QLA_SUCCESS;
 | 
				
			||||||
 | 
								rval = qla24xx_async_gpnft(vha, FC4_TYPE_FCP_SCSI);
 | 
				
			||||||
 | 
								if (rval)
 | 
				
			||||||
 | 
									set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
 | 
				
			||||||
 | 
							} else  {
 | 
				
			||||||
 | 
								rval = qla2x00_find_all_fabric_devs(vha);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		if (rval != QLA_SUCCESS)
 | 
							if (rval != QLA_SUCCESS)
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
	} while (0);
 | 
						} while (0);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3904,7 +3904,10 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
 | 
				
			||||||
			id.b.area   = rptid_entry->u.f2.remote_nport_id[1];
 | 
								id.b.area   = rptid_entry->u.f2.remote_nport_id[1];
 | 
				
			||||||
			id.b.domain = rptid_entry->u.f2.remote_nport_id[2];
 | 
								id.b.domain = rptid_entry->u.f2.remote_nport_id[2];
 | 
				
			||||||
			qla24xx_post_newsess_work(vha, &id,
 | 
								qla24xx_post_newsess_work(vha, &id,
 | 
				
			||||||
			    rptid_entry->u.f2.port_name, NULL);
 | 
								    rptid_entry->u.f2.port_name,
 | 
				
			||||||
 | 
								    rptid_entry->u.f2.node_name,
 | 
				
			||||||
 | 
								    NULL,
 | 
				
			||||||
 | 
								    FC4_TYPE_UNKNOWN);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3639,6 +3639,8 @@ qla2x00_remove_one(struct pci_dev *pdev)
 | 
				
			||||||
	dma_free_coherent(&ha->pdev->dev,
 | 
						dma_free_coherent(&ha->pdev->dev,
 | 
				
			||||||
		base_vha->gnl.size, base_vha->gnl.l, base_vha->gnl.ldma);
 | 
							base_vha->gnl.size, base_vha->gnl.l, base_vha->gnl.ldma);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						vfree(base_vha->scan.l);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (IS_QLAFX00(ha))
 | 
						if (IS_QLAFX00(ha))
 | 
				
			||||||
		qlafx00_driver_shutdown(base_vha, 20);
 | 
							qlafx00_driver_shutdown(base_vha, 20);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4587,6 +4589,18 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* todo: what about ext login? */
 | 
				
			||||||
 | 
						vha->scan.size = ha->max_fibre_devices * sizeof(struct fab_scan_rp);
 | 
				
			||||||
 | 
						vha->scan.l = vmalloc(vha->scan.size);
 | 
				
			||||||
 | 
						if (!vha->scan.l) {
 | 
				
			||||||
 | 
							ql_log(ql_log_fatal, vha, 0xd04a,
 | 
				
			||||||
 | 
							    "Alloc failed for scan database.\n");
 | 
				
			||||||
 | 
							dma_free_coherent(&ha->pdev->dev, vha->gnl.size,
 | 
				
			||||||
 | 
							    vha->gnl.l, vha->gnl.ldma);
 | 
				
			||||||
 | 
							scsi_remove_host(vha->host);
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no);
 | 
						sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no);
 | 
				
			||||||
	ql_dbg(ql_dbg_init, vha, 0x0041,
 | 
						ql_dbg(ql_dbg_init, vha, 0x0041,
 | 
				
			||||||
	    "Allocated the host=%p hw=%p vha=%p dev_name=%s",
 | 
						    "Allocated the host=%p hw=%p vha=%p dev_name=%s",
 | 
				
			||||||
| 
						 | 
					@ -4760,6 +4774,7 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
 | 
				
			||||||
	struct qlt_plogi_ack_t *pla =
 | 
						struct qlt_plogi_ack_t *pla =
 | 
				
			||||||
	    (struct qlt_plogi_ack_t *)e->u.new_sess.pla;
 | 
						    (struct qlt_plogi_ack_t *)e->u.new_sess.pla;
 | 
				
			||||||
	uint8_t free_fcport = 0;
 | 
						uint8_t free_fcport = 0;
 | 
				
			||||||
 | 
						u64 wwn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ql_dbg(ql_dbg_disc, vha, 0xffff,
 | 
						ql_dbg(ql_dbg_disc, vha, 0xffff,
 | 
				
			||||||
	    "%s %d %8phC enter\n",
 | 
						    "%s %d %8phC enter\n",
 | 
				
			||||||
| 
						 | 
					@ -4785,9 +4800,10 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
 | 
				
			||||||
		fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
 | 
							fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
 | 
				
			||||||
		if (fcport) {
 | 
							if (fcport) {
 | 
				
			||||||
			fcport->d_id = e->u.new_sess.id;
 | 
								fcport->d_id = e->u.new_sess.id;
 | 
				
			||||||
			fcport->scan_state = QLA_FCPORT_FOUND;
 | 
					 | 
				
			||||||
			fcport->flags |= FCF_FABRIC_DEVICE;
 | 
								fcport->flags |= FCF_FABRIC_DEVICE;
 | 
				
			||||||
			fcport->fw_login_state = DSC_LS_PLOGI_PEND;
 | 
								fcport->fw_login_state = DSC_LS_PLOGI_PEND;
 | 
				
			||||||
 | 
								if (e->u.new_sess.fc4_type == FC4_TYPE_FCP_SCSI)
 | 
				
			||||||
 | 
									fcport->fc4_type = FC4_TYPE_FCP_SCSI;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			memcpy(fcport->port_name, e->u.new_sess.port_name,
 | 
								memcpy(fcport->port_name, e->u.new_sess.port_name,
 | 
				
			||||||
			    WWN_SIZE);
 | 
								    WWN_SIZE);
 | 
				
			||||||
| 
						 | 
					@ -4802,7 +4818,7 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
 | 
							spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
 | 
				
			||||||
		/* search again to make sure one else got ahead */
 | 
							/* search again to make sure no one else got ahead */
 | 
				
			||||||
		tfcp = qla2x00_find_fcport_by_wwpn(vha,
 | 
							tfcp = qla2x00_find_fcport_by_wwpn(vha,
 | 
				
			||||||
		    e->u.new_sess.port_name, 1);
 | 
							    e->u.new_sess.port_name, 1);
 | 
				
			||||||
		if (tfcp) {
 | 
							if (tfcp) {
 | 
				
			||||||
| 
						 | 
					@ -4829,6 +4845,10 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
 | 
				
			||||||
		if (N2N_TOPO(vha->hw))
 | 
							if (N2N_TOPO(vha->hw))
 | 
				
			||||||
			fcport->flags &= ~FCF_FABRIC_DEVICE;
 | 
								fcport->flags &= ~FCF_FABRIC_DEVICE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							fcport->id_changed = 1;
 | 
				
			||||||
 | 
							fcport->scan_state = QLA_FCPORT_FOUND;
 | 
				
			||||||
 | 
							memcpy(fcport->node_name, e->u.new_sess.node_name, WWN_SIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (pla) {
 | 
							if (pla) {
 | 
				
			||||||
			if (pla->iocb.u.isp24.status_subcode == ELS_PRLI) {
 | 
								if (pla->iocb.u.isp24.status_subcode == ELS_PRLI) {
 | 
				
			||||||
				u16 wd3_lo;
 | 
									u16 wd3_lo;
 | 
				
			||||||
| 
						 | 
					@ -4881,7 +4901,13 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
 | 
								spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
 | 
				
			||||||
			qla24xx_async_gnl(vha, fcport);
 | 
					
 | 
				
			||||||
 | 
								wwn = wwn_to_u64(fcport->node_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!wwn)
 | 
				
			||||||
 | 
									qla24xx_async_gnnid(vha, fcport);
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									qla24xx_async_gnl(vha, fcport);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4980,6 +5006,21 @@ qla2x00_do_work(struct scsi_qla_host *vha)
 | 
				
			||||||
			qla2x00_async_prlo_done(vha, e->u.logio.fcport,
 | 
								qla2x00_async_prlo_done(vha, e->u.logio.fcport,
 | 
				
			||||||
			    e->u.logio.data);
 | 
								    e->u.logio.data);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
							case QLA_EVT_GPNFT:
 | 
				
			||||||
 | 
								qla24xx_async_gpnft(vha, e->u.gpnft.fc4_type);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case QLA_EVT_GPNFT_DONE:
 | 
				
			||||||
 | 
								qla24xx_async_gpnft_done(vha, e->u.iosb.sp);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case QLA_EVT_GNNFT_DONE:
 | 
				
			||||||
 | 
								qla24xx_async_gnnft_done(vha, e->u.iosb.sp);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case QLA_EVT_GNNID:
 | 
				
			||||||
 | 
								qla24xx_async_gnnid(vha, e->u.fcport.fcport);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case QLA_EVT_GFPNID:
 | 
				
			||||||
 | 
								qla24xx_async_gfpnid(vha, e->u.fcport.fcport);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (e->flags & QLA_EVT_FLAG_FREE)
 | 
							if (e->flags & QLA_EVT_FLAG_FREE)
 | 
				
			||||||
			kfree(e);
 | 
								kfree(e);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -969,7 +969,6 @@ static void qlt_free_session_done(struct work_struct *work)
 | 
				
			||||||
	struct qla_hw_data *ha = vha->hw;
 | 
						struct qla_hw_data *ha = vha->hw;
 | 
				
			||||||
	unsigned long flags;
 | 
						unsigned long flags;
 | 
				
			||||||
	bool logout_started = false;
 | 
						bool logout_started = false;
 | 
				
			||||||
	struct event_arg ea;
 | 
					 | 
				
			||||||
	scsi_qla_host_t *base_vha;
 | 
						scsi_qla_host_t *base_vha;
 | 
				
			||||||
	struct qlt_plogi_ack_t *own =
 | 
						struct qlt_plogi_ack_t *own =
 | 
				
			||||||
		sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN];
 | 
							sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN];
 | 
				
			||||||
| 
						 | 
					@ -1121,11 +1120,18 @@ static void qlt_free_session_done(struct work_struct *work)
 | 
				
			||||||
	if (test_bit(PFLG_DRIVER_REMOVING, &base_vha->pci_flags))
 | 
						if (test_bit(PFLG_DRIVER_REMOVING, &base_vha->pci_flags))
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!tgt || !tgt->tgt_stop) {
 | 
						if ((!tgt || !tgt->tgt_stop) && !LOOP_TRANSITION(vha)) {
 | 
				
			||||||
		memset(&ea, 0, sizeof(ea));
 | 
							switch (vha->host->active_mode) {
 | 
				
			||||||
		ea.event = FCME_DELETE_DONE;
 | 
							case MODE_INITIATOR:
 | 
				
			||||||
		ea.fcport = sess;
 | 
							case MODE_DUAL:
 | 
				
			||||||
		qla2x00_fcport_event_handler(vha, &ea);
 | 
								set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
 | 
				
			||||||
 | 
								qla2xxx_wake_dpc(vha);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case MODE_TARGET:
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								/* no-op */
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4318,6 +4324,7 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
 | 
				
			||||||
	struct fc_port *sess;
 | 
						struct fc_port *sess;
 | 
				
			||||||
	struct qla_tgt_cmd *cmd;
 | 
						struct qla_tgt_cmd *cmd;
 | 
				
			||||||
	unsigned long flags;
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
						port_id_t id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (unlikely(tgt->tgt_stop)) {
 | 
						if (unlikely(tgt->tgt_stop)) {
 | 
				
			||||||
		ql_dbg(ql_dbg_io, vha, 0x3061,
 | 
							ql_dbg(ql_dbg_io, vha, 0x3061,
 | 
				
			||||||
| 
						 | 
					@ -4325,6 +4332,12 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
 | 
				
			||||||
		return -EFAULT;
 | 
							return -EFAULT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						id.b.al_pa = atio->u.isp24.fcp_hdr.s_id[2];
 | 
				
			||||||
 | 
						id.b.area = atio->u.isp24.fcp_hdr.s_id[1];
 | 
				
			||||||
 | 
						id.b.domain = atio->u.isp24.fcp_hdr.s_id[0];
 | 
				
			||||||
 | 
						if (IS_SW_RESV_ADDR(id))
 | 
				
			||||||
 | 
							return -EBUSY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, atio->u.isp24.fcp_hdr.s_id);
 | 
						sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, atio->u.isp24.fcp_hdr.s_id);
 | 
				
			||||||
	if (unlikely(!sess)) {
 | 
						if (unlikely(!sess)) {
 | 
				
			||||||
		struct qla_tgt_sess_op *op = kzalloc(sizeof(struct qla_tgt_sess_op),
 | 
							struct qla_tgt_sess_op *op = kzalloc(sizeof(struct qla_tgt_sess_op),
 | 
				
			||||||
| 
						 | 
					@ -4739,8 +4752,16 @@ static int qlt_handle_login(struct scsi_qla_host *vha,
 | 
				
			||||||
		ql_dbg(ql_dbg_disc, vha, 0xffff,
 | 
							ql_dbg(ql_dbg_disc, vha, 0xffff,
 | 
				
			||||||
		    "%s %d %8phC post new sess\n",
 | 
							    "%s %d %8phC post new sess\n",
 | 
				
			||||||
		    __func__, __LINE__, iocb->u.isp24.port_name);
 | 
							    __func__, __LINE__, iocb->u.isp24.port_name);
 | 
				
			||||||
		qla24xx_post_newsess_work(vha, &port_id,
 | 
							if (iocb->u.isp24.status_subcode == ELS_PLOGI)
 | 
				
			||||||
		    iocb->u.isp24.port_name, pla);
 | 
								qla24xx_post_newsess_work(vha, &port_id,
 | 
				
			||||||
 | 
								    iocb->u.isp24.port_name,
 | 
				
			||||||
 | 
								    iocb->u.isp24.u.plogi.node_name,
 | 
				
			||||||
 | 
								    pla, FC4_TYPE_UNKNOWN);
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								qla24xx_post_newsess_work(vha, &port_id,
 | 
				
			||||||
 | 
								    iocb->u.isp24.port_name, NULL,
 | 
				
			||||||
 | 
								    pla, FC4_TYPE_UNKNOWN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4869,6 +4890,11 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (IS_SW_RESV_ADDR(port_id)) {
 | 
				
			||||||
 | 
								res = 1;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		wd3_lo = le16_to_cpu(iocb->u.isp24.u.prli.wd3_lo);
 | 
							wd3_lo = le16_to_cpu(iocb->u.isp24.u.prli.wd3_lo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (wwn) {
 | 
							if (wwn) {
 | 
				
			||||||
| 
						 | 
					@ -4896,12 +4922,32 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (sess != NULL) {
 | 
							if (sess != NULL) {
 | 
				
			||||||
 | 
								bool delete = false;
 | 
				
			||||||
			spin_lock_irqsave(&tgt->ha->tgt.sess_lock, flags);
 | 
								spin_lock_irqsave(&tgt->ha->tgt.sess_lock, flags);
 | 
				
			||||||
			switch (sess->fw_login_state) {
 | 
								switch (sess->fw_login_state) {
 | 
				
			||||||
 | 
								case DSC_LS_PLOGI_PEND:
 | 
				
			||||||
			case DSC_LS_PLOGI_COMP:
 | 
								case DSC_LS_PLOGI_COMP:
 | 
				
			||||||
			case DSC_LS_PRLI_COMP:
 | 
								case DSC_LS_PRLI_COMP:
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			default:
 | 
								default:
 | 
				
			||||||
 | 
									delete = true;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								switch (sess->disc_state) {
 | 
				
			||||||
 | 
								case DSC_LOGIN_PEND:
 | 
				
			||||||
 | 
								case DSC_GPDB:
 | 
				
			||||||
 | 
								case DSC_GPSC:
 | 
				
			||||||
 | 
								case DSC_UPD_FCPORT:
 | 
				
			||||||
 | 
								case DSC_LOGIN_COMPLETE:
 | 
				
			||||||
 | 
								case DSC_ADISC:
 | 
				
			||||||
 | 
									delete = false;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								default:
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (delete) {
 | 
				
			||||||
				spin_unlock_irqrestore(&tgt->ha->tgt.sess_lock,
 | 
									spin_unlock_irqrestore(&tgt->ha->tgt.sess_lock,
 | 
				
			||||||
				    flags);
 | 
									    flags);
 | 
				
			||||||
				/*
 | 
									/*
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -993,7 +993,7 @@ struct qla_tgt_prm {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Check for Switch reserved address */
 | 
					/* Check for Switch reserved address */
 | 
				
			||||||
#define IS_SW_RESV_ADDR(_s_id) \
 | 
					#define IS_SW_RESV_ADDR(_s_id) \
 | 
				
			||||||
	((_s_id.b.domain == 0xff) && (_s_id.b.area == 0xfc))
 | 
						((_s_id.b.domain == 0xff) && ((_s_id.b.area & 0xf0) == 0xf0))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define QLA_TGT_XMIT_DATA		1
 | 
					#define QLA_TGT_XMIT_DATA		1
 | 
				
			||||||
#define QLA_TGT_XMIT_STATUS		2
 | 
					#define QLA_TGT_XMIT_STATUS		2
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue