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

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
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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;
+52 −32
Original line number Diff line number Diff line
@@ -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,18 +3221,34 @@ 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_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 {
				if (ha->fw_dump)
					vfree(ha->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,
				    "Allocated (%d KB) for firmware dump.\n",
				    dump_size / 1024);
@@ -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->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_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));
					htonl(offsetof
					    (struct qla2xxx_fw_dump, isp));
			}
		}
	}
}