diff options
author | Vikas Chaudhary <vikas.chaudhary@qlogic.com> | 2010-07-28 15:53:44 +0530 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-07-28 09:04:23 -0500 |
commit | f4f5df23bf72208d0c2f1d8be629839924c2f4c2 (patch) | |
tree | 88c41a002e0f9f4470543209047d1111a51a0d06 /drivers/scsi/qla4xxx | |
parent | dbaf82ece08bf93ae5200f03efd87c4f1fc453f1 (diff) |
[SCSI] qla4xxx: Added support for ISP82XX
Signed-off-by: Vikas Chaudhary <Vikas Chaudhary@qlogic.com>
Signed-off-by: Karen Higgins <karen.higgins@qlogic.com>
Signed-off-by: Ravi Anand <ravi.anand@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/qla4xxx')
-rw-r--r-- | drivers/scsi/qla4xxx/Kconfig | 8 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/Makefile | 2 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_def.h | 141 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_fw.h | 139 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_glbl.h | 106 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_init.c | 136 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_inline.h | 2 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_iocb.c | 73 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_isr.c | 388 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_mbx.c | 172 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_nvram.c | 2 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_nvram.h | 10 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_nx.c | 2321 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_nx.h | 779 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_os.c | 678 |
15 files changed, 4600 insertions, 357 deletions
diff --git a/drivers/scsi/qla4xxx/Kconfig b/drivers/scsi/qla4xxx/Kconfig index 69cbff3f57c..2c33ce6eac1 100644 --- a/drivers/scsi/qla4xxx/Kconfig +++ b/drivers/scsi/qla4xxx/Kconfig @@ -1,7 +1,7 @@ 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. diff --git a/drivers/scsi/qla4xxx/Makefile b/drivers/scsi/qla4xxx/Makefile index 86ea37baa0f..0339ff03a53 100644 --- a/drivers/scsi/qla4xxx/Makefile +++ b/drivers/scsi/qla4xxx/Makefile @@ -1,5 +1,5 @@ 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 diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index 3e1c990f5e2..a79da8dd206 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h @@ -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) && diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h index 855226e0866..c94c9ddfb3a 100644 --- a/drivers/scsi/qla4xxx/ql4_fw.h +++ b/drivers/scsi/qla4xxx/ql4_fw.h @@ -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 */ diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index c4636f6cb3c..c9cd5d6db98 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.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 */ diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index 4a332c32d71..539546df037 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c @@ -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); @@ -86,6 +86,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 scs |