提交 edd05de1 编写于 作者: D Duane Grigsby 提交者: Martin K. Petersen

scsi: qla2xxx: Changes to support N2N logins

If we discovered a topology that is N2N then we will issue a login to
the target. If our WWPN is bigger than the target's WWPN then we will
initiate login, otherwise we will just wait for the target to initiate
login.

[mkp: many whitespace errors]
Signed-off-by: NDuane Grigsby <duane.grigsby@cavium.com>
Signed-off-by: NMichael Hernandez <michael.hernandez@cavium.com>
Signed-off-by: NHimanshu Madhani <himanshu.madhani@cavium.com>
Reviewed-by: NJohannes Thumshirn <jthumshirn@suse.de>
Tested-by: NEwan D. Milne <emilne@redhat.com>
Signed-off-by: NMartin K. Petersen <martin.petersen@oracle.com>
上级 c0c462c8
master alk-4.19.24 alk-4.19.30 alk-4.19.34 alk-4.19.36 alk-4.19.43 alk-4.19.48 alk-4.19.57 ck-4.19.67 ck-4.19.81 ck-4.19.91 github/fork/deepanshu1422/fix-typo-in-comment github/fork/haosdent/fix-typo linux-next v4.19.91 v4.19.90 v4.19.89 v4.19.88 v4.19.87 v4.19.86 v4.19.85 v4.19.84 v4.19.83 v4.19.82 v4.19.81 v4.19.80 v4.19.79 v4.19.78 v4.19.77 v4.19.76 v4.19.75 v4.19.74 v4.19.73 v4.19.72 v4.19.71 v4.19.70 v4.19.69 v4.19.68 v4.19.67 v4.19.66 v4.19.65 v4.19.64 v4.19.63 v4.19.62 v4.19.61 v4.19.60 v4.19.59 v4.19.58 v4.19.57 v4.19.56 v4.19.55 v4.19.54 v4.19.53 v4.19.52 v4.19.51 v4.19.50 v4.19.49 v4.19.48 v4.19.47 v4.19.46 v4.19.45 v4.19.44 v4.19.43 v4.19.42 v4.19.41 v4.19.40 v4.19.39 v4.19.38 v4.19.37 v4.19.36 v4.19.35 v4.19.34 v4.19.33 v4.19.32 v4.19.31 v4.19.30 v4.19.29 v4.19.28 v4.19.27 v4.19.26 v4.19.25 v4.19.24 v4.19.23 v4.19.22 v4.19.21 v4.19.20 v4.19.19 v4.19.18 v4.19.17 v4.19.16 v4.19.15 v4.19.14 v4.19.13 v4.19.12 v4.19.11 v4.19.10 v4.19.9 v4.19.8 v4.19.7 v4.19.6 v4.19.5 v4.19.4 v4.19.3 v4.19.2 v4.19.1 v4.19 v4.19-rc8 v4.19-rc7 v4.19-rc6 v4.19-rc5 v4.19-rc4 v4.19-rc3 v4.19-rc2 v4.19-rc1 ck-release-21 ck-release-20 ck-release-19.2 ck-release-19.1 ck-release-19 ck-release-18 ck-release-17.2 ck-release-17.1 ck-release-17 ck-release-16 ck-release-15.1 ck-release-15 ck-release-14 ck-release-13.2 ck-release-13 ck-release-12 ck-release-11 ck-release-10 ck-release-9 ck-release-7 alk-release-15 alk-release-14 alk-release-13.2 alk-release-13 alk-release-12 alk-release-11 alk-release-10 alk-release-9 alk-release-7
无相关合并请求
...@@ -323,6 +323,12 @@ struct els_logo_payload { ...@@ -323,6 +323,12 @@ struct els_logo_payload {
uint8_t wwpn[WWN_SIZE]; uint8_t wwpn[WWN_SIZE];
}; };
struct els_plogi_payload {
uint8_t opcode;
uint8_t rsvd[3];
uint8_t data[112];
};
struct ct_arg { struct ct_arg {
void *iocb; void *iocb;
u16 nport_handle; u16 nport_handle;
...@@ -358,6 +364,19 @@ struct srb_iocb { ...@@ -358,6 +364,19 @@ struct srb_iocb {
dma_addr_t els_logo_pyld_dma; dma_addr_t els_logo_pyld_dma;
} els_logo; } els_logo;
struct { struct {
#define ELS_DCMD_PLOGI 0x3
uint32_t flags;
uint32_t els_cmd;
struct completion comp;
struct els_plogi_payload *els_plogi_pyld;
struct els_plogi_payload *els_resp_pyld;
dma_addr_t els_plogi_pyld_dma;
dma_addr_t els_resp_pyld_dma;
uint32_t fw_status[3];
__le16 comp_status;
__le16 len;
} els_plogi;
struct {
/* /*
* Values for flags field below are as * Values for flags field below are as
* defined in tsk_mgmt_entry struct * defined in tsk_mgmt_entry struct
...@@ -2349,6 +2368,7 @@ typedef struct fc_port { ...@@ -2349,6 +2368,7 @@ typedef struct fc_port {
uint8_t fc4_type; uint8_t fc4_type;
uint8_t fc4f_nvme; uint8_t fc4f_nvme;
uint8_t scan_state; uint8_t scan_state;
uint8_t n2n_flag;
unsigned long last_queue_full; unsigned long last_queue_full;
unsigned long last_ramp_up; unsigned long last_ramp_up;
...@@ -2372,6 +2392,7 @@ typedef struct fc_port { ...@@ -2372,6 +2392,7 @@ typedef struct fc_port {
u8 iocb[IOCB_SIZE]; u8 iocb[IOCB_SIZE];
u8 current_login_state; u8 current_login_state;
u8 last_login_state; u8 last_login_state;
struct completion n2n_done;
} fc_port_t; } fc_port_t;
#define QLA_FCPORT_SCAN 1 #define QLA_FCPORT_SCAN 1
...@@ -4228,6 +4249,9 @@ typedef struct scsi_qla_host { ...@@ -4228,6 +4249,9 @@ typedef struct scsi_qla_host {
wait_queue_head_t fcport_waitQ; wait_queue_head_t fcport_waitQ;
wait_queue_head_t vref_waitq; wait_queue_head_t vref_waitq;
uint8_t min_link_speed_feat; uint8_t min_link_speed_feat;
uint8_t n2n_node_name[WWN_SIZE];
uint8_t n2n_port_name[WWN_SIZE];
uint16_t n2n_id;
} scsi_qla_host_t; } scsi_qla_host_t;
struct qla27xx_image_status { struct qla27xx_image_status {
......
...@@ -753,9 +753,7 @@ struct els_entry_24xx { ...@@ -753,9 +753,7 @@ struct els_entry_24xx {
uint8_t reserved_2; uint8_t reserved_2;
uint8_t port_id[3]; uint8_t port_id[3];
uint8_t reserved_3; uint8_t s_id[3];
uint16_t reserved_4;
uint16_t control_flags; /* Control flags. */ uint16_t control_flags; /* Control flags. */
#define ECF_PAYLOAD_DESCR_MASK (BIT_15|BIT_14|BIT_13) #define ECF_PAYLOAD_DESCR_MASK (BIT_15|BIT_14|BIT_13)
......
...@@ -45,6 +45,8 @@ extern int qla2x00_fabric_login(scsi_qla_host_t *, fc_port_t *, uint16_t *); ...@@ -45,6 +45,8 @@ extern int qla2x00_fabric_login(scsi_qla_host_t *, fc_port_t *, uint16_t *);
extern int qla2x00_local_device_login(scsi_qla_host_t *, fc_port_t *); extern int qla2x00_local_device_login(scsi_qla_host_t *, fc_port_t *);
extern int qla24xx_els_dcmd_iocb(scsi_qla_host_t *, int, port_id_t); extern int qla24xx_els_dcmd_iocb(scsi_qla_host_t *, int, port_id_t);
extern int qla24xx_els_dcmd2_iocb(scsi_qla_host_t *, int, fc_port_t *,
port_id_t);
extern void qla2x00_update_fcports(scsi_qla_host_t *); extern void qla2x00_update_fcports(scsi_qla_host_t *);
...@@ -487,6 +489,8 @@ int qla24xx_gidlist_wait(struct scsi_qla_host *, void *, dma_addr_t, ...@@ -487,6 +489,8 @@ int qla24xx_gidlist_wait(struct scsi_qla_host *, void *, dma_addr_t,
uint16_t *); uint16_t *);
int __qla24xx_parse_gpdb(struct scsi_qla_host *, fc_port_t *, int __qla24xx_parse_gpdb(struct scsi_qla_host *, fc_port_t *,
struct port_database_24xx *); struct port_database_24xx *);
int qla24xx_get_port_login_templ(scsi_qla_host_t *, dma_addr_t,
void *, uint16_t);
extern int qla27xx_get_zio_threshold(scsi_qla_host_t *, uint16_t *); extern int qla27xx_get_zio_threshold(scsi_qla_host_t *, uint16_t *);
extern int qla27xx_set_zio_threshold(scsi_qla_host_t *, uint16_t); extern int qla27xx_set_zio_threshold(scsi_qla_host_t *, uint16_t);
......
...@@ -1433,6 +1433,14 @@ qla24xx_handle_prli_done_event(struct scsi_qla_host *vha, struct event_arg *ea) ...@@ -1433,6 +1433,14 @@ qla24xx_handle_prli_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
qla24xx_post_gpdb_work(vha, ea->fcport, 0); qla24xx_post_gpdb_work(vha, ea->fcport, 0);
break; break;
default: default:
if (ea->fcport->n2n_flag) {
ql_dbg(ql_dbg_disc, vha, 0x2118,
"%s %d %8phC post fc4 prli\n",
__func__, __LINE__, ea->fcport->port_name);
ea->fcport->fc4f_nvme = 0;
ea->fcport->n2n_flag = 0;
qla24xx_post_prli_work(vha, ea->fcport);
}
ql_dbg(ql_dbg_disc, vha, 0x2119, ql_dbg(ql_dbg_disc, vha, 0x2119,
"%s %d %8phC unhandle event of %x\n", "%s %d %8phC unhandle event of %x\n",
__func__, __LINE__, ea->fcport->port_name, ea->data[0]); __func__, __LINE__, ea->fcport->port_name, ea->data[0]);
...@@ -4366,7 +4374,109 @@ qla2x00_configure_loop(scsi_qla_host_t *vha) ...@@ -4366,7 +4374,109 @@ qla2x00_configure_loop(scsi_qla_host_t *vha)
return (rval); return (rval);
} }
/*
* N2N Login
* Updates Fibre Channel Device Database with local loop devices.
*
* Input:
* ha = adapter block pointer.
*
* Returns:
*/
static int qla24xx_n2n_handle_login(struct scsi_qla_host *vha,
fc_port_t *fcport)
{
struct qla_hw_data *ha = vha->hw;
int res = QLA_SUCCESS, rval;
int greater_wwpn = 0;
int logged_in = 0;
if (ha->current_topology != ISP_CFG_N)
return res;
if (wwn_to_u64(vha->port_name) >
wwn_to_u64(vha->n2n_port_name)) {
ql_dbg(ql_dbg_disc, vha, 0x2002,
"HBA WWPN is greater %llx > target %llx\n",
wwn_to_u64(vha->port_name),
wwn_to_u64(vha->n2n_port_name));
greater_wwpn = 1;
fcport->d_id.b24 = vha->n2n_id;
}
fcport->loop_id = vha->loop_id;
fcport->fc4f_nvme = 0;
fcport->query = 1;
ql_dbg(ql_dbg_disc, vha, 0x4001,
"Initiate N2N login handler: HBA port_id=%06x loopid=%d\n",
fcport->d_id.b24, vha->loop_id);
/* Fill in member data. */
if (!greater_wwpn) {
rval = qla2x00_get_port_database(vha, fcport, 0);
ql_dbg(ql_dbg_disc, vha, 0x1051,
"Remote login-state (%x/%x) port_id=%06x loop_id=%x, rval=%d\n",
fcport->current_login_state, fcport->last_login_state,
fcport->d_id.b24, fcport->loop_id, rval);
if (((fcport->current_login_state & 0xf) == 0x4) ||
((fcport->current_login_state & 0xf) == 0x6))
logged_in = 1;
}
if (logged_in || greater_wwpn) {
if (!vha->nvme_local_port && vha->flags.nvme_enabled)
qla_nvme_register_hba(vha);
/* Set connected N_Port d_id */
if (vha->flags.nvme_enabled)
fcport->fc4f_nvme = 1;
fcport->scan_state = QLA_FCPORT_FOUND;
fcport->fw_login_state = DSC_LS_PORT_UNAVAIL;
fcport->disc_state = DSC_GNL;
fcport->n2n_flag = 1;
fcport->flags = 3;
vha->hw->flags.gpsc_supported = 0;
if (greater_wwpn) {
ql_dbg(ql_dbg_disc, vha, 0x20e5,
"%s %d PLOGI ELS %8phC\n",
__func__, __LINE__, fcport->port_name);
res = qla24xx_els_dcmd2_iocb(vha, ELS_DCMD_PLOGI,
fcport, fcport->d_id);
}
if (res != QLA_SUCCESS) {
ql_log(ql_log_info, vha, 0xd04d,
"PLOGI Failed: portid=%06x - retrying\n",
fcport->d_id.b24);
res = QLA_SUCCESS;
} else {
/* State 0x6 means FCP PRLI complete */
if ((fcport->current_login_state & 0xf) == 0x6) {
ql_dbg(ql_dbg_disc, vha, 0x2118,
"%s %d %8phC post GPDB work\n",
__func__, __LINE__, fcport->port_name);
fcport->chip_reset =
vha->hw->base_qpair->chip_reset;
qla24xx_post_gpdb_work(vha, fcport, 0);
} else {
ql_dbg(ql_dbg_disc, vha, 0x2118,
"%s %d %8phC post NVMe PRLI\n",
__func__, __LINE__, fcport->port_name);
qla24xx_post_prli_work(vha, fcport);
}
}
} else {
/* Wait for next database change */
set_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags);
}
return res;
}
/* /*
* qla2x00_configure_local_loop * qla2x00_configure_local_loop
...@@ -4437,6 +4547,14 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha) ...@@ -4437,6 +4547,14 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
} }
} }
/* Inititae N2N login. */
if (test_and_clear_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags)) {
rval = qla24xx_n2n_handle_login(vha, new_fcport);
if (rval != QLA_SUCCESS)
goto cleanup_allocation;
return QLA_SUCCESS;
}
/* Add devices to port list. */ /* Add devices to port list. */
id_iter = (char *)ha->gid_list; id_iter = (char *)ha->gid_list;
for (index = 0; index < entries; index++) { for (index = 0; index < entries; index++) {
...@@ -4478,10 +4596,13 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha) ...@@ -4478,10 +4596,13 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
"Failed to retrieve fcport information " "Failed to retrieve fcport information "
"-- get_port_database=%x, loop_id=0x%04x.\n", "-- get_port_database=%x, loop_id=0x%04x.\n",
rval2, new_fcport->loop_id); rval2, new_fcport->loop_id);
ql_dbg(ql_dbg_disc, vha, 0x2105, /* Skip retry if N2N */
"Scheduling resync.\n"); if (ha->current_topology != ISP_CFG_N) {
set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); ql_dbg(ql_dbg_disc, vha, 0x2105,
continue; "Scheduling resync.\n");
set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
continue;
}
} }
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
...@@ -7554,6 +7675,12 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) ...@@ -7554,6 +7675,12 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
if (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha)) if (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha))
icb->firmware_options_3 |= BIT_0; icb->firmware_options_3 |= BIT_0;
if (IS_QLA27XX(ha)) {
icb->firmware_options_3 |= BIT_8;
ql_dbg(ql_log_info, vha, 0x0075,
"Enabling direct connection.\n");
}
if (rval) { if (rval) {
ql_log(ql_log_warn, vha, 0x0076, ql_log(ql_log_warn, vha, 0x0076,
"NVRAM configuration failed.\n"); "NVRAM configuration failed.\n");
......
...@@ -2518,6 +2518,7 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) ...@@ -2518,6 +2518,7 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
{ {
scsi_qla_host_t *vha = sp->vha; scsi_qla_host_t *vha = sp->vha;
struct srb_iocb *elsio = &sp->u.iocb_cmd; struct srb_iocb *elsio = &sp->u.iocb_cmd;
uint32_t dsd_len = 24;
els_iocb->entry_type = ELS_IOCB_TYPE; els_iocb->entry_type = ELS_IOCB_TYPE;
els_iocb->entry_count = 1; els_iocb->entry_count = 1;
...@@ -2534,23 +2535,197 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) ...@@ -2534,23 +2535,197 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
els_iocb->port_id[0] = sp->fcport->d_id.b.al_pa; els_iocb->port_id[0] = sp->fcport->d_id.b.al_pa;
els_iocb->port_id[1] = sp->fcport->d_id.b.area; els_iocb->port_id[1] = sp->fcport->d_id.b.area;
els_iocb->port_id[2] = sp->fcport->d_id.b.domain; els_iocb->port_id[2] = sp->fcport->d_id.b.domain;
els_iocb->s_id[0] = vha->d_id.b.al_pa;
els_iocb->s_id[1] = vha->d_id.b.area;
els_iocb->s_id[2] = vha->d_id.b.domain;
els_iocb->control_flags = 0; els_iocb->control_flags = 0;
els_iocb->tx_byte_count = sizeof(struct els_logo_payload); if (elsio->u.els_logo.els_cmd == ELS_DCMD_PLOGI) {
els_iocb->tx_address[0] = els_iocb->tx_byte_count = sizeof(struct els_plogi_payload);
cpu_to_le32(LSD(elsio->u.els_logo.els_logo_pyld_dma)); els_iocb->tx_address[0] =
els_iocb->tx_address[1] = cpu_to_le32(LSD(elsio->u.els_plogi.els_plogi_pyld_dma));
cpu_to_le32(MSD(elsio->u.els_logo.els_logo_pyld_dma)); els_iocb->tx_address[1] =
els_iocb->tx_len = cpu_to_le32(sizeof(struct els_logo_payload)); cpu_to_le32(MSD(elsio->u.els_plogi.els_plogi_pyld_dma));
els_iocb->tx_len = dsd_len;
els_iocb->rx_dsd_count = 1;
els_iocb->rx_byte_count = sizeof(struct els_plogi_payload);
els_iocb->rx_address[0] =
cpu_to_le32(LSD(elsio->u.els_plogi.els_resp_pyld_dma));
els_iocb->rx_address[1] =
cpu_to_le32(MSD(elsio->u.els_plogi.els_resp_pyld_dma));
els_iocb->rx_len = dsd_len;
ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x3073,
"PLOGI ELS IOCB:\n");
ql_dump_buffer(ql_log_info, vha, 0x0109,
(uint8_t *)els_iocb, 0x70);
} else {
els_iocb->tx_byte_count = sizeof(struct els_logo_payload);
els_iocb->tx_address[0] =
cpu_to_le32(LSD(elsio->u.els_logo.els_logo_pyld_dma));
els_iocb->tx_address[1] =
cpu_to_le32(MSD(elsio->u.els_logo.els_logo_pyld_dma));
els_iocb->tx_len = cpu_to_le32(sizeof(struct els_logo_payload));
els_iocb->rx_byte_count = 0; els_iocb->rx_byte_count = 0;
els_iocb->rx_address[0] = 0; els_iocb->rx_address[0] = 0;
els_iocb->rx_address[1] = 0; els_iocb->rx_address[1] = 0;
els_iocb->rx_len = 0; els_iocb->rx_len = 0;
}
sp->vha->qla_stats.control_requests++; sp->vha->qla_stats.control_requests++;
} }
static void
qla2x00_els_dcmd2_sp_free(void *data)
{
srb_t *sp = data;
struct srb_iocb *elsio = &sp->u.iocb_cmd;
if (elsio->u.els_plogi.els_plogi_pyld)
dma_free_coherent(&sp->vha->hw->pdev->dev, DMA_POOL_SIZE,
elsio->u.els_plogi.els_plogi_pyld,
elsio->u.els_plogi.els_plogi_pyld_dma);
if (elsio->u.els_plogi.els_resp_pyld)
dma_free_coherent(&sp->vha->hw->pdev->dev, DMA_POOL_SIZE,
elsio->u.els_plogi.els_resp_pyld,
elsio->u.els_plogi.els_resp_pyld_dma);
del_timer(&elsio->timer);
qla2x00_rel_sp(sp);
}
static void
qla2x00_els_dcmd2_iocb_timeout(void *data)
{
srb_t *sp = data;
fc_port_t *fcport = sp->fcport;
struct scsi_qla_host *vha = sp->vha;
struct qla_hw_data *ha = vha->hw;
struct srb_iocb *lio = &sp->u.iocb_cmd;
unsigned long flags = 0;
int res;
ql_dbg(ql_dbg_io + ql_dbg_disc, vha, 0x3069,
"%s hdl=%x ELS Timeout, %8phC portid=%06x\n",
sp->name, sp->handle, fcport->port_name, fcport->d_id.b24);
/* Abort the exchange */
spin_lock_irqsave(&ha->hardware_lock, flags);
res = ha->isp_ops->abort_command(sp);
ql_dbg(ql_dbg_io, vha, 0x3070,
"mbx abort_command %s\n",
(res == QLA_SUCCESS) ? "successful" : "failed");
spin_unlock_irqrestore(&ha->hardware_lock, flags);
complete(&lio->u.els_plogi.comp);
}
static void
qla2x00_els_dcmd2_sp_done(void *ptr, int res)
{
srb_t *sp = ptr;
fc_port_t *fcport = sp->fcport;
struct srb_iocb *lio = &sp->u.iocb_cmd;
struct scsi_qla_host *vha = sp->vha;
ql_dbg(ql_dbg_io + ql_dbg_disc, vha, 0x3072,
"%s ELS hdl=%x, portid=%06x done %8pC\n",
sp->name, sp->handle, fcport->d_id.b24, fcport->port_name);
complete(&lio->u.els_plogi.comp);
}
int
qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
fc_port_t *fcport, port_id_t remote_did)
{
srb_t *sp;
struct srb_iocb *elsio = NULL;
struct qla_hw_data *ha = vha->hw;
int rval = QLA_SUCCESS;
void *ptr, *resp_ptr;
dma_addr_t ptr_dma;
/* Alloc SRB structure */
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
if (!sp) {
ql_log(ql_log_info, vha, 0x70e6,
"SRB allocation failed\n");
return -ENOMEM;
}
elsio = &sp->u.iocb_cmd;
fcport->d_id.b.domain = remote_did.b.domain;
fcport->d_id.b.area = remote_did.b.area;
fcport->d_id.b.al_pa = remote_did.b.al_pa;
ql_dbg(ql_dbg_io, vha, 0x3073,
"Enter: PLOGI portid=%06x\n", fcport->d_id.b24);
sp->type = SRB_ELS_DCMD;
sp->name = "ELS_DCMD";
sp->fcport = fcport;
qla2x00_init_timer(sp, ELS_DCMD_TIMEOUT);
elsio->timeout = qla2x00_els_dcmd2_iocb_timeout;
sp->done = qla2x00_els_dcmd2_sp_done;
sp->free = qla2x00_els_dcmd2_sp_free;
ptr = elsio->u.els_plogi.els_plogi_pyld =
dma_alloc_coherent(&ha->pdev->dev, DMA_POOL_SIZE,
&elsio->u.els_plogi.els_plogi_pyld_dma, GFP_KERNEL);
ptr_dma = elsio->u.els_plogi.els_plogi_pyld_dma;
if (!elsio->u.els_plogi.els_plogi_pyld) {
rval = QLA_FUNCTION_FAILED;
goto out;
}
resp_ptr = elsio->u.els_plogi.els_resp_pyld =
dma_alloc_coherent(&ha->pdev->dev, DMA_POOL_SIZE,
&elsio->u.els_plogi.els_resp_pyld_dma, GFP_KERNEL);
if (!elsio->u.els_plogi.els_resp_pyld) {
rval = QLA_FUNCTION_FAILED;
goto out;
}
ql_dbg(ql_dbg_io, vha, 0x3073, "PLOGI %p %p\n", ptr, resp_ptr);
memset(ptr, 0, sizeof(struct els_plogi_payload));
memset(resp_ptr, 0, sizeof(struct els_plogi_payload));
elsio->u.els_plogi.els_cmd = els_opcode;
elsio->u.els_plogi.els_plogi_pyld->opcode = els_opcode;
qla24xx_get_port_login_templ(vha, ptr_dma + 4,
&elsio->u.els_plogi.els_plogi_pyld->data[0],
sizeof(struct els_plogi_payload));
ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x3073, "PLOGI buffer:\n");
ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x0109,
(uint8_t *)elsio->u.els_plogi.els_plogi_pyld, 0x70);
init_completion(&elsio->u.els_plogi.comp);
rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS) {
rval = QLA_FUNCTION_FAILED;
goto out;
}
ql_dbg(ql_dbg_io, vha, 0x3074,
"%s PLOGI sent, hdl=%x, loopid=%x, portid=%06x\n",
sp->name, sp->handle, fcport->loop_id, fcport->d_id.b24);
wait_for_completion(&elsio->u.els_plogi.comp);
if (elsio->u.els_plogi.comp_status != CS_COMPLETE)
rval = QLA_FUNCTION_FAILED;
out:
sp->free(sp);
return rval;
}
static void static void
qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
{ {
......
...@@ -1041,6 +1041,7 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb) ...@@ -1041,6 +1041,7 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
*/ */
atomic_set(&vha->loop_down_timer, 0); atomic_set(&vha->loop_down_timer, 0);
if (atomic_read(&vha->loop_state) != LOOP_DOWN && if (atomic_read(&vha->loop_state) != LOOP_DOWN &&
!ha->flags.n2n_ae &&
atomic_read(&vha->loop_state) != LOOP_DEAD) { atomic_read(&vha->loop_state) != LOOP_DEAD) {
ql_dbg(ql_dbg_async, vha, 0x5011, ql_dbg(ql_dbg_async, vha, 0x5011,
"Asynchronous PORT UPDATE ignored %04x/%04x/%04x.\n", "Asynchronous PORT UPDATE ignored %04x/%04x/%04x.\n",
...@@ -1545,6 +1546,7 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, ...@@ -1545,6 +1546,7 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
uint32_t fw_status[3]; uint32_t fw_status[3];
uint8_t* fw_sts_ptr; uint8_t* fw_sts_ptr;
int res; int res;
struct srb_iocb *els;
sp = qla2x00_get_sp_from_handle(vha, func, req, pkt); sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
if (!sp) if (!sp)
...@@ -1561,10 +1563,14 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, ...@@ -1561,10 +1563,14 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
break; break;
case SRB_ELS_DCMD: case SRB_ELS_DCMD:
type = "Driver ELS logo"; type = "Driver ELS logo";
ql_dbg(ql_dbg_user, vha, 0x5047, if (iocb_type != ELS_IOCB_TYPE) {
"Completing %s: (%p) type=%d.\n", type, sp, sp->type); ql_dbg(ql_dbg_user, vha, 0x5047,
sp->done(sp, 0); "Completing %s: (%p) type=%d.\n",
return; type, sp, sp->type);
sp->done(sp, 0);
return;
}
break;
case SRB_CT_PTHRU_CMD: case SRB_CT_PTHRU_CMD:
/* borrowing sts_entry_24xx.comp_status. /* borrowing sts_entry_24xx.comp_status.
same location as ct_entry_24xx.comp_status same location as ct_entry_24xx.comp_status
...@@ -1584,6 +1590,33 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, ...@@ -1584,6 +1590,33 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
fw_status[1] = le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_1); fw_status[1] = le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_1);
fw_status[2] = le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_2); fw_status[2] = le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_2);
if (iocb_type == ELS_IOCB_TYPE) {
els = &sp->u.iocb_cmd;
els->u.els_plogi.fw_status[0] = fw_status[0];
els->u.els_plogi.fw_status[1] = fw_status[1];
els->u.els_plogi.fw_status[2] = fw_status[2];
els->u.els_plogi.comp_status = fw_status[0];
if (comp_status == CS_COMPLETE) {
res = DID_OK << 16;
} else {
if (comp_status == CS_DATA_UNDERRUN) {
res = DID_OK << 16;
els->u.els_plogi.len =
le16_to_cpu(((struct els_sts_entry_24xx *)
pkt)->total_byte_count);
} else {
els->u.els_plogi.len = 0;
res = DID_ERROR << 16;
}
}
ql_log(ql_log_info, vha, 0x503f,
"ELS IOCB Done -%s error hdl=%x comp_status=0x%x error subcode 1=0x%x error subcode 2=0x%x total_byte=0x%x\n",
type, sp->handle, comp_status, fw_status[1], fw_status[2],
le16_to_cpu(((struct els_sts_entry_24xx *)
pkt)->total_byte_count));
goto els_ct_done;
}
/* return FC_CTELS_STATUS_OK and leave the decoding of the ELS/CT /* return FC_CTELS_STATUS_OK and leave the decoding of the ELS/CT
* fc payload to the caller * fc payload to the caller
*/ */
...@@ -1631,6 +1664,7 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, ...@@ -1631,6 +1664,7 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
bsg_reply->reply_payload_rcv_len = bsg_job->reply_payload.payload_len; bsg_reply->reply_payload_rcv_len = bsg_job->reply_payload.payload_len;
bsg_job->reply_len = 0; bsg_job->reply_len = 0;
} }
els_ct_done:
sp->done(sp, res); sp->done(sp, res);
} }
......
...@@ -1786,6 +1786,7 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt) ...@@ -1786,6 +1786,7 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt)
if (pd == NULL) { if (pd == NULL) {
ql_log(ql_log_warn, vha, 0x1050, ql_log(ql_log_warn, vha, 0x1050,
"Failed to allocate port database structure.\n"); "Failed to allocate port database structure.\n");
fcport->query = 0;
return QLA_MEMORY_ALLOC_FAILED; return QLA_MEMORY_ALLOC_FAILED;
} }
...@@ -1926,6 +1927,7 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt) ...@@ -1926,6 +1927,7 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt)
gpd_error_out: gpd_error_out:
dma_pool_free(ha->s_dma_pool, pd, pd_dma); dma_pool_free(ha->s_dma_pool, pd, pd_dma);
fcport->query = 0;
if (rval != QLA_SUCCESS) { if (rval != QLA_SUCCESS) {
ql_dbg(ql_dbg_mbx, vha, 0x1052, ql_dbg(ql_dbg_mbx, vha, 0x1052,
...@@ -3762,6 +3764,38 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, ...@@ -3762,6 +3764,38 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
rptid_entry->vp_status, rptid_entry->vp_status,
rptid_entry->port_id[2], rptid_entry->port_id[1], rptid_entry->port_id[2], rptid_entry->port_id[1],
rptid_entry->port_id[0]); rptid_entry->port_id[0]);
ql_dbg(ql_dbg_async, vha, 0x5075,
"Format 1: Remote WWPN %8phC.\n",
rptid_entry->u.f1.port_name);
ql_dbg(ql_dbg_async, vha, 0x5075,
"Format 1: WWPN %8phC.\n",
vha->port_name);
/* N2N. direct connect */
if (IS_QLA27XX(ha) &&
((rptid_entry->u.f1.flags>>1) & 0x7) == 2) {
/* if our portname is higher then initiate N2N login */
if (wwn_to_u64(vha->port_name) >
wwn_to_u64(rptid_entry->u.f1.port_name)) {
// ??? qlt_update_host_map(vha, id);
vha->n2n_id = 0x1;
ql_dbg(ql_dbg_async, vha, 0x5075,
"Format 1: Setting n2n_update_needed for id %d\n",
vha->n2n_id);
} else {
ql_dbg(ql_dbg_async, vha, 0x5075,
"Format 1: Remote login - Waiting for WWPN %8phC.\n",
rptid_entry->u.f1.port_name);
}
memcpy(vha->n2n_port_name, rptid_entry->u.f1.port_name,
WWN_SIZE);
set_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags);
set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags);
set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags);
return;
}
/* buffer to buffer credit flag */ /* buffer to buffer credit flag */
vha->flags.bbcr_enable = (rptid_entry->u.f1.bbcr & 0xf) != 0; vha->flags.bbcr_enable = (rptid_entry->u.f1.bbcr & 0xf) != 0;
...@@ -4599,6 +4633,48 @@ qla25xx_set_driver_version(scsi_qla_host_t *vha, char *version) ...@@ -4599,6 +4633,48 @@ qla25xx_set_driver_version(scsi_qla_host_t *vha, char *version)
return rval; return rval;
} }
int
qla24xx_get_port_login_templ(scsi_qla_host_t *vha, dma_addr_t buf_dma,
void *buf, uint16_t bufsiz)
{
int rval, i;
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
uint32_t *bp;
if (!IS_FWI2_CAPABLE(vha->hw))
return QLA_FUNCTION_FAILED;
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1159,
"Entered %s.\n", __func__);
mcp->mb[0] = MBC_GET_RNID_PARAMS;
mcp->mb[1] = RNID_TYPE_PORT_LOGIN << 8;
mcp->mb[2] = MSW(buf_dma);
mcp->mb[3] = LSW(buf_dma);
mcp->mb[6] = MSW(MSD(buf_dma));
mcp->mb[7] = LSW(MSD(buf_dma));
mcp->mb[8] = bufsiz/4;
mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
mcp->in_mb = MBX_1|MBX_0;
mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
ql_dbg(ql_dbg_mbx, vha, 0x115a,
"Failed=%x mb[0]=%x,%x.\n", rval, mcp->mb[0], mcp->mb[1]);
} else {
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x115b,
"Done %s.\n", __func__);
bp = (uint32_t *) buf;
for (i = 0; i < (bufsiz-4)/4; i++, bp++)
*bp = cpu_to_be32(*bp);
}
return rval;
}
static int static int
qla2x00_read_asic_temperature(scsi_qla_host_t *vha, uint16_t *temp) qla2x00_read_asic_temperature(scsi_qla_host_t *vha, uint16_t *temp)
{ {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册