1
0
Fork 0

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>
hifive-unleashed-5.1
Quinn Tran 2017-01-19 22:28:00 -08:00 committed by Nicholas Bellinger
parent 5d964837c6
commit 726b854870
13 changed files with 3111 additions and 984 deletions

View File

@ -2163,6 +2163,9 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
clear_bit(vha->vp_idx, ha->vp_idx_map);
mutex_unlock(&ha->vport_lock);
dma_free_coherent(&ha->pdev->dev, vha->gnl.size, vha->gnl.l,
vha->gnl.ldma);
if (vha->qpair->vp_idx == vha->vp_idx) {
if (qla2xxx_delete_qpair(vha, vha->qpair) != QLA_SUCCESS)
ql_log(ql_log_warn, vha, 0x7087,

View File

@ -55,6 +55,8 @@
#include "qla_settings.h"
#define MODE_DUAL (MODE_TARGET | MODE_INITIATOR)
/*
* Data bit definitions
*/
@ -251,6 +253,14 @@
#define MAX_CMDSZ 16 /* SCSI maximum CDB size. */
#include "qla_fw.h"
struct name_list_extended {
struct get_name_list_extended *l;
dma_addr_t ldma;
struct list_head fcports; /* protect by sess_list */
u32 size;
u8 sent;
};
/*
* Timeout timer counts in seconds
*/
@ -309,6 +319,17 @@ struct els_logo_payload {
uint8_t wwpn[WWN_SIZE];
};
struct ct_arg {
void *iocb;
u16 nport_handle;
dma_addr_t req_dma;
dma_addr_t rsp_dma;
u32 req_size;
u32 rsp_size;
void *req;
void *rsp;
};
/*
* SRB extensions.
*/
@ -320,6 +341,7 @@ struct srb_iocb {
#define SRB_LOGIN_COND_PLOGI BIT_1
#define SRB_LOGIN_SKIP_PRLI BIT_2
uint16_t data[2];
u32 iop[2];
} logio;
struct {
#define ELS_DCMD_TIMEOUT 20
@ -372,6 +394,16 @@ struct srb_iocb {
__le16 comp_status;
struct completion comp;
} abt;
struct ct_arg ctarg;
struct {
__le16 in_mb[28]; /* fr fw */
__le16 out_mb[28]; /* to fw */
void *out, *in;
dma_addr_t out_dma, in_dma;
} mbx;
struct {
struct imm_ntfy_from_isp *ntfy;
} nack;
} u;
struct timer_list timer;
@ -392,16 +424,24 @@ struct srb_iocb {
#define SRB_FXIOCB_BCMD 11
#define SRB_ABT_CMD 12
#define SRB_ELS_DCMD 13
#define SRB_MB_IOCB 14
#define SRB_CT_PTHRU_CMD 15
#define SRB_NACK_PLOGI 16
#define SRB_NACK_PRLI 17
#define SRB_NACK_LOGO 18
typedef struct srb {
atomic_t ref_count;
struct fc_port *fcport;
void *vha;
uint32_t handle;
uint16_t flags;
uint16_t type;
char *name;
int iocbs;
struct qla_qpair *qpair;
u32 gen1; /* scratch */
u32 gen2; /* scratch */
union {
struct srb_iocb iocb_cmd;
struct bsg_job *bsg_job;
@ -2101,6 +2141,18 @@ typedef struct {
#define FC4_TYPE_OTHER 0x0
#define FC4_TYPE_UNKNOWN 0xff
/* mailbox command 4G & above */
struct mbx_24xx_entry {
uint8_t entry_type;
uint8_t entry_count;
uint8_t sys_define1;
uint8_t entry_status;
uint32_t handle;
uint16_t mb[28];
};
#define IOCB_SIZE 64
/*
* Fibre channel port type.
*/
@ -2113,6 +2165,12 @@ typedef enum {
FCT_TARGET
} fc_port_type_t;
enum qla_sess_deletion {
QLA_SESS_DELETION_NONE = 0,
QLA_SESS_DELETION_IN_PROGRESS,
QLA_SESS_DELETED,
};
enum qlt_plogi_link_t {
QLT_PLOGI_LINK_SAME_WWN,
QLT_PLOGI_LINK_CONFLICT,
@ -2124,6 +2182,48 @@ struct qlt_plogi_ack_t {
struct imm_ntfy_from_isp iocb;
port_id_t id;
int ref_count;
void *fcport;
};
struct ct_sns_desc {
struct ct_sns_pkt *ct_sns;
dma_addr_t ct_sns_dma;
};
enum discovery_state {
DSC_DELETED,
DSC_GID_PN,
DSC_GNL,
DSC_LOGIN_PEND,
DSC_LOGIN_FAILED,
DSC_GPDB,
DSC_GPSC,
DSC_UPD_FCPORT,
DSC_LOGIN_COMPLETE,
DSC_DELETE_PEND,
};
enum login_state { /* FW control Target side */
DSC_LS_LLIOCB_SENT = 2,
DSC_LS_PLOGI_PEND,
DSC_LS_PLOGI_COMP,
DSC_LS_PRLI_PEND,
DSC_LS_PRLI_COMP,
DSC_LS_PORT_UNAVAIL,
DSC_LS_PRLO_PEND = 9,
DSC_LS_LOGO_PEND,
};
enum fcport_mgt_event {
FCME_RELOGIN = 1,
FCME_RSCN,
FCME_GIDPN_DONE,
FCME_PLOGI_DONE, /* Initiator side sent LLIOCB */
FCME_GNL_DONE,
FCME_GPSC_DONE,
FCME_GPDB_DONE,
FCME_GPNID_DONE,
FCME_DELETE_DONE,
};
/*
@ -2143,9 +2243,13 @@ typedef struct fc_port {
unsigned int deleted:2;
unsigned int local:1;
unsigned int logout_on_delete:1;
unsigned int logo_ack_needed:1;
unsigned int keep_nport_handle:1;
unsigned int send_els_logo:1;
unsigned int login_pause:1;
unsigned int login_succ:1;
struct fc_port *conflict;
unsigned char logout_completed;
int generation;
@ -2186,8 +2290,30 @@ typedef struct fc_port {
unsigned long retry_delay_timestamp;
struct qla_tgt_sess *tgt_session;
struct ct_sns_desc ct_desc;
enum discovery_state disc_state;
enum login_state fw_login_state;
u32 login_gen, last_login_gen;
u32 rscn_gen, last_rscn_gen;
u32 chip_reset;
struct list_head gnl_entry;
struct work_struct del_work;
u8 iocb[IOCB_SIZE];
} fc_port_t;
#define QLA_FCPORT_SCAN 1
#define QLA_FCPORT_FOUND 2
struct event_arg {
enum fcport_mgt_event event;
fc_port_t *fcport;
srb_t *sp;
port_id_t id;
u16 data[2], rc;
u8 port_name[WWN_SIZE];
u32 iop[2];
};
#include "qla_mr.h"
/*
@ -2265,6 +2391,10 @@ static const char * const port_state_str[] = {
#define GFT_ID_REQ_SIZE (16 + 4)
#define GFT_ID_RSP_SIZE (16 + 32)
#define GID_PN_CMD 0x121
#define GID_PN_REQ_SIZE (16 + 8)
#define GID_PN_RSP_SIZE (16 + 4)
#define RFT_ID_CMD 0x217
#define RFT_ID_REQ_SIZE (16 + 4 + 32)
#define RFT_ID_RSP_SIZE 16
@ -2590,6 +2720,10 @@ struct ct_sns_req {
uint8_t reserved;
uint8_t port_name[3];
} gff_id;
struct {
uint8_t port_name[8];
} gid_pn;
} req;
};
@ -2669,6 +2803,10 @@ struct ct_sns_rsp {
struct {
uint8_t fc4_features[128];
} gff_id;
struct {
uint8_t reserved;
uint8_t port_id[3];
} gid_pn;
} rsp;
};
@ -2810,11 +2948,11 @@ struct isp_operations {
uint16_t (*calc_req_entries) (uint16_t);
void (*build_iocbs) (srb_t *, cmd_entry_t *, uint16_t);
void * (*prep_ms_iocb) (struct scsi_qla_host *, uint32_t, uint32_t);
void * (*prep_ms_fdmi_iocb) (struct scsi_qla_host *, uint32_t,
void *(*prep_ms_iocb) (struct scsi_qla_host *, struct ct_arg *);
void *(*prep_ms_fdmi_iocb) (struct scsi_qla_host *, uint32_t,
uint32_t);
uint8_t * (*read_nvram) (struct scsi_qla_host *, uint8_t *,
uint8_t *(*read_nvram) (struct scsi_qla_host *, uint8_t *,
uint32_t, uint32_t);
int (*write_nvram) (struct scsi_qla_host *, uint8_t *, uint32_t,
uint32_t);
@ -2876,13 +3014,21 @@ enum qla_work_type {
QLA_EVT_AEN,
QLA_EVT_IDC_ACK,
QLA_EVT_ASYNC_LOGIN,
QLA_EVT_ASYNC_LOGIN_DONE,
QLA_EVT_ASYNC_LOGOUT,
QLA_EVT_ASYNC_LOGOUT_DONE,
QLA_EVT_ASYNC_ADISC,
QLA_EVT_ASYNC_ADISC_DONE,
QLA_EVT_UEVENT,
QLA_EVT_AENFX,
QLA_EVT_GIDPN,
QLA_EVT_GPNID,
QLA_EVT_GPNID_DONE,
QLA_EVT_NEW_SESS,
QLA_EVT_GPDB,
QLA_EVT_GPSC,
QLA_EVT_UPD_FCPORT,
QLA_EVT_GNL,
QLA_EVT_NACK,
};
@ -2918,6 +3064,23 @@ struct qla_work_evt {
struct {
srb_t *sp;
} iosb;
struct {
port_id_t id;
} gpnid;
struct {
port_id_t id;
u8 port_name[8];
void *pla;
} new_sess;
struct { /*Get PDB, Get Speed, update fcport, gnl, gidpn */
fc_port_t *fcport;
u8 opt;
} fcport;
struct {
fc_port_t *fcport;
u8 iocb[IOCB_SIZE];
int type;
} nack;
} u;
};
@ -3899,6 +4062,10 @@ typedef struct scsi_qla_host {
struct qla8044_reset_template reset_tmplt;
struct qla_tgt_counters tgt_counters;
uint16_t bbcr;
struct name_list_extended gnl;
/* Count of active session/fcport */
int fcport_count;
wait_queue_head_t fcport_waitQ;
} scsi_qla_host_t;
struct qla27xx_image_status {

View File

@ -72,6 +72,37 @@ struct port_database_24xx {
uint8_t reserved_3[24];
};
/*
* MB 75h returns a list of DB entries similar to port_database_24xx(64B).
* However, in this case it returns 1st 40 bytes.
*/
struct get_name_list_extended {
__le16 flags;
u8 current_login_state;
u8 last_login_state;
u8 hard_address[3];
u8 reserved_1;
u8 port_id[3];
u8 sequence_id;
__le16 port_timer;
__le16 nport_handle; /* N_PORT handle. */
__le16 receive_data_size;
__le16 reserved_2;
/* PRLI SVC Param are Big endian */
u8 prli_svc_param_word_0[2]; /* Bits 15-0 of word 0 */
u8 prli_svc_param_word_3[2]; /* Bits 15-0 of word 3 */
u8 port_name[WWN_SIZE];
u8 node_name[WWN_SIZE];
};
/* MB 75h: This is the short version of the database */
struct get_name_list {
u8 port_node_name[WWN_SIZE]; /* B7 most sig, B0 least sig */
__le16 nport_handle;
u8 reserved;
};
struct vp_database_24xx {
uint16_t vp_status;
uint8_t options;

View File

@ -73,6 +73,10 @@ extern void qla2x00_async_logout_done(struct scsi_qla_host *, fc_port_t *,
uint16_t *);
extern void qla2x00_async_adisc_done(struct scsi_qla_host *, fc_port_t *,
uint16_t *);
struct qla_work_evt *qla2x00_alloc_work(struct scsi_qla_host *,
enum qla_work_type);
extern int qla24xx_async_gnl(struct scsi_qla_host *, fc_port_t *);
int qla2x00_post_work(struct scsi_qla_host *vha, struct qla_work_evt *e);
extern void *qla2x00_alloc_iocbs(struct scsi_qla_host *, srb_t *);
extern void *qla2x00_alloc_iocbs_ready(struct scsi_qla_host *, srb_t *);
extern int qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *, fc_port_t *);
@ -94,6 +98,13 @@ extern uint8_t qla27xx_find_valid_image(struct scsi_qla_host *);
extern struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *,
int, int);
extern int qla2xxx_delete_qpair(struct scsi_qla_host *, struct qla_qpair *);
void qla2x00_fcport_event_handler(scsi_qla_host_t *, struct event_arg *);
int qla24xx_async_gpdb(struct scsi_qla_host *, fc_port_t *, u8);
int qla24xx_async_notify_ack(scsi_qla_host_t *, fc_port_t *,
struct imm_ntfy_from_isp *, int);
int qla24xx_post_newsess_work(struct scsi_qla_host *, port_id_t *, u8 *,
void *);
int qla24xx_fcport_handle_login(struct scsi_qla_host *, fc_port_t *);
/*
* Global Data in qla_os.c source file.
@ -135,8 +146,6 @@ extern int qla2x00_post_aen_work(struct scsi_qla_host *, enum
extern int qla2x00_post_idc_ack_work(struct scsi_qla_host *, uint16_t *);
extern int qla2x00_post_async_login_work(struct scsi_qla_host *, fc_port_t *,
uint16_t *);
extern int qla2x00_post_async_login_done_work(struct scsi_qla_host *,
fc_port_t *, uint16_t *);
extern int qla2x00_post_async_logout_work(struct scsi_qla_host *, fc_port_t *,
uint16_t *);
extern int qla2x00_post_async_logout_done_work(struct scsi_qla_host *,
@ -179,6 +188,10 @@ extern void qla2x00_disable_board_on_pci_error(struct work_struct *);
extern void qla2x00_sp_compl(void *, void *, int);
extern void qla2xxx_qpair_sp_free_dma(void *, void *);
extern void qla2xxx_qpair_sp_compl(void *, void *, int);
extern int qla24xx_post_upd_fcport_work(struct scsi_qla_host *, fc_port_t *);
void qla2x00_handle_login_done_event(struct scsi_qla_host *, fc_port_t *,
uint16_t *);
int qla24xx_post_gnl_work(struct scsi_qla_host *, fc_port_t *);
/*
* Global Functions in qla_mid.c source file.
@ -301,9 +314,6 @@ qla2x00_get_retry_cnt(scsi_qla_host_t *, uint8_t *, uint8_t *, uint16_t *);
extern int
qla2x00_init_firmware(scsi_qla_host_t *, uint16_t);
extern int
qla2x00_get_node_name_list(scsi_qla_host_t *, void **, int *);
extern int
qla2x00_get_port_database(scsi_qla_host_t *, fc_port_t *, uint8_t);
@ -483,6 +493,9 @@ qla2x00_process_completed_request(struct scsi_qla_host *, struct req_que *,
uint32_t);
extern irqreturn_t
qla2xxx_msix_rsp_q(int irq, void *dev_id);
fc_port_t *qla2x00_find_fcport_by_loopid(scsi_qla_host_t *, uint16_t);
fc_port_t *qla2x00_find_fcport_by_wwpn(scsi_qla_host_t *, u8 *, u8);
fc_port_t *qla2x00_find_fcport_by_nportid(scsi_qla_host_t *, port_id_t *, u8);
/*
* Global Function Prototypes in qla_sup.c source file.
@ -574,8 +587,8 @@ extern void qla2xxx_dump_post_process(scsi_qla_host_t *, int);
/*
* Global Function Prototypes in qla_gs.c source file.
*/
extern void *qla2x00_prep_ms_iocb(scsi_qla_host_t *, uint32_t, uint32_t);
extern void *qla24xx_prep_ms_iocb(scsi_qla_host_t *, uint32_t, uint32_t);
extern void *qla2x00_prep_ms_iocb(scsi_qla_host_t *, struct ct_arg *);
extern void *qla24xx_prep_ms_iocb(scsi_qla_host_t *, struct ct_arg *);
extern int qla2x00_ga_nxt(scsi_qla_host_t *, fc_port_t *);
extern int qla2x00_gid_pt(scsi_qla_host_t *, sw_info_t *);
extern int qla2x00_gpn_id(scsi_qla_host_t *, sw_info_t *);
@ -591,6 +604,23 @@ extern int qla2x00_fdmi_register(scsi_qla_host_t *);
extern int qla2x00_gfpn_id(scsi_qla_host_t *, sw_info_t *);
extern int qla2x00_gpsc(scsi_qla_host_t *, sw_info_t *);
extern void qla2x00_get_sym_node_name(scsi_qla_host_t *, uint8_t *, size_t);
extern int qla2x00_chk_ms_status(scsi_qla_host_t *, ms_iocb_entry_t *,
struct ct_sns_rsp *, const char *);
extern void qla2x00_async_iocb_timeout(void *data);
extern int qla24xx_async_gidpn(scsi_qla_host_t *, fc_port_t *);
int qla24xx_post_gidpn_work(struct scsi_qla_host *, fc_port_t *);
void qla24xx_handle_gidpn_event(scsi_qla_host_t *, struct event_arg *);
extern void qla2x00_free_fcport(fc_port_t *);
extern int qla24xx_post_gpnid_work(struct scsi_qla_host *, port_id_t *);
extern int qla24xx_async_gpnid(scsi_qla_host_t *, port_id_t *);
void qla24xx_async_gpnid_done(scsi_qla_host_t *, srb_t*);
void qla24xx_handle_gpnid_event(scsi_qla_host_t *, struct event_arg *);
int qla24xx_post_gpsc_work(struct scsi_qla_host *, fc_port_t *);
int qla24xx_async_gpsc(scsi_qla_host_t *, fc_port_t *);
int qla2x00_mgmt_svr_login(scsi_qla_host_t *);
/*
* Global Function Prototypes in qla_attr.c source file.
@ -803,4 +833,16 @@ extern int qla_get_exchoffld_status(scsi_qla_host_t *, uint16_t *, uint16_t *);
extern int qla_set_exchoffld_mem_cfg(scsi_qla_host_t *, dma_addr_t);
extern void qlt_handle_abts_recv(struct scsi_qla_host *, response_t *);
int qla24xx_async_notify_ack(scsi_qla_host_t *, fc_port_t *,
struct imm_ntfy_from_isp *, int);
void qla24xx_do_nack_work(struct scsi_qla_host *, struct qla_work_evt *);
void qlt_plogi_ack_link(struct scsi_qla_host *, struct qlt_plogi_ack_t *,
struct fc_port *, enum qlt_plogi_link_t);
void qlt_plogi_ack_unref(struct scsi_qla_host *, struct qlt_plogi_ack_t *);
extern void qlt_schedule_sess_for_deletion(struct fc_port *, bool);
extern void qlt_schedule_sess_for_deletion_lock(struct fc_port *);
extern struct fc_port *qlt_find_sess_invalidate_other(scsi_qla_host_t *,
uint64_t wwn, port_id_t port_id, uint16_t loop_id, struct fc_port **);
void qla24xx_delete_sess_fn(struct work_struct *);
#endif /* _QLA_GBL_H */

View File

@ -24,12 +24,12 @@ static int qla2x00_sns_rnn_id(scsi_qla_host_t *);
* Returns a pointer to the @ha's ms_iocb.
*/
void *
qla2x00_prep_ms_iocb(scsi_qla_host_t *vha, uint32_t req_size, uint32_t rsp_size)
qla2x00_prep_ms_iocb(scsi_qla_host_t *vha, struct ct_arg *arg)
{
struct qla_hw_data *ha = vha->hw;
ms_iocb_entry_t *ms_pkt;
ms_pkt = ha->ms_iocb;
ms_pkt = (ms_iocb_entry_t *)arg->iocb;
memset(ms_pkt, 0, sizeof(ms_iocb_entry_t));
ms_pkt->entry_type = MS_IOCB_TYPE;
@ -39,15 +39,15 @@ qla2x00_prep_ms_iocb(scsi_qla_host_t *vha, uint32_t req_size, uint32_t rsp_size)
ms_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
ms_pkt->cmd_dsd_count = cpu_to_le16(1);
ms_pkt->total_dsd_count = cpu_to_le16(2);
ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size);
ms_pkt->req_bytecount = cpu_to_le32(req_size);
ms_pkt->rsp_bytecount = cpu_to_le32(arg->rsp_size);
ms_pkt->req_bytecount = cpu_to_le32(arg->req_size);
ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(arg->req_dma));
ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(arg->req_dma));
ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(arg->rsp_dma));
ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(arg->rsp_dma));
ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount;
vha->qla_stats.control_requests++;
@ -64,29 +64,29 @@ qla2x00_prep_ms_iocb(scsi_qla_host_t *vha, uint32_t req_size, uint32_t rsp_size)
* Returns a pointer to the @ha's ms_iocb.
*/
void *
qla24xx_prep_ms_iocb(scsi_qla_host_t *vha, uint32_t req_size, uint32_t rsp_size)
qla24xx_prep_ms_iocb(scsi_qla_host_t *vha, struct ct_arg *arg)
{
struct qla_hw_data *ha = vha->hw;
struct ct_entry_24xx *ct_pkt;
ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
ct_pkt = (struct ct_entry_24xx *)arg->iocb;
memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
ct_pkt->entry_type = CT_IOCB_TYPE;
ct_pkt->entry_count = 1;
ct_pkt->nport_handle = cpu_to_le16(NPH_SNS);
ct_pkt->nport_handle = cpu_to_le16(arg->nport_handle);
ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
ct_pkt->cmd_dsd_count = cpu_to_le16(1);
ct_pkt->rsp_dsd_count = cpu_to_le16(1);
ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
ct_pkt->rsp_byte_count = cpu_to_le32(arg->rsp_size);
ct_pkt->cmd_byte_count = cpu_to_le32(arg->req_size);
ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(arg->req_dma));
ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(arg->req_dma));
ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(arg->rsp_dma));
ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(arg->rsp_dma));
ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
ct_pkt->vp_index = vha->vp_idx;
@ -117,7 +117,7 @@ qla2x00_prep_ct_req(struct ct_sns_pkt *p, uint16_t cmd, uint16_t rsp_size)
return &p->p.req;
}
static int
int
qla2x00_chk_ms_status(scsi_qla_host_t *vha, ms_iocb_entry_t *ms_pkt,
struct ct_sns_rsp *ct_rsp, const char *routine)
{
@ -183,14 +183,21 @@ qla2x00_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
struct ct_sns_req *ct_req;
struct ct_sns_rsp *ct_rsp;
struct qla_hw_data *ha = vha->hw;
struct ct_arg arg;
if (IS_QLA2100(ha) || IS_QLA2200(ha))
return qla2x00_sns_ga_nxt(vha, fcport);
arg.iocb = ha->ms_iocb;
arg.req_dma = ha->ct_sns_dma;
arg.rsp_dma = ha->ct_sns_dma;
arg.req_size = GA_NXT_REQ_SIZE;
arg.rsp_size = GA_NXT_RSP_SIZE;
arg.nport_handle = NPH_SNS;
/* Issue GA_NXT */
/* Prepare common MS IOCB */
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GA_NXT_REQ_SIZE,
GA_NXT_RSP_SIZE);
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req(ha->ct_sns, GA_NXT_CMD,
@ -269,16 +276,24 @@ qla2x00_gid_pt(scsi_qla_host_t *vha, sw_info_t *list)
struct ct_sns_gid_pt_data *gid_data;
struct qla_hw_data *ha = vha->hw;
uint16_t gid_pt_rsp_size;
struct ct_arg arg;
if (IS_QLA2100(ha) || IS_QLA2200(ha))
return qla2x00_sns_gid_pt(vha, list);
gid_data = NULL;
gid_pt_rsp_size = qla2x00_gid_pt_rsp_size(vha);
arg.iocb = ha->ms_iocb;
arg.req_dma = ha->ct_sns_dma;
arg.rsp_dma = ha->ct_sns_dma;
arg.req_size = GID_PT_REQ_SIZE;
arg.rsp_size = gid_pt_rsp_size;
arg.nport_handle = NPH_SNS;
/* Issue GID_PT */
/* Prepare common MS IOCB */
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GID_PT_REQ_SIZE,
gid_pt_rsp_size);
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req(ha->ct_sns, GID_PT_CMD, gid_pt_rsp_size);
@ -344,15 +359,22 @@ qla2x00_gpn_id(scsi_qla_host_t *vha, sw_info_t *list)
struct ct_sns_req *ct_req;
struct ct_sns_rsp *ct_rsp;
struct qla_hw_data *ha = vha->hw;
struct ct_arg arg;
if (IS_QLA2100(ha) || IS_QLA2200(ha))
return qla2x00_sns_gpn_id(vha, list);
arg.iocb = ha->ms_iocb;
arg.req_dma = ha->ct_sns_dma;
arg.rsp_dma = ha->ct_sns_dma;
arg.req_size = GPN_ID_REQ_SIZE;
arg.rsp_size = GPN_ID_RSP_SIZE;
arg.nport_handle = NPH_SNS;
for (i = 0; i < ha->max_fibre_devices; i++) {
/* Issue GPN_ID */
/* Prepare common MS IOCB */
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GPN_ID_REQ_SIZE,
GPN_ID_RSP_SIZE);
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req(ha->ct_sns, GPN_ID_CMD,
@ -406,15 +428,22 @@ qla2x00_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
ms_iocb_entry_t *ms_pkt;
struct ct_sns_req *ct_req;
struct ct_sns_rsp *ct_rsp;
struct ct_arg arg;
if (IS_QLA2100(ha) || IS_QLA2200(ha))
return qla2x00_sns_gnn_id(vha, list);
arg.iocb = ha->ms_iocb;
arg.req_dma = ha->ct_sns_dma;
arg.rsp_dma = ha->ct_sns_dma;
arg.req_size = GNN_ID_REQ_SIZE;
arg.rsp_size = GNN_ID_RSP_SIZE;
arg.nport_handle = NPH_SNS;
for (i = 0; i < ha->max_fibre_devices; i++) {
/* Issue GNN_ID */
/* Prepare common MS IOCB */
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GNN_ID_REQ_SIZE,
GNN_ID_RSP_SIZE);
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req(ha->ct_sns, GNN_ID_CMD,
@ -473,14 +502,21 @@ qla2x00_rft_id(scsi_qla_host_t *vha)
ms_iocb_entry_t *ms_pkt;
struct ct_sns_req *ct_req;
struct ct_sns_rsp *ct_rsp;
struct ct_arg arg;
if (IS_QLA2100(ha) || IS_QLA2200(ha))
return qla2x00_sns_rft_id(vha);
arg.iocb = ha->ms_iocb;
arg.req_dma = ha->ct_sns_dma;
arg.rsp_dma = ha->ct_sns_dma;
arg.req_size = RFT_ID_REQ_SIZE;
arg.rsp_size = RFT_ID_RSP_SIZE;
arg.nport_handle = NPH_SNS;
/* Issue RFT_ID */
/* Prepare common MS IOCB */
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, RFT_ID_REQ_SIZE,
RFT_ID_RSP_SIZE);
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req(ha->ct_sns, RFT_ID_CMD,
@ -526,6 +562,7 @@ qla2x00_rff_id(scsi_qla_host_t *vha)
ms_iocb_entry_t *ms_pkt;
struct ct_sns_req *ct_req;
struct ct_sns_rsp *ct_rsp;
struct ct_arg arg;
if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
ql_dbg(ql_dbg_disc, vha, 0x2046,
@ -533,10 +570,16 @@ qla2x00_rff_id(scsi_qla_host_t *vha)
return (QLA_SUCCESS);
}
arg.iocb = ha->ms_iocb;
arg.req_dma = ha->ct_sns_dma;
arg.rsp_dma = ha->ct_sns_dma;
arg.req_size = RFF_ID_REQ_SIZE;
arg.rsp_size = RFF_ID_RSP_SIZE;
arg.nport_handle = NPH_SNS;
/* Issue RFF_ID */
/* Prepare common MS IOCB */
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, RFF_ID_REQ_SIZE,
RFF_ID_RSP_SIZE);
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req(ha->ct_sns, RFF_ID_CMD,
@ -584,14 +627,21 @@ qla2x00_rnn_id(scsi_qla_host_t *vha)
ms_iocb_entry_t *ms_pkt;
struct ct_sns_req *ct_req;
struct ct_sns_rsp *ct_rsp;
struct ct_arg arg;
if (IS_QLA2100(ha) || IS_QLA2200(ha))
return qla2x00_sns_rnn_id(vha);
arg.iocb = ha->ms_iocb;
arg.req_dma = ha->ct_sns_dma;
arg.rsp_dma = ha->ct_sns_dma;
arg.req_size = RNN_ID_REQ_SIZE;
arg.rsp_size = RNN_ID_RSP_SIZE;
arg.nport_handle = NPH_SNS;
/* Issue RNN_ID */
/* Prepare common MS IOCB */
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, RNN_ID_REQ_SIZE,
RNN_ID_RSP_SIZE);
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req(ha->ct_sns, RNN_ID_CMD, RNN_ID_RSP_SIZE);
@ -651,6 +701,7 @@ qla2x00_rsnn_nn(scsi_qla_host_t *vha)
ms_iocb_entry_t *ms_pkt;
struct ct_sns_req *ct_req;
struct ct_sns_rsp *ct_rsp;
struct ct_arg arg;
if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
ql_dbg(ql_dbg_disc, vha, 0x2050,
@ -658,10 +709,17 @@ qla2x00_rsnn_nn(scsi_qla_host_t *vha)
return (QLA_SUCCESS);
}
arg.iocb = ha->ms_iocb;
arg.req_dma = ha->ct_sns_dma;
arg.rsp_dma = ha->ct_sns_dma;
arg.req_size = 0;
arg.rsp_size = RSNN_NN_RSP_SIZE;
arg.nport_handle = NPH_SNS;
/* Issue RSNN_NN */
/* Prepare common MS IOCB */
/* Request size adjusted after CT preparation */
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, 0, RSNN_NN_RSP_SIZE);
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req(ha->ct_sns, RSNN_NN_CMD,
@ -1103,7 +1161,7 @@ qla2x00_sns_rnn_id(scsi_qla_host_t *vha)
*
* Returns 0 on success.
*/
static int
int
qla2x00_mgmt_svr_login(scsi_qla_host_t *vha)
{
int ret, rval;
@ -2425,15 +2483,22 @@ qla2x00_gfpn_id(scsi_qla_host_t *vha, sw_info_t *list)
ms_iocb_entry_t *ms_pkt;
struct ct_sns_req *ct_req;
struct ct_sns_rsp *ct_rsp;
struct ct_arg arg;
if (!IS_IIDMA_CAPABLE(ha))
return QLA_FUNCTION_FAILED;
arg.iocb = ha->ms_iocb;
arg.req_dma = ha->ct_sns_dma;
arg.rsp_dma = ha->ct_sns_dma;
arg.req_size = GFPN_ID_REQ_SIZE;
arg.rsp_size = GFPN_ID_RSP_SIZE;
arg.nport_handle = NPH_SNS;
for (i = 0; i < ha->max_fibre_devices; i++) {
/* Issue GFPN_ID */
/* Prepare common MS IOCB */
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GFPN_ID_REQ_SIZE,
GFPN_ID_RSP_SIZE);
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req(ha->ct_sns, GFPN_ID_CMD,
@ -2471,36 +2536,6 @@ qla2x00_gfpn_id(scsi_qla_host_t *vha, sw_info_t *list)
return (rval);
}
static inline void *
qla24xx_prep_ms_fm_iocb(scsi_qla_host_t *vha, uint32_t req_size,
uint32_t rsp_size)
{
struct ct_entry_24xx *ct_pkt;
struct qla_hw_data *ha = vha->hw;
ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;
memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));
ct_pkt->entry_type = CT_IOCB_TYPE;
ct_pkt->entry_count = 1;
ct_pkt->nport_handle = cpu_to_le16(vha->mgmt_svr_loop_id);
ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
ct_pkt->cmd_dsd_count = cpu_to_le16(1);
ct_pkt->rsp_dsd_count = cpu_to_le16(1);
ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
ct_pkt->vp_index = vha->vp_idx;
return ct_pkt;
}
static inline struct ct_sns_req *
qla24xx_prep_ct_fm_req(struct ct_sns_pkt *p, uint16_t cmd,
@ -2530,9 +2565,10 @@ qla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list)
int rval;
uint16_t i;
struct qla_hw_data *ha = vha->hw;
ms_iocb_entry_t *ms_pkt;
ms_iocb_entry_t *ms_pkt;
struct ct_sns_req *ct_req;
struct ct_sns_rsp *ct_rsp;
struct ct_arg arg;
if (!IS_IIDMA_CAPABLE(ha))
return QLA_FUNCTION_FAILED;
@ -2543,11 +2579,17 @@ qla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list)
if (rval)
return rval;
arg.iocb = ha->ms_iocb;
arg.req_dma = ha->ct_sns_dma;
arg.rsp_dma = ha->ct_sns_dma;
arg.req_size = GPSC_REQ_SIZE;
arg.rsp_size = GPSC_RSP_SIZE;
arg.nport_handle = vha->mgmt_svr_loop_id;
for (i = 0; i < ha->max_fibre_devices; i++) {
/* Issue GFPN_ID */
/* Prepare common MS IOCB */
ms_pkt = qla24xx_prep_ms_fm_iocb(vha, GPSC_REQ_SIZE,
GPSC_RSP_SIZE);
ms_pkt = qla24xx_prep_ms_iocb(vha, &arg);
/* Prepare CT request */
ct_req = qla24xx_prep_ct_fm_req(ha->ct_sns, GPSC_CMD,
@ -2641,6 +2683,7 @@ qla2x00_gff_id(scsi_qla_host_t *vha, sw_info_t *list)
struct ct_sns_rsp *ct_rsp;
struct qla_hw_data *ha = vha->hw;
uint8_t fcp_scsi_features = 0;
struct ct_arg arg;
for (i = 0; i < ha->max_fibre_devices; i++) {
/* Set default FC4 Type as UNKNOWN so the default is to
@ -2651,9 +2694,15 @@ qla2x00_gff_id(scsi_qla_host_t *vha, sw_info_t *list)
if (!IS_FWI2_CAPABLE(ha))
continue;
arg.iocb = ha->ms_iocb;
arg.req_dma = ha->ct_sns_dma;
arg.rsp_dma = ha->ct_sns_dma;
arg.req_size = GFF_ID_REQ_SIZE;
arg.rsp_size = GFF_ID_RSP_SIZE;
arg.nport_handle = NPH_SNS;
/* Prepare common MS IOCB */
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, GFF_ID_REQ_SIZE,
GFF_ID_RSP_SIZE);
ms_pkt = ha->isp_ops->prep_ms_iocb(vha, &arg);
/* Prepare CT request */
ct_req = qla2x00_prep_ct_req(ha->ct_sns, GFF_ID_CMD,
@ -2692,3 +2741,536 @@ qla2x00_gff_id(scsi_qla_host_t *vha, sw_info_t *list)
break;
}
}
/* GID_PN completion processing. */
void qla24xx_handle_gidpn_event(scsi_qla_host_t *vha, struct event_arg *ea)
{
fc_port_t *fcport = ea->fcport;
ql_dbg(ql_dbg_disc, vha, 0xffff,
"%s %8phC login state %d \n",
__func__, fcport->port_name, fcport->fw_login_state);
if (ea->sp->gen2 != fcport->login_gen) {
/* PLOGI/PRLI/LOGO came in while cmd was out.*/
ql_dbg(ql_dbg_disc, vha, 0xffff,
"%s %8phC generation changed rscn %d|%d login %d|%d \n",
__func__, fcport->port_name, fcport->last_rscn_gen,
fcport->rscn_gen, fcport->last_login_gen, fcport->login_gen);
return;
}
if (!ea->rc) {
if (ea->sp->gen1 == fcport->rscn_gen) {
fcport->scan_state = QLA_FCPORT_FOUND;
fcport->flags |= FCF_FABRIC_DEVICE;
if (fcport->d_id.b24 == ea->id.b24) {
/* cable plugged into the same place */
switch (vha->host->active_mode) {
case MODE_TARGET:
/* NOOP. let the other guy login to us.*/
break;
case MODE_INITIATOR:
case MODE_DUAL:
default:
if (atomic_read(&fcport->state) ==
FCS_ONLINE)
break;
ql_dbg(ql_dbg_disc, vha, 0xffff,
"%s %d %8phC post gnl\n",
__func__, __LINE__, fcport->port_name);
qla24xx_post_gnl_work(vha, fcport);
break;
}
} else { /* fcport->d_id.b24 != ea->id.b24 */
fcport->d_id.b24 = ea->id.b24;
if (fcport->deleted == QLA_SESS_DELETED) {
ql_dbg(ql_dbg_disc, vha, 0xffff,
"%s %d %8phC post del sess\n",
__func__, __LINE__, fcport->port_name);
qlt_schedule_sess_for_deletion_lock(fcport);
}
}
} else { /* ea->sp->gen1 != fcport->rscn_gen */
ql_dbg(ql_dbg_disc, vha, 0xffff,
"%s %d %8phC post gidpn\n",
__func__, __LINE__, fcport->port_name);
/* rscn came in while cmd was out */
qla24xx_post_gidpn_work(vha, fcport);
}
} else { /* ea->rc */
/* cable pulled */
if (ea->sp->gen1 == fcport->rscn_gen) {
if (ea->sp->gen2 == fcport->login_gen) {
ql_dbg(ql_dbg_disc, vha, 0xffff,
"%s %d %8phC post del sess\n", __func__,
__LINE__, fcport->port_name);
qlt_schedule_sess_for_deletion_lock(fcport);
} else {
ql_dbg(ql_dbg_disc, vha, 0xffff,
"%s %d %8phC login\n", __func__, __LINE__,
fcport->port_name);
qla24xx_fcport_handle_login(vha, fcport);
}
} else {
ql_dbg(ql_dbg_disc, vha, 0xffff,
"%s %d %8phC post gidpn\n", __func__, __LINE__,
fcport->port_name);
qla24xx_post_gidpn_work(vha, fcport);
}
}
} /* gidpn_event */
static void qla2x00_async_gidpn_sp_done(void *v, void *s, int res)
{
struct scsi_qla_host *vha = (struct scsi_qla_host *)v;
struct srb *sp = (struct srb *)s;
fc_port_t *fcport = sp->fcport;
u8 *id = fcport->ct_desc.ct_sns->p.rsp.rsp.gid_pn.port_id;
struct event_arg ea;
fcport->flags &= ~FCF_ASYNC_SENT;
memset(&ea, 0, sizeof(ea));
ea.fcport = fcport;
ea.id.b.domain = id[0];
ea.id.b.area = id[1];
ea.id.b.al_pa = id[2];
ea.sp = sp;
ea.rc = res;
ea.event = FCME_GIDPN_DONE;
ql_dbg(ql_dbg_disc, vha, 0xffff,
"Async done-%s res %x, WWPN %8phC ID %3phC \n",
sp->name, res, fcport->port_name, id);
qla2x00_fcport_event_handler(vha, &ea);
sp->free(vha, sp);
}
int qla24xx_async_gidpn(scsi_qla_host_t *vha, fc_port_t *fcport)
{
int rval = QLA_FUNCTION_FAILED;
struct ct_sns_req *ct_req;
srb_t *sp;
if (!vha->flags.online)
goto done;
fcport->flags |= FCF_ASYNC_SENT;
fcport->disc_state = DSC_GID_PN;
fcport->scan_state = QLA_FCPORT_SCAN;
sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
if (!sp)
goto done;
sp->type = SRB_CT_PTHRU_CMD;
sp->name = "gidpn";
sp->gen1 = fcport->rscn_gen;
sp->gen2 = fcport->login_gen;
qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
/* CT_IU preamble */
ct_req = qla2x00_prep_ct_req(fcport->ct_desc.ct_sns, GID_PN_CMD,
GID_PN_RSP_SIZE);
/* GIDPN req */
memcpy(ct_req->req.gid_pn.port_name, fcport->port_name,
WWN_SIZE);
/* req & rsp use the same buffer */
sp->u.iocb_cmd.u.ctarg.req = fcport->ct_desc.ct_sns;
sp->u.iocb_cmd.u.ctarg.req_dma = fcport->ct_desc.ct_sns_dma;
sp->u.iocb_cmd.u.ctarg.rsp = fcport->ct_desc.ct_sns;
sp->u.iocb_cmd.u.ctarg.rsp_dma = fcport->ct_desc.ct_sns_dma;
sp->u.iocb_cmd.u.ctarg.req_size = GID_PN_REQ_SIZE;
sp->u.iocb_cmd.u.ctarg.rsp_size = GID_PN_RSP_SIZE;
sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
sp->done = qla2x00_async_gidpn_sp_done;
rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS)
goto done_free_sp;
ql_dbg(ql_dbg_disc, vha, 0x206f,
"Async-%s - %8phC hdl=%x loopid=%x portid %02x%02x%02x.\n",
sp->name, fcport->port_name,
sp->handle, fcport->loop_id, fcport->d_id.b.domain,
fcport->d_id.b.area, fcport->d_id.b.al_pa);
return rval;
done_free_sp:
sp->free(vha, sp);
done:
fcport->flags &= ~FCF_ASYNC_SENT;
return rval;
}
int qla24xx_post_gidpn_work(struct scsi_qla_host *vha, fc_port_t *fcport)
{
struct qla_work_evt *e;
if ((atomic_read(&vha->loop_state) != LOOP_READY) ||
test_bit(UNLOADING, &vha->dpc_flags))
return 0;
e = qla2x00_alloc_work(vha, QLA_EVT_GIDPN);
if (!e)
return QLA_FUNCTION_FAILED;
e->u.fcport.fcport = fcport;
return qla2x00_post_work(vha, e);
}
int qla24xx_post_gpsc_work(struct scsi_qla_host *vha, fc_port_t *fcport)
{
struct qla_work_evt *e;
e = qla2x00_alloc_work(vha, QLA_EVT_GPSC);
if (!e)
return QLA_FUNCTION_FAILED;
e->u.fcport.fcport = fcport;
return qla2x00_post_work(vha, e);
}
static void qla24xx_async_gpsc_sp_done(void *v, void *s, int res)
{
struct scsi_qla_host *vha = (struct scsi_qla_host *)v;
struct qla_hw_data *ha = vha->hw;
struct srb *sp = (struct srb *)s;
fc_port_t *fcport = sp->fcport;
struct ct_sns_rsp *ct_rsp;
struct event_arg ea;
ct_rsp = &fcport->ct_desc.ct_sns->p.rsp;
ql_dbg(ql_dbg_disc, vha, 0xffff,
"Async done-%s res %x, WWPN %8phC \n",
sp->name, res, fcport->port_name);
fcport->flags &= ~FCF_ASYNC_SENT;
if (res == (DID_ERROR << 16)) {
/* entry status error */
goto done;
} else if (res) {
if ((ct_rsp->header.reason_code ==
CT_REASON_INVALID_COMMAND_CODE) ||
(ct_rsp->header.reason_code ==
CT_REASON_COMMAND_UNSUPPORTED)) {
ql_dbg(ql_dbg_disc, vha, 0x205a,
"GPSC command unsupported, disabling "
"query.\n");
ha->flags.gpsc_supported = 0;
res = QLA_SUCCESS;
}
} else {
switch (be16_to_cpu(ct_rsp->rsp.gpsc.speed)) {
case BIT_15:
fcport->fp_speed = PORT_SPEED_1GB;
break;
case BIT_14:
fcport->fp_speed = PORT_SPEED_2GB;
break;
case BIT_13:
fcport->fp_speed = PORT_SPEED_4GB;
break;
case BIT_12:
fcport->fp_speed = PORT_SPEED_10GB;
break;
case BIT_11:
fcport->fp_speed = PORT_SPEED_8GB;
break;
case BIT_10:
fcport->fp_speed = PORT_SPEED_16GB;
break;
case BIT_8:
fcport->fp_speed = PORT_SPEED_32GB;
break;
}
ql_dbg(ql_dbg_disc, vha, 0xffff,
"Async-%s OUT WWPN %8phC speeds=%04x speed=%04x.\n",
sp->name,
fcport->fabric_port_name,
be16_to_cpu(ct_rsp->rsp.gpsc.speeds),
be16_to_cpu(ct_rsp->rsp.gpsc.speed));
}
done:
memset(&ea, 0, sizeof(ea));
ea.event = FCME_GPSC_DONE;
ea.rc = res;
ea.fcport = fcport;
qla2x00_fcport_event_handler(vha, &ea);
sp->free(vha, sp);
}
int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)
{
int rval = QLA_FUNCTION_FAILED;
struct ct_sns_req *ct_req;
srb_t *sp;
if (!vha->flags.online)
goto done;
fcport->flags |= FCF_ASYNC_SENT;
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
if (!sp)
goto done;
sp->type = SRB_CT_PTHRU_CMD;
sp->name = "gpsc";
sp->gen1 = fcport->rscn_gen;
sp->gen2 = fcport->login_gen;
qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
/* CT_IU preamble */
ct_req = qla24xx_prep_ct_fm_req(fcport->ct_desc.ct_sns, GPSC_CMD,
GPSC_RSP_SIZE);
/* GPSC req */
memcpy(ct_req->req.gpsc.port_name, fcport->port_name,
WWN_SIZE);
sp->u.iocb_cmd.u.ctarg.req = fcport->ct_desc.ct_sns;
sp->u.iocb_cmd.u.ctarg.req_dma = fcport->ct_desc.ct_sns_dma;
sp->u.iocb_cmd.u.ctarg.rsp = fcport->ct_desc.ct_sns;
sp->u.iocb_cmd.u.ctarg.rsp_dma = fcport->ct_desc.ct_sns_dma;
sp->u.iocb_cmd.u.ctarg.req_size = GPSC_REQ_SIZE;
sp->u.iocb_cmd.u.ctarg.rsp_size = GPSC_RSP_SIZE;
sp->u.iocb_cmd.u.ctarg.nport_handle = vha->mgmt_svr_loop_id;
sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
sp->done = qla24xx_async_gpsc_sp_done;
rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS)
goto done_free_sp;
ql_dbg(ql_dbg_disc, vha, 0xffff,
"Async-%s %8phC hdl=%x loopid=%x portid=%02x%02x%02x.\n",
sp->name, fcport->port_name, sp->handle,
fcport->loop_id, fcport->d_id.b.domain,
fcport->d_id.b.area, fcport->d_id.b.al_pa);
return rval;
done_free_sp:
sp->free(vha, sp);
done:
fcport->flags &= ~FCF_ASYNC_SENT;
return rval;
}
int qla24xx_post_gpnid_work(struct scsi_qla_host *vha, port_id_t *id)
{
struct qla_work_evt *e;
if (test_bit(UNLOADING, &vha->dpc_flags))
return 0;
e = qla2x00_alloc_work(vha, QLA_EVT_GPNID);
if (!e)
return QLA_FUNCTION_FAILED;
e->u.gpnid.id = *id;
return qla2x00_post_work(vha, e);
}
void qla24xx_async_gpnid_done(scsi_qla_host_t *vha, srb_t *sp)
{
if (sp->u.iocb_cmd.u.ctarg.req) {
dma_free_coherent(&vha->hw->pdev->dev,
sizeof(struct ct_sns_pkt),
sp->u.iocb_cmd.u.ctarg.req,
sp->u.iocb_cmd.u.ctarg.req_dma);
sp->u.iocb_cmd.u.ctarg.req = NULL;
}
if (sp->u.iocb_cmd.u.ctarg.rsp) {
dma_free_coherent(&vha->hw->pdev->dev,
sizeof(struct ct_sns_pkt),
sp->u.iocb_cmd.u.ctarg.rsp,
sp->u.iocb_cmd.u.ctarg.rsp_dma);
sp->u.iocb_cmd.u.ctarg.rsp = NULL;
}
sp->free(vha, sp);
}
void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
{
fc_port_t *fcport;
unsigned long flags;
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
fcport = qla2x00_find_fcport_by_wwpn(vha, ea->port_name, 1);
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
if (fcport) {
/* cable moved. just plugged in */
ql_dbg(ql_dbg_disc, vha, 0xffff,
"%s %d %8phC post del sess\n",
__func__, __LINE__, fcport->port_name);
fcport->rscn_gen++;
fcport->d_id = ea->id;
fcport->scan_state = QLA_FCPORT_FOUND;
fcport->flags |= FCF_FABRIC_DEVICE;
qlt_schedule_sess_for_deletion_lock(fcport);
} else {
/* create new fcport */
ql_dbg(ql_dbg_disc, vha, 0xffff,
"%s %d %8phC post new sess\n",
__func__, __LINE__, ea->port_name);
qla24xx_post_newsess_work(vha, &ea->id, ea->port_name, NULL);
}
}
static void qla2x00_async_gpnid_sp_done(void *v, void *s, int res)
{
struct scsi_qla_host *vha = (struct scsi_qla_host *)v;
struct srb *sp = (struct srb *)s;
struct ct_sns_req *ct_req =
(struct ct_sns_req *)sp->u.iocb_cmd.u.ctarg.req;
struct ct_sns_rsp *ct_rsp =
(struct ct_sns_rsp *)sp->u.iocb_cmd.u.ctarg.rsp;
struct event_arg ea;
struct qla_work_evt *e;
ql_dbg(ql_dbg_disc, vha, 0xffff,
"Async done-%s res %x ID %3phC. %8phC\n",
sp->name, res, ct_req->req.port_id.port_id,
ct_rsp->rsp.gpn_id.port_name);
memset(&ea, 0, sizeof(ea));
memcpy(ea.port_name, ct_rsp->rsp.gpn_id.port_name, WWN_SIZE);
ea.sp = sp;
ea.id.b.domain = ct_req->req.port_id.port_id[0];
ea.id.b.area = ct_req->req.port_id.port_id[1];
ea.id.b.al_pa = ct_req->req.port_id.port_id[2];
ea.rc = res;
ea.event = FCME_GPNID_DONE;
qla2x00_fcport_event_handler(vha, &ea);
e = qla2x00_alloc_work(vha, QLA_EVT_GPNID_DONE);
if (!e) {
/* please ignore kernel warning. otherwise, we have mem leak. */
if (sp->u.iocb_cmd.u.ctarg.req) {
dma_free_coherent(&vha->hw->pdev->dev,
sizeof(struct ct_sns_pkt),
sp->u.iocb_cmd.u.ctarg.req,
sp->u.iocb_cmd.u.ctarg.req_dma);
sp->u.iocb_cmd.u.ctarg.req = NULL;
}
if (sp->u.iocb_cmd.u.ctarg.rsp) {
dma_free_coherent(&vha->hw->pdev->dev,
sizeof(struct ct_sns_pkt),
sp->u.iocb_cmd.u.ctarg.rsp,
sp->u.iocb_cmd.u.ctarg.rsp_dma);
sp->u.iocb_cmd.u.ctarg.rsp = NULL;
}
sp->free(vha, sp);
return;
}
e->u.iosb.sp = sp;
qla2x00_post_work(vha, e);
}
/* Get WWPN with Nport ID. */
int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id)
{
int rval = QLA_FUNCTION_FAILED;
struct ct_sns_req *ct_req;
srb_t *sp;
struct ct_sns_pkt *ct_sns;
if (!vha->flags.online)
goto done;
sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
if (!sp)
goto done;
sp->type = SRB_CT_PTHRU_CMD;
sp->name = "gpnid";
qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,
sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,
GFP_KERNEL);
if (!sp->u.iocb_cmd.u.ctarg.req) {
ql_log(ql_log_warn, vha, 0xffff,
"Failed to allocate ct_sns request.\n");
goto done_free_sp;
}
sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,
sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.rsp_dma,
GFP_KERNEL);
if (!sp->u.iocb_cmd.u.ctarg.rsp) {
ql_log(ql_log_warn, vha, 0xffff,
"Failed to allocate ct_sns request.\n");
goto done_free_sp;
}
ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.rsp;
memset(ct_sns, 0, sizeof(*ct_sns));
ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req;
/* CT_IU preamble */
ct_req = qla2x00_prep_ct_req(ct_sns, GPN_ID_CMD, GPN_ID_RSP_SIZE);
/* GPN_ID req */
ct_req->req.port_id.port_id[0] = id->b.domain;
ct_req->req.port_id.port_id[1] = id->b.area;
ct_req->req.port_id.port_id[2] = id->b.al_pa;
sp->u.iocb_cmd.u.ctarg.req_size = GPN_ID_REQ_SIZE;
sp->u.iocb_cmd.u.ctarg.rsp_size = GPN_ID_RSP_SIZE;
sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS;
sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
sp->done = qla2x00_async_gpnid_sp_done;
rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS)
goto done_free_sp;
ql_dbg(ql_dbg_disc, vha, 0xffff,
"Async-%s hdl=%x ID %3phC.\n", sp->name,
sp->handle, ct_req->req.port_id.port_id);
return rval;
done_free_sp:
if (sp->u.iocb_cmd.u.ctarg.req) {
dma_free_coherent(&vha->hw->pdev->dev,
sizeof(struct ct_sns_pkt),
sp->u.iocb_cmd.u.ctarg.req,
sp->u.iocb_cmd.u.ctarg.req_dma);
sp->u.iocb_cmd.u.ctarg.req = NULL;
}
if (sp->u.iocb_cmd.u.ctarg.rsp) {
dma_free_coherent(&vha->hw->pdev->dev,
sizeof(struct ct_sns_pkt),
sp->u.iocb_cmd.u.ctarg.rsp,
sp->u.iocb_cmd.u.ctarg.rsp_dma);
sp->u.iocb_cmd.u.ctarg.rsp = NULL;
}
sp->free(vha, sp);
done:
return rval;
}

File diff suppressed because it is too large Load Diff

View File

@ -166,8 +166,8 @@ qla2x00_set_fcport_state(fc_port_t *fcport, int state)
/* Don't print state transitions during initial allocation of fcport */
if (old_state && old_state != state) {
ql_dbg(ql_dbg_disc, fcport->vha, 0x207d,
"FCPort state transitioned from %s to %s - "
"portid=%02x%02x%02x.\n",
"FCPort %8phC state transitioned from %s to %s - "
"portid=%02x%02x%02x.\n", fcport->port_name,
port_state_str[old_state], port_state_str[state],
fcport->d_id.b.domain, fcport->d_id.b.area,
fcport->d_id.b.al_pa);
@ -263,6 +263,7 @@ qla2x00_get_sp(scsi_qla_host_t *vha, fc_port_t *fcport, gfp_t flag)
memset(sp, 0, sizeof(*sp));
sp->fcport = fcport;
sp->iocbs = 1;
sp->vha = vha;
done:
if (!sp)
QLA_VHA_MARK_NOT_BUSY(vha);
@ -285,7 +286,7 @@ qla2x00_init_timer(srb_t *sp, unsigned long tmo)
sp->u.iocb_cmd.timer.function = qla2x00_sp_timeout;
add_timer(&sp->u.iocb_cmd.timer);
sp->free = qla2x00_sp_free;
if ((IS_QLAFX00(sp->fcport->vha->hw)) &&
if ((IS_QLAFX00(((scsi_qla_host_t *)sp->vha)->hw)) &&
(sp->type == SRB_FXIOCB_DCMD))
init_completion(&sp->u.iocb_cmd.u.fxiocb.fxiocb_comp);
if (sp->type == SRB_ELS_DCMD)

View File

@ -2247,7 +2247,7 @@ qla24xx_logout_iocb(srb_t *sp, struct logio_entry_24xx *logio)
logio->entry_type = LOGINOUT_PORT_IOCB_TYPE;
logio->control_flags =
cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO);
if (!sp->fcport->tgt_session ||
if (!sp->fcport->se_sess ||
!sp->fcport->keep_nport_handle)
logio->control_flags |= cpu_to_le16(LCF_FREE_NPORT);
logio->nport_handle = cpu_to_le16(sp->fcport->loop_id);
@ -3079,19 +3079,69 @@ qla24xx_abort_iocb(srb_t *sp, struct abort_entry_24xx *abt_iocb)
wmb();
}
static void
qla2x00_mb_iocb(srb_t *sp, struct mbx_24xx_entry *mbx)
{
int i, sz;
mbx->entry_type = MBX_IOCB_TYPE;
mbx->handle = sp->handle;
sz = min(ARRAY_SIZE(mbx->mb), ARRAY_SIZE(sp->u.iocb_cmd.u.mbx.out_mb));
for (i = 0; i < sz; i++)
mbx->mb[i] = cpu_to_le16(sp->u.iocb_cmd.u.mbx.out_mb[i]);
}
static void
qla2x00_ctpthru_cmd_iocb(srb_t *sp, struct ct_entry_24xx *ct_pkt)
{
sp->u.iocb_cmd.u.ctarg.iocb = ct_pkt;
qla24xx_prep_ms_iocb(sp->vha, &sp->u.iocb_cmd.u.ctarg);
ct_pkt->handle = sp->handle;
}
static void qla2x00_send_notify_ack_iocb(srb_t *sp,
struct nack_to_isp *nack)
{
struct imm_ntfy_from_isp *ntfy = sp->u.iocb_cmd.u.nack.ntfy;
nack->entry_type = NOTIFY_ACK_TYPE;
nack->entry_count = 1;
nack->ox_id = ntfy->ox_id;
nack->u.isp24.handle = sp->handle;
nack->u.isp24.nport_handle = ntfy->u.isp24.nport_handle;
if (le16_to_cpu(ntfy->u.isp24.status) == IMM_NTFY_ELS) {
nack->u.isp24.flags = ntfy->u.isp24.flags &
cpu_to_le32(NOTIFY24XX_FLAGS_PUREX_IOCB);
}
nack->u.isp24.srr_rx_id = ntfy->u.isp24.srr_rx_id;
nack->u.isp24.status = ntfy->u.isp24.status;
nack->u.isp24.status_subcode = ntfy->u.isp24.status_subcode;
nack->u.isp24.fw_handle = ntfy->u.isp24.fw_handle;
nack->u.isp24.exchange_address = ntfy->u.isp24.exchange_address;
nack->u.isp24.srr_rel_offs = ntfy->u.isp24.srr_rel_offs;
nack->u.isp24.srr_ui = ntfy->u.isp24.srr_ui;
nack->u.isp24.srr_flags = 0;
nack->u.isp24.srr_reject_code = 0;
nack->u.isp24.srr_reject_code_expl = 0;
nack->u.isp24.vp_index = ntfy->u.isp24.vp_index;
}
int
qla2x00_start_sp(srb_t *sp)
{
int rval;
struct qla_hw_data *ha = sp->fcport->vha->hw;
scsi_qla_host_t *vha = (scsi_qla_host_t *)sp->vha;
struct qla_hw_data *ha = vha->hw;
void *pkt;
unsigned long flags;
rval = QLA_FUNCTION_FAILED;
spin_lock_irqsave(&ha->hardware_lock, flags);
pkt = qla2x00_alloc_iocbs(sp->fcport->vha, sp);
pkt = qla2x00_alloc_iocbs(vha, sp);
if (!pkt) {
ql_log(ql_log_warn, sp->fcport->vha, 0x700c,
ql_log(ql_log_warn, vha, 0x700c,
"qla2x00_alloc_iocbs failed.\n");
goto done;
}
@ -3139,12 +3189,23 @@ qla2x00_start_sp(srb_t *sp)
case SRB_ELS_DCMD:
qla24xx_els_logo_iocb(sp, pkt);
break;
case SRB_CT_PTHRU_CMD:
qla2x00_ctpthru_cmd_iocb(sp, pkt);
break;
case SRB_MB_IOCB:
qla2x00_mb_iocb(sp, pkt);
break;
case SRB_NACK_PLOGI:
case SRB_NACK_PRLI:
case SRB_NACK_LOGO:
qla2x00_send_notify_ack_iocb(sp, pkt);
break;
default:
break;
}
wmb();
qla2x00_start_iocbs(sp->fcport->vha, ha->req_q_map[0]);
qla2x00_start_iocbs(vha, ha->req_q_map[0]);
done:
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return rval;

View File

@ -561,14 +561,50 @@ qla2x00_is_a_vp_did(scsi_qla_host_t *vha, uint32_t rscn_entry)
return ret;
}
static inline fc_port_t *
fc_port_t *
qla2x00_find_fcport_by_loopid(scsi_qla_host_t *vha, uint16_t loop_id)
{
fc_port_t *fcport;
fc_port_t *f, *tf;
list_for_each_entry(fcport, &vha->vp_fcports, list)
if (fcport->loop_id == loop_id)
return fcport;
f = tf = NULL;
list_for_each_entry_safe(f, tf, &vha->vp_fcports, list)
if (f->loop_id == loop_id)
return f;
return NULL;
}
fc_port_t *
qla2x00_find_fcport_by_wwpn(scsi_qla_host_t *vha, u8 *wwpn, u8 incl_deleted)
{
fc_port_t *f, *tf;
f = tf = NULL;
list_for_each_entry_safe(f, tf, &vha->vp_fcports, list) {
if (memcmp(f->port_name, wwpn, WWN_SIZE) == 0) {
if (incl_deleted)
return f;
else if (f->deleted == 0)
return f;
}
}
return NULL;
}
fc_port_t *
qla2x00_find_fcport_by_nportid(scsi_qla_host_t *vha, port_id_t *id,
u8 incl_deleted)
{
fc_port_t *f, *tf;
f = tf = NULL;
list_for_each_entry_safe(f, tf, &vha->vp_fcports, list) {
if (f->d_id.b24 == id->b24) {
if (incl_deleted)
return f;
else if (f->deleted == 0)
return f;
}
}
return NULL;
}
@ -934,7 +970,11 @@ skip_rio:
ql_dbg(ql_dbg_async, vha, 0x508a,
"Marking port lost loopid=%04x portid=%06x.\n",
fcport->loop_id, fcport->d_id.b24);
qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1);
if (qla_ini_mode_enabled(vha)) {
qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1);
fcport->logout_on_delete = 0;
qlt_schedule_sess_for_deletion_lock(fcport);
}
break;
global_port_update:
@ -1024,27 +1064,17 @@ global_port_update:
if (qla2x00_is_a_vp_did(vha, rscn_entry))
break;
/*
* Search for the rport related to this RSCN entry and mark it
* as lost.
*/
list_for_each_entry(fcport, &vha->vp_fcports, list) {
if (atomic_read(&fcport->state) != FCS_ONLINE)
continue;
if (fcport->d_id.b24 == rscn_entry) {
qla2x00_mark_device_lost(vha, fcport, 0, 0);
break;
}
}
atomic_set(&vha->loop_down_timer, 0);
vha->flags.management_server_logged_in = 0;
{
struct event_arg ea;
set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
set_bit(RSCN_UPDATE, &vha->dpc_flags);
qla2x00_post_aen_work(vha, FCH_EVT_RSCN, rscn_entry);
memset(&ea, 0, sizeof(ea));
ea.event = FCME_RSCN;
ea.id.b24 = rscn_entry;
qla2x00_fcport_event_handler(vha, &ea);
}
break;
/* case MBA_RIO_RESPONSE: */
case MBA_ZIO_RESPONSE:
ql_dbg(ql_dbg_async, vha, 0x5015,
@ -1235,7 +1265,8 @@ qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func,
index = LSW(pkt->handle);
if (index >= req->num_outstanding_cmds) {
ql_log(ql_log_warn, vha, 0x5031,
"Invalid command index (%x).\n", index);
"Invalid command index (%x) type %8ph.\n",
index, iocb);
if (IS_P3P_TYPE(ha))
set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
else
@ -1346,6 +1377,49 @@ logio_done:
sp->done(vha, sp, 0);
}
static void
qla24xx_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
struct mbx_24xx_entry *pkt)
{
const char func[] = "MBX-IOCB2";
srb_t *sp;
struct srb_iocb *si;
u16 sz, i;
int res;
sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
if (!sp)
return;
si = &sp->u.iocb_cmd;
sz = min(ARRAY_SIZE(pkt->mb), ARRAY_SIZE(sp->u.iocb_cmd.u.mbx.in_mb));
for (i = 0; i < sz; i++)
si->u.mbx.in_mb[i] = le16_to_cpu(pkt->mb[i]);
res = (si->u.mbx.in_mb[0] & MBS_MASK);
sp->done(vha, sp, res);
}
static void
qla24xxx_nack_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
struct nack_to_isp *pkt)
{
const char func[] = "nack";
srb_t *sp;
int res = 0;
sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
if (!sp)
return;
if (pkt->u.isp2x.status != cpu_to_le16(NOTIFY_ACK_SUCCESS))
res = QLA_FUNCTION_FAILED;
sp->done(vha, sp, res);
}
static void
qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
sts_entry_t *pkt, int iocb_type)
@ -1356,50 +1430,63 @@ qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
struct bsg_job *bsg_job;
struct fc_bsg_reply *bsg_reply;
uint16_t comp_status;
int res;
int res = 0;
sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
if (!sp)
return;
bsg_job = sp->u.bsg_job;
bsg_reply = bsg_job->reply;
switch (sp->type) {
case SRB_CT_CMD:
bsg_job = sp->u.bsg_job;
bsg_reply = bsg_job->reply;
type = "ct pass-through";
type = "ct pass-through";
comp_status = le16_to_cpu(pkt->comp_status);
comp_status = le16_to_cpu(pkt->comp_status);
/* return FC_CTELS_STATUS_OK and leave the decoding of the ELS/CT
* fc payload to the caller
*/
bsg_reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
bsg_job->reply_len = sizeof(struct fc_bsg_reply);
/*
* return FC_CTELS_STATUS_OK and leave the decoding of the ELS/CT
* fc payload to the caller
*/
bsg_reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
bsg_job->reply_len = sizeof(struct fc_bsg_reply);
if (comp_status != CS_COMPLETE) {
if (comp_status == CS_DATA_UNDERRUN) {
res = DID_OK << 16;
bsg_reply->reply_payload_rcv_len =
le16_to_cpu(((sts_entry_t *)pkt)->rsp_info_len);
if (comp_status != CS_COMPLETE) {
if (comp_status == CS_DATA_UNDERRUN) {
res = DID_OK << 16;
bsg_reply->reply_payload_rcv_len =
le16_to_cpu(((sts_entry_t *)pkt)->rsp_info_len);
ql_log(ql_log_warn, vha, 0x5048,
"CT pass-through-%s error "
"comp_status-status=0x%x total_byte = 0x%x.\n",
type, comp_status,
bsg_reply->reply_payload_rcv_len);
} else {
ql_log(ql_log_warn, vha, 0x5049,
"CT pass-through-%s error "
"comp_status-status=0x%x.\n", type, comp_status);
res = DID_ERROR << 16;
bsg_reply->reply_payload_rcv_len = 0;
}
ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5035,
(uint8_t *)pkt, sizeof(*pkt));
} else {
res = DID_OK << 16;
bsg_reply->reply_payload_rcv_len =
bsg_job->reply_payload.payload_len;
bsg_job->reply_len = 0;
ql_log(ql_log_warn, vha, 0x5048,
"CT pass-through-%s error comp_status=0x%x total_byte=0x%x.\n",
type, comp_status,
bsg_reply->reply_payload_rcv_len);
} else {
ql_log(ql_log_warn, vha, 0x5049,
"CT pass-through-%s error comp_status=0x%x.\n",
type, comp_status);
res = DID_ERROR << 16;
bsg_reply->reply_payload_rcv_len = 0;
}
ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5035,
(uint8_t *)pkt, sizeof(*pkt));
} else {
res = DID_OK << 16;
bsg_reply->reply_payload_rcv_len =
bsg_job->reply_payload.payload_len;
bsg_job->reply_len = 0;
}
break;
case SRB_CT_PTHRU_CMD:
/*
* borrowing sts_entry_24xx.comp_status.
* same location as ct_entry_24xx.comp_status
*/
res = qla2x00_chk_ms_status(vha, (ms_iocb_entry_t *)pkt,
(struct ct_sns_rsp *)sp->u.iocb_cmd.u.ctarg.rsp,
sp->name);
break;
}
sp->done(vha, sp, res);
@ -1440,6 +1527,15 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
"Completing %s: (%p) type=%d.\n", type, sp, sp->type);
sp->done(vha, sp, 0);
return;
case SRB_CT_PTHRU_CMD:
/* borrowing sts_entry_24xx.comp_status.
same location as ct_entry_24xx.comp_status
*/
res = qla2x00_chk_ms_status(vha, (ms_iocb_entry_t *)pkt,
(struct ct_sns_rsp *)sp->u.iocb_cmd.u.ctarg.rsp,
sp->name);
sp->done(vha, sp, res);
return;
default:
ql_dbg(ql_dbg_user, vha, 0x503e,
"Unrecognized SRB: (%p) type=%d.\n", sp, sp->type);
@ -1566,6 +1662,8 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
iop[0] = le32_to_cpu(logio->io_parameter[0]);
iop[1] = le32_to_cpu(logio->io_parameter[1]);
lio->u.logio.iop[0] = iop[0];
lio->u.logio.iop[1] = iop[1];
switch (iop[0]) {
case LSC_SCODE_PORTID_USED:
data[0] = MBS_PORT_ID_USED;
@ -2074,6 +2172,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
int res = 0;
uint16_t state_flags = 0;
uint16_t retry_delay = 0;
uint8_t no_logout = 0;
sts = (sts_entry_t *) pkt;
sts24 = (struct sts_entry_24xx *) pkt;
@ -2334,6 +2433,7 @@ check_scsi_status:
break;
case CS_PORT_LOGGED_OUT:
no_logout = 1;
case CS_PORT_CONFIG_CHG:
case CS_PORT_BUSY:
case CS_INCOMPLETE:
@ -2356,14 +2456,21 @@ check_scsi_status:
break;
}
ql_dbg(ql_dbg_io, fcport->vha, 0x3021,
"Port to be marked lost on fcport=%02x%02x%02x, current "
"port state= %s.\n", fcport->d_id.b.domain,
fcport->d_id.b.area, fcport->d_id.b.al_pa,
port_state_str[atomic_read(&fcport->state)]);
if (atomic_read(&fcport->state) == FCS_ONLINE) {
ql_dbg(ql_dbg_disc, fcport->vha, 0x3021,
"Port to be marked lost on fcport=%02x%02x%02x, current "
"port state= %s comp_status %x.\n", fcport->d_id.b.domain,
fcport->d_id.b.area, fcport->d_id.b.al_pa,
port_state_str[atomic_read(&fcport->state)],
comp_status);
if (no_logout)
fcport->logout_on_delete = 0;
if (atomic_read(&fcport->state) == FCS_ONLINE)
qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1);
qlt_schedule_sess_for_deletion_lock(fcport);
}
break;
case CS_ABORTED:
@ -2627,10 +2734,16 @@ process_err:
}
case ABTS_RESP_24XX:
case CTIO_TYPE7:
case NOTIFY_ACK_TYPE:
case CTIO_CRC2:
qlt_response_pkt_all_vps(vha, (response_t *)pkt);
break;
case NOTIFY_ACK_TYPE:
if (pkt->handle == QLA_TGT_SKIP_HANDLE)
qlt_response_pkt_all_vps(vha, (response_t *)pkt);
else
qla24xxx_nack_iocb_entry(vha, rsp->req,
(struct nack_to_isp *)pkt);
break;
case MARKER_TYPE:
/* Do nothing in this case, this check is to prevent it
* from falling into default case
@ -2640,6 +2753,10 @@ process_err:
qla24xx_abort_iocb_entry(vha, rsp->req,
(struct abort_entry_24xx *)pkt);
break;
case MBX_IOCB_TYPE:
qla24xx_mbx_iocb_entry(vha, rsp->req,
(struct mbx_24xx_entry *)pkt);
break;
default:
/* Type Not Supported. */
ql_dbg(ql_dbg_async, vha, 0x5042,
@ -2656,8 +2773,9 @@ process_err:
if (IS_P3P_TYPE(ha)) {
struct device_reg_82xx __iomem *reg = &ha->iobase->isp82;
WRT_REG_DWORD(&reg->rsp_q_out[0], rsp->ring_index);
} else
} else {
WRT_REG_DWORD(rsp->rsp_q_out, rsp->ring_index);
}
}
static void

View File

@ -1637,94 +1637,6 @@ qla2x00_init_firmware(scsi_qla_host_t *vha, uint16_t size)
return rval;
}
/*
* qla2x00_get_node_name_list
* Issue get node name list mailbox command, kmalloc()
* and return the resulting list. Caller must kfree() it!
*
* Input:
* ha = adapter state pointer.
* out_data = resulting list
* out_len = length of the resulting list
*
* Returns:
* qla2x00 local function return status code.
*
* Context:
* Kernel context.
*/
int
qla2x00_get_node_name_list(scsi_qla_host_t *vha, void **out_data, int *out_len)
{
struct qla_hw_data *ha = vha->hw;
struct qla_port_24xx_data *list = NULL;
void *pmap;
mbx_cmd_t mc;
dma_addr_t pmap_dma;
ulong dma_size;
int rval, left;
left = 1;
while (left > 0) {
dma_size = left * sizeof(*list);
pmap = dma_alloc_coherent(&ha->pdev->dev, dma_size,
&pmap_dma, GFP_KERNEL);
if (!pmap) {
ql_log(ql_log_warn, vha, 0x113f,
"%s(%ld): DMA Alloc failed of %ld\n",
__func__, vha->host_no, dma_size);
rval = QLA_MEMORY_ALLOC_FAILED;
goto out;
}
mc.mb[0] = MBC_PORT_NODE_NAME_LIST;
mc.mb[1] = BIT_1 | BIT_3;
mc.mb[2] = MSW(pmap_dma);
mc.mb[3] = LSW(pmap_dma);
mc.mb[6] = MSW(MSD(pmap_dma));
mc.mb[7] = LSW(MSD(pmap_dma));
mc.mb[8] = dma_size;
mc.out_mb = MBX_0|MBX_1|MBX_2|MBX_3|MBX_6|MBX_7|MBX_8;
mc.in_mb = MBX_0|MBX_1;
mc.tov = 30;
mc.flags = MBX_DMA_IN;
rval = qla2x00_mailbox_command(vha, &mc);
if (rval != QLA_SUCCESS) {
if ((mc.mb[0] == MBS_COMMAND_ERROR) &&
(mc.mb[1] == 0xA)) {
left += le16_to_cpu(mc.mb[2]) /
sizeof(struct qla_port_24xx_data);
goto restart;
}
goto out_free;
}
left = 0;
list = kmemdup(pmap, dma_size, GFP_KERNEL);
if (!list) {
ql_log(ql_log_warn, vha, 0x1140,
"%s(%ld): failed to allocate node names list "
"structure.\n", __func__, vha->host_no);
rval = QLA_MEMORY_ALLOC_FAILED;
goto out_free;
}
restart:
dma_free_coherent(&ha->pdev->dev, dma_size, pmap, pmap_dma);
}
*out_data = list;
*out_len = dma_size;
out:
return rval;
out_free:
dma_free_coherent(&ha->pdev->dev, dma_size, pmap, pmap_dma);
return rval;
}
/*
* qla2x00_get_port_database

View File

@ -1043,6 +1043,34 @@ qla2x00_wait_for_hba_online(scsi_qla_host_t *vha)
return (return_status);
}
static inline int test_fcport_count(scsi_qla_host_t *vha)
{
struct qla_hw_data *ha = vha->hw;
unsigned long flags;
int res;
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
ql_dbg(ql_dbg_init, vha, 0xffff,
"tgt %p, fcport_count=%d\n",
vha, vha->fcport_count);
res = (vha->fcport_count == 0);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
return res;
}
/*
* qla2x00_wait_for_sess_deletion can only be called from remove_one.
* it has dependency on UNLOADING flag to stop device discovery
*/
static void
qla2x00_wait_for_sess_deletion(scsi_qla_host_t *vha)
{
qla2x00_mark_all_devices_lost(vha, 0);
wait_event(vha->fcport_waitQ, test_fcport_count(vha));
}
/*
* qla2x00_wait_for_hba_ready
* Wait till the HBA is ready before doing driver unload
@ -2904,6 +2932,18 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
if (ret)
goto probe_init_failed;
base_vha->gnl.size = (ha->max_loop_id + 1) *
sizeof(struct get_name_list_extended);
base_vha->gnl.l = dma_alloc_coherent(&ha->pdev->dev,
base_vha->gnl.size, &base_vha->gnl.ldma, GFP_KERNEL);
INIT_LIST_HEAD(&base_vha->gnl.fcports);
if (base_vha->gnl.l == NULL) {
ql_log(ql_log_fatal, base_vha, 0xffff,
"Alloc failed for name list.\n");
goto probe_init_failed;
}
/* Alloc arrays of request and response ring ptrs */
if (!qla2x00_alloc_queues(ha, req, rsp)) {
ql_log(ql_log_fatal, base_vha, 0x003d,
@ -3123,7 +3163,8 @@ skip_dpc:
ql_dbg(ql_dbg_init, base_vha, 0x00f2,
"Init done and hba is online.\n");
if (qla_ini_mode_enabled(base_vha))
if (qla_ini_mode_enabled(base_vha) ||
qla_dual_mode_enabled(base_vha))
scsi_scan_host(host);
else
ql_dbg(ql_dbg_init, base_vha, 0x0122,
@ -3372,21 +3413,26 @@ qla2x00_remove_one(struct pci_dev *pdev)
* resources.
*/
if (!atomic_read(&pdev->enable_cnt)) {
dma_free_coherent(&ha->pdev->dev, base_vha->gnl.size,
base_vha->gnl.l, base_vha->gnl.ldma);
scsi_host_put(base_vha->host);
kfree(ha);
pci_set_drvdata(pdev, NULL);
return;
}
qla2x00_wait_for_hba_ready(base_vha);
/* if UNLOAD flag is already set, then continue unload,
/*
* if UNLOAD flag is already set, then continue unload,
* where it was set first.
*/
if (test_bit(UNLOADING, &base_vha->dpc_flags))
return;
set_bit(UNLOADING, &base_vha->dpc_flags);
dma_free_coherent(&ha->pdev->dev,
base_vha->gnl.size, base_vha->gnl.l, base_vha->gnl.ldma);
if (IS_QLAFX00(ha))
qlafx00_driver_shutdown(base_vha, 20);
@ -3535,10 +3581,14 @@ qla2x00_schedule_rport_del(struct scsi_qla_host *vha, fc_port_t *fcport,
qla2xxx_wake_dpc(base_vha);
} else {
int now;
if (rport)
if (rport) {
ql_dbg(ql_dbg_disc, fcport->vha, 0xffff,
"%s %8phN. rport %p roles %x \n",
__func__, fcport->port_name, rport,
rport->roles);
fc_remote_port_delete(rport);
}
qlt_do_generation_tick(vha, &now);
qlt_fc_port_deleted(vha, fcport, now);
}
}
@ -3581,7 +3631,7 @@ void qla2x00_mark_device_lost(scsi_qla_host_t *vha, fc_port_t *fcport,
fcport->login_retry = vha->hw->login_retry_count;
ql_dbg(ql_dbg_disc, vha, 0x2067,
"Port login retry %8phN, id = 0x%04x retry cnt=%d.\n",
"Port login retry %8phN, lid 0x%04x retry cnt=%d.\n",
fcport->port_name, fcport->loop_id, fcport->login_retry);
}
}
@ -3604,7 +3654,13 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *vha, int defer)
{
fc_port_t *fcport;
ql_dbg(ql_dbg_disc, vha, 0xffff,
"Mark all dev lost\n");
list_for_each_entry(fcport, &vha->vp_fcports, list) {
fcport->scan_state = 0;
qlt_schedule_sess_for_deletion_lock(fcport);
if (vha->vp_idx != 0 && vha->vp_idx != fcport->vha->vp_idx)
continue;
@ -4219,6 +4275,7 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
spin_lock_init(&vha->work_lock);
spin_lock_init(&vha->cmd_list_lock);
init_waitqueue_head(&vha->fcport_waitQ);
sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no);
ql_dbg(ql_dbg_init, vha, 0x0041,
@ -4232,7 +4289,7 @@ fail:
return vha;
}
static struct qla_work_evt *
struct qla_work_evt *
qla2x00_alloc_work(struct scsi_qla_host *vha, enum qla_work_type type)
{
struct qla_work_evt *e;
@ -4254,7 +4311,7 @@ qla2x00_alloc_work(struct scsi_qla_host *vha, enum qla_work_type type)
return e;
}
static int
int
qla2x00_post_work(struct scsi_qla_host *vha, struct qla_work_evt *e)
{
unsigned long flags;
@ -4315,7 +4372,6 @@ int qla2x00_post_async_##name##_work( \
}
qla2x00_post_async_work(login, QLA_EVT_ASYNC_LOGIN);
qla2x00_post_async_work(login_done, QLA_EVT_ASYNC_LOGIN_DONE);
qla2x00_post_async_work(logout, QLA_EVT_ASYNC_LOGOUT);
qla2x00_post_async_work(logout_done, QLA_EVT_ASYNC_LOGOUT_DONE);
qla2x00_post_async_work(adisc, QLA_EVT_ASYNC_ADISC);
@ -4368,6 +4424,67 @@ qlafx00_post_aenfx_work(struct scsi_qla_host *vha, uint32_t evtcode,
return qla2x00_post_work(vha, e);
}
int qla24xx_post_upd_fcport_work(struct scsi_qla_host *vha, fc_port_t *fcport)
{
struct qla_work_evt *e;
e = qla2x00_alloc_work(vha, QLA_EVT_UPD_FCPORT);
if (!e)
return QLA_FUNCTION_FAILED;
e->u.fcport.fcport = fcport;
return qla2x00_post_work(vha, e);
}
static
void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
{
unsigned long flags;
fc_port_t *fcport = NULL;
struct qlt_plogi_ack_t *pla =
(struct qlt_plogi_ack_t *)e->u.new_sess.pla;
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
fcport = qla2x00_find_fcport_by_wwpn(vha, e->u.new_sess.port_name, 1);
if (fcport) {
fcport->d_id = e->u.new_sess.id;
if (pla) {
fcport->fw_login_state = DSC_LS_PLOGI_PEND;
qlt_plogi_ack_link(vha, pla, fcport, QLT_PLOGI_LINK_SAME_WWN);
/* we took an extra ref_count to prevent PLOGI ACK when
* fcport/sess has not been created.
*/
pla->ref_count--;
}
} else {
fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
if (fcport) {
fcport->d_id = e->u.new_sess.id;
fcport->scan_state = QLA_FCPORT_FOUND;
fcport->flags |= FCF_FABRIC_DEVICE;
fcport->fw_login_state = DSC_LS_PLOGI_PEND;
memcpy(fcport->port_name, e->u.new_sess.port_name,
WWN_SIZE);
list_add_tail(&fcport->list, &vha->vp_fcports);
if (pla) {
qlt_plogi_ack_link(vha, pla, fcport,
QLT_PLOGI_LINK_SAME_WWN);
pla->ref_count--;
}
}
}
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
if (fcport) {
if (pla)
qlt_plogi_ack_unref(vha, pla);
else
qla24xx_async_gnl(vha, fcport);
}
}
void
qla2x00_do_work(struct scsi_qla_host *vha)
{
@ -4394,10 +4511,6 @@ qla2x00_do_work(struct scsi_qla_host *vha)
qla2x00_async_login(vha, e->u.logio.fcport,
e->u.logio.data);
break;
case QLA_EVT_ASYNC_LOGIN_DONE:
qla2x00_async_login_done(vha, e->u.logio.fcport,
e->u.logio.data);
break;
case QLA_EVT_ASYNC_LOGOUT:
qla2x00_async_logout(vha, e->u.logio.fcport);
break;
@ -4419,6 +4532,34 @@ qla2x00_do_work(struct scsi_qla_host *vha)
case QLA_EVT_AENFX:
qlafx00_process_aen(vha, e);
break;
case QLA_EVT_GIDPN:
qla24xx_async_gidpn(vha, e->u.fcport.fcport);
break;
case QLA_EVT_GPNID:
qla24xx_async_gpnid(vha, &e->u.gpnid.id);
break;
case QLA_EVT_GPNID_DONE:
qla24xx_async_gpnid_done(vha, e->u.iosb.sp);
break;
case QLA_EVT_NEW_SESS:
qla24xx_create_new_sess(vha, e);
break;
case QLA_EVT_GPDB:
qla24xx_async_gpdb(vha, e->u.fcport.fcport,
e->u.fcport.opt);
break;
case QLA_EVT_GPSC:
qla24xx_async_gpsc(vha, e->u.fcport.fcport);
break;
case QLA_EVT_UPD_FCPORT:
qla2x00_update_fcport(vha, e->u.fcport.fcport);
break;
case QLA_EVT_GNL:
qla24xx_async_gnl(vha, e->u.fcport.fcport);
break;
case QLA_EVT_NACK:
qla24xx_do_nack_work(vha, e);
break;
}
if (e->flags & QLA_EVT_FLAG_FREE)
kfree(e);
@ -4435,9 +4576,7 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
{
fc_port_t *fcport;
int status;
uint16_t next_loopid = 0;
struct qla_hw_data *ha = vha->hw;
uint16_t data[2];
struct event_arg ea;
list_for_each_entry(fcport, &vha->vp_fcports, list) {
/*
@ -4448,77 +4587,38 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
fcport->login_retry && !(fcport->flags & FCF_ASYNC_SENT)) {
fcport->login_retry--;
if (fcport->flags & FCF_FABRIC_DEVICE) {
if (fcport->flags & FCF_FCP2_DEVICE)
ha->isp_ops->fabric_logout(vha,
fcport->loop_id,
fcport->d_id.b.domain,
fcport->d_id.b.area,
fcport->d_id.b.al_pa);
if (fcport->loop_id == FC_NO_LOOP_ID) {
fcport->loop_id = next_loopid =
ha->min_external_loopid;
status = qla2x00_find_new_loop_id(
vha, fcport);
if (status != QLA_SUCCESS) {
/* Ran out of IDs to use */
break;
}
}
if (IS_ALOGIO_CAPABLE(ha)) {
fcport->flags |= FCF_ASYNC_SENT;
data[0] = 0;
data[1] = QLA_LOGIO_LOGIN_RETRIED;
status = qla2x00_post_async_login_work(
vha, fcport, data);
if (status == QLA_SUCCESS)
continue;
/* Attempt a retry. */
status = 1;
} else {
status = qla2x00_fabric_login(vha,
fcport, &next_loopid);
if (status == QLA_SUCCESS) {
int status2;
uint8_t opts;
opts = 0;
if (fcport->flags &
FCF_FCP2_DEVICE)
opts |= BIT_1;
status2 =
qla2x00_get_port_database(
vha, fcport, opts);
if (status2 != QLA_SUCCESS)
status = 1;
}
}
} else
ql_dbg(ql_dbg_disc, fcport->vha, 0xffff,
"%s %8phC DS %d LS %d\n", __func__,
fcport->port_name, fcport->disc_state,
fcport->fw_login_state);
memset(&ea, 0, sizeof(ea));
ea.event = FCME_RELOGIN;
ea.fcport = fcport;
qla2x00_fcport_event_handler(vha, &ea);
} else {
status = qla2x00_local_device_login(vha,
fcport);
if (status == QLA_SUCCESS) {
fcport->old_loop_id = fcport->loop_id;
ql_dbg(ql_dbg_disc, vha, 0x2003,
"Port login OK: logged in ID 0x%x.\n",
fcport->loop_id);
qla2x00_update_fcport(vha, fcport);
} else if (status == 1) {
set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
/* retry the login again */
ql_dbg(ql_dbg_disc, vha, 0x2007,
"Retrying %d login again loop_id 0x%x.\n",
fcport->login_retry,
fcport->loop_id);
} else {
fcport->login_retry = 0;
}
if (status == QLA_SUCCESS) {
fcport->old_loop_id = fcport->loop_id;
ql_dbg(ql_dbg_disc, vha, 0x2003,
"Port login OK: logged in ID 0x%x.\n",
fcport->loop_id);
qla2x00_update_fcport(vha, fcport);
} else if (status == 1) {
set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
/* retry the login again */
ql_dbg(ql_dbg_disc, vha, 0x2007,
"Retrying %d login again loop_id 0x%x.\n",
fcport->login_retry, fcport->loop_id);
} else {
fcport->login_retry = 0;
if (fcport->login_retry == 0 &&
status != QLA_SUCCESS)
qla2x00_clear_loop_id(fcport);
}
if (fcport->login_retry == 0 && status != QLA_SUCCESS)
qla2x00_clear_loop_id(fcport);
}
if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
break;
@ -5182,7 +5282,8 @@ qla2x00_disable_board_on_pci_error(struct work_struct *work)
struct pci_dev *pdev = ha->pdev;
scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
/* if UNLOAD flag is already set, then continue unload,
/*
* if UNLOAD flag is already set, then continue unload,
* where it was set first.
*/
if (test_bit(UNLOADING, &base_vha->dpc_flags))
@ -5191,6 +5292,8 @@ qla2x00_disable_board_on_pci_error(struct work_struct *work)
ql_log(ql_log_warn, base_vha, 0x015b,
"Disabling adapter.\n");
qla2x00_wait_for_sess_deletion(base_vha);
set_bit(UNLOADING, &base_vha->dpc_flags);
qla2x00_delete_all_vps(ha, base_vha);

File diff suppressed because it is too large Load Diff

View File

@ -799,7 +799,6 @@ struct qla_tgt {
/* Protected by hardware_lock */
struct list_head del_sess_list;
struct delayed_work sess_del_work;
spinlock_t sess_work_lock;
struct list_head sess_works_list;
@ -823,13 +822,6 @@ struct qla_tgt_sess_op {
bool aborted;
};
enum qla_sess_deletion {
QLA_SESS_DELETION_NONE = 0,
QLA_SESS_DELETION_PENDING = 1, /* hopefully we can get rid of
* this one */
QLA_SESS_DELETION_IN_PROGRESS = 2,
};
enum trace_flags {
TRC_NEW_CMD = BIT_0,
TRC_DO_WORK = BIT_1,
@ -987,12 +979,17 @@ extern int ql2x_ini_mode;
static inline bool qla_tgt_mode_enabled(struct scsi_qla_host *ha)
{
return ha->host->active_mode & MODE_TARGET;
return ha->host->active_mode == MODE_TARGET;
}
static inline bool qla_ini_mode_enabled(struct scsi_qla_host *ha)
{
return ha->host->active_mode & MODE_INITIATOR;
return ha->host->active_mode == MODE_INITIATOR;
}
static inline bool qla_dual_mode_enabled(struct scsi_qla_host *ha)
{
return (ha->host->active_mode == MODE_DUAL);
}
static inline void qla_reverse_ini_mode(struct scsi_qla_host *ha)