Commit edd05de1 authored by Duane Grigsby's avatar Duane Grigsby Committed by 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: default avatarDuane Grigsby <duane.grigsby@cavium.com>
Signed-off-by: default avatarMichael Hernandez <michael.hernandez@cavium.com>
Signed-off-by: default avatarHimanshu Madhani <himanshu.madhani@cavium.com>
Reviewed-by: default avatarJohannes Thumshirn <jthumshirn@suse.de>
Tested-by: default avatarEwan D. Milne <emilne@redhat.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent c0c462c8
...@@ -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%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment