[SCSI] qla4xxx: Added support for ISP83XX
Signed-off-by: Poornima Vonti <poornima.vonti@qlogic.com> Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com> Reviewed-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
This commit is contained in:
parent
aec07caedb
commit
6e7b429259
|
@ -4,5 +4,5 @@ config SCSI_QLA_ISCSI
|
|||
select SCSI_ISCSI_ATTRS
|
||||
select ISCSI_BOOT_SYSFS
|
||||
---help---
|
||||
This driver supports the QLogic 40xx (ISP4XXX) and 8022 (ISP82XX)
|
||||
iSCSI host adapter family.
|
||||
This driver supports the QLogic 40xx (ISP4XXX), 8022 (ISP82XX)
|
||||
and 8032 (ISP83XX) iSCSI host adapter family.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
qla4xxx-y := ql4_os.o ql4_init.o ql4_mbx.o ql4_iocb.o ql4_isr.o \
|
||||
ql4_nx.o ql4_nvram.o ql4_dbg.o ql4_attr.o ql4_bsg.o
|
||||
ql4_nx.o ql4_nvram.o ql4_dbg.o ql4_attr.o ql4_bsg.o ql4_83xx.o
|
||||
|
||||
obj-$(CONFIG_SCSI_QLA_ISCSI) += qla4xxx.o
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
* QLogic iSCSI HBA Driver
|
||||
* Copyright (c) 2003-2012 QLogic Corporation
|
||||
*
|
||||
* See LICENSE.qla4xxx for copyright and licensing details.
|
||||
*/
|
||||
|
||||
#ifndef __QL483XX_H
|
||||
#define __QL483XX_H
|
||||
|
||||
/* Indirectly Mapped Registers */
|
||||
#define QLA83XX_FLASH_SPI_STATUS 0x2808E010
|
||||
#define QLA83XX_FLASH_SPI_CONTROL 0x2808E014
|
||||
#define QLA83XX_FLASH_STATUS 0x42100004
|
||||
#define QLA83XX_FLASH_CONTROL 0x42110004
|
||||
#define QLA83XX_FLASH_ADDR 0x42110008
|
||||
#define QLA83XX_FLASH_WRDATA 0x4211000C
|
||||
#define QLA83XX_FLASH_RDDATA 0x42110018
|
||||
#define QLA83XX_FLASH_DIRECT_WINDOW 0x42110030
|
||||
#define QLA83XX_FLASH_DIRECT_DATA(DATA) (0x42150000 | (0x0000FFFF&DATA))
|
||||
|
||||
/* Directly Mapped Registers in 83xx register table */
|
||||
|
||||
/* Flash access regs */
|
||||
#define QLA83XX_FLASH_LOCK 0x3850
|
||||
#define QLA83XX_FLASH_UNLOCK 0x3854
|
||||
#define QLA83XX_FLASH_LOCK_ID 0x3500
|
||||
|
||||
/* Driver Lock regs */
|
||||
#define QLA83XX_DRV_LOCK 0x3868
|
||||
#define QLA83XX_DRV_UNLOCK 0x386C
|
||||
#define QLA83XX_DRV_LOCK_ID 0x3504
|
||||
#define QLA83XX_DRV_LOCKRECOVERY 0x379C
|
||||
|
||||
/* IDC version */
|
||||
#define QLA83XX_IDC_VER_MAJ_VALUE 0x1
|
||||
#define QLA83XX_IDC_VER_MIN_VALUE 0x0
|
||||
|
||||
/* IDC Registers : Driver Coexistence Defines */
|
||||
#define QLA83XX_CRB_IDC_VER_MAJOR 0x3780
|
||||
#define QLA83XX_CRB_IDC_VER_MINOR 0x3798
|
||||
#define QLA83XX_IDC_DRV_CTRL 0x3790
|
||||
#define QLA83XX_IDC_DRV_AUDIT 0x3794
|
||||
|
||||
/* qla_83xx_reg_tbl registers */
|
||||
#define QLA83XX_PEG_HALT_STATUS1 0x34A8
|
||||
#define QLA83XX_PEG_HALT_STATUS2 0x34AC
|
||||
#define QLA83XX_PEG_ALIVE_COUNTER 0x34B0 /* FW_HEARTBEAT */
|
||||
#define QLA83XX_FW_CAPABILITIES 0x3528
|
||||
#define QLA83XX_CRB_DRV_ACTIVE 0x3788 /* IDC_DRV_PRESENCE */
|
||||
#define QLA83XX_CRB_DEV_STATE 0x3784 /* IDC_DEV_STATE */
|
||||
#define QLA83XX_CRB_DRV_STATE 0x378C /* IDC_DRV_ACK */
|
||||
#define QLA83XX_CRB_DRV_SCRATCH 0x3548
|
||||
#define QLA83XX_CRB_DEV_PART_INFO1 0x37E0
|
||||
#define QLA83XX_CRB_DEV_PART_INFO2 0x37E4
|
||||
|
||||
#define QLA83XX_FW_VER_MAJOR 0x3550
|
||||
#define QLA83XX_FW_VER_MINOR 0x3554
|
||||
#define QLA83XX_FW_VER_SUB 0x3558
|
||||
#define QLA83XX_NPAR_STATE 0x359C
|
||||
#define QLA83XX_FW_IMAGE_VALID 0x35FC
|
||||
#define QLA83XX_CMDPEG_STATE 0x3650
|
||||
#define QLA83XX_ASIC_TEMP 0x37B4
|
||||
#define QLA83XX_FW_API 0x356C
|
||||
#define QLA83XX_DRV_OP_MODE 0x3570
|
||||
|
||||
static const uint32_t qla4_83xx_reg_tbl[] = {
|
||||
QLA83XX_PEG_HALT_STATUS1,
|
||||
QLA83XX_PEG_HALT_STATUS2,
|
||||
QLA83XX_PEG_ALIVE_COUNTER,
|
||||
QLA83XX_CRB_DRV_ACTIVE,
|
||||
QLA83XX_CRB_DEV_STATE,
|
||||
QLA83XX_CRB_DRV_STATE,
|
||||
QLA83XX_CRB_DRV_SCRATCH,
|
||||
QLA83XX_CRB_DEV_PART_INFO1,
|
||||
QLA83XX_CRB_IDC_VER_MAJOR,
|
||||
QLA83XX_FW_VER_MAJOR,
|
||||
QLA83XX_FW_VER_MINOR,
|
||||
QLA83XX_FW_VER_SUB,
|
||||
QLA83XX_CMDPEG_STATE,
|
||||
QLA83XX_ASIC_TEMP,
|
||||
};
|
||||
|
||||
#define QLA83XX_CRB_WIN_BASE 0x3800
|
||||
#define QLA83XX_CRB_WIN_FUNC(f) (QLA83XX_CRB_WIN_BASE+((f)*4))
|
||||
#define QLA83XX_SEM_LOCK_BASE 0x3840
|
||||
#define QLA83XX_SEM_UNLOCK_BASE 0x3844
|
||||
#define QLA83XX_SEM_LOCK_FUNC(f) (QLA83XX_SEM_LOCK_BASE+((f)*8))
|
||||
#define QLA83XX_SEM_UNLOCK_FUNC(f) (QLA83XX_SEM_UNLOCK_BASE+((f)*8))
|
||||
#define QLA83XX_LINK_STATE(f) (0x3698+((f) > 7 ? 4 : 0))
|
||||
#define QLA83XX_LINK_SPEED(f) (0x36E0+(((f) >> 2) * 4))
|
||||
#define QLA83XX_MAX_LINK_SPEED(f) (0x36F0+(((f) / 4) * 4))
|
||||
#define QLA83XX_LINK_SPEED_FACTOR 10
|
||||
|
||||
/* FLASH API Defines */
|
||||
#define QLA83xx_FLASH_MAX_WAIT_USEC 100
|
||||
#define QLA83XX_FLASH_LOCK_TIMEOUT 10000
|
||||
#define QLA83XX_FLASH_SECTOR_SIZE 65536
|
||||
#define QLA83XX_DRV_LOCK_TIMEOUT 2000
|
||||
#define QLA83XX_FLASH_SECTOR_ERASE_CMD 0xdeadbeef
|
||||
#define QLA83XX_FLASH_WRITE_CMD 0xdacdacda
|
||||
#define QLA83XX_FLASH_BUFFER_WRITE_CMD 0xcadcadca
|
||||
#define QLA83XX_FLASH_READ_RETRY_COUNT 2000
|
||||
#define QLA83XX_FLASH_STATUS_READY 0x6
|
||||
#define QLA83XX_FLASH_BUFFER_WRITE_MIN 2
|
||||
#define QLA83XX_FLASH_BUFFER_WRITE_MAX 64
|
||||
#define QLA83XX_FLASH_STATUS_REG_POLL_DELAY 1
|
||||
#define QLA83XX_ERASE_MODE 1
|
||||
#define QLA83XX_WRITE_MODE 2
|
||||
#define QLA83XX_DWORD_WRITE_MODE 3
|
||||
|
||||
#define QLA83XX_GLOBAL_RESET 0x38CC
|
||||
#define QLA83XX_WILDCARD 0x38F0
|
||||
#define QLA83XX_INFORMANT 0x38FC
|
||||
#define QLA83XX_HOST_MBX_CTRL 0x3038
|
||||
#define QLA83XX_FW_MBX_CTRL 0x303C
|
||||
#define QLA83XX_BOOTLOADER_ADDR 0x355C
|
||||
#define QLA83XX_BOOTLOADER_SIZE 0x3560
|
||||
#define QLA83XX_FW_IMAGE_ADDR 0x3564
|
||||
#define QLA83XX_MBX_INTR_ENABLE 0x1000
|
||||
#define QLA83XX_MBX_INTR_MASK 0x1200
|
||||
|
||||
/* IDC Control Register bit defines */
|
||||
#define DONTRESET_BIT0 0x1
|
||||
#define GRACEFUL_RESET_BIT1 0x2
|
||||
|
||||
#define QLA83XX_HALT_STATUS_INFORMATIONAL (0x1 << 29)
|
||||
#define QLA83XX_HALT_STATUS_FW_RESET (0x2 << 29)
|
||||
#define QLA83XX_HALT_STATUS_UNRECOVERABLE (0x4 << 29)
|
||||
|
||||
/* Firmware image definitions */
|
||||
#define QLA83XX_BOOTLOADER_FLASH_ADDR 0x10000
|
||||
#define QLA83XX_BOOT_FROM_FLASH 0
|
||||
|
||||
#define QLA83XX_IDC_PARAM_ADDR 0x3e8020
|
||||
/* Reset template definitions */
|
||||
#define QLA83XX_MAX_RESET_SEQ_ENTRIES 16
|
||||
#define QLA83XX_RESTART_TEMPLATE_SIZE 0x2000
|
||||
#define QLA83XX_RESET_TEMPLATE_ADDR 0x4F0000
|
||||
#define QLA83XX_RESET_SEQ_VERSION 0x0101
|
||||
|
||||
/* Reset template entry opcodes */
|
||||
#define OPCODE_NOP 0x0000
|
||||
#define OPCODE_WRITE_LIST 0x0001
|
||||
#define OPCODE_READ_WRITE_LIST 0x0002
|
||||
#define OPCODE_POLL_LIST 0x0004
|
||||
#define OPCODE_POLL_WRITE_LIST 0x0008
|
||||
#define OPCODE_READ_MODIFY_WRITE 0x0010
|
||||
#define OPCODE_SEQ_PAUSE 0x0020
|
||||
#define OPCODE_SEQ_END 0x0040
|
||||
#define OPCODE_TMPL_END 0x0080
|
||||
#define OPCODE_POLL_READ_LIST 0x0100
|
||||
|
||||
/* Template Header */
|
||||
#define RESET_TMPLT_HDR_SIGNATURE 0xCAFE
|
||||
struct qla4_83xx_reset_template_hdr {
|
||||
__le16 version;
|
||||
__le16 signature;
|
||||
__le16 size;
|
||||
__le16 entries;
|
||||
__le16 hdr_size;
|
||||
__le16 checksum;
|
||||
__le16 init_seq_offset;
|
||||
__le16 start_seq_offset;
|
||||
} __packed;
|
||||
|
||||
/* Common Entry Header. */
|
||||
struct qla4_83xx_reset_entry_hdr {
|
||||
__le16 cmd;
|
||||
__le16 size;
|
||||
__le16 count;
|
||||
__le16 delay;
|
||||
} __packed;
|
||||
|
||||
/* Generic poll entry type. */
|
||||
struct qla4_83xx_poll {
|
||||
__le32 test_mask;
|
||||
__le32 test_value;
|
||||
} __packed;
|
||||
|
||||
/* Read modify write entry type. */
|
||||
struct qla4_83xx_rmw {
|
||||
__le32 test_mask;
|
||||
__le32 xor_value;
|
||||
__le32 or_value;
|
||||
uint8_t shl;
|
||||
uint8_t shr;
|
||||
uint8_t index_a;
|
||||
uint8_t rsvd;
|
||||
} __packed;
|
||||
|
||||
/* Generic Entry Item with 2 DWords. */
|
||||
struct qla4_83xx_entry {
|
||||
__le32 arg1;
|
||||
__le32 arg2;
|
||||
} __packed;
|
||||
|
||||
/* Generic Entry Item with 4 DWords.*/
|
||||
struct qla4_83xx_quad_entry {
|
||||
__le32 dr_addr;
|
||||
__le32 dr_value;
|
||||
__le32 ar_addr;
|
||||
__le32 ar_value;
|
||||
} __packed;
|
||||
|
||||
struct qla4_83xx_reset_template {
|
||||
int seq_index;
|
||||
int seq_error;
|
||||
int array_index;
|
||||
uint32_t array[QLA83XX_MAX_RESET_SEQ_ENTRIES];
|
||||
uint8_t *buff;
|
||||
uint8_t *stop_offset;
|
||||
uint8_t *start_offset;
|
||||
uint8_t *init_offset;
|
||||
struct qla4_83xx_reset_template_hdr *hdr;
|
||||
uint8_t seq_end;
|
||||
uint8_t template_end;
|
||||
};
|
||||
|
||||
/* POLLRD Entry */
|
||||
struct qla83xx_minidump_entry_pollrd {
|
||||
struct qla8xxx_minidump_entry_hdr h;
|
||||
uint32_t select_addr;
|
||||
uint32_t read_addr;
|
||||
uint32_t select_value;
|
||||
uint16_t select_value_stride;
|
||||
uint16_t op_count;
|
||||
uint32_t poll_wait;
|
||||
uint32_t poll_mask;
|
||||
uint32_t data_size;
|
||||
uint32_t rsvd_1;
|
||||
};
|
||||
|
||||
/* RDMUX2 Entry */
|
||||
struct qla83xx_minidump_entry_rdmux2 {
|
||||
struct qla8xxx_minidump_entry_hdr h;
|
||||
uint32_t select_addr_1;
|
||||
uint32_t select_addr_2;
|
||||
uint32_t select_value_1;
|
||||
uint32_t select_value_2;
|
||||
uint32_t op_count;
|
||||
uint32_t select_value_mask;
|
||||
uint32_t read_addr;
|
||||
uint8_t select_value_stride;
|
||||
uint8_t data_size;
|
||||
uint8_t rsvd[2];
|
||||
};
|
||||
|
||||
/* POLLRDMWR Entry */
|
||||
struct qla83xx_minidump_entry_pollrdmwr {
|
||||
struct qla8xxx_minidump_entry_hdr h;
|
||||
uint32_t addr_1;
|
||||
uint32_t addr_2;
|
||||
uint32_t value_1;
|
||||
uint32_t value_2;
|
||||
uint32_t poll_wait;
|
||||
uint32_t poll_mask;
|
||||
uint32_t modify_mask;
|
||||
uint32_t data_size;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -150,7 +150,7 @@ qla4xxx_fw_version_show(struct device *dev,
|
|||
{
|
||||
struct scsi_qla_host *ha = to_qla_host(class_to_shost(dev));
|
||||
|
||||
if (is_qla8022(ha))
|
||||
if (is_qla80XX(ha))
|
||||
return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d (%x)\n",
|
||||
ha->firmware_version[0],
|
||||
ha->firmware_version[1],
|
||||
|
|
|
@ -131,3 +131,31 @@ void qla4xxx_dump_registers(struct scsi_qla_host *ha)
|
|||
&ha->reg->ctrl_status);
|
||||
}
|
||||
}
|
||||
|
||||
void qla4_8xxx_dump_peg_reg(struct scsi_qla_host *ha)
|
||||
{
|
||||
uint32_t halt_status1, halt_status2;
|
||||
|
||||
halt_status1 = qla4_8xxx_rd_direct(ha, QLA8XXX_PEG_HALT_STATUS1);
|
||||
halt_status2 = qla4_8xxx_rd_direct(ha, QLA8XXX_PEG_HALT_STATUS2);
|
||||
|
||||
if (is_qla8022(ha)) {
|
||||
ql4_printk(KERN_INFO, ha,
|
||||
"scsi(%ld): %s, ISP8022 Dumping hw/fw registers:\n"
|
||||
" PEG_HALT_STATUS1: 0x%x, PEG_HALT_STATUS2: 0x%x,\n"
|
||||
" PEG_NET_0_PC: 0x%x, PEG_NET_1_PC: 0x%x,\n"
|
||||
" PEG_NET_2_PC: 0x%x, PEG_NET_3_PC: 0x%x,\n"
|
||||
" PEG_NET_4_PC: 0x%x\n", ha->host_no,
|
||||
__func__, halt_status1, halt_status2,
|
||||
qla4_82xx_rd_32(ha, QLA82XX_CRB_PEG_NET_0 + 0x3c),
|
||||
qla4_82xx_rd_32(ha, QLA82XX_CRB_PEG_NET_1 + 0x3c),
|
||||
qla4_82xx_rd_32(ha, QLA82XX_CRB_PEG_NET_2 + 0x3c),
|
||||
qla4_82xx_rd_32(ha, QLA82XX_CRB_PEG_NET_3 + 0x3c),
|
||||
qla4_82xx_rd_32(ha, QLA82XX_CRB_PEG_NET_4 + 0x3c));
|
||||
} else if (is_qla8032(ha)) {
|
||||
ql4_printk(KERN_INFO, ha,
|
||||
"scsi(%ld): %s, ISP8324 Dumping hw/fw registers:\n"
|
||||
" PEG_HALT_STATUS1: 0x%x, PEG_HALT_STATUS2: 0x%x,\n",
|
||||
ha->host_no, __func__, halt_status1, halt_status2);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "ql4_nx.h"
|
||||
#include "ql4_fw.h"
|
||||
#include "ql4_nvram.h"
|
||||
#include "ql4_83xx.h"
|
||||
|
||||
#ifndef PCI_DEVICE_ID_QLOGIC_ISP4010
|
||||
#define PCI_DEVICE_ID_QLOGIC_ISP4010 0x4010
|
||||
|
@ -59,6 +60,10 @@
|
|||
#define PCI_DEVICE_ID_QLOGIC_ISP8022 0x8022
|
||||
#endif
|
||||
|
||||
#ifndef PCI_DEVICE_ID_QLOGIC_ISP8324
|
||||
#define PCI_DEVICE_ID_QLOGIC_ISP8324 0x8032
|
||||
#endif
|
||||
|
||||
#define ISP4XXX_PCI_FN_1 0x1
|
||||
#define ISP4XXX_PCI_FN_2 0x3
|
||||
|
||||
|
@ -510,6 +515,7 @@ struct scsi_qla_host {
|
|||
#define AF_82XX_FW_DUMPED 24 /* 0x01000000 */
|
||||
#define AF_8XXX_RST_OWNER 25 /* 0x02000000 */
|
||||
#define AF_82XX_DUMP_READING 26 /* 0x04000000 */
|
||||
#define AF_83XX_NO_FW_DUMP 27 /* 0x08000000 */
|
||||
|
||||
unsigned long dpc_flags;
|
||||
|
||||
|
@ -746,6 +752,10 @@ struct scsi_qla_host {
|
|||
uint32_t mrb_index;
|
||||
|
||||
uint32_t *reg_tbl;
|
||||
struct qla4_83xx_reset_template reset_tmplt;
|
||||
struct device_reg_83xx __iomem *qla4_83xx_reg; /* Base I/O address
|
||||
for ISP8324 */
|
||||
uint32_t pf_bit;
|
||||
};
|
||||
|
||||
struct ql4_task_data {
|
||||
|
@ -808,13 +818,20 @@ static inline int is_qla8022(struct scsi_qla_host *ha)
|
|||
return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8022;
|
||||
}
|
||||
|
||||
/* Note: Currently AER/EEH is now supported only for 8022 cards
|
||||
* This function needs to be updated when AER/EEH is enabled
|
||||
* for other cards.
|
||||
*/
|
||||
static inline int is_qla8032(struct scsi_qla_host *ha)
|
||||
{
|
||||
return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8324;
|
||||
}
|
||||
|
||||
static inline int is_qla80XX(struct scsi_qla_host *ha)
|
||||
{
|
||||
return is_qla8022(ha) || is_qla8032(ha);
|
||||
}
|
||||
|
||||
static inline int is_aer_supported(struct scsi_qla_host *ha)
|
||||
{
|
||||
return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8022;
|
||||
return ((ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8022) ||
|
||||
(ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8324));
|
||||
}
|
||||
|
||||
static inline int adapter_up(struct scsi_qla_host *ha)
|
||||
|
|
|
@ -65,6 +65,40 @@ struct device_reg_82xx {
|
|||
#define ISRX_82XX_RISC_INT BIT_0 /* RISC interrupt. */
|
||||
};
|
||||
|
||||
/* ISP 83xx I/O Register Set structure */
|
||||
struct device_reg_83xx {
|
||||
__le32 mailbox_in[16]; /* 0x0000 */
|
||||
__le32 reserve1[496]; /* 0x0040 */
|
||||
__le32 mailbox_out[16]; /* 0x0800 */
|
||||
__le32 reserve2[496];
|
||||
__le32 mbox_int; /* 0x1000 */
|
||||
__le32 reserve3[63];
|
||||
__le32 req_q_out; /* 0x1100 */
|
||||
__le32 reserve4[63];
|
||||
|
||||
__le32 rsp_q_in; /* 0x1200 */
|
||||
__le32 reserve5[1919];
|
||||
|
||||
__le32 req_q_in; /* 0x3000 */
|
||||
__le32 reserve6[3];
|
||||
__le32 iocb_int_mask; /* 0x3010 */
|
||||
__le32 reserve7[3];
|
||||
__le32 rsp_q_out; /* 0x3020 */
|
||||
__le32 reserve8[3];
|
||||
__le32 anonymousbuff; /* 0x3030 */
|
||||
__le32 mb_int_mask; /* 0x3034 */
|
||||
|
||||
__le32 host_intr; /* 0x3038 - Host Interrupt Register */
|
||||
__le32 risc_intr; /* 0x303C - RISC Interrupt Register */
|
||||
__le32 reserve9[544];
|
||||
__le32 leg_int_ptr; /* 0x38C0 - Legacy Interrupt Pointer Register */
|
||||
__le32 leg_int_trig; /* 0x38C4 - Legacy Interrupt Trigger Control */
|
||||
__le32 leg_int_mask; /* 0x38C8 - Legacy Interrupt Mask Register */
|
||||
};
|
||||
|
||||
#define INT_ENABLE_FW_MB (1 << 2)
|
||||
#define INT_MASK_FW_MB (1 << 2)
|
||||
|
||||
/* remote register set (access via PCI memory read/write) */
|
||||
struct isp_reg {
|
||||
#define MBOX_REG_COUNT 8
|
||||
|
@ -1198,6 +1232,9 @@ struct ql_iscsi_stats {
|
|||
#define QLA8XXX_DBG_STATE_ARRAY_LEN 16
|
||||
#define QLA8XXX_DBG_CAP_SIZE_ARRAY_LEN 8
|
||||
#define QLA8XXX_DBG_RSVD_ARRAY_LEN 8
|
||||
#define QLA83XX_DBG_OCM_WNDREG_ARRAY_LEN 16
|
||||
#define QLA83XX_SS_OCM_WNDREG_INDEX 3
|
||||
#define QLA83XX_SS_PCI_INDEX 0
|
||||
|
||||
struct qla4_8xxx_minidump_template_hdr {
|
||||
uint32_t entry_type;
|
||||
|
@ -1216,6 +1253,7 @@ struct qla4_8xxx_minidump_template_hdr {
|
|||
|
||||
uint32_t saved_state_array[QLA8XXX_DBG_STATE_ARRAY_LEN];
|
||||
uint32_t capture_size_array[QLA8XXX_DBG_CAP_SIZE_ARRAY_LEN];
|
||||
uint32_t ocm_window_reg[QLA83XX_DBG_OCM_WNDREG_ARRAY_LEN];
|
||||
};
|
||||
|
||||
#endif /* _QLA4X_FW_H */
|
||||
|
|
|
@ -214,6 +214,47 @@ void qla4_82xx_process_mbox_intr(struct scsi_qla_host *ha, int outcount);
|
|||
void qla4xxx_queue_mbox_cmd(struct scsi_qla_host *ha, uint32_t *mbx_cmd,
|
||||
int incount);
|
||||
void qla4xxx_process_mbox_intr(struct scsi_qla_host *ha, int outcount);
|
||||
void qla4_8xxx_dump_peg_reg(struct scsi_qla_host *ha);
|
||||
void qla4_83xx_disable_intrs(struct scsi_qla_host *ha);
|
||||
void qla4_83xx_enable_intrs(struct scsi_qla_host *ha);
|
||||
int qla4_83xx_start_firmware(struct scsi_qla_host *ha);
|
||||
irqreturn_t qla4_83xx_intr_handler(int irq, void *dev_id);
|
||||
void qla4_83xx_interrupt_service_routine(struct scsi_qla_host *ha,
|
||||
uint32_t intr_status);
|
||||
int qla4_83xx_isp_reset(struct scsi_qla_host *ha);
|
||||
void qla4_83xx_queue_iocb(struct scsi_qla_host *ha);
|
||||
void qla4_83xx_complete_iocb(struct scsi_qla_host *ha);
|
||||
uint16_t qla4_83xx_rd_shdw_req_q_out(struct scsi_qla_host *ha);
|
||||
uint16_t qla4_83xx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha);
|
||||
uint32_t qla4_83xx_rd_reg(struct scsi_qla_host *ha, ulong addr);
|
||||
void qla4_83xx_wr_reg(struct scsi_qla_host *ha, ulong addr, uint32_t val);
|
||||
int qla4_83xx_rd_reg_indirect(struct scsi_qla_host *ha, uint32_t addr,
|
||||
uint32_t *data);
|
||||
int qla4_83xx_wr_reg_indirect(struct scsi_qla_host *ha, uint32_t addr,
|
||||
uint32_t data);
|
||||
int qla4_83xx_drv_lock(struct scsi_qla_host *ha);
|
||||
void qla4_83xx_drv_unlock(struct scsi_qla_host *ha);
|
||||
void qla4_83xx_rom_lock_recovery(struct scsi_qla_host *ha);
|
||||
void qla4_83xx_queue_mbox_cmd(struct scsi_qla_host *ha, uint32_t *mbx_cmd,
|
||||
int incount);
|
||||
void qla4_83xx_process_mbox_intr(struct scsi_qla_host *ha, int outcount);
|
||||
void qla4_83xx_read_reset_template(struct scsi_qla_host *ha);
|
||||
void qla4_83xx_set_idc_dontreset(struct scsi_qla_host *ha);
|
||||
int qla4_83xx_idc_dontreset(struct scsi_qla_host *ha);
|
||||
int qla4_83xx_lockless_flash_read_u32(struct scsi_qla_host *ha,
|
||||
uint32_t flash_addr, uint8_t *p_data,
|
||||
int u32_word_count);
|
||||
void qla4_83xx_clear_idc_dontreset(struct scsi_qla_host *ha);
|
||||
void qla4_83xx_need_reset_handler(struct scsi_qla_host *ha);
|
||||
int qla4_83xx_flash_read_u32(struct scsi_qla_host *ha, uint32_t flash_addr,
|
||||
uint8_t *p_data, int u32_word_count);
|
||||
void qla4_83xx_get_idc_param(struct scsi_qla_host *ha);
|
||||
void qla4_8xxx_set_rst_ready(struct scsi_qla_host *ha);
|
||||
void qla4_8xxx_clear_rst_ready(struct scsi_qla_host *ha);
|
||||
int qla4_8xxx_device_bootstrap(struct scsi_qla_host *ha);
|
||||
void qla4_8xxx_get_minidump(struct scsi_qla_host *ha);
|
||||
int qla4_8xxx_mbx_intr_disable(struct scsi_qla_host *ha);
|
||||
int qla4_8xxx_mbx_intr_enable(struct scsi_qla_host *ha);
|
||||
|
||||
extern int ql4xextended_error_logging;
|
||||
extern int ql4xdontresethba;
|
||||
|
|
|
@ -107,6 +107,13 @@ int qla4xxx_init_rings(struct scsi_qla_host *ha)
|
|||
(unsigned long __iomem *)&ha->qla4_82xx_reg->rsp_q_in);
|
||||
writel(0,
|
||||
(unsigned long __iomem *)&ha->qla4_82xx_reg->rsp_q_out);
|
||||
} else if (is_qla8032(ha)) {
|
||||
writel(0,
|
||||
(unsigned long __iomem *)&ha->qla4_83xx_reg->req_q_in);
|
||||
writel(0,
|
||||
(unsigned long __iomem *)&ha->qla4_83xx_reg->rsp_q_in);
|
||||
writel(0,
|
||||
(unsigned long __iomem *)&ha->qla4_83xx_reg->rsp_q_out);
|
||||
} else {
|
||||
/*
|
||||
* Initialize DMA Shadow registers. The firmware is really
|
||||
|
@ -524,7 +531,7 @@ static int qla4xxx_init_firmware(struct scsi_qla_host *ha)
|
|||
/* For 82xx, stop firmware before initializing because if BIOS
|
||||
* has previously initialized firmware, then driver's initialize
|
||||
* firmware will fail. */
|
||||
if (is_qla8022(ha))
|
||||
if (is_qla80XX(ha))
|
||||
qla4_8xxx_stop_firmware(ha);
|
||||
|
||||
ql4_printk(KERN_INFO, ha, "Initializing firmware..\n");
|
||||
|
@ -537,7 +544,7 @@ static int qla4xxx_init_firmware(struct scsi_qla_host *ha)
|
|||
if (!qla4xxx_fw_ready(ha))
|
||||
return status;
|
||||
|
||||
if (is_qla8022(ha) && !test_bit(AF_INIT_DONE, &ha->flags))
|
||||
if (is_qla80XX(ha) && !test_bit(AF_INIT_DONE, &ha->flags))
|
||||
qla4xxx_alloc_fw_dump(ha);
|
||||
|
||||
return qla4xxx_get_firmware_status(ha);
|
||||
|
@ -946,9 +953,9 @@ int qla4xxx_initialize_adapter(struct scsi_qla_host *ha, int is_reset)
|
|||
|
||||
set_bit(AF_ONLINE, &ha->flags);
|
||||
exit_init_hba:
|
||||
if (is_qla8022(ha) && (status == QLA_ERROR)) {
|
||||
if (is_qla80XX(ha) && (status == QLA_ERROR)) {
|
||||
/* Since interrupts are registered in start_firmware for
|
||||
* 82xx, release them here if initialize_adapter fails */
|
||||
* 80XX, release them here if initialize_adapter fails */
|
||||
qla4xxx_free_irqs(ha);
|
||||
}
|
||||
|
||||
|
|
|
@ -192,6 +192,18 @@ static void qla4xxx_build_scsi_iocbs(struct srb *srb,
|
|||
}
|
||||
}
|
||||
|
||||
void qla4_83xx_queue_iocb(struct scsi_qla_host *ha)
|
||||
{
|
||||
writel(ha->request_in, &ha->qla4_83xx_reg->req_q_in);
|
||||
readl(&ha->qla4_83xx_reg->req_q_in);
|
||||
}
|
||||
|
||||
void qla4_83xx_complete_iocb(struct scsi_qla_host *ha)
|
||||
{
|
||||
writel(ha->response_out, &ha->qla4_83xx_reg->rsp_q_out);
|
||||
readl(&ha->qla4_83xx_reg->rsp_q_out);
|
||||
}
|
||||
|
||||
/**
|
||||
* qla4_82xx_queue_iocb - Tell ISP it's got new request(s)
|
||||
* @ha: pointer to host adapter structure.
|
||||
|
|
|
@ -126,7 +126,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
|
|||
ql4_printk(KERN_WARNING, ha, "%s invalid status entry: "
|
||||
"handle=0x%0x, srb=%p\n", __func__,
|
||||
sts_entry->handle, srb);
|
||||
if (is_qla8022(ha))
|
||||
if (is_qla80XX(ha))
|
||||
set_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags);
|
||||
else
|
||||
set_bit(DPC_RESET_HA, &ha->dpc_flags);
|
||||
|
@ -594,6 +594,14 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
|
|||
{
|
||||
int i;
|
||||
uint32_t mbox_sts[MBOX_AEN_REG_COUNT];
|
||||
__le32 __iomem *mailbox_out;
|
||||
|
||||
if (is_qla8032(ha))
|
||||
mailbox_out = &ha->qla4_83xx_reg->mailbox_out[0];
|
||||
else if (is_qla8022(ha))
|
||||
mailbox_out = &ha->qla4_82xx_reg->mailbox_out[0];
|
||||
else
|
||||
mailbox_out = &ha->reg->mailbox[0];
|
||||
|
||||
if ((mbox_status == MBOX_STS_BUSY) ||
|
||||
(mbox_status == MBOX_STS_INTERMEDIATE_COMPLETION) ||
|
||||
|
@ -606,9 +614,7 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
|
|||
* location and set mailbox command done flag
|
||||
*/
|
||||
for (i = 0; i < ha->mbox_status_count; i++)
|
||||
ha->mbox_status[i] = is_qla8022(ha)
|
||||
? readl(&ha->qla4_82xx_reg->mailbox_out[i])
|
||||
: readl(&ha->reg->mailbox[i]);
|
||||
ha->mbox_status[i] = readl(&mailbox_out[i]);
|
||||
|
||||
set_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
|
||||
|
||||
|
@ -617,9 +623,7 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
|
|||
}
|
||||
} else if (mbox_status >> 12 == MBOX_ASYNC_EVENT_STATUS) {
|
||||
for (i = 0; i < MBOX_AEN_REG_COUNT; i++)
|
||||
mbox_sts[i] = is_qla8022(ha)
|
||||
? readl(&ha->qla4_82xx_reg->mailbox_out[i])
|
||||
: readl(&ha->reg->mailbox[i]);
|
||||
mbox_sts[i] = readl(&mailbox_out[i]);
|
||||
|
||||
/* Immediately process the AENs that don't require much work.
|
||||
* Only queue the database_changed AENs */
|
||||
|
@ -635,7 +639,8 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
|
|||
ql4_printk(KERN_INFO, ha, "%s: System Err\n", __func__);
|
||||
qla4xxx_dump_registers(ha);
|
||||
|
||||
if (ql4xdontresethba) {
|
||||
if ((is_qla8022(ha) && ql4xdontresethba) ||
|
||||
(is_qla8032(ha) && qla4_83xx_idc_dontreset(ha))) {
|
||||
DEBUG2(printk("scsi%ld: %s:Don't Reset HBA\n",
|
||||
ha->host_no, __func__));
|
||||
} else {
|
||||
|
@ -651,7 +656,7 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
|
|||
case MBOX_ASTS_DHCP_LEASE_EXPIRED:
|
||||
DEBUG2(printk("scsi%ld: AEN %04x, ERROR Status, "
|
||||
"Reset HA\n", ha->host_no, mbox_status));
|
||||
if (is_qla8022(ha))
|
||||
if (is_qla80XX(ha))
|
||||
set_bit(DPC_RESET_HA_FW_CONTEXT,
|
||||
&ha->dpc_flags);
|
||||
else
|
||||
|
@ -716,7 +721,7 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
|
|||
set_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags);
|
||||
else if ((mbox_sts[3] == ACB_STATE_ACQUIRING) &&
|
||||
(mbox_sts[2] == ACB_STATE_VALID)) {
|
||||
if (is_qla8022(ha))
|
||||
if (is_qla80XX(ha))
|
||||
set_bit(DPC_RESET_HA_FW_CONTEXT,
|
||||
&ha->dpc_flags);
|
||||
else
|
||||
|
@ -815,6 +820,23 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
|
|||
}
|
||||
}
|
||||
|
||||
void qla4_83xx_interrupt_service_routine(struct scsi_qla_host *ha,
|
||||
uint32_t intr_status)
|
||||
{
|
||||
/* Process mailbox/asynch event interrupt.*/
|
||||
if (intr_status) {
|
||||
qla4xxx_isr_decode_mailbox(ha,
|
||||
readl(&ha->qla4_83xx_reg->mailbox_out[0]));
|
||||
/* clear the interrupt */
|
||||
writel(0, &ha->qla4_83xx_reg->risc_intr);
|
||||
} else {
|
||||
qla4xxx_process_response_queue(ha);
|
||||
}
|
||||
|
||||
/* clear the interrupt */
|
||||
writel(0, &ha->qla4_83xx_reg->mb_int_mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* qla4_82xx_interrupt_service_routine - isr
|
||||
* @ha: pointer to host adapter structure.
|
||||
|
@ -1045,6 +1067,59 @@ irqreturn_t qla4_82xx_intr_handler(int irq, void *dev_id)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
#define LEG_INT_PTR_B31 (1 << 31)
|
||||
#define LEG_INT_PTR_B30 (1 << 30)
|
||||
#define PF_BITS_MASK (0xF << 16)
|
||||
|
||||
/**
|
||||
* qla4_83xx_intr_handler - hardware interrupt handler.
|
||||
* @irq: Unused
|
||||
* @dev_id: Pointer to host adapter structure
|
||||
**/
|
||||
irqreturn_t qla4_83xx_intr_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct scsi_qla_host *ha = dev_id;
|
||||
uint32_t leg_int_ptr = 0;
|
||||
unsigned long flags = 0;
|
||||
|
||||
ha->isr_count++;
|
||||
leg_int_ptr = readl(&ha->qla4_83xx_reg->leg_int_ptr);
|
||||
|
||||
/* Legacy interrupt is valid if bit31 of leg_int_ptr is set */
|
||||
if (!(leg_int_ptr & LEG_INT_PTR_B31)) {
|
||||
ql4_printk(KERN_ERR, ha,
|
||||
"%s: Legacy Interrupt Bit 31 not set, spurious interrupt!\n",
|
||||
__func__);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
/* Validate the PCIE function ID set in leg_int_ptr bits [19..16] */
|
||||
if ((leg_int_ptr & PF_BITS_MASK) != ha->pf_bit) {
|
||||
ql4_printk(KERN_ERR, ha,
|
||||
"%s: Incorrect function ID 0x%x in legacy interrupt register, ha->pf_bit = 0x%x\n",
|
||||
__func__, (leg_int_ptr & PF_BITS_MASK), ha->pf_bit);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
/* To de-assert legacy interrupt, write 0 to Legacy Interrupt Trigger
|
||||
* Control register and poll till Legacy Interrupt Pointer register
|
||||
* bit30 is 0.
|
||||
*/
|
||||
writel(0, &ha->qla4_83xx_reg->leg_int_trig);
|
||||
do {
|
||||
leg_int_ptr = readl(&ha->qla4_83xx_reg->leg_int_ptr);
|
||||
if ((leg_int_ptr & PF_BITS_MASK) != ha->pf_bit)
|
||||
break;
|
||||
} while (leg_int_ptr & LEG_INT_PTR_B30);
|
||||
|
||||
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||
leg_int_ptr = readl(&ha->qla4_83xx_reg->risc_intr);
|
||||
ha->isp_ops->interrupt_service_routine(ha, leg_int_ptr);
|
||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
irqreturn_t
|
||||
qla4_8xxx_msi_handler(int irq, void *dev_id)
|
||||
{
|
||||
|
@ -1068,6 +1143,37 @@ qla4_8xxx_msi_handler(int irq, void *dev_id)
|
|||
return qla4_8xxx_default_intr_handler(irq, dev_id);
|
||||
}
|
||||
|
||||
static irqreturn_t qla4_83xx_mailbox_intr_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct scsi_qla_host *ha = dev_id;
|
||||
unsigned long flags;
|
||||
uint32_t ival = 0;
|
||||
|
||||
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||
|
||||
ival = readl(&ha->qla4_83xx_reg->risc_intr);
|
||||
if (ival == 0) {
|
||||
ql4_printk(KERN_INFO, ha,
|
||||
"%s: It is a spurious mailbox interrupt!\n",
|
||||
__func__);
|
||||
ival = readl(&ha->qla4_83xx_reg->mb_int_mask);
|
||||
ival &= ~INT_MASK_FW_MB;
|
||||
writel(ival, &ha->qla4_83xx_reg->mb_int_mask);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
qla4xxx_isr_decode_mailbox(ha,
|
||||
readl(&ha->qla4_83xx_reg->mailbox_out[0]));
|
||||
writel(0, &ha->qla4_83xx_reg->risc_intr);
|
||||
ival = readl(&ha->qla4_83xx_reg->mb_int_mask);
|
||||
ival &= ~INT_MASK_FW_MB;
|
||||
writel(ival, &ha->qla4_83xx_reg->mb_int_mask);
|
||||
ha->isr_count++;
|
||||
exit:
|
||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* qla4_8xxx_default_intr_handler - hardware interrupt handler.
|
||||
* @irq: Unused
|
||||
|
@ -1084,29 +1190,32 @@ qla4_8xxx_default_intr_handler(int irq, void *dev_id)
|
|||
uint32_t intr_status;
|
||||
uint8_t reqs_count = 0;
|
||||
|
||||
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||
while (1) {
|
||||
if (!(readl(&ha->qla4_82xx_reg->host_int) &
|
||||
ISRX_82XX_RISC_INT)) {
|
||||
qla4_82xx_spurious_interrupt(ha, reqs_count);
|
||||
break;
|
||||
if (is_qla8032(ha)) {
|
||||
qla4_83xx_mailbox_intr_handler(irq, dev_id);
|
||||
} else {
|
||||
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||
while (1) {
|
||||
if (!(readl(&ha->qla4_82xx_reg->host_int) &
|
||||
ISRX_82XX_RISC_INT)) {
|
||||
qla4_82xx_spurious_interrupt(ha, reqs_count);
|
||||
break;
|
||||
}
|
||||
|
||||
intr_status = readl(&ha->qla4_82xx_reg->host_status);
|
||||
if ((intr_status &
|
||||
(HSRX_RISC_MB_INT | HSRX_RISC_IOCB_INT)) == 0) {
|
||||
qla4_82xx_spurious_interrupt(ha, reqs_count);
|
||||
break;
|
||||
}
|
||||
|
||||
ha->isp_ops->interrupt_service_routine(ha, intr_status);
|
||||
|
||||
if (++reqs_count == MAX_REQS_SERVICED_PER_INTR)
|
||||
break;
|
||||
}
|
||||
|
||||
intr_status = readl(&ha->qla4_82xx_reg->host_status);
|
||||
if ((intr_status &
|
||||
(HSRX_RISC_MB_INT | HSRX_RISC_IOCB_INT)) == 0) {
|
||||
qla4_82xx_spurious_interrupt(ha, reqs_count);
|
||||
break;
|
||||
}
|
||||
|
||||
ha->isp_ops->interrupt_service_routine(ha, intr_status);
|
||||
|
||||
if (++reqs_count == MAX_REQS_SERVICED_PER_INTR)
|
||||
break;
|
||||
ha->isr_count++;
|
||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||
}
|
||||
|
||||
ha->isr_count++;
|
||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
@ -1115,13 +1224,25 @@ qla4_8xxx_msix_rsp_q(int irq, void *dev_id)
|
|||
{
|
||||
struct scsi_qla_host *ha = dev_id;
|
||||
unsigned long flags;
|
||||
uint32_t ival = 0;
|
||||
|
||||
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||
qla4xxx_process_response_queue(ha);
|
||||
writel(0, &ha->qla4_82xx_reg->host_int);
|
||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||
|
||||
if (is_qla8032(ha)) {
|
||||
ival = readl(&ha->qla4_83xx_reg->iocb_int_mask);
|
||||
if (ival == 0) {
|
||||
ql4_printk(KERN_INFO, ha, "%s: It is a spurious iocb interrupt!\n",
|
||||
__func__);
|
||||
goto exit_msix_rsp_q;
|
||||
}
|
||||
qla4xxx_process_response_queue(ha);
|
||||
writel(0, &ha->qla4_83xx_reg->iocb_int_mask);
|
||||
} else {
|
||||
qla4xxx_process_response_queue(ha);
|
||||
writel(0, &ha->qla4_82xx_reg->host_int);
|
||||
}
|
||||
ha->isr_count++;
|
||||
exit_msix_rsp_q:
|
||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
@ -1196,8 +1317,15 @@ int qla4xxx_request_irqs(struct scsi_qla_host *ha)
|
|||
if (is_qla40XX(ha))
|
||||
goto try_intx;
|
||||
|
||||
if (ql4xenablemsix == 2)
|
||||
if (ql4xenablemsix == 2) {
|
||||
/* Note: MSI Interrupts not supported for ISP8324 */
|
||||
if (is_qla8032(ha)) {
|
||||
ql4_printk(KERN_INFO, ha, "%s: MSI Interrupts not supported for ISP8324, Falling back-to INTx mode\n",
|
||||
__func__);
|
||||
goto try_intx;
|
||||
}
|
||||
goto try_msi;
|
||||
}
|
||||
|
||||
if (ql4xenablemsix == 0 || ql4xenablemsix != 1)
|
||||
goto try_intx;
|
||||
|
@ -1208,6 +1336,12 @@ int qla4xxx_request_irqs(struct scsi_qla_host *ha)
|
|||
DEBUG2(ql4_printk(KERN_INFO, ha,
|
||||
"MSI-X: Enabled (0x%X).\n", ha->revision_id));
|
||||
goto irq_attached;
|
||||
} else {
|
||||
if (is_qla8032(ha)) {
|
||||
ql4_printk(KERN_INFO, ha, "%s: ISP8324: MSI-X: Falling back-to INTx mode. ret = %d\n",
|
||||
__func__, ret);
|
||||
goto try_intx;
|
||||
}
|
||||
}
|
||||
|
||||
ql4_printk(KERN_WARNING, ha,
|
||||
|
|
|
@ -107,7 +107,7 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
|
|||
msleep(10);
|
||||
}
|
||||
|
||||
if (is_qla8022(ha)) {
|
||||
if (is_qla80XX(ha)) {
|
||||
if (test_bit(AF_FW_RECOVERY, &ha->flags)) {
|
||||
DEBUG2(ql4_printk(KERN_WARNING, ha,
|
||||
"scsi%ld: %s: prematurely completing mbx cmd as firmware recovery detected\n",
|
||||
|
@ -183,7 +183,7 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
|
|||
|
||||
/* Check for mailbox timeout. */
|
||||
if (!test_bit(AF_MBOX_COMMAND_DONE, &ha->flags)) {
|
||||
if (is_qla8022(ha) &&
|
||||
if (is_qla80XX(ha) &&
|
||||
test_bit(AF_FW_RECOVERY, &ha->flags)) {
|
||||
DEBUG2(ql4_printk(KERN_INFO, ha,
|
||||
"scsi%ld: %s: prematurely completing mbx cmd as "
|
||||
|
@ -544,7 +544,7 @@ int qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha)
|
|||
__constant_cpu_to_le16(FWOPT_SESSION_MODE |
|
||||
FWOPT_INITIATOR_MODE);
|
||||
|
||||
if (is_qla8022(ha))
|
||||
if (is_qla80XX(ha))
|
||||
init_fw_cb->fw_options |=
|
||||
__constant_cpu_to_le16(FWOPT_ENABLE_CRBDB);
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <linux/ratelimit.h>
|
||||
#include "ql4_def.h"
|
||||
#include "ql4_glbl.h"
|
||||
#include "ql4_inline.h"
|
||||
|
||||
#include <asm-generic/io-64-nonatomic-lo-hi.h>
|
||||
|
||||
|
@ -1511,7 +1512,17 @@ qla4_8xxx_set_drv_active(struct scsi_qla_host *ha)
|
|||
uint32_t drv_active;
|
||||
|
||||
drv_active = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_ACTIVE);
|
||||
drv_active |= (1 << (ha->func_num * 4));
|
||||
|
||||
/*
|
||||
* For ISP8324, drv_active register has 1 bit per function,
|
||||
* shift 1 by func_num to set a bit for the function.
|
||||
* For ISP8022, drv_active has 4 bits per function
|
||||
*/
|
||||
if (is_qla8032(ha))
|
||||
drv_active |= (1 << ha->func_num);
|
||||
else
|
||||
drv_active |= (1 << (ha->func_num * 4));
|
||||
|
||||
ql4_printk(KERN_INFO, ha, "%s(%ld): drv_active: 0x%08x\n",
|
||||
__func__, ha->host_no, drv_active);
|
||||
qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_ACTIVE, drv_active);
|
||||
|
@ -1523,7 +1534,17 @@ qla4_8xxx_clear_drv_active(struct scsi_qla_host *ha)
|
|||
uint32_t drv_active;
|
||||
|
||||
drv_active = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_ACTIVE);
|
||||
drv_active &= ~(1 << (ha->func_num * 4));
|
||||
|
||||
/*
|
||||
* For ISP8324, drv_active register has 1 bit per function,
|
||||
* shift 1 by func_num to set a bit for the function.
|
||||
* For ISP8022, drv_active has 4 bits per function
|
||||
*/
|
||||
if (is_qla8032(ha))
|
||||
drv_active &= ~(1 << (ha->func_num));
|
||||
else
|
||||
drv_active &= ~(1 << (ha->func_num * 4));
|
||||
|
||||
ql4_printk(KERN_INFO, ha, "%s(%ld): drv_active: 0x%08x\n",
|
||||
__func__, ha->host_no, drv_active);
|
||||
qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_ACTIVE, drv_active);
|
||||
|
@ -1536,32 +1557,60 @@ inline int qla4_8xxx_need_reset(struct scsi_qla_host *ha)
|
|||
|
||||
drv_active = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_ACTIVE);
|
||||
drv_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_STATE);
|
||||
rval = drv_state & (1 << (ha->func_num * 4));
|
||||
|
||||
/*
|
||||
* For ISP8324, drv_active register has 1 bit per function,
|
||||
* shift 1 by func_num to set a bit for the function.
|
||||
* For ISP8022, drv_active has 4 bits per function
|
||||
*/
|
||||
if (is_qla8032(ha))
|
||||
rval = drv_state & (1 << ha->func_num);
|
||||
else
|
||||
rval = drv_state & (1 << (ha->func_num * 4));
|
||||
|
||||
if ((test_bit(AF_EEH_BUSY, &ha->flags)) && drv_active)
|
||||
rval = 1;
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
static inline void
|
||||
qla4_8xxx_set_rst_ready(struct scsi_qla_host *ha)
|
||||
void qla4_8xxx_set_rst_ready(struct scsi_qla_host *ha)
|
||||
{
|
||||
uint32_t drv_state;
|
||||
|
||||
drv_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_STATE);
|
||||
drv_state |= (1 << (ha->func_num * 4));
|
||||
|
||||
/*
|
||||
* For ISP8324, drv_active register has 1 bit per function,
|
||||
* shift 1 by func_num to set a bit for the function.
|
||||
* For ISP8022, drv_active has 4 bits per function
|
||||
*/
|
||||
if (is_qla8032(ha))
|
||||
drv_state |= (1 << ha->func_num);
|
||||
else
|
||||
drv_state |= (1 << (ha->func_num * 4));
|
||||
|
||||
ql4_printk(KERN_INFO, ha, "%s(%ld): drv_state: 0x%08x\n",
|
||||
__func__, ha->host_no, drv_state);
|
||||
qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_STATE, drv_state);
|
||||
}
|
||||
|
||||
static inline void
|
||||
qla4_8xxx_clear_rst_ready(struct scsi_qla_host *ha)
|
||||
void qla4_8xxx_clear_rst_ready(struct scsi_qla_host *ha)
|
||||
{
|
||||
uint32_t drv_state;
|
||||
|
||||
drv_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_STATE);
|
||||
drv_state &= ~(1 << (ha->func_num * 4));
|
||||
|
||||
/*
|
||||
* For ISP8324, drv_active register has 1 bit per function,
|
||||
* shift 1 by func_num to set a bit for the function.
|
||||
* For ISP8022, drv_active has 4 bits per function
|
||||
*/
|
||||
if (is_qla8032(ha))
|
||||
drv_state &= ~(1 << ha->func_num);
|
||||
else
|
||||
drv_state &= ~(1 << (ha->func_num * 4));
|
||||
|
||||
ql4_printk(KERN_INFO, ha, "%s(%ld): drv_state: 0x%08x\n",
|
||||
__func__, ha->host_no, drv_state);
|
||||
qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_STATE, drv_state);
|
||||
|
@ -1573,7 +1622,17 @@ qla4_8xxx_set_qsnt_ready(struct scsi_qla_host *ha)
|
|||
uint32_t qsnt_state;
|
||||
|
||||
qsnt_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_STATE);
|
||||
qsnt_state |= (2 << (ha->func_num * 4));
|
||||
|
||||
/*
|
||||
* For ISP8324, drv_active register has 1 bit per function,
|
||||
* shift 1 by func_num to set a bit for the function.
|
||||
* For ISP8022, drv_active has 4 bits per function.
|
||||
*/
|
||||
if (is_qla8032(ha))
|
||||
qsnt_state |= (1 << ha->func_num);
|
||||
else
|
||||
qsnt_state |= (2 << (ha->func_num * 4));
|
||||
|
||||
qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_STATE, qsnt_state);
|
||||
}
|
||||
|
||||
|
@ -2104,6 +2163,196 @@ static void qla4_8xxx_mark_entry_skipped(struct scsi_qla_host *ha,
|
|||
entry_hdr->d_ctrl.entry_capture_mask));
|
||||
}
|
||||
|
||||
/* ISP83xx functions to process new minidump entries... */
|
||||
static uint32_t qla83xx_minidump_process_pollrd(struct scsi_qla_host *ha,
|
||||
struct qla8xxx_minidump_entry_hdr *entry_hdr,
|
||||
uint32_t **d_ptr)
|
||||
{
|
||||
uint32_t r_addr, s_addr, s_value, r_value, poll_wait, poll_mask;
|
||||
uint16_t s_stride, i;
|
||||
uint32_t *data_ptr = *d_ptr;
|
||||
uint32_t rval = QLA_SUCCESS;
|
||||
struct qla83xx_minidump_entry_pollrd *pollrd_hdr;
|
||||
|
||||
pollrd_hdr = (struct qla83xx_minidump_entry_pollrd *)entry_hdr;
|
||||
s_addr = le32_to_cpu(pollrd_hdr->select_addr);
|
||||
r_addr = le32_to_cpu(pollrd_hdr->read_addr);
|
||||
s_value = le32_to_cpu(pollrd_hdr->select_value);
|
||||
s_stride = le32_to_cpu(pollrd_hdr->select_value_stride);
|
||||
|
||||
poll_wait = le32_to_cpu(pollrd_hdr->poll_wait);
|
||||
poll_mask = le32_to_cpu(pollrd_hdr->poll_mask);
|
||||
|
||||
for (i = 0; i < le32_to_cpu(pollrd_hdr->op_count); i++) {
|
||||
ha->isp_ops->wr_reg_indirect(ha, s_addr, s_value);
|
||||
poll_wait = le32_to_cpu(pollrd_hdr->poll_wait);
|
||||
while (1) {
|
||||
ha->isp_ops->rd_reg_indirect(ha, s_addr, &r_value);
|
||||
|
||||
if ((r_value & poll_mask) != 0) {
|
||||
break;
|
||||
} else {
|
||||
msleep(1);
|
||||
if (--poll_wait == 0) {
|
||||
ql4_printk(KERN_ERR, ha, "%s: TIMEOUT\n",
|
||||
__func__);
|
||||
rval = QLA_ERROR;
|
||||
goto exit_process_pollrd;
|
||||
}
|
||||
}
|
||||
}
|
||||
ha->isp_ops->rd_reg_indirect(ha, r_addr, &r_value);
|
||||
*data_ptr++ = cpu_to_le32(s_value);
|
||||
*data_ptr++ = cpu_to_le32(r_value);
|
||||
s_value += s_stride;
|
||||
}
|
||||
|
||||
*d_ptr = data_ptr;
|
||||
|
||||
exit_process_pollrd:
|
||||
return rval;
|
||||
}
|
||||
|
||||
static void qla83xx_minidump_process_rdmux2(struct scsi_qla_host *ha,
|
||||
struct qla8xxx_minidump_entry_hdr *entry_hdr,
|
||||
uint32_t **d_ptr)
|
||||
{
|
||||
uint32_t sel_val1, sel_val2, t_sel_val, data, i;
|
||||
uint32_t sel_addr1, sel_addr2, sel_val_mask, read_addr;
|
||||
struct qla83xx_minidump_entry_rdmux2 *rdmux2_hdr;
|
||||
uint32_t *data_ptr = *d_ptr;
|
||||
|
||||
rdmux2_hdr = (struct qla83xx_minidump_entry_rdmux2 *)entry_hdr;
|
||||
sel_val1 = le32_to_cpu(rdmux2_hdr->select_value_1);
|
||||
sel_val2 = le32_to_cpu(rdmux2_hdr->select_value_2);
|
||||
sel_addr1 = le32_to_cpu(rdmux2_hdr->select_addr_1);
|
||||
sel_addr2 = le32_to_cpu(rdmux2_hdr->select_addr_2);
|
||||
sel_val_mask = le32_to_cpu(rdmux2_hdr->select_value_mask);
|
||||
read_addr = le32_to_cpu(rdmux2_hdr->read_addr);
|
||||
|
||||
for (i = 0; i < rdmux2_hdr->op_count; i++) {
|
||||
ha->isp_ops->wr_reg_indirect(ha, sel_addr1, sel_val1);
|
||||
t_sel_val = sel_val1 & sel_val_mask;
|
||||
*data_ptr++ = cpu_to_le32(t_sel_val);
|
||||
|
||||
ha->isp_ops->wr_reg_indirect(ha, sel_addr2, t_sel_val);
|
||||
ha->isp_ops->rd_reg_indirect(ha, read_addr, &data);
|
||||
|
||||
*data_ptr++ = cpu_to_le32(data);
|
||||
|
||||
ha->isp_ops->wr_reg_indirect(ha, sel_addr1, sel_val2);
|
||||
t_sel_val = sel_val2 & sel_val_mask;
|
||||
*data_ptr++ = cpu_to_le32(t_sel_val);
|
||||
|
||||
ha->isp_ops->wr_reg_indirect(ha, sel_addr2, t_sel_val);
|
||||
ha->isp_ops->rd_reg_indirect(ha, read_addr, &data);
|
||||
|
||||
*data_ptr++ = cpu_to_le32(data);
|
||||
|
||||
sel_val1 += rdmux2_hdr->select_value_stride;
|
||||
sel_val2 += rdmux2_hdr->select_value_stride;
|
||||
}
|
||||
|
||||
*d_ptr = data_ptr;
|
||||
}
|
||||
|
||||
static uint32_t qla83xx_minidump_process_pollrdmwr(struct scsi_qla_host *ha,
|
||||
struct qla8xxx_minidump_entry_hdr *entry_hdr,
|
||||
uint32_t **d_ptr)
|
||||
{
|
||||
uint32_t poll_wait, poll_mask, r_value, data;
|
||||
uint32_t addr_1, addr_2, value_1, value_2;
|
||||
uint32_t *data_ptr = *d_ptr;
|
||||
uint32_t rval = QLA_SUCCESS;
|
||||
struct qla83xx_minidump_entry_pollrdmwr *poll_hdr;
|
||||
|
||||
poll_hdr = (struct qla83xx_minidump_entry_pollrdmwr *)entry_hdr;
|
||||
addr_1 = le32_to_cpu(poll_hdr->addr_1);
|
||||
addr_2 = le32_to_cpu(poll_hdr->addr_2);
|
||||
value_1 = le32_to_cpu(poll_hdr->value_1);
|
||||
value_2 = le32_to_cpu(poll_hdr->value_2);
|
||||
poll_mask = le32_to_cpu(poll_hdr->poll_mask);
|
||||
|
||||
ha->isp_ops->wr_reg_indirect(ha, addr_1, value_1);
|
||||
|
||||
poll_wait = le32_to_cpu(poll_hdr->poll_wait);
|
||||
while (1) {
|
||||
ha->isp_ops->rd_reg_indirect(ha, addr_1, &r_value);
|
||||
|
||||
if ((r_value & poll_mask) != 0) {
|
||||
break;
|
||||
} else {
|
||||
msleep(1);
|
||||
if (--poll_wait == 0) {
|
||||
ql4_printk(KERN_ERR, ha, "%s: TIMEOUT_1\n",
|
||||
__func__);
|
||||
rval = QLA_ERROR;
|
||||
goto exit_process_pollrdmwr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ha->isp_ops->rd_reg_indirect(ha, addr_2, &data);
|
||||
data &= le32_to_cpu(poll_hdr->modify_mask);
|
||||
ha->isp_ops->wr_reg_indirect(ha, addr_2, data);
|
||||
ha->isp_ops->wr_reg_indirect(ha, addr_1, value_2);
|
||||
|
||||
poll_wait = le32_to_cpu(poll_hdr->poll_wait);
|
||||
while (1) {
|
||||
ha->isp_ops->rd_reg_indirect(ha, addr_1, &r_value);
|
||||
|
||||
if ((r_value & poll_mask) != 0) {
|
||||
break;
|
||||
} else {
|
||||
msleep(1);
|
||||
if (--poll_wait == 0) {
|
||||
ql4_printk(KERN_ERR, ha, "%s: TIMEOUT_2\n",
|
||||
__func__);
|
||||
rval = QLA_ERROR;
|
||||
goto exit_process_pollrdmwr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*data_ptr++ = cpu_to_le32(addr_2);
|
||||
*data_ptr++ = cpu_to_le32(data);
|
||||
*d_ptr = data_ptr;
|
||||
|
||||
exit_process_pollrdmwr:
|
||||
return rval;
|
||||
}
|
||||
|
||||
static uint32_t qla4_83xx_minidump_process_rdrom(struct scsi_qla_host *ha,
|
||||
struct qla8xxx_minidump_entry_hdr *entry_hdr,
|
||||
uint32_t **d_ptr)
|
||||
{
|
||||
uint32_t fl_addr, u32_count, rval;
|
||||
struct qla8xxx_minidump_entry_rdrom *rom_hdr;
|
||||
uint32_t *data_ptr = *d_ptr;
|
||||
|
||||
rom_hdr = (struct qla8xxx_minidump_entry_rdrom *)entry_hdr;
|
||||
fl_addr = le32_to_cpu(rom_hdr->read_addr);
|
||||
u32_count = le32_to_cpu(rom_hdr->read_data_size)/sizeof(uint32_t);
|
||||
|
||||
DEBUG2(ql4_printk(KERN_INFO, ha, "[%s]: fl_addr: 0x%x, count: 0x%x\n",
|
||||
__func__, fl_addr, u32_count));
|
||||
|
||||
rval = qla4_83xx_lockless_flash_read_u32(ha, fl_addr,
|
||||
(u8 *)(data_ptr), u32_count);
|
||||
|
||||
if (rval == QLA_ERROR) {
|
||||
ql4_printk(KERN_ERR, ha, "%s: Flash Read Error,Count=%d\n",
|
||||
__func__, u32_count);
|
||||
goto exit_process_rdrom;
|
||||
}
|
||||
|
||||
data_ptr += u32_count;
|
||||
*d_ptr = data_ptr;
|
||||
|
||||
exit_process_rdrom:
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* qla4_8xxx_collect_md_data - Retrieve firmware minidump data.
|
||||
* @ha: pointer to adapter structure
|
||||
|
@ -2151,6 +2400,10 @@ static int qla4_8xxx_collect_md_data(struct scsi_qla_host *ha)
|
|||
(((uint8_t *)ha->fw_dump_tmplt_hdr) +
|
||||
tmplt_hdr->first_entry_offset);
|
||||
|
||||
if (is_qla8032(ha))
|
||||
tmplt_hdr->saved_state_array[QLA83XX_SS_OCM_WNDREG_INDEX] =
|
||||
tmplt_hdr->ocm_window_reg[ha->func_num];
|
||||
|
||||
/* Walk through the entry headers - validate/perform required action */
|
||||
for (i = 0; i < num_entry_hdr; i++) {
|
||||
if (data_collected >= ha->fw_dump_size) {
|
||||
|
@ -2201,8 +2454,18 @@ static int qla4_8xxx_collect_md_data(struct scsi_qla_host *ha)
|
|||
break;
|
||||
case QLA8XXX_BOARD:
|
||||
case QLA8XXX_RDROM:
|
||||
qla4_82xx_minidump_process_rdrom(ha, entry_hdr,
|
||||
&data_ptr);
|
||||
if (is_qla8022(ha)) {
|
||||
qla4_82xx_minidump_process_rdrom(ha, entry_hdr,
|
||||
&data_ptr);
|
||||
} else if (is_qla8032(ha)) {
|
||||
rval = qla4_83xx_minidump_process_rdrom(ha,
|
||||
entry_hdr,
|
||||
&data_ptr);
|
||||
if (rval != QLA_SUCCESS)
|
||||
qla4_8xxx_mark_entry_skipped(ha,
|
||||
entry_hdr,
|
||||
i);
|
||||
}
|
||||
break;
|
||||
case QLA8XXX_L2DTG:
|
||||
case QLA8XXX_L2ITG:
|
||||
|
@ -2215,6 +2478,8 @@ static int qla4_8xxx_collect_md_data(struct scsi_qla_host *ha)
|
|||
goto md_failed;
|
||||
}
|
||||
break;
|
||||
case QLA8XXX_L1DTG:
|
||||
case QLA8XXX_L1ITG:
|
||||
case QLA8XXX_L1DAT:
|
||||
case QLA8XXX_L1INS:
|
||||
qla4_8xxx_minidump_process_l1cache(ha, entry_hdr,
|
||||
|
@ -2232,6 +2497,34 @@ static int qla4_8xxx_collect_md_data(struct scsi_qla_host *ha)
|
|||
qla4_8xxx_minidump_process_queue(ha, entry_hdr,
|
||||
&data_ptr);
|
||||
break;
|
||||
case QLA83XX_POLLRD:
|
||||
if (!is_qla8032(ha)) {
|
||||
qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i);
|
||||
break;
|
||||
}
|
||||
rval = qla83xx_minidump_process_pollrd(ha, entry_hdr,
|
||||
&data_ptr);
|
||||
if (rval != QLA_SUCCESS)
|
||||
qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i);
|
||||
break;
|
||||
case QLA83XX_RDMUX2:
|
||||
if (!is_qla8032(ha)) {
|
||||
qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i);
|
||||
break;
|
||||
}
|
||||
qla83xx_minidump_process_rdmux2(ha, entry_hdr,
|
||||
&data_ptr);
|
||||
break;
|
||||
case QLA83XX_POLLRDMWR:
|
||||
if (!is_qla8032(ha)) {
|
||||
qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i);
|
||||
break;
|
||||
}
|
||||
rval = qla83xx_minidump_process_pollrdmwr(ha, entry_hdr,
|
||||
&data_ptr);
|
||||
if (rval != QLA_SUCCESS)
|
||||
qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i);
|
||||
break;
|
||||
case QLA8XXX_RDNOP:
|
||||
default:
|
||||
qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i);
|
||||
|
@ -2283,7 +2576,7 @@ static void qla4_8xxx_uevent_emit(struct scsi_qla_host *ha, u32 code)
|
|||
kobject_uevent_env(&(&ha->pdev->dev)->kobj, KOBJ_CHANGE, envp);
|
||||
}
|
||||
|
||||
static void qla4_8xxx_get_minidump(struct scsi_qla_host *ha)
|
||||
void qla4_8xxx_get_minidump(struct scsi_qla_host *ha)
|
||||
{
|
||||
if (ql4xenablemd && test_bit(AF_FW_RECOVERY, &ha->flags) &&
|
||||
!test_bit(AF_82XX_FW_DUMPED, &ha->flags)) {
|
||||
|
@ -2303,12 +2596,11 @@ static void qla4_8xxx_get_minidump(struct scsi_qla_host *ha)
|
|||
*
|
||||
* Note: IDC lock must be held upon entry
|
||||
**/
|
||||
static int
|
||||
qla4_8xxx_device_bootstrap(struct scsi_qla_host *ha)
|
||||
int qla4_8xxx_device_bootstrap(struct scsi_qla_host *ha)
|
||||
{
|
||||
int rval = QLA_ERROR;
|
||||
int i, timeout;
|
||||
uint32_t old_count, count;
|
||||
uint32_t old_count, count, idc_ctrl;
|
||||
int need_reset = 0, peg_stuck = 1;
|
||||
|
||||
need_reset = ha->isp_ops->need_reset(ha);
|
||||
|
@ -2351,8 +2643,24 @@ dev_initialize:
|
|||
qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DEV_STATE,
|
||||
QLA8XXX_DEV_INITIALIZING);
|
||||
|
||||
/*
|
||||
* For ISP8324, if IDC_CTRL GRACEFUL_RESET_BIT1 is set, reset it after
|
||||
* device goes to INIT state.
|
||||
*/
|
||||
if (is_qla8032(ha)) {
|
||||
idc_ctrl = qla4_83xx_rd_reg(ha, QLA83XX_IDC_DRV_CTRL);
|
||||
if (idc_ctrl & GRACEFUL_RESET_BIT1) {
|
||||
qla4_83xx_wr_reg(ha, QLA83XX_IDC_DRV_CTRL,
|
||||
(idc_ctrl & ~GRACEFUL_RESET_BIT1));
|
||||
set_bit(AF_83XX_NO_FW_DUMP, &ha->flags);
|
||||
}
|
||||
}
|
||||
|
||||
ha->isp_ops->idc_unlock(ha);
|
||||
qla4_8xxx_get_minidump(ha);
|
||||
|
||||
if (is_qla8022(ha))
|
||||
qla4_8xxx_get_minidump(ha);
|
||||
|
||||
rval = ha->isp_ops->restart_firmware(ha);
|
||||
ha->isp_ops->idc_lock(ha);
|
||||
|
||||
|
@ -2487,14 +2795,77 @@ static void qla4_82xx_set_idc_ver(struct scsi_qla_host *ha)
|
|||
}
|
||||
}
|
||||
|
||||
static void qla4_8xxx_update_idc_reg(struct scsi_qla_host *ha)
|
||||
static int qla4_83xx_set_idc_ver(struct scsi_qla_host *ha)
|
||||
{
|
||||
if (!test_bit(AF_INIT_DONE, &ha->flags)) {
|
||||
ha->isp_ops->idc_lock(ha);
|
||||
qla4_8xxx_set_drv_active(ha);
|
||||
qla4_82xx_set_idc_ver(ha);
|
||||
ha->isp_ops->idc_unlock(ha);
|
||||
int idc_ver;
|
||||
uint32_t drv_active;
|
||||
int rval = QLA_SUCCESS;
|
||||
|
||||
drv_active = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_ACTIVE);
|
||||
if (drv_active == (1 << ha->func_num)) {
|
||||
idc_ver = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_IDC_VERSION);
|
||||
idc_ver &= (~0xFF);
|
||||
idc_ver |= QLA83XX_IDC_VER_MAJ_VALUE;
|
||||
qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_IDC_VERSION, idc_ver);
|
||||
ql4_printk(KERN_INFO, ha,
|
||||
"%s: IDC version updated to %d\n", __func__,
|
||||
QLA83XX_IDC_VER_MAJ_VALUE);
|
||||
} else {
|
||||
idc_ver = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_IDC_VERSION);
|
||||
idc_ver &= 0xFF;
|
||||
if (QLA83XX_IDC_VER_MAJ_VALUE != idc_ver) {
|
||||
ql4_printk(KERN_INFO, ha,
|
||||
"%s: qla4xxx driver IDC version %d is not compatible with IDC version %d of other drivers!\n",
|
||||
__func__, QLA83XX_IDC_VER_MAJ_VALUE,
|
||||
idc_ver);
|
||||
rval = QLA_ERROR;
|
||||
goto exit_set_idc_ver;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update IDC_MINOR_VERSION */
|
||||
idc_ver = qla4_83xx_rd_reg(ha, QLA83XX_CRB_IDC_VER_MINOR);
|
||||
idc_ver &= ~(0x03 << (ha->func_num * 2));
|
||||
idc_ver |= (QLA83XX_IDC_VER_MIN_VALUE << (ha->func_num * 2));
|
||||
qla4_83xx_wr_reg(ha, QLA83XX_CRB_IDC_VER_MINOR, idc_ver);
|
||||
|
||||
exit_set_idc_ver:
|
||||
return rval;
|
||||
}
|
||||
|
||||
static int qla4_8xxx_update_idc_reg(struct scsi_qla_host *ha)
|
||||
{
|
||||
uint32_t drv_active;
|
||||
int rval = QLA_SUCCESS;
|
||||
|
||||
if (test_bit(AF_INIT_DONE, &ha->flags))
|
||||
goto exit_update_idc_reg;
|
||||
|
||||
ha->isp_ops->idc_lock(ha);
|
||||
qla4_8xxx_set_drv_active(ha);
|
||||
|
||||
/*
|
||||
* If we are the first driver to load and
|
||||
* ql4xdontresethba is not set, clear IDC_CTRL BIT0.
|
||||
*/
|
||||
if (is_qla8032(ha)) {
|
||||
drv_active = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_ACTIVE);
|
||||
if ((drv_active == (1 << ha->func_num)) && !ql4xdontresethba)
|
||||
qla4_83xx_clear_idc_dontreset(ha);
|
||||
}
|
||||
|
||||
if (is_qla8022(ha)) {
|
||||
qla4_82xx_set_idc_ver(ha);
|
||||
} else if (is_qla8032(ha)) {
|
||||
rval = qla4_83xx_set_idc_ver(ha);
|
||||
if (rval == QLA_ERROR)
|
||||
qla4_8xxx_clear_drv_active(ha);
|
||||
}
|
||||
|
||||
ha->isp_ops->idc_unlock(ha);
|
||||
|
||||
exit_update_idc_reg:
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2509,7 +2880,9 @@ int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha)
|
|||
int rval = QLA_SUCCESS;
|
||||
unsigned long dev_init_timeout;
|
||||
|
||||
qla4_8xxx_update_idc_reg(ha);
|
||||
rval = qla4_8xxx_update_idc_reg(ha);
|
||||
if (rval == QLA_ERROR)
|
||||
goto exit_state_handler;
|
||||
|
||||
dev_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DEV_STATE);
|
||||
DEBUG2(ql4_printk(KERN_INFO, ha, "Device state is 0x%x = %s\n",
|
||||
|
@ -2550,16 +2923,25 @@ int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha)
|
|||
ha->isp_ops->idc_lock(ha);
|
||||
break;
|
||||
case QLA8XXX_DEV_NEED_RESET:
|
||||
if (!ql4xdontresethba) {
|
||||
qla4_82xx_need_reset_handler(ha);
|
||||
/* Update timeout value after need
|
||||
* reset handler */
|
||||
dev_init_timeout = jiffies +
|
||||
(ha->nx_dev_init_timeout * HZ);
|
||||
} else {
|
||||
ha->isp_ops->idc_unlock(ha);
|
||||
msleep(1000);
|
||||
ha->isp_ops->idc_lock(ha);
|
||||
/*
|
||||
* For ISP8324, if NEED_RESET is set by any driver,
|
||||
* it should be honored, irrespective of IDC_CTRL
|
||||
* DONTRESET_BIT0
|
||||
*/
|
||||
if (is_qla8032(ha)) {
|
||||
qla4_83xx_need_reset_handler(ha);
|
||||
} else if (is_qla8022(ha)) {
|
||||
if (!ql4xdontresethba) {
|
||||
qla4_82xx_need_reset_handler(ha);
|
||||
/* Update timeout value after need
|
||||
* reset handler */
|
||||
dev_init_timeout = jiffies +
|
||||
(ha->nx_dev_init_timeout * HZ);
|
||||
} else {
|
||||
ha->isp_ops->idc_unlock(ha);
|
||||
msleep(1000);
|
||||
ha->isp_ops->idc_lock(ha);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case QLA8XXX_DEV_NEED_QUIESCENT:
|
||||
|
@ -2587,6 +2969,7 @@ int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha)
|
|||
}
|
||||
exit:
|
||||
ha->isp_ops->idc_unlock(ha);
|
||||
exit_state_handler:
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
@ -2595,8 +2978,13 @@ int qla4_8xxx_load_risc(struct scsi_qla_host *ha)
|
|||
int retval;
|
||||
|
||||
/* clear the interrupt */
|
||||
writel(0, &ha->qla4_82xx_reg->host_int);
|
||||
readl(&ha->qla4_82xx_reg->host_int);
|
||||
if (is_qla8032(ha)) {
|
||||
writel(0, &ha->qla4_83xx_reg->risc_intr);
|
||||
readl(&ha->qla4_83xx_reg->risc_intr);
|
||||
} else if (is_qla8022(ha)) {
|
||||
writel(0, &ha->qla4_82xx_reg->host_int);
|
||||
readl(&ha->qla4_82xx_reg->host_int);
|
||||
}
|
||||
|
||||
retval = qla4_8xxx_device_state_handler(ha);
|
||||
|
||||
|
@ -2695,7 +3083,7 @@ qla4_8xxx_get_flt_info(struct scsi_qla_host *ha, uint32_t flt_addr)
|
|||
const char *loc, *locations[] = { "DEF", "FLT" };
|
||||
uint16_t *wptr;
|
||||
uint16_t cnt, chksum;
|
||||
uint32_t start;
|
||||
uint32_t start, status;
|
||||
struct qla_flt_header *flt;
|
||||
struct qla_flt_region *region;
|
||||
struct ql82xx_hw_data *hw = &ha->hw;
|
||||
|
@ -2704,8 +3092,18 @@ qla4_8xxx_get_flt_info(struct scsi_qla_host *ha, uint32_t flt_addr)
|
|||
wptr = (uint16_t *)ha->request_ring;
|
||||
flt = (struct qla_flt_header *)ha->request_ring;
|
||||
region = (struct qla_flt_region *)&flt[1];
|
||||
qla4_82xx_read_optrom_data(ha, (uint8_t *)ha->request_ring,
|
||||
flt_addr << 2, OPTROM_BURST_SIZE);
|
||||
|
||||
if (is_qla8022(ha)) {
|
||||
qla4_82xx_read_optrom_data(ha, (uint8_t *)ha->request_ring,
|
||||
flt_addr << 2, OPTROM_BURST_SIZE);
|
||||
} else if (is_qla8032(ha)) {
|
||||
status = qla4_83xx_flash_read_u32(ha, flt_addr << 2,
|
||||
(uint8_t *)ha->request_ring,
|
||||
0x400);
|
||||
if (status != QLA_SUCCESS)
|
||||
goto no_flash_data;
|
||||
}
|
||||
|
||||
if (*wptr == __constant_cpu_to_le16(0xffff))
|
||||
goto no_flash_data;
|
||||
if (flt->version != __constant_cpu_to_le16(1)) {
|
||||
|
@ -2918,8 +3316,12 @@ qla4_8xxx_get_flash_info(struct scsi_qla_host *ha)
|
|||
return ret;
|
||||
|
||||
qla4_8xxx_get_flt_info(ha, flt_addr);
|
||||
qla4_82xx_get_fdt_info(ha);
|
||||
qla4_82xx_get_idc_param(ha);
|
||||
if (is_qla8022(ha)) {
|
||||
qla4_82xx_get_fdt_info(ha);
|
||||
qla4_82xx_get_idc_param(ha);
|
||||
} else if (is_qla8032(ha)) {
|
||||
qla4_83xx_get_idc_param(ha);
|
||||
}
|
||||
|
||||
return QLA_SUCCESS;
|
||||
}
|
||||
|
@ -3063,8 +3465,7 @@ exit_validate_mac82:
|
|||
|
||||
/* Interrupt handling helpers. */
|
||||
|
||||
static int
|
||||
qla4_8xxx_mbx_intr_enable(struct scsi_qla_host *ha)
|
||||
int qla4_8xxx_mbx_intr_enable(struct scsi_qla_host *ha)
|
||||
{
|
||||
uint32_t mbox_cmd[MBOX_REG_COUNT];
|
||||
uint32_t mbox_sts[MBOX_REG_COUNT];
|
||||
|
@ -3085,8 +3486,7 @@ qla4_8xxx_mbx_intr_enable(struct scsi_qla_host *ha)
|
|||
return QLA_SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
qla4_8xxx_mbx_intr_disable(struct scsi_qla_host *ha)
|
||||
int qla4_8xxx_mbx_intr_disable(struct scsi_qla_host *ha)
|
||||
{
|
||||
uint32_t mbox_cmd[MBOX_REG_COUNT];
|
||||
uint32_t mbox_sts[MBOX_REG_COUNT];
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#define CRB_RCVPEG_STATE QLA82XX_REG(0x13c)
|
||||
#define CRB_DMA_SHIFT QLA82XX_REG(0xcc)
|
||||
#define CRB_TEMP_STATE QLA82XX_REG(0x1b4)
|
||||
#define CRB_CMDPEG_CHECK_RETRY_COUNT 60
|
||||
#define CRB_CMDPEG_CHECK_DELAY 500
|
||||
|
||||
#define qla82xx_get_temp_val(x) ((x) >> 16)
|
||||
#define qla82xx_get_temp_state(x) ((x) & 0xffff)
|
||||
|
@ -508,6 +510,7 @@ enum {
|
|||
|
||||
#define QLA82XX_P2_ADDR_QDR_NET_MAX (0x00000003001fffffULL)
|
||||
#define QLA82XX_P3_ADDR_QDR_NET_MAX (0x0000000303ffffffULL)
|
||||
#define QLA8XXX_ADDR_QDR_NET_MAX (0x0000000307ffffffULL)
|
||||
|
||||
#define QLA82XX_PCI_CRBSPACE (unsigned long)0x06000000
|
||||
#define QLA82XX_PCI_DIRECT_CRB (unsigned long)0x04400000
|
||||
|
@ -852,9 +855,13 @@ struct crb_addr_pair {
|
|||
#define QLA8XXX_L2ITG 22
|
||||
#define QLA8XXX_L2DAT 23
|
||||
#define QLA8XXX_L2INS 24
|
||||
#define QLA83XX_POLLRD 35
|
||||
#define QLA83XX_RDMUX2 36
|
||||
#define QLA83XX_POLLRDMWR 37
|
||||
#define QLA8XXX_RDROM 71
|
||||
#define QLA8XXX_RDMEM 72
|
||||
#define QLA8XXX_CNTRL 98
|
||||
#define QLA83XX_TLHDR 99
|
||||
#define QLA8XXX_RDEND 255
|
||||
|
||||
/* Opcodes for Control Entries.
|
||||
|
@ -1007,6 +1014,16 @@ struct qla8xxx_minidump_entry_queue {
|
|||
#define MD_MIU_TEST_AGT_ADDR_LO 0x41000094
|
||||
#define MD_MIU_TEST_AGT_ADDR_HI 0x41000098
|
||||
|
||||
#define MD_MIU_TEST_AGT_WRDATA_LO 0x410000A0
|
||||
#define MD_MIU_TEST_AGT_WRDATA_HI 0x410000A4
|
||||
#define MD_MIU_TEST_AGT_WRDATA_ULO 0x410000B0
|
||||
#define MD_MIU_TEST_AGT_WRDATA_UHI 0x410000B4
|
||||
|
||||
#define MD_MIU_TEST_AGT_RDDATA_LO 0x410000A8
|
||||
#define MD_MIU_TEST_AGT_RDDATA_HI 0x410000AC
|
||||
#define MD_MIU_TEST_AGT_RDDATA_ULO 0x410000B8
|
||||
#define MD_MIU_TEST_AGT_RDDATA_UHI 0x410000BC
|
||||
|
||||
static const int MD_MIU_TEST_AGT_RDDATA[] = { 0x410000A8,
|
||||
0x410000AC, 0x410000B8, 0x410000BC };
|
||||
#endif
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "ql4_glbl.h"
|
||||
#include "ql4_dbg.h"
|
||||
#include "ql4_inline.h"
|
||||
#include "ql4_83xx.h"
|
||||
|
||||
/*
|
||||
* Driver version
|
||||
|
@ -2315,8 +2316,17 @@ static void qla4xxx_mem_free(struct scsi_qla_host *ha)
|
|||
if (ha->nx_pcibase)
|
||||
iounmap(
|
||||
(struct device_reg_82xx __iomem *)ha->nx_pcibase);
|
||||
} else if (ha->reg)
|
||||
} else if (is_qla8032(ha)) {
|
||||
if (ha->nx_pcibase)
|
||||
iounmap(
|
||||
(struct device_reg_83xx __iomem *)ha->nx_pcibase);
|
||||
} else if (ha->reg) {
|
||||
iounmap(ha->reg);
|
||||
}
|
||||
|
||||
if (ha->reset_tmplt.buff)
|
||||
vfree(ha->reset_tmplt.buff);
|
||||
|
||||
pci_release_regions(ha->pdev);
|
||||
}
|
||||
|
||||
|
@ -2454,7 +2464,6 @@ static int qla4_8xxx_check_temp(struct scsi_qla_host *ha)
|
|||
static int qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha)
|
||||
{
|
||||
uint32_t fw_heartbeat_counter;
|
||||
uint32_t halt_status1, halt_status2;
|
||||
int status = QLA_SUCCESS;
|
||||
|
||||
fw_heartbeat_counter = qla4_8xxx_rd_direct(ha,
|
||||
|
@ -2472,28 +2481,7 @@ static int qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha)
|
|||
/* FW not alive after 2 seconds */
|
||||
if (ha->seconds_since_last_heartbeat == 2) {
|
||||
ha->seconds_since_last_heartbeat = 0;
|
||||
halt_status1 = qla4_8xxx_rd_direct(ha,
|
||||
QLA8XXX_PEG_HALT_STATUS1);
|
||||
halt_status2 = qla4_8xxx_rd_direct(ha,
|
||||
QLA8XXX_PEG_HALT_STATUS2);
|
||||
|
||||
ql4_printk(KERN_INFO, ha,
|
||||
"scsi(%ld): %s, Dumping hw/fw registers:\n "
|
||||
" PEG_HALT_STATUS1: 0x%x, PEG_HALT_STATUS2:"
|
||||
" 0x%x,\n PEG_NET_0_PC: 0x%x, PEG_NET_1_PC:"
|
||||
" 0x%x,\n PEG_NET_2_PC: 0x%x, PEG_NET_3_PC:"
|
||||
" 0x%x,\n PEG_NET_4_PC: 0x%x\n", ha->host_no,
|
||||
__func__, halt_status1, halt_status2,
|
||||
qla4_82xx_rd_32(ha, QLA82XX_CRB_PEG_NET_0 +
|
||||
0x3c),
|
||||
qla4_82xx_rd_32(ha, QLA82XX_CRB_PEG_NET_1 +
|
||||
0x3c),
|
||||
qla4_82xx_rd_32(ha, QLA82XX_CRB_PEG_NET_2 +
|
||||
0x3c),
|
||||
qla4_82xx_rd_32(ha, QLA82XX_CRB_PEG_NET_3 +
|
||||
0x3c),
|
||||
qla4_82xx_rd_32(ha, QLA82XX_CRB_PEG_NET_4 +
|
||||
0x3c));
|
||||
qla4_8xxx_dump_peg_reg(ha);
|
||||
status = QLA_ERROR;
|
||||
}
|
||||
} else
|
||||
|
@ -2503,6 +2491,48 @@ static int qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha)
|
|||
return status;
|
||||
}
|
||||
|
||||
static void qla4_8xxx_process_fw_error(struct scsi_qla_host *ha)
|
||||
{
|
||||
uint32_t halt_status;
|
||||
int halt_status_unrecoverable = 0;
|
||||
|
||||
halt_status = qla4_8xxx_rd_direct(ha, QLA8XXX_PEG_HALT_STATUS1);
|
||||
|
||||
if (is_qla8022(ha)) {
|
||||
ql4_printk(KERN_INFO, ha, "%s: disabling pause transmit on port 0 & 1.\n",
|
||||
__func__);
|
||||
qla4_82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x98,
|
||||
CRB_NIU_XG_PAUSE_CTL_P0 |
|
||||
CRB_NIU_XG_PAUSE_CTL_P1);
|
||||
|
||||
if (QLA82XX_FWERROR_CODE(halt_status) == 0x67)
|
||||
ql4_printk(KERN_ERR, ha, "%s: Firmware aborted with error code 0x00006700. Device is being reset\n",
|
||||
__func__);
|
||||
if (halt_status & HALT_STATUS_UNRECOVERABLE)
|
||||
halt_status_unrecoverable = 1;
|
||||
} else if (is_qla8032(ha)) {
|
||||
if (halt_status & QLA83XX_HALT_STATUS_FW_RESET)
|
||||
ql4_printk(KERN_ERR, ha, "%s: Firmware error detected device is being reset\n",
|
||||
__func__);
|
||||
else if (halt_status & QLA83XX_HALT_STATUS_UNRECOVERABLE)
|
||||
halt_status_unrecoverable = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Since we cannot change dev_state in interrupt context,
|
||||
* set appropriate DPC flag then wakeup DPC
|
||||
*/
|
||||
if (halt_status_unrecoverable) {
|
||||
set_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags);
|
||||
} else {
|
||||
ql4_printk(KERN_INFO, ha, "%s: detect abort needed!\n",
|
||||
__func__);
|
||||
set_bit(DPC_RESET_HA, &ha->dpc_flags);
|
||||
}
|
||||
qla4xxx_mailbox_premature_completion(ha);
|
||||
qla4xxx_wake_dpc(ha);
|
||||
}
|
||||
|
||||
/**
|
||||
* qla4_8xxx_watchdog - Poll dev state
|
||||
* @ha: Pointer to host adapter structure.
|
||||
|
@ -2511,7 +2541,7 @@ static int qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha)
|
|||
**/
|
||||
void qla4_8xxx_watchdog(struct scsi_qla_host *ha)
|
||||
{
|
||||
uint32_t dev_state, halt_status;
|
||||
uint32_t dev_state;
|
||||
|
||||
/* don't poll if reset is going on */
|
||||
if (!(test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) ||
|
||||
|
@ -2520,16 +2550,18 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha)
|
|||
dev_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DEV_STATE);
|
||||
|
||||
if (qla4_8xxx_check_temp(ha)) {
|
||||
ql4_printk(KERN_INFO, ha, "disabling pause"
|
||||
" transmit on port 0 & 1.\n");
|
||||
qla4_82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x98,
|
||||
CRB_NIU_XG_PAUSE_CTL_P0 |
|
||||
CRB_NIU_XG_PAUSE_CTL_P1);
|
||||
if (is_qla8022(ha)) {
|
||||
ql4_printk(KERN_INFO, ha, "disabling pause transmit on port 0 & 1.\n");
|
||||
qla4_82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x98,
|
||||
CRB_NIU_XG_PAUSE_CTL_P0 |
|
||||
CRB_NIU_XG_PAUSE_CTL_P1);
|
||||
}
|
||||
set_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags);
|
||||
qla4xxx_wake_dpc(ha);
|
||||
} else if (dev_state == QLA8XXX_DEV_NEED_RESET &&
|
||||
!test_bit(DPC_RESET_HA, &ha->dpc_flags)) {
|
||||
if (!ql4xdontresethba) {
|
||||
!test_bit(DPC_RESET_HA, &ha->dpc_flags)) {
|
||||
if (is_qla8032(ha) ||
|
||||
(is_qla8022(ha) && !ql4xdontresethba)) {
|
||||
ql4_printk(KERN_INFO, ha, "%s: HW State: "
|
||||
"NEED RESET!\n", __func__);
|
||||
set_bit(DPC_RESET_HA, &ha->dpc_flags);
|
||||
|
@ -2543,36 +2575,8 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha)
|
|||
qla4xxx_wake_dpc(ha);
|
||||
} else {
|
||||
/* Check firmware health */
|
||||
if (qla4_8xxx_check_fw_alive(ha)) {
|
||||
ql4_printk(KERN_INFO, ha, "disabling pause"
|
||||
" transmit on port 0 & 1.\n");
|
||||
qla4_82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x98,
|
||||
CRB_NIU_XG_PAUSE_CTL_P0 |
|
||||
CRB_NIU_XG_PAUSE_CTL_P1);
|
||||
halt_status = qla4_8xxx_rd_direct(ha,
|
||||
QLA8XXX_PEG_HALT_STATUS1);
|
||||
|
||||
if (QLA82XX_FWERROR_CODE(halt_status) == 0x67)
|
||||
ql4_printk(KERN_ERR, ha, "%s:"
|
||||
" Firmware aborted with"
|
||||
" error code 0x00006700."
|
||||
" Device is being reset\n",
|
||||
__func__);
|
||||
|
||||
/* Since we cannot change dev_state in interrupt
|
||||
* context, set appropriate DPC flag then wakeup
|
||||
* DPC */
|
||||
if (halt_status & HALT_STATUS_UNRECOVERABLE)
|
||||
set_bit(DPC_HA_UNRECOVERABLE,
|
||||
&ha->dpc_flags);
|
||||
else {
|
||||
ql4_printk(KERN_INFO, ha, "%s: detect "
|
||||
"abort needed!\n", __func__);
|
||||
set_bit(DPC_RESET_HA, &ha->dpc_flags);
|
||||
}
|
||||
qla4xxx_mailbox_premature_completion(ha);
|
||||
qla4xxx_wake_dpc(ha);
|
||||
}
|
||||
if (qla4_8xxx_check_fw_alive(ha))
|
||||
qla4_8xxx_process_fw_error(ha);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2654,9 +2658,8 @@ static void qla4xxx_timer(struct scsi_qla_host *ha)
|
|||
if (!pci_channel_offline(ha->pdev))
|
||||
pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w);
|
||||
|
||||
if (is_qla8022(ha)) {
|
||||
if (is_qla80XX(ha))
|
||||
qla4_8xxx_watchdog(ha);
|
||||
}
|
||||
|
||||
if (is_qla40XX(ha)) {
|
||||
/* Check for heartbeat interval. */
|
||||
|
@ -2955,9 +2958,9 @@ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha)
|
|||
goto recover_ha_init_adapter;
|
||||
}
|
||||
|
||||
/* For the ISP-82xx adapter, issue a stop_firmware if invoked
|
||||
/* For the ISP-8xxx adapter, issue a stop_firmware if invoked
|
||||
* from eh_host_reset or ioctl module */
|
||||
if (is_qla8022(ha) && !reset_chip &&
|
||||
if (is_qla80XX(ha) && !reset_chip &&
|
||||
test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags)) {
|
||||
|
||||
DEBUG2(ql4_printk(KERN_INFO, ha,
|
||||
|
@ -2980,13 +2983,13 @@ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha)
|
|||
}
|
||||
|
||||
/* Issue full chip reset if recovering from a catastrophic error,
|
||||
* or if stop_firmware fails for ISP-82xx.
|
||||
* or if stop_firmware fails for ISP-8xxx.
|
||||
* This is the default case for ISP-4xxx */
|
||||
if (is_qla40XX(ha) || reset_chip) {
|
||||
if (is_qla40XX(ha))
|
||||
goto chip_reset;
|
||||
|
||||
/* Check if 82XX firmware is alive or not
|
||||
/* Check if 8XXX firmware is alive or not
|
||||
* We may have arrived here from NEED_RESET
|
||||
* detection only */
|
||||
if (test_bit(AF_FW_RECOVERY, &ha->flags))
|
||||
|
@ -3041,7 +3044,7 @@ recover_ha_init_adapter:
|
|||
* Since we don't want to block the DPC for too long
|
||||
* with multiple resets in the same thread,
|
||||
* utilize DPC to retry */
|
||||
if (is_qla8022(ha)) {
|
||||
if (is_qla80XX(ha)) {
|
||||
ha->isp_ops->idc_lock(ha);
|
||||
dev_state = qla4_8xxx_rd_direct(ha,
|
||||
QLA8XXX_CRB_DEV_STATE);
|
||||
|
@ -3386,7 +3389,7 @@ static void qla4xxx_do_dpc(struct work_struct *work)
|
|||
/* post events to application */
|
||||
qla4xxx_do_work(ha);
|
||||
|
||||
if (is_qla8022(ha)) {
|
||||
if (is_qla80XX(ha)) {
|
||||
if (test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags)) {
|
||||
ha->isp_ops->idc_lock(ha);
|
||||
qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DEV_STATE,
|
||||
|
@ -3404,7 +3407,8 @@ static void qla4xxx_do_dpc(struct work_struct *work)
|
|||
(test_bit(DPC_RESET_HA, &ha->dpc_flags) ||
|
||||
test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) ||
|
||||
test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags))) {
|
||||
if (ql4xdontresethba) {
|
||||
if ((is_qla8022(ha) && ql4xdontresethba) ||
|
||||
(is_qla8032(ha) && qla4_83xx_idc_dontreset(ha))) {
|
||||
DEBUG2(printk("scsi%ld: %s: Don't Reset HBA\n",
|
||||
ha->host_no, __func__));
|
||||
clear_bit(DPC_RESET_HA, &ha->dpc_flags);
|
||||
|
@ -3514,7 +3518,7 @@ static void qla4xxx_free_adapter(struct scsi_qla_host *ha)
|
|||
/* Put firmware in known state */
|
||||
ha->isp_ops->reset_firmware(ha);
|
||||
|
||||
if (is_qla8022(ha)) {
|
||||
if (is_qla80XX(ha)) {
|
||||
ha->isp_ops->idc_lock(ha);
|
||||
qla4_8xxx_clear_drv_active(ha);
|
||||
ha->isp_ops->idc_unlock(ha);
|
||||
|
@ -3564,16 +3568,20 @@ int qla4_8xxx_iospace_config(struct scsi_qla_host *ha)
|
|||
/* Mapping of IO base pointer, door bell read and write pointer */
|
||||
|
||||
/* mapping of IO base pointer */
|
||||
ha->qla4_82xx_reg =
|
||||
(struct device_reg_82xx __iomem *)((uint8_t *)ha->nx_pcibase +
|
||||
0xbc000 + (ha->pdev->devfn << 11));
|
||||
if (is_qla8022(ha)) {
|
||||
ha->qla4_82xx_reg = (struct device_reg_82xx __iomem *)
|
||||
((uint8_t *)ha->nx_pcibase + 0xbc000 +
|
||||
(ha->pdev->devfn << 11));
|
||||
ha->nx_db_wr_ptr = (ha->pdev->devfn == 4 ? QLA82XX_CAM_RAM_DB1 :
|
||||
QLA82XX_CAM_RAM_DB2);
|
||||
} else if (is_qla8032(ha)) {
|
||||
ha->qla4_83xx_reg = (struct device_reg_83xx __iomem *)
|
||||
((uint8_t *)ha->nx_pcibase);
|
||||
}
|
||||
|
||||
db_base = pci_resource_start(pdev, 4); /* doorbell is on bar 4 */
|
||||
db_len = pci_resource_len(pdev, 4);
|
||||
|
||||
ha->nx_db_wr_ptr = (ha->pdev->devfn == 4 ? QLA82XX_CAM_RAM_DB1 :
|
||||
QLA82XX_CAM_RAM_DB2);
|
||||
|
||||
return 0;
|
||||
iospace_error_exit:
|
||||
return -ENOMEM;
|
||||
|
@ -3693,6 +3701,34 @@ static struct isp_operations qla4_82xx_isp_ops = {
|
|||
.process_mailbox_interrupt = qla4_82xx_process_mbox_intr,
|
||||
};
|
||||
|
||||
static struct isp_operations qla4_83xx_isp_ops = {
|
||||
.iospace_config = qla4_8xxx_iospace_config,
|
||||
.pci_config = qla4_8xxx_pci_config,
|
||||
.disable_intrs = qla4_83xx_disable_intrs,
|
||||
.enable_intrs = qla4_83xx_enable_intrs,
|
||||
.start_firmware = qla4_8xxx_load_risc,
|
||||
.restart_firmware = qla4_83xx_start_firmware,
|
||||
.intr_handler = qla4_83xx_intr_handler,
|
||||
.interrupt_service_routine = qla4_83xx_interrupt_service_routine,
|
||||
.need_reset = qla4_8xxx_need_reset,
|
||||
.reset_chip = qla4_83xx_isp_reset,
|
||||
.reset_firmware = qla4_8xxx_stop_firmware,
|
||||
.queue_iocb = qla4_83xx_queue_iocb,
|
||||
.complete_iocb = qla4_83xx_complete_iocb,
|
||||
.rd_shdw_req_q_out = qla4_83xx_rd_shdw_req_q_out,
|
||||
.rd_shdw_rsp_q_in = qla4_83xx_rd_shdw_rsp_q_in,
|
||||
.get_sys_info = qla4_8xxx_get_sys_info,
|
||||
.rd_reg_direct = qla4_83xx_rd_reg,
|
||||
.wr_reg_direct = qla4_83xx_wr_reg,
|
||||
.rd_reg_indirect = qla4_83xx_rd_reg_indirect,
|
||||
.wr_reg_indirect = qla4_83xx_wr_reg_indirect,
|
||||
.idc_lock = qla4_83xx_drv_lock,
|
||||
.idc_unlock = qla4_83xx_drv_unlock,
|
||||
.rom_lock_recovery = qla4_83xx_rom_lock_recovery,
|
||||
.queue_mailbox_command = qla4_83xx_queue_mbox_cmd,
|
||||
.process_mailbox_interrupt = qla4_83xx_process_mbox_intr,
|
||||
};
|
||||
|
||||
uint16_t qla4xxx_rd_shdw_req_q_out(struct scsi_qla_host *ha)
|
||||
{
|
||||
return (uint16_t)le32_to_cpu(ha->shadow_regs->req_q_out);
|
||||
|
@ -3703,6 +3739,11 @@ uint16_t qla4_82xx_rd_shdw_req_q_out(struct scsi_qla_host *ha)
|
|||
return (uint16_t)le32_to_cpu(readl(&ha->qla4_82xx_reg->req_q_out));
|
||||
}
|
||||
|
||||
uint16_t qla4_83xx_rd_shdw_req_q_out(struct scsi_qla_host *ha)
|
||||
{
|
||||
return (uint16_t)le32_to_cpu(readl(&ha->qla4_83xx_reg->req_q_out));
|
||||
}
|
||||
|
||||
uint16_t qla4xxx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha)
|
||||
{
|
||||
return (uint16_t)le32_to_cpu(ha->shadow_regs->rsp_q_in);
|
||||
|
@ -3713,6 +3754,11 @@ uint16_t qla4_82xx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha)
|
|||
return (uint16_t)le32_to_cpu(readl(&ha->qla4_82xx_reg->rsp_q_in));
|
||||
}
|
||||
|
||||
uint16_t qla4_83xx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha)
|
||||
{
|
||||
return (uint16_t)le32_to_cpu(readl(&ha->qla4_83xx_reg->rsp_q_in));
|
||||
}
|
||||
|
||||
static ssize_t qla4xxx_show_boot_eth_info(void *data, int type, char *buf)
|
||||
{
|
||||
struct scsi_qla_host *ha = data;
|
||||
|
@ -5085,6 +5131,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
|
|||
ha->pdev = pdev;
|
||||
ha->host = host;
|
||||
ha->host_no = host->host_no;
|
||||
ha->func_num = PCI_FUNC(ha->pdev->devfn);
|
||||
|
||||
pci_enable_pcie_error_reporting(pdev);
|
||||
|
||||
|
@ -5092,24 +5139,28 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
|
|||
if (is_qla8022(ha)) {
|
||||
ha->isp_ops = &qla4_82xx_isp_ops;
|
||||
ha->reg_tbl = (uint32_t *) qla4_82xx_reg_tbl;
|
||||
rwlock_init(&ha->hw_lock);
|
||||
ha->qdr_sn_window = -1;
|
||||
ha->ddr_mn_window = -1;
|
||||
ha->curr_window = 255;
|
||||
ha->func_num = PCI_FUNC(ha->pdev->devfn);
|
||||
nx_legacy_intr = &legacy_intr[ha->func_num];
|
||||
ha->nx_legacy_intr.int_vec_bit = nx_legacy_intr->int_vec_bit;
|
||||
ha->nx_legacy_intr.tgt_status_reg =
|
||||
nx_legacy_intr->tgt_status_reg;
|
||||
ha->nx_legacy_intr.tgt_mask_reg = nx_legacy_intr->tgt_mask_reg;
|
||||
ha->nx_legacy_intr.pci_int_reg = nx_legacy_intr->pci_int_reg;
|
||||
} else if (is_qla8032(ha)) {
|
||||
ha->isp_ops = &qla4_83xx_isp_ops;
|
||||
ha->reg_tbl = (uint32_t *)qla4_83xx_reg_tbl;
|
||||
} else {
|
||||
ha->isp_ops = &qla4xxx_isp_ops;
|
||||
}
|
||||
|
||||
/* Set EEH reset type to fundamental if required by hba */
|
||||
if (is_qla8022(ha))
|
||||
if (is_qla80XX(ha)) {
|
||||
rwlock_init(&ha->hw_lock);
|
||||
ha->pf_bit = ha->func_num << 16;
|
||||
/* Set EEH reset type to fundamental if required by hba */
|
||||
pdev->needs_freset = 1;
|
||||
}
|
||||
|
||||
/* Configure PCI I/O space. */
|
||||
ret = ha->isp_ops->iospace_config(ha);
|
||||
|
@ -5165,8 +5216,20 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
|
|||
if (ret)
|
||||
goto probe_failed;
|
||||
|
||||
if (is_qla8022(ha))
|
||||
(void) qla4_8xxx_get_flash_info(ha);
|
||||
if (is_qla80XX(ha))
|
||||
qla4_8xxx_get_flash_info(ha);
|
||||
|
||||
if (is_qla8032(ha)) {
|
||||
qla4_83xx_read_reset_template(ha);
|
||||
/*
|
||||
* NOTE: If ql4dontresethba==1, set IDC_CTRL DONTRESET_BIT0.
|
||||
* If DONRESET_BIT0 is set, drivers should not set dev_state
|
||||
* to NEED_RESET. But if NEED_RESET is set, drivers should
|
||||
* should honor the reset.
|
||||
*/
|
||||
if (ql4xdontresethba == 1)
|
||||
qla4_83xx_set_idc_dontreset(ha);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the Host adapter request/response queues and
|
||||
|
@ -5177,7 +5240,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
|
|||
while ((!test_bit(AF_ONLINE, &ha->flags)) &&
|
||||
init_retry_count++ < MAX_INIT_RETRIES) {
|
||||
|
||||
if (is_qla8022(ha)) {
|
||||
if (is_qla80XX(ha)) {
|
||||
ha->isp_ops->idc_lock(ha);
|
||||
dev_state = qla4_8xxx_rd_direct(ha,
|
||||
QLA82XX_CRB_DEV_STATE);
|
||||
|
@ -5201,7 +5264,8 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
|
|||
if (!test_bit(AF_ONLINE, &ha->flags)) {
|
||||
ql4_printk(KERN_WARNING, ha, "Failed to initialize adapter\n");
|
||||
|
||||
if (is_qla8022(ha) && ql4xdontresethba) {
|
||||
if ((is_qla8022(ha) && ql4xdontresethba) ||
|
||||
(is_qla8032(ha) && qla4_83xx_idc_dontreset(ha))) {
|
||||
/* Put the device in failed state. */
|
||||
DEBUG2(printk(KERN_ERR "HW STATE: FAILED\n"));
|
||||
ha->isp_ops->idc_lock(ha);
|
||||
|
@ -5233,7 +5297,8 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
|
|||
goto remove_host;
|
||||
}
|
||||
|
||||
/* For ISP-82XX, request_irqs is called in qla4_8xxx_load_risc
|
||||
/*
|
||||
* For ISP-8XXX, request_irqs is called in qla4_8xxx_load_risc
|
||||
* (which is called indirectly by qla4xxx_initialize_adapter),
|
||||
* so that irqs will be registered after crbinit but before
|
||||
* mbx_intr_enable.
|
||||
|
@ -5793,7 +5858,16 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd)
|
|||
|
||||
ha = to_qla_host(cmd->device->host);
|
||||
|
||||
if (ql4xdontresethba) {
|
||||
if (is_qla8032(ha) && ql4xdontresethba)
|
||||
qla4_83xx_set_idc_dontreset(ha);
|
||||
|
||||
/*
|
||||
* For ISP8324, if IDC_CTRL DONTRESET_BIT0 is set by other
|
||||
* protocol drivers, we should not set device_state to
|
||||
* NEED_RESET
|
||||
*/
|
||||
if (ql4xdontresethba ||
|
||||
(is_qla8032(ha) && qla4_83xx_idc_dontreset(ha))) {
|
||||
DEBUG2(printk("scsi%ld: %s: Don't Reset HBA\n",
|
||||
ha->host_no, __func__));
|
||||
|
||||
|
@ -5817,7 +5891,7 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd)
|
|||
}
|
||||
|
||||
if (!test_bit(DPC_RESET_HA, &ha->dpc_flags)) {
|
||||
if (is_qla8022(ha))
|
||||
if (is_qla80XX(ha))
|
||||
set_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags);
|
||||
else
|
||||
set_bit(DPC_RESET_HA, &ha->dpc_flags);
|
||||
|
@ -5912,7 +5986,7 @@ static int qla4xxx_host_reset(struct Scsi_Host *shost, int reset_type)
|
|||
break;
|
||||
case SCSI_FIRMWARE_RESET:
|
||||
if (!test_bit(DPC_RESET_HA, &ha->dpc_flags)) {
|
||||
if (is_qla8022(ha))
|
||||
if (is_qla80XX(ha))
|
||||
/* set firmware context reset */
|
||||
set_bit(DPC_RESET_HA_FW_CONTEXT,
|
||||
&ha->dpc_flags);
|
||||
|
@ -6150,7 +6224,7 @@ qla4xxx_pci_slot_reset(struct pci_dev *pdev)
|
|||
|
||||
ha->isp_ops->disable_intrs(ha);
|
||||
|
||||
if (is_qla8022(ha)) {
|
||||
if (is_qla80XX(ha)) {
|
||||
if (qla4_8xxx_error_recovery(ha) == QLA_SUCCESS) {
|
||||
ret = PCI_ERS_RESULT_RECOVERED;
|
||||
goto exit_slot_reset;
|
||||
|
@ -6216,6 +6290,12 @@ static struct pci_device_id qla4xxx_pci_tbl[] = {
|
|||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_QLOGIC,
|
||||
.device = PCI_DEVICE_ID_QLOGIC_ISP8324,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
},
|
||||
{0, 0},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, qla4xxx_pci_tbl);
|
||||
|
|
Loading…
Reference in New Issue