diff options
author | Andrew Vasquez <andrew.vasquez@qlogic.com> | 2009-01-05 14:18:09 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-01-07 16:50:59 -0500 |
commit | d63ab53394f408f9e59f5b6ba0580f8c6ef2357a (patch) | |
tree | 7a1d17ecdfa754ed0819c3104a09a148c078599b /drivers | |
parent | bb99de6703526ebed42e29b8dee402df235f28c7 (diff) |
[SCSI] qla2xxx: Correct MQ-chain information retrieval during a firmware dump.
Original code would not read request/response queue pointers.
Also, collapse code into a helper qla25xx_copy_mq() function in
preparation for newer ISP parts.
Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_dbg.c | 77 |
1 files changed, 40 insertions, 37 deletions
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 49040ed3cea8..4f478364fa43 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c | |||
@@ -347,6 +347,39 @@ qla25xx_copy_fce(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain) | |||
347 | return iter_reg; | 347 | return iter_reg; |
348 | } | 348 | } |
349 | 349 | ||
350 | static inline void * | ||
351 | qla25xx_copy_mq(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain) | ||
352 | { | ||
353 | uint32_t cnt, que_idx; | ||
354 | uint8_t req_cnt, rsp_cnt, que_cnt; | ||
355 | struct qla2xxx_mq_chain *mq = ptr; | ||
356 | struct device_reg_25xxmq __iomem *reg; | ||
357 | |||
358 | if (!ha->mqenable) | ||
359 | return ptr; | ||
360 | |||
361 | mq = ptr; | ||
362 | *last_chain = &mq->type; | ||
363 | mq->type = __constant_htonl(DUMP_CHAIN_MQ); | ||
364 | mq->chain_size = __constant_htonl(sizeof(struct qla2xxx_mq_chain)); | ||
365 | |||
366 | req_cnt = find_first_zero_bit(ha->req_qid_map, ha->max_queues); | ||
367 | rsp_cnt = find_first_zero_bit(ha->rsp_qid_map, ha->max_queues); | ||
368 | que_cnt = req_cnt > rsp_cnt ? req_cnt : rsp_cnt; | ||
369 | mq->count = htonl(que_cnt); | ||
370 | for (cnt = 0; cnt < que_cnt; cnt++) { | ||
371 | reg = (struct device_reg_25xxmq *) ((void *) | ||
372 | ha->mqiobase + cnt * QLA_QUE_PAGE); | ||
373 | que_idx = cnt * 4; | ||
374 | mq->qregs[que_idx] = htonl(RD_REG_DWORD(®->req_q_in)); | ||
375 | mq->qregs[que_idx+1] = htonl(RD_REG_DWORD(®->req_q_out)); | ||
376 | mq->qregs[que_idx+2] = htonl(RD_REG_DWORD(®->rsp_q_in)); | ||
377 | mq->qregs[que_idx+3] = htonl(RD_REG_DWORD(®->rsp_q_out)); | ||
378 | } | ||
379 | |||
380 | return ptr + sizeof(struct qla2xxx_mq_chain); | ||
381 | } | ||
382 | |||
350 | /** | 383 | /** |
351 | * qla2300_fw_dump() - Dumps binary data from the 2300 firmware. | 384 | * qla2300_fw_dump() - Dumps binary data from the 2300 firmware. |
352 | * @ha: HA context | 385 | * @ha: HA context |
@@ -979,19 +1012,14 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) | |||
979 | uint32_t risc_address; | 1012 | uint32_t risc_address; |
980 | struct qla_hw_data *ha = vha->hw; | 1013 | struct qla_hw_data *ha = vha->hw; |
981 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; | 1014 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; |
982 | struct device_reg_25xxmq __iomem *reg25; | ||
983 | uint32_t __iomem *dmp_reg; | 1015 | uint32_t __iomem *dmp_reg; |
984 | uint32_t *iter_reg; | 1016 | uint32_t *iter_reg; |
985 | uint16_t __iomem *mbx_reg; | 1017 | uint16_t __iomem *mbx_reg; |
986 | unsigned long flags; | 1018 | unsigned long flags; |
987 | struct qla25xx_fw_dump *fw; | 1019 | struct qla25xx_fw_dump *fw; |
988 | uint32_t ext_mem_cnt; | 1020 | uint32_t ext_mem_cnt; |
989 | void *nxt; | 1021 | void *nxt, *nxt_chain; |
990 | uint32_t *last_chain = NULL; | 1022 | uint32_t *last_chain = NULL; |
991 | struct qla2xxx_mq_chain *mq = NULL; | ||
992 | uint32_t qreg_size; | ||
993 | uint8_t req_cnt, rsp_cnt, que_cnt; | ||
994 | uint32_t que_idx; | ||
995 | struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); | 1023 | struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); |
996 | 1024 | ||
997 | risc_address = ext_mem_cnt = 0; | 1025 | risc_address = ext_mem_cnt = 0; |
@@ -1038,29 +1066,6 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) | |||
1038 | fw->pcie_regs[2] = htonl(RD_REG_DWORD(dmp_reg)); | 1066 | fw->pcie_regs[2] = htonl(RD_REG_DWORD(dmp_reg)); |
1039 | fw->pcie_regs[3] = htonl(RD_REG_DWORD(®->iobase_window)); | 1067 | fw->pcie_regs[3] = htonl(RD_REG_DWORD(®->iobase_window)); |
1040 | 1068 | ||
1041 | /* Multi queue registers */ | ||
1042 | if (ha->mqenable) { | ||
1043 | qreg_size = sizeof(struct qla2xxx_mq_chain); | ||
1044 | mq = kzalloc(qreg_size, GFP_KERNEL); | ||
1045 | if (!mq) | ||
1046 | goto qla25xx_fw_dump_failed_0; | ||
1047 | req_cnt = find_first_zero_bit(ha->req_qid_map, ha->max_queues); | ||
1048 | rsp_cnt = find_first_zero_bit(ha->rsp_qid_map, ha->max_queues); | ||
1049 | que_cnt = req_cnt > rsp_cnt ? req_cnt : rsp_cnt; | ||
1050 | mq->count = htonl(que_cnt); | ||
1051 | mq->chain_size = htonl(qreg_size); | ||
1052 | last_chain = &mq->type; | ||
1053 | mq->type = __constant_htonl(DUMP_CHAIN_MQ); | ||
1054 | for (cnt = 0; cnt < que_cnt; cnt++) { | ||
1055 | reg25 = (struct device_reg_25xxmq *) ((void *) | ||
1056 | ha->mqiobase + cnt * QLA_QUE_PAGE); | ||
1057 | que_idx = cnt * 4; | ||
1058 | mq->qregs[que_idx] = htonl(reg25->req_q_in); | ||
1059 | mq->qregs[que_idx+1] = htonl(reg25->req_q_out); | ||
1060 | mq->qregs[que_idx+2] = htonl(reg25->rsp_q_in); | ||
1061 | mq->qregs[que_idx+3] = htonl(reg25->rsp_q_out); | ||
1062 | } | ||
1063 | } | ||
1064 | WRT_REG_DWORD(®->iobase_window, 0x00); | 1069 | WRT_REG_DWORD(®->iobase_window, 0x00); |
1065 | RD_REG_DWORD(®->iobase_window); | 1070 | RD_REG_DWORD(®->iobase_window); |
1066 | 1071 | ||
@@ -1278,6 +1283,10 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) | |||
1278 | iter_reg = qla24xx_read_window(reg, 0x61B0, 16, iter_reg); | 1283 | iter_reg = qla24xx_read_window(reg, 0x61B0, 16, iter_reg); |
1279 | qla24xx_read_window(reg, 0x6F00, 16, iter_reg); | 1284 | qla24xx_read_window(reg, 0x6F00, 16, iter_reg); |
1280 | 1285 | ||
1286 | /* Multi queue registers */ | ||
1287 | nxt_chain = qla25xx_copy_mq(ha, (void *)ha->fw_dump + ha->chain_offset, | ||
1288 | &last_chain); | ||
1289 | |||
1281 | rval = qla24xx_soft_reset(ha); | 1290 | rval = qla24xx_soft_reset(ha); |
1282 | if (rval != QLA_SUCCESS) | 1291 | if (rval != QLA_SUCCESS) |
1283 | goto qla25xx_fw_dump_failed_0; | 1292 | goto qla25xx_fw_dump_failed_0; |
@@ -1291,14 +1300,8 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) | |||
1291 | 1300 | ||
1292 | nxt = qla24xx_copy_eft(ha, nxt); | 1301 | nxt = qla24xx_copy_eft(ha, nxt); |
1293 | 1302 | ||
1294 | /* Chain entries. */ | 1303 | /* Chain entries -- started with MQ. */ |
1295 | if (ha->mqenable) { | 1304 | qla25xx_copy_fce(ha, nxt_chain, &last_chain); |
1296 | memcpy(nxt, mq, qreg_size); | ||
1297 | kfree(mq); | ||
1298 | nxt += qreg_size; | ||
1299 | } | ||
1300 | |||
1301 | qla25xx_copy_fce(ha, nxt, &last_chain); | ||
1302 | if (last_chain) { | 1305 | if (last_chain) { |
1303 | ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT); | 1306 | ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT); |
1304 | *last_chain |= __constant_htonl(DUMP_CHAIN_LAST); | 1307 | *last_chain |= __constant_htonl(DUMP_CHAIN_LAST); |