Skip to content

Commit

Permalink
scsi: qla2xxx: Fix buffer-buffer credit extraction error
Browse files Browse the repository at this point in the history
Current code uses wrong mailbox option to extract bbc from firmware. This
field is nested inside of PLOGI payload.  Extract bbc from PLOGI template
payload.

Link: https://lore.kernel.org/r/20200929102152.32278-3-njavali@marvell.com
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
Signed-off-by: Quinn Tran <qutran@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
  • Loading branch information
Quinn Tran authored and Martin K. Petersen committed Sep 30, 2020
1 parent 7dc0f67 commit 44f5a37
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 81 deletions.
4 changes: 3 additions & 1 deletion drivers/scsi/qla2xxx/qla_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -3915,6 +3915,7 @@ struct qla_hw_data {
/* Enabled in Driver */
uint32_t scm_enabled:1;
uint32_t max_req_queue_warned:1;
uint32_t plogi_template_valid:1;
} flags;

uint16_t max_exchg;
Expand Down Expand Up @@ -4263,7 +4264,8 @@ struct qla_hw_data {
int exchoffld_count;

/* n2n */
struct els_plogi_payload plogi_els_payld;
struct fc_els_flogi plogi_els_payld;
#define LOGIN_TEMPLATE_SIZE (sizeof(struct fc_els_flogi) - 4)

void *swl;

Expand Down
50 changes: 26 additions & 24 deletions drivers/scsi/qla2xxx/qla_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -4991,6 +4991,29 @@ qla2x00_free_fcport(fc_port_t *fcport)
kfree(fcport);
}

static void qla_get_login_template(scsi_qla_host_t *vha)
{
struct qla_hw_data *ha = vha->hw;
int rval;
u32 *bp, sz;
__be32 *q;

memset(ha->init_cb, 0, ha->init_cb_size);
sz = min_t(int, sizeof(struct fc_els_flogi), ha->init_cb_size);
rval = qla24xx_get_port_login_templ(vha, ha->init_cb_dma,
ha->init_cb, sz);
if (rval != QLA_SUCCESS) {
ql_dbg(ql_dbg_init, vha, 0x00d1,
"PLOGI ELS param read fail.\n");
return;
}
q = (__be32 *)&ha->plogi_els_payld.fl_csp;

bp = (uint32_t *)ha->init_cb;
cpu_to_be32_array(q, bp, sz / 4);
ha->flags.plogi_template_valid = 1;
}

/*
* qla2x00_configure_loop
* Updates Fibre Channel Device Database with what is actually on loop.
Expand Down Expand Up @@ -5034,6 +5057,7 @@ qla2x00_configure_loop(scsi_qla_host_t *vha)
clear_bit(RSCN_UPDATE, &vha->dpc_flags);

qla2x00_get_data_rate(vha);
qla_get_login_template(vha);

/* Determine what we need to do */
if ((ha->current_topology == ISP_CFG_FL ||
Expand Down Expand Up @@ -5118,32 +5142,11 @@ qla2x00_configure_loop(scsi_qla_host_t *vha)

static int qla2x00_configure_n2n_loop(scsi_qla_host_t *vha)
{
struct qla_hw_data *ha = vha->hw;
unsigned long flags;
fc_port_t *fcport;
int rval;

if (test_and_clear_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags)) {
/* borrowing */
u32 *bp, sz;

memset(ha->init_cb, 0, ha->init_cb_size);
sz = min_t(int, sizeof(struct els_plogi_payload),
ha->init_cb_size);
rval = qla24xx_get_port_login_templ(vha, ha->init_cb_dma,
ha->init_cb, sz);
if (rval == QLA_SUCCESS) {
__be32 *q = &ha->plogi_els_payld.data[0];

bp = (uint32_t *)ha->init_cb;
cpu_to_be32_array(q, bp, sz / 4);
memcpy(bp, q, sizeof(ha->plogi_els_payld.data));
} else {
ql_dbg(ql_dbg_init, vha, 0x00d1,
"PLOGI ELS param read fail.\n");
goto skip_login;
}
}
if (test_and_clear_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags))
set_bit(RELOGIN_NEEDED, &vha->dpc_flags);

list_for_each_entry(fcport, &vha->vp_fcports, list) {
if (fcport->n2n_flag) {
Expand All @@ -5152,7 +5155,6 @@ static int qla2x00_configure_n2n_loop(scsi_qla_host_t *vha)
}
}

skip_login:
spin_lock_irqsave(&vha->work_lock, flags);
vha->scan.scan_retry++;
spin_unlock_irqrestore(&vha->work_lock, flags);
Expand Down
3 changes: 1 addition & 2 deletions drivers/scsi/qla2xxx/qla_iocb.c
Original file line number Diff line number Diff line change
Expand Up @@ -3013,8 +3013,7 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
memset(ptr, 0, sizeof(struct els_plogi_payload));
memset(resp_ptr, 0, sizeof(struct els_plogi_payload));
memcpy(elsio->u.els_plogi.els_plogi_pyld->data,
&ha->plogi_els_payld.data,
sizeof(elsio->u.els_plogi.els_plogi_pyld->data));
&ha->plogi_els_payld.fl_csp, LOGIN_TEMPLATE_SIZE);

elsio->u.els_plogi.els_cmd = els_opcode;
elsio->u.els_plogi.els_plogi_pyld->opcode = els_opcode;
Expand Down
39 changes: 0 additions & 39 deletions drivers/scsi/qla2xxx/qla_mbx.c
Original file line number Diff line number Diff line change
Expand Up @@ -4977,45 +4977,6 @@ qla25xx_set_els_cmds_supported(scsi_qla_host_t *vha)
return rval;
}

int
qla24xx_get_buffer_credits(scsi_qla_host_t *vha, struct buffer_credit_24xx *bbc,
dma_addr_t bbc_dma)
{
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
int rval;

if (!IS_FWI2_CAPABLE(vha->hw))
return QLA_FUNCTION_FAILED;

ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x118e,
"Entered %s.\n", __func__);

mcp->mb[0] = MBC_GET_RNID_PARAMS;
mcp->mb[1] = RNID_BUFFER_CREDITS << 8;
mcp->mb[2] = MSW(LSD(bbc_dma));
mcp->mb[3] = LSW(LSD(bbc_dma));
mcp->mb[6] = MSW(MSD(bbc_dma));
mcp->mb[7] = LSW(MSD(bbc_dma));
mcp->mb[8] = sizeof(*bbc) / sizeof(*bbc->parameter);
mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
mcp->in_mb = MBX_1|MBX_0;
mcp->buf_size = sizeof(*bbc);
mcp->flags = MBX_DMA_IN;
mcp->tov = MBX_TOV_SECONDS;
rval = qla2x00_mailbox_command(vha, mcp);

if (rval != QLA_SUCCESS) {
ql_dbg(ql_dbg_mbx, vha, 0x118f,
"Failed=%x mb[0]=%x,%x.\n", rval, mcp->mb[0], mcp->mb[1]);
} else {
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1190,
"Done %s.\n", __func__);
}

return rval;
}

static int
qla2x00_read_asic_temperature(scsi_qla_host_t *vha, uint16_t *temp)
{
Expand Down
19 changes: 4 additions & 15 deletions drivers/scsi/qla2xxx/qla_os.c
Original file line number Diff line number Diff line change
Expand Up @@ -5837,12 +5837,10 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha,
dma_addr_t rsp_els_dma;
dma_addr_t rsp_payload_dma;
dma_addr_t stat_dma;
dma_addr_t bbc_dma;
dma_addr_t sfp_dma;
struct els_entry_24xx *rsp_els = NULL;
struct rdp_rsp_payload *rsp_payload = NULL;
struct link_statistics *stat = NULL;
struct buffer_credit_24xx *bbc = NULL;
uint8_t *sfp = NULL;
uint16_t sfp_flags = 0;
uint rsp_payload_length = sizeof(*rsp_payload);
Expand Down Expand Up @@ -5886,9 +5884,6 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha,
stat = dma_alloc_coherent(&ha->pdev->dev, sizeof(*stat),
&stat_dma, GFP_KERNEL);

bbc = dma_alloc_coherent(&ha->pdev->dev, sizeof(*bbc),
&bbc_dma, GFP_KERNEL);

/* Prepare Response IOCB */
rsp_els->entry_type = ELS_IOCB_TYPE;
rsp_els->entry_count = 1;
Expand Down Expand Up @@ -6042,13 +6037,10 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha,
rsp_payload->buffer_credit_desc.attached_fcport_b2b = cpu_to_be32(0);
rsp_payload->buffer_credit_desc.fcport_rtt = cpu_to_be32(0);

if (bbc) {
memset(bbc, 0, sizeof(*bbc));
rval = qla24xx_get_buffer_credits(vha, bbc, bbc_dma);
if (!rval) {
rsp_payload->buffer_credit_desc.fcport_b2b =
cpu_to_be32(LSW(bbc->parameter[0]));
}
if (ha->flags.plogi_template_valid) {
uint32_t tmp =
be16_to_cpu(ha->plogi_els_payld.fl_csp.sp_bb_cred);
rsp_payload->buffer_credit_desc.fcport_b2b = cpu_to_be32(tmp);
}

if (rsp_payload_length < sizeof(*rsp_payload))
Expand Down Expand Up @@ -6226,9 +6218,6 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha,
}

dealloc:
if (bbc)
dma_free_coherent(&ha->pdev->dev, sizeof(*bbc),
bbc, bbc_dma);
if (stat)
dma_free_coherent(&ha->pdev->dev, sizeof(*stat),
stat, stat_dma);
Expand Down

0 comments on commit 44f5a37

Please sign in to comment.