Commit a4226ec3 authored by Quinn Tran's avatar Quinn Tran Committed by Martin K. Petersen

scsi: qla2xxx: Fix fw dump corruption

If fw dump buffer size changes and there is an existing fw dump, then save
the old dump in the newly allocated buffer.
Signed-off-by: default avatarQuinn Tran <quinn.tran@cavium.com>
Signed-off-by: default avatarHimanshu Madhani <hmadhani@marvell.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent e81d1bcb
...@@ -4046,6 +4046,7 @@ struct qla_hw_data { ...@@ -4046,6 +4046,7 @@ struct qla_hw_data {
} fwdt[2]; } fwdt[2];
struct qla2xxx_fw_dump *fw_dump; struct qla2xxx_fw_dump *fw_dump;
uint32_t fw_dump_len; uint32_t fw_dump_len;
u32 fw_dump_alloc_len;
bool fw_dumped; bool fw_dumped;
bool fw_dump_mpi; bool fw_dump_mpi;
unsigned long fw_dump_cap_flags; unsigned long fw_dump_cap_flags;
......
...@@ -3141,12 +3141,12 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) ...@@ -3141,12 +3141,12 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
!IS_QLA28XX(ha)) !IS_QLA28XX(ha))
mq_size = sizeof(struct qla2xxx_mq_chain); mq_size = sizeof(struct qla2xxx_mq_chain);
/* /*
* Allocate maximum buffer size for all queues. * Allocate maximum buffer size for all queues - Q0.
* Resizing must be done at end-of-dump processing. * Resizing must be done at end-of-dump processing.
*/ */
mq_size += ha->max_req_queues * mq_size += (ha->max_req_queues - 1) *
(req->length * sizeof(request_t)); (req->length * sizeof(request_t));
mq_size += ha->max_rsp_queues * mq_size += (ha->max_rsp_queues - 1) *
(rsp->length * sizeof(response_t)); (rsp->length * sizeof(response_t));
} }
if (ha->tgt.atio_ring) if (ha->tgt.atio_ring)
...@@ -3221,18 +3221,34 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) ...@@ -3221,18 +3221,34 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
ha->exlogin_size; ha->exlogin_size;
allocate: allocate:
if (!ha->fw_dump_len || dump_size != ha->fw_dump_len) { if (!ha->fw_dump_len || dump_size > ha->fw_dump_alloc_len) {
ql_dbg(ql_dbg_init, vha, 0x00c5,
"%s dump_size %d fw_dump_len %d fw_dump_alloc_len %d\n",
__func__, dump_size, ha->fw_dump_len,
ha->fw_dump_alloc_len);
fw_dump = vmalloc(dump_size); fw_dump = vmalloc(dump_size);
if (!fw_dump) { if (!fw_dump) {
ql_log(ql_log_warn, vha, 0x00c4, ql_log(ql_log_warn, vha, 0x00c4,
"Unable to allocate (%d KB) for firmware dump.\n", "Unable to allocate (%d KB) for firmware dump.\n",
dump_size / 1024); dump_size / 1024);
} else {
if (ha->fw_dumped) {
memcpy(fw_dump, ha->fw_dump, ha->fw_dump_len);
vfree(ha->fw_dump);
ha->fw_dump = fw_dump;
ha->fw_dump_alloc_len = dump_size;
ql_dbg(ql_dbg_init, vha, 0x00c5,
"Re-Allocated (%d KB) and save firmware dump.\n",
dump_size / 1024);
} else { } else {
if (ha->fw_dump) if (ha->fw_dump)
vfree(ha->fw_dump); vfree(ha->fw_dump);
ha->fw_dump = fw_dump; ha->fw_dump = fw_dump;
ha->fw_dump_len = dump_size; ha->fw_dump_len = ha->fw_dump_alloc_len =
dump_size;
ql_dbg(ql_dbg_init, vha, 0x00c5, ql_dbg(ql_dbg_init, vha, 0x00c5,
"Allocated (%d KB) for firmware dump.\n", "Allocated (%d KB) for firmware dump.\n",
dump_size / 1024); dump_size / 1024);
...@@ -3252,11 +3268,15 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) ...@@ -3252,11 +3268,15 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
ha->fw_dump->rsp_q_size = htonl(rsp_q_size); ha->fw_dump->rsp_q_size = htonl(rsp_q_size);
ha->fw_dump->eft_size = htonl(eft_size); ha->fw_dump->eft_size = htonl(eft_size);
ha->fw_dump->eft_addr_l = htonl(LSD(ha->eft_dma)); ha->fw_dump->eft_addr_l =
ha->fw_dump->eft_addr_h = htonl(MSD(ha->eft_dma)); htonl(LSD(ha->eft_dma));
ha->fw_dump->eft_addr_h =
htonl(MSD(ha->eft_dma));
ha->fw_dump->header_size = ha->fw_dump->header_size =
htonl(offsetof(struct qla2xxx_fw_dump, isp)); htonl(offsetof
(struct qla2xxx_fw_dump, isp));
}
} }
} }
} }
......
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