提交 f4f5df23 编写于 作者: V Vikas Chaudhary 提交者: James Bottomley

[SCSI] qla4xxx: Added support for ISP82XX

Signed-off-by: Vikas Chaudhary <Vikas Chaudhary@qlogic.com>
Signed-off-by: NKaren Higgins <karen.higgins@qlogic.com>
Signed-off-by: NRavi Anand <ravi.anand@qlogic.com>
Signed-off-by: NJames Bottomley <James.Bottomley@suse.de>
上级 dbaf82ec
config SCSI_QLA_ISCSI
tristate "QLogic ISP4XXX host adapter family support"
depends on PCI && SCSI && NET
tristate "QLogic ISP4XXX and ISP82XX host adapter family support"
depends on PCI && SCSI
select SCSI_ISCSI_ATTRS
---help---
This driver supports the QLogic 40xx (ISP4XXX) iSCSI host
adapter family.
This driver supports the QLogic 40xx (ISP4XXX) and 8022 (ISP82XX)
iSCSI host adapter family.
qla4xxx-y := ql4_os.o ql4_init.o ql4_mbx.o ql4_iocb.o ql4_isr.o \
ql4_nvram.o ql4_dbg.o
ql4_nx.o ql4_nvram.o ql4_dbg.o
obj-$(CONFIG_SCSI_QLA_ISCSI) += qla4xxx.o
......@@ -33,6 +33,8 @@
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_iscsi.h>
#include "ql4_dbg.h"
#include "ql4_nx.h"
#ifndef PCI_DEVICE_ID_QLOGIC_ISP4010
#define PCI_DEVICE_ID_QLOGIC_ISP4010 0x4010
......@@ -46,6 +48,10 @@
#define PCI_DEVICE_ID_QLOGIC_ISP4032 0x4032
#endif
#ifndef PCI_DEVICE_ID_QLOGIC_ISP8022
#define PCI_DEVICE_ID_QLOGIC_ISP8022 0x8022
#endif
#define QLA_SUCCESS 0
#define QLA_ERROR 1
......@@ -85,15 +91,22 @@
#define BIT_30 0x40000000
#define BIT_31 0x80000000
/**
* Macros to help code, maintain, etc.
**/
#define ql4_printk(level, ha, format, arg...) \
dev_printk(level , &((ha)->pdev->dev) , format , ## arg)
/*
* Host adapter default definitions
***********************************/
#define MAX_HBAS 16
#define MAX_BUSES 1
#define MAX_TARGETS (MAX_PRST_DEV_DB_ENTRIES + MAX_DEV_DB_ENTRIES)
#define MAX_TARGETS MAX_DEV_DB_ENTRIES
#define MAX_LUNS 0xffff
#define MAX_AEN_ENTRIES 256 /* should be > EXT_DEF_MAX_AEN_QUEUE */
#define MAX_DDB_ENTRIES (MAX_PRST_DEV_DB_ENTRIES + MAX_DEV_DB_ENTRIES)
#define MAX_DDB_ENTRIES MAX_DEV_DB_ENTRIES
#define MAX_PDU_ENTRIES 32
#define INVALID_ENTRY 0xFFFF
#define MAX_CMDS_TO_RISC 1024
......@@ -134,7 +147,7 @@
#define SOFT_RESET_TOV 30
#define RESET_INTR_TOV 3
#define SEMAPHORE_TOV 10
#define ADAPTER_INIT_TOV 120
#define ADAPTER_INIT_TOV 30
#define ADAPTER_RESET_TOV 180
#define EXTEND_CMD_TOV 60
#define WAIT_CMD_TOV 30
......@@ -184,8 +197,6 @@ struct srb {
uint16_t iocb_tov;
uint16_t iocb_cnt; /* Number of used iocbs */
uint16_t cc_stat;
u_long r_start; /* Time we recieve a cmd from OS */
u_long u_start; /* Time when we handed the cmd to F/W */
/* Used for extended sense / status continuation */
uint8_t *req_sense_ptr;
......@@ -221,7 +232,6 @@ struct ddb_entry {
unsigned long dev_scan_wait_to_start_relogin;
unsigned long dev_scan_wait_to_complete_relogin;
uint16_t os_target_id; /* Target ID */
uint16_t fw_ddb_index; /* DDB firmware index */
uint16_t options;
uint32_t fw_ddb_device_state; /* F/W Device State -- see ql4_fw.h */
......@@ -285,6 +295,67 @@ struct ddb_entry {
#include "ql4_fw.h"
#include "ql4_nvram.h"
struct ql82xx_hw_data {
/* Offsets for flash/nvram access (set to ~0 if not used). */
uint32_t flash_conf_off;
uint32_t flash_data_off;
uint32_t fdt_wrt_disable;
uint32_t fdt_erase_cmd;
uint32_t fdt_block_size;
uint32_t fdt_unprotect_sec_cmd;
uint32_t fdt_protect_sec_cmd;
uint32_t flt_region_flt;
uint32_t flt_region_fdt;
uint32_t flt_region_boot;
uint32_t flt_region_bootload;
uint32_t flt_region_fw;
uint32_t reserved;
};
struct qla4_8xxx_legacy_intr_set {
uint32_t int_vec_bit;
uint32_t tgt_status_reg;
uint32_t tgt_mask_reg;
uint32_t pci_int_reg;
};
/* MSI-X Support */
#define QLA_MSIX_DEFAULT 0x00
#define QLA_MSIX_RSP_Q 0x01
#define QLA_MSIX_ENTRIES 2
#define QLA_MIDX_DEFAULT 0
#define QLA_MIDX_RSP_Q 1
struct ql4_msix_entry {
int have_irq;
uint16_t msix_vector;
uint16_t msix_entry;
};
/*
* ISP Operations
*/
struct isp_operations {
int (*iospace_config) (struct scsi_qla_host *ha);
void (*pci_config) (struct scsi_qla_host *);
void (*disable_intrs) (struct scsi_qla_host *);
void (*enable_intrs) (struct scsi_qla_host *);
int (*start_firmware) (struct scsi_qla_host *);
irqreturn_t (*intr_handler) (int , void *);
void (*interrupt_service_routine) (struct scsi_qla_host *, uint32_t);
int (*reset_chip) (struct scsi_qla_host *);
int (*reset_firmware) (struct scsi_qla_host *);
void (*queue_iocb) (struct scsi_qla_host *);
void (*complete_iocb) (struct scsi_qla_host *);
uint16_t (*rd_shdw_req_q_out) (struct scsi_qla_host *);
uint16_t (*rd_shdw_rsp_q_in) (struct scsi_qla_host *);
int (*get_sys_info) (struct scsi_qla_host *);
};
/*
* Linux Host Adapter structure
*/
......@@ -296,28 +367,39 @@ struct scsi_qla_host {
#define AF_INIT_DONE 1 /* 0x00000002 */
#define AF_MBOX_COMMAND 2 /* 0x00000004 */
#define AF_MBOX_COMMAND_DONE 3 /* 0x00000008 */
#define AF_DPC_SCHEDULED 5 /* 0x00000020 */
#define AF_INTERRUPTS_ON 6 /* 0x00000040 */
#define AF_GET_CRASH_RECORD 7 /* 0x00000080 */
#define AF_LINK_UP 8 /* 0x00000100 */
#define AF_IRQ_ATTACHED 10 /* 0x00000400 */
#define AF_DISABLE_ACB_COMPLETE 11 /* 0x00000800 */
#define AF_HBA_GOING_AWAY 12 /* 0x00001000 */
#define AF_INTx_ENABLED 15 /* 0x00008000 */
#define AF_MSI_ENABLED 16 /* 0x00010000 */
#define AF_MSIX_ENABLED 17 /* 0x00020000 */
#define AF_MBOX_COMMAND_NOPOLL 18 /* 0x00040000 */
unsigned long dpc_flags;
#define DPC_RESET_HA 1 /* 0x00000002 */
#define DPC_RETRY_RESET_HA 2 /* 0x00000004 */
#define DPC_RELOGIN_DEVICE 3 /* 0x00000008 */
#define DPC_RESET_HA_DESTROY_DDB_LIST 4 /* 0x00000010 */
#define DPC_RESET_HA_FW_CONTEXT 4 /* 0x00000010 */
#define DPC_RESET_HA_INTR 5 /* 0x00000020 */
#define DPC_ISNS_RESTART 7 /* 0x00000080 */
#define DPC_AEN 9 /* 0x00000200 */
#define DPC_GET_DHCP_IP_ADDR 15 /* 0x00008000 */
#define DPC_LINK_CHANGED 18 /* 0x00040000 */
#define DPC_RESET_ACTIVE 20 /* 0x00040000 */
#define DPC_HA_UNRECOVERABLE 21 /* 0x00080000 ISP-82xx only*/
#define DPC_HA_NEED_QUIESCENT 22 /* 0x00100000 ISP-82xx only*/
struct Scsi_Host *host; /* pointer to host data */
uint32_t tot_ddbs;
uint16_t iocb_cnt;
uint16_t iocb_cnt;
/* SRB cache. */
#define SRB_MIN_REQ 128
......@@ -332,14 +414,13 @@ struct scsi_qla_host {
#define MIN_IOBASE_LEN 0x100
uint16_t req_q_count;
uint8_t rsvd1[2];
unsigned long host_no;
/* NVRAM registers */
struct eeprom_data *nvram;
spinlock_t hardware_lock ____cacheline_aligned;
uint32_t eeprom_cmd_data;
uint32_t eeprom_cmd_data;
/* Counters for general statistics */
uint64_t isr_count;
......@@ -375,7 +456,6 @@ struct scsi_qla_host {
uint8_t alias[32];
uint8_t name_string[256];
uint8_t heartbeat_interval;
uint8_t rsvd;
/* --- From FlashSysInfo --- */
uint8_t my_mac[MAC_ADDR_LEN];
......@@ -469,6 +549,40 @@ struct scsi_qla_host {
struct in6_addr ipv6_addr0;
struct in6_addr ipv6_addr1;
struct in6_addr ipv6_default_router_addr;
/* qla82xx specific fields */
struct device_reg_82xx __iomem *qla4_8xxx_reg; /* Base I/O address */
unsigned long nx_pcibase; /* Base I/O address */
uint8_t *nx_db_rd_ptr; /* Doorbell read pointer */
unsigned long nx_db_wr_ptr; /* Door bell write pointer */
unsigned long first_page_group_start;
unsigned long first_page_group_end;
uint32_t crb_win;
uint32_t curr_window;
uint32_t ddr_mn_window;
unsigned long mn_win_crb;
unsigned long ms_win_crb;
int qdr_sn_window;
rwlock_t hw_lock;
uint16_t func_num;
int link_width;
struct qla4_8xxx_legacy_intr_set nx_legacy_intr;
u32 nx_crb_mask;
uint8_t revision_id;
uint32_t fw_heartbeat_counter;
struct isp_operations *isp_ops;
struct ql82xx_hw_data hw;
struct ql4_msix_entry msix_entries[QLA_MSIX_ENTRIES];
uint32_t nx_dev_init_timeout;
uint32_t nx_reset_timeout;
struct completion mbx_intr_comp;
};
static inline int is_ipv4_enabled(struct scsi_qla_host *ha)
......@@ -496,6 +610,11 @@ static inline int is_qla4032(struct scsi_qla_host *ha)
return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP4032;
}
static inline int is_qla8022(struct scsi_qla_host *ha)
{
return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8022;
}
static inline int adapter_up(struct scsi_qla_host *ha)
{
return (test_bit(AF_ONLINE, &ha->flags) != 0) &&
......
......@@ -11,7 +11,7 @@
#define MAX_PRST_DEV_DB_ENTRIES 64
#define MIN_DISC_DEV_DB_ENTRY MAX_PRST_DEV_DB_ENTRIES
#define MAX_DEV_DB_ENTRIES 512
#define MAX_DEV_DB_ENTRIES 512
/*************************************************************************
*
......@@ -37,6 +37,33 @@ struct host_mem_cfg_regs {
__le32 rsrvd1[31]; /* 0x84-0xFF */
};
/*
* ISP 82xx I/O Register Set structure definitions.
*/
struct device_reg_82xx {
__le32 req_q_out; /* 0x0000 (R): Request Queue out-Pointer. */
__le32 reserve1[63]; /* Request Queue out-Pointer. (64 * 4) */
__le32 rsp_q_in; /* 0x0100 (R/W): Response Queue In-Pointer. */
__le32 reserve2[63]; /* Response Queue In-Pointer. */
__le32 rsp_q_out; /* 0x0200 (R/W): Response Queue Out-Pointer. */
__le32 reserve3[63]; /* Response Queue Out-Pointer. */
__le32 mailbox_in[8]; /* 0x0300 (R/W): Mail box In registers */
__le32 reserve4[24];
__le32 hint; /* 0x0380 (R/W): Host interrupt register */
#define HINT_MBX_INT_PENDING BIT_0
__le32 reserve5[31];
__le32 mailbox_out[8]; /* 0x0400 (R): Mail box Out registers */
__le32 reserve6[56];
__le32 host_status; /* Offset 0x500 (R): host status */
#define HSRX_RISC_MB_INT BIT_0 /* RISC to Host Mailbox interrupt */
#define HSRX_RISC_IOCB_INT BIT_1 /* RISC to Host IOCB interrupt */
__le32 host_int; /* Offset 0x0504 (R/W): Interrupt status. */
#define ISRX_82XX_RISC_INT BIT_0 /* RISC interrupt. */
};
/* remote register set (access via PCI memory read/write) */
struct isp_reg {
#define MBOX_REG_COUNT 8
......@@ -206,6 +233,79 @@ union external_hw_config_reg {
uint32_t Asuint32_t;
};
/* 82XX Support start */
/* 82xx Default FLT Addresses */
#define FA_FLASH_LAYOUT_ADDR_82 0xFC400
#define FA_FLASH_DESCR_ADDR_82 0xFC000
#define FA_BOOT_LOAD_ADDR_82 0x04000
#define FA_BOOT_CODE_ADDR_82 0x20000
#define FA_RISC_CODE_ADDR_82 0x40000
#define FA_GOLD_RISC_CODE_ADDR_82 0x80000
/* Flash Description Table */
struct qla_fdt_layout {
uint8_t sig[4];
uint16_t version;
uint16_t len;
uint16_t checksum;
uint8_t unused1[2];
uint8_t model[16];
uint16_t man_id;
uint16_t id;
uint8_t flags;
uint8_t erase_cmd;
uint8_t alt_erase_cmd;
uint8_t wrt_enable_cmd;
uint8_t wrt_enable_bits;
uint8_t wrt_sts_reg_cmd;
uint8_t unprotect_sec_cmd;
uint8_t read_man_id_cmd;
uint32_t block_size;
uint32_t alt_block_size;
uint32_t flash_size;
uint32_t wrt_enable_data;
uint8_t read_id_addr_len;
uint8_t wrt_disable_bits;
uint8_t read_dev_id_len;
uint8_t chip_erase_cmd;
uint16_t read_timeout;
uint8_t protect_sec_cmd;
uint8_t unused2[65];
};
/* Flash Layout Table */
struct qla_flt_location {
uint8_t sig[4];
uint16_t start_lo;
uint16_t start_hi;
uint8_t version;
uint8_t unused[5];
uint16_t checksum;
};
struct qla_flt_header {
uint16_t version;
uint16_t length;
uint16_t checksum;
uint16_t unused;
};
/* 82xx FLT Regions */
#define FLT_REG_FDT 0x1a
#define FLT_REG_FLT 0x1c
#define FLT_REG_BOOTLOAD_82 0x72
#define FLT_REG_FW_82 0x74
#define FLT_REG_GOLD_FW_82 0x75
#define FLT_REG_BOOT_CODE_82 0x78
struct qla_flt_region {
uint32_t code;
uint32_t size;
uint32_t start;
uint32_t end;
};
/*************************************************************************
*
* Mailbox Commands Structures and Definitions
......@@ -215,6 +315,10 @@ union external_hw_config_reg {
/* Mailbox command definitions */
#define MBOX_CMD_ABOUT_FW 0x0009
#define MBOX_CMD_PING 0x000B
#define MBOX_CMD_ENABLE_INTRS 0x0010
#define INTR_DISABLE 0
#define INTR_ENABLE 1
#define MBOX_CMD_STOP_FW 0x0014
#define MBOX_CMD_ABORT_TASK 0x0015
#define MBOX_CMD_LUN_RESET 0x0016
#define MBOX_CMD_TARGET_WARM_RESET 0x0017
......@@ -243,6 +347,7 @@ union external_hw_config_reg {
#define DDB_DS_LOGIN_IN_PROCESS 0x07
#define MBOX_CMD_GET_FW_STATE 0x0069
#define MBOX_CMD_GET_INIT_FW_CTRL_BLOCK_DEFAULTS 0x006A
#define MBOX_CMD_GET_SYS_INFO 0x0078
#define MBOX_CMD_RESTORE_FACTORY_DEFAULTS 0x0087
#define MBOX_CMD_SET_ACB 0x0088
#define MBOX_CMD_GET_ACB 0x0089
......@@ -318,6 +423,15 @@ union external_hw_config_reg {
#define MBOX_ASTS_IPSEC_SYSTEM_FATAL_ERROR 0x8022
#define MBOX_ASTS_SUBNET_STATE_CHANGE 0x8027
/* ACB State Defines */
#define ACB_STATE_UNCONFIGURED 0x00
#define ACB_STATE_INVALID 0x01
#define ACB_STATE_ACQUIRING 0x02
#define ACB_STATE_TENTATIVE 0x03
#define ACB_STATE_DEPRICATED 0x04
#define ACB_STATE_VALID 0x05
#define ACB_STATE_DISABLING 0x06
/*************************************************************************/
/* Host Adapter Initialization Control Block (from host) */
......@@ -558,6 +672,20 @@ struct flash_sys_info {
uint32_t reserved1[39]; /* 170-1ff */
}; /* 200 */
struct mbx_sys_info {
uint8_t board_id_str[16]; /* Keep board ID string first */
/* in this structure for GUI. */
uint16_t board_id; /* board ID code */
uint16_t phys_port_cnt; /* number of physical network ports */
uint16_t port_num; /* network port for this PCI function */
/* (port 0 is first port) */
uint8_t mac_addr[6]; /* MAC address for this PCI function */
uint32_t iscsi_pci_func_cnt; /* number of iSCSI PCI functions */
uint32_t pci_func; /* this PCI function */
unsigned char serial_number[16]; /* serial number string */
uint8_t reserved[16];
};
struct crash_record {
uint16_t fw_major_version; /* 00 - 01 */
uint16_t fw_minor_version; /* 02 - 03 */
......@@ -814,4 +942,13 @@ struct passthru_status {
uint8_t res4[16]; /* 30-3F */
};
/*
* ISP queue - response queue entry definition.
*/
struct response {
uint8_t data[60];
uint32_t signature;
#define RESPONSE_PROCESSED 0xDEADDEAD /* Signature */
};
#endif /* _QLA4X_FW_H */
......@@ -10,31 +10,32 @@
struct iscsi_cls_conn;
void qla4xxx_hw_reset(struct scsi_qla_host *ha);
int qla4xxx_hw_reset(struct scsi_qla_host *ha);
int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a);
int qla4xxx_send_tgts(struct scsi_qla_host *ha, char *ip, uint16_t port);
int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb);
int qla4xxx_initialize_adapter(struct scsi_qla_host * ha,
int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb *srb);
int qla4xxx_initialize_adapter(struct scsi_qla_host *ha,
uint8_t renew_ddb_list);
int qla4xxx_soft_reset(struct scsi_qla_host *ha);
irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id);
void qla4xxx_free_ddb_list(struct scsi_qla_host * ha);
void qla4xxx_process_aen(struct scsi_qla_host * ha, uint8_t process_aen);
void qla4xxx_free_ddb_list(struct scsi_qla_host *ha);
void qla4xxx_free_ddb(struct scsi_qla_host *ha, struct ddb_entry *ddb_entry);
void qla4xxx_process_aen(struct scsi_qla_host *ha, uint8_t process_aen);
int qla4xxx_get_dhcp_ip_address(struct scsi_qla_host * ha);
int qla4xxx_relogin_device(struct scsi_qla_host * ha,
struct ddb_entry * ddb_entry);
int qla4xxx_get_dhcp_ip_address(struct scsi_qla_host *ha);
int qla4xxx_relogin_device(struct scsi_qla_host *ha,
struct ddb_entry *ddb_entry);
int qla4xxx_abort_task(struct scsi_qla_host *ha, struct srb *srb);
int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry,
int qla4xxx_reset_lun(struct scsi_qla_host *ha, struct ddb_entry *ddb_entry,
int lun);
int qla4xxx_reset_target(struct scsi_qla_host * ha,
struct ddb_entry * ddb_entry);
int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr,
int qla4xxx_reset_target(struct scsi_qla_host *ha,
struct ddb_entry *ddb_entry);
int qla4xxx_get_flash(struct scsi_qla_host *ha, dma_addr_t dma_addr,
uint32_t offset, uint32_t len);
int qla4xxx_get_firmware_status(struct scsi_qla_host * ha);
int qla4xxx_get_firmware_state(struct scsi_qla_host * ha);
int qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha);
int qla4xxx_get_firmware_status(struct scsi_qla_host *ha);
int qla4xxx_get_firmware_state(struct scsi_qla_host *ha);
int qla4xxx_initialize_fw_cb(struct scsi_qla_host *ha);
/* FIXME: Goodness! this really wants a small struct to hold the
* parameters. On x86 the args will get passed on the stack! */
......@@ -54,20 +55,20 @@ int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index,
void qla4xxx_mark_device_missing(struct scsi_qla_host *ha,
struct ddb_entry *ddb_entry);
u16 rd_nvram_word(struct scsi_qla_host * ha, int offset);
void qla4xxx_get_crash_record(struct scsi_qla_host * ha);
u16 rd_nvram_word(struct scsi_qla_host *ha, int offset);
void qla4xxx_get_crash_record(struct scsi_qla_host *ha);
struct ddb_entry *qla4xxx_alloc_sess(struct scsi_qla_host *ha);
int qla4xxx_add_sess(struct ddb_entry *);
void qla4xxx_destroy_sess(struct ddb_entry *ddb_entry);
int qla4xxx_is_nvram_configuration_valid(struct scsi_qla_host * ha);
int qla4xxx_is_nvram_configuration_valid(struct scsi_qla_host *ha);
int qla4xxx_get_fw_version(struct scsi_qla_host * ha);
void qla4xxx_interrupt_service_routine(struct scsi_qla_host * ha,
void qla4xxx_interrupt_service_routine(struct scsi_qla_host *ha,
uint32_t intr_status);
int qla4xxx_init_rings(struct scsi_qla_host * ha);
struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha,
uint32_t index);
int qla4xxx_init_rings(struct scsi_qla_host *ha);
void qla4xxx_srb_compl(struct kref *ref);
int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host * ha);
struct srb *qla4xxx_del_from_active_array(struct scsi_qla_host *ha,
uint32_t index);
int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host *ha);
int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
uint32_t state, uint32_t conn_error);
void qla4xxx_dump_buffer(void *b, uint32_t size);
......@@ -75,8 +76,65 @@ int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
struct ddb_entry *ddb_entry, int lun, uint16_t mrkr_mod);
int qla4_is_relogin_allowed(struct scsi_qla_host *ha, uint32_t conn_err);
int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
uint8_t outCount, uint32_t *mbx_cmd, uint32_t *mbx_sts);
void qla4xxx_queue_iocb(struct scsi_qla_host *ha);
void qla4xxx_complete_iocb(struct scsi_qla_host *ha);
int qla4xxx_get_sys_info(struct scsi_qla_host *ha);
int qla4xxx_iospace_config(struct scsi_qla_host *ha);
void qla4xxx_pci_config(struct scsi_qla_host *ha);
int qla4xxx_start_firmware(struct scsi_qla_host *ha);
irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id);
uint16_t qla4xxx_rd_shdw_req_q_out(struct scsi_qla_host *ha);
uint16_t qla4xxx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha);
int qla4xxx_request_irqs(struct scsi_qla_host *ha);
void qla4xxx_free_irqs(struct scsi_qla_host *ha);
void qla4xxx_process_response_queue(struct scsi_qla_host *ha);
void qla4xxx_wake_dpc(struct scsi_qla_host *ha);
void qla4xxx_get_conn_event_log(struct scsi_qla_host *ha);
void qla4_8xxx_pci_config(struct scsi_qla_host *);
int qla4_8xxx_iospace_config(struct scsi_qla_host *ha);
int qla4_8xxx_load_risc(struct scsi_qla_host *);
irqreturn_t qla4_8xxx_intr_handler(int irq, void *dev_id);
void qla4_8xxx_queue_iocb(struct scsi_qla_host *ha);
void qla4_8xxx_complete_iocb(struct scsi_qla_host *ha);
int qla4_8xxx_crb_win_lock(struct scsi_qla_host *);
void qla4_8xxx_crb_win_unlock(struct scsi_qla_host *);
int qla4_8xxx_pci_get_crb_addr_2M(struct scsi_qla_host *, ulong *);
void qla4_8xxx_wr_32(struct scsi_qla_host *, ulong, u32);
int qla4_8xxx_rd_32(struct scsi_qla_host *, ulong);
int qla4_8xxx_pci_mem_read_2M(struct scsi_qla_host *, u64, void *, int);
int qla4_8xxx_pci_mem_write_2M(struct scsi_qla_host *ha, u64, void *, int);
int qla4_8xxx_isp_reset(struct scsi_qla_host *ha);
void qla4_8xxx_interrupt_service_routine(struct scsi_qla_host *ha,
uint32_t intr_status);
uint16_t qla4_8xxx_rd_shdw_req_q_out(struct scsi_qla_host *ha);
uint16_t qla4_8xxx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha);
int qla4_8xxx_get_sys_info(struct scsi_qla_host *ha);
void qla4_8xxx_watchdog(struct scsi_qla_host *ha);
int qla4_8xxx_stop_firmware(struct scsi_qla_host *ha);
int qla4_8xxx_get_flash_info(struct scsi_qla_host *ha);
void qla4_8xxx_enable_intrs(struct scsi_qla_host *ha);
void qla4_8xxx_disable_intrs(struct scsi_qla_host *ha);
int qla4_8xxx_enable_msix(struct scsi_qla_host *ha);
void qla4_8xxx_disable_msix(struct scsi_qla_host *ha);
irqreturn_t qla4_8xxx_msi_handler(int irq, void *dev_id);
irqreturn_t qla4_8xxx_default_intr_handler(int irq, void *dev_id);
irqreturn_t qla4_8xxx_msix_rsp_q(int irq, void *dev_id);
void qla4xxx_mark_all_devices_missing(struct scsi_qla_host *ha);
void qla4xxx_dead_adapter_cleanup(struct scsi_qla_host *ha);
int qla4_8xxx_idc_lock(struct scsi_qla_host *ha);
void qla4_8xxx_idc_unlock(struct scsi_qla_host *ha);
int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha);
void qla4_8xxx_need_qsnt_handler(struct scsi_qla_host *ha);
void qla4_8xxx_clear_drv_active(struct scsi_qla_host *ha);
extern int ql4xextended_error_logging;
extern int ql4xdiscoverywait;
extern int ql4xdontresethba;
extern int ql4_mod_unload;
extern int ql4xenablemsix;
#endif /* _QLA4x_GBL_H */
......@@ -11,8 +11,8 @@
#include "ql4_dbg.h"
#include "ql4_inline.h"
static struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha,
uint32_t fw_ddb_index);
static struct ddb_entry *qla4xxx_alloc_ddb(struct scsi_qla_host *ha,
uint32_t fw_ddb_index);
static void ql4xxx_set_mac_number(struct scsi_qla_host *ha)
{
......@@ -51,8 +51,8 @@ static void ql4xxx_set_mac_number(struct scsi_qla_host *ha)
* This routine deallocates and unlinks the specified ddb_entry from the
* adapter's
**/
static void qla4xxx_free_ddb(struct scsi_qla_host *ha,
struct ddb_entry *ddb_entry)
void qla4xxx_free_ddb(struct scsi_qla_host *ha,
struct ddb_entry *ddb_entry)
{
/* Remove device entry from list */
list_del_init(&ddb_entry->list);
......@@ -85,6 +85,25 @@ void qla4xxx_free_ddb_list(struct scsi_qla_host *ha)
}
}
/**
* qla4xxx_init_response_q_entries() - Initializes response queue entries.
* @ha: HA context
*
* Beginning of request ring has initialization control block already built
* by nvram config routine.
**/
static void qla4xxx_init_response_q_entries(struct scsi_qla_host *ha)
{
uint16_t cnt;
struct response *pkt;
pkt = (struct response *)ha->response_ptr;
for (cnt = 0; cnt < RESPONSE_QUEUE_DEPTH; cnt++) {
pkt->signature = RESPONSE_PROCESSED;
pkt++;
}
}
/**
* qla4xxx_init_rings - initialize hw queues
* @ha: pointer to host adapter structure.
......@@ -109,19 +128,31 @@ int qla4xxx_init_rings(struct scsi_qla_host *ha)
ha->response_out = 0;
ha->response_ptr = &ha->response_ring[ha->response_out];
/*
* Initialize DMA Shadow registers. The firmware is really supposed to
* take care of this, but on some uniprocessor systems, the shadow
* registers aren't cleared-- causing the interrupt_handler to think
* there are responses to be processed when there aren't.
*/
ha->shadow_regs->req_q_out = __constant_cpu_to_le32(0);
ha->shadow_regs->rsp_q_in = __constant_cpu_to_le32(0);
wmb();
if (is_qla8022(ha)) {
writel(0,
(unsigned long __iomem *)&ha->qla4_8xxx_reg->req_q_out);
writel(0,
(unsigned long __iomem *)&ha->qla4_8xxx_reg->rsp_q_in);
writel(0,
(unsigned long __iomem *)&ha->qla4_8xxx_reg->rsp_q_out);
} else {
/*
* Initialize DMA Shadow registers. The firmware is really
* supposed to take care of this, but on some uniprocessor
* systems, the shadow registers aren't cleared-- causing
* the interrupt_handler to think there are responses to be
* processed when there aren't.
*/
ha->shadow_regs->req_q_out = __constant_cpu_to_le32(0);
ha->shadow_regs->rsp_q_in = __constant_cpu_to_le32(0);
wmb();
writel(0, &ha->reg->req_q_in);
writel(0, &ha->reg->rsp_q_out);
readl(&ha->reg->rsp_q_out);
writel(0, &ha->reg->req_q_in);
writel(0, &ha->reg->rsp_q_out);
readl(&ha->reg->rsp_q_out);
}
qla4xxx_init_response_q_entries(ha);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
......@@ -129,11 +160,11 @@ int qla4xxx_init_rings(struct scsi_qla_host *ha)
}
/**
* qla4xxx_validate_mac_address - validate adapter MAC address(es)
* qla4xxx_get_sys_info - validate adapter MAC address(es)
* @ha: pointer to host adapter structure.
*
**/
static int qla4xxx_validate_mac_address(struct scsi_qla_host *ha)
int qla4xxx_get_sys_info(struct scsi_qla_host *ha)
{
struct flash_sys_info *sys_info;
dma_addr_t sys_info_dma;
......@@ -145,7 +176,7 @@ static int qla4xxx_validate_mac_address(struct scsi_qla_host *ha)
DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n",
ha->host_no, __func__));
goto exit_validate_mac_no_free;
goto exit_get_sys_info_no_free;
}
memset(sys_info, 0, sizeof(*sys_info));
......@@ -155,7 +186,7 @@ static int qla4xxx_validate_mac_address(struct scsi_qla_host *ha)
DEBUG2(printk("scsi%ld: %s: get_flash FLASH_OFFSET_SYS_INFO "
"failed\n", ha->host_no, __func__));
goto exit_validate_mac;
goto exit_get_sys_info;
}
/* Save M.A.C. address & serial_number */
......@@ -168,11 +199,11 @@ static int qla4xxx_validate_mac_address(struct scsi_qla_host *ha)
status = QLA_SUCCESS;
exit_validate_mac:
exit_get_sys_info:
dma_free_coherent(&ha->pdev->dev, sizeof(*sys_info), sys_info,
sys_info_dma);
exit_validate_mac_no_free:
exit_get_sys_info_no_free:
return status;
}
......@@ -584,21 +615,19 @@ static int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha,
min(sizeof(ddb_entry->link_local_ipv6_addr),
sizeof(fw_ddb_entry->link_local_ipv6_addr)));
DEBUG2(dev_info(&ha->pdev->dev, "%s: DDB[%d] osIdx = %d "
"State %04x ConnErr %08x IP %pI6 "
DEBUG2(ql4_printk(KERN_INFO, ha, "%s: DDB[%d] State %04x"
" ConnErr %08x IP %pI6 "
":%04d \"%s\"\n",
__func__, fw_ddb_index,
ddb_entry->os_target_id,
ddb_entry->fw_ddb_device_state,
conn_err, fw_ddb_entry->ip_addr,
le16_to_cpu(fw_ddb_entry->port),
fw_ddb_entry->iscsi_name));
} else
DEBUG2(dev_info(&ha->pdev->dev, "%s: DDB[%d] osIdx = %d "
"State %04x ConnErr %08x IP %pI4 "
DEBUG2(ql4_printk(KERN_INFO, ha, "%s: DDB[%d] State %04x"
" ConnErr %08x IP %pI4 "
":%04d \"%s\"\n",
__func__, fw_ddb_index,
ddb_entry->os_target_id,
ddb_entry->fw_ddb_device_state,
conn_err, fw_ddb_entry->ip_addr,
le16_to_cpu(fw_ddb_entry->port),
......@@ -984,7 +1013,7 @@ static int qla4xxx_initialize_ddb_list(struct scsi_qla_host *ha)
}
/**
* qla4xxx_update_ddb_list - update the driver ddb list
* qla4xxx_reinitialize_ddb_list - update the driver ddb list
* @ha: pointer to host adapter structure.
*
* This routine obtains device information from the F/W database after
......@@ -1028,7 +1057,7 @@ int qla4xxx_relogin_device(struct scsi_qla_host *ha,
(uint16_t)RELOGIN_TOV);
atomic_set(&ddb_entry->relogin_timer, relogin_timer);
DEBUG2(printk("scsi%ld: Relogin index [%d]. TOV=%d\n", ha->host_no,
DEBUG2(printk("scsi%ld: Relogin ddb [%d]. TOV=%d\n", ha->host_no,
ddb_entry->fw_ddb_index, relogin_timer));
qla4xxx_set_ddb_entry(ha, ddb_entry->fw_ddb_index, 0);
......@@ -1085,7 +1114,16 @@ static int qla4xxx_config_nvram(struct scsi_qla_host *ha)
return QLA_SUCCESS;
}
static void qla4x00_pci_config(struct scsi_qla_host *ha)
/**
* qla4_8xxx_pci_config() - Setup ISP82xx PCI configuration registers.
* @ha: HA context
*/
void qla4_8xxx_pci_config(struct scsi_qla_host *ha)
{
pci_set_master(ha->pdev);
}
void qla4xxx_pci_config(struct scsi_qla_host *ha)
{
uint16_t w;
int status;
......@@ -1216,7 +1254,7 @@ int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a)
* This routine performs the necessary steps to start the firmware for
* the QLA4010 adapter.
**/
static int qla4xxx_start_firmware(struct scsi_qla_host *ha)
int qla4xxx_start_firmware(struct scsi_qla_host *ha)
{
unsigned long flags = 0;
uint32_t mbox_status;
......@@ -1295,7 +1333,8 @@ static int qla4xxx_start_firmware(struct scsi_qla_host *ha)
if (soft_reset) {
DEBUG(printk("scsi%ld: %s: Issue Soft Reset\n", ha->host_no,
__func__));
status = qla4xxx_soft_reset(ha);
status = qla4xxx_soft_reset(ha); /* NOTE: acquires drvr
* lock again, but ok */
if (status == QLA_ERROR) {
DEBUG(printk("scsi%d: %s: Soft Reset failed!\n",
ha->host_no, __func__));
......@@ -1316,7 +1355,6 @@ static int qla4xxx_start_firmware(struct scsi_qla_host *ha)
ql4xxx_unlock_drvr(ha);
if (status == QLA_SUCCESS) {
qla4xxx_get_fw_version(ha);
if (test_and_clear_bit(AF_GET_CRASH_RECORD, &ha->flags))
qla4xxx_get_crash_record(ha);
} else {
......@@ -1343,18 +1381,21 @@ int qla4xxx_initialize_adapter(struct scsi_qla_host *ha,
int status = QLA_ERROR;
int8_t ip_address[IP_ADDR_LEN] = {0} ;
clear_bit(AF_ONLINE, &ha->flags);
ha->eeprom_cmd_data = 0;
qla4x00_pci_config(ha);
ql4_printk(KERN_INFO, ha, "Configuring PCI space...\n");
ha->isp_ops->pci_config(ha);
qla4xxx_disable_intrs(ha);
ha->isp_ops->disable_intrs(ha);
/* Initialize the Host adapter request/response queues and firmware */
if (qla4xxx_start_firmware(ha) == QLA_ERROR)
if (ha->isp_ops->start_firmware(ha) == QLA_ERROR)
goto exit_init_hba;
if (qla4xxx_get_fw_version(ha) == QLA_ERROR)
goto exit_init_hba;
if (qla4xxx_validate_mac_address(ha) == QLA_ERROR)
if (ha->isp_ops->get_sys_info(ha) == QLA_ERROR)
goto exit_init_hba;
if (qla4xxx_init_local_data(ha) == QLA_ERROR)
......@@ -1407,6 +1448,8 @@ int qla4xxx_initialize_adapter(struct scsi_qla_host *ha,
exit_init_online:
set_bit(AF_ONLINE, &ha->flags);
exit_init_hba:
DEBUG2(printk("scsi%ld: initialize adapter: %s\n", ha->host_no,
status == QLA_ERROR ? "FAILED" : "SUCCEDED"));
return status;
}
......@@ -1558,9 +1601,20 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
atomic_set(&ddb_entry->relogin_timer, 0);
atomic_set(&ddb_entry->retry_relogin_timer,
ddb_entry->default_time2wait + 4);
DEBUG(printk("scsi%ld: %s: ddb[%d] "
"initiate relogin after %d seconds\n",
ha->host_no, __func__,
ddb_entry->fw_ddb_index,
ddb_entry->default_time2wait + 4));
} else {
DEBUG(printk("scsi%ld: %s: ddb[%d] "
"relogin not initiated, state = %d, "
"ddb_entry->flags = 0x%lx\n",
ha->host_no, __func__,
ddb_entry->fw_ddb_index,
ddb_entry->fw_ddb_device_state,
ddb_entry->flags));
}
}
return QLA_SUCCESS;
}
......@@ -29,7 +29,7 @@ qla4xxx_lookup_ddb_by_fw_index(struct scsi_qla_host *ha, uint32_t fw_ddb_index)
ddb_entry = ha->fw_ddb_index_map[fw_ddb_index];
}
DEBUG3(printk("scsi%d: %s: index [%d], ddb_entry = %p\n",
DEBUG3(printk("scsi%d: %s: ddb [%d], ddb_entry = %p\n",
ha->host_no, __func__, fw_ddb_index, ddb_entry));
return ddb_entry;
......
......@@ -108,8 +108,7 @@ int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
wmb();
/* Tell ISP it's got a new I/O request */
writel(ha->request_in, &ha->reg->req_q_in);
readl(&ha->reg->req_q_in);
ha->isp_ops->queue_iocb(ha);
exit_send_marker:
spin_unlock_irqrestore(&ha->hardware_lock, flags);
......@@ -193,6 +192,72 @@ static void qla4xxx_build_scsi_iocbs(struct srb *srb,
}
}
/**
* qla4_8xxx_queue_iocb - Tell ISP it's got new request(s)
* @ha: pointer to host adapter structure.
*
* This routine notifies the ISP that one or more new request
* queue entries have been placed on the request queue.
**/
void qla4_8xxx_queue_iocb(struct scsi_qla_host *ha)
{
uint32_t dbval = 0;
unsigned long wtime;
dbval = 0x14 | (ha->func_num << 5);
dbval = dbval | (0 << 8) | (ha->request_in << 16);
writel(dbval, (unsigned long __iomem *)ha->nx_db_wr_ptr);
wmb();
wtime = jiffies + (2 * HZ);
while (readl((void __iomem *)ha->nx_db_rd_ptr) != dbval &&
!time_after_eq(jiffies, wtime)) {
writel(dbval, (unsigned long __iomem *)ha->nx_db_wr_ptr);
wmb();
}
}
/**
* qla4_8xxx_complete_iocb - Tell ISP we're done with response(s)
* @ha: pointer to host adapter structure.
*
* This routine notifies the ISP that one or more response/completion
* queue entries have been processed by the driver.
* This also clears the interrupt.
**/
void qla4_8xxx_complete_iocb(struct scsi_qla_host *ha)
{
writel(ha->response_out, &ha->qla4_8xxx_reg->rsp_q_out);
readl(&ha->qla4_8xxx_reg->rsp_q_out);
}
/**
* qla4xxx_queue_iocb - Tell ISP it's got new request(s)
* @ha: pointer to host adapter structure.
*
* This routine is notifies the ISP that one or more new request
* queue entries have been placed on the request queue.
**/
void qla4xxx_queue_iocb(struct scsi_qla_host *ha)
{
writel(ha->request_in, &ha->reg->req_q_in);
readl(&ha->reg->req_q_in);
}
/**
* qla4xxx_complete_iocb - Tell ISP we're done with response(s)
* @ha: pointer to host adapter structure.
*
* This routine is notifies the ISP that one or more response/completion
* queue entries have been processed by the driver.
* This also clears the interrupt.
**/
void qla4xxx_complete_iocb(struct scsi_qla_host *ha)
{
writel(ha->response_out, &ha->reg->rsp_q_out);
readl(&ha->reg->rsp_q_out);
}
/**
* qla4xxx_send_command_to_isp - issues command to HBA
* @ha: pointer to host adapter structure.
......@@ -310,9 +375,7 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb)
srb->iocb_cnt = req_cnt;
ha->req_q_count -= req_cnt;
/* Debug print statements */
writel(ha->request_in, &ha->reg->req_q_in);
readl(&ha->reg->req_q_in);
ha->isp_ops->queue_iocb(ha);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return QLA_SUCCESS;
......
......@@ -118,7 +118,6 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
srb = qla4xxx_del_from_active_array(ha, le32_to_cpu(sts_entry->handle));
if (!srb) {
/* FIXMEdg: Don't we need to reset ISP in this case??? */
DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Status Entry invalid "
"handle 0x%x, sp=%p. This cmd may have already "
"been completed.\n", ha->host_no, __func__,
......@@ -293,6 +292,10 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
case SCS_DEVICE_LOGGED_OUT:
case SCS_DEVICE_UNAVAILABLE:
DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%d: SCS_DEVICE "
"state: 0x%x\n", ha->host_no,
cmd->device->channel, cmd->device->id,
cmd->device->lun, sts_entry->completionStatus));
/*
* Mark device missing so that we won't continue to
* send I/O to this device. We should get a ddb
......@@ -339,16 +342,14 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
* This routine process response queue completions in interrupt context.
* Hardware_lock locked upon entry
**/
static void qla4xxx_process_response_queue(struct scsi_qla_host * ha)
void qla4xxx_process_response_queue(struct scsi_qla_host *ha)
{
uint32_t count = 0;
struct srb *srb = NULL;
struct status_entry *sts_entry;
/* Process all responses from response queue */
while ((ha->response_in =
(uint16_t)le32_to_cpu(ha->shadow_regs->rsp_q_in)) !=
ha->response_out) {
while ((ha->response_ptr->signature != RESPONSE_PROCESSED)) {
sts_entry = (struct status_entry *) ha->response_ptr;
count++;
......@@ -413,14 +414,14 @@ static void qla4xxx_process_response_queue(struct scsi_qla_host * ha)
sts_entry->hdr.entryType));
goto exit_prq_error;
}
((struct response *)sts_entry)->signature = RESPONSE_PROCESSED;
wmb();
}
/*
* Done with responses, update the ISP For QLA4010, this also clears
* the interrupt.
* Tell ISP we're done with response(s). This also clears the interrupt.
*/
writel(ha->response_out, &ha->reg->rsp_q_out);
readl(&ha->reg->rsp_q_out);
ha->isp_ops->complete_iocb(ha);
return;
......@@ -430,9 +431,7 @@ static void qla4xxx_process_response_queue(struct scsi_qla_host * ha)
sts_entry->completionStatus));
exit_prq_error:
writel(ha->response_out, &ha->reg->rsp_q_out);
readl(&ha->reg->rsp_q_out);
ha->isp_ops->complete_iocb(ha);
set_bit(DPC_RESET_HA, &ha->dpc_flags);
}
......@@ -448,7 +447,7 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
uint32_t mbox_status)
{
int i;
uint32_t mbox_stat2, mbox_stat3;
uint32_t mbox_sts[MBOX_AEN_REG_COUNT];
if ((mbox_status == MBOX_STS_BUSY) ||
(mbox_status == MBOX_STS_INTERMEDIATE_COMPLETION) ||
......@@ -460,27 +459,37 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
* Copy all mailbox registers to a temporary
* location and set mailbox command done flag
*/
for (i = 1; i < ha->mbox_status_count; i++)
ha->mbox_status[i] =
readl(&ha->reg->mailbox[i]);
for (i = 0; i < ha->mbox_status_count; i++)
ha->mbox_status[i] = is_qla8022(ha)
? readl(&ha->qla4_8xxx_reg->mailbox_out[i])
: readl(&ha->reg->mailbox[i]);
set_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
if (test_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags))
complete(&ha->mbx_intr_comp);
}
} 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_8xxx_reg->mailbox_out[i])
: readl(&ha->reg->mailbox[i]);
/* Immediately process the AENs that don't require much work.
* Only queue the database_changed AENs */
if (ha->aen_log.count < MAX_AEN_ENTRIES) {
for (i = 0; i < MBOX_AEN_REG_COUNT; i++)
ha->aen_log.entry[ha->aen_log.count].mbox_sts[i] =
readl(&ha->reg->mailbox[i]);
mbox_sts[i];
ha->aen_log.count++;
}
switch (mbox_status) {
case MBOX_ASTS_SYSTEM_ERROR:
/* Log Mailbox registers */
ql4_printk(KERN_INFO, ha, "%s: System Err\n", __func__);
if (ql4xdontresethba) {
DEBUG2(printk("%s:Dont Reset HBA\n",
__func__));
DEBUG2(printk("scsi%ld: %s:Don't Reset HBA\n",
ha->host_no, __func__));
} else {
set_bit(AF_GET_CRASH_RECORD, &ha->flags);
set_bit(DPC_RESET_HA, &ha->dpc_flags);
......@@ -502,18 +511,15 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
if (test_bit(AF_INIT_DONE, &ha->flags))
set_bit(DPC_LINK_CHANGED, &ha->dpc_flags);
DEBUG2(printk(KERN_INFO "scsi%ld: AEN %04x Adapter"
" LINK UP\n", ha->host_no,
mbox_status));
ql4_printk(KERN_INFO, ha, "%s: LINK UP\n", __func__);
break;
case MBOX_ASTS_LINK_DOWN:
clear_bit(AF_LINK_UP, &ha->flags);
set_bit(DPC_LINK_CHANGED, &ha->dpc_flags);
if (test_bit(AF_INIT_DONE, &ha->flags))
set_bit(DPC_LINK_CHANGED, &ha->dpc_flags);
DEBUG2(printk(KERN_INFO "scsi%ld: AEN %04x Adapter"
" LINK DOWN\n", ha->host_no,
mbox_status));
ql4_printk(KERN_INFO, ha, "%s: LINK DOWN\n", __func__);
break;
case MBOX_ASTS_HEARTBEAT:
......@@ -539,12 +545,17 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
break;
case MBOX_ASTS_IP_ADDR_STATE_CHANGED:
mbox_stat2 = readl(&ha->reg->mailbox[2]);
mbox_stat3 = readl(&ha->reg->mailbox[3]);
if ((mbox_stat3 == 5) && (mbox_stat2 == 3))
printk("scsi%ld: AEN %04x, mbox_sts[2]=%04x, "
"mbox_sts[3]=%04x\n", ha->host_no, mbox_sts[0],
mbox_sts[2], mbox_sts[3]);
/* mbox_sts[2] = Old ACB state
* mbox_sts[3] = new ACB state */
if ((mbox_sts[3] == ACB_STATE_VALID) &&
(mbox_sts[2] == ACB_STATE_TENTATIVE))
set_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags);
else if ((mbox_stat3 == 2) && (mbox_stat2 == 5))
else if ((mbox_sts[3] == ACB_STATE_ACQUIRING) &&
(mbox_sts[2] == ACB_STATE_VALID))
set_bit(DPC_RESET_HA, &ha->dpc_flags);
break;
......@@ -553,9 +564,8 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
/* No action */
DEBUG2(printk(KERN_INFO "scsi%ld: AEN %04x, "
"mbox_sts[1]=%04x, mbox_sts[2]=%04x\n",
ha->host_no, mbox_status,
readl(&ha->reg->mailbox[1]),
readl(&ha->reg->mailbox[2])));
ha->host_no, mbox_sts[0],
mbox_sts[1], mbox_sts[2]));
break;
case MBOX_ASTS_SELF_TEST_FAILED:
......@@ -563,10 +573,8 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
/* No action */
DEBUG2(printk("scsi%ld: AEN %04x, mbox_sts[1]=%04x, "
"mbox_sts[2]=%04x, mbox_sts[3]=%04x\n",
ha->host_no, mbox_status,
readl(&ha->reg->mailbox[1]),
readl(&ha->reg->mailbox[2]),
readl(&ha->reg->mailbox[3])));
ha->host_no, mbox_sts[0], mbox_sts[1],
mbox_sts[2], mbox_sts[3]));
break;
case MBOX_ASTS_DATABASE_CHANGED:
......@@ -577,21 +585,17 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
/* decrement available counter */
ha->aen_q_count--;
for (i = 1; i < MBOX_AEN_REG_COUNT; i++)
for (i = 0; i < MBOX_AEN_REG_COUNT; i++)
ha->aen_q[ha->aen_in].mbox_sts[i] =
readl(&ha->reg->mailbox[i]);
ha->aen_q[ha->aen_in].mbox_sts[0] = mbox_status;
mbox_sts[i];
/* print debug message */
DEBUG2(printk("scsi%ld: AEN[%d] %04x queued"
" mb1:0x%x mb2:0x%x mb3:0x%x mb4:0x%x\n",
ha->host_no, ha->aen_in,
mbox_status,
ha->aen_q[ha->aen_in].mbox_sts[1],
ha->aen_q[ha->aen_in].mbox_sts[2],
ha->aen_q[ha->aen_in].mbox_sts[3],
ha->aen_q[ha->aen_in]. mbox_sts[4]));
" mb1:0x%x mb2:0x%x mb3:0x%x mb4:0x%x\n",
ha->host_no, ha->aen_in, mbox_sts[0],
mbox_sts[1], mbox_sts[2], mbox_sts[3],
mbox_sts[4]));
/* advance pointer */
ha->aen_in++;
if (ha->aen_in == MAX_AEN_ENTRIES)
......@@ -603,18 +607,16 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
DEBUG2(printk("scsi%ld: %s: aen %04x, queue "
"overflowed! AEN LOST!!\n",
ha->host_no, __func__,
mbox_status));
mbox_sts[0]));
DEBUG2(printk("scsi%ld: DUMP AEN QUEUE\n",
ha->host_no));
for (i = 0; i < MAX_AEN_ENTRIES; i++) {
DEBUG2(printk("AEN[%d] %04x %04x %04x "
"%04x\n", i,
ha->aen_q[i].mbox_sts[0],
ha->aen_q[i].mbox_sts[1],
ha->aen_q[i].mbox_sts[2],
ha->aen_q[i].mbox_sts[3]));
"%04x\n", i, mbox_sts[0],
mbox_sts[1], mbox_sts[2],
mbox_sts[3]));
}
}
break;
......@@ -622,7 +624,7 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
default:
DEBUG2(printk(KERN_WARNING
"scsi%ld: AEN %04x UNKNOWN\n",
ha->host_no, mbox_status));
ha->host_no, mbox_sts[0]));
break;
}
} else {
......@@ -633,6 +635,30 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
}
}
/**
* qla4_8xxx_interrupt_service_routine - isr
* @ha: pointer to host adapter structure.
*
* This is the main interrupt service routine.
* hardware_lock locked upon entry. runs in interrupt context.
**/
void qla4_8xxx_interrupt_service_routine(struct scsi_qla_host *ha,
uint32_t intr_status)
{
/* Process response queue interrupt. */
if (intr_status & HSRX_RISC_IOCB_INT)
qla4xxx_process_response_queue(ha);
/* Process mailbox/asynch event interrupt.*/
if (intr_status & HSRX_RISC_MB_INT)
qla4xxx_isr_decode_mailbox(ha,
readl(&ha->qla4_8xxx_reg->mailbox_out[0]));
/* clear the interrupt */
writel(0, &ha->qla4_8xxx_reg->host_int);
readl(&ha->qla4_8xxx_reg->host_int);
}
/**
* qla4xxx_interrupt_service_routine - isr
* @ha: pointer to host adapter structure.
......@@ -659,6 +685,28 @@ void qla4xxx_interrupt_service_routine(struct scsi_qla_host * ha,
}
}
/**
* qla4_8xxx_spurious_interrupt - processes spurious interrupt
* @ha: pointer to host adapter structure.
* @reqs_count: .
*
**/
static void qla4_8xxx_spurious_interrupt(struct scsi_qla_host *ha,
uint8_t reqs_count)
{
if (reqs_count)
return;
DEBUG2(ql4_printk(KERN_INFO, ha, "Spurious Interrupt\n"));
if (is_qla8022(ha)) {
writel(0, &ha->qla4_8xxx_reg->host_int);
if (test_bit(AF_INTx_ENABLED, &ha->flags))
qla4_8xxx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg,
0xfbff);
}
ha->spurious_int_count++;
}
/**
* qla4xxx_intr_handler - hardware interrupt handler.
* @irq: Unused
......@@ -689,15 +737,14 @@ irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id)
/*
* Read interrupt status
*/
if (le32_to_cpu(ha->shadow_regs->rsp_q_in) !=
if (ha->isp_ops->rd_shdw_rsp_q_in(ha) !=
ha->response_out)
intr_status = CSR_SCSI_COMPLETION_INTR;
else
intr_status = readl(&ha->reg->ctrl_status);
if ((intr_status &
(CSR_SCSI_RESET_INTR|CSR_FATAL_ERROR|INTR_PENDING)) ==
0) {
(CSR_SCSI_RESET_INTR|CSR_FATAL_ERROR|INTR_PENDING)) == 0) {
if (reqs_count == 0)
ha->spurious_int_count++;
break;
......@@ -739,22 +786,159 @@ irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id)
&ha->reg->ctrl_status);
readl(&ha->reg->ctrl_status);
if (!ql4_mod_unload)
if (!test_bit(AF_HBA_GOING_AWAY, &ha->flags))
set_bit(DPC_RESET_HA_INTR, &ha->dpc_flags);
break;
} else if (intr_status & INTR_PENDING) {
qla4xxx_interrupt_service_routine(ha, intr_status);
ha->isp_ops->interrupt_service_routine(ha, intr_status);
ha->total_io_count++;
if (++reqs_count == MAX_REQS_SERVICED_PER_INTR)
break;
}
}
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return IRQ_HANDLED;
}
/**
* qla4_8xxx_intr_handler - hardware interrupt handler.
* @irq: Unused
* @dev_id: Pointer to host adapter structure
**/
irqreturn_t qla4_8xxx_intr_handler(int irq, void *dev_id)
{
struct scsi_qla_host *ha = dev_id;
uint32_t intr_status;
uint32_t status;
unsigned long flags = 0;
uint8_t reqs_count = 0;
ha->isr_count++;
status = qla4_8xxx_rd_32(ha, ISR_INT_VECTOR);
if (!(status & ha->nx_legacy_intr.int_vec_bit))
return IRQ_NONE;
status = qla4_8xxx_rd_32(ha, ISR_INT_STATE_REG);
if (!ISR_IS_LEGACY_INTR_TRIGGERED(status)) {
DEBUG2(ql4_printk(KERN_INFO, ha,
"%s legacy Int not triggered\n", __func__));
return IRQ_NONE;
}
/* clear the interrupt */
qla4_8xxx_wr_32(ha, ha->nx_legacy_intr.tgt_status_reg, 0xffffffff);
/* read twice to ensure write is flushed */
qla4_8xxx_rd_32(ha, ISR_INT_VECTOR);
qla4_8xxx_rd_32(ha, ISR_INT_VECTOR);
spin_lock_irqsave(&ha->hardware_lock, flags);
while (1) {
if (!(readl(&ha->qla4_8xxx_reg->host_int) &
ISRX_82XX_RISC_INT)) {
qla4_8xxx_spurious_interrupt(ha, reqs_count);
break;
}
intr_status = readl(&ha->qla4_8xxx_reg->host_status);
if ((intr_status &
(HSRX_RISC_MB_INT | HSRX_RISC_IOCB_INT)) == 0) {
qla4_8xxx_spurious_interrupt(ha, reqs_count);
break;
}
ha->isp_ops->interrupt_service_routine(ha, intr_status);
/* Enable Interrupt */
qla4_8xxx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0xfbff);
intr_status = 0;
if (++reqs_count == MAX_REQS_SERVICED_PER_INTR)
break;
}
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return IRQ_HANDLED;
}
irqreturn_t
qla4_8xxx_msi_handler(int irq, void *dev_id)
{
struct scsi_qla_host *ha;
ha = (struct scsi_qla_host *) dev_id;
if (!ha) {
DEBUG2(printk(KERN_INFO
"qla4xxx: MSIX: Interrupt with NULL host ptr\n"));
return IRQ_NONE;
}
ha->isr_count++;
/* clear the interrupt */
qla4_8xxx_wr_32(ha, ha->nx_legacy_intr.tgt_status_reg, 0xffffffff);
/* read twice to ensure write is flushed */
qla4_8xxx_rd_32(ha, ISR_INT_VECTOR);
qla4_8xxx_rd_32(ha, ISR_INT_VECTOR);
return qla4_8xxx_default_intr_handler(irq, dev_id);
}
/**
* qla4_8xxx_default_intr_handler - hardware interrupt handler.
* @irq: Unused
* @dev_id: Pointer to host adapter structure
*
* This interrupt handler is called directly for MSI-X, and
* called indirectly for MSI.
**/
irqreturn_t
qla4_8xxx_default_intr_handler(int irq, void *dev_id)
{
struct scsi_qla_host *ha = dev_id;
unsigned long flags;
uint32_t intr_status;
uint8_t reqs_count = 0;
spin_lock_irqsave(&ha->hardware_lock, flags);
while (1) {
if (!(readl(&ha->qla4_8xxx_reg->host_int) &
ISRX_82XX_RISC_INT)) {
qla4_8xxx_spurious_interrupt(ha, reqs_count);
break;
}
intr_status = readl(&ha->qla4_8xxx_reg->host_status);
if ((intr_status &
(HSRX_RISC_MB_INT | HSRX_RISC_IOCB_INT)) == 0) {
qla4_8xxx_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);
return IRQ_HANDLED;
}
irqreturn_t
qla4_8xxx_msix_rsp_q(int irq, void *dev_id)
{
struct scsi_qla_host *ha = dev_id;
unsigned long flags;
spin_lock_irqsave(&ha->hardware_lock, flags);
qla4xxx_process_response_queue(ha);
writel(0, &ha->qla4_8xxx_reg->host_int);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
ha->isr_count++;
return IRQ_HANDLED;
}
......@@ -825,7 +1009,7 @@ void qla4xxx_process_aen(struct scsi_qla_host * ha, uint8_t process_aen)
((ddb_entry->default_time2wait +
4) * HZ);
DEBUG2(printk("scsi%ld: ddb index [%d] initate"
DEBUG2(printk("scsi%ld: ddb [%d] initate"
" RELOGIN after %d seconds\n",
ha->host_no,
ddb_entry->fw_ddb_index,
......@@ -847,3 +1031,81 @@ void qla4xxx_process_aen(struct scsi_qla_host * ha, uint8_t process_aen)
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
int qla4xxx_request_irqs(struct scsi_qla_host *ha)
{
int ret;
if (!is_qla8022(ha))
goto try_intx;
if (ql4xenablemsix == 2)
goto try_msi;
if (ql4xenablemsix == 0 || ql4xenablemsix != 1)
goto try_intx;
/* Trying MSI-X */
ret = qla4_8xxx_enable_msix(ha);
if (!ret) {
DEBUG2(ql4_printk(KERN_INFO, ha,
"MSI-X: Enabled (0x%X).\n", ha->revision_id));
goto irq_attached;
}
ql4_printk(KERN_WARNING, ha,
"MSI-X: Falling back-to MSI mode -- %d.\n", ret);
try_msi:
/* Trying MSI */
ret = pci_enable_msi(ha->pdev);
if (!ret) {
ret = request_irq(ha->pdev->irq, qla4_8xxx_msi_handler,
IRQF_DISABLED|IRQF_SHARED, DRIVER_NAME, ha);
if (!ret) {
DEBUG2(ql4_printk(KERN_INFO, ha, "MSI: Enabled.\n"));
set_bit(AF_MSI_ENABLED, &ha->flags);
goto irq_attached;
} else {
ql4_printk(KERN_WARNING, ha,
"MSI: Failed to reserve interrupt %d "
"already in use.\n", ha->pdev->irq);
pci_disable_msi(ha->pdev);
}
}
ql4_printk(KERN_WARNING, ha,
"MSI: Falling back-to INTx mode -- %d.\n", ret);
try_intx:
/* Trying INTx */
ret = request_irq(ha->pdev->irq, ha->isp_ops->intr_handler,
IRQF_DISABLED|IRQF_SHARED, DRIVER_NAME, ha);
if (!ret) {
DEBUG2(ql4_printk(KERN_INFO, ha, "INTx: Enabled.\n"));
set_bit(AF_INTx_ENABLED, &ha->flags);
goto irq_attached;
} else {
ql4_printk(KERN_WARNING, ha,
"INTx: Failed to reserve interrupt %d already in"
" use.\n", ha->pdev->irq);
return ret;
}
irq_attached:
set_bit(AF_IRQ_ATTACHED, &ha->flags);
ha->host->irq = ha->pdev->irq;
ql4_printk(KERN_INFO, ha, "%s: irq %d attached\n",
__func__, ha->pdev->irq);
return ret;
}
void qla4xxx_free_irqs(struct scsi_qla_host *ha)
{
if (test_bit(AF_MSIX_ENABLED, &ha->flags))
qla4_8xxx_disable_msix(ha);
else if (test_and_clear_bit(AF_MSI_ENABLED, &ha->flags)) {
free_irq(ha->pdev->irq, ha);
pci_disable_msi(ha->pdev);
} else if (test_and_clear_bit(AF_INTx_ENABLED, &ha->flags))
free_irq(ha->pdev->irq, ha);
}
......@@ -19,13 +19,13 @@
* @mbx_cmd: data pointer for mailbox in registers.
* @mbx_sts: data pointer for mailbox out registers.
*
* This routine sssue mailbox commands and waits for completion.
* This routine isssue mailbox commands and waits for completion.
* If outCount is 0, this routine completes successfully WITHOUT waiting
* for the mailbox command to complete.
**/
static int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
uint8_t outCount, uint32_t *mbx_cmd,
uint32_t *mbx_sts)
int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
uint8_t outCount, uint32_t *mbx_cmd,
uint32_t *mbx_sts)
{
int status = QLA_ERROR;
uint8_t i;
......@@ -59,32 +59,66 @@ static int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
}
/* To prevent overwriting mailbox registers for a command that has
* not yet been serviced, check to see if a previously issued
* mailbox command is interrupting.
* not yet been serviced, check to see if an active command
* (AEN, IOCB, etc.) is interrupting, then service it.
* -----------------------------------------------------------------
*/
spin_lock_irqsave(&ha->hardware_lock, flags);
intr_status = readl(&ha->reg->ctrl_status);
if (intr_status & CSR_SCSI_PROCESSOR_INTR) {
/* Service existing interrupt */
qla4xxx_interrupt_service_routine(ha, intr_status);
clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
if (is_qla8022(ha)) {
intr_status = readl(&ha->qla4_8xxx_reg->host_int);
if (intr_status & ISRX_82XX_RISC_INT) {
/* Service existing interrupt */
DEBUG2(printk("scsi%ld: %s: "
"servicing existing interrupt\n",
ha->host_no, __func__));
intr_status = readl(&ha->qla4_8xxx_reg->host_status);
ha->isp_ops->interrupt_service_routine(ha, intr_status);
clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
if (test_bit(AF_INTERRUPTS_ON, &ha->flags) &&
test_bit(AF_INTx_ENABLED, &ha->flags))
qla4_8xxx_wr_32(ha,
ha->nx_legacy_intr.tgt_mask_reg,
0xfbff);
}
} else {
intr_status = readl(&ha->reg->ctrl_status);
if (intr_status & CSR_SCSI_PROCESSOR_INTR) {
/* Service existing interrupt */
ha->isp_ops->interrupt_service_routine(ha, intr_status);
clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
}
}
/* Send the mailbox command to the firmware */
ha->mbox_status_count = outCount;
for (i = 0; i < outCount; i++)
ha->mbox_status[i] = 0;
/* Load all mailbox registers, except mailbox 0. */
for (i = 1; i < inCount; i++)
writel(mbx_cmd[i], &ha->reg->mailbox[i]);
if (is_qla8022(ha)) {
/* Load all mailbox registers, except mailbox 0. */
DEBUG5(
printk("scsi%ld: %s: Cmd ", ha->host_no, __func__);
for (i = 0; i < inCount; i++)
printk("mb%d=%04x ", i, mbx_cmd[i]);
printk("\n"));
for (i = 1; i < inCount; i++)
writel(mbx_cmd[i], &ha->qla4_8xxx_reg->mailbox_in[i]);
writel(mbx_cmd[0], &ha->qla4_8xxx_reg->mailbox_in[0]);
readl(&ha->qla4_8xxx_reg->mailbox_in[0]);
writel(HINT_MBX_INT_PENDING, &ha->qla4_8xxx_reg->hint);
} else {
/* Load all mailbox registers, except mailbox 0. */
for (i = 1; i < inCount; i++)
writel(mbx_cmd[i], &ha->reg->mailbox[i]);
/* Wakeup firmware */
writel(mbx_cmd[0], &ha->reg->mailbox[0]);
readl(&ha->reg->mailbox[0]);
writel(set_rmask(CSR_INTR_RISC), &ha->reg->ctrl_status);
readl(&ha->reg->ctrl_status);
}
/* Wakeup firmware */
writel(mbx_cmd[0], &ha->reg->mailbox[0]);
readl(&ha->reg->mailbox[0]);
writel(set_rmask(CSR_INTR_RISC), &ha->reg->ctrl_status);
readl(&ha->reg->ctrl_status);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
/* Wait for completion */
......@@ -98,26 +132,66 @@ static int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
status = QLA_SUCCESS;
goto mbox_exit;
}
/* Wait for command to complete */
wait_count = jiffies + MBOX_TOV * HZ;
while (test_bit(AF_MBOX_COMMAND_DONE, &ha->flags) == 0) {
if (time_after_eq(jiffies, wait_count))
break;
spin_lock_irqsave(&ha->hardware_lock, flags);
intr_status = readl(&ha->reg->ctrl_status);
if (intr_status & INTR_PENDING) {
/*
* Wait for completion: Poll or completion queue
*/
if (test_bit(AF_IRQ_ATTACHED, &ha->flags) &&
test_bit(AF_INTERRUPTS_ON, &ha->flags) &&
test_bit(AF_ONLINE, &ha->flags) &&
!test_bit(AF_HBA_GOING_AWAY, &ha->flags)) {
/* Do not poll for completion. Use completion queue */
set_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags);
wait_for_completion_timeout(&ha->mbx_intr_comp, MBOX_TOV * HZ);
clear_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags);
} else {
/* Poll for command to complete */
wait_count = jiffies + MBOX_TOV * HZ;
while (test_bit(AF_MBOX_COMMAND_DONE, &ha->flags) == 0) {
if (time_after_eq(jiffies, wait_count))
break;
/*
* Service the interrupt.
* The ISR will save the mailbox status registers
* to a temporary storage location in the adapter
* structure.
*/
ha->mbox_status_count = outCount;
qla4xxx_interrupt_service_routine(ha, intr_status);
spin_lock_irqsave(&ha->hardware_lock, flags);
if (is_qla8022(ha)) {
intr_status =
readl(&ha->qla4_8xxx_reg->host_int);
if (intr_status & ISRX_82XX_RISC_INT) {
ha->mbox_status_count = outCount;
intr_status =
readl(&ha->qla4_8xxx_reg->host_status);
ha->isp_ops->interrupt_service_routine(
ha, intr_status);
if (test_bit(AF_INTERRUPTS_ON,
&ha->flags) &&
test_bit(AF_INTx_ENABLED,
&ha->flags))
qla4_8xxx_wr_32(ha,
ha->nx_legacy_intr.tgt_mask_reg,
0xfbff);
}
} else {
intr_status = readl(&ha->reg->ctrl_status);
if (intr_status & INTR_PENDING) {
/*
* Service the interrupt.
* The ISR will save the mailbox status
* registers to a temporary storage
* location in the adapter structure.
*/
ha->mbox_status_count = outCount;
ha->isp_ops->interrupt_service_routine(
ha, intr_status);
}
}
spin_unlock_irqrestore(&ha->hardware_lock, flags);
msleep(10);
}
spin_unlock_irqrestore(&ha->hardware_lock, flags);
msleep(10);
}
/* Check for mailbox timeout. */
......@@ -172,7 +246,7 @@ static int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
return status;
}
uint8_t
static uint8_t
qla4xxx_set_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma)
{
......@@ -196,7 +270,7 @@ qla4xxx_set_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
return QLA_SUCCESS;
}
uint8_t
static uint8_t
qla4xxx_get_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma)
{
......@@ -218,7 +292,7 @@ qla4xxx_get_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
return QLA_SUCCESS;
}
void
static void
qla4xxx_update_local_ip(struct scsi_qla_host *ha,
struct addr_ctrl_blk *init_fw_cb)
{
......@@ -256,7 +330,7 @@ qla4xxx_update_local_ip(struct scsi_qla_host *ha,
}
}
uint8_t
static uint8_t
qla4xxx_update_local_ifcb(struct scsi_qla_host *ha,
uint32_t *mbox_cmd,
uint32_t *mbox_sts,
......@@ -445,7 +519,7 @@ int qla4xxx_get_firmware_state(struct scsi_qla_host * ha)
DEBUG2(printk("scsi%ld: %s firmware_state=0x%x\n",
ha->host_no, __func__, ha->firmware_state);)
return QLA_SUCCESS;
return QLA_SUCCESS;
}
/**
......@@ -470,6 +544,10 @@ int qla4xxx_get_firmware_status(struct scsi_qla_host * ha)
mbox_sts[0]));
return QLA_ERROR;
}
ql4_printk(KERN_INFO, ha, "%ld firmare IOCBs available (%d).\n",
ha->host_no, mbox_cmd[2]);
return QLA_SUCCESS;
}
......@@ -500,7 +578,7 @@ int qla4xxx_get_fwddb_entry(struct scsi_qla_host *ha,
/* Make sure the device index is valid */
if (fw_ddb_index >= MAX_DDB_ENTRIES) {
DEBUG2(printk("scsi%ld: %s: index [%d] out of range.\n",
DEBUG2(printk("scsi%ld: %s: ddb [%d] out of range.\n",
ha->host_no, __func__, fw_ddb_index));
goto exit_get_fwddb;
}
......@@ -521,7 +599,7 @@ int qla4xxx_get_fwddb_entry(struct scsi_qla_host *ha,
goto exit_get_fwddb;
}
if (fw_ddb_index != mbox_sts[1]) {
DEBUG2(printk("scsi%ld: %s: index mismatch [%d] != [%d].\n",
DEBUG2(printk("scsi%ld: %s: ddb mismatch [%d] != [%d].\n",
ha->host_no, __func__, fw_ddb_index,
mbox_sts[1]));
goto exit_get_fwddb;
......@@ -590,6 +668,7 @@ int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index,
{
uint32_t mbox_cmd[MBOX_REG_COUNT];
uint32_t mbox_sts[MBOX_REG_COUNT];
int status;
/* Do not wait for completion. The firmware will send us an
* ASTS_DATABASE_CHANGED (0x8014) to notify us of the login status.
......@@ -603,7 +682,12 @@ int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index,
mbox_cmd[3] = MSDW(fw_ddb_entry_dma);
mbox_cmd[4] = sizeof(struct dev_db_entry);
return qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]);
status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0],
&mbox_sts[0]);
DEBUG2(printk("scsi%ld: %s: status=%d mbx0=0x%x mbx4=0x%x\n",
ha->host_no, __func__, status, mbox_sts[0], mbox_sts[4]);)
return status;
}
/**
......@@ -817,8 +901,8 @@ int qla4xxx_abort_task(struct scsi_qla_host *ha, struct srb *srb)
/**
* qla4xxx_reset_lun - issues LUN Reset
* @ha: Pointer to host adapter structure.
* @db_entry: Pointer to device database entry
* @un_entry: Pointer to lun entry structure
* @ddb_entry: Pointer to device database entry
* @lun: lun number
*
* This routine performs a LUN RESET on the specified target/lun.
* The caller must ensure that the ddb_entry and lun_entry pointers
......@@ -832,7 +916,7 @@ int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry,
int status = QLA_SUCCESS;
DEBUG2(printk("scsi%ld:%d:%d: lun reset issued\n", ha->host_no,
ddb_entry->os_target_id, lun));
ddb_entry->fw_ddb_index, lun));
/*
* Send lun reset command to ISP, so that the ISP will return all
......@@ -872,7 +956,7 @@ int qla4xxx_reset_target(struct scsi_qla_host *ha,
int status = QLA_SUCCESS;
DEBUG2(printk("scsi%ld:%d: target reset issued\n", ha->host_no,
ddb_entry->os_target_id));
ddb_entry->fw_ddb_index));
/*
* Send target reset command to ISP, so that the ISP will return all
......
......@@ -149,7 +149,7 @@ static int eeprom_readword(int eepromAddr, u16 * value,
/* Hardware_lock must be set before calling */
u16 rd_nvram_word(struct scsi_qla_host * ha, int offset)
{
u16 val;
u16 val = 0;
/* NOTE: NVRAM uses half-word addresses */
eeprom_readword(offset, &val, ha);
......
......@@ -8,9 +8,9 @@
#ifndef _QL4XNVRM_H_
#define _QL4XNVRM_H_
/*
/**
* AM29LV Flash definitions
*/
**/
#define FM93C56A_SIZE_8 0x100
#define FM93C56A_SIZE_16 0x80
#define FM93C66A_SIZE_8 0x200
......@@ -19,7 +19,7 @@
#define FM93C56A_START 0x1
// Commands
/* Commands */
#define FM93C56A_READ 0x2
#define FM93C56A_WEN 0x0
#define FM93C56A_WRITE 0x1
......@@ -62,9 +62,9 @@
#define AUBURN_EEPROM_CLK_RISE 0x1
#define AUBURN_EEPROM_CLK_FALL 0x0
/* */
/**/
/* EEPROM format */
/* */
/**/
struct bios_params {
uint16_t SpinUpDelay:1;
uint16_t BIOSDisable:1;
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册