summaryrefslogtreecommitdiff
path: root/drivers/scsi/qla2xxx/qla_mbx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_mbx.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c123
1 files changed, 100 insertions, 23 deletions
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 968b84613..23698c998 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -64,6 +64,13 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
return QLA_FUNCTION_TIMEOUT;
}
+ /* if PCI error, then avoid mbx processing.*/
+ if (test_bit(PCI_ERR, &base_vha->dpc_flags)) {
+ ql_log(ql_log_warn, vha, 0x1191,
+ "PCI error, exiting.\n");
+ return QLA_FUNCTION_TIMEOUT;
+ }
+
reg = ha->iobase;
io_lock_on = base_vha->flags.init_done;
@@ -266,6 +273,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
uint16_t mb0;
uint32_t ictrl;
+ uint16_t w;
if (IS_FWI2_CAPABLE(ha)) {
mb0 = RD_REG_WORD(&reg->isp24.mailbox0);
@@ -279,15 +287,32 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
"mb[0]=0x%x\n", command, ictrl, jiffies, mb0);
ql_dump_regs(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1019);
- /*
- * Attempt to capture a firmware dump for further analysis
- * of the current firmware state. We do not need to do this
- * if we are intentionally generating a dump.
- */
- if (mcp->mb[0] != MBC_GEN_SYSTEM_ERROR)
- ha->isp_ops->fw_dump(vha, 0);
+ /* Capture FW dump only, if PCI device active */
+ if (!pci_channel_offline(vha->hw->pdev)) {
+ pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w);
+ if (w == 0xffff || ictrl == 0xffffffff) {
+ /* This is special case if there is unload
+ * of driver happening and if PCI device go
+ * into bad state due to PCI error condition
+ * then only PCI ERR flag would be set.
+ * we will do premature exit for above case.
+ */
+ if (test_bit(UNLOADING, &base_vha->dpc_flags))
+ set_bit(PCI_ERR, &base_vha->dpc_flags);
+ ha->flags.mbox_busy = 0;
+ rval = QLA_FUNCTION_TIMEOUT;
+ goto premature_exit;
+ }
- rval = QLA_FUNCTION_TIMEOUT;
+ /* Attempt to capture firmware dump for further
+ * anallysis of the current formware state. we do not
+ * need to do this if we are intentionally generating
+ * a dump
+ */
+ if (mcp->mb[0] != MBC_GEN_SYSTEM_ERROR)
+ ha->isp_ops->fw_dump(vha, 0);
+ rval = QLA_FUNCTION_TIMEOUT;
+ }
}
ha->flags.mbox_busy = 0;
@@ -379,7 +404,7 @@ mbx_done:
"**** Failed mbx[0]=%x, mb[1]=%x, mb[2]=%x, mb[3]=%x, cmd=%x ****.\n",
mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3], command);
- ql_dbg(ql_dbg_disc, vha, 0x1115,
+ ql_dbg(ql_dbg_mbx, vha, 0x1198,
"host status: 0x%x, flags:0x%lx, intr ctrl reg:0x%x, intr status:0x%x\n",
RD_REG_DWORD(&reg->isp24.host_status),
ha->fw_dump_cap_flags,
@@ -388,7 +413,7 @@ mbx_done:
mbx_reg = &reg->isp24.mailbox0;
for (i = 0; i < 6; i++)
- ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x1116,
+ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1199,
"mbox[%d] 0x%04x\n", i, RD_REG_WORD(mbx_reg++));
} else {
ql_dbg(ql_dbg_mbx, base_vha, 0x1021, "Done %s.\n", __func__);
@@ -782,8 +807,9 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha)
if (IS_FWI2_CAPABLE(ha))
mcp->in_mb |= MBX_17|MBX_16|MBX_15;
if (IS_QLA27XX(ha))
- mcp->in_mb |= MBX_23 | MBX_22 | MBX_21 | MBX_20 | MBX_19 |
- MBX_18 | MBX_14 | MBX_13 | MBX_11 | MBX_10 | MBX_9 | MBX_8;
+ mcp->in_mb |=
+ MBX_25|MBX_24|MBX_23|MBX_22|MBX_21|MBX_20|MBX_19|MBX_18|
+ MBX_14|MBX_13|MBX_11|MBX_10|MBX_9|MBX_8;
mcp->flags = 0;
mcp->tov = MBX_TOV_SECONDS;
@@ -842,6 +868,8 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha)
ha->pep_version[2] = mcp->mb[14] & 0xff;
ha->fw_shared_ram_start = (mcp->mb[19] << 16) | mcp->mb[18];
ha->fw_shared_ram_end = (mcp->mb[21] << 16) | mcp->mb[20];
+ ha->fw_ddr_ram_start = (mcp->mb[23] << 16) | mcp->mb[22];
+ ha->fw_ddr_ram_end = (mcp->mb[25] << 16) | mcp->mb[24];
}
failed:
@@ -1844,7 +1872,7 @@ qla2x00_get_firmware_state(scsi_qla_host_t *vha, uint16_t *states)
states[0] = mcp->mb[1];
if (IS_FWI2_CAPABLE(vha->hw)) {
states[1] = mcp->mb[2];
- states[2] = mcp->mb[3];
+ states[2] = mcp->mb[3]; /* SFP info */
states[3] = mcp->mb[4];
states[4] = mcp->mb[5];
states[5] = mcp->mb[6]; /* DPORT status */
@@ -2759,15 +2787,16 @@ qla2x00_get_link_status(scsi_qla_host_t *vha, uint16_t loop_id,
int rval;
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- uint32_t *iter, dwords;
+ uint32_t *iter = (void *)stats;
+ ushort dwords = offsetof(typeof(*stats), link_up_cnt)/sizeof(*iter);
struct qla_hw_data *ha = vha->hw;
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1084,
"Entered %s.\n", __func__);
mcp->mb[0] = MBC_GET_LINK_STATUS;
- mcp->mb[2] = MSW(stats_dma);
- mcp->mb[3] = LSW(stats_dma);
+ mcp->mb[2] = MSW(LSD(stats_dma));
+ mcp->mb[3] = LSW(LSD(stats_dma));
mcp->mb[6] = MSW(MSD(stats_dma));
mcp->mb[7] = LSW(MSD(stats_dma));
mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
@@ -2796,12 +2825,9 @@ qla2x00_get_link_status(scsi_qla_host_t *vha, uint16_t loop_id,
"Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
rval = QLA_FUNCTION_FAILED;
} else {
- /* Copy over data -- firmware data is LE. */
+ /* Re-endianize - firmware data is le32. */
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1086,
"Done %s.\n", __func__);
- dwords = offsetof(struct link_statistics,
- link_up_cnt) / 4;
- iter = &stats->link_fail_cnt;
for ( ; dwords--; iter++)
le32_to_cpus(iter);
}
@@ -2815,7 +2841,7 @@ qla2x00_get_link_status(scsi_qla_host_t *vha, uint16_t loop_id,
int
qla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats,
- dma_addr_t stats_dma)
+ dma_addr_t stats_dma, uint options)
{
int rval;
mbx_cmd_t mc;
@@ -2832,7 +2858,7 @@ qla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats,
mcp->mb[7] = LSW(MSD(stats_dma));
mcp->mb[8] = sizeof(struct link_statistics) / 4;
mcp->mb[9] = vha->vp_idx;
- mcp->mb[10] = 0;
+ mcp->mb[10] = options;
mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
mcp->in_mb = MBX_2|MBX_1|MBX_0;
mcp->tov = MBX_TOV_SECONDS;
@@ -2847,7 +2873,7 @@ qla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats,
} else {
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x108a,
"Done %s.\n", __func__);
- /* Copy over data -- firmware data is LE. */
+ /* Re-endianize - firmware data is le32. */
dwords = sizeof(struct link_statistics) / 4;
iter = &stats->link_fail_cnt;
for ( ; dwords--; iter++)
@@ -5722,3 +5748,54 @@ qla2x00_dump_mctp_data(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t addr,
return rval;
}
+
+int
+qla26xx_dport_diagnostics(scsi_qla_host_t *vha,
+ void *dd_buf, uint size, uint options)
+{
+ int rval;
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+ dma_addr_t dd_dma;
+
+ if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw))
+ return QLA_FUNCTION_FAILED;
+
+ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1192,
+ "Entered %s.\n", __func__);
+
+ dd_dma = dma_map_single(&vha->hw->pdev->dev,
+ dd_buf, size, DMA_FROM_DEVICE);
+ if (!dd_dma) {
+ ql_log(ql_log_warn, vha, 0x1194, "Failed to map dma buffer.\n");
+ return QLA_MEMORY_ALLOC_FAILED;
+ }
+
+ memset(dd_buf, 0, size);
+
+ mcp->mb[0] = MBC_DPORT_DIAGNOSTICS;
+ mcp->mb[1] = options;
+ mcp->mb[2] = MSW(LSD(dd_dma));
+ mcp->mb[3] = LSW(LSD(dd_dma));
+ mcp->mb[6] = MSW(MSD(dd_dma));
+ mcp->mb[7] = LSW(MSD(dd_dma));
+ mcp->mb[8] = size;
+ mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->buf_size = size;
+ mcp->flags = MBX_DMA_IN;
+ mcp->tov = MBX_TOV_SECONDS * 4;
+ rval = qla2x00_mailbox_command(vha, mcp);
+
+ if (rval != QLA_SUCCESS) {
+ ql_dbg(ql_dbg_mbx, vha, 0x1195, "Failed=%x.\n", rval);
+ } else {
+ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1196,
+ "Done %s.\n", __func__);
+ }
+
+ dma_unmap_single(&vha->hw->pdev->dev, dd_dma,
+ size, DMA_FROM_DEVICE);
+
+ return rval;
+}