aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_nx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_nx.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_nx.c910
1 files changed, 884 insertions, 26 deletions
diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c
index 049807cda419..43a0a9a4556f 100644
--- a/drivers/scsi/qla2xxx/qla_nx.c
+++ b/drivers/scsi/qla2xxx/qla_nx.c
@@ -7,6 +7,8 @@
7#include "qla_def.h" 7#include "qla_def.h"
8#include <linux/delay.h> 8#include <linux/delay.h>
9#include <linux/pci.h> 9#include <linux/pci.h>
10#include <linux/ratelimit.h>
11#include <linux/vmalloc.h>
10#include <scsi/scsi_tcq.h> 12#include <scsi/scsi_tcq.h>
11 13
12#define MASK(n) ((1ULL<<(n))-1) 14#define MASK(n) ((1ULL<<(n))-1)
@@ -328,7 +330,7 @@ unsigned qla82xx_crb_hub_agt[64] = {
328}; 330};
329 331
330/* Device states */ 332/* Device states */
331char *qdev_state[] = { 333char *q_dev_state[] = {
332 "Unknown", 334 "Unknown",
333 "Cold", 335 "Cold",
334 "Initializing", 336 "Initializing",
@@ -339,6 +341,11 @@ char *qdev_state[] = {
339 "Quiescent", 341 "Quiescent",
340}; 342};
341 343
344char *qdev_state(uint32_t dev_state)
345{
346 return q_dev_state[dev_state];
347}
348
342/* 349/*
343 * In: 'off' is offset from CRB space in 128M pci map 350 * In: 'off' is offset from CRB space in 128M pci map
344 * Out: 'off' is 2M pci map addr 351 * Out: 'off' is 2M pci map addr
@@ -2355,9 +2362,13 @@ qla82xx_need_reset(struct qla_hw_data *ha)
2355 uint32_t drv_state; 2362 uint32_t drv_state;
2356 int rval; 2363 int rval;
2357 2364
2358 drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE); 2365 if (ha->flags.isp82xx_reset_owner)
2359 rval = drv_state & (QLA82XX_DRVST_RST_RDY << (ha->portnum * 4)); 2366 return 1;
2360 return rval; 2367 else {
2368 drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
2369 rval = drv_state & (QLA82XX_DRVST_RST_RDY << (ha->portnum * 4));
2370 return rval;
2371 }
2361} 2372}
2362 2373
2363static inline void 2374static inline void
@@ -2374,8 +2385,8 @@ qla82xx_set_rst_ready(struct qla_hw_data *ha)
2374 drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE); 2385 drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
2375 } 2386 }
2376 drv_state |= (QLA82XX_DRVST_RST_RDY << (ha->portnum * 4)); 2387 drv_state |= (QLA82XX_DRVST_RST_RDY << (ha->portnum * 4));
2377 ql_log(ql_log_info, vha, 0x00bb, 2388 ql_dbg(ql_dbg_init, vha, 0x00bb,
2378 "drv_state = 0x%x.\n", drv_state); 2389 "drv_state = 0x%08x.\n", drv_state);
2379 qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, drv_state); 2390 qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, drv_state);
2380} 2391}
2381 2392
@@ -3528,7 +3539,7 @@ qla82xx_dev_failed_handler(scsi_qla_host_t *vha)
3528static void 3539static void
3529qla82xx_need_reset_handler(scsi_qla_host_t *vha) 3540qla82xx_need_reset_handler(scsi_qla_host_t *vha)
3530{ 3541{
3531 uint32_t dev_state, drv_state, drv_active; 3542 uint32_t dev_state, drv_state, drv_active, active_mask;
3532 unsigned long reset_timeout; 3543 unsigned long reset_timeout;
3533 struct qla_hw_data *ha = vha->hw; 3544 struct qla_hw_data *ha = vha->hw;
3534 struct req_que *req = ha->req_q_map[0]; 3545 struct req_que *req = ha->req_q_map[0];
@@ -3541,15 +3552,32 @@ qla82xx_need_reset_handler(scsi_qla_host_t *vha)
3541 qla82xx_idc_lock(ha); 3552 qla82xx_idc_lock(ha);
3542 } 3553 }
3543 3554
3544 qla82xx_set_rst_ready(ha); 3555 drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
3556 if (!ha->flags.isp82xx_reset_owner) {
3557 ql_dbg(ql_dbg_p3p, vha, 0xb028,
3558 "reset_acknowledged by 0x%x\n", ha->portnum);
3559 qla82xx_set_rst_ready(ha);
3560 } else {
3561 active_mask = ~(QLA82XX_DRV_ACTIVE << (ha->portnum * 4));
3562 drv_active &= active_mask;
3563 ql_dbg(ql_dbg_p3p, vha, 0xb029,
3564 "active_mask: 0x%08x\n", active_mask);
3565 }
3545 3566
3546 /* wait for 10 seconds for reset ack from all functions */ 3567 /* wait for 10 seconds for reset ack from all functions */
3547 reset_timeout = jiffies + (ha->nx_reset_timeout * HZ); 3568 reset_timeout = jiffies + (ha->nx_reset_timeout * HZ);
3548 3569
3549 drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE); 3570 drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
3550 drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); 3571 drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
3572 dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
3551 3573
3552 while (drv_state != drv_active) { 3574 ql_dbg(ql_dbg_p3p, vha, 0xb02a,
3575 "drv_state: 0x%08x, drv_active: 0x%08x, "
3576 "dev_state: 0x%08x, active_mask: 0x%08x\n",
3577 drv_state, drv_active, dev_state, active_mask);
3578
3579 while (drv_state != drv_active &&
3580 dev_state != QLA82XX_DEV_INITIALIZING) {
3553 if (time_after_eq(jiffies, reset_timeout)) { 3581 if (time_after_eq(jiffies, reset_timeout)) {
3554 ql_log(ql_log_warn, vha, 0x00b5, 3582 ql_log(ql_log_warn, vha, 0x00b5,
3555 "Reset timeout.\n"); 3583 "Reset timeout.\n");
@@ -3560,22 +3588,78 @@ qla82xx_need_reset_handler(scsi_qla_host_t *vha)
3560 qla82xx_idc_lock(ha); 3588 qla82xx_idc_lock(ha);
3561 drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE); 3589 drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
3562 drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); 3590 drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
3591 if (ha->flags.isp82xx_reset_owner)
3592 drv_active &= active_mask;
3593 dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
3563 } 3594 }
3564 3595
3565 dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); 3596 ql_dbg(ql_dbg_p3p, vha, 0xb02b,
3597 "drv_state: 0x%08x, drv_active: 0x%08x, "
3598 "dev_state: 0x%08x, active_mask: 0x%08x\n",
3599 drv_state, drv_active, dev_state, active_mask);
3600
3566 ql_log(ql_log_info, vha, 0x00b6, 3601 ql_log(ql_log_info, vha, 0x00b6,
3567 "Device state is 0x%x = %s.\n", 3602 "Device state is 0x%x = %s.\n",
3568 dev_state, 3603 dev_state,
3569 dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown"); 3604 dev_state < MAX_STATES ? qdev_state(dev_state) : "Unknown");
3570 3605
3571 /* Force to DEV_COLD unless someone else is starting a reset */ 3606 /* Force to DEV_COLD unless someone else is starting a reset */
3572 if (dev_state != QLA82XX_DEV_INITIALIZING) { 3607 if (dev_state != QLA82XX_DEV_INITIALIZING &&
3608 dev_state != QLA82XX_DEV_COLD) {
3573 ql_log(ql_log_info, vha, 0x00b7, 3609 ql_log(ql_log_info, vha, 0x00b7,
3574 "HW State: COLD/RE-INIT.\n"); 3610 "HW State: COLD/RE-INIT.\n");
3575 qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_COLD); 3611 qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_COLD);
3612 if (ql2xmdenable) {
3613 if (qla82xx_md_collect(vha))
3614 ql_log(ql_log_warn, vha, 0xb02c,
3615 "Not able to collect minidump.\n");
3616 } else
3617 ql_log(ql_log_warn, vha, 0xb04f,
3618 "Minidump disabled.\n");
3576 } 3619 }
3577} 3620}
3578 3621
3622static void
3623qla82xx_check_md_needed(scsi_qla_host_t *vha)
3624{
3625 struct qla_hw_data *ha = vha->hw;
3626 uint16_t fw_major_version, fw_minor_version, fw_subminor_version;
3627 uint16_t fw_attributes;
3628 uint32_t fw_memory_size, mpi_capabilities;
3629 uint8_t mpi_version[3], phy_version[3];
3630
3631 if (!ha->fw_dumped) {
3632 qla2x00_get_fw_version(vha,
3633 &fw_major_version,
3634 &fw_minor_version,
3635 &fw_subminor_version,
3636 &fw_attributes, &fw_memory_size,
3637 mpi_version, &mpi_capabilities,
3638 phy_version);
3639
3640 if (fw_major_version != ha->fw_major_version ||
3641 fw_minor_version != ha->fw_minor_version ||
3642 fw_subminor_version != ha->fw_subminor_version) {
3643 ql_log(ql_log_info, vha, 0xb02d,
3644 "Firmware version differs "
3645 "Previous version: %d:%d:%d - "
3646 "New version: %d:%d:%d\n",
3647 ha->fw_major_version,
3648 ha->fw_minor_version, ha->fw_subminor_version,
3649 fw_major_version, fw_minor_version,
3650 fw_subminor_version);
3651 /* Release MiniDump resources */
3652 qla82xx_md_free(vha);
3653 /* ALlocate MiniDump resources */
3654 qla82xx_md_prep(vha);
3655 }
3656 } else
3657 ql_log(ql_log_info, vha, 0xb02e,
3658 "Firmware dump available to retrieve\n",
3659 vha->host_no);
3660}
3661
3662
3579int 3663int
3580qla82xx_check_fw_alive(scsi_qla_host_t *vha) 3664qla82xx_check_fw_alive(scsi_qla_host_t *vha)
3581{ 3665{
@@ -3637,7 +3721,7 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha)
3637 ql_log(ql_log_info, vha, 0x009b, 3721 ql_log(ql_log_info, vha, 0x009b,
3638 "Device state is 0x%x = %s.\n", 3722 "Device state is 0x%x = %s.\n",
3639 dev_state, 3723 dev_state,
3640 dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown"); 3724 dev_state < MAX_STATES ? qdev_state(dev_state) : "Unknown");
3641 3725
3642 /* wait for 30 seconds for device to go ready */ 3726 /* wait for 30 seconds for device to go ready */
3643 dev_init_timeout = jiffies + (ha->nx_dev_init_timeout * HZ); 3727 dev_init_timeout = jiffies + (ha->nx_dev_init_timeout * HZ);
@@ -3659,16 +3743,18 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha)
3659 ql_log(ql_log_info, vha, 0x009d, 3743 ql_log(ql_log_info, vha, 0x009d,
3660 "Device state is 0x%x = %s.\n", 3744 "Device state is 0x%x = %s.\n",
3661 dev_state, 3745 dev_state,
3662 dev_state < MAX_STATES ? qdev_state[dev_state] : 3746 dev_state < MAX_STATES ? qdev_state(dev_state) :
3663 "Unknown"); 3747 "Unknown");
3664 } 3748 }
3665 3749
3666 switch (dev_state) { 3750 switch (dev_state) {
3667 case QLA82XX_DEV_READY: 3751 case QLA82XX_DEV_READY:
3752 qla82xx_check_md_needed(vha);
3753 ha->flags.isp82xx_reset_owner = 0;
3668 goto exit; 3754 goto exit;
3669 case QLA82XX_DEV_COLD: 3755 case QLA82XX_DEV_COLD:
3670 rval = qla82xx_device_bootstrap(vha); 3756 rval = qla82xx_device_bootstrap(vha);
3671 goto exit; 3757 break;
3672 case QLA82XX_DEV_INITIALIZING: 3758 case QLA82XX_DEV_INITIALIZING:
3673 qla82xx_idc_unlock(ha); 3759 qla82xx_idc_unlock(ha);
3674 msleep(1000); 3760 msleep(1000);
@@ -3791,6 +3877,28 @@ int qla82xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
3791 return rval; 3877 return rval;
3792} 3878}
3793 3879
3880void
3881qla82xx_set_reset_owner(scsi_qla_host_t *vha)
3882{
3883 struct qla_hw_data *ha = vha->hw;
3884 uint32_t dev_state;
3885
3886 dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
3887 if (dev_state == QLA82XX_DEV_READY) {
3888 ql_log(ql_log_info, vha, 0xb02f,
3889 "HW State: NEED RESET\n");
3890 qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
3891 QLA82XX_DEV_NEED_RESET);
3892 ha->flags.isp82xx_reset_owner = 1;
3893 ql_dbg(ql_dbg_p3p, vha, 0xb030,
3894 "reset_owner is 0x%x\n", ha->portnum);
3895 } else
3896 ql_log(ql_log_info, vha, 0xb031,
3897 "Device state is 0x%x = %s.\n",
3898 dev_state,
3899 dev_state < MAX_STATES ? qdev_state(dev_state) : "Unknown");
3900}
3901
3794/* 3902/*
3795 * qla82xx_abort_isp 3903 * qla82xx_abort_isp
3796 * Resets ISP and aborts all outstanding commands. 3904 * Resets ISP and aborts all outstanding commands.
@@ -3806,7 +3914,6 @@ qla82xx_abort_isp(scsi_qla_host_t *vha)
3806{ 3914{
3807 int rval; 3915 int rval;
3808 struct qla_hw_data *ha = vha->hw; 3916 struct qla_hw_data *ha = vha->hw;
3809 uint32_t dev_state;
3810 3917
3811 if (vha->device_flags & DFLG_DEV_FAILED) { 3918 if (vha->device_flags & DFLG_DEV_FAILED) {
3812 ql_log(ql_log_warn, vha, 0x8024, 3919 ql_log(ql_log_warn, vha, 0x8024,
@@ -3816,16 +3923,7 @@ qla82xx_abort_isp(scsi_qla_host_t *vha)
3816 ha->flags.isp82xx_reset_hdlr_active = 1; 3923 ha->flags.isp82xx_reset_hdlr_active = 1;
3817 3924
3818 qla82xx_idc_lock(ha); 3925 qla82xx_idc_lock(ha);
3819 dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); 3926 qla82xx_set_reset_owner(vha);
3820 if (dev_state == QLA82XX_DEV_READY) {
3821 ql_log(ql_log_info, vha, 0x8025,
3822 "HW State: NEED RESET.\n");
3823 qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
3824 QLA82XX_DEV_NEED_RESET);
3825 } else
3826 ql_log(ql_log_info, vha, 0x8026,
3827 "Hw State: %s.\n", dev_state < MAX_STATES ?
3828 qdev_state[dev_state] : "Unknown");
3829 qla82xx_idc_unlock(ha); 3927 qla82xx_idc_unlock(ha);
3830 3928
3831 rval = qla82xx_device_state_handler(vha); 3929 rval = qla82xx_device_state_handler(vha);
@@ -4016,3 +4114,763 @@ qla82xx_chip_reset_cleanup(scsi_qla_host_t *vha)
4016 } 4114 }
4017 } 4115 }
4018} 4116}
4117
4118/* Minidump related functions */
4119int
4120qla82xx_md_rw_32(struct qla_hw_data *ha, uint32_t off, u32 data, uint8_t flag)
4121{
4122 uint32_t off_value, rval = 0;
4123
4124 WRT_REG_DWORD((void *)(CRB_WINDOW_2M + ha->nx_pcibase),
4125 (off & 0xFFFF0000));
4126
4127 /* Read back value to make sure write has gone through */
4128 RD_REG_DWORD((void *)(CRB_WINDOW_2M + ha->nx_pcibase));
4129 off_value = (off & 0x0000FFFF);
4130
4131 if (flag)
4132 WRT_REG_DWORD((void *)
4133 (off_value + CRB_INDIRECT_2M + ha->nx_pcibase),
4134 data);
4135 else
4136 rval = RD_REG_DWORD((void *)
4137 (off_value + CRB_INDIRECT_2M + ha->nx_pcibase));
4138
4139 return rval;
4140}
4141
4142static int
4143qla82xx_minidump_process_control(scsi_qla_host_t *vha,
4144 qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
4145{
4146 struct qla_hw_data *ha = vha->hw;
4147 struct qla82xx_md_entry_crb *crb_entry;
4148 uint32_t read_value, opcode, poll_time;
4149 uint32_t addr, index, crb_addr;
4150 unsigned long wtime;
4151 struct qla82xx_md_template_hdr *tmplt_hdr;
4152 uint32_t rval = QLA_SUCCESS;
4153 int i;
4154
4155 tmplt_hdr = (struct qla82xx_md_template_hdr *)ha->md_tmplt_hdr;
4156 crb_entry = (struct qla82xx_md_entry_crb *)entry_hdr;
4157 crb_addr = crb_entry->addr;
4158
4159 for (i = 0; i < crb_entry->op_count; i++) {
4160 opcode = crb_entry->crb_ctrl.opcode;
4161 if (opcode & QLA82XX_DBG_OPCODE_WR) {
4162 qla82xx_md_rw_32(ha, crb_addr,
4163 crb_entry->value_1, 1);
4164 opcode &= ~QLA82XX_DBG_OPCODE_WR;
4165 }
4166
4167 if (opcode & QLA82XX_DBG_OPCODE_RW) {
4168 read_value = qla82xx_md_rw_32(ha, crb_addr, 0, 0);
4169 qla82xx_md_rw_32(ha, crb_addr, read_value, 1);
4170 opcode &= ~QLA82XX_DBG_OPCODE_RW;
4171 }
4172
4173 if (opcode & QLA82XX_DBG_OPCODE_AND) {
4174 read_value = qla82xx_md_rw_32(ha, crb_addr, 0, 0);
4175 read_value &= crb_entry->value_2;
4176 opcode &= ~QLA82XX_DBG_OPCODE_AND;
4177 if (opcode & QLA82XX_DBG_OPCODE_OR) {
4178 read_value |= crb_entry->value_3;
4179 opcode &= ~QLA82XX_DBG_OPCODE_OR;
4180 }
4181 qla82xx_md_rw_32(ha, crb_addr, read_value, 1);
4182 }
4183
4184 if (opcode & QLA82XX_DBG_OPCODE_OR) {
4185 read_value = qla82xx_md_rw_32(ha, crb_addr, 0, 0);
4186 read_value |= crb_entry->value_3;
4187 qla82xx_md_rw_32(ha, crb_addr, read_value, 1);
4188 opcode &= ~QLA82XX_DBG_OPCODE_OR;
4189 }
4190
4191 if (opcode & QLA82XX_DBG_OPCODE_POLL) {
4192 poll_time = crb_entry->crb_strd.poll_timeout;
4193 wtime = jiffies + poll_time;
4194 read_value = qla82xx_md_rw_32(ha, crb_addr, 0, 0);
4195
4196 do {
4197 if ((read_value & crb_entry->value_2)
4198 == crb_entry->value_1)
4199 break;
4200 else if (time_after_eq(jiffies, wtime)) {
4201 /* capturing dump failed */
4202 rval = QLA_FUNCTION_FAILED;
4203 break;
4204 } else
4205 read_value = qla82xx_md_rw_32(ha,
4206 crb_addr, 0, 0);
4207 } while (1);
4208 opcode &= ~QLA82XX_DBG_OPCODE_POLL;
4209 }
4210
4211 if (opcode & QLA82XX_DBG_OPCODE_RDSTATE) {
4212 if (crb_entry->crb_strd.state_index_a) {
4213 index = crb_entry->crb_strd.state_index_a;
4214 addr = tmplt_hdr->saved_state_array[index];
4215 } else
4216 addr = crb_addr;
4217
4218 read_value = qla82xx_md_rw_32(ha, addr, 0, 0);
4219 index = crb_entry->crb_ctrl.state_index_v;
4220 tmplt_hdr->saved_state_array[index] = read_value;
4221 opcode &= ~QLA82XX_DBG_OPCODE_RDSTATE;
4222 }
4223
4224 if (opcode & QLA82XX_DBG_OPCODE_WRSTATE) {
4225 if (crb_entry->crb_strd.state_index_a) {
4226 index = crb_entry->crb_strd.state_index_a;
4227 addr = tmplt_hdr->saved_state_array[index];
4228 } else
4229 addr = crb_addr;
4230
4231 if (crb_entry->crb_ctrl.state_index_v) {
4232 index = crb_entry->crb_ctrl.state_index_v;
4233 read_value =
4234 tmplt_hdr->saved_state_array[index];
4235 } else
4236 read_value = crb_entry->value_1;
4237
4238 qla82xx_md_rw_32(ha, addr, read_value, 1);
4239 opcode &= ~QLA82XX_DBG_OPCODE_WRSTATE;
4240 }
4241
4242 if (opcode & QLA82XX_DBG_OPCODE_MDSTATE) {
4243 index = crb_entry->crb_ctrl.state_index_v;
4244 read_value = tmplt_hdr->saved_state_array[index];
4245 read_value <<= crb_entry->crb_ctrl.shl;
4246 read_value >>= crb_entry->crb_ctrl.shr;
4247 if (crb_entry->value_2)
4248 read_value &= crb_entry->value_2;
4249 read_value |= crb_entry->value_3;
4250 read_value += crb_entry->value_1;
4251 tmplt_hdr->saved_state_array[index] = read_value;
4252 opcode &= ~QLA82XX_DBG_OPCODE_MDSTATE;
4253 }
4254 crb_addr += crb_entry->crb_strd.addr_stride;
4255 }
4256 return rval;
4257}
4258
4259static void
4260qla82xx_minidump_process_rdocm(scsi_qla_host_t *vha,
4261 qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
4262{
4263 struct qla_hw_data *ha = vha->hw;
4264 uint32_t r_addr, r_stride, loop_cnt, i, r_value;
4265 struct qla82xx_md_entry_rdocm *ocm_hdr;
4266 uint32_t *data_ptr = *d_ptr;
4267
4268 ocm_hdr = (struct qla82xx_md_entry_rdocm *)entry_hdr;
4269 r_addr = ocm_hdr->read_addr;
4270 r_stride = ocm_hdr->read_addr_stride;
4271 loop_cnt = ocm_hdr->op_count;
4272
4273 for (i = 0; i < loop_cnt; i++) {
4274 r_value = RD_REG_DWORD((void *)(r_addr + ha->nx_pcibase));
4275 *data_ptr++ = cpu_to_le32(r_value);
4276 r_addr += r_stride;
4277 }
4278 *d_ptr = data_ptr;
4279}
4280
4281static void
4282qla82xx_minidump_process_rdmux(scsi_qla_host_t *vha,
4283 qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
4284{
4285 struct qla_hw_data *ha = vha->hw;
4286 uint32_t r_addr, s_stride, s_addr, s_value, loop_cnt, i, r_value;
4287 struct qla82xx_md_entry_mux *mux_hdr;
4288 uint32_t *data_ptr = *d_ptr;
4289
4290 mux_hdr = (struct qla82xx_md_entry_mux *)entry_hdr;
4291 r_addr = mux_hdr->read_addr;
4292 s_addr = mux_hdr->select_addr;
4293 s_stride = mux_hdr->select_value_stride;
4294 s_value = mux_hdr->select_value;
4295 loop_cnt = mux_hdr->op_count;
4296
4297 for (i = 0; i < loop_cnt; i++) {
4298 qla82xx_md_rw_32(ha, s_addr, s_value, 1);
4299 r_value = qla82xx_md_rw_32(ha, r_addr, 0, 0);
4300 *data_ptr++ = cpu_to_le32(s_value);
4301 *data_ptr++ = cpu_to_le32(r_value);
4302 s_value += s_stride;
4303 }
4304 *d_ptr = data_ptr;
4305}
4306
4307static void
4308qla82xx_minidump_process_rdcrb(scsi_qla_host_t *vha,
4309 qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
4310{
4311 struct qla_hw_data *ha = vha->hw;
4312 uint32_t r_addr, r_stride, loop_cnt, i, r_value;
4313 struct qla82xx_md_entry_crb *crb_hdr;
4314 uint32_t *data_ptr = *d_ptr;
4315
4316 crb_hdr = (struct qla82xx_md_entry_crb *)entry_hdr;
4317 r_addr = crb_hdr->addr;
4318 r_stride = crb_hdr->crb_strd.addr_stride;
4319 loop_cnt = crb_hdr->op_count;
4320
4321 for (i = 0; i < loop_cnt; i++) {
4322 r_value = qla82xx_md_rw_32(ha, r_addr, 0, 0);
4323 *data_ptr++ = cpu_to_le32(r_addr);
4324 *data_ptr++ = cpu_to_le32(r_value);
4325 r_addr += r_stride;
4326 }
4327 *d_ptr = data_ptr;
4328}
4329
4330static int
4331qla82xx_minidump_process_l2tag(scsi_qla_host_t *vha,
4332 qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
4333{
4334 struct qla_hw_data *ha = vha->hw;
4335 uint32_t addr, r_addr, c_addr, t_r_addr;
4336 uint32_t i, k, loop_count, t_value, r_cnt, r_value;
4337 unsigned long p_wait, w_time, p_mask;
4338 uint32_t c_value_w, c_value_r;
4339 struct qla82xx_md_entry_cache *cache_hdr;
4340 int rval = QLA_FUNCTION_FAILED;
4341 uint32_t *data_ptr = *d_ptr;
4342
4343 cache_hdr = (struct qla82xx_md_entry_cache *)entry_hdr;
4344 loop_count = cache_hdr->op_count;
4345 r_addr = cache_hdr->read_addr;
4346 c_addr = cache_hdr->control_addr;
4347 c_value_w = cache_hdr->cache_ctrl.write_value;
4348
4349 t_r_addr = cache_hdr->tag_reg_addr;
4350 t_value = cache_hdr->addr_ctrl.init_tag_value;
4351 r_cnt = cache_hdr->read_ctrl.read_addr_cnt;
4352 p_wait = cache_hdr->cache_ctrl.poll_wait;
4353 p_mask = cache_hdr->cache_ctrl.poll_mask;
4354
4355 for (i = 0; i < loop_count; i++) {
4356 qla82xx_md_rw_32(ha, t_r_addr, t_value, 1);
4357 if (c_value_w)
4358 qla82xx_md_rw_32(ha, c_addr, c_value_w, 1);
4359
4360 if (p_mask) {
4361 w_time = jiffies + p_wait;
4362 do {
4363 c_value_r = qla82xx_md_rw_32(ha, c_addr, 0, 0);
4364 if ((c_value_r & p_mask) == 0)
4365 break;
4366 else if (time_after_eq(jiffies, w_time)) {
4367 /* capturing dump failed */
4368 ql_dbg(ql_dbg_p3p, vha, 0xb032,
4369 "c_value_r: 0x%x, poll_mask: 0x%lx, "
4370 "w_time: 0x%lx\n",
4371 c_value_r, p_mask, w_time);
4372 return rval;
4373 }
4374 } while (1);
4375 }
4376
4377 addr = r_addr;
4378 for (k = 0; k < r_cnt; k++) {
4379 r_value = qla82xx_md_rw_32(ha, addr, 0, 0);
4380 *data_ptr++ = cpu_to_le32(r_value);
4381 addr += cache_hdr->read_ctrl.read_addr_stride;
4382 }
4383 t_value += cache_hdr->addr_ctrl.tag_value_stride;
4384 }
4385 *d_ptr = data_ptr;
4386 return QLA_SUCCESS;
4387}
4388
4389static void
4390qla82xx_minidump_process_l1cache(scsi_qla_host_t *vha,
4391 qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
4392{
4393 struct qla_hw_data *ha = vha->hw;
4394 uint32_t addr, r_addr, c_addr, t_r_addr;
4395 uint32_t i, k, loop_count, t_value, r_cnt, r_value;
4396 uint32_t c_value_w;
4397 struct qla82xx_md_entry_cache *cache_hdr;
4398 uint32_t *data_ptr = *d_ptr;
4399
4400 cache_hdr = (struct qla82xx_md_entry_cache *)entry_hdr;
4401 loop_count = cache_hdr->op_count;
4402 r_addr = cache_hdr->read_addr;
4403 c_addr = cache_hdr->control_addr;
4404 c_value_w = cache_hdr->cache_ctrl.write_value;
4405
4406 t_r_addr = cache_hdr->tag_reg_addr;
4407 t_value = cache_hdr->addr_ctrl.init_tag_value;
4408 r_cnt = cache_hdr->read_ctrl.read_addr_cnt;
4409
4410 for (i = 0; i < loop_count; i++) {
4411 qla82xx_md_rw_32(ha, t_r_addr, t_value, 1);
4412 qla82xx_md_rw_32(ha, c_addr, c_value_w, 1);
4413 addr = r_addr;
4414 for (k = 0; k < r_cnt; k++) {
4415 r_value = qla82xx_md_rw_32(ha, addr, 0, 0);
4416 *data_ptr++ = cpu_to_le32(r_value);
4417 addr += cache_hdr->read_ctrl.read_addr_stride;
4418 }
4419 t_value += cache_hdr->addr_ctrl.tag_value_stride;
4420 }
4421 *d_ptr = data_ptr;
4422}
4423
4424static void
4425qla82xx_minidump_process_queue(scsi_qla_host_t *vha,
4426 qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
4427{
4428 struct qla_hw_data *ha = vha->hw;
4429 uint32_t s_addr, r_addr;
4430 uint32_t r_stride, r_value, r_cnt, qid = 0;
4431 uint32_t i, k, loop_cnt;
4432 struct qla82xx_md_entry_queue *q_hdr;
4433 uint32_t *data_ptr = *d_ptr;
4434
4435 q_hdr = (struct qla82xx_md_entry_queue *)entry_hdr;
4436 s_addr = q_hdr->select_addr;
4437 r_cnt = q_hdr->rd_strd.read_addr_cnt;
4438 r_stride = q_hdr->rd_strd.read_addr_stride;
4439 loop_cnt = q_hdr->op_count;
4440
4441 for (i = 0; i < loop_cnt; i++) {
4442 qla82xx_md_rw_32(ha, s_addr, qid, 1);
4443 r_addr = q_hdr->read_addr;
4444 for (k = 0; k < r_cnt; k++) {
4445 r_value = qla82xx_md_rw_32(ha, r_addr, 0, 0);
4446 *data_ptr++ = cpu_to_le32(r_value);
4447 r_addr += r_stride;
4448 }
4449 qid += q_hdr->q_strd.queue_id_stride;
4450 }
4451 *d_ptr = data_ptr;
4452}
4453
4454static void
4455qla82xx_minidump_process_rdrom(scsi_qla_host_t *vha,
4456 qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
4457{
4458 struct qla_hw_data *ha = vha->hw;
4459 uint32_t r_addr, r_value;
4460 uint32_t i, loop_cnt;
4461 struct qla82xx_md_entry_rdrom *rom_hdr;
4462 uint32_t *data_ptr = *d_ptr;
4463
4464 rom_hdr = (struct qla82xx_md_entry_rdrom *)entry_hdr;
4465 r_addr = rom_hdr->read_addr;
4466 loop_cnt = rom_hdr->read_data_size/sizeof(uint32_t);
4467
4468 for (i = 0; i < loop_cnt; i++) {
4469 qla82xx_md_rw_32(ha, MD_DIRECT_ROM_WINDOW,
4470 (r_addr & 0xFFFF0000), 1);
4471 r_value = qla82xx_md_rw_32(ha,
4472 MD_DIRECT_ROM_READ_BASE +
4473 (r_addr & 0x0000FFFF), 0, 0);
4474 *data_ptr++ = cpu_to_le32(r_value);
4475 r_addr += sizeof(uint32_t);
4476 }
4477 *d_ptr = data_ptr;
4478}
4479
4480static int
4481qla82xx_minidump_process_rdmem(scsi_qla_host_t *vha,
4482 qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
4483{
4484 struct qla_hw_data *ha = vha->hw;
4485 uint32_t r_addr, r_value, r_data;
4486 uint32_t i, j, loop_cnt;
4487 struct qla82xx_md_entry_rdmem *m_hdr;
4488 unsigned long flags;
4489 int rval = QLA_FUNCTION_FAILED;
4490 uint32_t *data_ptr = *d_ptr;
4491
4492 m_hdr = (struct qla82xx_md_entry_rdmem *)entry_hdr;
4493 r_addr = m_hdr->read_addr;
4494 loop_cnt = m_hdr->read_data_size/16;
4495
4496 if (r_addr & 0xf) {
4497 ql_log(ql_log_warn, vha, 0xb033,
4498 "Read addr 0x%x not 16 bytes alligned\n", r_addr);
4499 return rval;
4500 }
4501
4502 if (m_hdr->read_data_size % 16) {
4503 ql_log(ql_log_warn, vha, 0xb034,
4504 "Read data[0x%x] not multiple of 16 bytes\n",
4505 m_hdr->read_data_size);
4506 return rval;
4507 }
4508
4509 ql_dbg(ql_dbg_p3p, vha, 0xb035,
4510 "[%s]: rdmem_addr: 0x%x, read_data_size: 0x%x, loop_cnt: 0x%x\n",
4511 __func__, r_addr, m_hdr->read_data_size, loop_cnt);
4512
4513 write_lock_irqsave(&ha->hw_lock, flags);
4514 for (i = 0; i < loop_cnt; i++) {
4515 qla82xx_md_rw_32(ha, MD_MIU_TEST_AGT_ADDR_LO, r_addr, 1);
4516 r_value = 0;
4517 qla82xx_md_rw_32(ha, MD_MIU_TEST_AGT_ADDR_HI, r_value, 1);
4518 r_value = MIU_TA_CTL_ENABLE;
4519 qla82xx_md_rw_32(ha, MD_MIU_TEST_AGT_CTRL, r_value, 1);
4520 r_value = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE;
4521 qla82xx_md_rw_32(ha, MD_MIU_TEST_AGT_CTRL, r_value, 1);
4522
4523 for (j = 0; j < MAX_CTL_CHECK; j++) {
4524 r_value = qla82xx_md_rw_32(ha,
4525 MD_MIU_TEST_AGT_CTRL, 0, 0);
4526 if ((r_value & MIU_TA_CTL_BUSY) == 0)
4527 break;
4528 }
4529
4530 if (j >= MAX_CTL_CHECK) {
4531 printk_ratelimited(KERN_ERR
4532 "failed to read through agent\n");
4533 write_unlock_irqrestore(&ha->hw_lock, flags);
4534 return rval;
4535 }
4536
4537 for (j = 0; j < 4; j++) {
4538 r_data = qla82xx_md_rw_32(ha,
4539 MD_MIU_TEST_AGT_RDDATA[j], 0, 0);
4540 *data_ptr++ = cpu_to_le32(r_data);
4541 }
4542 r_addr += 16;
4543 }
4544 write_unlock_irqrestore(&ha->hw_lock, flags);
4545 *d_ptr = data_ptr;
4546 return QLA_SUCCESS;
4547}
4548
4549static int
4550qla82xx_validate_template_chksum(scsi_qla_host_t *vha)
4551{
4552 struct qla_hw_data *ha = vha->hw;
4553 uint64_t chksum = 0;
4554 uint32_t *d_ptr = (uint32_t *)ha->md_tmplt_hdr;
4555 int count = ha->md_template_size/sizeof(uint32_t);
4556
4557 while (count-- > 0)
4558 chksum += *d_ptr++;
4559 while (chksum >> 32)
4560 chksum = (chksum & 0xFFFFFFFF) + (chksum >> 32);
4561 return ~chksum;
4562}
4563
4564static void
4565qla82xx_mark_entry_skipped(scsi_qla_host_t *vha,
4566 qla82xx_md_entry_hdr_t *entry_hdr, int index)
4567{
4568 entry_hdr->d_ctrl.driver_flags |= QLA82XX_DBG_SKIPPED_FLAG;
4569 ql_dbg(ql_dbg_p3p, vha, 0xb036,
4570 "Skipping entry[%d]: "
4571 "ETYPE[0x%x]-ELEVEL[0x%x]\n",
4572 index, entry_hdr->entry_type,
4573 entry_hdr->d_ctrl.entry_capture_mask);
4574}
4575
4576int
4577qla82xx_md_collect(scsi_qla_host_t *vha)
4578{
4579 struct qla_hw_data *ha = vha->hw;
4580 int no_entry_hdr = 0;
4581 qla82xx_md_entry_hdr_t *entry_hdr;
4582 struct qla82xx_md_template_hdr *tmplt_hdr;
4583 uint32_t *data_ptr;
4584 uint32_t total_data_size = 0, f_capture_mask, data_collected = 0;
4585 int i = 0, rval = QLA_FUNCTION_FAILED;
4586
4587 tmplt_hdr = (struct qla82xx_md_template_hdr *)ha->md_tmplt_hdr;
4588 data_ptr = (uint32_t *)ha->md_dump;
4589
4590 if (ha->fw_dumped) {
4591 ql_log(ql_log_info, vha, 0xb037,
4592 "Firmware dump available to retrive\n");
4593 goto md_failed;
4594 }
4595
4596 ha->fw_dumped = 0;
4597
4598 if (!ha->md_tmplt_hdr || !ha->md_dump) {
4599 ql_log(ql_log_warn, vha, 0xb038,
4600 "Memory not allocated for minidump capture\n");
4601 goto md_failed;
4602 }
4603
4604 if (qla82xx_validate_template_chksum(vha)) {
4605 ql_log(ql_log_info, vha, 0xb039,
4606 "Template checksum validation error\n");
4607 goto md_failed;
4608 }
4609
4610 no_entry_hdr = tmplt_hdr->num_of_entries;
4611 ql_dbg(ql_dbg_p3p, vha, 0xb03a,
4612 "No of entry headers in Template: 0x%x\n", no_entry_hdr);
4613
4614 ql_dbg(ql_dbg_p3p, vha, 0xb03b,
4615 "Capture Mask obtained: 0x%x\n", tmplt_hdr->capture_debug_level);
4616
4617 f_capture_mask = tmplt_hdr->capture_debug_level & 0xFF;
4618
4619 /* Validate whether required debug level is set */
4620 if ((f_capture_mask & 0x3) != 0x3) {
4621 ql_log(ql_log_warn, vha, 0xb03c,
4622 "Minimum required capture mask[0x%x] level not set\n",
4623 f_capture_mask);
4624 goto md_failed;
4625 }
4626 tmplt_hdr->driver_capture_mask = ql2xmdcapmask;
4627
4628 tmplt_hdr->driver_info[0] = vha->host_no;
4629 tmplt_hdr->driver_info[1] = (QLA_DRIVER_MAJOR_VER << 24) |
4630 (QLA_DRIVER_MINOR_VER << 16) | (QLA_DRIVER_PATCH_VER << 8) |
4631 QLA_DRIVER_BETA_VER;
4632
4633 total_data_size = ha->md_dump_size;
4634
4635 ql_dbg(ql_log_info, vha, 0xb03d,
4636 "Total minidump data_size 0x%x to be captured\n", total_data_size);
4637
4638 /* Check whether template obtained is valid */
4639 if (tmplt_hdr->entry_type != QLA82XX_TLHDR) {
4640 ql_log(ql_log_warn, vha, 0xb04e,
4641 "Bad template header entry type: 0x%x obtained\n",
4642 tmplt_hdr->entry_type);
4643 goto md_failed;
4644 }
4645
4646 entry_hdr = (qla82xx_md_entry_hdr_t *) \
4647 (((uint8_t *)ha->md_tmplt_hdr) + tmplt_hdr->first_entry_offset);
4648
4649 /* Walk through the entry headers */
4650 for (i = 0; i < no_entry_hdr; i++) {
4651
4652 if (data_collected > total_data_size) {
4653 ql_log(ql_log_warn, vha, 0xb03e,
4654 "More MiniDump data collected: [0x%x]\n",
4655 data_collected);
4656 goto md_failed;
4657 }
4658
4659 if (!(entry_hdr->d_ctrl.entry_capture_mask &
4660 ql2xmdcapmask)) {
4661 entry_hdr->d_ctrl.driver_flags |=
4662 QLA82XX_DBG_SKIPPED_FLAG;
4663 ql_dbg(ql_dbg_p3p, vha, 0xb03f,
4664 "Skipping entry[%d]: "
4665 "ETYPE[0x%x]-ELEVEL[0x%x]\n",
4666 i, entry_hdr->entry_type,
4667 entry_hdr->d_ctrl.entry_capture_mask);
4668 goto skip_nxt_entry;
4669 }
4670
4671 ql_dbg(ql_dbg_p3p, vha, 0xb040,
4672 "[%s]: data ptr[%d]: %p, entry_hdr: %p\n"
4673 "entry_type: 0x%x, captrue_mask: 0x%x\n",
4674 __func__, i, data_ptr, entry_hdr,
4675 entry_hdr->entry_type,
4676 entry_hdr->d_ctrl.entry_capture_mask);
4677
4678 ql_dbg(ql_dbg_p3p, vha, 0xb041,
4679 "Data collected: [0x%x], Dump size left:[0x%x]\n",
4680 data_collected, (ha->md_dump_size - data_collected));
4681
4682 /* Decode the entry type and take
4683 * required action to capture debug data */
4684 switch (entry_hdr->entry_type) {
4685 case QLA82XX_RDEND:
4686 qla82xx_mark_entry_skipped(vha, entry_hdr, i);
4687 break;
4688 case QLA82XX_CNTRL:
4689 rval = qla82xx_minidump_process_control(vha,
4690 entry_hdr, &data_ptr);
4691 if (rval != QLA_SUCCESS) {
4692 qla82xx_mark_entry_skipped(vha, entry_hdr, i);
4693 goto md_failed;
4694 }
4695 break;
4696 case QLA82XX_RDCRB:
4697 qla82xx_minidump_process_rdcrb(vha,
4698 entry_hdr, &data_ptr);
4699 break;
4700 case QLA82XX_RDMEM:
4701 rval = qla82xx_minidump_process_rdmem(vha,
4702 entry_hdr, &data_ptr);
4703 if (rval != QLA_SUCCESS) {
4704 qla82xx_mark_entry_skipped(vha, entry_hdr, i);
4705 goto md_failed;
4706 }
4707 break;
4708 case QLA82XX_BOARD:
4709 case QLA82XX_RDROM:
4710 qla82xx_minidump_process_rdrom(vha,
4711 entry_hdr, &data_ptr);
4712 break;
4713 case QLA82XX_L2DTG:
4714 case QLA82XX_L2ITG:
4715 case QLA82XX_L2DAT:
4716 case QLA82XX_L2INS:
4717 rval = qla82xx_minidump_process_l2tag(vha,
4718 entry_hdr, &data_ptr);
4719 if (rval != QLA_SUCCESS) {
4720 qla82xx_mark_entry_skipped(vha, entry_hdr, i);
4721 goto md_failed;
4722 }
4723 break;
4724 case QLA82XX_L1DAT:
4725 case QLA82XX_L1INS:
4726 qla82xx_minidump_process_l1cache(vha,
4727 entry_hdr, &data_ptr);
4728 break;
4729 case QLA82XX_RDOCM:
4730 qla82xx_minidump_process_rdocm(vha,
4731 entry_hdr, &data_ptr);
4732 break;
4733 case QLA82XX_RDMUX:
4734 qla82xx_minidump_process_rdmux(vha,
4735 entry_hdr, &data_ptr);
4736 break;
4737 case QLA82XX_QUEUE:
4738 qla82xx_minidump_process_queue(vha,
4739 entry_hdr, &data_ptr);
4740 break;
4741 case QLA82XX_RDNOP:
4742 default:
4743 qla82xx_mark_entry_skipped(vha, entry_hdr, i);
4744 break;
4745 }
4746
4747 ql_dbg(ql_dbg_p3p, vha, 0xb042,
4748 "[%s]: data ptr[%d]: %p\n", __func__, i, data_ptr);
4749
4750 data_collected = (uint8_t *)data_ptr -
4751 (uint8_t *)ha->md_dump;
4752skip_nxt_entry:
4753 entry_hdr = (qla82xx_md_entry_hdr_t *) \
4754 (((uint8_t *)entry_hdr) + entry_hdr->entry_size);
4755 }
4756
4757 if (data_collected != total_data_size) {
4758 ql_dbg(ql_log_warn, vha, 0xb043,
4759 "MiniDump data mismatch: Data collected: [0x%x],"
4760 "total_data_size:[0x%x]\n",
4761 data_collected, total_data_size);
4762 goto md_failed;
4763 }
4764
4765 ql_log(ql_log_info, vha, 0xb044,
4766 "Firmware dump saved to temp buffer (%ld/%p %ld/%p).\n",
4767 vha->host_no, ha->md_tmplt_hdr, vha->host_no, ha->md_dump);
4768 ha->fw_dumped = 1;
4769 qla2x00_post_uevent_work(vha, QLA_UEVENT_CODE_FW_DUMP);
4770
4771md_failed:
4772 return rval;
4773}
4774
4775int
4776qla82xx_md_alloc(scsi_qla_host_t *vha)
4777{
4778 struct qla_hw_data *ha = vha->hw;
4779 int i, k;
4780 struct qla82xx_md_template_hdr *tmplt_hdr;
4781
4782 tmplt_hdr = (struct qla82xx_md_template_hdr *)ha->md_tmplt_hdr;
4783
4784 if (ql2xmdcapmask < 0x3 || ql2xmdcapmask > 0x7F) {
4785 ql2xmdcapmask = tmplt_hdr->capture_debug_level & 0xFF;
4786 ql_log(ql_log_info, vha, 0xb045,
4787 "Forcing driver capture mask to firmware default capture mask: 0x%x.\n",
4788 ql2xmdcapmask);
4789 }
4790
4791 for (i = 0x2, k = 1; (i & QLA82XX_DEFAULT_CAP_MASK); i <<= 1, k++) {
4792 if (i & ql2xmdcapmask)
4793 ha->md_dump_size += tmplt_hdr->capture_size_array[k];
4794 }
4795
4796 if (ha->md_dump) {
4797 ql_log(ql_log_warn, vha, 0xb046,
4798 "Firmware dump previously allocated.\n");
4799 return 1;
4800 }
4801
4802 ha->md_dump = vmalloc(ha->md_dump_size);
4803 if (ha->md_dump == NULL) {
4804 ql_log(ql_log_warn, vha, 0xb047,
4805 "Unable to allocate memory for Minidump size "
4806 "(0x%x).\n", ha->md_dump_size);
4807 return 1;
4808 }
4809 return 0;
4810}
4811
4812void
4813qla82xx_md_free(scsi_qla_host_t *vha)
4814{
4815 struct qla_hw_data *ha = vha->hw;
4816
4817 /* Release the template header allocated */
4818 if (ha->md_tmplt_hdr) {
4819 ql_log(ql_log_info, vha, 0xb048,
4820 "Free MiniDump template: %p, size (%d KB)\n",
4821 ha->md_tmplt_hdr, ha->md_template_size / 1024);
4822 dma_free_coherent(&ha->pdev->dev, ha->md_template_size,
4823 ha->md_tmplt_hdr, ha->md_tmplt_hdr_dma);
4824 ha->md_tmplt_hdr = 0;
4825 }
4826
4827 /* Release the template data buffer allocated */
4828 if (ha->md_dump) {
4829 ql_log(ql_log_info, vha, 0xb049,
4830 "Free MiniDump memory: %p, size (%d KB)\n",
4831 ha->md_dump, ha->md_dump_size / 1024);
4832 vfree(ha->md_dump);
4833 ha->md_dump_size = 0;
4834 ha->md_dump = 0;
4835 }
4836}
4837
4838void
4839qla82xx_md_prep(scsi_qla_host_t *vha)
4840{
4841 struct qla_hw_data *ha = vha->hw;
4842 int rval;
4843
4844 /* Get Minidump template size */
4845 rval = qla82xx_md_get_template_size(vha);
4846 if (rval == QLA_SUCCESS) {
4847 ql_log(ql_log_info, vha, 0xb04a,
4848 "MiniDump Template size obtained (%d KB)\n",
4849 ha->md_template_size / 1024);
4850
4851 /* Get Minidump template */
4852 rval = qla82xx_md_get_template(vha);
4853 if (rval == QLA_SUCCESS) {
4854 ql_dbg(ql_dbg_p3p, vha, 0xb04b,
4855 "MiniDump Template obtained\n");
4856
4857 /* Allocate memory for minidump */
4858 rval = qla82xx_md_alloc(vha);
4859 if (rval == QLA_SUCCESS)
4860 ql_log(ql_log_info, vha, 0xb04c,
4861 "MiniDump memory allocated (%d KB)\n",
4862 ha->md_dump_size / 1024);
4863 else {
4864 ql_log(ql_log_info, vha, 0xb04d,
4865 "Free MiniDump template: %p, size: (%d KB)\n",
4866 ha->md_tmplt_hdr,
4867 ha->md_template_size / 1024);
4868 dma_free_coherent(&ha->pdev->dev,
4869 ha->md_template_size,
4870 ha->md_tmplt_hdr, ha->md_tmplt_hdr_dma);
4871 ha->md_tmplt_hdr = 0;
4872 }
4873
4874 }
4875 }
4876}