mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-03 17:40:04 +00: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);
|
clear_bit(vha->vp_idx, ha->vp_idx_map);
|
||||||
mutex_unlock(&ha->vport_lock);
|
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 (vha->qpair->vp_idx == vha->vp_idx) {
|
||||||
if (qla2xxx_delete_qpair(vha, vha->qpair) != QLA_SUCCESS)
|
if (qla2xxx_delete_qpair(vha, vha->qpair) != QLA_SUCCESS)
|
||||||
ql_log(ql_log_warn, vha, 0x7087,
|
ql_log(ql_log_warn, vha, 0x7087,
|
||||||
|
|
|
@ -55,6 +55,8 @@
|
||||||
|
|
||||||
#include "qla_settings.h"
|
#include "qla_settings.h"
|
||||||
|
|
||||||
|
#define MODE_DUAL (MODE_TARGET | MODE_INITIATOR)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Data bit definitions
|
* Data bit definitions
|
||||||
*/
|
*/
|
||||||
|
@ -251,6 +253,14 @@
|
||||||
|
|
||||||
#define MAX_CMDSZ 16 /* SCSI maximum CDB size. */
|
#define MAX_CMDSZ 16 /* SCSI maximum CDB size. */
|
||||||
#include "qla_fw.h"
|
#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
|
* Timeout timer counts in seconds
|
||||||
*/
|
*/
|
||||||
|
@ -309,6 +319,17 @@ struct els_logo_payload {
|
||||||
uint8_t wwpn[WWN_SIZE];
|
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.
|
* SRB extensions.
|
||||||
*/
|
*/
|
||||||
|
@ -320,6 +341,7 @@ struct srb_iocb {
|
||||||
#define SRB_LOGIN_COND_PLOGI BIT_1
|
#define SRB_LOGIN_COND_PLOGI BIT_1
|
||||||
#define SRB_LOGIN_SKIP_PRLI BIT_2
|
#define SRB_LOGIN_SKIP_PRLI BIT_2
|
||||||
uint16_t data[2];
|
uint16_t data[2];
|
||||||
|
u32 iop[2];
|
||||||
} logio;
|
} logio;
|
||||||
struct {
|
struct {
|
||||||
#define ELS_DCMD_TIMEOUT 20
|
#define ELS_DCMD_TIMEOUT 20
|
||||||
|
@ -372,6 +394,16 @@ struct srb_iocb {
|
||||||
__le16 comp_status;
|
__le16 comp_status;
|
||||||
struct completion comp;
|
struct completion comp;
|
||||||
} abt;
|
} 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;
|
} u;
|
||||||
|
|
||||||
struct timer_list timer;
|
struct timer_list timer;
|
||||||
|
@ -392,16 +424,24 @@ struct srb_iocb {
|
||||||
#define SRB_FXIOCB_BCMD 11
|
#define SRB_FXIOCB_BCMD 11
|
||||||
#define SRB_ABT_CMD 12
|
#define SRB_ABT_CMD 12
|
||||||
#define SRB_ELS_DCMD 13
|
#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 {
|
typedef struct srb {
|
||||||
atomic_t ref_count;
|
atomic_t ref_count;
|
||||||
struct fc_port *fcport;
|
struct fc_port *fcport;
|
||||||
|
void *vha;
|
||||||
uint32_t handle;
|
uint32_t handle;
|
||||||
uint16_t flags;
|
uint16_t flags;
|
||||||
uint16_t type;
|
uint16_t type;
|
||||||
char *name;
|
char *name;
|
||||||
int iocbs;
|
int iocbs;
|
||||||
struct qla_qpair *qpair;
|
struct qla_qpair *qpair;
|
||||||
|
u32 gen1; /* scratch */
|
||||||
|
u32 gen2; /* scratch */
|
||||||
union {
|
union {
|
||||||
struct srb_iocb iocb_cmd;
|
struct srb_iocb iocb_cmd;
|
||||||
struct bsg_job *bsg_job;
|
struct bsg_job *bsg_job;
|
||||||
|
@ -2101,6 +2141,18 @@ typedef struct {
|
||||||
#define FC4_TYPE_OTHER 0x0
|
#define FC4_TYPE_OTHER 0x0
|
||||||
#define FC4_TYPE_UNKNOWN 0xff
|
#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.
|
* Fibre channel port type.
|
||||||
*/
|
*/
|
||||||
|
@ -2113,6 +2165,12 @@ typedef enum {
|
||||||
FCT_TARGET
|
FCT_TARGET
|
||||||
} fc_port_type_t;
|
} 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 {
|
enum qlt_plogi_link_t {
|
||||||
QLT_PLOGI_LINK_SAME_WWN,
|
QLT_PLOGI_LINK_SAME_WWN,
|
||||||
QLT_PLOGI_LINK_CONFLICT,
|
QLT_PLOGI_LINK_CONFLICT,
|
||||||
|
@ -2124,6 +2182,48 @@ struct qlt_plogi_ack_t {
|
||||||
struct imm_ntfy_from_isp iocb;
|
struct imm_ntfy_from_isp iocb;
|
||||||
port_id_t id;
|
port_id_t id;
|
||||||
int ref_count;
|
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 deleted:2;
|
||||||
unsigned int local:1;
|
unsigned int local:1;
|
||||||
unsigned int logout_on_delete:1;
|
unsigned int logout_on_delete:1;
|
||||||
|
unsigned int logo_ack_needed:1;
|
||||||
unsigned int keep_nport_handle:1;
|
unsigned int keep_nport_handle:1;
|
||||||
unsigned int send_els_logo:1;
|
unsigned int send_els_logo:1;
|
||||||
|
unsigned int login_pause:1;
|
||||||
|
unsigned int login_succ:1;
|
||||||
|
|
||||||
|
struct fc_port *conflict;
|
||||||
unsigned char logout_completed;
|
unsigned char logout_completed;
|
||||||
int generation;
|
int generation;
|
||||||
|
|
||||||
|
@ -2186,8 +2290,30 @@ typedef struct fc_port {
|
||||||
|
|
||||||
unsigned long retry_delay_timestamp;
|
unsigned long retry_delay_timestamp;
|
||||||
struct qla_tgt_sess *tgt_session;
|
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;
|
} 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"
|
#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_REQ_SIZE (16 + 4)
|
||||||
#define GFT_ID_RSP_SIZE (16 + 32)
|
#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_CMD 0x217
|
||||||
#define RFT_ID_REQ_SIZE (16 + 4 + 32)
|
#define RFT_ID_REQ_SIZE (16 + 4 + 32)
|
||||||
#define RFT_ID_RSP_SIZE 16
|
#define RFT_ID_RSP_SIZE 16
|
||||||
|
@ -2590,6 +2720,10 @@ struct ct_sns_req {
|
||||||
uint8_t reserved;
|
uint8_t reserved;
|
||||||
uint8_t port_name[3];
|
uint8_t port_name[3];
|
||||||
} gff_id;
|
} gff_id;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint8_t port_name[8];
|
||||||
|
} gid_pn;
|
||||||
} req;
|
} req;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2669,6 +2803,10 @@ struct ct_sns_rsp {
|
||||||
struct {
|
struct {
|
||||||
uint8_t fc4_features[128];
|
uint8_t fc4_features[128];
|
||||||
} gff_id;
|
} gff_id;
|
||||||
|
struct {
|
||||||
|
uint8_t reserved;
|
||||||
|
uint8_t port_id[3];
|
||||||
|
} gid_pn;
|
||||||
} rsp;
|
} rsp;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2810,11 +2948,11 @@ struct isp_operations {
|
||||||
|
|
||||||
uint16_t (*calc_req_entries) (uint16_t);
|
uint16_t (*calc_req_entries) (uint16_t);
|
||||||
void (*build_iocbs) (srb_t *, cmd_entry_t *, uint16_t);
|
void (*build_iocbs) (srb_t *, cmd_entry_t *, uint16_t);
|
||||||
void * (*prep_ms_iocb) (struct scsi_qla_host *, uint32_t, uint32_t);
|
void *(*prep_ms_iocb) (struct scsi_qla_host *, struct ct_arg *);
|
||||||
void * (*prep_ms_fdmi_iocb) (struct scsi_qla_host *, uint32_t,
|
void *(*prep_ms_fdmi_iocb) (struct scsi_qla_host *, uint32_t,
|
||||||
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);
|
uint32_t, uint32_t);
|
||||||
int (*write_nvram) (struct scsi_qla_host *, uint8_t *, uint32_t,
|
int (*write_nvram) (struct scsi_qla_host *, uint8_t *, uint32_t,
|
||||||
uint32_t);
|
uint32_t);
|
||||||
|
@ -2876,13 +3014,21 @@ enum qla_work_type {
|
||||||
QLA_EVT_AEN,
|
QLA_EVT_AEN,
|
||||||
QLA_EVT_IDC_ACK,
|
QLA_EVT_IDC_ACK,
|
||||||
QLA_EVT_ASYNC_LOGIN,
|
QLA_EVT_ASYNC_LOGIN,
|
||||||
QLA_EVT_ASYNC_LOGIN_DONE,
|
|
||||||
QLA_EVT_ASYNC_LOGOUT,
|
QLA_EVT_ASYNC_LOGOUT,
|
||||||
QLA_EVT_ASYNC_LOGOUT_DONE,
|
QLA_EVT_ASYNC_LOGOUT_DONE,
|
||||||
QLA_EVT_ASYNC_ADISC,
|
QLA_EVT_ASYNC_ADISC,
|
||||||
QLA_EVT_ASYNC_ADISC_DONE,
|
QLA_EVT_ASYNC_ADISC_DONE,
|
||||||
QLA_EVT_UEVENT,
|
QLA_EVT_UEVENT,
|
||||||
QLA_EVT_AENFX,
|
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 {
|
struct {
|
||||||
srb_t *sp;
|
srb_t *sp;
|
||||||
} iosb;
|
} 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;
|
} u;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3899,6 +4062,10 @@ typedef struct scsi_qla_host {
|
||||||
struct qla8044_reset_template reset_tmplt;
|
struct qla8044_reset_template reset_tmplt;
|
||||||
struct qla_tgt_counters tgt_counters;
|
struct qla_tgt_counters tgt_counters;
|
||||||
uint16_t bbcr;
|
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;
|
} scsi_qla_host_t;
|
||||||
|
|
||||||
struct qla27xx_image_status {
|
struct qla27xx_image_status {
|
||||||
|
|
|
@ -72,6 +72,37 @@ struct port_database_24xx {
|
||||||
uint8_t reserved_3[24];
|
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 {
|
struct vp_database_24xx {
|
||||||
uint16_t vp_status;
|
uint16_t vp_status;
|
||||||
uint8_t options;
|
uint8_t options;
|
||||||
|
|
|
@ -73,6 +73,10 @@ extern void qla2x00_async_logout_done(struct scsi_qla_host *, fc_port_t *,
|
||||||
uint16_t *);
|
uint16_t *);
|
||||||
extern void qla2x00_async_adisc_done(struct scsi_qla_host *, fc_port_t *,
|
extern void qla2x00_async_adisc_done(struct scsi_qla_host *, fc_port_t *,
|
||||||
uint16_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(struct scsi_qla_host *, srb_t *);
|
||||||
extern void *qla2x00_alloc_iocbs_ready(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 *);
|
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 *,
|
extern struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *,
|
||||||
int, int);
|
int, int);
|
||||||
extern int qla2xxx_delete_qpair(struct scsi_qla_host *, struct qla_qpair *);
|
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.
|
* 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_idc_ack_work(struct scsi_qla_host *, uint16_t *);
|
||||||
extern int qla2x00_post_async_login_work(struct scsi_qla_host *, fc_port_t *,
|
extern int qla2x00_post_async_login_work(struct scsi_qla_host *, fc_port_t *,
|
||||||
uint16_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 *,
|
extern int qla2x00_post_async_logout_work(struct scsi_qla_host *, fc_port_t *,
|
||||||
uint16_t *);
|
uint16_t *);
|
||||||
extern int qla2x00_post_async_logout_done_work(struct scsi_qla_host *,
|
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 qla2x00_sp_compl(void *, void *, int);
|
||||||
extern void qla2xxx_qpair_sp_free_dma(void *, void *);
|
extern void qla2xxx_qpair_sp_free_dma(void *, void *);
|
||||||
extern void qla2xxx_qpair_sp_compl(void *, void *, int);
|
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.
|
* 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
|
extern int
|
||||||
qla2x00_init_firmware(scsi_qla_host_t *, uint16_t);
|
qla2x00_init_firmware(scsi_qla_host_t *, uint16_t);
|
||||||
|
|
||||||
extern int
|
|
||||||
qla2x00_get_node_name_list(scsi_qla_host_t *, void **, int *);
|
|
||||||
|
|
||||||
extern int
|
extern int
|
||||||
qla2x00_get_port_database(scsi_qla_host_t *, fc_port_t *, uint8_t);
|
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);
|
uint32_t);
|
||||||
extern irqreturn_t
|
extern irqreturn_t
|
||||||
qla2xxx_msix_rsp_q(int irq, void *dev_id);
|
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.
|
* 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.
|
* 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 *qla2x00_prep_ms_iocb(scsi_qla_host_t *, struct ct_arg *);
|
||||||
extern void *qla24xx_prep_ms_iocb(scsi_qla_host_t *, uint32_t, uint32_t);
|
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_ga_nxt(scsi_qla_host_t *, fc_port_t *);
|
||||||
extern int qla2x00_gid_pt(scsi_qla_host_t *, sw_info_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 *);
|
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_gfpn_id(scsi_qla_host_t *, sw_info_t *);
|
||||||
extern int qla2x00_gpsc(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 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.
|
* 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 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 *);
|
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 */
|
#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.
|
* Returns a pointer to the @ha's ms_iocb.
|
||||||
*/
|
*/
|
||||||
void *
|
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;
|
struct qla_hw_data *ha = vha->hw;
|
||||||
ms_iocb_entry_t *ms_pkt;
|
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));
|
memset(ms_pkt, 0, sizeof(ms_iocb_entry_t));
|
||||||
|
|
||||||
ms_pkt->entry_type = MS_IOCB_TYPE;
|
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->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
|
||||||
ms_pkt->cmd_dsd_count = cpu_to_le16(1);
|
ms_pkt->cmd_dsd_count = cpu_to_le16(1);
|
||||||
ms_pkt->total_dsd_count = cpu_to_le16(2);
|
ms_pkt->total_dsd_count = cpu_to_le16(2);
|
||||||
ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size);
|
ms_pkt->rsp_bytecount = cpu_to_le32(arg->rsp_size);
|
||||||
ms_pkt->req_bytecount = cpu_to_le32(req_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[0] = cpu_to_le32(LSD(arg->req_dma));
|
||||||
ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(ha->ct_sns_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_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[0] = cpu_to_le32(LSD(arg->rsp_dma));
|
||||||
ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
|
ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(arg->rsp_dma));
|
||||||
ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount;
|
ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount;
|
||||||
|
|
||||||
vha->qla_stats.control_requests++;
|
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.
|
* Returns a pointer to the @ha's ms_iocb.
|
||||||
*/
|
*/
|
||||||
void *
|
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 qla_hw_data *ha = vha->hw;
|
||||||
struct ct_entry_24xx *ct_pkt;
|
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));
|
memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
|
||||||
|
|
||||||
ct_pkt->entry_type = CT_IOCB_TYPE;
|
ct_pkt->entry_type = CT_IOCB_TYPE;
|
||||||
ct_pkt->entry_count = 1;
|
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->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
|
||||||
ct_pkt->cmd_dsd_count = cpu_to_le16(1);
|
ct_pkt->cmd_dsd_count = cpu_to_le16(1);
|
||||||
ct_pkt->rsp_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->rsp_byte_count = cpu_to_le32(arg->rsp_size);
|
||||||
ct_pkt->cmd_byte_count = cpu_to_le32(req_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[0] = cpu_to_le32(LSD(arg->req_dma));
|
||||||
ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_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_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[0] = cpu_to_le32(LSD(arg->rsp_dma));
|
||||||
ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_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->dseg_1_len = ct_pkt->rsp_byte_count;
|
||||||
ct_pkt->vp_index = vha->vp_idx;
|
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;
|
return &p->p.req;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int
|
||||||
qla2x00_chk_ms_status(scsi_qla_host_t *vha, ms_iocb_entry_t *ms_pkt,
|
qla2x00_chk_ms_status(scsi_qla_host_t *vha, ms_iocb_entry_t *ms_pkt,
|
||||||
struct ct_sns_rsp *ct_rsp, const char *routine)
|
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_req *ct_req;
|
||||||
struct ct_sns_rsp *ct_rsp;
|
struct ct_sns_rsp *ct_rsp;
|
||||||
struct qla_hw_data *ha = vha->hw;
|
struct qla_hw_data *ha = vha->hw;
|
||||||
|
struct ct_arg arg;
|
||||||
|
|
||||||
if (IS_QLA2100(ha) || IS_QLA2200(ha))
|
if (IS_QLA2100(ha) || IS_QLA2200(ha))
|
||||||
return qla2x00_sns_ga_nxt(vha, fcport);
|
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 */
|
/* Issue GA_NXT */
|
||||||
/* Prepare common MS IOCB */
|
/* Prepare common MS IOCB */
|
||||||
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GA_NXT_REQ_SIZE,
|
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
|
||||||
GA_NXT_RSP_SIZE);
|
|
||||||
|
|
||||||
/* Prepare CT request */
|
/* Prepare CT request */
|
||||||
ct_req = qla2x00_prep_ct_req(ha->ct_sns, GA_NXT_CMD,
|
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 ct_sns_gid_pt_data *gid_data;
|
||||||
struct qla_hw_data *ha = vha->hw;
|
struct qla_hw_data *ha = vha->hw;
|
||||||
uint16_t gid_pt_rsp_size;
|
uint16_t gid_pt_rsp_size;
|
||||||
|
struct ct_arg arg;
|
||||||
|
|
||||||
if (IS_QLA2100(ha) || IS_QLA2200(ha))
|
if (IS_QLA2100(ha) || IS_QLA2200(ha))
|
||||||
return qla2x00_sns_gid_pt(vha, list);
|
return qla2x00_sns_gid_pt(vha, list);
|
||||||
|
|
||||||
gid_data = NULL;
|
gid_data = NULL;
|
||||||
gid_pt_rsp_size = qla2x00_gid_pt_rsp_size(vha);
|
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 */
|
/* Issue GID_PT */
|
||||||
/* Prepare common MS IOCB */
|
/* Prepare common MS IOCB */
|
||||||
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GID_PT_REQ_SIZE,
|
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
|
||||||
gid_pt_rsp_size);
|
|
||||||
|
|
||||||
/* Prepare CT request */
|
/* Prepare CT request */
|
||||||
ct_req = qla2x00_prep_ct_req(ha->ct_sns, GID_PT_CMD, gid_pt_rsp_size);
|
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_req *ct_req;
|
||||||
struct ct_sns_rsp *ct_rsp;
|
struct ct_sns_rsp *ct_rsp;
|
||||||
struct qla_hw_data *ha = vha->hw;
|
struct qla_hw_data *ha = vha->hw;
|
||||||
|
struct ct_arg arg;
|
||||||
|
|
||||||
if (IS_QLA2100(ha) || IS_QLA2200(ha))
|
if (IS_QLA2100(ha) || IS_QLA2200(ha))
|
||||||
return qla2x00_sns_gpn_id(vha, list);
|
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++) {
|
for (i = 0; i < ha->max_fibre_devices; i++) {
|
||||||
/* Issue GPN_ID */
|
/* Issue GPN_ID */
|
||||||
/* Prepare common MS IOCB */
|
/* Prepare common MS IOCB */
|
||||||
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GPN_ID_REQ_SIZE,
|
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
|
||||||
GPN_ID_RSP_SIZE);
|
|
||||||
|
|
||||||
/* Prepare CT request */
|
/* Prepare CT request */
|
||||||
ct_req = qla2x00_prep_ct_req(ha->ct_sns, GPN_ID_CMD,
|
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;
|
ms_iocb_entry_t *ms_pkt;
|
||||||
struct ct_sns_req *ct_req;
|
struct ct_sns_req *ct_req;
|
||||||
struct ct_sns_rsp *ct_rsp;
|
struct ct_sns_rsp *ct_rsp;
|
||||||
|
struct ct_arg arg;
|
||||||
|
|
||||||
if (IS_QLA2100(ha) || IS_QLA2200(ha))
|
if (IS_QLA2100(ha) || IS_QLA2200(ha))
|
||||||
return qla2x00_sns_gnn_id(vha, list);
|
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++) {
|
for (i = 0; i < ha->max_fibre_devices; i++) {
|
||||||
/* Issue GNN_ID */
|
/* Issue GNN_ID */
|
||||||
/* Prepare common MS IOCB */
|
/* Prepare common MS IOCB */
|
||||||
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GNN_ID_REQ_SIZE,
|
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
|
||||||
GNN_ID_RSP_SIZE);
|
|
||||||
|
|
||||||
/* Prepare CT request */
|
/* Prepare CT request */
|
||||||
ct_req = qla2x00_prep_ct_req(ha->ct_sns, GNN_ID_CMD,
|
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;
|
ms_iocb_entry_t *ms_pkt;
|
||||||
struct ct_sns_req *ct_req;
|
struct ct_sns_req *ct_req;
|
||||||
struct ct_sns_rsp *ct_rsp;
|
struct ct_sns_rsp *ct_rsp;
|
||||||
|
struct ct_arg arg;
|
||||||
|
|
||||||
if (IS_QLA2100(ha) || IS_QLA2200(ha))
|
if (IS_QLA2100(ha) || IS_QLA2200(ha))
|
||||||
return qla2x00_sns_rft_id(vha);
|
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 */
|
/* Issue RFT_ID */
|
||||||
/* Prepare common MS IOCB */
|
/* Prepare common MS IOCB */
|
||||||
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, RFT_ID_REQ_SIZE,
|
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
|
||||||
RFT_ID_RSP_SIZE);
|
|
||||||
|
|
||||||
/* Prepare CT request */
|
/* Prepare CT request */
|
||||||
ct_req = qla2x00_prep_ct_req(ha->ct_sns, RFT_ID_CMD,
|
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;
|
ms_iocb_entry_t *ms_pkt;
|
||||||
struct ct_sns_req *ct_req;
|
struct ct_sns_req *ct_req;
|
||||||
struct ct_sns_rsp *ct_rsp;
|
struct ct_sns_rsp *ct_rsp;
|
||||||
|
struct ct_arg arg;
|
||||||
|
|
||||||
if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
|
if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
|
||||||
ql_dbg(ql_dbg_disc, vha, 0x2046,
|
ql_dbg(ql_dbg_disc, vha, 0x2046,
|
||||||
|
@ -533,10 +570,16 @@ qla2x00_rff_id(scsi_qla_host_t *vha)
|
||||||
return (QLA_SUCCESS);
|
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 */
|
/* Issue RFF_ID */
|
||||||
/* Prepare common MS IOCB */
|
/* Prepare common MS IOCB */
|
||||||
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, RFF_ID_REQ_SIZE,
|
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
|
||||||
RFF_ID_RSP_SIZE);
|
|
||||||
|
|
||||||
/* Prepare CT request */
|
/* Prepare CT request */
|
||||||
ct_req = qla2x00_prep_ct_req(ha->ct_sns, RFF_ID_CMD,
|
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;
|
ms_iocb_entry_t *ms_pkt;
|
||||||
struct ct_sns_req *ct_req;
|
struct ct_sns_req *ct_req;
|
||||||
struct ct_sns_rsp *ct_rsp;
|
struct ct_sns_rsp *ct_rsp;
|
||||||
|
struct ct_arg arg;
|
||||||
|
|
||||||
if (IS_QLA2100(ha) || IS_QLA2200(ha))
|
if (IS_QLA2100(ha) || IS_QLA2200(ha))
|
||||||
return qla2x00_sns_rnn_id(vha);
|
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 */
|
/* Issue RNN_ID */
|
||||||
/* Prepare common MS IOCB */
|
/* Prepare common MS IOCB */
|
||||||
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, RNN_ID_REQ_SIZE,
|
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
|
||||||
RNN_ID_RSP_SIZE);
|
|
||||||
|
|
||||||
/* Prepare CT request */
|
/* Prepare CT request */
|
||||||
ct_req = qla2x00_prep_ct_req(ha->ct_sns, RNN_ID_CMD, RNN_ID_RSP_SIZE);
|
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;
|
ms_iocb_entry_t *ms_pkt;
|
||||||
struct ct_sns_req *ct_req;
|
struct ct_sns_req *ct_req;
|
||||||
struct ct_sns_rsp *ct_rsp;
|
struct ct_sns_rsp *ct_rsp;
|
||||||
|
struct ct_arg arg;
|
||||||
|
|
||||||
if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
|
if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
|
||||||
ql_dbg(ql_dbg_disc, vha, 0x2050,
|
ql_dbg(ql_dbg_disc, vha, 0x2050,
|
||||||
|
@ -658,10 +709,17 @@ qla2x00_rsnn_nn(scsi_qla_host_t *vha)
|
||||||
return (QLA_SUCCESS);
|
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 */
|
/* Issue RSNN_NN */
|
||||||
/* Prepare common MS IOCB */
|
/* Prepare common MS IOCB */
|
||||||
/* Request size adjusted after CT preparation */
|
/* 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 */
|
/* Prepare CT request */
|
||||||
ct_req = qla2x00_prep_ct_req(ha->ct_sns, RSNN_NN_CMD,
|
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.
|
* Returns 0 on success.
|
||||||
*/
|
*/
|
||||||
static int
|
int
|
||||||
qla2x00_mgmt_svr_login(scsi_qla_host_t *vha)
|
qla2x00_mgmt_svr_login(scsi_qla_host_t *vha)
|
||||||
{
|
{
|
||||||
int ret, rval;
|
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;
|
ms_iocb_entry_t *ms_pkt;
|
||||||
struct ct_sns_req *ct_req;
|
struct ct_sns_req *ct_req;
|
||||||
struct ct_sns_rsp *ct_rsp;
|
struct ct_sns_rsp *ct_rsp;
|
||||||
|
struct ct_arg arg;
|
||||||
|
|
||||||
if (!IS_IIDMA_CAPABLE(ha))
|
if (!IS_IIDMA_CAPABLE(ha))
|
||||||
return QLA_FUNCTION_FAILED;
|
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++) {
|
for (i = 0; i < ha->max_fibre_devices; i++) {
|
||||||
/* Issue GFPN_ID */
|
/* Issue GFPN_ID */
|
||||||
/* Prepare common MS IOCB */
|
/* Prepare common MS IOCB */
|
||||||
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GFPN_ID_REQ_SIZE,
|
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
|
||||||
GFPN_ID_RSP_SIZE);
|
|
||||||
|
|
||||||
/* Prepare CT request */
|
/* Prepare CT request */
|
||||||
ct_req = qla2x00_prep_ct_req(ha->ct_sns, GFPN_ID_CMD,
|
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);
|
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 *
|
static inline struct ct_sns_req *
|
||||||
qla24xx_prep_ct_fm_req(struct ct_sns_pkt *p, uint16_t cmd,
|
qla24xx_prep_ct_fm_req(struct ct_sns_pkt *p, uint16_t cmd,
|
||||||
|
@ -2533,6 +2568,7 @@ qla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list)
|
||||||
ms_iocb_entry_t *ms_pkt;
|
ms_iocb_entry_t *ms_pkt;
|
||||||
struct ct_sns_req *ct_req;
|
struct ct_sns_req *ct_req;
|
||||||
struct ct_sns_rsp *ct_rsp;
|
struct ct_sns_rsp *ct_rsp;
|
||||||
|
struct ct_arg arg;
|
||||||
|
|
||||||
if (!IS_IIDMA_CAPABLE(ha))
|
if (!IS_IIDMA_CAPABLE(ha))
|
||||||
return QLA_FUNCTION_FAILED;
|
return QLA_FUNCTION_FAILED;
|
||||||
|
@ -2543,11 +2579,17 @@ qla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list)
|
||||||
if (rval)
|
if (rval)
|
||||||
return 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++) {
|
for (i = 0; i < ha->max_fibre_devices; i++) {
|
||||||
/* Issue GFPN_ID */
|
/* Issue GFPN_ID */
|
||||||
/* Prepare common MS IOCB */
|
/* Prepare common MS IOCB */
|
||||||
ms_pkt = qla24xx_prep_ms_fm_iocb(vha, GPSC_REQ_SIZE,
|
ms_pkt = qla24xx_prep_ms_iocb(vha, &arg);
|
||||||
GPSC_RSP_SIZE);
|
|
||||||
|
|
||||||
/* Prepare CT request */
|
/* Prepare CT request */
|
||||||
ct_req = qla24xx_prep_ct_fm_req(ha->ct_sns, GPSC_CMD,
|
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 ct_sns_rsp *ct_rsp;
|
||||||
struct qla_hw_data *ha = vha->hw;
|
struct qla_hw_data *ha = vha->hw;
|
||||||
uint8_t fcp_scsi_features = 0;
|
uint8_t fcp_scsi_features = 0;
|
||||||
|
struct ct_arg arg;
|
||||||
|
|
||||||
for (i = 0; i < ha->max_fibre_devices; i++) {
|
for (i = 0; i < ha->max_fibre_devices; i++) {
|
||||||
/* Set default FC4 Type as UNKNOWN so the default is to
|
/* 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))
|
if (!IS_FWI2_CAPABLE(ha))
|
||||||
continue;
|
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 */
|
/* Prepare common MS IOCB */
|
||||||
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GFF_ID_REQ_SIZE,
|
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
|
||||||
GFF_ID_RSP_SIZE);
|
|
||||||
|
|
||||||
/* Prepare CT request */
|
/* Prepare CT request */
|
||||||
ct_req = qla2x00_prep_ct_req(ha->ct_sns, GFF_ID_CMD,
|
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;
|
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 */
|
/* Don't print state transitions during initial allocation of fcport */
|
||||||
if (old_state && old_state != state) {
|
if (old_state && old_state != state) {
|
||||||
ql_dbg(ql_dbg_disc, fcport->vha, 0x207d,
|
ql_dbg(ql_dbg_disc, fcport->vha, 0x207d,
|
||||||
"FCPort state transitioned from %s to %s - "
|
"FCPort %8phC state transitioned from %s to %s - "
|
||||||
"portid=%02x%02x%02x.\n",
|
"portid=%02x%02x%02x.\n", fcport->port_name,
|
||||||
port_state_str[old_state], port_state_str[state],
|
port_state_str[old_state], port_state_str[state],
|
||||||
fcport->d_id.b.domain, fcport->d_id.b.area,
|
fcport->d_id.b.domain, fcport->d_id.b.area,
|
||||||
fcport->d_id.b.al_pa);
|
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));
|
memset(sp, 0, sizeof(*sp));
|
||||||
sp->fcport = fcport;
|
sp->fcport = fcport;
|
||||||
sp->iocbs = 1;
|
sp->iocbs = 1;
|
||||||
|
sp->vha = vha;
|
||||||
done:
|
done:
|
||||||
if (!sp)
|
if (!sp)
|
||||||
QLA_VHA_MARK_NOT_BUSY(vha);
|
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;
|
sp->u.iocb_cmd.timer.function = qla2x00_sp_timeout;
|
||||||
add_timer(&sp->u.iocb_cmd.timer);
|
add_timer(&sp->u.iocb_cmd.timer);
|
||||||
sp->free = qla2x00_sp_free;
|
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))
|
(sp->type == SRB_FXIOCB_DCMD))
|
||||||
init_completion(&sp->u.iocb_cmd.u.fxiocb.fxiocb_comp);
|
init_completion(&sp->u.iocb_cmd.u.fxiocb.fxiocb_comp);
|
||||||
if (sp->type == SRB_ELS_DCMD)
|
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->entry_type = LOGINOUT_PORT_IOCB_TYPE;
|
||||||
logio->control_flags =
|
logio->control_flags =
|
||||||
cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO);
|
cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO);
|
||||||
if (!sp->fcport->tgt_session ||
|
if (!sp->fcport->se_sess ||
|
||||||
!sp->fcport->keep_nport_handle)
|
!sp->fcport->keep_nport_handle)
|
||||||
logio->control_flags |= cpu_to_le16(LCF_FREE_NPORT);
|
logio->control_flags |= cpu_to_le16(LCF_FREE_NPORT);
|
||||||
logio->nport_handle = cpu_to_le16(sp->fcport->loop_id);
|
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();
|
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
|
int
|
||||||
qla2x00_start_sp(srb_t *sp)
|
qla2x00_start_sp(srb_t *sp)
|
||||||
{
|
{
|
||||||
int rval;
|
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;
|
void *pkt;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
rval = QLA_FUNCTION_FAILED;
|
rval = QLA_FUNCTION_FAILED;
|
||||||
spin_lock_irqsave(&ha->hardware_lock, flags);
|
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||||
pkt = qla2x00_alloc_iocbs(sp->fcport->vha, sp);
|
pkt = qla2x00_alloc_iocbs(vha, sp);
|
||||||
if (!pkt) {
|
if (!pkt) {
|
||||||
ql_log(ql_log_warn, sp->fcport->vha, 0x700c,
|
ql_log(ql_log_warn, vha, 0x700c,
|
||||||
"qla2x00_alloc_iocbs failed.\n");
|
"qla2x00_alloc_iocbs failed.\n");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
@ -3139,12 +3189,23 @@ qla2x00_start_sp(srb_t *sp)
|
||||||
case SRB_ELS_DCMD:
|
case SRB_ELS_DCMD:
|
||||||
qla24xx_els_logo_iocb(sp, pkt);
|
qla24xx_els_logo_iocb(sp, pkt);
|
||||||
break;
|
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:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
wmb();
|
wmb();
|
||||||
qla2x00_start_iocbs(sp->fcport->vha, ha->req_q_map[0]);
|
qla2x00_start_iocbs(vha, ha->req_q_map[0]);
|
||||||
done:
|
done:
|
||||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||||
return rval;
|
return rval;
|
||||||
|
|
|
@ -561,14 +561,50 @@ qla2x00_is_a_vp_did(scsi_qla_host_t *vha, uint32_t rscn_entry)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline fc_port_t *
|
fc_port_t *
|
||||||
qla2x00_find_fcport_by_loopid(scsi_qla_host_t *vha, uint16_t loop_id)
|
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)
|
f = tf = NULL;
|
||||||
if (fcport->loop_id == loop_id)
|
list_for_each_entry_safe(f, tf, &vha->vp_fcports, list)
|
||||||
return fcport;
|
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;
|
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,
|
ql_dbg(ql_dbg_async, vha, 0x508a,
|
||||||
"Marking port lost loopid=%04x portid=%06x.\n",
|
"Marking port lost loopid=%04x portid=%06x.\n",
|
||||||
fcport->loop_id, fcport->d_id.b24);
|
fcport->loop_id, fcport->d_id.b24);
|
||||||
|
if (qla_ini_mode_enabled(vha)) {
|
||||||
qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1);
|
qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1);
|
||||||
|
fcport->logout_on_delete = 0;
|
||||||
|
qlt_schedule_sess_for_deletion_lock(fcport);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
global_port_update:
|
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))
|
if (qla2x00_is_a_vp_did(vha, rscn_entry))
|
||||||
break;
|
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);
|
atomic_set(&vha->loop_down_timer, 0);
|
||||||
vha->flags.management_server_logged_in = 0;
|
vha->flags.management_server_logged_in = 0;
|
||||||
|
{
|
||||||
|
struct event_arg ea;
|
||||||
|
|
||||||
set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
|
memset(&ea, 0, sizeof(ea));
|
||||||
set_bit(RSCN_UPDATE, &vha->dpc_flags);
|
ea.event = FCME_RSCN;
|
||||||
qla2x00_post_aen_work(vha, FCH_EVT_RSCN, rscn_entry);
|
ea.id.b24 = rscn_entry;
|
||||||
|
qla2x00_fcport_event_handler(vha, &ea);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* case MBA_RIO_RESPONSE: */
|
/* case MBA_RIO_RESPONSE: */
|
||||||
case MBA_ZIO_RESPONSE:
|
case MBA_ZIO_RESPONSE:
|
||||||
ql_dbg(ql_dbg_async, vha, 0x5015,
|
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);
|
index = LSW(pkt->handle);
|
||||||
if (index >= req->num_outstanding_cmds) {
|
if (index >= req->num_outstanding_cmds) {
|
||||||
ql_log(ql_log_warn, vha, 0x5031,
|
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))
|
if (IS_P3P_TYPE(ha))
|
||||||
set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
|
set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
|
||||||
else
|
else
|
||||||
|
@ -1346,6 +1377,49 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
|
||||||
sp->done(vha, sp, 0);
|
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
|
static void
|
||||||
qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
|
qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
|
||||||
sts_entry_t *pkt, int iocb_type)
|
sts_entry_t *pkt, int iocb_type)
|
||||||
|
@ -1356,12 +1430,14 @@ qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
|
||||||
struct bsg_job *bsg_job;
|
struct bsg_job *bsg_job;
|
||||||
struct fc_bsg_reply *bsg_reply;
|
struct fc_bsg_reply *bsg_reply;
|
||||||
uint16_t comp_status;
|
uint16_t comp_status;
|
||||||
int res;
|
int res = 0;
|
||||||
|
|
||||||
sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
|
sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
|
||||||
if (!sp)
|
if (!sp)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
switch (sp->type) {
|
||||||
|
case SRB_CT_CMD:
|
||||||
bsg_job = sp->u.bsg_job;
|
bsg_job = sp->u.bsg_job;
|
||||||
bsg_reply = bsg_job->reply;
|
bsg_reply = bsg_job->reply;
|
||||||
|
|
||||||
|
@ -1369,7 +1445,8 @@ qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
|
||||||
|
|
||||||
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
|
/*
|
||||||
|
* return FC_CTELS_STATUS_OK and leave the decoding of the ELS/CT
|
||||||
* fc payload to the caller
|
* fc payload to the caller
|
||||||
*/
|
*/
|
||||||
bsg_reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
|
bsg_reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
|
||||||
|
@ -1382,14 +1459,13 @@ qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
|
||||||
le16_to_cpu(((sts_entry_t *)pkt)->rsp_info_len);
|
le16_to_cpu(((sts_entry_t *)pkt)->rsp_info_len);
|
||||||
|
|
||||||
ql_log(ql_log_warn, vha, 0x5048,
|
ql_log(ql_log_warn, vha, 0x5048,
|
||||||
"CT pass-through-%s error "
|
"CT pass-through-%s error comp_status=0x%x total_byte=0x%x.\n",
|
||||||
"comp_status-status=0x%x total_byte = 0x%x.\n",
|
|
||||||
type, comp_status,
|
type, comp_status,
|
||||||
bsg_reply->reply_payload_rcv_len);
|
bsg_reply->reply_payload_rcv_len);
|
||||||
} else {
|
} else {
|
||||||
ql_log(ql_log_warn, vha, 0x5049,
|
ql_log(ql_log_warn, vha, 0x5049,
|
||||||
"CT pass-through-%s error "
|
"CT pass-through-%s error comp_status=0x%x.\n",
|
||||||
"comp_status-status=0x%x.\n", type, comp_status);
|
type, comp_status);
|
||||||
res = DID_ERROR << 16;
|
res = DID_ERROR << 16;
|
||||||
bsg_reply->reply_payload_rcv_len = 0;
|
bsg_reply->reply_payload_rcv_len = 0;
|
||||||
}
|
}
|
||||||
|
@ -1401,6 +1477,17 @@ qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
|
||||||
bsg_job->reply_payload.payload_len;
|
bsg_job->reply_payload.payload_len;
|
||||||
bsg_job->reply_len = 0;
|
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);
|
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);
|
"Completing %s: (%p) type=%d.\n", type, sp, sp->type);
|
||||||
sp->done(vha, sp, 0);
|
sp->done(vha, sp, 0);
|
||||||
return;
|
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:
|
default:
|
||||||
ql_dbg(ql_dbg_user, vha, 0x503e,
|
ql_dbg(ql_dbg_user, vha, 0x503e,
|
||||||
"Unrecognized SRB: (%p) type=%d.\n", sp, sp->type);
|
"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[0] = le32_to_cpu(logio->io_parameter[0]);
|
||||||
iop[1] = le32_to_cpu(logio->io_parameter[1]);
|
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]) {
|
switch (iop[0]) {
|
||||||
case LSC_SCODE_PORTID_USED:
|
case LSC_SCODE_PORTID_USED:
|
||||||
data[0] = MBS_PORT_ID_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;
|
int res = 0;
|
||||||
uint16_t state_flags = 0;
|
uint16_t state_flags = 0;
|
||||||
uint16_t retry_delay = 0;
|
uint16_t retry_delay = 0;
|
||||||
|
uint8_t no_logout = 0;
|
||||||
|
|
||||||
sts = (sts_entry_t *) pkt;
|
sts = (sts_entry_t *) pkt;
|
||||||
sts24 = (struct sts_entry_24xx *) 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;
|
break;
|
||||||
|
|
||||||
case CS_PORT_LOGGED_OUT:
|
case CS_PORT_LOGGED_OUT:
|
||||||
|
no_logout = 1;
|
||||||
case CS_PORT_CONFIG_CHG:
|
case CS_PORT_CONFIG_CHG:
|
||||||
case CS_PORT_BUSY:
|
case CS_PORT_BUSY:
|
||||||
case CS_INCOMPLETE:
|
case CS_INCOMPLETE:
|
||||||
|
@ -2356,14 +2456,21 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ql_dbg(ql_dbg_io, fcport->vha, 0x3021,
|
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 to be marked lost on fcport=%02x%02x%02x, current "
|
||||||
"port state= %s.\n", fcport->d_id.b.domain,
|
"port state= %s comp_status %x.\n", fcport->d_id.b.domain,
|
||||||
fcport->d_id.b.area, fcport->d_id.b.al_pa,
|
fcport->d_id.b.area, fcport->d_id.b.al_pa,
|
||||||
port_state_str[atomic_read(&fcport->state)]);
|
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);
|
qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1);
|
||||||
|
qlt_schedule_sess_for_deletion_lock(fcport);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CS_ABORTED:
|
case CS_ABORTED:
|
||||||
|
@ -2627,10 +2734,16 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
|
||||||
}
|
}
|
||||||
case ABTS_RESP_24XX:
|
case ABTS_RESP_24XX:
|
||||||
case CTIO_TYPE7:
|
case CTIO_TYPE7:
|
||||||
case NOTIFY_ACK_TYPE:
|
|
||||||
case CTIO_CRC2:
|
case CTIO_CRC2:
|
||||||
qlt_response_pkt_all_vps(vha, (response_t *)pkt);
|
qlt_response_pkt_all_vps(vha, (response_t *)pkt);
|
||||||
break;
|
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:
|
case MARKER_TYPE:
|
||||||
/* Do nothing in this case, this check is to prevent it
|
/* Do nothing in this case, this check is to prevent it
|
||||||
* from falling into default case
|
* 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,
|
qla24xx_abort_iocb_entry(vha, rsp->req,
|
||||||
(struct abort_entry_24xx *)pkt);
|
(struct abort_entry_24xx *)pkt);
|
||||||
break;
|
break;
|
||||||
|
case MBX_IOCB_TYPE:
|
||||||
|
qla24xx_mbx_iocb_entry(vha, rsp->req,
|
||||||
|
(struct mbx_24xx_entry *)pkt);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
/* Type Not Supported. */
|
/* Type Not Supported. */
|
||||||
ql_dbg(ql_dbg_async, vha, 0x5042,
|
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)) {
|
if (IS_P3P_TYPE(ha)) {
|
||||||
struct device_reg_82xx __iomem *reg = &ha->iobase->isp82;
|
struct device_reg_82xx __iomem *reg = &ha->iobase->isp82;
|
||||||
WRT_REG_DWORD(®->rsp_q_out[0], rsp->ring_index);
|
WRT_REG_DWORD(®->rsp_q_out[0], rsp->ring_index);
|
||||||
} else
|
} else {
|
||||||
WRT_REG_DWORD(rsp->rsp_q_out, rsp->ring_index);
|
WRT_REG_DWORD(rsp->rsp_q_out, rsp->ring_index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -1637,94 +1637,6 @@ qla2x00_init_firmware(scsi_qla_host_t *vha, uint16_t size)
|
||||||
return rval;
|
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
|
* qla2x00_get_port_database
|
||||||
|
|
|
@ -1043,6 +1043,34 @@ qla2x00_wait_for_hba_online(scsi_qla_host_t *vha)
|
||||||
return (return_status);
|
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
|
* qla2x00_wait_for_hba_ready
|
||||||
* Wait till the HBA is ready before doing driver unload
|
* 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)
|
if (ret)
|
||||||
goto probe_init_failed;
|
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 */
|
/* Alloc arrays of request and response ring ptrs */
|
||||||
if (!qla2x00_alloc_queues(ha, req, rsp)) {
|
if (!qla2x00_alloc_queues(ha, req, rsp)) {
|
||||||
ql_log(ql_log_fatal, base_vha, 0x003d,
|
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,
|
ql_dbg(ql_dbg_init, base_vha, 0x00f2,
|
||||||
"Init done and hba is online.\n");
|
"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);
|
scsi_scan_host(host);
|
||||||
else
|
else
|
||||||
ql_dbg(ql_dbg_init, base_vha, 0x0122,
|
ql_dbg(ql_dbg_init, base_vha, 0x0122,
|
||||||
|
@ -3372,21 +3413,26 @@ qla2x00_remove_one(struct pci_dev *pdev)
|
||||||
* resources.
|
* resources.
|
||||||
*/
|
*/
|
||||||
if (!atomic_read(&pdev->enable_cnt)) {
|
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);
|
scsi_host_put(base_vha->host);
|
||||||
kfree(ha);
|
kfree(ha);
|
||||||
pci_set_drvdata(pdev, NULL);
|
pci_set_drvdata(pdev, NULL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qla2x00_wait_for_hba_ready(base_vha);
|
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.
|
* where it was set first.
|
||||||
*/
|
*/
|
||||||
if (test_bit(UNLOADING, &base_vha->dpc_flags))
|
if (test_bit(UNLOADING, &base_vha->dpc_flags))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
set_bit(UNLOADING, &base_vha->dpc_flags);
|
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))
|
if (IS_QLAFX00(ha))
|
||||||
qlafx00_driver_shutdown(base_vha, 20);
|
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);
|
qla2xxx_wake_dpc(base_vha);
|
||||||
} else {
|
} else {
|
||||||
int now;
|
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);
|
fc_remote_port_delete(rport);
|
||||||
|
}
|
||||||
qlt_do_generation_tick(vha, &now);
|
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;
|
fcport->login_retry = vha->hw->login_retry_count;
|
||||||
|
|
||||||
ql_dbg(ql_dbg_disc, vha, 0x2067,
|
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);
|
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;
|
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) {
|
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)
|
if (vha->vp_idx != 0 && vha->vp_idx != fcport->vha->vp_idx)
|
||||||
continue;
|
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->work_lock);
|
||||||
spin_lock_init(&vha->cmd_list_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);
|
sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no);
|
||||||
ql_dbg(ql_dbg_init, vha, 0x0041,
|
ql_dbg(ql_dbg_init, vha, 0x0041,
|
||||||
|
@ -4232,7 +4289,7 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
|
||||||
return vha;
|
return vha;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct qla_work_evt *
|
struct qla_work_evt *
|
||||||
qla2x00_alloc_work(struct scsi_qla_host *vha, enum qla_work_type type)
|
qla2x00_alloc_work(struct scsi_qla_host *vha, enum qla_work_type type)
|
||||||
{
|
{
|
||||||
struct qla_work_evt *e;
|
struct qla_work_evt *e;
|
||||||
|
@ -4254,7 +4311,7 @@ qla2x00_alloc_work(struct scsi_qla_host *vha, enum qla_work_type type)
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int
|
||||||
qla2x00_post_work(struct scsi_qla_host *vha, struct qla_work_evt *e)
|
qla2x00_post_work(struct scsi_qla_host *vha, struct qla_work_evt *e)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
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, 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, QLA_EVT_ASYNC_LOGOUT);
|
||||||
qla2x00_post_async_work(logout_done, QLA_EVT_ASYNC_LOGOUT_DONE);
|
qla2x00_post_async_work(logout_done, QLA_EVT_ASYNC_LOGOUT_DONE);
|
||||||
qla2x00_post_async_work(adisc, QLA_EVT_ASYNC_ADISC);
|
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);
|
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
|
void
|
||||||
qla2x00_do_work(struct scsi_qla_host *vha)
|
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,
|
qla2x00_async_login(vha, e->u.logio.fcport,
|
||||||
e->u.logio.data);
|
e->u.logio.data);
|
||||||
break;
|
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:
|
case QLA_EVT_ASYNC_LOGOUT:
|
||||||
qla2x00_async_logout(vha, e->u.logio.fcport);
|
qla2x00_async_logout(vha, e->u.logio.fcport);
|
||||||
break;
|
break;
|
||||||
|
@ -4419,6 +4532,34 @@ qla2x00_do_work(struct scsi_qla_host *vha)
|
||||||
case QLA_EVT_AENFX:
|
case QLA_EVT_AENFX:
|
||||||
qlafx00_process_aen(vha, e);
|
qlafx00_process_aen(vha, e);
|
||||||
break;
|
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)
|
if (e->flags & QLA_EVT_FLAG_FREE)
|
||||||
kfree(e);
|
kfree(e);
|
||||||
|
@ -4435,9 +4576,7 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
|
||||||
{
|
{
|
||||||
fc_port_t *fcport;
|
fc_port_t *fcport;
|
||||||
int status;
|
int status;
|
||||||
uint16_t next_loopid = 0;
|
struct event_arg ea;
|
||||||
struct qla_hw_data *ha = vha->hw;
|
|
||||||
uint16_t data[2];
|
|
||||||
|
|
||||||
list_for_each_entry(fcport, &vha->vp_fcports, list) {
|
list_for_each_entry(fcport, &vha->vp_fcports, list) {
|
||||||
/*
|
/*
|
||||||
|
@ -4448,78 +4587,39 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
|
||||||
fcport->login_retry && !(fcport->flags & FCF_ASYNC_SENT)) {
|
fcport->login_retry && !(fcport->flags & FCF_ASYNC_SENT)) {
|
||||||
fcport->login_retry--;
|
fcport->login_retry--;
|
||||||
if (fcport->flags & FCF_FABRIC_DEVICE) {
|
if (fcport->flags & FCF_FABRIC_DEVICE) {
|
||||||
if (fcport->flags & FCF_FCP2_DEVICE)
|
ql_dbg(ql_dbg_disc, fcport->vha, 0xffff,
|
||||||
ha->isp_ops->fabric_logout(vha,
|
"%s %8phC DS %d LS %d\n", __func__,
|
||||||
fcport->loop_id,
|
fcport->port_name, fcport->disc_state,
|
||||||
fcport->d_id.b.domain,
|
fcport->fw_login_state);
|
||||||
fcport->d_id.b.area,
|
memset(&ea, 0, sizeof(ea));
|
||||||
fcport->d_id.b.al_pa);
|
ea.event = FCME_RELOGIN;
|
||||||
|
ea.fcport = fcport;
|
||||||
if (fcport->loop_id == FC_NO_LOOP_ID) {
|
qla2x00_fcport_event_handler(vha, &ea);
|
||||||
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 {
|
} 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
|
|
||||||
status = qla2x00_local_device_login(vha,
|
status = qla2x00_local_device_login(vha,
|
||||||
fcport);
|
fcport);
|
||||||
|
|
||||||
if (status == QLA_SUCCESS) {
|
if (status == QLA_SUCCESS) {
|
||||||
fcport->old_loop_id = fcport->loop_id;
|
fcport->old_loop_id = fcport->loop_id;
|
||||||
|
|
||||||
ql_dbg(ql_dbg_disc, vha, 0x2003,
|
ql_dbg(ql_dbg_disc, vha, 0x2003,
|
||||||
"Port login OK: logged in ID 0x%x.\n",
|
"Port login OK: logged in ID 0x%x.\n",
|
||||||
fcport->loop_id);
|
fcport->loop_id);
|
||||||
|
|
||||||
qla2x00_update_fcport(vha, fcport);
|
qla2x00_update_fcport(vha, fcport);
|
||||||
|
|
||||||
} else if (status == 1) {
|
} else if (status == 1) {
|
||||||
set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
|
set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
|
||||||
/* retry the login again */
|
/* retry the login again */
|
||||||
ql_dbg(ql_dbg_disc, vha, 0x2007,
|
ql_dbg(ql_dbg_disc, vha, 0x2007,
|
||||||
"Retrying %d login again loop_id 0x%x.\n",
|
"Retrying %d login again loop_id 0x%x.\n",
|
||||||
fcport->login_retry, fcport->loop_id);
|
fcport->login_retry,
|
||||||
|
fcport->loop_id);
|
||||||
} else {
|
} else {
|
||||||
fcport->login_retry = 0;
|
fcport->login_retry = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fcport->login_retry == 0 && status != QLA_SUCCESS)
|
if (fcport->login_retry == 0 &&
|
||||||
|
status != QLA_SUCCESS)
|
||||||
qla2x00_clear_loop_id(fcport);
|
qla2x00_clear_loop_id(fcport);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
|
if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -5182,7 +5282,8 @@ qla2x00_disable_board_on_pci_error(struct work_struct *work)
|
||||||
struct pci_dev *pdev = ha->pdev;
|
struct pci_dev *pdev = ha->pdev;
|
||||||
scsi_qla_host_t *base_vha = pci_get_drvdata(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.
|
* where it was set first.
|
||||||
*/
|
*/
|
||||||
if (test_bit(UNLOADING, &base_vha->dpc_flags))
|
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,
|
ql_log(ql_log_warn, base_vha, 0x015b,
|
||||||
"Disabling adapter.\n");
|
"Disabling adapter.\n");
|
||||||
|
|
||||||
|
qla2x00_wait_for_sess_deletion(base_vha);
|
||||||
|
|
||||||
set_bit(UNLOADING, &base_vha->dpc_flags);
|
set_bit(UNLOADING, &base_vha->dpc_flags);
|
||||||
|
|
||||||
qla2x00_delete_all_vps(ha, base_vha);
|
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 */
|
/* Protected by hardware_lock */
|
||||||
struct list_head del_sess_list;
|
struct list_head del_sess_list;
|
||||||
struct delayed_work sess_del_work;
|
|
||||||
|
|
||||||
spinlock_t sess_work_lock;
|
spinlock_t sess_work_lock;
|
||||||
struct list_head sess_works_list;
|
struct list_head sess_works_list;
|
||||||
|
@ -823,13 +822,6 @@ struct qla_tgt_sess_op {
|
||||||
bool aborted;
|
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 {
|
enum trace_flags {
|
||||||
TRC_NEW_CMD = BIT_0,
|
TRC_NEW_CMD = BIT_0,
|
||||||
TRC_DO_WORK = BIT_1,
|
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)
|
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)
|
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)
|
static inline void qla_reverse_ini_mode(struct scsi_qla_host *ha)
|
||||||
|
|
Loading…
Reference in a new issue