mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-18 16:44:33 +00:00
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: Quinn Tran <quinn.tran@cavium.com> Signed-off-by: Himanshu Madhani <hmadhani@marvell.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
e81d1bcbde
commit
a4226ec3ef
2 changed files with 47 additions and 26 deletions
|
@ -4046,6 +4046,7 @@ struct qla_hw_data {
|
|||
} fwdt[2];
|
||||
struct qla2xxx_fw_dump *fw_dump;
|
||||
uint32_t fw_dump_len;
|
||||
u32 fw_dump_alloc_len;
|
||||
bool fw_dumped;
|
||||
bool fw_dump_mpi;
|
||||
unsigned long fw_dump_cap_flags;
|
||||
|
|
|
@ -3141,12 +3141,12 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
|
|||
!IS_QLA28XX(ha))
|
||||
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.
|
||||
*/
|
||||
mq_size += ha->max_req_queues *
|
||||
mq_size += (ha->max_req_queues - 1) *
|
||||
(req->length * sizeof(request_t));
|
||||
mq_size += ha->max_rsp_queues *
|
||||
mq_size += (ha->max_rsp_queues - 1) *
|
||||
(rsp->length * sizeof(response_t));
|
||||
}
|
||||
if (ha->tgt.atio_ring)
|
||||
|
@ -3221,42 +3221,62 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
|
|||
ha->exlogin_size;
|
||||
|
||||
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);
|
||||
if (!fw_dump) {
|
||||
ql_log(ql_log_warn, vha, 0x00c4,
|
||||
"Unable to allocate (%d KB) for firmware dump.\n",
|
||||
dump_size / 1024);
|
||||
} else {
|
||||
if (ha->fw_dump)
|
||||
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 = 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 {
|
||||
if (ha->fw_dump)
|
||||
vfree(ha->fw_dump);
|
||||
ha->fw_dump = fw_dump;
|
||||
|
||||
ha->fw_dump_len = dump_size;
|
||||
ql_dbg(ql_dbg_init, vha, 0x00c5,
|
||||
"Allocated (%d KB) for firmware dump.\n",
|
||||
dump_size / 1024);
|
||||
ha->fw_dump_len = ha->fw_dump_alloc_len =
|
||||
dump_size;
|
||||
ql_dbg(ql_dbg_init, vha, 0x00c5,
|
||||
"Allocated (%d KB) for firmware dump.\n",
|
||||
dump_size / 1024);
|
||||
|
||||
if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
|
||||
return;
|
||||
if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
|
||||
return;
|
||||
|
||||
ha->fw_dump->signature[0] = 'Q';
|
||||
ha->fw_dump->signature[1] = 'L';
|
||||
ha->fw_dump->signature[2] = 'G';
|
||||
ha->fw_dump->signature[3] = 'C';
|
||||
ha->fw_dump->version = htonl(1);
|
||||
ha->fw_dump->signature[0] = 'Q';
|
||||
ha->fw_dump->signature[1] = 'L';
|
||||
ha->fw_dump->signature[2] = 'G';
|
||||
ha->fw_dump->signature[3] = 'C';
|
||||
ha->fw_dump->version = htonl(1);
|
||||
|
||||
ha->fw_dump->fixed_size = htonl(fixed_size);
|
||||
ha->fw_dump->mem_size = htonl(mem_size);
|
||||
ha->fw_dump->req_q_size = htonl(req_q_size);
|
||||
ha->fw_dump->rsp_q_size = htonl(rsp_q_size);
|
||||
ha->fw_dump->fixed_size = htonl(fixed_size);
|
||||
ha->fw_dump->mem_size = htonl(mem_size);
|
||||
ha->fw_dump->req_q_size = htonl(req_q_size);
|
||||
ha->fw_dump->rsp_q_size = htonl(rsp_q_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_h = htonl(MSD(ha->eft_dma));
|
||||
ha->fw_dump->eft_size = htonl(eft_size);
|
||||
ha->fw_dump->eft_addr_l =
|
||||
htonl(LSD(ha->eft_dma));
|
||||
ha->fw_dump->eft_addr_h =
|
||||
htonl(MSD(ha->eft_dma));
|
||||
|
||||
ha->fw_dump->header_size =
|
||||
htonl(offsetof(struct qla2xxx_fw_dump, isp));
|
||||
ha->fw_dump->header_size =
|
||||
htonl(offsetof
|
||||
(struct qla2xxx_fw_dump, isp));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue