On Fri, 2017-10-13 at 09:34 -0700, Madhani, Madhani wrote: > From: Duane Grigsby <duane.grigsby@xxxxxxxxxx> > > 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. > > Signed-off-by: Duane Grigsby <duane.grigsby@xxxxxxxxxx> > Signed-off-by: Michael Hernandez <michael.hernandez@xxxxxxxxxx> > Signed-off-by: Himanshu Madhani <himanshu.madhani@xxxxxxxxxx> > --- > drivers/scsi/qla2xxx/qla_def.h | 24 +++++ > drivers/scsi/qla2xxx/qla_fw.h | 4 +- > drivers/scsi/qla2xxx/qla_gbl.h | 4 + > drivers/scsi/qla2xxx/qla_init.c | 135 +++++++++++++++++++++++++++- > drivers/scsi/qla2xxx/qla_iocb.c | 195 +++++++++++++++++++++++++++++++++++++--- > drivers/scsi/qla2xxx/qla_isr.c | 42 ++++++++- > drivers/scsi/qla2xxx/qla_mbx.c | 76 ++++++++++++++++ > 7 files changed, 459 insertions(+), 21 deletions(-) > > diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h > index f712c0cd46d6..01a9b8971e88 100644 > --- a/drivers/scsi/qla2xxx/qla_def.h > +++ b/drivers/scsi/qla2xxx/qla_def.h > @@ -323,6 +323,12 @@ struct els_logo_payload { > uint8_t wwpn[WWN_SIZE]; > }; > > +struct els_plogi_payload { > + uint8_t opcode; > + uint8_t rsvd[3]; > + uint8_t data[112]; > +}; > + > struct ct_arg { > void *iocb; > u16 nport_handle; > @@ -358,6 +364,19 @@ struct srb_iocb { > dma_addr_t els_logo_pyld_dma; > } els_logo; > 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 > * defined in tsk_mgmt_entry struct > @@ -2349,6 +2368,7 @@ typedef struct fc_port { > uint8_t fc4_type; > uint8_t fc4f_nvme; > uint8_t scan_state; > + uint8_t n2n_flag; > > unsigned long last_queue_full; > unsigned long last_ramp_up; > @@ -2372,6 +2392,7 @@ typedef struct fc_port { > u8 iocb[IOCB_SIZE]; > u8 current_login_state; > u8 last_login_state; > + struct completion n2n_done; > } fc_port_t; > > #define QLA_FCPORT_SCAN 1 > @@ -4228,6 +4249,9 @@ typedef struct scsi_qla_host { > wait_queue_head_t fcport_waitQ; > wait_queue_head_t vref_waitq; > 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; > > struct qla27xx_image_status { > diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h > index bec641aae7b3..d5cef0727e72 100644 > --- a/drivers/scsi/qla2xxx/qla_fw.h > +++ b/drivers/scsi/qla2xxx/qla_fw.h > @@ -753,9 +753,7 @@ struct els_entry_24xx { > uint8_t reserved_2; > > uint8_t port_id[3]; > - uint8_t reserved_3; > - > - uint16_t reserved_4; > + uint8_t s_id[3]; > > uint16_t control_flags; /* Control flags. */ > #define ECF_PAYLOAD_DESCR_MASK (BIT_15|BIT_14|BIT_13) > diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h > index 46c7822c20fc..1e35e961683f 100644 > --- a/drivers/scsi/qla2xxx/qla_gbl.h > +++ b/drivers/scsi/qla2xxx/qla_gbl.h > @@ -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 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 *); > > @@ -487,6 +489,8 @@ int qla24xx_gidlist_wait(struct scsi_qla_host *, void *, dma_addr_t, > uint16_t *); > int __qla24xx_parse_gpdb(struct scsi_qla_host *, fc_port_t *, > 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_set_zio_threshold(scsi_qla_host_t *, uint16_t); > diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c > index 4c53199db371..b2a391f93775 100644 > --- a/drivers/scsi/qla2xxx/qla_init.c > +++ b/drivers/scsi/qla2xxx/qla_init.c > @@ -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); > break; > 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, > "%s %d %8phC unhandle event of %x\n", > __func__, __LINE__, ea->fcport->port_name, ea->data[0]); > @@ -4366,7 +4374,109 @@ qla2x00_configure_loop(scsi_qla_host_t *vha) > 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 > @@ -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. */ > id_iter = (char *)ha->gid_list; > for (index = 0; index < entries; index++) { > @@ -4478,10 +4596,13 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha) > "Failed to retrieve fcport information " > "-- get_port_database=%x, loop_id=0x%04x.\n", > rval2, new_fcport->loop_id); > - ql_dbg(ql_dbg_disc, vha, 0x2105, > - "Scheduling resync.\n"); > - set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); > - continue; > + /* Skip retry if N2N */ > + if (ha->current_topology != ISP_CFG_N) { > + ql_dbg(ql_dbg_disc, vha, 0x2105, > + "Scheduling resync.\n"); > + set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); > + continue; > + } > } > > spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); > @@ -7554,6 +7675,12 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) > if (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha)) > 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) { > ql_log(ql_log_warn, vha, 0x0076, > "NVRAM configuration failed.\n"); > diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c > index 2f94159186d7..0502ed7ee14e 100644 > --- a/drivers/scsi/qla2xxx/qla_iocb.c > +++ b/drivers/scsi/qla2xxx/qla_iocb.c > @@ -2518,6 +2518,7 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) > { > scsi_qla_host_t *vha = sp->vha; > struct srb_iocb *elsio = &sp->u.iocb_cmd; > + uint32_t dsd_len = 24; > > els_iocb->entry_type = ELS_IOCB_TYPE; > els_iocb->entry_count = 1; > @@ -2534,24 +2535,198 @@ 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[1] = sp->fcport->d_id.b.area; > 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->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)); > + if (elsio->u.els_logo.els_cmd == ELS_DCMD_PLOGI) { > + els_iocb->tx_byte_count = sizeof(struct els_plogi_payload); > + els_iocb->tx_address[0] = > + cpu_to_le32(LSD(elsio->u.els_plogi.els_plogi_pyld_dma)); > + els_iocb->tx_address[1] = > + 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_address[0] = 0; > - els_iocb->rx_address[1] = 0; > - els_iocb->rx_len = 0; > + els_iocb->rx_byte_count = 0; > + els_iocb->rx_address[0] = 0; > + els_iocb->rx_address[1] = 0; > + els_iocb->rx_len = 0; > + } > > 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 > qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) > { > struct bsg_job *bsg_job = sp->u.bsg_job; > diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c > index ab97fb06c239..d06a1a809188 100644 > --- a/drivers/scsi/qla2xxx/qla_isr.c > +++ b/drivers/scsi/qla2xxx/qla_isr.c > @@ -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); > if (atomic_read(&vha->loop_state) != LOOP_DOWN && > + !ha->flags.n2n_ae && > atomic_read(&vha->loop_state) != LOOP_DEAD) { > ql_dbg(ql_dbg_async, vha, 0x5011, > "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, > uint32_t fw_status[3]; > uint8_t* fw_sts_ptr; > int res; > + struct srb_iocb *els; > > sp = qla2x00_get_sp_from_handle(vha, func, req, pkt); > if (!sp) > @@ -1561,10 +1563,14 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, > break; > case SRB_ELS_DCMD: > type = "Driver ELS logo"; > - ql_dbg(ql_dbg_user, vha, 0x5047, > - "Completing %s: (%p) type=%d.\n", type, sp, sp->type); > - sp->done(sp, 0); > - return; > + if (iocb_type != ELS_IOCB_TYPE) { > + ql_dbg(ql_dbg_user, vha, 0x5047, > + "Completing %s: (%p) type=%d.\n", > + type, sp, sp->type); > + sp->done(sp, 0); > + return; > + } > + break; > case SRB_CT_PTHRU_CMD: > /* borrowing sts_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, > 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); > > + 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 > * fc payload to the caller > */ > @@ -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_job->reply_len = 0; > } > +els_ct_done: > > sp->done(sp, res); > } > diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c > index 71e56877e1eb..d44f65fe9434 100644 > --- a/drivers/scsi/qla2xxx/qla_mbx.c > +++ b/drivers/scsi/qla2xxx/qla_mbx.c > @@ -1786,6 +1786,7 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt) > if (pd == NULL) { > ql_log(ql_log_warn, vha, 0x1050, > "Failed to allocate port database structure.\n"); > + fcport->query = 0; > 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) > > gpd_error_out: > dma_pool_free(ha->s_dma_pool, pd, pd_dma); > + fcport->query = 0; > > if (rval != QLA_SUCCESS) { > ql_dbg(ql_dbg_mbx, vha, 0x1052, > @@ -3762,6 +3764,38 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, > rptid_entry->vp_status, > rptid_entry->port_id[2], rptid_entry->port_id[1], > 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 */ > 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) > 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 > qla2x00_read_asic_temperature(scsi_qla_host_t *vha, uint16_t *temp) > { Thanks. Tested-by: Ewan D. Milne <emilne@xxxxxxxxxx>