mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	qla2xxx: Add framework for async fabric discovery
Currently code performs a full scan of the fabric for every RSCN. Its an expensive process in a noisy large SAN. This patch optimizes expensive fabric discovery process by scanning switch for the affected port when RSCN is received. Currently Initiator Mode code makes login/logout decision without knowledge of target mode. This causes driver and firmware to go out-of-sync. This framework synchronizes both initiator mode personality and target mode personality in making login/logout decision. This patch adds following capabilities in the driver - Send Notification Acknowledgement asynchronously. - Update session/fcport state asynchronously. - Create a session or fcport struct asynchronously. - Send GNL asynchronously. The command will ask FW to provide a list of FC Port entries FW knows about. - Send GPDB asynchronously. The command will ask FW to provide detail data of an FC Port FW knows about or perform ADISC to verify the state of the session. - Send GPNID asynchronously. The command will ask switch to provide WWPN for provided NPort ID. - Send GPSC asynchronously. The command will ask switch to provide registered port speed for provided WWPN. - Send GIDPN asynchronously. The command will ask the switch to provide Nport ID for provided WWPN. - In driver unload path, schedule all session for deletion and wait for deletion to complete before allowing driver unload to proceed. Signed-off-by: Quinn Tran <quinn.tran@cavium.com> Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com> [ bvanassche: fixed spelling in patch description ] Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
This commit is contained in:
		
							parent
							
								
									5d964837c6
								
							
						
					
					
						commit
						726b854870
					
				
					 13 changed files with 3111 additions and 984 deletions
				
			
		| 
						 | 
				
			
			@ -2163,6 +2163,9 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
 | 
			
		|||
	clear_bit(vha->vp_idx, ha->vp_idx_map);
 | 
			
		||||
	mutex_unlock(&ha->vport_lock);
 | 
			
		||||
 | 
			
		||||
	dma_free_coherent(&ha->pdev->dev, vha->gnl.size, vha->gnl.l,
 | 
			
		||||
	    vha->gnl.ldma);
 | 
			
		||||
 | 
			
		||||
	if (vha->qpair->vp_idx == vha->vp_idx) {
 | 
			
		||||
		if (qla2xxx_delete_qpair(vha, vha->qpair) != QLA_SUCCESS)
 | 
			
		||||
			ql_log(ql_log_warn, vha, 0x7087,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -55,6 +55,8 @@
 | 
			
		|||
 | 
			
		||||
#include "qla_settings.h"
 | 
			
		||||
 | 
			
		||||
#define MODE_DUAL (MODE_TARGET | MODE_INITIATOR)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Data bit definitions
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -251,6 +253,14 @@
 | 
			
		|||
 | 
			
		||||
#define MAX_CMDSZ	16		/* SCSI maximum CDB size. */
 | 
			
		||||
#include "qla_fw.h"
 | 
			
		||||
 | 
			
		||||
struct name_list_extended {
 | 
			
		||||
	struct get_name_list_extended *l;
 | 
			
		||||
	dma_addr_t		ldma;
 | 
			
		||||
	struct list_head 	fcports;	/* protect by sess_list */
 | 
			
		||||
	u32			size;
 | 
			
		||||
	u8			sent;
 | 
			
		||||
};
 | 
			
		||||
/*
 | 
			
		||||
 * Timeout timer counts in seconds
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -309,6 +319,17 @@ struct els_logo_payload {
 | 
			
		|||
	uint8_t wwpn[WWN_SIZE];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ct_arg {
 | 
			
		||||
	void		*iocb;
 | 
			
		||||
	u16		nport_handle;
 | 
			
		||||
	dma_addr_t	req_dma;
 | 
			
		||||
	dma_addr_t	rsp_dma;
 | 
			
		||||
	u32		req_size;
 | 
			
		||||
	u32		rsp_size;
 | 
			
		||||
	void		*req;
 | 
			
		||||
	void		*rsp;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * SRB extensions.
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -320,6 +341,7 @@ struct srb_iocb {
 | 
			
		|||
#define SRB_LOGIN_COND_PLOGI	BIT_1
 | 
			
		||||
#define SRB_LOGIN_SKIP_PRLI	BIT_2
 | 
			
		||||
			uint16_t data[2];
 | 
			
		||||
			u32 iop[2];
 | 
			
		||||
		} logio;
 | 
			
		||||
		struct {
 | 
			
		||||
#define ELS_DCMD_TIMEOUT 20
 | 
			
		||||
| 
						 | 
				
			
			@ -372,6 +394,16 @@ struct srb_iocb {
 | 
			
		|||
			__le16 comp_status;
 | 
			
		||||
			struct completion comp;
 | 
			
		||||
		} abt;
 | 
			
		||||
		struct ct_arg ctarg;
 | 
			
		||||
		struct {
 | 
			
		||||
			__le16 in_mb[28]; 	/* fr fw */
 | 
			
		||||
			__le16 out_mb[28];	/* to fw */
 | 
			
		||||
			void *out, *in;
 | 
			
		||||
			dma_addr_t out_dma, in_dma;
 | 
			
		||||
		} mbx;
 | 
			
		||||
		struct {
 | 
			
		||||
			struct imm_ntfy_from_isp *ntfy;
 | 
			
		||||
		} nack;
 | 
			
		||||
	} u;
 | 
			
		||||
 | 
			
		||||
	struct timer_list timer;
 | 
			
		||||
| 
						 | 
				
			
			@ -392,16 +424,24 @@ struct srb_iocb {
 | 
			
		|||
#define SRB_FXIOCB_BCMD	11
 | 
			
		||||
#define SRB_ABT_CMD	12
 | 
			
		||||
#define SRB_ELS_DCMD	13
 | 
			
		||||
#define SRB_MB_IOCB	14
 | 
			
		||||
#define SRB_CT_PTHRU_CMD 15
 | 
			
		||||
#define SRB_NACK_PLOGI	16
 | 
			
		||||
#define SRB_NACK_PRLI	17
 | 
			
		||||
#define SRB_NACK_LOGO	18
 | 
			
		||||
 | 
			
		||||
typedef struct srb {
 | 
			
		||||
	atomic_t ref_count;
 | 
			
		||||
	struct fc_port *fcport;
 | 
			
		||||
	void *vha;
 | 
			
		||||
	uint32_t handle;
 | 
			
		||||
	uint16_t flags;
 | 
			
		||||
	uint16_t type;
 | 
			
		||||
	char *name;
 | 
			
		||||
	int iocbs;
 | 
			
		||||
	struct qla_qpair *qpair;
 | 
			
		||||
	u32 gen1;	/* scratch */
 | 
			
		||||
	u32 gen2;	/* scratch */
 | 
			
		||||
	union {
 | 
			
		||||
		struct srb_iocb iocb_cmd;
 | 
			
		||||
		struct bsg_job *bsg_job;
 | 
			
		||||
| 
						 | 
				
			
			@ -2101,6 +2141,18 @@ typedef struct {
 | 
			
		|||
#define FC4_TYPE_OTHER		0x0
 | 
			
		||||
#define FC4_TYPE_UNKNOWN	0xff
 | 
			
		||||
 | 
			
		||||
/* mailbox command 4G & above */
 | 
			
		||||
struct mbx_24xx_entry {
 | 
			
		||||
	uint8_t		entry_type;
 | 
			
		||||
	uint8_t		entry_count;
 | 
			
		||||
	uint8_t		sys_define1;
 | 
			
		||||
	uint8_t		entry_status;
 | 
			
		||||
	uint32_t	handle;
 | 
			
		||||
	uint16_t	mb[28];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define IOCB_SIZE 64
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Fibre channel port type.
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -2113,6 +2165,12 @@ typedef enum {
 | 
			
		|||
	FCT_TARGET
 | 
			
		||||
} fc_port_type_t;
 | 
			
		||||
 | 
			
		||||
enum qla_sess_deletion {
 | 
			
		||||
	QLA_SESS_DELETION_NONE		= 0,
 | 
			
		||||
	QLA_SESS_DELETION_IN_PROGRESS,
 | 
			
		||||
	QLA_SESS_DELETED,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum qlt_plogi_link_t {
 | 
			
		||||
	QLT_PLOGI_LINK_SAME_WWN,
 | 
			
		||||
	QLT_PLOGI_LINK_CONFLICT,
 | 
			
		||||
| 
						 | 
				
			
			@ -2124,6 +2182,48 @@ struct qlt_plogi_ack_t {
 | 
			
		|||
	struct imm_ntfy_from_isp iocb;
 | 
			
		||||
	port_id_t	id;
 | 
			
		||||
	int		ref_count;
 | 
			
		||||
	void		*fcport;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ct_sns_desc {
 | 
			
		||||
	struct ct_sns_pkt	*ct_sns;
 | 
			
		||||
	dma_addr_t		ct_sns_dma;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum discovery_state {
 | 
			
		||||
	DSC_DELETED,
 | 
			
		||||
	DSC_GID_PN,
 | 
			
		||||
	DSC_GNL,
 | 
			
		||||
	DSC_LOGIN_PEND,
 | 
			
		||||
	DSC_LOGIN_FAILED,
 | 
			
		||||
	DSC_GPDB,
 | 
			
		||||
	DSC_GPSC,
 | 
			
		||||
	DSC_UPD_FCPORT,
 | 
			
		||||
	DSC_LOGIN_COMPLETE,
 | 
			
		||||
	DSC_DELETE_PEND,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum login_state {	/* FW control Target side */
 | 
			
		||||
	DSC_LS_LLIOCB_SENT = 2,
 | 
			
		||||
	DSC_LS_PLOGI_PEND,
 | 
			
		||||
	DSC_LS_PLOGI_COMP,
 | 
			
		||||
	DSC_LS_PRLI_PEND,
 | 
			
		||||
	DSC_LS_PRLI_COMP,
 | 
			
		||||
	DSC_LS_PORT_UNAVAIL,
 | 
			
		||||
	DSC_LS_PRLO_PEND = 9,
 | 
			
		||||
	DSC_LS_LOGO_PEND,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum fcport_mgt_event {
 | 
			
		||||
	FCME_RELOGIN = 1,
 | 
			
		||||
	FCME_RSCN,
 | 
			
		||||
	FCME_GIDPN_DONE,
 | 
			
		||||
	FCME_PLOGI_DONE,	/* Initiator side sent LLIOCB */
 | 
			
		||||
	FCME_GNL_DONE,
 | 
			
		||||
	FCME_GPSC_DONE,
 | 
			
		||||
	FCME_GPDB_DONE,
 | 
			
		||||
	FCME_GPNID_DONE,
 | 
			
		||||
	FCME_DELETE_DONE,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
| 
						 | 
				
			
			@ -2143,9 +2243,13 @@ typedef struct fc_port {
 | 
			
		|||
	unsigned int deleted:2;
 | 
			
		||||
	unsigned int local:1;
 | 
			
		||||
	unsigned int logout_on_delete:1;
 | 
			
		||||
	unsigned int logo_ack_needed:1;
 | 
			
		||||
	unsigned int keep_nport_handle:1;
 | 
			
		||||
	unsigned int send_els_logo:1;
 | 
			
		||||
	unsigned int login_pause:1;
 | 
			
		||||
	unsigned int login_succ:1;
 | 
			
		||||
 | 
			
		||||
	struct fc_port *conflict;
 | 
			
		||||
	unsigned char logout_completed;
 | 
			
		||||
	int generation;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2186,8 +2290,30 @@ typedef struct fc_port {
 | 
			
		|||
 | 
			
		||||
	unsigned long retry_delay_timestamp;
 | 
			
		||||
	struct qla_tgt_sess *tgt_session;
 | 
			
		||||
	struct ct_sns_desc ct_desc;
 | 
			
		||||
	enum discovery_state disc_state;
 | 
			
		||||
	enum login_state fw_login_state;
 | 
			
		||||
	u32 login_gen, last_login_gen;
 | 
			
		||||
	u32 rscn_gen, last_rscn_gen;
 | 
			
		||||
	u32 chip_reset;
 | 
			
		||||
	struct list_head gnl_entry;
 | 
			
		||||
	struct work_struct del_work;
 | 
			
		||||
	u8 iocb[IOCB_SIZE];
 | 
			
		||||
} fc_port_t;
 | 
			
		||||
 | 
			
		||||
#define QLA_FCPORT_SCAN		1
 | 
			
		||||
#define QLA_FCPORT_FOUND	2
 | 
			
		||||
 | 
			
		||||
struct event_arg {
 | 
			
		||||
	enum fcport_mgt_event	event;
 | 
			
		||||
	fc_port_t		*fcport;
 | 
			
		||||
	srb_t			*sp;
 | 
			
		||||
	port_id_t		id;
 | 
			
		||||
	u16			data[2], rc;
 | 
			
		||||
	u8			port_name[WWN_SIZE];
 | 
			
		||||
	u32			iop[2];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#include "qla_mr.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
| 
						 | 
				
			
			@ -2265,6 +2391,10 @@ static const char * const port_state_str[] = {
 | 
			
		|||
#define	GFT_ID_REQ_SIZE	(16 + 4)
 | 
			
		||||
#define	GFT_ID_RSP_SIZE	(16 + 32)
 | 
			
		||||
 | 
			
		||||
#define GID_PN_CMD 0x121
 | 
			
		||||
#define GID_PN_REQ_SIZE (16 + 8)
 | 
			
		||||
#define GID_PN_RSP_SIZE (16 + 4)
 | 
			
		||||
 | 
			
		||||
#define	RFT_ID_CMD	0x217
 | 
			
		||||
#define	RFT_ID_REQ_SIZE	(16 + 4 + 32)
 | 
			
		||||
#define	RFT_ID_RSP_SIZE	16
 | 
			
		||||
| 
						 | 
				
			
			@ -2590,6 +2720,10 @@ struct ct_sns_req {
 | 
			
		|||
			uint8_t reserved;
 | 
			
		||||
			uint8_t port_name[3];
 | 
			
		||||
		} gff_id;
 | 
			
		||||
 | 
			
		||||
		struct {
 | 
			
		||||
			uint8_t port_name[8];
 | 
			
		||||
		} gid_pn;
 | 
			
		||||
	} req;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2669,6 +2803,10 @@ struct ct_sns_rsp {
 | 
			
		|||
		struct {
 | 
			
		||||
			uint8_t fc4_features[128];
 | 
			
		||||
		} gff_id;
 | 
			
		||||
		struct {
 | 
			
		||||
			uint8_t reserved;
 | 
			
		||||
			uint8_t port_id[3];
 | 
			
		||||
		} gid_pn;
 | 
			
		||||
	} rsp;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2810,11 +2948,11 @@ struct isp_operations {
 | 
			
		|||
 | 
			
		||||
	uint16_t (*calc_req_entries) (uint16_t);
 | 
			
		||||
	void (*build_iocbs) (srb_t *, cmd_entry_t *, uint16_t);
 | 
			
		||||
	void * (*prep_ms_iocb) (struct scsi_qla_host *, uint32_t, uint32_t);
 | 
			
		||||
	void * (*prep_ms_fdmi_iocb) (struct scsi_qla_host *, uint32_t,
 | 
			
		||||
	void *(*prep_ms_iocb) (struct scsi_qla_host *, struct ct_arg *);
 | 
			
		||||
	void *(*prep_ms_fdmi_iocb) (struct scsi_qla_host *, uint32_t,
 | 
			
		||||
	    uint32_t);
 | 
			
		||||
 | 
			
		||||
	uint8_t * (*read_nvram) (struct scsi_qla_host *, uint8_t *,
 | 
			
		||||
	uint8_t *(*read_nvram) (struct scsi_qla_host *, uint8_t *,
 | 
			
		||||
		uint32_t, uint32_t);
 | 
			
		||||
	int (*write_nvram) (struct scsi_qla_host *, uint8_t *, uint32_t,
 | 
			
		||||
		uint32_t);
 | 
			
		||||
| 
						 | 
				
			
			@ -2876,13 +3014,21 @@ enum qla_work_type {
 | 
			
		|||
	QLA_EVT_AEN,
 | 
			
		||||
	QLA_EVT_IDC_ACK,
 | 
			
		||||
	QLA_EVT_ASYNC_LOGIN,
 | 
			
		||||
	QLA_EVT_ASYNC_LOGIN_DONE,
 | 
			
		||||
	QLA_EVT_ASYNC_LOGOUT,
 | 
			
		||||
	QLA_EVT_ASYNC_LOGOUT_DONE,
 | 
			
		||||
	QLA_EVT_ASYNC_ADISC,
 | 
			
		||||
	QLA_EVT_ASYNC_ADISC_DONE,
 | 
			
		||||
	QLA_EVT_UEVENT,
 | 
			
		||||
	QLA_EVT_AENFX,
 | 
			
		||||
	QLA_EVT_GIDPN,
 | 
			
		||||
	QLA_EVT_GPNID,
 | 
			
		||||
	QLA_EVT_GPNID_DONE,
 | 
			
		||||
	QLA_EVT_NEW_SESS,
 | 
			
		||||
	QLA_EVT_GPDB,
 | 
			
		||||
	QLA_EVT_GPSC,
 | 
			
		||||
	QLA_EVT_UPD_FCPORT,
 | 
			
		||||
	QLA_EVT_GNL,
 | 
			
		||||
	QLA_EVT_NACK,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2918,6 +3064,23 @@ struct qla_work_evt {
 | 
			
		|||
		struct {
 | 
			
		||||
			srb_t *sp;
 | 
			
		||||
		} iosb;
 | 
			
		||||
		struct {
 | 
			
		||||
			port_id_t id;
 | 
			
		||||
		} gpnid;
 | 
			
		||||
		struct {
 | 
			
		||||
			port_id_t id;
 | 
			
		||||
			u8 port_name[8];
 | 
			
		||||
			void *pla;
 | 
			
		||||
		} new_sess;
 | 
			
		||||
		struct { /*Get PDB, Get Speed, update fcport, gnl, gidpn */
 | 
			
		||||
			fc_port_t *fcport;
 | 
			
		||||
			u8 opt;
 | 
			
		||||
		} fcport;
 | 
			
		||||
		struct {
 | 
			
		||||
			fc_port_t *fcport;
 | 
			
		||||
			u8 iocb[IOCB_SIZE];
 | 
			
		||||
			int type;
 | 
			
		||||
		} nack;
 | 
			
		||||
	 } u;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3899,6 +4062,10 @@ typedef struct scsi_qla_host {
 | 
			
		|||
	struct qla8044_reset_template reset_tmplt;
 | 
			
		||||
	struct qla_tgt_counters tgt_counters;
 | 
			
		||||
	uint16_t	bbcr;
 | 
			
		||||
	struct name_list_extended gnl;
 | 
			
		||||
	/* Count of active session/fcport */
 | 
			
		||||
	int fcport_count;
 | 
			
		||||
	wait_queue_head_t fcport_waitQ;
 | 
			
		||||
} scsi_qla_host_t;
 | 
			
		||||
 | 
			
		||||
struct qla27xx_image_status {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -72,6 +72,37 @@ struct port_database_24xx {
 | 
			
		|||
	uint8_t reserved_3[24];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * MB 75h returns a list of DB entries similar to port_database_24xx(64B).
 | 
			
		||||
 * However, in this case it returns 1st 40 bytes.
 | 
			
		||||
 */
 | 
			
		||||
struct get_name_list_extended {
 | 
			
		||||
	__le16 flags;
 | 
			
		||||
	u8 current_login_state;
 | 
			
		||||
	u8 last_login_state;
 | 
			
		||||
	u8 hard_address[3];
 | 
			
		||||
	u8 reserved_1;
 | 
			
		||||
	u8 port_id[3];
 | 
			
		||||
	u8 sequence_id;
 | 
			
		||||
	__le16 port_timer;
 | 
			
		||||
	__le16 nport_handle;			/* N_PORT handle. */
 | 
			
		||||
	__le16 receive_data_size;
 | 
			
		||||
	__le16 reserved_2;
 | 
			
		||||
 | 
			
		||||
	/* PRLI SVC Param are Big endian */
 | 
			
		||||
	u8 prli_svc_param_word_0[2]; /* Bits 15-0 of word 0 */
 | 
			
		||||
	u8 prli_svc_param_word_3[2]; /* Bits 15-0 of word 3 */
 | 
			
		||||
	u8 port_name[WWN_SIZE];
 | 
			
		||||
	u8 node_name[WWN_SIZE];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* MB 75h: This is the short version of the database */
 | 
			
		||||
struct get_name_list {
 | 
			
		||||
	u8 port_node_name[WWN_SIZE]; /* B7 most sig, B0 least sig */
 | 
			
		||||
	__le16 nport_handle;
 | 
			
		||||
	u8 reserved;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct vp_database_24xx {
 | 
			
		||||
	uint16_t vp_status;
 | 
			
		||||
	uint8_t  options;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -73,6 +73,10 @@ extern void qla2x00_async_logout_done(struct scsi_qla_host *, fc_port_t *,
 | 
			
		|||
    uint16_t *);
 | 
			
		||||
extern void qla2x00_async_adisc_done(struct scsi_qla_host *, fc_port_t *,
 | 
			
		||||
    uint16_t *);
 | 
			
		||||
struct qla_work_evt *qla2x00_alloc_work(struct scsi_qla_host *,
 | 
			
		||||
    enum qla_work_type);
 | 
			
		||||
extern int qla24xx_async_gnl(struct scsi_qla_host *, fc_port_t *);
 | 
			
		||||
int qla2x00_post_work(struct scsi_qla_host *vha, struct qla_work_evt *e);
 | 
			
		||||
extern void *qla2x00_alloc_iocbs(struct scsi_qla_host *, srb_t *);
 | 
			
		||||
extern void *qla2x00_alloc_iocbs_ready(struct scsi_qla_host *, srb_t *);
 | 
			
		||||
extern int qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *, fc_port_t *);
 | 
			
		||||
| 
						 | 
				
			
			@ -94,6 +98,13 @@ extern uint8_t qla27xx_find_valid_image(struct scsi_qla_host *);
 | 
			
		|||
extern struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *,
 | 
			
		||||
	int, int);
 | 
			
		||||
extern int qla2xxx_delete_qpair(struct scsi_qla_host *, struct qla_qpair *);
 | 
			
		||||
void qla2x00_fcport_event_handler(scsi_qla_host_t *, struct event_arg *);
 | 
			
		||||
int qla24xx_async_gpdb(struct scsi_qla_host *, fc_port_t *, u8);
 | 
			
		||||
int qla24xx_async_notify_ack(scsi_qla_host_t *, fc_port_t *,
 | 
			
		||||
	struct imm_ntfy_from_isp *, int);
 | 
			
		||||
int qla24xx_post_newsess_work(struct scsi_qla_host *, port_id_t *, u8 *,
 | 
			
		||||
    void *);
 | 
			
		||||
int qla24xx_fcport_handle_login(struct scsi_qla_host *, fc_port_t *);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Global Data in qla_os.c source file.
 | 
			
		||||
| 
						 | 
				
			
			@ -135,8 +146,6 @@ extern int qla2x00_post_aen_work(struct scsi_qla_host *, enum
 | 
			
		|||
extern int qla2x00_post_idc_ack_work(struct scsi_qla_host *, uint16_t *);
 | 
			
		||||
extern int qla2x00_post_async_login_work(struct scsi_qla_host *, fc_port_t *,
 | 
			
		||||
    uint16_t *);
 | 
			
		||||
extern int qla2x00_post_async_login_done_work(struct scsi_qla_host *,
 | 
			
		||||
    fc_port_t *, uint16_t *);
 | 
			
		||||
extern int qla2x00_post_async_logout_work(struct scsi_qla_host *, fc_port_t *,
 | 
			
		||||
    uint16_t *);
 | 
			
		||||
extern int qla2x00_post_async_logout_done_work(struct scsi_qla_host *,
 | 
			
		||||
| 
						 | 
				
			
			@ -179,6 +188,10 @@ extern void qla2x00_disable_board_on_pci_error(struct work_struct *);
 | 
			
		|||
extern void qla2x00_sp_compl(void *, void *, int);
 | 
			
		||||
extern void qla2xxx_qpair_sp_free_dma(void *, void *);
 | 
			
		||||
extern void qla2xxx_qpair_sp_compl(void *, void *, int);
 | 
			
		||||
extern int qla24xx_post_upd_fcport_work(struct scsi_qla_host *, fc_port_t *);
 | 
			
		||||
void qla2x00_handle_login_done_event(struct scsi_qla_host *, fc_port_t *,
 | 
			
		||||
	uint16_t *);
 | 
			
		||||
int qla24xx_post_gnl_work(struct scsi_qla_host *, fc_port_t *);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Global Functions in qla_mid.c source file.
 | 
			
		||||
| 
						 | 
				
			
			@ -301,9 +314,6 @@ qla2x00_get_retry_cnt(scsi_qla_host_t *, uint8_t *, uint8_t *, uint16_t *);
 | 
			
		|||
extern int
 | 
			
		||||
qla2x00_init_firmware(scsi_qla_host_t *, uint16_t);
 | 
			
		||||
 | 
			
		||||
extern int
 | 
			
		||||
qla2x00_get_node_name_list(scsi_qla_host_t *, void **, int *);
 | 
			
		||||
 | 
			
		||||
extern int
 | 
			
		||||
qla2x00_get_port_database(scsi_qla_host_t *, fc_port_t *, uint8_t);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -483,6 +493,9 @@ qla2x00_process_completed_request(struct scsi_qla_host *, struct req_que *,
 | 
			
		|||
	uint32_t);
 | 
			
		||||
extern irqreturn_t
 | 
			
		||||
qla2xxx_msix_rsp_q(int irq, void *dev_id);
 | 
			
		||||
fc_port_t *qla2x00_find_fcport_by_loopid(scsi_qla_host_t *, uint16_t);
 | 
			
		||||
fc_port_t *qla2x00_find_fcport_by_wwpn(scsi_qla_host_t *, u8 *, u8);
 | 
			
		||||
fc_port_t *qla2x00_find_fcport_by_nportid(scsi_qla_host_t *, port_id_t *, u8);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Global Function Prototypes in qla_sup.c source file.
 | 
			
		||||
| 
						 | 
				
			
			@ -574,8 +587,8 @@ extern void qla2xxx_dump_post_process(scsi_qla_host_t *, int);
 | 
			
		|||
/*
 | 
			
		||||
 * Global Function Prototypes in qla_gs.c source file.
 | 
			
		||||
 */
 | 
			
		||||
extern void *qla2x00_prep_ms_iocb(scsi_qla_host_t *, uint32_t, uint32_t);
 | 
			
		||||
extern void *qla24xx_prep_ms_iocb(scsi_qla_host_t *, uint32_t, uint32_t);
 | 
			
		||||
extern void *qla2x00_prep_ms_iocb(scsi_qla_host_t *, struct ct_arg *);
 | 
			
		||||
extern void *qla24xx_prep_ms_iocb(scsi_qla_host_t *, struct ct_arg *);
 | 
			
		||||
extern int qla2x00_ga_nxt(scsi_qla_host_t *, fc_port_t *);
 | 
			
		||||
extern int qla2x00_gid_pt(scsi_qla_host_t *, sw_info_t *);
 | 
			
		||||
extern int qla2x00_gpn_id(scsi_qla_host_t *, sw_info_t *);
 | 
			
		||||
| 
						 | 
				
			
			@ -591,6 +604,23 @@ extern int qla2x00_fdmi_register(scsi_qla_host_t *);
 | 
			
		|||
extern int qla2x00_gfpn_id(scsi_qla_host_t *, sw_info_t *);
 | 
			
		||||
extern int qla2x00_gpsc(scsi_qla_host_t *, sw_info_t *);
 | 
			
		||||
extern void qla2x00_get_sym_node_name(scsi_qla_host_t *, uint8_t *, size_t);
 | 
			
		||||
extern int qla2x00_chk_ms_status(scsi_qla_host_t *, ms_iocb_entry_t *,
 | 
			
		||||
	struct ct_sns_rsp *, const char *);
 | 
			
		||||
extern void qla2x00_async_iocb_timeout(void *data);
 | 
			
		||||
extern int qla24xx_async_gidpn(scsi_qla_host_t *, fc_port_t *);
 | 
			
		||||
int qla24xx_post_gidpn_work(struct scsi_qla_host *, fc_port_t *);
 | 
			
		||||
void qla24xx_handle_gidpn_event(scsi_qla_host_t *, struct event_arg *);
 | 
			
		||||
 | 
			
		||||
extern void qla2x00_free_fcport(fc_port_t *);
 | 
			
		||||
 | 
			
		||||
extern int qla24xx_post_gpnid_work(struct scsi_qla_host *, port_id_t *);
 | 
			
		||||
extern int qla24xx_async_gpnid(scsi_qla_host_t *, port_id_t *);
 | 
			
		||||
void qla24xx_async_gpnid_done(scsi_qla_host_t *, srb_t*);
 | 
			
		||||
void qla24xx_handle_gpnid_event(scsi_qla_host_t *, struct event_arg *);
 | 
			
		||||
 | 
			
		||||
int qla24xx_post_gpsc_work(struct scsi_qla_host *, fc_port_t *);
 | 
			
		||||
int qla24xx_async_gpsc(scsi_qla_host_t *, fc_port_t *);
 | 
			
		||||
int qla2x00_mgmt_svr_login(scsi_qla_host_t *);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Global Function Prototypes in qla_attr.c source file.
 | 
			
		||||
| 
						 | 
				
			
			@ -803,4 +833,16 @@ extern int qla_get_exchoffld_status(scsi_qla_host_t *, uint16_t *, uint16_t *);
 | 
			
		|||
extern int qla_set_exchoffld_mem_cfg(scsi_qla_host_t *, dma_addr_t);
 | 
			
		||||
extern void qlt_handle_abts_recv(struct scsi_qla_host *, response_t *);
 | 
			
		||||
 | 
			
		||||
int qla24xx_async_notify_ack(scsi_qla_host_t *, fc_port_t *,
 | 
			
		||||
	struct imm_ntfy_from_isp *, int);
 | 
			
		||||
void qla24xx_do_nack_work(struct scsi_qla_host *, struct qla_work_evt *);
 | 
			
		||||
void qlt_plogi_ack_link(struct scsi_qla_host *, struct qlt_plogi_ack_t *,
 | 
			
		||||
	struct fc_port *, enum qlt_plogi_link_t);
 | 
			
		||||
void qlt_plogi_ack_unref(struct scsi_qla_host *, struct qlt_plogi_ack_t *);
 | 
			
		||||
extern void qlt_schedule_sess_for_deletion(struct fc_port *, bool);
 | 
			
		||||
extern void qlt_schedule_sess_for_deletion_lock(struct fc_port *);
 | 
			
		||||
extern struct fc_port *qlt_find_sess_invalidate_other(scsi_qla_host_t *,
 | 
			
		||||
	uint64_t wwn, port_id_t port_id, uint16_t loop_id, struct fc_port **);
 | 
			
		||||
void qla24xx_delete_sess_fn(struct work_struct *);
 | 
			
		||||
 | 
			
		||||
#endif /* _QLA_GBL_H */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,12 +24,12 @@ static int qla2x00_sns_rnn_id(scsi_qla_host_t *);
 | 
			
		|||
 * Returns a pointer to the @ha's ms_iocb.
 | 
			
		||||
 */
 | 
			
		||||
void *
 | 
			
		||||
qla2x00_prep_ms_iocb(scsi_qla_host_t *vha, uint32_t req_size, uint32_t rsp_size)
 | 
			
		||||
qla2x00_prep_ms_iocb(scsi_qla_host_t *vha, struct ct_arg *arg)
 | 
			
		||||
{
 | 
			
		||||
	struct qla_hw_data *ha = vha->hw;
 | 
			
		||||
	ms_iocb_entry_t *ms_pkt;
 | 
			
		||||
 | 
			
		||||
	ms_pkt = ha->ms_iocb;
 | 
			
		||||
	ms_pkt = (ms_iocb_entry_t *)arg->iocb;
 | 
			
		||||
	memset(ms_pkt, 0, sizeof(ms_iocb_entry_t));
 | 
			
		||||
 | 
			
		||||
	ms_pkt->entry_type = MS_IOCB_TYPE;
 | 
			
		||||
| 
						 | 
				
			
			@ -39,15 +39,15 @@ qla2x00_prep_ms_iocb(scsi_qla_host_t *vha, uint32_t req_size, uint32_t rsp_size)
 | 
			
		|||
	ms_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
 | 
			
		||||
	ms_pkt->cmd_dsd_count = cpu_to_le16(1);
 | 
			
		||||
	ms_pkt->total_dsd_count = cpu_to_le16(2);
 | 
			
		||||
	ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size);
 | 
			
		||||
	ms_pkt->req_bytecount = cpu_to_le32(req_size);
 | 
			
		||||
	ms_pkt->rsp_bytecount = cpu_to_le32(arg->rsp_size);
 | 
			
		||||
	ms_pkt->req_bytecount = cpu_to_le32(arg->req_size);
 | 
			
		||||
 | 
			
		||||
	ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
 | 
			
		||||
	ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
 | 
			
		||||
	ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(arg->req_dma));
 | 
			
		||||
	ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(arg->req_dma));
 | 
			
		||||
	ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
 | 
			
		||||
 | 
			
		||||
	ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
 | 
			
		||||
	ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
 | 
			
		||||
	ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(arg->rsp_dma));
 | 
			
		||||
	ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(arg->rsp_dma));
 | 
			
		||||
	ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount;
 | 
			
		||||
 | 
			
		||||
	vha->qla_stats.control_requests++;
 | 
			
		||||
| 
						 | 
				
			
			@ -64,29 +64,29 @@ qla2x00_prep_ms_iocb(scsi_qla_host_t *vha, uint32_t req_size, uint32_t rsp_size)
 | 
			
		|||
 * Returns a pointer to the @ha's ms_iocb.
 | 
			
		||||
 */
 | 
			
		||||
void *
 | 
			
		||||
qla24xx_prep_ms_iocb(scsi_qla_host_t *vha, uint32_t req_size, uint32_t rsp_size)
 | 
			
		||||
qla24xx_prep_ms_iocb(scsi_qla_host_t *vha, struct ct_arg *arg)
 | 
			
		||||
{
 | 
			
		||||
	struct qla_hw_data *ha = vha->hw;
 | 
			
		||||
	struct ct_entry_24xx *ct_pkt;
 | 
			
		||||
 | 
			
		||||
	ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
 | 
			
		||||
	ct_pkt = (struct ct_entry_24xx *)arg->iocb;
 | 
			
		||||
	memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
 | 
			
		||||
 | 
			
		||||
	ct_pkt->entry_type = CT_IOCB_TYPE;
 | 
			
		||||
	ct_pkt->entry_count = 1;
 | 
			
		||||
	ct_pkt->nport_handle = cpu_to_le16(NPH_SNS);
 | 
			
		||||
	ct_pkt->nport_handle = cpu_to_le16(arg->nport_handle);
 | 
			
		||||
	ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
 | 
			
		||||
	ct_pkt->cmd_dsd_count = cpu_to_le16(1);
 | 
			
		||||
	ct_pkt->rsp_dsd_count = cpu_to_le16(1);
 | 
			
		||||
	ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
 | 
			
		||||
	ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
 | 
			
		||||
	ct_pkt->rsp_byte_count = cpu_to_le32(arg->rsp_size);
 | 
			
		||||
	ct_pkt->cmd_byte_count = cpu_to_le32(arg->req_size);
 | 
			
		||||
 | 
			
		||||
	ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
 | 
			
		||||
	ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
 | 
			
		||||
	ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(arg->req_dma));
 | 
			
		||||
	ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(arg->req_dma));
 | 
			
		||||
	ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
 | 
			
		||||
 | 
			
		||||
	ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
 | 
			
		||||
	ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
 | 
			
		||||
	ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(arg->rsp_dma));
 | 
			
		||||
	ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(arg->rsp_dma));
 | 
			
		||||
	ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
 | 
			
		||||
	ct_pkt->vp_index = vha->vp_idx;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -117,7 +117,7 @@ qla2x00_prep_ct_req(struct ct_sns_pkt *p, uint16_t cmd, uint16_t rsp_size)
 | 
			
		|||
	return &p->p.req;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
int
 | 
			
		||||
qla2x00_chk_ms_status(scsi_qla_host_t *vha, ms_iocb_entry_t *ms_pkt,
 | 
			
		||||
    struct ct_sns_rsp *ct_rsp, const char *routine)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -183,14 +183,21 @@ qla2x00_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
 | 
			
		|||
	struct ct_sns_req	*ct_req;
 | 
			
		||||
	struct ct_sns_rsp	*ct_rsp;
 | 
			
		||||
	struct qla_hw_data *ha = vha->hw;
 | 
			
		||||
	struct ct_arg arg;
 | 
			
		||||
 | 
			
		||||
	if (IS_QLA2100(ha) || IS_QLA2200(ha))
 | 
			
		||||
		return qla2x00_sns_ga_nxt(vha, fcport);
 | 
			
		||||
 | 
			
		||||
	arg.iocb = ha->ms_iocb;
 | 
			
		||||
	arg.req_dma = ha->ct_sns_dma;
 | 
			
		||||
	arg.rsp_dma = ha->ct_sns_dma;
 | 
			
		||||
	arg.req_size = GA_NXT_REQ_SIZE;
 | 
			
		||||
	arg.rsp_size = GA_NXT_RSP_SIZE;
 | 
			
		||||
	arg.nport_handle = NPH_SNS;
 | 
			
		||||
 | 
			
		||||
	/* Issue GA_NXT */
 | 
			
		||||
	/* Prepare common MS IOCB */
 | 
			
		||||
	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GA_NXT_REQ_SIZE,
 | 
			
		||||
	    GA_NXT_RSP_SIZE);
 | 
			
		||||
	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
 | 
			
		||||
 | 
			
		||||
	/* Prepare CT request */
 | 
			
		||||
	ct_req = qla2x00_prep_ct_req(ha->ct_sns, GA_NXT_CMD,
 | 
			
		||||
| 
						 | 
				
			
			@ -269,16 +276,24 @@ qla2x00_gid_pt(scsi_qla_host_t *vha, sw_info_t *list)
 | 
			
		|||
	struct ct_sns_gid_pt_data *gid_data;
 | 
			
		||||
	struct qla_hw_data *ha = vha->hw;
 | 
			
		||||
	uint16_t gid_pt_rsp_size;
 | 
			
		||||
	struct ct_arg arg;
 | 
			
		||||
 | 
			
		||||
	if (IS_QLA2100(ha) || IS_QLA2200(ha))
 | 
			
		||||
		return qla2x00_sns_gid_pt(vha, list);
 | 
			
		||||
 | 
			
		||||
	gid_data = NULL;
 | 
			
		||||
	gid_pt_rsp_size = qla2x00_gid_pt_rsp_size(vha);
 | 
			
		||||
 | 
			
		||||
	arg.iocb = ha->ms_iocb;
 | 
			
		||||
	arg.req_dma = ha->ct_sns_dma;
 | 
			
		||||
	arg.rsp_dma = ha->ct_sns_dma;
 | 
			
		||||
	arg.req_size = GID_PT_REQ_SIZE;
 | 
			
		||||
	arg.rsp_size = gid_pt_rsp_size;
 | 
			
		||||
	arg.nport_handle = NPH_SNS;
 | 
			
		||||
 | 
			
		||||
	/* Issue GID_PT */
 | 
			
		||||
	/* Prepare common MS IOCB */
 | 
			
		||||
	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GID_PT_REQ_SIZE,
 | 
			
		||||
	    gid_pt_rsp_size);
 | 
			
		||||
	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
 | 
			
		||||
 | 
			
		||||
	/* Prepare CT request */
 | 
			
		||||
	ct_req = qla2x00_prep_ct_req(ha->ct_sns, GID_PT_CMD, gid_pt_rsp_size);
 | 
			
		||||
| 
						 | 
				
			
			@ -344,15 +359,22 @@ qla2x00_gpn_id(scsi_qla_host_t *vha, sw_info_t *list)
 | 
			
		|||
	struct ct_sns_req	*ct_req;
 | 
			
		||||
	struct ct_sns_rsp	*ct_rsp;
 | 
			
		||||
	struct qla_hw_data *ha = vha->hw;
 | 
			
		||||
	struct ct_arg arg;
 | 
			
		||||
 | 
			
		||||
	if (IS_QLA2100(ha) || IS_QLA2200(ha))
 | 
			
		||||
		return qla2x00_sns_gpn_id(vha, list);
 | 
			
		||||
 | 
			
		||||
	arg.iocb = ha->ms_iocb;
 | 
			
		||||
	arg.req_dma = ha->ct_sns_dma;
 | 
			
		||||
	arg.rsp_dma = ha->ct_sns_dma;
 | 
			
		||||
	arg.req_size = GPN_ID_REQ_SIZE;
 | 
			
		||||
	arg.rsp_size = GPN_ID_RSP_SIZE;
 | 
			
		||||
	arg.nport_handle = NPH_SNS;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < ha->max_fibre_devices; i++) {
 | 
			
		||||
		/* Issue GPN_ID */
 | 
			
		||||
		/* Prepare common MS IOCB */
 | 
			
		||||
		ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GPN_ID_REQ_SIZE,
 | 
			
		||||
		    GPN_ID_RSP_SIZE);
 | 
			
		||||
		ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
 | 
			
		||||
 | 
			
		||||
		/* Prepare CT request */
 | 
			
		||||
		ct_req = qla2x00_prep_ct_req(ha->ct_sns, GPN_ID_CMD,
 | 
			
		||||
| 
						 | 
				
			
			@ -406,15 +428,22 @@ qla2x00_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
 | 
			
		|||
	ms_iocb_entry_t	*ms_pkt;
 | 
			
		||||
	struct ct_sns_req	*ct_req;
 | 
			
		||||
	struct ct_sns_rsp	*ct_rsp;
 | 
			
		||||
	struct ct_arg arg;
 | 
			
		||||
 | 
			
		||||
	if (IS_QLA2100(ha) || IS_QLA2200(ha))
 | 
			
		||||
		return qla2x00_sns_gnn_id(vha, list);
 | 
			
		||||
 | 
			
		||||
	arg.iocb = ha->ms_iocb;
 | 
			
		||||
	arg.req_dma = ha->ct_sns_dma;
 | 
			
		||||
	arg.rsp_dma = ha->ct_sns_dma;
 | 
			
		||||
	arg.req_size = GNN_ID_REQ_SIZE;
 | 
			
		||||
	arg.rsp_size = GNN_ID_RSP_SIZE;
 | 
			
		||||
	arg.nport_handle = NPH_SNS;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < ha->max_fibre_devices; i++) {
 | 
			
		||||
		/* Issue GNN_ID */
 | 
			
		||||
		/* Prepare common MS IOCB */
 | 
			
		||||
		ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GNN_ID_REQ_SIZE,
 | 
			
		||||
		    GNN_ID_RSP_SIZE);
 | 
			
		||||
		ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
 | 
			
		||||
 | 
			
		||||
		/* Prepare CT request */
 | 
			
		||||
		ct_req = qla2x00_prep_ct_req(ha->ct_sns, GNN_ID_CMD,
 | 
			
		||||
| 
						 | 
				
			
			@ -473,14 +502,21 @@ qla2x00_rft_id(scsi_qla_host_t *vha)
 | 
			
		|||
	ms_iocb_entry_t	*ms_pkt;
 | 
			
		||||
	struct ct_sns_req	*ct_req;
 | 
			
		||||
	struct ct_sns_rsp	*ct_rsp;
 | 
			
		||||
	struct ct_arg arg;
 | 
			
		||||
 | 
			
		||||
	if (IS_QLA2100(ha) || IS_QLA2200(ha))
 | 
			
		||||
		return qla2x00_sns_rft_id(vha);
 | 
			
		||||
 | 
			
		||||
	arg.iocb = ha->ms_iocb;
 | 
			
		||||
	arg.req_dma = ha->ct_sns_dma;
 | 
			
		||||
	arg.rsp_dma = ha->ct_sns_dma;
 | 
			
		||||
	arg.req_size = RFT_ID_REQ_SIZE;
 | 
			
		||||
	arg.rsp_size = RFT_ID_RSP_SIZE;
 | 
			
		||||
	arg.nport_handle = NPH_SNS;
 | 
			
		||||
 | 
			
		||||
	/* Issue RFT_ID */
 | 
			
		||||
	/* Prepare common MS IOCB */
 | 
			
		||||
	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, RFT_ID_REQ_SIZE,
 | 
			
		||||
	    RFT_ID_RSP_SIZE);
 | 
			
		||||
	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
 | 
			
		||||
 | 
			
		||||
	/* Prepare CT request */
 | 
			
		||||
	ct_req = qla2x00_prep_ct_req(ha->ct_sns, RFT_ID_CMD,
 | 
			
		||||
| 
						 | 
				
			
			@ -526,6 +562,7 @@ qla2x00_rff_id(scsi_qla_host_t *vha)
 | 
			
		|||
	ms_iocb_entry_t	*ms_pkt;
 | 
			
		||||
	struct ct_sns_req	*ct_req;
 | 
			
		||||
	struct ct_sns_rsp	*ct_rsp;
 | 
			
		||||
	struct ct_arg arg;
 | 
			
		||||
 | 
			
		||||
	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
 | 
			
		||||
		ql_dbg(ql_dbg_disc, vha, 0x2046,
 | 
			
		||||
| 
						 | 
				
			
			@ -533,10 +570,16 @@ qla2x00_rff_id(scsi_qla_host_t *vha)
 | 
			
		|||
		return (QLA_SUCCESS);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	arg.iocb = ha->ms_iocb;
 | 
			
		||||
	arg.req_dma = ha->ct_sns_dma;
 | 
			
		||||
	arg.rsp_dma = ha->ct_sns_dma;
 | 
			
		||||
	arg.req_size = RFF_ID_REQ_SIZE;
 | 
			
		||||
	arg.rsp_size = RFF_ID_RSP_SIZE;
 | 
			
		||||
	arg.nport_handle = NPH_SNS;
 | 
			
		||||
 | 
			
		||||
	/* Issue RFF_ID */
 | 
			
		||||
	/* Prepare common MS IOCB */
 | 
			
		||||
	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, RFF_ID_REQ_SIZE,
 | 
			
		||||
	    RFF_ID_RSP_SIZE);
 | 
			
		||||
	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
 | 
			
		||||
 | 
			
		||||
	/* Prepare CT request */
 | 
			
		||||
	ct_req = qla2x00_prep_ct_req(ha->ct_sns, RFF_ID_CMD,
 | 
			
		||||
| 
						 | 
				
			
			@ -584,14 +627,21 @@ qla2x00_rnn_id(scsi_qla_host_t *vha)
 | 
			
		|||
	ms_iocb_entry_t	*ms_pkt;
 | 
			
		||||
	struct ct_sns_req	*ct_req;
 | 
			
		||||
	struct ct_sns_rsp	*ct_rsp;
 | 
			
		||||
	struct ct_arg arg;
 | 
			
		||||
 | 
			
		||||
	if (IS_QLA2100(ha) || IS_QLA2200(ha))
 | 
			
		||||
		return qla2x00_sns_rnn_id(vha);
 | 
			
		||||
 | 
			
		||||
	arg.iocb = ha->ms_iocb;
 | 
			
		||||
	arg.req_dma = ha->ct_sns_dma;
 | 
			
		||||
	arg.rsp_dma = ha->ct_sns_dma;
 | 
			
		||||
	arg.req_size = RNN_ID_REQ_SIZE;
 | 
			
		||||
	arg.rsp_size = RNN_ID_RSP_SIZE;
 | 
			
		||||
	arg.nport_handle = NPH_SNS;
 | 
			
		||||
 | 
			
		||||
	/* Issue RNN_ID */
 | 
			
		||||
	/* Prepare common MS IOCB */
 | 
			
		||||
	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, RNN_ID_REQ_SIZE,
 | 
			
		||||
	    RNN_ID_RSP_SIZE);
 | 
			
		||||
	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
 | 
			
		||||
 | 
			
		||||
	/* Prepare CT request */
 | 
			
		||||
	ct_req = qla2x00_prep_ct_req(ha->ct_sns, RNN_ID_CMD, RNN_ID_RSP_SIZE);
 | 
			
		||||
| 
						 | 
				
			
			@ -651,6 +701,7 @@ qla2x00_rsnn_nn(scsi_qla_host_t *vha)
 | 
			
		|||
	ms_iocb_entry_t	*ms_pkt;
 | 
			
		||||
	struct ct_sns_req	*ct_req;
 | 
			
		||||
	struct ct_sns_rsp	*ct_rsp;
 | 
			
		||||
	struct ct_arg arg;
 | 
			
		||||
 | 
			
		||||
	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
 | 
			
		||||
		ql_dbg(ql_dbg_disc, vha, 0x2050,
 | 
			
		||||
| 
						 | 
				
			
			@ -658,10 +709,17 @@ qla2x00_rsnn_nn(scsi_qla_host_t *vha)
 | 
			
		|||
		return (QLA_SUCCESS);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	arg.iocb = ha->ms_iocb;
 | 
			
		||||
	arg.req_dma = ha->ct_sns_dma;
 | 
			
		||||
	arg.rsp_dma = ha->ct_sns_dma;
 | 
			
		||||
	arg.req_size = 0;
 | 
			
		||||
	arg.rsp_size = RSNN_NN_RSP_SIZE;
 | 
			
		||||
	arg.nport_handle = NPH_SNS;
 | 
			
		||||
 | 
			
		||||
	/* Issue RSNN_NN */
 | 
			
		||||
	/* Prepare common MS IOCB */
 | 
			
		||||
	/*   Request size adjusted after CT preparation */
 | 
			
		||||
	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, 0, RSNN_NN_RSP_SIZE);
 | 
			
		||||
	ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
 | 
			
		||||
 | 
			
		||||
	/* Prepare CT request */
 | 
			
		||||
	ct_req = qla2x00_prep_ct_req(ha->ct_sns, RSNN_NN_CMD,
 | 
			
		||||
| 
						 | 
				
			
			@ -1103,7 +1161,7 @@ qla2x00_sns_rnn_id(scsi_qla_host_t *vha)
 | 
			
		|||
 *
 | 
			
		||||
 * Returns 0 on success.
 | 
			
		||||
 */
 | 
			
		||||
static int
 | 
			
		||||
int
 | 
			
		||||
qla2x00_mgmt_svr_login(scsi_qla_host_t *vha)
 | 
			
		||||
{
 | 
			
		||||
	int ret, rval;
 | 
			
		||||
| 
						 | 
				
			
			@ -2425,15 +2483,22 @@ qla2x00_gfpn_id(scsi_qla_host_t *vha, sw_info_t *list)
 | 
			
		|||
	ms_iocb_entry_t	*ms_pkt;
 | 
			
		||||
	struct ct_sns_req	*ct_req;
 | 
			
		||||
	struct ct_sns_rsp	*ct_rsp;
 | 
			
		||||
	struct ct_arg arg;
 | 
			
		||||
 | 
			
		||||
	if (!IS_IIDMA_CAPABLE(ha))
 | 
			
		||||
		return QLA_FUNCTION_FAILED;
 | 
			
		||||
 | 
			
		||||
	arg.iocb = ha->ms_iocb;
 | 
			
		||||
	arg.req_dma = ha->ct_sns_dma;
 | 
			
		||||
	arg.rsp_dma = ha->ct_sns_dma;
 | 
			
		||||
	arg.req_size = GFPN_ID_REQ_SIZE;
 | 
			
		||||
	arg.rsp_size = GFPN_ID_RSP_SIZE;
 | 
			
		||||
	arg.nport_handle = NPH_SNS;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < ha->max_fibre_devices; i++) {
 | 
			
		||||
		/* Issue GFPN_ID */
 | 
			
		||||
		/* Prepare common MS IOCB */
 | 
			
		||||
		ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GFPN_ID_REQ_SIZE,
 | 
			
		||||
		    GFPN_ID_RSP_SIZE);
 | 
			
		||||
		ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
 | 
			
		||||
 | 
			
		||||
		/* Prepare CT request */
 | 
			
		||||
		ct_req = qla2x00_prep_ct_req(ha->ct_sns, GFPN_ID_CMD,
 | 
			
		||||
| 
						 | 
				
			
			@ -2471,36 +2536,6 @@ qla2x00_gfpn_id(scsi_qla_host_t *vha, sw_info_t *list)
 | 
			
		|||
	return (rval);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void *
 | 
			
		||||
qla24xx_prep_ms_fm_iocb(scsi_qla_host_t *vha, uint32_t req_size,
 | 
			
		||||
    uint32_t rsp_size)
 | 
			
		||||
{
 | 
			
		||||
	struct ct_entry_24xx *ct_pkt;
 | 
			
		||||
	struct qla_hw_data *ha = vha->hw;
 | 
			
		||||
	ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
 | 
			
		||||
	memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
 | 
			
		||||
 | 
			
		||||
	ct_pkt->entry_type = CT_IOCB_TYPE;
 | 
			
		||||
	ct_pkt->entry_count = 1;
 | 
			
		||||
	ct_pkt->nport_handle = cpu_to_le16(vha->mgmt_svr_loop_id);
 | 
			
		||||
	ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
 | 
			
		||||
	ct_pkt->cmd_dsd_count = cpu_to_le16(1);
 | 
			
		||||
	ct_pkt->rsp_dsd_count = cpu_to_le16(1);
 | 
			
		||||
	ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
 | 
			
		||||
	ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
 | 
			
		||||
 | 
			
		||||
	ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
 | 
			
		||||
	ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
 | 
			
		||||
	ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
 | 
			
		||||
 | 
			
		||||
	ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
 | 
			
		||||
	ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
 | 
			
		||||
	ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
 | 
			
		||||
	ct_pkt->vp_index = vha->vp_idx;
 | 
			
		||||
 | 
			
		||||
	return ct_pkt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static inline struct ct_sns_req *
 | 
			
		||||
qla24xx_prep_ct_fm_req(struct ct_sns_pkt *p, uint16_t cmd,
 | 
			
		||||
| 
						 | 
				
			
			@ -2530,9 +2565,10 @@ qla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list)
 | 
			
		|||
	int		rval;
 | 
			
		||||
	uint16_t	i;
 | 
			
		||||
	struct qla_hw_data *ha = vha->hw;
 | 
			
		||||
	ms_iocb_entry_t	*ms_pkt;
 | 
			
		||||
	ms_iocb_entry_t *ms_pkt;
 | 
			
		||||
	struct ct_sns_req	*ct_req;
 | 
			
		||||
	struct ct_sns_rsp	*ct_rsp;
 | 
			
		||||
	struct ct_arg arg;
 | 
			
		||||
 | 
			
		||||
	if (!IS_IIDMA_CAPABLE(ha))
 | 
			
		||||
		return QLA_FUNCTION_FAILED;
 | 
			
		||||
| 
						 | 
				
			
			@ -2543,11 +2579,17 @@ qla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list)
 | 
			
		|||
	if (rval)
 | 
			
		||||
		return rval;
 | 
			
		||||
 | 
			
		||||
	arg.iocb = ha->ms_iocb;
 | 
			
		||||
	arg.req_dma = ha->ct_sns_dma;
 | 
			
		||||
	arg.rsp_dma = ha->ct_sns_dma;
 | 
			
		||||
	arg.req_size = GPSC_REQ_SIZE;
 | 
			
		||||
	arg.rsp_size = GPSC_RSP_SIZE;
 | 
			
		||||
	arg.nport_handle = vha->mgmt_svr_loop_id;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < ha->max_fibre_devices; i++) {
 | 
			
		||||
		/* Issue GFPN_ID */
 | 
			
		||||
		/* Prepare common MS IOCB */
 | 
			
		||||
		ms_pkt = qla24xx_prep_ms_fm_iocb(vha, GPSC_REQ_SIZE,
 | 
			
		||||
		    GPSC_RSP_SIZE);
 | 
			
		||||
		ms_pkt = qla24xx_prep_ms_iocb(vha, &arg);
 | 
			
		||||
 | 
			
		||||
		/* Prepare CT request */
 | 
			
		||||
		ct_req = qla24xx_prep_ct_fm_req(ha->ct_sns, GPSC_CMD,
 | 
			
		||||
| 
						 | 
				
			
			@ -2641,6 +2683,7 @@ qla2x00_gff_id(scsi_qla_host_t *vha, sw_info_t *list)
 | 
			
		|||
	struct ct_sns_rsp	*ct_rsp;
 | 
			
		||||
	struct qla_hw_data *ha = vha->hw;
 | 
			
		||||
	uint8_t fcp_scsi_features = 0;
 | 
			
		||||
	struct ct_arg arg;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < ha->max_fibre_devices; i++) {
 | 
			
		||||
		/* Set default FC4 Type as UNKNOWN so the default is to
 | 
			
		||||
| 
						 | 
				
			
			@ -2651,9 +2694,15 @@ qla2x00_gff_id(scsi_qla_host_t *vha, sw_info_t *list)
 | 
			
		|||
		if (!IS_FWI2_CAPABLE(ha))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		arg.iocb = ha->ms_iocb;
 | 
			
		||||
		arg.req_dma = ha->ct_sns_dma;
 | 
			
		||||
		arg.rsp_dma = ha->ct_sns_dma;
 | 
			
		||||
		arg.req_size = GFF_ID_REQ_SIZE;
 | 
			
		||||
		arg.rsp_size = GFF_ID_RSP_SIZE;
 | 
			
		||||
		arg.nport_handle = NPH_SNS;
 | 
			
		||||
 | 
			
		||||
		/* Prepare common MS IOCB */
 | 
			
		||||
		ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GFF_ID_REQ_SIZE,
 | 
			
		||||
		    GFF_ID_RSP_SIZE);
 | 
			
		||||
		ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
 | 
			
		||||
 | 
			
		||||
		/* Prepare CT request */
 | 
			
		||||
		ct_req = qla2x00_prep_ct_req(ha->ct_sns, GFF_ID_CMD,
 | 
			
		||||
| 
						 | 
				
			
			@ -2692,3 +2741,536 @@ qla2x00_gff_id(scsi_qla_host_t *vha, sw_info_t *list)
 | 
			
		|||
			break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* GID_PN completion processing. */
 | 
			
		||||
void qla24xx_handle_gidpn_event(scsi_qla_host_t *vha, struct event_arg *ea)
 | 
			
		||||
{
 | 
			
		||||
	fc_port_t *fcport = ea->fcport;
 | 
			
		||||
 | 
			
		||||
	ql_dbg(ql_dbg_disc, vha, 0xffff,
 | 
			
		||||
		"%s %8phC login state %d \n",
 | 
			
		||||
		__func__, fcport->port_name, fcport->fw_login_state);
 | 
			
		||||
 | 
			
		||||
	if (ea->sp->gen2 != fcport->login_gen) {
 | 
			
		||||
		/* PLOGI/PRLI/LOGO came in while cmd was out.*/
 | 
			
		||||
		ql_dbg(ql_dbg_disc, vha, 0xffff,
 | 
			
		||||
		    "%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;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!ea->rc) {
 | 
			
		||||
		if (ea->sp->gen1 == fcport->rscn_gen) {
 | 
			
		||||
			fcport->scan_state = QLA_FCPORT_FOUND;
 | 
			
		||||
			fcport->flags |= FCF_FABRIC_DEVICE;
 | 
			
		||||
 | 
			
		||||
			if (fcport->d_id.b24 == ea->id.b24) {
 | 
			
		||||
				/* cable plugged into the same place */
 | 
			
		||||
				switch (vha->host->active_mode) {
 | 
			
		||||
				case MODE_TARGET:
 | 
			
		||||
					/* NOOP. let the other guy login to us.*/
 | 
			
		||||
					break;
 | 
			
		||||
				case MODE_INITIATOR:
 | 
			
		||||
				case MODE_DUAL:
 | 
			
		||||
				default:
 | 
			
		||||
					if (atomic_read(&fcport->state) ==
 | 
			
		||||
					    FCS_ONLINE)
 | 
			
		||||
						break;
 | 
			
		||||
					ql_dbg(ql_dbg_disc, vha, 0xffff,
 | 
			
		||||
					    "%s %d %8phC post gnl\n",
 | 
			
		||||
					    __func__, __LINE__, fcport->port_name);
 | 
			
		||||
					qla24xx_post_gnl_work(vha, fcport);
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
			} else { /* fcport->d_id.b24 != ea->id.b24 */
 | 
			
		||||
				fcport->d_id.b24 = ea->id.b24;
 | 
			
		||||
				if (fcport->deleted == QLA_SESS_DELETED) {
 | 
			
		||||
					ql_dbg(ql_dbg_disc, vha, 0xffff,
 | 
			
		||||
					    "%s %d %8phC post del sess\n",
 | 
			
		||||
					    __func__, __LINE__, fcport->port_name);
 | 
			
		||||
					qlt_schedule_sess_for_deletion_lock(fcport);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		} else { /* ea->sp->gen1 != fcport->rscn_gen */
 | 
			
		||||
			ql_dbg(ql_dbg_disc, vha, 0xffff,
 | 
			
		||||
			    "%s %d %8phC post gidpn\n",
 | 
			
		||||
			    __func__, __LINE__, fcport->port_name);
 | 
			
		||||
			/* rscn came in while cmd was out */
 | 
			
		||||
			qla24xx_post_gidpn_work(vha, fcport);
 | 
			
		||||
		}
 | 
			
		||||
	} else { /* ea->rc */
 | 
			
		||||
		/* cable pulled */
 | 
			
		||||
		if (ea->sp->gen1 == fcport->rscn_gen) {
 | 
			
		||||
			if (ea->sp->gen2 == fcport->login_gen) {
 | 
			
		||||
				ql_dbg(ql_dbg_disc, vha, 0xffff,
 | 
			
		||||
				    "%s %d %8phC post del sess\n", __func__,
 | 
			
		||||
				    __LINE__, fcport->port_name);
 | 
			
		||||
				qlt_schedule_sess_for_deletion_lock(fcport);
 | 
			
		||||
			} else {
 | 
			
		||||
				ql_dbg(ql_dbg_disc, vha, 0xffff,
 | 
			
		||||
				    "%s %d %8phC login\n", __func__, __LINE__,
 | 
			
		||||
				    fcport->port_name);
 | 
			
		||||
				qla24xx_fcport_handle_login(vha, fcport);
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			ql_dbg(ql_dbg_disc, vha, 0xffff,
 | 
			
		||||
			    "%s %d %8phC post gidpn\n", __func__, __LINE__,
 | 
			
		||||
			    fcport->port_name);
 | 
			
		||||
			qla24xx_post_gidpn_work(vha, fcport);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
} /* gidpn_event */
 | 
			
		||||
 | 
			
		||||
static void qla2x00_async_gidpn_sp_done(void *v, void *s, int res)
 | 
			
		||||
{
 | 
			
		||||
	struct scsi_qla_host *vha = (struct scsi_qla_host *)v;
 | 
			
		||||
	struct srb *sp = (struct srb *)s;
 | 
			
		||||
	fc_port_t *fcport = sp->fcport;
 | 
			
		||||
	u8 *id = fcport->ct_desc.ct_sns->p.rsp.rsp.gid_pn.port_id;
 | 
			
		||||
	struct event_arg ea;
 | 
			
		||||
 | 
			
		||||
	fcport->flags &= ~FCF_ASYNC_SENT;
 | 
			
		||||
 | 
			
		||||
	memset(&ea, 0, sizeof(ea));
 | 
			
		||||
	ea.fcport = fcport;
 | 
			
		||||
	ea.id.b.domain = id[0];
 | 
			
		||||
	ea.id.b.area = id[1];
 | 
			
		||||
	ea.id.b.al_pa = id[2];
 | 
			
		||||
	ea.sp = sp;
 | 
			
		||||
	ea.rc = res;
 | 
			
		||||
	ea.event = FCME_GIDPN_DONE;
 | 
			
		||||
 | 
			
		||||
	ql_dbg(ql_dbg_disc, vha, 0xffff,
 | 
			
		||||
	    "Async done-%s res %x, WWPN %8phC ID %3phC \n",
 | 
			
		||||
	    sp->name, res, fcport->port_name, id);
 | 
			
		||||
 | 
			
		||||
	qla2x00_fcport_event_handler(vha, &ea);
 | 
			
		||||
 | 
			
		||||
	sp->free(vha, sp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int qla24xx_async_gidpn(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_GID_PN;
 | 
			
		||||
	fcport->scan_state = QLA_FCPORT_SCAN;
 | 
			
		||||
	sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
 | 
			
		||||
	if (!sp)
 | 
			
		||||
		goto done;
 | 
			
		||||
 | 
			
		||||
	sp->type = SRB_CT_PTHRU_CMD;
 | 
			
		||||
	sp->name = "gidpn";
 | 
			
		||||
	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, GID_PN_CMD,
 | 
			
		||||
		GID_PN_RSP_SIZE);
 | 
			
		||||
 | 
			
		||||
	/* GIDPN req */
 | 
			
		||||
	memcpy(ct_req->req.gid_pn.port_name, fcport->port_name,
 | 
			
		||||
		WWN_SIZE);
 | 
			
		||||
 | 
			
		||||
	/* 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 = GID_PN_REQ_SIZE;
 | 
			
		||||
	sp->u.iocb_cmd.u.ctarg.rsp_size = GID_PN_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_gidpn_sp_done;
 | 
			
		||||
 | 
			
		||||
	rval = qla2x00_start_sp(sp);
 | 
			
		||||
	if (rval != QLA_SUCCESS)
 | 
			
		||||
		goto done_free_sp;
 | 
			
		||||
 | 
			
		||||
	ql_dbg(ql_dbg_disc, vha, 0x206f,
 | 
			
		||||
		"Async-%s - %8phC hdl=%x loopid=%x portid %02x%02x%02x.\n",
 | 
			
		||||
		sp->name, fcport->port_name,
 | 
			
		||||
		sp->handle, fcport->loop_id, fcport->d_id.b.domain,
 | 
			
		||||
		fcport->d_id.b.area, fcport->d_id.b.al_pa);
 | 
			
		||||
	return rval;
 | 
			
		||||
 | 
			
		||||
done_free_sp:
 | 
			
		||||
	sp->free(vha, sp);
 | 
			
		||||
done:
 | 
			
		||||
	fcport->flags &= ~FCF_ASYNC_SENT;
 | 
			
		||||
	return rval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int qla24xx_post_gidpn_work(struct scsi_qla_host *vha, fc_port_t *fcport)
 | 
			
		||||
{
 | 
			
		||||
	struct qla_work_evt *e;
 | 
			
		||||
 | 
			
		||||
	if ((atomic_read(&vha->loop_state) != LOOP_READY) ||
 | 
			
		||||
		test_bit(UNLOADING, &vha->dpc_flags))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	e = qla2x00_alloc_work(vha, QLA_EVT_GIDPN);
 | 
			
		||||
	if (!e)
 | 
			
		||||
		return QLA_FUNCTION_FAILED;
 | 
			
		||||
 | 
			
		||||
	e->u.fcport.fcport = fcport;
 | 
			
		||||
	return qla2x00_post_work(vha, e);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int qla24xx_post_gpsc_work(struct scsi_qla_host *vha, fc_port_t *fcport)
 | 
			
		||||
{
 | 
			
		||||
	struct qla_work_evt *e;
 | 
			
		||||
 | 
			
		||||
	e = qla2x00_alloc_work(vha, QLA_EVT_GPSC);
 | 
			
		||||
	if (!e)
 | 
			
		||||
		return QLA_FUNCTION_FAILED;
 | 
			
		||||
 | 
			
		||||
	e->u.fcport.fcport = fcport;
 | 
			
		||||
	return qla2x00_post_work(vha, e);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void qla24xx_async_gpsc_sp_done(void *v, void *s, int res)
 | 
			
		||||
{
 | 
			
		||||
	struct scsi_qla_host *vha = (struct scsi_qla_host *)v;
 | 
			
		||||
	struct qla_hw_data *ha = vha->hw;
 | 
			
		||||
	struct srb *sp = (struct srb *)s;
 | 
			
		||||
	fc_port_t *fcport = sp->fcport;
 | 
			
		||||
	struct ct_sns_rsp       *ct_rsp;
 | 
			
		||||
	struct event_arg ea;
 | 
			
		||||
 | 
			
		||||
	ct_rsp = &fcport->ct_desc.ct_sns->p.rsp;
 | 
			
		||||
 | 
			
		||||
	ql_dbg(ql_dbg_disc, vha, 0xffff,
 | 
			
		||||
	    "Async done-%s res %x, WWPN %8phC \n",
 | 
			
		||||
	    sp->name, res, fcport->port_name);
 | 
			
		||||
 | 
			
		||||
	fcport->flags &= ~FCF_ASYNC_SENT;
 | 
			
		||||
 | 
			
		||||
	if (res == (DID_ERROR << 16)) {
 | 
			
		||||
		/* entry status error */
 | 
			
		||||
		goto done;
 | 
			
		||||
	} else if (res) {
 | 
			
		||||
		if ((ct_rsp->header.reason_code ==
 | 
			
		||||
			 CT_REASON_INVALID_COMMAND_CODE) ||
 | 
			
		||||
			(ct_rsp->header.reason_code ==
 | 
			
		||||
			 CT_REASON_COMMAND_UNSUPPORTED)) {
 | 
			
		||||
			ql_dbg(ql_dbg_disc, vha, 0x205a,
 | 
			
		||||
				"GPSC command unsupported, disabling "
 | 
			
		||||
				"query.\n");
 | 
			
		||||
			ha->flags.gpsc_supported = 0;
 | 
			
		||||
			res = QLA_SUCCESS;
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		switch (be16_to_cpu(ct_rsp->rsp.gpsc.speed)) {
 | 
			
		||||
		case BIT_15:
 | 
			
		||||
			fcport->fp_speed = PORT_SPEED_1GB;
 | 
			
		||||
			break;
 | 
			
		||||
		case BIT_14:
 | 
			
		||||
			fcport->fp_speed = PORT_SPEED_2GB;
 | 
			
		||||
			break;
 | 
			
		||||
		case BIT_13:
 | 
			
		||||
			fcport->fp_speed = PORT_SPEED_4GB;
 | 
			
		||||
			break;
 | 
			
		||||
		case BIT_12:
 | 
			
		||||
			fcport->fp_speed = PORT_SPEED_10GB;
 | 
			
		||||
			break;
 | 
			
		||||
		case BIT_11:
 | 
			
		||||
			fcport->fp_speed = PORT_SPEED_8GB;
 | 
			
		||||
			break;
 | 
			
		||||
		case BIT_10:
 | 
			
		||||
			fcport->fp_speed = PORT_SPEED_16GB;
 | 
			
		||||
			break;
 | 
			
		||||
		case BIT_8:
 | 
			
		||||
			fcport->fp_speed = PORT_SPEED_32GB;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ql_dbg(ql_dbg_disc, vha, 0xffff,
 | 
			
		||||
		"Async-%s OUT WWPN %8phC speeds=%04x speed=%04x.\n",
 | 
			
		||||
			sp->name,
 | 
			
		||||
			fcport->fabric_port_name,
 | 
			
		||||
			be16_to_cpu(ct_rsp->rsp.gpsc.speeds),
 | 
			
		||||
			be16_to_cpu(ct_rsp->rsp.gpsc.speed));
 | 
			
		||||
	}
 | 
			
		||||
done:
 | 
			
		||||
	memset(&ea, 0, sizeof(ea));
 | 
			
		||||
	ea.event = FCME_GPSC_DONE;
 | 
			
		||||
	ea.rc = res;
 | 
			
		||||
	ea.fcport = fcport;
 | 
			
		||||
	qla2x00_fcport_event_handler(vha, &ea);
 | 
			
		||||
 | 
			
		||||
	sp->free(vha, sp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int qla24xx_async_gpsc(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;
 | 
			
		||||
	sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
 | 
			
		||||
	if (!sp)
 | 
			
		||||
		goto done;
 | 
			
		||||
 | 
			
		||||
	sp->type = SRB_CT_PTHRU_CMD;
 | 
			
		||||
	sp->name = "gpsc";
 | 
			
		||||
	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 = qla24xx_prep_ct_fm_req(fcport->ct_desc.ct_sns, GPSC_CMD,
 | 
			
		||||
		GPSC_RSP_SIZE);
 | 
			
		||||
 | 
			
		||||
	/* GPSC req */
 | 
			
		||||
	memcpy(ct_req->req.gpsc.port_name, fcport->port_name,
 | 
			
		||||
		WWN_SIZE);
 | 
			
		||||
 | 
			
		||||
	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 = GPSC_REQ_SIZE;
 | 
			
		||||
	sp->u.iocb_cmd.u.ctarg.rsp_size = GPSC_RSP_SIZE;
 | 
			
		||||
	sp->u.iocb_cmd.u.ctarg.nport_handle = vha->mgmt_svr_loop_id;
 | 
			
		||||
 | 
			
		||||
	sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
 | 
			
		||||
	sp->done = qla24xx_async_gpsc_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=%02x%02x%02x.\n",
 | 
			
		||||
		sp->name, fcport->port_name, sp->handle,
 | 
			
		||||
		fcport->loop_id, fcport->d_id.b.domain,
 | 
			
		||||
		fcport->d_id.b.area, fcport->d_id.b.al_pa);
 | 
			
		||||
	return rval;
 | 
			
		||||
 | 
			
		||||
done_free_sp:
 | 
			
		||||
	sp->free(vha, sp);
 | 
			
		||||
done:
 | 
			
		||||
	fcport->flags &= ~FCF_ASYNC_SENT;
 | 
			
		||||
	return rval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int qla24xx_post_gpnid_work(struct scsi_qla_host *vha, port_id_t *id)
 | 
			
		||||
{
 | 
			
		||||
	struct qla_work_evt *e;
 | 
			
		||||
 | 
			
		||||
	if (test_bit(UNLOADING, &vha->dpc_flags))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	e = qla2x00_alloc_work(vha, QLA_EVT_GPNID);
 | 
			
		||||
	if (!e)
 | 
			
		||||
		return QLA_FUNCTION_FAILED;
 | 
			
		||||
 | 
			
		||||
	e->u.gpnid.id = *id;
 | 
			
		||||
	return qla2x00_post_work(vha, e);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void qla24xx_async_gpnid_done(scsi_qla_host_t *vha, srb_t *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(vha, sp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
 | 
			
		||||
{
 | 
			
		||||
	fc_port_t *fcport;
 | 
			
		||||
	unsigned long flags;
 | 
			
		||||
 | 
			
		||||
	spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
 | 
			
		||||
	fcport = qla2x00_find_fcport_by_wwpn(vha, ea->port_name, 1);
 | 
			
		||||
	spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
 | 
			
		||||
 | 
			
		||||
	if (fcport) {
 | 
			
		||||
		/* cable moved. just plugged in */
 | 
			
		||||
		ql_dbg(ql_dbg_disc, vha, 0xffff,
 | 
			
		||||
			   "%s %d %8phC post del sess\n",
 | 
			
		||||
			   __func__, __LINE__, fcport->port_name);
 | 
			
		||||
 | 
			
		||||
		fcport->rscn_gen++;
 | 
			
		||||
		fcport->d_id = ea->id;
 | 
			
		||||
		fcport->scan_state = QLA_FCPORT_FOUND;
 | 
			
		||||
		fcport->flags |= FCF_FABRIC_DEVICE;
 | 
			
		||||
 | 
			
		||||
		qlt_schedule_sess_for_deletion_lock(fcport);
 | 
			
		||||
	} else {
 | 
			
		||||
		/* create new fcport */
 | 
			
		||||
		ql_dbg(ql_dbg_disc, vha, 0xffff,
 | 
			
		||||
			   "%s %d %8phC post new sess\n",
 | 
			
		||||
			   __func__, __LINE__, ea->port_name);
 | 
			
		||||
 | 
			
		||||
		qla24xx_post_newsess_work(vha, &ea->id, ea->port_name, NULL);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void qla2x00_async_gpnid_sp_done(void *v, void *s, int res)
 | 
			
		||||
{
 | 
			
		||||
	struct scsi_qla_host *vha = (struct scsi_qla_host *)v;
 | 
			
		||||
	struct srb *sp = (struct srb *)s;
 | 
			
		||||
	struct ct_sns_req *ct_req =
 | 
			
		||||
	    (struct ct_sns_req *)sp->u.iocb_cmd.u.ctarg.req;
 | 
			
		||||
	struct ct_sns_rsp *ct_rsp =
 | 
			
		||||
	    (struct ct_sns_rsp *)sp->u.iocb_cmd.u.ctarg.rsp;
 | 
			
		||||
	struct event_arg ea;
 | 
			
		||||
	struct qla_work_evt *e;
 | 
			
		||||
 | 
			
		||||
	ql_dbg(ql_dbg_disc, vha, 0xffff,
 | 
			
		||||
		"Async done-%s res %x ID %3phC. %8phC\n",
 | 
			
		||||
		sp->name, res, ct_req->req.port_id.port_id,
 | 
			
		||||
		ct_rsp->rsp.gpn_id.port_name);
 | 
			
		||||
 | 
			
		||||
	memset(&ea, 0, sizeof(ea));
 | 
			
		||||
	memcpy(ea.port_name, ct_rsp->rsp.gpn_id.port_name, WWN_SIZE);
 | 
			
		||||
	ea.sp = sp;
 | 
			
		||||
	ea.id.b.domain = ct_req->req.port_id.port_id[0];
 | 
			
		||||
	ea.id.b.area = ct_req->req.port_id.port_id[1];
 | 
			
		||||
	ea.id.b.al_pa = ct_req->req.port_id.port_id[2];
 | 
			
		||||
	ea.rc = res;
 | 
			
		||||
	ea.event = FCME_GPNID_DONE;
 | 
			
		||||
 | 
			
		||||
	qla2x00_fcport_event_handler(vha, &ea);
 | 
			
		||||
 | 
			
		||||
	e = qla2x00_alloc_work(vha, QLA_EVT_GPNID_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;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		sp->free(vha, sp);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	e->u.iosb.sp = sp;
 | 
			
		||||
	qla2x00_post_work(vha, e);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Get WWPN with Nport ID. */
 | 
			
		||||
int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id)
 | 
			
		||||
{
 | 
			
		||||
	int rval = QLA_FUNCTION_FAILED;
 | 
			
		||||
	struct ct_sns_req       *ct_req;
 | 
			
		||||
	srb_t *sp;
 | 
			
		||||
	struct ct_sns_pkt *ct_sns;
 | 
			
		||||
 | 
			
		||||
	if (!vha->flags.online)
 | 
			
		||||
		goto done;
 | 
			
		||||
 | 
			
		||||
	sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
 | 
			
		||||
	if (!sp)
 | 
			
		||||
		goto done;
 | 
			
		||||
 | 
			
		||||
	sp->type = SRB_CT_PTHRU_CMD;
 | 
			
		||||
	sp->name = "gpnid";
 | 
			
		||||
	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
 | 
			
		||||
 | 
			
		||||
	sp->u.iocb_cmd.u.ctarg.req = dma_alloc_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;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,
 | 
			
		||||
		sizeof(struct ct_sns_pkt), &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;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp;
 | 
			
		||||
	memset(ct_sns, 0, sizeof(*ct_sns));
 | 
			
		||||
 | 
			
		||||
	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_ID_CMD, GPN_ID_RSP_SIZE);
 | 
			
		||||
 | 
			
		||||
	/* GPN_ID req */
 | 
			
		||||
	ct_req->req.port_id.port_id[0] = id->b.domain;
 | 
			
		||||
	ct_req->req.port_id.port_id[1] = id->b.area;
 | 
			
		||||
	ct_req->req.port_id.port_id[2] = id->b.al_pa;
 | 
			
		||||
 | 
			
		||||
	sp->u.iocb_cmd.u.ctarg.req_size = GPN_ID_REQ_SIZE;
 | 
			
		||||
	sp->u.iocb_cmd.u.ctarg.rsp_size = GPN_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_gpnid_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 ID %3phC.\n", sp->name,
 | 
			
		||||
		sp->handle, ct_req->req.port_id.port_id);
 | 
			
		||||
	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(vha, sp);
 | 
			
		||||
done:
 | 
			
		||||
	return rval;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
				
			
			@ -166,8 +166,8 @@ qla2x00_set_fcport_state(fc_port_t *fcport, int state)
 | 
			
		|||
	/* Don't print state transitions during initial allocation of fcport */
 | 
			
		||||
	if (old_state && old_state != state) {
 | 
			
		||||
		ql_dbg(ql_dbg_disc, fcport->vha, 0x207d,
 | 
			
		||||
		    "FCPort state transitioned from %s to %s - "
 | 
			
		||||
		    "portid=%02x%02x%02x.\n",
 | 
			
		||||
		    "FCPort %8phC state transitioned from %s to %s - "
 | 
			
		||||
			"portid=%02x%02x%02x.\n", fcport->port_name,
 | 
			
		||||
		    port_state_str[old_state], port_state_str[state],
 | 
			
		||||
		    fcport->d_id.b.domain, fcport->d_id.b.area,
 | 
			
		||||
		    fcport->d_id.b.al_pa);
 | 
			
		||||
| 
						 | 
				
			
			@ -263,6 +263,7 @@ qla2x00_get_sp(scsi_qla_host_t *vha, fc_port_t *fcport, gfp_t flag)
 | 
			
		|||
	memset(sp, 0, sizeof(*sp));
 | 
			
		||||
	sp->fcport = fcport;
 | 
			
		||||
	sp->iocbs = 1;
 | 
			
		||||
	sp->vha = vha;
 | 
			
		||||
done:
 | 
			
		||||
	if (!sp)
 | 
			
		||||
		QLA_VHA_MARK_NOT_BUSY(vha);
 | 
			
		||||
| 
						 | 
				
			
			@ -285,7 +286,7 @@ qla2x00_init_timer(srb_t *sp, unsigned long tmo)
 | 
			
		|||
	sp->u.iocb_cmd.timer.function = qla2x00_sp_timeout;
 | 
			
		||||
	add_timer(&sp->u.iocb_cmd.timer);
 | 
			
		||||
	sp->free = qla2x00_sp_free;
 | 
			
		||||
	if ((IS_QLAFX00(sp->fcport->vha->hw)) &&
 | 
			
		||||
	if ((IS_QLAFX00(((scsi_qla_host_t *)sp->vha)->hw)) &&
 | 
			
		||||
	    (sp->type == SRB_FXIOCB_DCMD))
 | 
			
		||||
		init_completion(&sp->u.iocb_cmd.u.fxiocb.fxiocb_comp);
 | 
			
		||||
	if (sp->type == SRB_ELS_DCMD)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2247,7 +2247,7 @@ qla24xx_logout_iocb(srb_t *sp, struct logio_entry_24xx *logio)
 | 
			
		|||
	logio->entry_type = LOGINOUT_PORT_IOCB_TYPE;
 | 
			
		||||
	logio->control_flags =
 | 
			
		||||
	    cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO);
 | 
			
		||||
	if (!sp->fcport->tgt_session ||
 | 
			
		||||
	if (!sp->fcport->se_sess ||
 | 
			
		||||
	    !sp->fcport->keep_nport_handle)
 | 
			
		||||
		logio->control_flags |= cpu_to_le16(LCF_FREE_NPORT);
 | 
			
		||||
	logio->nport_handle = cpu_to_le16(sp->fcport->loop_id);
 | 
			
		||||
| 
						 | 
				
			
			@ -3079,19 +3079,69 @@ qla24xx_abort_iocb(srb_t *sp, struct abort_entry_24xx *abt_iocb)
 | 
			
		|||
	wmb();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
qla2x00_mb_iocb(srb_t *sp, struct mbx_24xx_entry *mbx)
 | 
			
		||||
{
 | 
			
		||||
	int i, sz;
 | 
			
		||||
 | 
			
		||||
	mbx->entry_type = MBX_IOCB_TYPE;
 | 
			
		||||
	mbx->handle = sp->handle;
 | 
			
		||||
	sz = min(ARRAY_SIZE(mbx->mb), ARRAY_SIZE(sp->u.iocb_cmd.u.mbx.out_mb));
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < sz; i++)
 | 
			
		||||
		mbx->mb[i] = cpu_to_le16(sp->u.iocb_cmd.u.mbx.out_mb[i]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
qla2x00_ctpthru_cmd_iocb(srb_t *sp, struct ct_entry_24xx *ct_pkt)
 | 
			
		||||
{
 | 
			
		||||
	sp->u.iocb_cmd.u.ctarg.iocb = ct_pkt;
 | 
			
		||||
	qla24xx_prep_ms_iocb(sp->vha, &sp->u.iocb_cmd.u.ctarg);
 | 
			
		||||
	ct_pkt->handle = sp->handle;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void qla2x00_send_notify_ack_iocb(srb_t *sp,
 | 
			
		||||
	struct nack_to_isp *nack)
 | 
			
		||||
{
 | 
			
		||||
	struct imm_ntfy_from_isp *ntfy = sp->u.iocb_cmd.u.nack.ntfy;
 | 
			
		||||
 | 
			
		||||
	nack->entry_type = NOTIFY_ACK_TYPE;
 | 
			
		||||
	nack->entry_count = 1;
 | 
			
		||||
	nack->ox_id = ntfy->ox_id;
 | 
			
		||||
 | 
			
		||||
	nack->u.isp24.handle = sp->handle;
 | 
			
		||||
	nack->u.isp24.nport_handle = ntfy->u.isp24.nport_handle;
 | 
			
		||||
	if (le16_to_cpu(ntfy->u.isp24.status) == IMM_NTFY_ELS) {
 | 
			
		||||
		nack->u.isp24.flags = ntfy->u.isp24.flags &
 | 
			
		||||
			cpu_to_le32(NOTIFY24XX_FLAGS_PUREX_IOCB);
 | 
			
		||||
	}
 | 
			
		||||
	nack->u.isp24.srr_rx_id = ntfy->u.isp24.srr_rx_id;
 | 
			
		||||
	nack->u.isp24.status = ntfy->u.isp24.status;
 | 
			
		||||
	nack->u.isp24.status_subcode = ntfy->u.isp24.status_subcode;
 | 
			
		||||
	nack->u.isp24.fw_handle = ntfy->u.isp24.fw_handle;
 | 
			
		||||
	nack->u.isp24.exchange_address = ntfy->u.isp24.exchange_address;
 | 
			
		||||
	nack->u.isp24.srr_rel_offs = ntfy->u.isp24.srr_rel_offs;
 | 
			
		||||
	nack->u.isp24.srr_ui = ntfy->u.isp24.srr_ui;
 | 
			
		||||
	nack->u.isp24.srr_flags = 0;
 | 
			
		||||
	nack->u.isp24.srr_reject_code = 0;
 | 
			
		||||
	nack->u.isp24.srr_reject_code_expl = 0;
 | 
			
		||||
	nack->u.isp24.vp_index = ntfy->u.isp24.vp_index;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
qla2x00_start_sp(srb_t *sp)
 | 
			
		||||
{
 | 
			
		||||
	int rval;
 | 
			
		||||
	struct qla_hw_data *ha = sp->fcport->vha->hw;
 | 
			
		||||
	scsi_qla_host_t *vha = (scsi_qla_host_t *)sp->vha;
 | 
			
		||||
	struct qla_hw_data *ha = vha->hw;
 | 
			
		||||
	void *pkt;
 | 
			
		||||
	unsigned long flags;
 | 
			
		||||
 | 
			
		||||
	rval = QLA_FUNCTION_FAILED;
 | 
			
		||||
	spin_lock_irqsave(&ha->hardware_lock, flags);
 | 
			
		||||
	pkt = qla2x00_alloc_iocbs(sp->fcport->vha, sp);
 | 
			
		||||
	pkt = qla2x00_alloc_iocbs(vha, sp);
 | 
			
		||||
	if (!pkt) {
 | 
			
		||||
		ql_log(ql_log_warn, sp->fcport->vha, 0x700c,
 | 
			
		||||
		ql_log(ql_log_warn, vha, 0x700c,
 | 
			
		||||
		    "qla2x00_alloc_iocbs failed.\n");
 | 
			
		||||
		goto done;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -3139,12 +3189,23 @@ qla2x00_start_sp(srb_t *sp)
 | 
			
		|||
	case SRB_ELS_DCMD:
 | 
			
		||||
		qla24xx_els_logo_iocb(sp, pkt);
 | 
			
		||||
		break;
 | 
			
		||||
	case SRB_CT_PTHRU_CMD:
 | 
			
		||||
		qla2x00_ctpthru_cmd_iocb(sp, pkt);
 | 
			
		||||
		break;
 | 
			
		||||
	case SRB_MB_IOCB:
 | 
			
		||||
		qla2x00_mb_iocb(sp, pkt);
 | 
			
		||||
		break;
 | 
			
		||||
	case SRB_NACK_PLOGI:
 | 
			
		||||
	case SRB_NACK_PRLI:
 | 
			
		||||
	case SRB_NACK_LOGO:
 | 
			
		||||
		qla2x00_send_notify_ack_iocb(sp, pkt);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	wmb();
 | 
			
		||||
	qla2x00_start_iocbs(sp->fcport->vha, ha->req_q_map[0]);
 | 
			
		||||
	qla2x00_start_iocbs(vha, ha->req_q_map[0]);
 | 
			
		||||
done:
 | 
			
		||||
	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 | 
			
		||||
	return rval;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -561,14 +561,50 @@ qla2x00_is_a_vp_did(scsi_qla_host_t *vha, uint32_t rscn_entry)
 | 
			
		|||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline fc_port_t *
 | 
			
		||||
fc_port_t *
 | 
			
		||||
qla2x00_find_fcport_by_loopid(scsi_qla_host_t *vha, uint16_t loop_id)
 | 
			
		||||
{
 | 
			
		||||
	fc_port_t *fcport;
 | 
			
		||||
	fc_port_t *f, *tf;
 | 
			
		||||
 | 
			
		||||
	list_for_each_entry(fcport, &vha->vp_fcports, list)
 | 
			
		||||
		if (fcport->loop_id == loop_id)
 | 
			
		||||
			return fcport;
 | 
			
		||||
	f = tf = NULL;
 | 
			
		||||
	list_for_each_entry_safe(f, tf, &vha->vp_fcports, list)
 | 
			
		||||
		if (f->loop_id == loop_id)
 | 
			
		||||
			return f;
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fc_port_t *
 | 
			
		||||
qla2x00_find_fcport_by_wwpn(scsi_qla_host_t *vha, u8 *wwpn, u8 incl_deleted)
 | 
			
		||||
{
 | 
			
		||||
	fc_port_t *f, *tf;
 | 
			
		||||
 | 
			
		||||
	f = tf = NULL;
 | 
			
		||||
	list_for_each_entry_safe(f, tf, &vha->vp_fcports, list) {
 | 
			
		||||
		if (memcmp(f->port_name, wwpn, WWN_SIZE) == 0) {
 | 
			
		||||
			if (incl_deleted)
 | 
			
		||||
				return f;
 | 
			
		||||
			else if (f->deleted == 0)
 | 
			
		||||
				return f;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fc_port_t *
 | 
			
		||||
qla2x00_find_fcport_by_nportid(scsi_qla_host_t *vha, port_id_t *id,
 | 
			
		||||
	u8 incl_deleted)
 | 
			
		||||
{
 | 
			
		||||
	fc_port_t *f, *tf;
 | 
			
		||||
 | 
			
		||||
	f = tf = NULL;
 | 
			
		||||
	list_for_each_entry_safe(f, tf, &vha->vp_fcports, list) {
 | 
			
		||||
		if (f->d_id.b24 == id->b24) {
 | 
			
		||||
			if (incl_deleted)
 | 
			
		||||
				return f;
 | 
			
		||||
			else if (f->deleted == 0)
 | 
			
		||||
				return f;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -934,7 +970,11 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
 | 
			
		|||
			ql_dbg(ql_dbg_async, vha, 0x508a,
 | 
			
		||||
			    "Marking port lost loopid=%04x portid=%06x.\n",
 | 
			
		||||
			    fcport->loop_id, fcport->d_id.b24);
 | 
			
		||||
			qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1);
 | 
			
		||||
			if (qla_ini_mode_enabled(vha)) {
 | 
			
		||||
				qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1);
 | 
			
		||||
				fcport->logout_on_delete = 0;
 | 
			
		||||
				qlt_schedule_sess_for_deletion_lock(fcport);
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
global_port_update:
 | 
			
		||||
| 
						 | 
				
			
			@ -1024,27 +1064,17 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
 | 
			
		|||
		if (qla2x00_is_a_vp_did(vha, rscn_entry))
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * Search for the rport related to this RSCN entry and mark it
 | 
			
		||||
		 * as lost.
 | 
			
		||||
		 */
 | 
			
		||||
		list_for_each_entry(fcport, &vha->vp_fcports, list) {
 | 
			
		||||
			if (atomic_read(&fcport->state) != FCS_ONLINE)
 | 
			
		||||
				continue;
 | 
			
		||||
			if (fcport->d_id.b24 == rscn_entry) {
 | 
			
		||||
				qla2x00_mark_device_lost(vha, fcport, 0, 0);
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		atomic_set(&vha->loop_down_timer, 0);
 | 
			
		||||
		vha->flags.management_server_logged_in = 0;
 | 
			
		||||
		{
 | 
			
		||||
			struct event_arg ea;
 | 
			
		||||
 | 
			
		||||
		set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
 | 
			
		||||
		set_bit(RSCN_UPDATE, &vha->dpc_flags);
 | 
			
		||||
		qla2x00_post_aen_work(vha, FCH_EVT_RSCN, rscn_entry);
 | 
			
		||||
			memset(&ea, 0, sizeof(ea));
 | 
			
		||||
			ea.event = FCME_RSCN;
 | 
			
		||||
			ea.id.b24 = rscn_entry;
 | 
			
		||||
			qla2x00_fcport_event_handler(vha, &ea);
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	/* case MBA_RIO_RESPONSE: */
 | 
			
		||||
	case MBA_ZIO_RESPONSE:
 | 
			
		||||
		ql_dbg(ql_dbg_async, vha, 0x5015,
 | 
			
		||||
| 
						 | 
				
			
			@ -1235,7 +1265,8 @@ qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func,
 | 
			
		|||
	index = LSW(pkt->handle);
 | 
			
		||||
	if (index >= req->num_outstanding_cmds) {
 | 
			
		||||
		ql_log(ql_log_warn, vha, 0x5031,
 | 
			
		||||
		    "Invalid command index (%x).\n", index);
 | 
			
		||||
			   "Invalid command index (%x) type %8ph.\n",
 | 
			
		||||
			   index, iocb);
 | 
			
		||||
		if (IS_P3P_TYPE(ha))
 | 
			
		||||
			set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
 | 
			
		||||
		else
 | 
			
		||||
| 
						 | 
				
			
			@ -1346,6 +1377,49 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
 | 
			
		|||
	sp->done(vha, sp, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
qla24xx_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
 | 
			
		||||
    struct mbx_24xx_entry *pkt)
 | 
			
		||||
{
 | 
			
		||||
	const char func[] = "MBX-IOCB2";
 | 
			
		||||
	srb_t *sp;
 | 
			
		||||
	struct srb_iocb *si;
 | 
			
		||||
	u16 sz, i;
 | 
			
		||||
	int res;
 | 
			
		||||
 | 
			
		||||
	sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
 | 
			
		||||
	if (!sp)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	si = &sp->u.iocb_cmd;
 | 
			
		||||
	sz = min(ARRAY_SIZE(pkt->mb), ARRAY_SIZE(sp->u.iocb_cmd.u.mbx.in_mb));
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < sz; i++)
 | 
			
		||||
		si->u.mbx.in_mb[i] = le16_to_cpu(pkt->mb[i]);
 | 
			
		||||
 | 
			
		||||
	res = (si->u.mbx.in_mb[0] & MBS_MASK);
 | 
			
		||||
 | 
			
		||||
	sp->done(vha, sp, res);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
qla24xxx_nack_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
 | 
			
		||||
    struct nack_to_isp *pkt)
 | 
			
		||||
{
 | 
			
		||||
	const char func[] = "nack";
 | 
			
		||||
	srb_t *sp;
 | 
			
		||||
	int res = 0;
 | 
			
		||||
 | 
			
		||||
	sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
 | 
			
		||||
	if (!sp)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (pkt->u.isp2x.status != cpu_to_le16(NOTIFY_ACK_SUCCESS))
 | 
			
		||||
		res = QLA_FUNCTION_FAILED;
 | 
			
		||||
 | 
			
		||||
	sp->done(vha, sp, res);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
 | 
			
		||||
    sts_entry_t *pkt, int iocb_type)
 | 
			
		||||
| 
						 | 
				
			
			@ -1356,50 +1430,63 @@ qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
 | 
			
		|||
	struct bsg_job *bsg_job;
 | 
			
		||||
	struct fc_bsg_reply *bsg_reply;
 | 
			
		||||
	uint16_t comp_status;
 | 
			
		||||
	int res;
 | 
			
		||||
	int res = 0;
 | 
			
		||||
 | 
			
		||||
	sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
 | 
			
		||||
	if (!sp)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	bsg_job = sp->u.bsg_job;
 | 
			
		||||
	bsg_reply = bsg_job->reply;
 | 
			
		||||
	switch (sp->type) {
 | 
			
		||||
	case SRB_CT_CMD:
 | 
			
		||||
	    bsg_job = sp->u.bsg_job;
 | 
			
		||||
	    bsg_reply = bsg_job->reply;
 | 
			
		||||
 | 
			
		||||
	type = "ct pass-through";
 | 
			
		||||
	    type = "ct pass-through";
 | 
			
		||||
 | 
			
		||||
	comp_status = le16_to_cpu(pkt->comp_status);
 | 
			
		||||
	    comp_status = le16_to_cpu(pkt->comp_status);
 | 
			
		||||
 | 
			
		||||
	/* return FC_CTELS_STATUS_OK and leave the decoding of the ELS/CT
 | 
			
		||||
	 * fc payload  to the caller
 | 
			
		||||
	 */
 | 
			
		||||
	bsg_reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
 | 
			
		||||
	bsg_job->reply_len = sizeof(struct fc_bsg_reply);
 | 
			
		||||
	    /*
 | 
			
		||||
	     * return FC_CTELS_STATUS_OK and leave the decoding of the ELS/CT
 | 
			
		||||
	     * fc payload  to the caller
 | 
			
		||||
	     */
 | 
			
		||||
	    bsg_reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
 | 
			
		||||
	    bsg_job->reply_len = sizeof(struct fc_bsg_reply);
 | 
			
		||||
 | 
			
		||||
	if (comp_status != CS_COMPLETE) {
 | 
			
		||||
		if (comp_status == CS_DATA_UNDERRUN) {
 | 
			
		||||
			res = DID_OK << 16;
 | 
			
		||||
			bsg_reply->reply_payload_rcv_len =
 | 
			
		||||
			    le16_to_cpu(((sts_entry_t *)pkt)->rsp_info_len);
 | 
			
		||||
	    if (comp_status != CS_COMPLETE) {
 | 
			
		||||
		    if (comp_status == CS_DATA_UNDERRUN) {
 | 
			
		||||
			    res = DID_OK << 16;
 | 
			
		||||
			    bsg_reply->reply_payload_rcv_len =
 | 
			
		||||
				le16_to_cpu(((sts_entry_t *)pkt)->rsp_info_len);
 | 
			
		||||
 | 
			
		||||
			ql_log(ql_log_warn, vha, 0x5048,
 | 
			
		||||
			    "CT pass-through-%s error "
 | 
			
		||||
			    "comp_status-status=0x%x total_byte = 0x%x.\n",
 | 
			
		||||
			    type, comp_status,
 | 
			
		||||
			    bsg_reply->reply_payload_rcv_len);
 | 
			
		||||
		} else {
 | 
			
		||||
			ql_log(ql_log_warn, vha, 0x5049,
 | 
			
		||||
			    "CT pass-through-%s error "
 | 
			
		||||
			    "comp_status-status=0x%x.\n", type, comp_status);
 | 
			
		||||
			res = DID_ERROR << 16;
 | 
			
		||||
			bsg_reply->reply_payload_rcv_len = 0;
 | 
			
		||||
		}
 | 
			
		||||
		ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5035,
 | 
			
		||||
		    (uint8_t *)pkt, sizeof(*pkt));
 | 
			
		||||
	} else {
 | 
			
		||||
		res = DID_OK << 16;
 | 
			
		||||
		bsg_reply->reply_payload_rcv_len =
 | 
			
		||||
		    bsg_job->reply_payload.payload_len;
 | 
			
		||||
		bsg_job->reply_len = 0;
 | 
			
		||||
			    ql_log(ql_log_warn, vha, 0x5048,
 | 
			
		||||
				"CT pass-through-%s error comp_status=0x%x total_byte=0x%x.\n",
 | 
			
		||||
				type, comp_status,
 | 
			
		||||
				bsg_reply->reply_payload_rcv_len);
 | 
			
		||||
		    } else {
 | 
			
		||||
			    ql_log(ql_log_warn, vha, 0x5049,
 | 
			
		||||
				"CT pass-through-%s error comp_status=0x%x.\n",
 | 
			
		||||
				type, comp_status);
 | 
			
		||||
			    res = DID_ERROR << 16;
 | 
			
		||||
			    bsg_reply->reply_payload_rcv_len = 0;
 | 
			
		||||
		    }
 | 
			
		||||
		    ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5035,
 | 
			
		||||
			(uint8_t *)pkt, sizeof(*pkt));
 | 
			
		||||
	    } else {
 | 
			
		||||
		    res = DID_OK << 16;
 | 
			
		||||
		    bsg_reply->reply_payload_rcv_len =
 | 
			
		||||
			bsg_job->reply_payload.payload_len;
 | 
			
		||||
		    bsg_job->reply_len = 0;
 | 
			
		||||
	    }
 | 
			
		||||
	    break;
 | 
			
		||||
	case SRB_CT_PTHRU_CMD:
 | 
			
		||||
	    /*
 | 
			
		||||
	     * borrowing sts_entry_24xx.comp_status.
 | 
			
		||||
	     * same location as ct_entry_24xx.comp_status
 | 
			
		||||
	     */
 | 
			
		||||
	     res = qla2x00_chk_ms_status(vha, (ms_iocb_entry_t *)pkt,
 | 
			
		||||
		 (struct ct_sns_rsp *)sp->u.iocb_cmd.u.ctarg.rsp,
 | 
			
		||||
		 sp->name);
 | 
			
		||||
	     break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sp->done(vha, sp, res);
 | 
			
		||||
| 
						 | 
				
			
			@ -1440,6 +1527,15 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
 | 
			
		|||
		    "Completing %s: (%p) type=%d.\n", type, sp, sp->type);
 | 
			
		||||
		sp->done(vha, sp, 0);
 | 
			
		||||
		return;
 | 
			
		||||
	case SRB_CT_PTHRU_CMD:
 | 
			
		||||
		/* borrowing sts_entry_24xx.comp_status.
 | 
			
		||||
		   same location as ct_entry_24xx.comp_status
 | 
			
		||||
		 */
 | 
			
		||||
		res = qla2x00_chk_ms_status(vha, (ms_iocb_entry_t *)pkt,
 | 
			
		||||
			(struct ct_sns_rsp *)sp->u.iocb_cmd.u.ctarg.rsp,
 | 
			
		||||
			sp->name);
 | 
			
		||||
		sp->done(vha, sp, res);
 | 
			
		||||
		return;
 | 
			
		||||
	default:
 | 
			
		||||
		ql_dbg(ql_dbg_user, vha, 0x503e,
 | 
			
		||||
		    "Unrecognized SRB: (%p) type=%d.\n", sp, sp->type);
 | 
			
		||||
| 
						 | 
				
			
			@ -1566,6 +1662,8 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
 | 
			
		|||
 | 
			
		||||
	iop[0] = le32_to_cpu(logio->io_parameter[0]);
 | 
			
		||||
	iop[1] = le32_to_cpu(logio->io_parameter[1]);
 | 
			
		||||
	lio->u.logio.iop[0] = iop[0];
 | 
			
		||||
	lio->u.logio.iop[1] = iop[1];
 | 
			
		||||
	switch (iop[0]) {
 | 
			
		||||
	case LSC_SCODE_PORTID_USED:
 | 
			
		||||
		data[0] = MBS_PORT_ID_USED;
 | 
			
		||||
| 
						 | 
				
			
			@ -2074,6 +2172,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
 | 
			
		|||
	int res = 0;
 | 
			
		||||
	uint16_t state_flags = 0;
 | 
			
		||||
	uint16_t retry_delay = 0;
 | 
			
		||||
	uint8_t no_logout = 0;
 | 
			
		||||
 | 
			
		||||
	sts = (sts_entry_t *) pkt;
 | 
			
		||||
	sts24 = (struct sts_entry_24xx *) pkt;
 | 
			
		||||
| 
						 | 
				
			
			@ -2334,6 +2433,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
 | 
			
		|||
		break;
 | 
			
		||||
 | 
			
		||||
	case CS_PORT_LOGGED_OUT:
 | 
			
		||||
		no_logout = 1;
 | 
			
		||||
	case CS_PORT_CONFIG_CHG:
 | 
			
		||||
	case CS_PORT_BUSY:
 | 
			
		||||
	case CS_INCOMPLETE:
 | 
			
		||||
| 
						 | 
				
			
			@ -2356,14 +2456,21 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
 | 
			
		|||
				break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ql_dbg(ql_dbg_io, fcport->vha, 0x3021,
 | 
			
		||||
		    "Port to be marked lost on fcport=%02x%02x%02x, current "
 | 
			
		||||
		    "port state= %s.\n", fcport->d_id.b.domain,
 | 
			
		||||
		    fcport->d_id.b.area, fcport->d_id.b.al_pa,
 | 
			
		||||
		    port_state_str[atomic_read(&fcport->state)]);
 | 
			
		||||
		if (atomic_read(&fcport->state) == FCS_ONLINE) {
 | 
			
		||||
			ql_dbg(ql_dbg_disc, fcport->vha, 0x3021,
 | 
			
		||||
				"Port to be marked lost on fcport=%02x%02x%02x, current "
 | 
			
		||||
				"port state= %s comp_status %x.\n", fcport->d_id.b.domain,
 | 
			
		||||
				fcport->d_id.b.area, fcport->d_id.b.al_pa,
 | 
			
		||||
				port_state_str[atomic_read(&fcport->state)],
 | 
			
		||||
				comp_status);
 | 
			
		||||
 | 
			
		||||
			if (no_logout)
 | 
			
		||||
				fcport->logout_on_delete = 0;
 | 
			
		||||
 | 
			
		||||
		if (atomic_read(&fcport->state) == FCS_ONLINE)
 | 
			
		||||
			qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1);
 | 
			
		||||
			qlt_schedule_sess_for_deletion_lock(fcport);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case CS_ABORTED:
 | 
			
		||||
| 
						 | 
				
			
			@ -2627,10 +2734,16 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
 | 
			
		|||
			}
 | 
			
		||||
		case ABTS_RESP_24XX:
 | 
			
		||||
		case CTIO_TYPE7:
 | 
			
		||||
		case NOTIFY_ACK_TYPE:
 | 
			
		||||
		case CTIO_CRC2:
 | 
			
		||||
			qlt_response_pkt_all_vps(vha, (response_t *)pkt);
 | 
			
		||||
			break;
 | 
			
		||||
		case NOTIFY_ACK_TYPE:
 | 
			
		||||
			if (pkt->handle == QLA_TGT_SKIP_HANDLE)
 | 
			
		||||
				qlt_response_pkt_all_vps(vha, (response_t *)pkt);
 | 
			
		||||
			else
 | 
			
		||||
				qla24xxx_nack_iocb_entry(vha, rsp->req,
 | 
			
		||||
					(struct nack_to_isp *)pkt);
 | 
			
		||||
			break;
 | 
			
		||||
		case MARKER_TYPE:
 | 
			
		||||
			/* Do nothing in this case, this check is to prevent it
 | 
			
		||||
			 * from falling into default case
 | 
			
		||||
| 
						 | 
				
			
			@ -2640,6 +2753,10 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
 | 
			
		|||
			qla24xx_abort_iocb_entry(vha, rsp->req,
 | 
			
		||||
			    (struct abort_entry_24xx *)pkt);
 | 
			
		||||
			break;
 | 
			
		||||
		case MBX_IOCB_TYPE:
 | 
			
		||||
			qla24xx_mbx_iocb_entry(vha, rsp->req,
 | 
			
		||||
			    (struct mbx_24xx_entry *)pkt);
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			/* Type Not Supported. */
 | 
			
		||||
			ql_dbg(ql_dbg_async, vha, 0x5042,
 | 
			
		||||
| 
						 | 
				
			
			@ -2656,8 +2773,9 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
 | 
			
		|||
	if (IS_P3P_TYPE(ha)) {
 | 
			
		||||
		struct device_reg_82xx __iomem *reg = &ha->iobase->isp82;
 | 
			
		||||
		WRT_REG_DWORD(®->rsp_q_out[0], rsp->ring_index);
 | 
			
		||||
	} else
 | 
			
		||||
	} else {
 | 
			
		||||
		WRT_REG_DWORD(rsp->rsp_q_out, rsp->ring_index);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1637,94 +1637,6 @@ qla2x00_init_firmware(scsi_qla_host_t *vha, uint16_t size)
 | 
			
		|||
	return rval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * qla2x00_get_node_name_list
 | 
			
		||||
 *      Issue get node name list mailbox command, kmalloc()
 | 
			
		||||
 *      and return the resulting list. Caller must kfree() it!
 | 
			
		||||
 *
 | 
			
		||||
 * Input:
 | 
			
		||||
 *      ha = adapter state pointer.
 | 
			
		||||
 *      out_data = resulting list
 | 
			
		||||
 *      out_len = length of the resulting list
 | 
			
		||||
 *
 | 
			
		||||
 * Returns:
 | 
			
		||||
 *      qla2x00 local function return status code.
 | 
			
		||||
 *
 | 
			
		||||
 * Context:
 | 
			
		||||
 *      Kernel context.
 | 
			
		||||
 */
 | 
			
		||||
int
 | 
			
		||||
qla2x00_get_node_name_list(scsi_qla_host_t *vha, void **out_data, int *out_len)
 | 
			
		||||
{
 | 
			
		||||
	struct qla_hw_data *ha = vha->hw;
 | 
			
		||||
	struct qla_port_24xx_data *list = NULL;
 | 
			
		||||
	void *pmap;
 | 
			
		||||
	mbx_cmd_t mc;
 | 
			
		||||
	dma_addr_t pmap_dma;
 | 
			
		||||
	ulong dma_size;
 | 
			
		||||
	int rval, left;
 | 
			
		||||
 | 
			
		||||
	left = 1;
 | 
			
		||||
	while (left > 0) {
 | 
			
		||||
		dma_size = left * sizeof(*list);
 | 
			
		||||
		pmap = dma_alloc_coherent(&ha->pdev->dev, dma_size,
 | 
			
		||||
					 &pmap_dma, GFP_KERNEL);
 | 
			
		||||
		if (!pmap) {
 | 
			
		||||
			ql_log(ql_log_warn, vha, 0x113f,
 | 
			
		||||
			    "%s(%ld): DMA Alloc failed of %ld\n",
 | 
			
		||||
			    __func__, vha->host_no, dma_size);
 | 
			
		||||
			rval = QLA_MEMORY_ALLOC_FAILED;
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		mc.mb[0] = MBC_PORT_NODE_NAME_LIST;
 | 
			
		||||
		mc.mb[1] = BIT_1 | BIT_3;
 | 
			
		||||
		mc.mb[2] = MSW(pmap_dma);
 | 
			
		||||
		mc.mb[3] = LSW(pmap_dma);
 | 
			
		||||
		mc.mb[6] = MSW(MSD(pmap_dma));
 | 
			
		||||
		mc.mb[7] = LSW(MSD(pmap_dma));
 | 
			
		||||
		mc.mb[8] = dma_size;
 | 
			
		||||
		mc.out_mb = MBX_0|MBX_1|MBX_2|MBX_3|MBX_6|MBX_7|MBX_8;
 | 
			
		||||
		mc.in_mb = MBX_0|MBX_1;
 | 
			
		||||
		mc.tov = 30;
 | 
			
		||||
		mc.flags = MBX_DMA_IN;
 | 
			
		||||
 | 
			
		||||
		rval = qla2x00_mailbox_command(vha, &mc);
 | 
			
		||||
		if (rval != QLA_SUCCESS) {
 | 
			
		||||
			if ((mc.mb[0] == MBS_COMMAND_ERROR) &&
 | 
			
		||||
			    (mc.mb[1] == 0xA)) {
 | 
			
		||||
				left += le16_to_cpu(mc.mb[2]) /
 | 
			
		||||
				    sizeof(struct qla_port_24xx_data);
 | 
			
		||||
				goto restart;
 | 
			
		||||
			}
 | 
			
		||||
			goto out_free;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		left = 0;
 | 
			
		||||
 | 
			
		||||
		list = kmemdup(pmap, dma_size, GFP_KERNEL);
 | 
			
		||||
		if (!list) {
 | 
			
		||||
			ql_log(ql_log_warn, vha, 0x1140,
 | 
			
		||||
			    "%s(%ld): failed to allocate node names list "
 | 
			
		||||
			    "structure.\n", __func__, vha->host_no);
 | 
			
		||||
			rval = QLA_MEMORY_ALLOC_FAILED;
 | 
			
		||||
			goto out_free;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
restart:
 | 
			
		||||
		dma_free_coherent(&ha->pdev->dev, dma_size, pmap, pmap_dma);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*out_data = list;
 | 
			
		||||
	*out_len = dma_size;
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
	return rval;
 | 
			
		||||
 | 
			
		||||
out_free:
 | 
			
		||||
	dma_free_coherent(&ha->pdev->dev, dma_size, pmap, pmap_dma);
 | 
			
		||||
	return rval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * qla2x00_get_port_database
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1043,6 +1043,34 @@ qla2x00_wait_for_hba_online(scsi_qla_host_t *vha)
 | 
			
		|||
	return (return_status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int test_fcport_count(scsi_qla_host_t *vha)
 | 
			
		||||
{
 | 
			
		||||
	struct qla_hw_data *ha = vha->hw;
 | 
			
		||||
	unsigned long flags;
 | 
			
		||||
	int res;
 | 
			
		||||
 | 
			
		||||
	spin_lock_irqsave(&ha->tgt.sess_lock, flags);
 | 
			
		||||
	ql_dbg(ql_dbg_init, vha, 0xffff,
 | 
			
		||||
		"tgt %p, fcport_count=%d\n",
 | 
			
		||||
		vha, vha->fcport_count);
 | 
			
		||||
	res = (vha->fcport_count == 0);
 | 
			
		||||
	spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
 | 
			
		||||
 | 
			
		||||
	return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * qla2x00_wait_for_sess_deletion can only be called from remove_one.
 | 
			
		||||
 * it has dependency on UNLOADING flag to stop device discovery
 | 
			
		||||
 */
 | 
			
		||||
static void
 | 
			
		||||
qla2x00_wait_for_sess_deletion(scsi_qla_host_t *vha)
 | 
			
		||||
{
 | 
			
		||||
	qla2x00_mark_all_devices_lost(vha, 0);
 | 
			
		||||
 | 
			
		||||
	wait_event(vha->fcport_waitQ, test_fcport_count(vha));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * qla2x00_wait_for_hba_ready
 | 
			
		||||
 * Wait till the HBA is ready before doing driver unload
 | 
			
		||||
| 
						 | 
				
			
			@ -2904,6 +2932,18 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 | 
			
		|||
	if (ret)
 | 
			
		||||
		goto probe_init_failed;
 | 
			
		||||
 | 
			
		||||
	base_vha->gnl.size = (ha->max_loop_id + 1) *
 | 
			
		||||
		sizeof(struct get_name_list_extended);
 | 
			
		||||
	base_vha->gnl.l = dma_alloc_coherent(&ha->pdev->dev,
 | 
			
		||||
		base_vha->gnl.size, &base_vha->gnl.ldma, GFP_KERNEL);
 | 
			
		||||
	INIT_LIST_HEAD(&base_vha->gnl.fcports);
 | 
			
		||||
 | 
			
		||||
	if (base_vha->gnl.l == NULL) {
 | 
			
		||||
		ql_log(ql_log_fatal, base_vha, 0xffff,
 | 
			
		||||
			"Alloc failed for name list.\n");
 | 
			
		||||
		goto probe_init_failed;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Alloc arrays of request and response ring ptrs */
 | 
			
		||||
	if (!qla2x00_alloc_queues(ha, req, rsp)) {
 | 
			
		||||
		ql_log(ql_log_fatal, base_vha, 0x003d,
 | 
			
		||||
| 
						 | 
				
			
			@ -3123,7 +3163,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 | 
			
		|||
	ql_dbg(ql_dbg_init, base_vha, 0x00f2,
 | 
			
		||||
	    "Init done and hba is online.\n");
 | 
			
		||||
 | 
			
		||||
	if (qla_ini_mode_enabled(base_vha))
 | 
			
		||||
	if (qla_ini_mode_enabled(base_vha) ||
 | 
			
		||||
		qla_dual_mode_enabled(base_vha))
 | 
			
		||||
		scsi_scan_host(host);
 | 
			
		||||
	else
 | 
			
		||||
		ql_dbg(ql_dbg_init, base_vha, 0x0122,
 | 
			
		||||
| 
						 | 
				
			
			@ -3372,21 +3413,26 @@ qla2x00_remove_one(struct pci_dev *pdev)
 | 
			
		|||
	 * resources.
 | 
			
		||||
	 */
 | 
			
		||||
	if (!atomic_read(&pdev->enable_cnt)) {
 | 
			
		||||
		dma_free_coherent(&ha->pdev->dev, base_vha->gnl.size,
 | 
			
		||||
		    base_vha->gnl.l, base_vha->gnl.ldma);
 | 
			
		||||
 | 
			
		||||
		scsi_host_put(base_vha->host);
 | 
			
		||||
		kfree(ha);
 | 
			
		||||
		pci_set_drvdata(pdev, NULL);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	qla2x00_wait_for_hba_ready(base_vha);
 | 
			
		||||
 | 
			
		||||
	/* if UNLOAD flag is already set, then continue unload,
 | 
			
		||||
	/*
 | 
			
		||||
	 * if UNLOAD flag is already set, then continue unload,
 | 
			
		||||
	 * where it was set first.
 | 
			
		||||
	 */
 | 
			
		||||
	if (test_bit(UNLOADING, &base_vha->dpc_flags))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	set_bit(UNLOADING, &base_vha->dpc_flags);
 | 
			
		||||
	dma_free_coherent(&ha->pdev->dev,
 | 
			
		||||
		base_vha->gnl.size, base_vha->gnl.l, base_vha->gnl.ldma);
 | 
			
		||||
 | 
			
		||||
	if (IS_QLAFX00(ha))
 | 
			
		||||
		qlafx00_driver_shutdown(base_vha, 20);
 | 
			
		||||
| 
						 | 
				
			
			@ -3535,10 +3581,14 @@ qla2x00_schedule_rport_del(struct scsi_qla_host *vha, fc_port_t *fcport,
 | 
			
		|||
		qla2xxx_wake_dpc(base_vha);
 | 
			
		||||
	} else {
 | 
			
		||||
		int now;
 | 
			
		||||
		if (rport)
 | 
			
		||||
		if (rport) {
 | 
			
		||||
			ql_dbg(ql_dbg_disc, fcport->vha, 0xffff,
 | 
			
		||||
				"%s %8phN. rport %p roles %x \n",
 | 
			
		||||
				__func__, fcport->port_name, rport,
 | 
			
		||||
				rport->roles);
 | 
			
		||||
			fc_remote_port_delete(rport);
 | 
			
		||||
		}
 | 
			
		||||
		qlt_do_generation_tick(vha, &now);
 | 
			
		||||
		qlt_fc_port_deleted(vha, fcport, now);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3581,7 +3631,7 @@ void qla2x00_mark_device_lost(scsi_qla_host_t *vha, fc_port_t *fcport,
 | 
			
		|||
		fcport->login_retry = vha->hw->login_retry_count;
 | 
			
		||||
 | 
			
		||||
		ql_dbg(ql_dbg_disc, vha, 0x2067,
 | 
			
		||||
		    "Port login retry %8phN, id = 0x%04x retry cnt=%d.\n",
 | 
			
		||||
		    "Port login retry %8phN, lid 0x%04x retry cnt=%d.\n",
 | 
			
		||||
		    fcport->port_name, fcport->loop_id, fcport->login_retry);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -3604,7 +3654,13 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *vha, int defer)
 | 
			
		|||
{
 | 
			
		||||
	fc_port_t *fcport;
 | 
			
		||||
 | 
			
		||||
	ql_dbg(ql_dbg_disc, vha, 0xffff,
 | 
			
		||||
		   "Mark all dev lost\n");
 | 
			
		||||
 | 
			
		||||
	list_for_each_entry(fcport, &vha->vp_fcports, list) {
 | 
			
		||||
		fcport->scan_state = 0;
 | 
			
		||||
		qlt_schedule_sess_for_deletion_lock(fcport);
 | 
			
		||||
 | 
			
		||||
		if (vha->vp_idx != 0 && vha->vp_idx != fcport->vha->vp_idx)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -4219,6 +4275,7 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
 | 
			
		|||
 | 
			
		||||
	spin_lock_init(&vha->work_lock);
 | 
			
		||||
	spin_lock_init(&vha->cmd_list_lock);
 | 
			
		||||
	init_waitqueue_head(&vha->fcport_waitQ);
 | 
			
		||||
 | 
			
		||||
	sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no);
 | 
			
		||||
	ql_dbg(ql_dbg_init, vha, 0x0041,
 | 
			
		||||
| 
						 | 
				
			
			@ -4232,7 +4289,7 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
 | 
			
		|||
	return vha;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct qla_work_evt *
 | 
			
		||||
struct qla_work_evt *
 | 
			
		||||
qla2x00_alloc_work(struct scsi_qla_host *vha, enum qla_work_type type)
 | 
			
		||||
{
 | 
			
		||||
	struct qla_work_evt *e;
 | 
			
		||||
| 
						 | 
				
			
			@ -4254,7 +4311,7 @@ qla2x00_alloc_work(struct scsi_qla_host *vha, enum qla_work_type type)
 | 
			
		|||
	return e;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
int
 | 
			
		||||
qla2x00_post_work(struct scsi_qla_host *vha, struct qla_work_evt *e)
 | 
			
		||||
{
 | 
			
		||||
	unsigned long flags;
 | 
			
		||||
| 
						 | 
				
			
			@ -4315,7 +4372,6 @@ int qla2x00_post_async_##name##_work(		\
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
qla2x00_post_async_work(login, QLA_EVT_ASYNC_LOGIN);
 | 
			
		||||
qla2x00_post_async_work(login_done, QLA_EVT_ASYNC_LOGIN_DONE);
 | 
			
		||||
qla2x00_post_async_work(logout, QLA_EVT_ASYNC_LOGOUT);
 | 
			
		||||
qla2x00_post_async_work(logout_done, QLA_EVT_ASYNC_LOGOUT_DONE);
 | 
			
		||||
qla2x00_post_async_work(adisc, QLA_EVT_ASYNC_ADISC);
 | 
			
		||||
| 
						 | 
				
			
			@ -4368,6 +4424,67 @@ qlafx00_post_aenfx_work(struct scsi_qla_host *vha,  uint32_t evtcode,
 | 
			
		|||
	return qla2x00_post_work(vha, e);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int qla24xx_post_upd_fcport_work(struct scsi_qla_host *vha, fc_port_t *fcport)
 | 
			
		||||
{
 | 
			
		||||
	struct qla_work_evt *e;
 | 
			
		||||
 | 
			
		||||
	e = qla2x00_alloc_work(vha, QLA_EVT_UPD_FCPORT);
 | 
			
		||||
	if (!e)
 | 
			
		||||
		return QLA_FUNCTION_FAILED;
 | 
			
		||||
 | 
			
		||||
	e->u.fcport.fcport = fcport;
 | 
			
		||||
	return qla2x00_post_work(vha, e);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
 | 
			
		||||
{
 | 
			
		||||
	unsigned long flags;
 | 
			
		||||
	fc_port_t *fcport =  NULL;
 | 
			
		||||
	struct qlt_plogi_ack_t *pla =
 | 
			
		||||
	    (struct qlt_plogi_ack_t *)e->u.new_sess.pla;
 | 
			
		||||
 | 
			
		||||
	spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
 | 
			
		||||
	fcport = qla2x00_find_fcport_by_wwpn(vha, e->u.new_sess.port_name, 1);
 | 
			
		||||
	if (fcport) {
 | 
			
		||||
		fcport->d_id = e->u.new_sess.id;
 | 
			
		||||
		if (pla) {
 | 
			
		||||
			fcport->fw_login_state = DSC_LS_PLOGI_PEND;
 | 
			
		||||
			qlt_plogi_ack_link(vha, pla, fcport, QLT_PLOGI_LINK_SAME_WWN);
 | 
			
		||||
			/* we took an extra ref_count to prevent PLOGI ACK when
 | 
			
		||||
			 * fcport/sess has not been created.
 | 
			
		||||
			 */
 | 
			
		||||
			pla->ref_count--;
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
 | 
			
		||||
		if (fcport) {
 | 
			
		||||
			fcport->d_id = e->u.new_sess.id;
 | 
			
		||||
			fcport->scan_state = QLA_FCPORT_FOUND;
 | 
			
		||||
			fcport->flags |= FCF_FABRIC_DEVICE;
 | 
			
		||||
			fcport->fw_login_state = DSC_LS_PLOGI_PEND;
 | 
			
		||||
 | 
			
		||||
			memcpy(fcport->port_name, e->u.new_sess.port_name,
 | 
			
		||||
			    WWN_SIZE);
 | 
			
		||||
			list_add_tail(&fcport->list, &vha->vp_fcports);
 | 
			
		||||
 | 
			
		||||
			if (pla) {
 | 
			
		||||
				qlt_plogi_ack_link(vha, pla, fcport,
 | 
			
		||||
				    QLT_PLOGI_LINK_SAME_WWN);
 | 
			
		||||
				pla->ref_count--;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
 | 
			
		||||
 | 
			
		||||
	if (fcport) {
 | 
			
		||||
		if (pla)
 | 
			
		||||
			qlt_plogi_ack_unref(vha, pla);
 | 
			
		||||
		else
 | 
			
		||||
			qla24xx_async_gnl(vha, fcport);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
qla2x00_do_work(struct scsi_qla_host *vha)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -4394,10 +4511,6 @@ qla2x00_do_work(struct scsi_qla_host *vha)
 | 
			
		|||
			qla2x00_async_login(vha, e->u.logio.fcport,
 | 
			
		||||
			    e->u.logio.data);
 | 
			
		||||
			break;
 | 
			
		||||
		case QLA_EVT_ASYNC_LOGIN_DONE:
 | 
			
		||||
			qla2x00_async_login_done(vha, e->u.logio.fcport,
 | 
			
		||||
			    e->u.logio.data);
 | 
			
		||||
			break;
 | 
			
		||||
		case QLA_EVT_ASYNC_LOGOUT:
 | 
			
		||||
			qla2x00_async_logout(vha, e->u.logio.fcport);
 | 
			
		||||
			break;
 | 
			
		||||
| 
						 | 
				
			
			@ -4419,6 +4532,34 @@ qla2x00_do_work(struct scsi_qla_host *vha)
 | 
			
		|||
		case QLA_EVT_AENFX:
 | 
			
		||||
			qlafx00_process_aen(vha, e);
 | 
			
		||||
			break;
 | 
			
		||||
		case QLA_EVT_GIDPN:
 | 
			
		||||
			qla24xx_async_gidpn(vha, e->u.fcport.fcport);
 | 
			
		||||
			break;
 | 
			
		||||
		case QLA_EVT_GPNID:
 | 
			
		||||
			qla24xx_async_gpnid(vha, &e->u.gpnid.id);
 | 
			
		||||
			break;
 | 
			
		||||
		case QLA_EVT_GPNID_DONE:
 | 
			
		||||
			qla24xx_async_gpnid_done(vha, e->u.iosb.sp);
 | 
			
		||||
			break;
 | 
			
		||||
		case QLA_EVT_NEW_SESS:
 | 
			
		||||
			qla24xx_create_new_sess(vha, e);
 | 
			
		||||
			break;
 | 
			
		||||
		case QLA_EVT_GPDB:
 | 
			
		||||
			qla24xx_async_gpdb(vha, e->u.fcport.fcport,
 | 
			
		||||
			    e->u.fcport.opt);
 | 
			
		||||
			break;
 | 
			
		||||
		case QLA_EVT_GPSC:
 | 
			
		||||
			qla24xx_async_gpsc(vha, e->u.fcport.fcport);
 | 
			
		||||
			break;
 | 
			
		||||
		case QLA_EVT_UPD_FCPORT:
 | 
			
		||||
			qla2x00_update_fcport(vha, e->u.fcport.fcport);
 | 
			
		||||
			break;
 | 
			
		||||
		case QLA_EVT_GNL:
 | 
			
		||||
			qla24xx_async_gnl(vha, e->u.fcport.fcport);
 | 
			
		||||
			break;
 | 
			
		||||
		case QLA_EVT_NACK:
 | 
			
		||||
			qla24xx_do_nack_work(vha, e);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		if (e->flags & QLA_EVT_FLAG_FREE)
 | 
			
		||||
			kfree(e);
 | 
			
		||||
| 
						 | 
				
			
			@ -4435,9 +4576,7 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
 | 
			
		|||
{
 | 
			
		||||
	fc_port_t       *fcport;
 | 
			
		||||
	int status;
 | 
			
		||||
	uint16_t        next_loopid = 0;
 | 
			
		||||
	struct qla_hw_data *ha = vha->hw;
 | 
			
		||||
	uint16_t data[2];
 | 
			
		||||
	struct event_arg ea;
 | 
			
		||||
 | 
			
		||||
	list_for_each_entry(fcport, &vha->vp_fcports, list) {
 | 
			
		||||
	/*
 | 
			
		||||
| 
						 | 
				
			
			@ -4448,77 +4587,38 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
 | 
			
		|||
		    fcport->login_retry && !(fcport->flags & FCF_ASYNC_SENT)) {
 | 
			
		||||
			fcport->login_retry--;
 | 
			
		||||
			if (fcport->flags & FCF_FABRIC_DEVICE) {
 | 
			
		||||
				if (fcport->flags & FCF_FCP2_DEVICE)
 | 
			
		||||
					ha->isp_ops->fabric_logout(vha,
 | 
			
		||||
							fcport->loop_id,
 | 
			
		||||
							fcport->d_id.b.domain,
 | 
			
		||||
							fcport->d_id.b.area,
 | 
			
		||||
							fcport->d_id.b.al_pa);
 | 
			
		||||
 | 
			
		||||
				if (fcport->loop_id == FC_NO_LOOP_ID) {
 | 
			
		||||
					fcport->loop_id = next_loopid =
 | 
			
		||||
					    ha->min_external_loopid;
 | 
			
		||||
					status = qla2x00_find_new_loop_id(
 | 
			
		||||
					    vha, fcport);
 | 
			
		||||
					if (status != QLA_SUCCESS) {
 | 
			
		||||
						/* Ran out of IDs to use */
 | 
			
		||||
						break;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (IS_ALOGIO_CAPABLE(ha)) {
 | 
			
		||||
					fcport->flags |= FCF_ASYNC_SENT;
 | 
			
		||||
					data[0] = 0;
 | 
			
		||||
					data[1] = QLA_LOGIO_LOGIN_RETRIED;
 | 
			
		||||
					status = qla2x00_post_async_login_work(
 | 
			
		||||
					    vha, fcport, data);
 | 
			
		||||
					if (status == QLA_SUCCESS)
 | 
			
		||||
						continue;
 | 
			
		||||
					/* Attempt a retry. */
 | 
			
		||||
					status = 1;
 | 
			
		||||
				} else {
 | 
			
		||||
					status = qla2x00_fabric_login(vha,
 | 
			
		||||
					    fcport, &next_loopid);
 | 
			
		||||
					if (status ==  QLA_SUCCESS) {
 | 
			
		||||
						int status2;
 | 
			
		||||
						uint8_t opts;
 | 
			
		||||
 | 
			
		||||
						opts = 0;
 | 
			
		||||
						if (fcport->flags &
 | 
			
		||||
						    FCF_FCP2_DEVICE)
 | 
			
		||||
							opts |= BIT_1;
 | 
			
		||||
						status2 =
 | 
			
		||||
						    qla2x00_get_port_database(
 | 
			
		||||
							vha, fcport, opts);
 | 
			
		||||
						if (status2 != QLA_SUCCESS)
 | 
			
		||||
							status = 1;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			} else
 | 
			
		||||
				ql_dbg(ql_dbg_disc, fcport->vha, 0xffff,
 | 
			
		||||
				    "%s %8phC DS %d LS %d\n", __func__,
 | 
			
		||||
				    fcport->port_name, fcport->disc_state,
 | 
			
		||||
				    fcport->fw_login_state);
 | 
			
		||||
				memset(&ea, 0, sizeof(ea));
 | 
			
		||||
				ea.event = FCME_RELOGIN;
 | 
			
		||||
				ea.fcport = fcport;
 | 
			
		||||
				qla2x00_fcport_event_handler(vha, &ea);
 | 
			
		||||
			} else {
 | 
			
		||||
				status = qla2x00_local_device_login(vha,
 | 
			
		||||
								fcport);
 | 
			
		||||
				if (status == QLA_SUCCESS) {
 | 
			
		||||
					fcport->old_loop_id = fcport->loop_id;
 | 
			
		||||
					ql_dbg(ql_dbg_disc, vha, 0x2003,
 | 
			
		||||
					    "Port login OK: logged in ID 0x%x.\n",
 | 
			
		||||
					    fcport->loop_id);
 | 
			
		||||
					qla2x00_update_fcport(vha, fcport);
 | 
			
		||||
				} else if (status == 1) {
 | 
			
		||||
					set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
 | 
			
		||||
					/* retry the login again */
 | 
			
		||||
					ql_dbg(ql_dbg_disc, vha, 0x2007,
 | 
			
		||||
					    "Retrying %d login again loop_id 0x%x.\n",
 | 
			
		||||
					    fcport->login_retry,
 | 
			
		||||
					    fcport->loop_id);
 | 
			
		||||
				} else {
 | 
			
		||||
					fcport->login_retry = 0;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			if (status == QLA_SUCCESS) {
 | 
			
		||||
				fcport->old_loop_id = fcport->loop_id;
 | 
			
		||||
 | 
			
		||||
				ql_dbg(ql_dbg_disc, vha, 0x2003,
 | 
			
		||||
				    "Port login OK: logged in ID 0x%x.\n",
 | 
			
		||||
				    fcport->loop_id);
 | 
			
		||||
 | 
			
		||||
				qla2x00_update_fcport(vha, fcport);
 | 
			
		||||
 | 
			
		||||
			} else if (status == 1) {
 | 
			
		||||
				set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
 | 
			
		||||
				/* retry the login again */
 | 
			
		||||
				ql_dbg(ql_dbg_disc, vha, 0x2007,
 | 
			
		||||
				    "Retrying %d login again loop_id 0x%x.\n",
 | 
			
		||||
				    fcport->login_retry, fcport->loop_id);
 | 
			
		||||
			} else {
 | 
			
		||||
				fcport->login_retry = 0;
 | 
			
		||||
				if (fcport->login_retry == 0 &&
 | 
			
		||||
				    status != QLA_SUCCESS)
 | 
			
		||||
					qla2x00_clear_loop_id(fcport);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (fcport->login_retry == 0 && status != QLA_SUCCESS)
 | 
			
		||||
				qla2x00_clear_loop_id(fcport);
 | 
			
		||||
		}
 | 
			
		||||
		if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
 | 
			
		||||
			break;
 | 
			
		||||
| 
						 | 
				
			
			@ -5182,7 +5282,8 @@ qla2x00_disable_board_on_pci_error(struct work_struct *work)
 | 
			
		|||
	struct pci_dev *pdev = ha->pdev;
 | 
			
		||||
	scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
 | 
			
		||||
 | 
			
		||||
	/* if UNLOAD flag is already set, then continue unload,
 | 
			
		||||
	/*
 | 
			
		||||
	 * if UNLOAD flag is already set, then continue unload,
 | 
			
		||||
	 * where it was set first.
 | 
			
		||||
	 */
 | 
			
		||||
	if (test_bit(UNLOADING, &base_vha->dpc_flags))
 | 
			
		||||
| 
						 | 
				
			
			@ -5191,6 +5292,8 @@ qla2x00_disable_board_on_pci_error(struct work_struct *work)
 | 
			
		|||
	ql_log(ql_log_warn, base_vha, 0x015b,
 | 
			
		||||
	    "Disabling adapter.\n");
 | 
			
		||||
 | 
			
		||||
	qla2x00_wait_for_sess_deletion(base_vha);
 | 
			
		||||
 | 
			
		||||
	set_bit(UNLOADING, &base_vha->dpc_flags);
 | 
			
		||||
 | 
			
		||||
	qla2x00_delete_all_vps(ha, base_vha);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
				
			
			@ -799,7 +799,6 @@ struct qla_tgt {
 | 
			
		|||
 | 
			
		||||
	/* Protected by hardware_lock */
 | 
			
		||||
	struct list_head del_sess_list;
 | 
			
		||||
	struct delayed_work sess_del_work;
 | 
			
		||||
 | 
			
		||||
	spinlock_t sess_work_lock;
 | 
			
		||||
	struct list_head sess_works_list;
 | 
			
		||||
| 
						 | 
				
			
			@ -823,13 +822,6 @@ struct qla_tgt_sess_op {
 | 
			
		|||
	bool aborted;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum qla_sess_deletion {
 | 
			
		||||
	QLA_SESS_DELETION_NONE		= 0,
 | 
			
		||||
	QLA_SESS_DELETION_PENDING	= 1, /* hopefully we can get rid of
 | 
			
		||||
					      * this one */
 | 
			
		||||
	QLA_SESS_DELETION_IN_PROGRESS	= 2,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum trace_flags {
 | 
			
		||||
	TRC_NEW_CMD = BIT_0,
 | 
			
		||||
	TRC_DO_WORK = BIT_1,
 | 
			
		||||
| 
						 | 
				
			
			@ -987,12 +979,17 @@ extern int ql2x_ini_mode;
 | 
			
		|||
 | 
			
		||||
static inline bool qla_tgt_mode_enabled(struct scsi_qla_host *ha)
 | 
			
		||||
{
 | 
			
		||||
	return ha->host->active_mode & MODE_TARGET;
 | 
			
		||||
	return ha->host->active_mode == MODE_TARGET;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline bool qla_ini_mode_enabled(struct scsi_qla_host *ha)
 | 
			
		||||
{
 | 
			
		||||
	return ha->host->active_mode & MODE_INITIATOR;
 | 
			
		||||
	return ha->host->active_mode == MODE_INITIATOR;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline bool qla_dual_mode_enabled(struct scsi_qla_host *ha)
 | 
			
		||||
{
 | 
			
		||||
	return (ha->host->active_mode == MODE_DUAL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void qla_reverse_ini_mode(struct scsi_qla_host *ha)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue