提交 a4239945 编写于 作者: Q Quinn Tran 提交者: Martin K. Petersen

scsi: qla2xxx: Add switch command to simplify fabric discovery

- add "async" gpn_ft, gnn_ft, gfpn_id, gnn_id switch commands.
- For 8G and newer adapters, use async commands when it comes to
fabric scan to reduce bottle neck.
Signed-off-by: NQuinn Tran <quinn.tran@cavium.com>
Signed-off-by: NHimanshu Madhani <himanshu.madhani@cavium.com>
Signed-off-by: NMartin K. Petersen <martin.petersen@oracle.com>
上级 1429f044
...@@ -2170,6 +2170,8 @@ qla24xx_vport_delete(struct fc_vport *fc_vport) ...@@ -2170,6 +2170,8 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
dma_free_coherent(&ha->pdev->dev, vha->gnl.size, vha->gnl.l, dma_free_coherent(&ha->pdev->dev, vha->gnl.size, vha->gnl.l,
vha->gnl.ldma); vha->gnl.ldma);
vfree(vha->scan.l);
if (vha->qpair && vha->qpair->vp_idx == vha->vp_idx) { if (vha->qpair && vha->qpair->vp_idx == vha->vp_idx) {
if (qla2xxx_delete_qpair(vha, vha->qpair) != QLA_SUCCESS) if (qla2xxx_delete_qpair(vha, vha->qpair) != QLA_SUCCESS)
ql_log(ql_log_warn, vha, 0x7087, ql_log(ql_log_warn, vha, 0x7087,
......
...@@ -2270,11 +2270,13 @@ struct ct_sns_desc { ...@@ -2270,11 +2270,13 @@ struct ct_sns_desc {
enum discovery_state { enum discovery_state {
DSC_DELETED, DSC_DELETED,
DSC_GNN_ID,
DSC_GID_PN, DSC_GID_PN,
DSC_GNL, DSC_GNL,
DSC_LOGIN_PEND, DSC_LOGIN_PEND,
DSC_LOGIN_FAILED, DSC_LOGIN_FAILED,
DSC_GPDB, DSC_GPDB,
DSC_GFPN_ID,
DSC_GPSC, DSC_GPSC,
DSC_UPD_FCPORT, DSC_UPD_FCPORT,
DSC_LOGIN_COMPLETE, DSC_LOGIN_COMPLETE,
...@@ -2304,8 +2306,9 @@ enum fcport_mgt_event { ...@@ -2304,8 +2306,9 @@ enum fcport_mgt_event {
FCME_GPDB_DONE, FCME_GPDB_DONE,
FCME_GPNID_DONE, FCME_GPNID_DONE,
FCME_GFFID_DONE, FCME_GFFID_DONE,
FCME_DELETE_DONE,
FCME_ADISC_DONE, FCME_ADISC_DONE,
FCME_GNNID_DONE,
FCME_GFPNID_DONE,
}; };
enum rscn_addr_format { enum rscn_addr_format {
...@@ -2338,6 +2341,7 @@ typedef struct fc_port { ...@@ -2338,6 +2341,7 @@ typedef struct fc_port {
unsigned int login_pause:1; unsigned int login_pause:1;
unsigned int login_succ:1; unsigned int login_succ:1;
unsigned int query:1; unsigned int query:1;
unsigned int id_changed:1;
struct work_struct nvme_del_work; struct work_struct nvme_del_work;
struct completion nvme_del_done; struct completion nvme_del_done;
...@@ -2485,6 +2489,11 @@ static const char * const port_state_str[] = { ...@@ -2485,6 +2489,11 @@ static const char * const port_state_str[] = {
#define GA_NXT_REQ_SIZE (16 + 4) #define GA_NXT_REQ_SIZE (16 + 4)
#define GA_NXT_RSP_SIZE (16 + 620) #define GA_NXT_RSP_SIZE (16 + 620)
#define GPN_FT_CMD 0x172
#define GPN_FT_REQ_SIZE (16 + 4)
#define GNN_FT_CMD 0x173
#define GNN_FT_REQ_SIZE (16 + 4)
#define GID_PT_CMD 0x1A1 #define GID_PT_CMD 0x1A1
#define GID_PT_REQ_SIZE (16 + 4) #define GID_PT_REQ_SIZE (16 + 4)
...@@ -2739,6 +2748,13 @@ struct ct_sns_req { ...@@ -2739,6 +2748,13 @@ struct ct_sns_req {
uint8_t port_id[3]; uint8_t port_id[3];
} port_id; } port_id;
struct {
uint8_t reserved;
uint8_t domain;
uint8_t area;
uint8_t port_type;
} gpn_ft;
struct { struct {
uint8_t port_type; uint8_t port_type;
uint8_t domain; uint8_t domain;
...@@ -2852,6 +2868,27 @@ struct ct_sns_gid_pt_data { ...@@ -2852,6 +2868,27 @@ struct ct_sns_gid_pt_data {
uint8_t port_id[3]; uint8_t port_id[3];
}; };
/* It's the same for both GPN_FT and GNN_FT */
struct ct_sns_gpnft_rsp {
struct {
struct ct_cmd_hdr header;
uint16_t response;
uint16_t residual;
uint8_t fragment_id;
uint8_t reason_code;
uint8_t explanation_code;
uint8_t vendor_unique;
};
/* Assume the largest number of targets for the union */
struct ct_sns_gpn_ft_data {
u8 control_byte;
u8 port_id[3];
u32 reserved;
u8 port_name[8];
} entries[1];
};
/* CT command response */
struct ct_sns_rsp { struct ct_sns_rsp {
struct ct_rsp_hdr header; struct ct_rsp_hdr header;
...@@ -2927,6 +2964,24 @@ struct ct_sns_pkt { ...@@ -2927,6 +2964,24 @@ struct ct_sns_pkt {
} p; } p;
}; };
struct ct_sns_gpnft_pkt {
union {
struct ct_sns_req req;
struct ct_sns_gpnft_rsp rsp;
} p;
};
struct fab_scan_rp {
port_id_t id;
u8 port_name[8];
u8 node_name[8];
};
struct fab_scan {
struct fab_scan_rp *l;
u32 size;
};
/* /*
* SNS command structures -- for 2200 compatibility. * SNS command structures -- for 2200 compatibility.
*/ */
...@@ -3143,6 +3198,11 @@ enum qla_work_type { ...@@ -3143,6 +3198,11 @@ enum qla_work_type {
QLA_EVT_RELOGIN, QLA_EVT_RELOGIN,
QLA_EVT_ASYNC_PRLO, QLA_EVT_ASYNC_PRLO,
QLA_EVT_ASYNC_PRLO_DONE, QLA_EVT_ASYNC_PRLO_DONE,
QLA_EVT_GPNFT,
QLA_EVT_GPNFT_DONE,
QLA_EVT_GNNFT_DONE,
QLA_EVT_GNNID,
QLA_EVT_GFPNID,
}; };
...@@ -3184,7 +3244,9 @@ struct qla_work_evt { ...@@ -3184,7 +3244,9 @@ struct qla_work_evt {
struct { struct {
port_id_t id; port_id_t id;
u8 port_name[8]; u8 port_name[8];
u8 node_name[8];
void *pla; void *pla;
u8 fc4_type;
} new_sess; } new_sess;
struct { /*Get PDB, Get Speed, update fcport, gnl, gidpn */ struct { /*Get PDB, Get Speed, update fcport, gnl, gidpn */
fc_port_t *fcport; fc_port_t *fcport;
...@@ -3195,6 +3257,9 @@ struct qla_work_evt { ...@@ -3195,6 +3257,9 @@ struct qla_work_evt {
u8 iocb[IOCB_SIZE]; u8 iocb[IOCB_SIZE];
int type; int type;
} nack; } nack;
struct {
u8 fc4_type;
} gpnft;
} u; } u;
}; };
...@@ -3729,6 +3794,8 @@ struct qla_hw_data { ...@@ -3729,6 +3794,8 @@ struct qla_hw_data {
(IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha))
#define IS_EXLOGIN_OFFLD_CAPABLE(ha) \ #define IS_EXLOGIN_OFFLD_CAPABLE(ha) \
(IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha))
#define USE_ASYNC_SCAN(ha) (IS_QLA25XX(ha) || IS_QLA81XX(ha) ||\
IS_QLA83XX(ha) || IS_QLA27XX(ha))
/* HBA serial number */ /* HBA serial number */
uint8_t serial0; uint8_t serial0;
...@@ -3811,7 +3878,7 @@ struct qla_hw_data { ...@@ -3811,7 +3878,7 @@ struct qla_hw_data {
int exchoffld_size; int exchoffld_size;
int exchoffld_count; int exchoffld_count;
void *swl; void *swl;
/* These are used by mailbox operations. */ /* These are used by mailbox operations. */
uint16_t mailbox_out[MAILBOX_REGISTER_COUNT]; uint16_t mailbox_out[MAILBOX_REGISTER_COUNT];
...@@ -4271,6 +4338,7 @@ typedef struct scsi_qla_host { ...@@ -4271,6 +4338,7 @@ typedef struct scsi_qla_host {
uint8_t n2n_port_name[WWN_SIZE]; uint8_t n2n_port_name[WWN_SIZE];
uint16_t n2n_id; uint16_t n2n_id;
struct list_head gpnid_list; struct list_head gpnid_list;
struct fab_scan scan;
} scsi_qla_host_t; } scsi_qla_host_t;
struct qla27xx_image_status { struct qla27xx_image_status {
......
...@@ -105,8 +105,8 @@ int qla24xx_async_gpdb(struct scsi_qla_host *, fc_port_t *, u8); ...@@ -105,8 +105,8 @@ int qla24xx_async_gpdb(struct scsi_qla_host *, fc_port_t *, u8);
int qla24xx_async_prli(struct scsi_qla_host *, fc_port_t *); int qla24xx_async_prli(struct scsi_qla_host *, fc_port_t *);
int qla24xx_async_notify_ack(scsi_qla_host_t *, fc_port_t *, int qla24xx_async_notify_ack(scsi_qla_host_t *, fc_port_t *,
struct imm_ntfy_from_isp *, int); struct imm_ntfy_from_isp *, int);
int qla24xx_post_newsess_work(struct scsi_qla_host *, port_id_t *, u8 *, int qla24xx_post_newsess_work(struct scsi_qla_host *, port_id_t *, u8 *, u8*,
void *); void *, u8);
int qla24xx_fcport_handle_login(struct scsi_qla_host *, fc_port_t *); int qla24xx_fcport_handle_login(struct scsi_qla_host *, fc_port_t *);
int qla24xx_detect_sfp(scsi_qla_host_t *vha); int qla24xx_detect_sfp(scsi_qla_host_t *vha);
int qla24xx_post_gpdb_work(struct scsi_qla_host *, fc_port_t *, u8); int qla24xx_post_gpdb_work(struct scsi_qla_host *, fc_port_t *, u8);
...@@ -655,9 +655,20 @@ void qla24xx_handle_gpnid_event(scsi_qla_host_t *, struct event_arg *); ...@@ -655,9 +655,20 @@ void qla24xx_handle_gpnid_event(scsi_qla_host_t *, struct event_arg *);
int qla24xx_post_gpsc_work(struct scsi_qla_host *, fc_port_t *); int qla24xx_post_gpsc_work(struct scsi_qla_host *, fc_port_t *);
int qla24xx_async_gpsc(scsi_qla_host_t *, fc_port_t *); int qla24xx_async_gpsc(scsi_qla_host_t *, fc_port_t *);
void qla24xx_handle_gpsc_event(scsi_qla_host_t *, struct event_arg *);
int qla2x00_mgmt_svr_login(scsi_qla_host_t *); int qla2x00_mgmt_svr_login(scsi_qla_host_t *);
void qla24xx_handle_gffid_event(scsi_qla_host_t *vha, struct event_arg *ea); void qla24xx_handle_gffid_event(scsi_qla_host_t *vha, struct event_arg *ea);
int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport); int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport);
int qla24xx_async_gpnft(scsi_qla_host_t *, u8);
void qla24xx_async_gpnft_done(scsi_qla_host_t *, srb_t *);
void qla24xx_async_gnnft_done(scsi_qla_host_t *, srb_t *);
int qla24xx_async_gnnid(scsi_qla_host_t *, fc_port_t *);
void qla24xx_handle_gnnid_event(scsi_qla_host_t *, struct event_arg *);
int qla24xx_post_gnnid_work(struct scsi_qla_host *, fc_port_t *);
int qla24xx_post_gfpnid_work(struct scsi_qla_host *, fc_port_t *);
int qla24xx_async_gfpnid(scsi_qla_host_t *, fc_port_t *);
void qla24xx_handle_gfpnid_event(scsi_qla_host_t *, struct event_arg *);
/* /*
* Global Function Prototypes in qla_attr.c source file. * Global Function Prototypes in qla_attr.c source file.
*/ */
......
此差异已折叠。
...@@ -41,7 +41,7 @@ static void qla24xx_handle_plogi_done_event(struct scsi_qla_host *, ...@@ -41,7 +41,7 @@ static void qla24xx_handle_plogi_done_event(struct scsi_qla_host *,
struct event_arg *); struct event_arg *);
static void qla24xx_handle_prli_done_event(struct scsi_qla_host *, static void qla24xx_handle_prli_done_event(struct scsi_qla_host *,
struct event_arg *); struct event_arg *);
static void qla24xx_handle_gpdb_event(scsi_qla_host_t *, struct event_arg *); static void __qla24xx_handle_gpdb_event(scsi_qla_host_t *, struct event_arg *);
/* SRB Extensions ---------------------------------------------------------- */ /* SRB Extensions ---------------------------------------------------------- */
...@@ -188,8 +188,11 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport, ...@@ -188,8 +188,11 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
fcport->flags |= FCF_ASYNC_SENT; fcport->flags |= FCF_ASYNC_SENT;
fcport->logout_completed = 0; fcport->logout_completed = 0;
fcport->disc_state = DSC_LOGIN_PEND;
sp->type = SRB_LOGIN_CMD; sp->type = SRB_LOGIN_CMD;
sp->name = "login"; sp->name = "login";
sp->gen1 = fcport->rscn_gen;
sp->gen2 = fcport->login_gen;
qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2); qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
lio = &sp->u.iocb_cmd; lio = &sp->u.iocb_cmd;
...@@ -336,7 +339,36 @@ qla2x00_async_prlo(struct scsi_qla_host *vha, fc_port_t *fcport) ...@@ -336,7 +339,36 @@ qla2x00_async_prlo(struct scsi_qla_host *vha, fc_port_t *fcport)
static static
void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, struct event_arg *ea) void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, struct event_arg *ea)
{ {
qla24xx_handle_gpdb_event(vha, ea); if (ea->rc) {
ql_dbg(ql_dbg_disc, vha, 0x2066,
"%s %8phC: adisc fail: post delete\n",
__func__, ea->fcport->port_name);
qlt_schedule_sess_for_deletion(ea->fcport, 1);
return;
}
ql_dbg(ql_dbg_disc, vha, 0x20d2,
"%s %8phC DS %d LS %d\n", __func__, ea->fcport->port_name,
ea->fcport->disc_state, ea->fcport->fw_login_state);
if (ea->fcport->disc_state == DSC_DELETE_PEND)
return;
if (ea->sp->gen2 != ea->fcport->login_gen) {
/* target side must have changed it. */
ql_dbg(ql_dbg_disc, vha, 0x20d3,
"%s %8phC generation changed rscn %d|%d login %d|%d\n",
__func__, ea->fcport->port_name, ea->fcport->last_rscn_gen,
ea->fcport->rscn_gen, ea->fcport->last_login_gen,
ea->fcport->login_gen);
return;
} else if (ea->sp->gen1 != ea->fcport->rscn_gen) {
ql_dbg(ql_dbg_disc, vha, 0x20d4, "%s %d %8phC post gidpn\n",
__func__, __LINE__, ea->fcport->port_name);
qla24xx_post_gidpn_work(vha, ea->fcport);
return;
}
__qla24xx_handle_gpdb_event(vha, ea);
} }
static void static void
...@@ -409,10 +441,14 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha, ...@@ -409,10 +441,14 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
u16 i, n, found = 0, loop_id; u16 i, n, found = 0, loop_id;
port_id_t id; port_id_t id;
u64 wwn; u64 wwn;
u8 opt = 0, current_login_state; u16 data[2];
u8 current_login_state;
fcport = ea->fcport; fcport = ea->fcport;
if (fcport->disc_state == DSC_DELETE_PEND)
return;
if (ea->rc) { /* rval */ if (ea->rc) { /* rval */
if (fcport->login_retry == 0) { if (fcport->login_retry == 0) {
fcport->login_retry = vha->hw->login_retry_count; fcport->login_retry = vha->hw->login_retry_count;
...@@ -506,8 +542,14 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha, ...@@ -506,8 +542,14 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
ql_dbg(ql_dbg_disc, vha, 0x20e4, ql_dbg(ql_dbg_disc, vha, 0x20e4,
"%s %d %8phC post gpdb\n", "%s %d %8phC post gpdb\n",
__func__, __LINE__, fcport->port_name); __func__, __LINE__, fcport->port_name);
opt = PDO_FORCE_ADISC;
qla24xx_post_gpdb_work(vha, fcport, opt); if ((e->prli_svc_param_word_3[0] & BIT_4) == 0)
fcport->port_type = FCT_INITIATOR;
else
fcport->port_type = FCT_TARGET;
data[0] = data[1] = 0;
qla2x00_post_async_adisc_work(vha, fcport, data);
break; break;
case DSC_LS_PORT_UNAVAIL: case DSC_LS_PORT_UNAVAIL:
default: default:
...@@ -572,6 +614,7 @@ qla24xx_async_gnl_sp_done(void *s, int res) ...@@ -572,6 +614,7 @@ qla24xx_async_gnl_sp_done(void *s, int res)
struct get_name_list_extended *e; struct get_name_list_extended *e;
u64 wwn; u64 wwn;
struct list_head h; struct list_head h;
bool found = false;
ql_dbg(ql_dbg_disc, vha, 0x20e7, ql_dbg(ql_dbg_disc, vha, 0x20e7,
"Async done-%s res %x mb[1]=%x mb[2]=%x \n", "Async done-%s res %x mb[1]=%x mb[2]=%x \n",
...@@ -621,6 +664,38 @@ qla24xx_async_gnl_sp_done(void *s, int res) ...@@ -621,6 +664,38 @@ qla24xx_async_gnl_sp_done(void *s, int res)
qla2x00_fcport_event_handler(vha, &ea); qla2x00_fcport_event_handler(vha, &ea);
} }
/* create new fcport if fw has knowledge of new sessions */
for (i = 0; i < n; i++) {
port_id_t id;
u64 wwnn;
e = &vha->gnl.l[i];
wwn = wwn_to_u64(e->port_name);
found = false;
list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) {
if (!memcmp((u8 *)&wwn, fcport->port_name,
WWN_SIZE)) {
found = true;
break;
}
}
id.b.domain = e->port_id[0];
id.b.area = e->port_id[1];
id.b.al_pa = e->port_id[2];
id.b.rsvd_1 = 0;
if (!found && wwn && !IS_SW_RESV_ADDR(id)) {
ql_dbg(ql_dbg_disc, vha, 0x2065,
"%s %d %8phC post new sess\n",
__func__, __LINE__, (u8 *)&wwn);
wwnn = wwn_to_u64(e->node_name);
qla24xx_post_newsess_work(vha, &id, (u8 *)&wwn,
(u8 *)&wwnn, NULL, FC4_TYPE_UNKNOWN);
}
}
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
sp->free(sp); sp->free(sp);
...@@ -715,10 +790,8 @@ void qla24xx_async_gpdb_sp_done(void *s, int res) ...@@ -715,10 +790,8 @@ void qla24xx_async_gpdb_sp_done(void *s, int res)
struct srb *sp = s; struct srb *sp = s;
struct scsi_qla_host *vha = sp->vha; struct scsi_qla_host *vha = sp->vha;
struct qla_hw_data *ha = vha->hw; struct qla_hw_data *ha = vha->hw;
struct port_database_24xx *pd;
fc_port_t *fcport = sp->fcport; fc_port_t *fcport = sp->fcport;
u16 *mb = sp->u.iocb_cmd.u.mbx.in_mb; u16 *mb = sp->u.iocb_cmd.u.mbx.in_mb;
int rval = QLA_SUCCESS;
struct event_arg ea; struct event_arg ea;
ql_dbg(ql_dbg_disc, vha, 0x20db, ql_dbg(ql_dbg_disc, vha, 0x20db,
...@@ -727,19 +800,8 @@ void qla24xx_async_gpdb_sp_done(void *s, int res) ...@@ -727,19 +800,8 @@ void qla24xx_async_gpdb_sp_done(void *s, int res)
fcport->flags &= ~FCF_ASYNC_SENT; fcport->flags &= ~FCF_ASYNC_SENT;
if (res) {
rval = res;
goto gpd_error_out;
}
pd = (struct port_database_24xx *)sp->u.iocb_cmd.u.mbx.in;
rval = __qla24xx_parse_gpdb(vha, fcport, pd);
gpd_error_out:
memset(&ea, 0, sizeof(ea)); memset(&ea, 0, sizeof(ea));
ea.event = FCME_GPDB_DONE; ea.event = FCME_GPDB_DONE;
ea.rc = rval;
ea.fcport = fcport; ea.fcport = fcport;
ea.sp = sp; ea.sp = sp;
...@@ -934,41 +996,10 @@ int qla24xx_async_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt) ...@@ -934,41 +996,10 @@ int qla24xx_async_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
} }
static static
void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea) void __qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
{ {
int rval = ea->rc;
fc_port_t *fcport = ea->fcport;
unsigned long flags; unsigned long flags;
fcport->flags &= ~FCF_ASYNC_SENT;
ql_dbg(ql_dbg_disc, vha, 0x20d2,
"%s %8phC DS %d LS %d rval %d\n", __func__, fcport->port_name,
fcport->disc_state, fcport->fw_login_state, rval);
if (ea->sp->gen2 != fcport->login_gen) {
/* target side must have changed it. */
ql_dbg(ql_dbg_disc, vha, 0x20d3,
"%s %8phC generation changed rscn %d|%d login %d|%d \n",
__func__, fcport->port_name, fcport->last_rscn_gen,
fcport->rscn_gen, fcport->last_login_gen,
fcport->login_gen);
set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
return;
} else if (ea->sp->gen1 != fcport->rscn_gen) {
ql_dbg(ql_dbg_disc, vha, 0x20d4, "%s %d %8phC post gidpn\n",
__func__, __LINE__, fcport->port_name);
qla24xx_post_gidpn_work(vha, fcport);
return;
}
if (rval != QLA_SUCCESS) {
ql_dbg(ql_dbg_disc, vha, 0x20d5, "%s %d %8phC post del sess\n",
__func__, __LINE__, fcport->port_name);
qlt_schedule_sess_for_deletion_lock(fcport);
return;
}
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
ea->fcport->login_gen++; ea->fcport->login_gen++;
ea->fcport->deleted = 0; ea->fcport->deleted = 0;
...@@ -982,32 +1013,81 @@ void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea) ...@@ -982,32 +1013,81 @@ void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
!vha->hw->flags.gpsc_supported) { !vha->hw->flags.gpsc_supported) {
ql_dbg(ql_dbg_disc, vha, 0x20d6, ql_dbg(ql_dbg_disc, vha, 0x20d6,
"%s %d %8phC post upd_fcport fcp_cnt %d\n", "%s %d %8phC post upd_fcport fcp_cnt %d\n",
__func__, __LINE__, fcport->port_name, __func__, __LINE__, ea->fcport->port_name,
vha->fcport_count); vha->fcport_count);
qla24xx_post_upd_fcport_work(vha, fcport); qla24xx_post_upd_fcport_work(vha, ea->fcport);
} else { } else {
ql_dbg(ql_dbg_disc, vha, 0x20d7, if (ea->fcport->id_changed) {
"%s %d %8phC post gpsc fcp_cnt %d\n", ea->fcport->id_changed = 0;
__func__, __LINE__, fcport->port_name, ql_dbg(ql_dbg_disc, vha, 0x20d7,
vha->fcport_count); "%s %d %8phC post gfpnid fcp_cnt %d\n",
__func__, __LINE__, ea->fcport->port_name,
qla24xx_post_gpsc_work(vha, fcport); vha->fcport_count);
qla24xx_post_gfpnid_work(vha, ea->fcport);
} else {
ql_dbg(ql_dbg_disc, vha, 0x20d7,
"%s %d %8phC post gpsc fcp_cnt %d\n",
__func__, __LINE__, ea->fcport->port_name,
vha->fcport_count);
qla24xx_post_gpsc_work(vha, ea->fcport);
}
} }
} else if (ea->fcport->login_succ) { } else if (ea->fcport->login_succ) {
/* /*
* We have an existing session. A late RSCN delivery * We have an existing session. A late RSCN delivery
* must have triggered the session to be re-validate. * must have triggered the session to be re-validate.
* session is still valid. * Session is still valid.
*/ */
ql_dbg(ql_dbg_disc, vha, 0x20d6, ql_dbg(ql_dbg_disc, vha, 0x20d6,
"%s %d %8phC session revalidate success\n", "%s %d %8phC session revalidate success\n",
__func__, __LINE__, fcport->port_name); __func__, __LINE__, ea->fcport->port_name);
fcport->disc_state = DSC_LOGIN_COMPLETE; ea->fcport->disc_state = DSC_LOGIN_COMPLETE;
} }
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
} /* gpdb event */ }
static
void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
{
int rval = ea->rc;
fc_port_t *fcport = ea->fcport;
struct port_database_24xx *pd;
struct srb *sp = ea->sp;
pd = (struct port_database_24xx *)sp->u.iocb_cmd.u.mbx.in;
fcport->flags &= ~FCF_ASYNC_SENT;
ql_dbg(ql_dbg_disc, vha, 0x20d2,
"%s %8phC DS %d LS %d rval %d\n", __func__, fcport->port_name,
fcport->disc_state, pd->current_login_state, rval);
if (fcport->disc_state == DSC_DELETE_PEND)
return;
switch (pd->current_login_state) {
case PDS_PRLI_COMPLETE:
__qla24xx_parse_gpdb(vha, fcport, pd);
break;
case PDS_PLOGI_PENDING:
case PDS_PLOGI_COMPLETE:
case PDS_PRLI_PENDING:
case PDS_PRLI2_PENDING:
ql_dbg(ql_dbg_disc, vha, 0x20d5, "%s %d %8phC relogin needed\n",
__func__, __LINE__, fcport->port_name);
set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
return;
case PDS_LOGO_PENDING:
case PDS_PORT_UNAVAILABLE:
default:
ql_dbg(ql_dbg_disc, vha, 0x20d5, "%s %d %8phC post del sess\n",
__func__, __LINE__, fcport->port_name);
qlt_schedule_sess_for_deletion_lock(fcport);
return;
}
__qla24xx_handle_gpdb_event(vha, ea);
} /* gpdb event */
static void qla_chk_n2n_b4_login(struct scsi_qla_host *vha, fc_port_t *fcport) static void qla_chk_n2n_b4_login(struct scsi_qla_host *vha, fc_port_t *fcport)
{ {
...@@ -1048,21 +1128,21 @@ static void qla_chk_n2n_b4_login(struct scsi_qla_host *vha, fc_port_t *fcport) ...@@ -1048,21 +1128,21 @@ static void qla_chk_n2n_b4_login(struct scsi_qla_host *vha, fc_port_t *fcport)
int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport) int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
{ {
u16 data[2]; u16 data[2];
if (fcport->login_retry == 0) u64 wwn;
return 0;
if (fcport->scan_state != QLA_FCPORT_FOUND)
return 0;
ql_dbg(ql_dbg_disc, vha, 0x20d8, ql_dbg(ql_dbg_disc, vha, 0x20d8,
"%s %8phC DS %d LS %d P %d fl %x confl %p rscn %d|%d login %d|%d retry %d lid %d\n", "%s %8phC DS %d LS %d P %d fl %x confl %p rscn %d|%d login %d|%d retry %d lid %d scan %d\n",
__func__, fcport->port_name, fcport->disc_state, __func__, fcport->port_name, fcport->disc_state,
fcport->fw_login_state, fcport->login_pause, fcport->flags, fcport->fw_login_state, fcport->login_pause, fcport->flags,
fcport->conflict, fcport->last_rscn_gen, fcport->rscn_gen, fcport->conflict, fcport->last_rscn_gen, fcport->rscn_gen,
fcport->last_login_gen, fcport->login_gen, fcport->login_retry, fcport->last_login_gen, fcport->login_gen, fcport->login_retry,
fcport->loop_id); fcport->loop_id, fcport->scan_state);
fcport->login_retry--; if (fcport->login_retry == 0)
return 0;
if (fcport->scan_state != QLA_FCPORT_FOUND)
return 0;
if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) || if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
(fcport->fw_login_state == DSC_LS_PRLI_PEND)) (fcport->fw_login_state == DSC_LS_PRLI_PEND))
...@@ -1084,9 +1164,17 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport) ...@@ -1084,9 +1164,17 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
return 0; return 0;
} }
fcport->login_retry--;
switch (fcport->disc_state) { switch (fcport->disc_state) {
case DSC_DELETED: case DSC_DELETED:
if (fcport->loop_id == FC_NO_LOOP_ID) { wwn = wwn_to_u64(fcport->node_name);
if (wwn == 0) {
ql_dbg(ql_dbg_disc, vha, 0xffff,
"%s %d %8phC post GNNID\n",
__func__, __LINE__, fcport->port_name);
qla24xx_post_gnnid_work(vha, fcport);
} else if (fcport->loop_id == FC_NO_LOOP_ID) {
ql_dbg(ql_dbg_disc, vha, 0x20bd, ql_dbg(ql_dbg_disc, vha, 0x20bd,
"%s %d %8phC post gnl\n", "%s %d %8phC post gnl\n",
__func__, __LINE__, fcport->port_name); __func__, __LINE__, fcport->port_name);
...@@ -1157,7 +1245,7 @@ void qla24xx_handle_rscn_event(fc_port_t *fcport, struct event_arg *ea) ...@@ -1157,7 +1245,7 @@ void qla24xx_handle_rscn_event(fc_port_t *fcport, struct event_arg *ea)
} }
int qla24xx_post_newsess_work(struct scsi_qla_host *vha, port_id_t *id, int qla24xx_post_newsess_work(struct scsi_qla_host *vha, port_id_t *id,
u8 *port_name, void *pla) u8 *port_name, u8 *node_name, void *pla, u8 fc4_type)
{ {
struct qla_work_evt *e; struct qla_work_evt *e;
e = qla2x00_alloc_work(vha, QLA_EVT_NEW_SESS); e = qla2x00_alloc_work(vha, QLA_EVT_NEW_SESS);
...@@ -1166,36 +1254,14 @@ int qla24xx_post_newsess_work(struct scsi_qla_host *vha, port_id_t *id, ...@@ -1166,36 +1254,14 @@ int qla24xx_post_newsess_work(struct scsi_qla_host *vha, port_id_t *id,
e->u.new_sess.id = *id; e->u.new_sess.id = *id;
e->u.new_sess.pla = pla; e->u.new_sess.pla = pla;
e->u.new_sess.fc4_type = fc4_type;
memcpy(e->u.new_sess.port_name, port_name, WWN_SIZE); memcpy(e->u.new_sess.port_name, port_name, WWN_SIZE);
if (node_name)
memcpy(e->u.new_sess.node_name, node_name, WWN_SIZE);
return qla2x00_post_work(vha, e); return qla2x00_post_work(vha, e);
} }
static
int qla24xx_handle_delete_done_event(scsi_qla_host_t *vha,
struct event_arg *ea)
{
fc_port_t *fcport = ea->fcport;
if (test_bit(UNLOADING, &vha->dpc_flags))
return 0;
switch (vha->host->active_mode) {
case MODE_INITIATOR:
case MODE_DUAL:
if (fcport->scan_state == QLA_FCPORT_FOUND)
qla24xx_fcport_handle_login(vha, fcport);
break;
case MODE_TARGET:
default:
/* no-op */
break;
}
return 0;
}
static static
void qla24xx_handle_relogin_event(scsi_qla_host_t *vha, void qla24xx_handle_relogin_event(scsi_qla_host_t *vha,
struct event_arg *ea) struct event_arg *ea)
...@@ -1261,6 +1327,7 @@ void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea) ...@@ -1261,6 +1327,7 @@ void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea)
case FCME_GIDPN_DONE: case FCME_GIDPN_DONE:
case FCME_GPSC_DONE: case FCME_GPSC_DONE:
case FCME_GPNID_DONE: case FCME_GPNID_DONE:
case FCME_GNNID_DONE:
if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags) || if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags) ||
test_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags)) test_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags))
return; return;
...@@ -1337,7 +1404,7 @@ void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea) ...@@ -1337,7 +1404,7 @@ void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea)
qla24xx_handle_gnl_done_event(vha, ea); qla24xx_handle_gnl_done_event(vha, ea);
break; break;
case FCME_GPSC_DONE: case FCME_GPSC_DONE:
qla24xx_post_upd_fcport_work(vha, ea->fcport); qla24xx_handle_gpsc_event(vha, ea);
break; break;
case FCME_PLOGI_DONE: /* Initiator side sent LLIOCB */ case FCME_PLOGI_DONE: /* Initiator side sent LLIOCB */
qla24xx_handle_plogi_done_event(vha, ea); qla24xx_handle_plogi_done_event(vha, ea);
...@@ -1354,12 +1421,15 @@ void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea) ...@@ -1354,12 +1421,15 @@ void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea)
case FCME_GFFID_DONE: case FCME_GFFID_DONE:
qla24xx_handle_gffid_event(vha, ea); qla24xx_handle_gffid_event(vha, ea);
break; break;
case FCME_DELETE_DONE:
qla24xx_handle_delete_done_event(vha, ea);
break;
case FCME_ADISC_DONE: case FCME_ADISC_DONE:
qla24xx_handle_adisc_event(vha, ea); qla24xx_handle_adisc_event(vha, ea);
break; break;
case FCME_GNNID_DONE:
qla24xx_handle_gnnid_event(vha, ea);
break;
case FCME_GFPNID_DONE:
qla24xx_handle_gfpnid_event(vha, ea);
break;
default: default:
BUG_ON(1); BUG_ON(1);
break; break;
...@@ -1568,6 +1638,33 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea) ...@@ -1568,6 +1638,33 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
u16 lid; u16 lid;
struct fc_port *conflict_fcport; struct fc_port *conflict_fcport;
unsigned long flags; unsigned long flags;
struct fc_port *fcport = ea->fcport;
if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
(fcport->fw_login_state == DSC_LS_PRLI_PEND)) {
ql_dbg(ql_dbg_disc, vha, 0x20ea,
"%s %d %8phC Remote is trying to login\n",
__func__, __LINE__, fcport->port_name);
return;
}
if (fcport->disc_state == DSC_DELETE_PEND)
return;
if (ea->sp->gen2 != fcport->login_gen) {
/* target side must have changed it. */
ql_dbg(ql_dbg_disc, vha, 0x20d3,
"%s %8phC generation changed rscn %d|%d login %d|%d\n",
__func__, fcport->port_name, fcport->last_rscn_gen,
fcport->rscn_gen, fcport->last_login_gen,
fcport->login_gen);
return;
} else if (ea->sp->gen1 != fcport->rscn_gen) {
ql_dbg(ql_dbg_disc, vha, 0x20d4, "%s %d %8phC post gidpn\n",
__func__, __LINE__, fcport->port_name);
qla24xx_post_gidpn_work(vha, fcport);
return;
}
switch (ea->data[0]) { switch (ea->data[0]) {
case MBS_COMMAND_COMPLETE: case MBS_COMMAND_COMPLETE:
...@@ -5124,7 +5221,14 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) ...@@ -5124,7 +5221,14 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
* will be newer than discovery_gen. */ * will be newer than discovery_gen. */
qlt_do_generation_tick(vha, &discovery_gen); qlt_do_generation_tick(vha, &discovery_gen);
rval = qla2x00_find_all_fabric_devs(vha); if (USE_ASYNC_SCAN(ha)) {
rval = QLA_SUCCESS;
rval = qla24xx_async_gpnft(vha, FC4_TYPE_FCP_SCSI);
if (rval)
set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
} else {
rval = qla2x00_find_all_fabric_devs(vha);
}
if (rval != QLA_SUCCESS) if (rval != QLA_SUCCESS)
break; break;
} while (0); } while (0);
......
...@@ -3904,7 +3904,10 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, ...@@ -3904,7 +3904,10 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
id.b.area = rptid_entry->u.f2.remote_nport_id[1]; id.b.area = rptid_entry->u.f2.remote_nport_id[1];
id.b.domain = rptid_entry->u.f2.remote_nport_id[2]; id.b.domain = rptid_entry->u.f2.remote_nport_id[2];
qla24xx_post_newsess_work(vha, &id, qla24xx_post_newsess_work(vha, &id,
rptid_entry->u.f2.port_name, NULL); rptid_entry->u.f2.port_name,
rptid_entry->u.f2.node_name,
NULL,
FC4_TYPE_UNKNOWN);
} }
} }
} }
......
...@@ -3639,6 +3639,8 @@ qla2x00_remove_one(struct pci_dev *pdev) ...@@ -3639,6 +3639,8 @@ qla2x00_remove_one(struct pci_dev *pdev)
dma_free_coherent(&ha->pdev->dev, dma_free_coherent(&ha->pdev->dev,
base_vha->gnl.size, base_vha->gnl.l, base_vha->gnl.ldma); base_vha->gnl.size, base_vha->gnl.l, base_vha->gnl.ldma);
vfree(base_vha->scan.l);
if (IS_QLAFX00(ha)) if (IS_QLAFX00(ha))
qlafx00_driver_shutdown(base_vha, 20); qlafx00_driver_shutdown(base_vha, 20);
...@@ -4587,6 +4589,18 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht, ...@@ -4587,6 +4589,18 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
return NULL; return NULL;
} }
/* todo: what about ext login? */
vha->scan.size = ha->max_fibre_devices * sizeof(struct fab_scan_rp);
vha->scan.l = vmalloc(vha->scan.size);
if (!vha->scan.l) {
ql_log(ql_log_fatal, vha, 0xd04a,
"Alloc failed for scan database.\n");
dma_free_coherent(&ha->pdev->dev, vha->gnl.size,
vha->gnl.l, vha->gnl.ldma);
scsi_remove_host(vha->host);
return NULL;
}
sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no); sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no);
ql_dbg(ql_dbg_init, vha, 0x0041, ql_dbg(ql_dbg_init, vha, 0x0041,
"Allocated the host=%p hw=%p vha=%p dev_name=%s", "Allocated the host=%p hw=%p vha=%p dev_name=%s",
...@@ -4760,6 +4774,7 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) ...@@ -4760,6 +4774,7 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
struct qlt_plogi_ack_t *pla = struct qlt_plogi_ack_t *pla =
(struct qlt_plogi_ack_t *)e->u.new_sess.pla; (struct qlt_plogi_ack_t *)e->u.new_sess.pla;
uint8_t free_fcport = 0; uint8_t free_fcport = 0;
u64 wwn;
ql_dbg(ql_dbg_disc, vha, 0xffff, ql_dbg(ql_dbg_disc, vha, 0xffff,
"%s %d %8phC enter\n", "%s %d %8phC enter\n",
...@@ -4785,9 +4800,10 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) ...@@ -4785,9 +4800,10 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL); fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
if (fcport) { if (fcport) {
fcport->d_id = e->u.new_sess.id; fcport->d_id = e->u.new_sess.id;
fcport->scan_state = QLA_FCPORT_FOUND;
fcport->flags |= FCF_FABRIC_DEVICE; fcport->flags |= FCF_FABRIC_DEVICE;
fcport->fw_login_state = DSC_LS_PLOGI_PEND; fcport->fw_login_state = DSC_LS_PLOGI_PEND;
if (e->u.new_sess.fc4_type == FC4_TYPE_FCP_SCSI)
fcport->fc4_type = FC4_TYPE_FCP_SCSI;
memcpy(fcport->port_name, e->u.new_sess.port_name, memcpy(fcport->port_name, e->u.new_sess.port_name,
WWN_SIZE); WWN_SIZE);
...@@ -4802,7 +4818,7 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) ...@@ -4802,7 +4818,7 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
} }
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
/* search again to make sure one else got ahead */ /* search again to make sure no one else got ahead */
tfcp = qla2x00_find_fcport_by_wwpn(vha, tfcp = qla2x00_find_fcport_by_wwpn(vha,
e->u.new_sess.port_name, 1); e->u.new_sess.port_name, 1);
if (tfcp) { if (tfcp) {
...@@ -4829,6 +4845,10 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) ...@@ -4829,6 +4845,10 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
if (N2N_TOPO(vha->hw)) if (N2N_TOPO(vha->hw))
fcport->flags &= ~FCF_FABRIC_DEVICE; fcport->flags &= ~FCF_FABRIC_DEVICE;
fcport->id_changed = 1;
fcport->scan_state = QLA_FCPORT_FOUND;
memcpy(fcport->node_name, e->u.new_sess.node_name, WWN_SIZE);
if (pla) { if (pla) {
if (pla->iocb.u.isp24.status_subcode == ELS_PRLI) { if (pla->iocb.u.isp24.status_subcode == ELS_PRLI) {
u16 wd3_lo; u16 wd3_lo;
...@@ -4881,7 +4901,13 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) ...@@ -4881,7 +4901,13 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
} }
} }
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
qla24xx_async_gnl(vha, fcport);
wwn = wwn_to_u64(fcport->node_name);
if (!wwn)
qla24xx_async_gnnid(vha, fcport);
else
qla24xx_async_gnl(vha, fcport);
} }
} }
...@@ -4980,6 +5006,21 @@ qla2x00_do_work(struct scsi_qla_host *vha) ...@@ -4980,6 +5006,21 @@ qla2x00_do_work(struct scsi_qla_host *vha)
qla2x00_async_prlo_done(vha, e->u.logio.fcport, qla2x00_async_prlo_done(vha, e->u.logio.fcport,
e->u.logio.data); e->u.logio.data);
break; break;
case QLA_EVT_GPNFT:
qla24xx_async_gpnft(vha, e->u.gpnft.fc4_type);
break;
case QLA_EVT_GPNFT_DONE:
qla24xx_async_gpnft_done(vha, e->u.iosb.sp);
break;
case QLA_EVT_GNNFT_DONE:
qla24xx_async_gnnft_done(vha, e->u.iosb.sp);
break;
case QLA_EVT_GNNID:
qla24xx_async_gnnid(vha, e->u.fcport.fcport);
break;
case QLA_EVT_GFPNID:
qla24xx_async_gfpnid(vha, e->u.fcport.fcport);
break;
} }
if (e->flags & QLA_EVT_FLAG_FREE) if (e->flags & QLA_EVT_FLAG_FREE)
kfree(e); kfree(e);
......
...@@ -969,7 +969,6 @@ static void qlt_free_session_done(struct work_struct *work) ...@@ -969,7 +969,6 @@ static void qlt_free_session_done(struct work_struct *work)
struct qla_hw_data *ha = vha->hw; struct qla_hw_data *ha = vha->hw;
unsigned long flags; unsigned long flags;
bool logout_started = false; bool logout_started = false;
struct event_arg ea;
scsi_qla_host_t *base_vha; scsi_qla_host_t *base_vha;
struct qlt_plogi_ack_t *own = struct qlt_plogi_ack_t *own =
sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN]; sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN];
...@@ -1121,11 +1120,18 @@ static void qlt_free_session_done(struct work_struct *work) ...@@ -1121,11 +1120,18 @@ static void qlt_free_session_done(struct work_struct *work)
if (test_bit(PFLG_DRIVER_REMOVING, &base_vha->pci_flags)) if (test_bit(PFLG_DRIVER_REMOVING, &base_vha->pci_flags))
return; return;
if (!tgt || !tgt->tgt_stop) { if ((!tgt || !tgt->tgt_stop) && !LOOP_TRANSITION(vha)) {
memset(&ea, 0, sizeof(ea)); switch (vha->host->active_mode) {
ea.event = FCME_DELETE_DONE; case MODE_INITIATOR:
ea.fcport = sess; case MODE_DUAL:
qla2x00_fcport_event_handler(vha, &ea); set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
qla2xxx_wake_dpc(vha);
break;
case MODE_TARGET:
default:
/* no-op */
break;
}
} }
} }
...@@ -4318,6 +4324,7 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha, ...@@ -4318,6 +4324,7 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
struct fc_port *sess; struct fc_port *sess;
struct qla_tgt_cmd *cmd; struct qla_tgt_cmd *cmd;
unsigned long flags; unsigned long flags;
port_id_t id;
if (unlikely(tgt->tgt_stop)) { if (unlikely(tgt->tgt_stop)) {
ql_dbg(ql_dbg_io, vha, 0x3061, ql_dbg(ql_dbg_io, vha, 0x3061,
...@@ -4325,6 +4332,12 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha, ...@@ -4325,6 +4332,12 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
return -EFAULT; return -EFAULT;
} }
id.b.al_pa = atio->u.isp24.fcp_hdr.s_id[2];
id.b.area = atio->u.isp24.fcp_hdr.s_id[1];
id.b.domain = atio->u.isp24.fcp_hdr.s_id[0];
if (IS_SW_RESV_ADDR(id))
return -EBUSY;
sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, atio->u.isp24.fcp_hdr.s_id); sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, atio->u.isp24.fcp_hdr.s_id);
if (unlikely(!sess)) { if (unlikely(!sess)) {
struct qla_tgt_sess_op *op = kzalloc(sizeof(struct qla_tgt_sess_op), struct qla_tgt_sess_op *op = kzalloc(sizeof(struct qla_tgt_sess_op),
...@@ -4739,8 +4752,16 @@ static int qlt_handle_login(struct scsi_qla_host *vha, ...@@ -4739,8 +4752,16 @@ static int qlt_handle_login(struct scsi_qla_host *vha,
ql_dbg(ql_dbg_disc, vha, 0xffff, ql_dbg(ql_dbg_disc, vha, 0xffff,
"%s %d %8phC post new sess\n", "%s %d %8phC post new sess\n",
__func__, __LINE__, iocb->u.isp24.port_name); __func__, __LINE__, iocb->u.isp24.port_name);
qla24xx_post_newsess_work(vha, &port_id, if (iocb->u.isp24.status_subcode == ELS_PLOGI)
iocb->u.isp24.port_name, pla); qla24xx_post_newsess_work(vha, &port_id,
iocb->u.isp24.port_name,
iocb->u.isp24.u.plogi.node_name,
pla, FC4_TYPE_UNKNOWN);
else
qla24xx_post_newsess_work(vha, &port_id,
iocb->u.isp24.port_name, NULL,
pla, FC4_TYPE_UNKNOWN);
goto out; goto out;
} }
...@@ -4869,6 +4890,11 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha, ...@@ -4869,6 +4890,11 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
break; break;
} }
if (IS_SW_RESV_ADDR(port_id)) {
res = 1;
break;
}
wd3_lo = le16_to_cpu(iocb->u.isp24.u.prli.wd3_lo); wd3_lo = le16_to_cpu(iocb->u.isp24.u.prli.wd3_lo);
if (wwn) { if (wwn) {
...@@ -4896,12 +4922,32 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha, ...@@ -4896,12 +4922,32 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
} }
if (sess != NULL) { if (sess != NULL) {
bool delete = false;
spin_lock_irqsave(&tgt->ha->tgt.sess_lock, flags); spin_lock_irqsave(&tgt->ha->tgt.sess_lock, flags);
switch (sess->fw_login_state) { switch (sess->fw_login_state) {
case DSC_LS_PLOGI_PEND:
case DSC_LS_PLOGI_COMP: case DSC_LS_PLOGI_COMP:
case DSC_LS_PRLI_COMP: case DSC_LS_PRLI_COMP:
break; break;
default: default:
delete = true;
break;
}
switch (sess->disc_state) {
case DSC_LOGIN_PEND:
case DSC_GPDB:
case DSC_GPSC:
case DSC_UPD_FCPORT:
case DSC_LOGIN_COMPLETE:
case DSC_ADISC:
delete = false;
break;
default:
break;
}
if (delete) {
spin_unlock_irqrestore(&tgt->ha->tgt.sess_lock, spin_unlock_irqrestore(&tgt->ha->tgt.sess_lock,
flags); flags);
/* /*
......
...@@ -993,7 +993,7 @@ struct qla_tgt_prm { ...@@ -993,7 +993,7 @@ struct qla_tgt_prm {
/* Check for Switch reserved address */ /* Check for Switch reserved address */
#define IS_SW_RESV_ADDR(_s_id) \ #define IS_SW_RESV_ADDR(_s_id) \
((_s_id.b.domain == 0xff) && (_s_id.b.area == 0xfc)) ((_s_id.b.domain == 0xff) && ((_s_id.b.area & 0xf0) == 0xf0))
#define QLA_TGT_XMIT_DATA 1 #define QLA_TGT_XMIT_DATA 1
#define QLA_TGT_XMIT_STATUS 2 #define QLA_TGT_XMIT_STATUS 2
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册