diff options
-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 69cbff3f57cf..2c33ce6eac1e 100644 --- a/drivers/scsi/qla4xxx/Kconfig +++ b/drivers/scsi/qla4xxx/Kconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | config SCSI_QLA_ISCSI | 1 | config SCSI_QLA_ISCSI |
2 | tristate "QLogic ISP4XXX host adapter family support" | 2 | tristate "QLogic ISP4XXX and ISP82XX host adapter family support" |
3 | depends on PCI && SCSI && NET | 3 | depends on PCI && SCSI |
4 | select SCSI_ISCSI_ATTRS | 4 | select SCSI_ISCSI_ATTRS |
5 | ---help--- | 5 | ---help--- |
6 | This driver supports the QLogic 40xx (ISP4XXX) iSCSI host | 6 | This driver supports the QLogic 40xx (ISP4XXX) and 8022 (ISP82XX) |
7 | adapter family. | 7 | iSCSI host adapter family. |
diff --git a/drivers/scsi/qla4xxx/Makefile b/drivers/scsi/qla4xxx/Makefile index 86ea37baa0fc..0339ff03a535 100644 --- a/drivers/scsi/qla4xxx/Makefile +++ b/drivers/scsi/qla4xxx/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | qla4xxx-y := ql4_os.o ql4_init.o ql4_mbx.o ql4_iocb.o ql4_isr.o \ | 1 | qla4xxx-y := ql4_os.o ql4_init.o ql4_mbx.o ql4_iocb.o ql4_isr.o \ |
2 | ql4_nvram.o ql4_dbg.o | 2 | ql4_nx.o ql4_nvram.o ql4_dbg.o |
3 | 3 | ||
4 | obj-$(CONFIG_SCSI_QLA_ISCSI) += qla4xxx.o | 4 | obj-$(CONFIG_SCSI_QLA_ISCSI) += qla4xxx.o |
5 | 5 | ||
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index 3e1c990f5e20..a79da8dd2064 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h | |||
@@ -33,6 +33,8 @@ | |||
33 | #include <scsi/scsi_transport.h> | 33 | #include <scsi/scsi_transport.h> |
34 | #include <scsi/scsi_transport_iscsi.h> | 34 | #include <scsi/scsi_transport_iscsi.h> |
35 | 35 | ||
36 | #include "ql4_dbg.h" | ||
37 | #include "ql4_nx.h" | ||
36 | 38 | ||
37 | #ifndef PCI_DEVICE_ID_QLOGIC_ISP4010 | 39 | #ifndef PCI_DEVICE_ID_QLOGIC_ISP4010 |
38 | #define PCI_DEVICE_ID_QLOGIC_ISP4010 0x4010 | 40 | #define PCI_DEVICE_ID_QLOGIC_ISP4010 0x4010 |
@@ -46,6 +48,10 @@ | |||
46 | #define PCI_DEVICE_ID_QLOGIC_ISP4032 0x4032 | 48 | #define PCI_DEVICE_ID_QLOGIC_ISP4032 0x4032 |
47 | #endif | 49 | #endif |
48 | 50 | ||
51 | #ifndef PCI_DEVICE_ID_QLOGIC_ISP8022 | ||
52 | #define PCI_DEVICE_ID_QLOGIC_ISP8022 0x8022 | ||
53 | #endif | ||
54 | |||
49 | #define QLA_SUCCESS 0 | 55 | #define QLA_SUCCESS 0 |
50 | #define QLA_ERROR 1 | 56 | #define QLA_ERROR 1 |
51 | 57 | ||
@@ -85,15 +91,22 @@ | |||
85 | #define BIT_30 0x40000000 | 91 | #define BIT_30 0x40000000 |
86 | #define BIT_31 0x80000000 | 92 | #define BIT_31 0x80000000 |
87 | 93 | ||
94 | /** | ||
95 | * Macros to help code, maintain, etc. | ||
96 | **/ | ||
97 | #define ql4_printk(level, ha, format, arg...) \ | ||
98 | dev_printk(level , &((ha)->pdev->dev) , format , ## arg) | ||
99 | |||
100 | |||
88 | /* | 101 | /* |
89 | * Host adapter default definitions | 102 | * Host adapter default definitions |
90 | ***********************************/ | 103 | ***********************************/ |
91 | #define MAX_HBAS 16 | 104 | #define MAX_HBAS 16 |
92 | #define MAX_BUSES 1 | 105 | #define MAX_BUSES 1 |
93 | #define MAX_TARGETS (MAX_PRST_DEV_DB_ENTRIES + MAX_DEV_DB_ENTRIES) | 106 | #define MAX_TARGETS MAX_DEV_DB_ENTRIES |
94 | #define MAX_LUNS 0xffff | 107 | #define MAX_LUNS 0xffff |
95 | #define MAX_AEN_ENTRIES 256 /* should be > EXT_DEF_MAX_AEN_QUEUE */ | 108 | #define MAX_AEN_ENTRIES 256 /* should be > EXT_DEF_MAX_AEN_QUEUE */ |
96 | #define MAX_DDB_ENTRIES (MAX_PRST_DEV_DB_ENTRIES + MAX_DEV_DB_ENTRIES) | 109 | #define MAX_DDB_ENTRIES MAX_DEV_DB_ENTRIES |
97 | #define MAX_PDU_ENTRIES 32 | 110 | #define MAX_PDU_ENTRIES 32 |
98 | #define INVALID_ENTRY 0xFFFF | 111 | #define INVALID_ENTRY 0xFFFF |
99 | #define MAX_CMDS_TO_RISC 1024 | 112 | #define MAX_CMDS_TO_RISC 1024 |
@@ -134,7 +147,7 @@ | |||
134 | #define SOFT_RESET_TOV 30 | 147 | #define SOFT_RESET_TOV 30 |
135 | #define RESET_INTR_TOV 3 | 148 | #define RESET_INTR_TOV 3 |
136 | #define SEMAPHORE_TOV 10 | 149 | #define SEMAPHORE_TOV 10 |
137 | #define ADAPTER_INIT_TOV 120 | 150 | #define ADAPTER_INIT_TOV 30 |
138 | #define ADAPTER_RESET_TOV 180 | 151 | #define ADAPTER_RESET_TOV 180 |
139 | #define EXTEND_CMD_TOV 60 | 152 | #define EXTEND_CMD_TOV 60 |
140 | #define WAIT_CMD_TOV 30 | 153 | #define WAIT_CMD_TOV 30 |
@@ -184,8 +197,6 @@ struct srb { | |||
184 | uint16_t iocb_tov; | 197 | uint16_t iocb_tov; |
185 | uint16_t iocb_cnt; /* Number of used iocbs */ | 198 | uint16_t iocb_cnt; /* Number of used iocbs */ |
186 | uint16_t cc_stat; | 199 | uint16_t cc_stat; |
187 | u_long r_start; /* Time we recieve a cmd from OS */ | ||
188 | u_long u_start; /* Time when we handed the cmd to F/W */ | ||
189 | 200 | ||
190 | /* Used for extended sense / status continuation */ | 201 | /* Used for extended sense / status continuation */ |
191 | uint8_t *req_sense_ptr; | 202 | uint8_t *req_sense_ptr; |
@@ -221,7 +232,6 @@ struct ddb_entry { | |||
221 | unsigned long dev_scan_wait_to_start_relogin; | 232 | unsigned long dev_scan_wait_to_start_relogin; |
222 | unsigned long dev_scan_wait_to_complete_relogin; | 233 | unsigned long dev_scan_wait_to_complete_relogin; |
223 | 234 | ||
224 | uint16_t os_target_id; /* Target ID */ | ||
225 | uint16_t fw_ddb_index; /* DDB firmware index */ | 235 | uint16_t fw_ddb_index; /* DDB firmware index */ |
226 | uint16_t options; | 236 | uint16_t options; |
227 | uint32_t fw_ddb_device_state; /* F/W Device State -- see ql4_fw.h */ | 237 | uint32_t fw_ddb_device_state; /* F/W Device State -- see ql4_fw.h */ |
@@ -285,6 +295,67 @@ struct ddb_entry { | |||
285 | #include "ql4_fw.h" | 295 | #include "ql4_fw.h" |
286 | #include "ql4_nvram.h" | 296 | #include "ql4_nvram.h" |
287 | 297 | ||
298 | struct ql82xx_hw_data { | ||
299 | /* Offsets for flash/nvram access (set to ~0 if not used). */ | ||
300 | uint32_t flash_conf_off; | ||
301 | uint32_t flash_data_off; | ||
302 | |||
303 | uint32_t fdt_wrt_disable; | ||
304 | uint32_t fdt_erase_cmd; | ||
305 | uint32_t fdt_block_size; | ||
306 | uint32_t fdt_unprotect_sec_cmd; | ||
307 | uint32_t fdt_protect_sec_cmd; | ||
308 | |||
309 | uint32_t flt_region_flt; | ||
310 | uint32_t flt_region_fdt; | ||
311 | uint32_t flt_region_boot; | ||
312 | uint32_t flt_region_bootload; | ||
313 | uint32_t flt_region_fw; | ||
314 | uint32_t reserved; | ||
315 | }; | ||
316 | |||
317 | struct qla4_8xxx_legacy_intr_set { | ||
318 | uint32_t int_vec_bit; | ||
319 | uint32_t tgt_status_reg; | ||
320 | uint32_t tgt_mask_reg; | ||
321 | uint32_t pci_int_reg; | ||
322 | }; | ||
323 | |||
324 | /* MSI-X Support */ | ||
325 | |||
326 | #define QLA_MSIX_DEFAULT 0x00 | ||
327 | #define QLA_MSIX_RSP_Q 0x01 | ||
328 | |||
329 | #define QLA_MSIX_ENTRIES 2 | ||
330 | #define QLA_MIDX_DEFAULT 0 | ||
331 | #define QLA_MIDX_RSP_Q 1 | ||
332 | |||
333 | struct ql4_msix_entry { | ||
334 | int have_irq; | ||
335 | uint16_t msix_vector; | ||
336 | uint16_t msix_entry; | ||
337 | }; | ||
338 | |||
339 | /* | ||
340 | * ISP Operations | ||
341 | */ | ||
342 | struct isp_operations { | ||
343 | int (*iospace_config) (struct scsi_qla_host *ha); | ||
344 | void (*pci_config) (struct scsi_qla_host *); | ||
345 | void (*disable_intrs) (struct scsi_qla_host *); | ||
346 | void (*enable_intrs) (struct scsi_qla_host *); | ||
347 | int (*start_firmware) (struct scsi_qla_host *); | ||
348 | irqreturn_t (*intr_handler) (int , void *); | ||
349 | void (*interrupt_service_routine) (struct scsi_qla_host *, uint32_t); | ||
350 | int (*reset_chip) (struct scsi_qla_host *); | ||
351 | int (*reset_firmware) (struct scsi_qla_host *); | ||
352 | void (*queue_iocb) (struct scsi_qla_host *); | ||
353 | void (*complete_iocb) (struct scsi_qla_host *); | ||
354 | uint16_t (*rd_shdw_req_q_out) (struct scsi_qla_host *); | ||
355 | uint16_t (*rd_shdw_rsp_q_in) (struct scsi_qla_host *); | ||
356 | int (*get_sys_info) (struct scsi_qla_host *); | ||
357 | }; | ||
358 | |||
288 | /* | 359 | /* |
289 | * Linux Host Adapter structure | 360 | * Linux Host Adapter structure |
290 | */ | 361 | */ |
@@ -296,28 +367,39 @@ struct scsi_qla_host { | |||
296 | #define AF_INIT_DONE 1 /* 0x00000002 */ | 367 | #define AF_INIT_DONE 1 /* 0x00000002 */ |
297 | #define AF_MBOX_COMMAND 2 /* 0x00000004 */ | 368 | #define AF_MBOX_COMMAND 2 /* 0x00000004 */ |
298 | #define AF_MBOX_COMMAND_DONE 3 /* 0x00000008 */ | 369 | #define AF_MBOX_COMMAND_DONE 3 /* 0x00000008 */ |
370 | #define AF_DPC_SCHEDULED 5 /* 0x00000020 */ | ||
299 | #define AF_INTERRUPTS_ON 6 /* 0x00000040 */ | 371 | #define AF_INTERRUPTS_ON 6 /* 0x00000040 */ |
300 | #define AF_GET_CRASH_RECORD 7 /* 0x00000080 */ | 372 | #define AF_GET_CRASH_RECORD 7 /* 0x00000080 */ |
301 | #define AF_LINK_UP 8 /* 0x00000100 */ | 373 | #define AF_LINK_UP 8 /* 0x00000100 */ |
302 | #define AF_IRQ_ATTACHED 10 /* 0x00000400 */ | 374 | #define AF_IRQ_ATTACHED 10 /* 0x00000400 */ |
303 | #define AF_DISABLE_ACB_COMPLETE 11 /* 0x00000800 */ | 375 | #define AF_DISABLE_ACB_COMPLETE 11 /* 0x00000800 */ |
376 | #define AF_HBA_GOING_AWAY 12 /* 0x00001000 */ | ||
377 | #define AF_INTx_ENABLED 15 /* 0x00008000 */ | ||
378 | #define AF_MSI_ENABLED 16 /* 0x00010000 */ | ||
379 | #define AF_MSIX_ENABLED 17 /* 0x00020000 */ | ||
380 | #define AF_MBOX_COMMAND_NOPOLL 18 /* 0x00040000 */ | ||
381 | |||
304 | 382 | ||
305 | unsigned long dpc_flags; | 383 | unsigned long dpc_flags; |
306 | 384 | ||
307 | #define DPC_RESET_HA 1 /* 0x00000002 */ | 385 | #define DPC_RESET_HA 1 /* 0x00000002 */ |
308 | #define DPC_RETRY_RESET_HA 2 /* 0x00000004 */ | 386 | #define DPC_RETRY_RESET_HA 2 /* 0x00000004 */ |
309 | #define DPC_RELOGIN_DEVICE 3 /* 0x00000008 */ | 387 | #define DPC_RELOGIN_DEVICE 3 /* 0x00000008 */ |
310 | #define DPC_RESET_HA_DESTROY_DDB_LIST 4 /* 0x00000010 */ | 388 | #define DPC_RESET_HA_FW_CONTEXT 4 /* 0x00000010 */ |
311 | #define DPC_RESET_HA_INTR 5 /* 0x00000020 */ | 389 | #define DPC_RESET_HA_INTR 5 /* 0x00000020 */ |
312 | #define DPC_ISNS_RESTART 7 /* 0x00000080 */ | 390 | #define DPC_ISNS_RESTART 7 /* 0x00000080 */ |
313 | #define DPC_AEN 9 /* 0x00000200 */ | 391 | #define DPC_AEN 9 /* 0x00000200 */ |
314 | #define DPC_GET_DHCP_IP_ADDR 15 /* 0x00008000 */ | 392 | #define DPC_GET_DHCP_IP_ADDR 15 /* 0x00008000 */ |
315 | #define DPC_LINK_CHANGED 18 /* 0x00040000 */ | 393 | #define DPC_LINK_CHANGED 18 /* 0x00040000 */ |
394 | #define DPC_RESET_ACTIVE 20 /* 0x00040000 */ | ||
395 | #define DPC_HA_UNRECOVERABLE 21 /* 0x00080000 ISP-82xx only*/ | ||
396 | #define DPC_HA_NEED_QUIESCENT 22 /* 0x00100000 ISP-82xx only*/ | ||
397 | |||
316 | 398 | ||
317 | struct Scsi_Host *host; /* pointer to host data */ | 399 | struct Scsi_Host *host; /* pointer to host data */ |
318 | uint32_t tot_ddbs; | 400 | uint32_t tot_ddbs; |
319 | 401 | ||
320 | uint16_t iocb_cnt; | 402 | uint16_t iocb_cnt; |
321 | 403 | ||
322 | /* SRB cache. */ | 404 | /* SRB cache. */ |
323 | #define SRB_MIN_REQ 128 | 405 | #define SRB_MIN_REQ 128 |
@@ -332,14 +414,13 @@ struct scsi_qla_host { | |||
332 | #define MIN_IOBASE_LEN 0x100 | 414 | #define MIN_IOBASE_LEN 0x100 |
333 | 415 | ||
334 | uint16_t req_q_count; | 416 | uint16_t req_q_count; |
335 | uint8_t rsvd1[2]; | ||
336 | 417 | ||
337 | unsigned long host_no; | 418 | unsigned long host_no; |
338 | 419 | ||
339 | /* NVRAM registers */ | 420 | /* NVRAM registers */ |
340 | struct eeprom_data *nvram; | 421 | struct eeprom_data *nvram; |
341 | spinlock_t hardware_lock ____cacheline_aligned; | 422 | spinlock_t hardware_lock ____cacheline_aligned; |
342 | uint32_t eeprom_cmd_data; | 423 | uint32_t eeprom_cmd_data; |
343 | 424 | ||
344 | /* Counters for general statistics */ | 425 | /* Counters for general statistics */ |
345 | uint64_t isr_count; | 426 | uint64_t isr_count; |
@@ -375,7 +456,6 @@ struct scsi_qla_host { | |||
375 | uint8_t alias[32]; | 456 | uint8_t alias[32]; |
376 | uint8_t name_string[256]; | 457 | uint8_t name_string[256]; |
377 | uint8_t heartbeat_interval; | 458 | uint8_t heartbeat_interval; |
378 | uint8_t rsvd; | ||
379 | 459 | ||
380 | /* --- From FlashSysInfo --- */ | 460 | /* --- From FlashSysInfo --- */ |
381 | uint8_t my_mac[MAC_ADDR_LEN]; | 461 | uint8_t my_mac[MAC_ADDR_LEN]; |
@@ -469,6 +549,40 @@ struct scsi_qla_host { | |||
469 | struct in6_addr ipv6_addr0; | 549 | struct in6_addr ipv6_addr0; |
470 | struct in6_addr ipv6_addr1; | 550 | struct in6_addr ipv6_addr1; |
471 | struct in6_addr ipv6_default_router_addr; | 551 | struct in6_addr ipv6_default_router_addr; |
552 | |||
553 | /* qla82xx specific fields */ | ||
554 | struct device_reg_82xx __iomem *qla4_8xxx_reg; /* Base I/O address */ | ||
555 | unsigned long nx_pcibase; /* Base I/O address */ | ||
556 | uint8_t *nx_db_rd_ptr; /* Doorbell read pointer */ | ||
557 | unsigned long nx_db_wr_ptr; /* Door bell write pointer */ | ||
558 | unsigned long first_page_group_start; | ||
559 | unsigned long first_page_group_end; | ||
560 | |||
561 | uint32_t crb_win; | ||
562 | uint32_t curr_window; | ||
563 | uint32_t ddr_mn_window; | ||
564 | unsigned long mn_win_crb; | ||
565 | unsigned long ms_win_crb; | ||
566 | int qdr_sn_window; | ||
567 | rwlock_t hw_lock; | ||
568 | uint16_t func_num; | ||
569 | int link_width; | ||
570 | |||
571 | struct qla4_8xxx_legacy_intr_set nx_legacy_intr; | ||
572 | u32 nx_crb_mask; | ||
573 | |||
574 | uint8_t revision_id; | ||
575 | uint32_t fw_heartbeat_counter; | ||
576 | |||
577 | struct isp_operations *isp_ops; | ||
578 | struct ql82xx_hw_data hw; | ||
579 | |||
580 | struct ql4_msix_entry msix_entries[QLA_MSIX_ENTRIES]; | ||
581 | |||
582 | uint32_t nx_dev_init_timeout; | ||
583 | uint32_t nx_reset_timeout; | ||
584 | |||
585 | struct completion mbx_intr_comp; | ||
472 | }; | 586 | }; |
473 | 587 | ||
474 | static inline int is_ipv4_enabled(struct scsi_qla_host *ha) | 588 | 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) | |||
496 | return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP4032; | 610 | return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP4032; |
497 | } | 611 | } |
498 | 612 | ||
613 | static inline int is_qla8022(struct scsi_qla_host *ha) | ||
614 | { | ||
615 | return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8022; | ||
616 | } | ||
617 | |||
499 | static inline int adapter_up(struct scsi_qla_host *ha) | 618 | static inline int adapter_up(struct scsi_qla_host *ha) |
500 | { | 619 | { |
501 | return (test_bit(AF_ONLINE, &ha->flags) != 0) && | 620 | 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 855226e08665..c94c9ddfb3a6 100644 --- a/drivers/scsi/qla4xxx/ql4_fw.h +++ b/drivers/scsi/qla4xxx/ql4_fw.h | |||
@@ -11,7 +11,7 @@ | |||
11 | 11 | ||
12 | #define MAX_PRST_DEV_DB_ENTRIES 64 | 12 | #define MAX_PRST_DEV_DB_ENTRIES 64 |
13 | #define MIN_DISC_DEV_DB_ENTRY MAX_PRST_DEV_DB_ENTRIES | 13 | #define MIN_DISC_DEV_DB_ENTRY MAX_PRST_DEV_DB_ENTRIES |
14 | #define MAX_DEV_DB_ENTRIES 512 | 14 | #define MAX_DEV_DB_ENTRIES 512 |
15 | 15 | ||
16 | /************************************************************************* | 16 | /************************************************************************* |
17 | * | 17 | * |
@@ -37,6 +37,33 @@ struct host_mem_cfg_regs { | |||
37 | __le32 rsrvd1[31]; /* 0x84-0xFF */ | 37 | __le32 rsrvd1[31]; /* 0x84-0xFF */ |
38 | }; | 38 | }; |
39 | 39 | ||
40 | /* | ||
41 | * ISP 82xx I/O Register Set structure definitions. | ||
42 | */ | ||
43 | struct device_reg_82xx { | ||
44 | __le32 req_q_out; /* 0x0000 (R): Request Queue out-Pointer. */ | ||
45 | __le32 reserve1[63]; /* Request Queue out-Pointer. (64 * 4) */ | ||
46 | __le32 rsp_q_in; /* 0x0100 (R/W): Response Queue In-Pointer. */ | ||
47 | __le32 reserve2[63]; /* Response Queue In-Pointer. */ | ||
48 | __le32 rsp_q_out; /* 0x0200 (R/W): Response Queue Out-Pointer. */ | ||
49 | __le32 reserve3[63]; /* Response Queue Out-Pointer. */ | ||
50 | |||
51 | __le32 mailbox_in[8]; /* 0x0300 (R/W): Mail box In registers */ | ||
52 | __le32 reserve4[24]; | ||
53 | __le32 hint; /* 0x0380 (R/W): Host interrupt register */ | ||
54 | #define HINT_MBX_INT_PENDING BIT_0 | ||
55 | __le32 reserve5[31]; | ||
56 | __le32 mailbox_out[8]; /* 0x0400 (R): Mail box Out registers */ | ||
57 | __le32 reserve6[56]; | ||
58 | |||
59 | __le32 host_status; /* Offset 0x500 (R): host status */ | ||
60 | #define HSRX_RISC_MB_INT BIT_0 /* RISC to Host Mailbox interrupt */ | ||
61 | #define HSRX_RISC_IOCB_INT BIT_1 /* RISC to Host IOCB interrupt */ | ||
62 | |||
63 | __le32 host_int; /* Offset 0x0504 (R/W): Interrupt status. */ | ||
64 | #define ISRX_82XX_RISC_INT BIT_0 /* RISC interrupt. */ | ||
65 | }; | ||
66 | |||
40 | /* remote register set (access via PCI memory read/write) */ | 67 | /* remote register set (access via PCI memory read/write) */ |
41 | struct isp_reg { | 68 | struct isp_reg { |
42 | #define MBOX_REG_COUNT 8 | 69 | #define MBOX_REG_COUNT 8 |
@@ -206,6 +233,79 @@ union external_hw_config_reg { | |||
206 | uint32_t Asuint32_t; | 233 | uint32_t Asuint32_t; |
207 | }; | 234 | }; |
208 | 235 | ||
236 | /* 82XX Support start */ | ||
237 | /* 82xx Default FLT Addresses */ | ||
238 | #define FA_FLASH_LAYOUT_ADDR_82 0xFC400 | ||
239 | #define FA_FLASH_DESCR_ADDR_82 0xFC000 | ||
240 | #define FA_BOOT_LOAD_ADDR_82 0x04000 | ||
241 | #define FA_BOOT_CODE_ADDR_82 0x20000 | ||
242 | #define FA_RISC_CODE_ADDR_82 0x40000 | ||
243 | #define FA_GOLD_RISC_CODE_ADDR_82 0x80000 | ||
244 | |||
245 | /* Flash Description Table */ | ||
246 | struct qla_fdt_layout { | ||
247 | uint8_t sig[4]; | ||
248 | uint16_t version; | ||
249 | uint16_t len; | ||
250 | uint16_t checksum; | ||
251 | uint8_t unused1[2]; | ||
252 | uint8_t model[16]; | ||
253 | uint16_t man_id; | ||
254 | uint16_t id; | ||
255 | uint8_t flags; | ||
256 | uint8_t erase_cmd; | ||
257 | uint8_t alt_erase_cmd; | ||
258 | uint8_t wrt_enable_cmd; | ||
259 | uint8_t wrt_enable_bits; | ||
260 | uint8_t wrt_sts_reg_cmd; | ||
261 | uint8_t unprotect_sec_cmd; | ||
262 | uint8_t read_man_id_cmd; | ||
263 | uint32_t block_size; | ||
264 | uint32_t alt_block_size; | ||
265 | uint32_t flash_size; | ||
266 | uint32_t wrt_enable_data; | ||
267 | uint8_t read_id_addr_len; | ||
268 | uint8_t wrt_disable_bits; | ||
269 | uint8_t read_dev_id_len; | ||
270 | uint8_t chip_erase_cmd; | ||
271 | uint16_t read_timeout; | ||
272 | uint8_t protect_sec_cmd; | ||
273 | uint8_t unused2[65]; | ||
274 | }; | ||
275 | |||
276 | /* Flash Layout Table */ | ||
277 | |||
278 | struct qla_flt_location { | ||
279 | uint8_t sig[4]; | ||
280 | uint16_t start_lo; | ||
281 | uint16_t start_hi; | ||
282 | uint8_t version; | ||
283 | uint8_t unused[5]; | ||
284 | uint16_t checksum; | ||
285 | }; | ||
286 | |||
287 | struct qla_flt_header { | ||
288 | uint16_t version; | ||
289 | uint16_t length; | ||
290 | uint16_t checksum; | ||
291 | uint16_t unused; | ||
292 | }; | ||
293 | |||
294 | /* 82xx FLT Regions */ | ||
295 | #define FLT_REG_FDT 0x1a | ||
296 | #define FLT_REG_FLT 0x1c | ||
297 | #define FLT_REG_BOOTLOAD_82 0x72 | ||
298 | #define FLT_REG_FW_82 0x74 | ||
299 | #define FLT_REG_GOLD_FW_82 0x75 | ||
300 | #define FLT_REG_BOOT_CODE_82 0x78 | ||
301 | |||
302 | struct qla_flt_region { | ||
303 | uint32_t code; | ||
304 | uint32_t size; | ||
305 | uint32_t start; | ||
306 | uint32_t end; | ||
307 | }; | ||
308 | |||
209 | /************************************************************************* | 309 | /************************************************************************* |
210 | * | 310 | * |
211 | * Mailbox Commands Structures and Definitions | 311 | * Mailbox Commands Structures and Definitions |
@@ -215,6 +315,10 @@ union external_hw_config_reg { | |||
215 | /* Mailbox command definitions */ | 315 | /* Mailbox command definitions */ |
216 | #define MBOX_CMD_ABOUT_FW 0x0009 | 316 | #define MBOX_CMD_ABOUT_FW 0x0009 |
217 | #define MBOX_CMD_PING 0x000B | 317 | #define MBOX_CMD_PING 0x000B |
318 | #define MBOX_CMD_ENABLE_INTRS 0x0010 | ||
319 | #define INTR_DISABLE 0 | ||
320 | #define INTR_ENABLE 1 | ||
321 | #define MBOX_CMD_STOP_FW 0x0014 | ||
218 | #define MBOX_CMD_ABORT_TASK 0x0015 | 322 | #define MBOX_CMD_ABORT_TASK 0x0015 |
219 | #define MBOX_CMD_LUN_RESET 0x0016 | 323 | #define MBOX_CMD_LUN_RESET 0x0016 |
220 | #define MBOX_CMD_TARGET_WARM_RESET 0x0017 | 324 | #define MBOX_CMD_TARGET_WARM_RESET 0x0017 |
@@ -243,6 +347,7 @@ union external_hw_config_reg { | |||
243 | #define DDB_DS_LOGIN_IN_PROCESS 0x07 | 347 | #define DDB_DS_LOGIN_IN_PROCESS 0x07 |
244 | #define MBOX_CMD_GET_FW_STATE 0x0069 | 348 | #define MBOX_CMD_GET_FW_STATE 0x0069 |
245 | #define MBOX_CMD_GET_INIT_FW_CTRL_BLOCK_DEFAULTS 0x006A | 349 | #define MBOX_CMD_GET_INIT_FW_CTRL_BLOCK_DEFAULTS 0x006A |
350 | #define MBOX_CMD_GET_SYS_INFO 0x0078 | ||
246 | #define MBOX_CMD_RESTORE_FACTORY_DEFAULTS 0x0087 | 351 | #define MBOX_CMD_RESTORE_FACTORY_DEFAULTS 0x0087 |
247 | #define MBOX_CMD_SET_ACB 0x0088 | 352 | #define MBOX_CMD_SET_ACB 0x0088 |
248 | #define MBOX_CMD_GET_ACB 0x0089 | 353 | #define MBOX_CMD_GET_ACB 0x0089 |
@@ -318,6 +423,15 @@ union external_hw_config_reg { | |||
318 | #define MBOX_ASTS_IPSEC_SYSTEM_FATAL_ERROR 0x8022 | 423 | #define MBOX_ASTS_IPSEC_SYSTEM_FATAL_ERROR 0x8022 |
319 | #define MBOX_ASTS_SUBNET_STATE_CHANGE 0x8027 | 424 | #define MBOX_ASTS_SUBNET_STATE_CHANGE 0x8027 |
320 | 425 | ||
426 | /* ACB State Defines */ | ||
427 | #define ACB_STATE_UNCONFIGURED 0x00 | ||
428 | #define ACB_STATE_INVALID 0x01 | ||
429 | #define ACB_STATE_ACQUIRING 0x02 | ||
430 | #define ACB_STATE_TENTATIVE 0x03 | ||
431 | #define ACB_STATE_DEPRICATED 0x04 | ||
432 | #define ACB_STATE_VALID 0x05 | ||
433 | #define ACB_STATE_DISABLING 0x06 | ||
434 | |||
321 | /*************************************************************************/ | 435 | /*************************************************************************/ |
322 | 436 | ||
323 | /* Host Adapter Initialization Control Block (from host) */ | 437 | /* Host Adapter Initialization Control Block (from host) */ |
@@ -558,6 +672,20 @@ struct flash_sys_info { | |||
558 | uint32_t reserved1[39]; /* 170-1ff */ | 672 | uint32_t reserved1[39]; /* 170-1ff */ |
559 | }; /* 200 */ | 673 | }; /* 200 */ |
560 | 674 | ||
675 | struct mbx_sys_info { | ||
676 | uint8_t board_id_str[16]; /* Keep board ID string first */ | ||
677 | /* in this structure for GUI. */ | ||
678 | uint16_t board_id; /* board ID code */ | ||
679 | uint16_t phys_port_cnt; /* number of physical network ports */ | ||
680 | uint16_t port_num; /* network port for this PCI function */ | ||
681 | /* (port 0 is first port) */ | ||
682 | uint8_t mac_addr[6]; /* MAC address for this PCI function */ | ||
683 | uint32_t iscsi_pci_func_cnt; /* number of iSCSI PCI functions */ | ||
684 | uint32_t pci_func; /* this PCI function */ | ||
685 | unsigned char serial_number[16]; /* serial number string */ | ||
686 | uint8_t reserved[16]; | ||
687 | }; | ||
688 | |||
561 | struct crash_record { | 689 | struct crash_record { |
562 | uint16_t fw_major_version; /* 00 - 01 */ | 690 | uint16_t fw_major_version; /* 00 - 01 */ |
563 | uint16_t fw_minor_version; /* 02 - 03 */ | 691 | uint16_t fw_minor_version; /* 02 - 03 */ |
@@ -814,4 +942,13 @@ struct passthru_status { | |||
814 | uint8_t res4[16]; /* 30-3F */ | 942 | uint8_t res4[16]; /* 30-3F */ |
815 | }; | 943 | }; |
816 | 944 | ||
945 | /* | ||
946 | * ISP queue - response queue entry definition. | ||
947 | */ | ||
948 | struct response { | ||
949 | uint8_t data[60]; | ||
950 | uint32_t signature; | ||
951 | #define RESPONSE_PROCESSED 0xDEADDEAD /* Signature */ | ||
952 | }; | ||
953 | |||
817 | #endif /* _QLA4X_FW_H */ | 954 | #endif /* _QLA4X_FW_H */ |
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index c4636f6cb3cb..c9cd5d6db982 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h | |||
@@ -10,31 +10,32 @@ | |||
10 | 10 | ||
11 | struct iscsi_cls_conn; | 11 | struct iscsi_cls_conn; |
12 | 12 | ||
13 | void qla4xxx_hw_reset(struct scsi_qla_host *ha); | 13 | int qla4xxx_hw_reset(struct scsi_qla_host *ha); |
14 | int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a); | 14 | int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a); |
15 | int qla4xxx_send_tgts(struct scsi_qla_host *ha, char *ip, uint16_t port); | 15 | int qla4xxx_send_tgts(struct scsi_qla_host *ha, char *ip, uint16_t port); |
16 | int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb); | 16 | int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb *srb); |
17 | int qla4xxx_initialize_adapter(struct scsi_qla_host * ha, | 17 | int qla4xxx_initialize_adapter(struct scsi_qla_host *ha, |
18 | uint8_t renew_ddb_list); | 18 | uint8_t renew_ddb_list); |
19 | int qla4xxx_soft_reset(struct scsi_qla_host *ha); | 19 | int qla4xxx_soft_reset(struct scsi_qla_host *ha); |
20 | irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id); | 20 | irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id); |
21 | 21 | ||
22 | void qla4xxx_free_ddb_list(struct scsi_qla_host * ha); | 22 | void qla4xxx_free_ddb_list(struct scsi_qla_host *ha); |
23 | void qla4xxx_process_aen(struct scsi_qla_host * ha, uint8_t process_aen); | 23 | void qla4xxx_free_ddb(struct scsi_qla_host *ha, struct ddb_entry *ddb_entry); |
24 | void qla4xxx_process_aen(struct scsi_qla_host *ha, uint8_t process_aen); | ||
24 | 25 | ||
25 | int qla4xxx_get_dhcp_ip_address(struct scsi_qla_host * ha); | 26 | int qla4xxx_get_dhcp_ip_address(struct scsi_qla_host *ha); |
26 | int qla4xxx_relogin_device(struct scsi_qla_host * ha, | 27 | int qla4xxx_relogin_device(struct scsi_qla_host *ha, |
27 | struct ddb_entry * ddb_entry); | 28 | struct ddb_entry *ddb_entry); |
28 | int qla4xxx_abort_task(struct scsi_qla_host *ha, struct srb *srb); | 29 | int qla4xxx_abort_task(struct scsi_qla_host *ha, struct srb *srb); |
29 | int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry, | 30 | int qla4xxx_reset_lun(struct scsi_qla_host *ha, struct ddb_entry *ddb_entry, |
30 | int lun); | 31 | int lun); |
31 | int qla4xxx_reset_target(struct scsi_qla_host * ha, | 32 | int qla4xxx_reset_target(struct scsi_qla_host *ha, |
32 | struct ddb_entry * ddb_entry); | 33 | struct ddb_entry *ddb_entry); |
33 | int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr, | 34 | int qla4xxx_get_flash(struct scsi_qla_host *ha, dma_addr_t dma_addr, |
34 | uint32_t offset, uint32_t len); | 35 | uint32_t offset, uint32_t len); |
35 | int qla4xxx_get_firmware_status(struct scsi_qla_host * ha); | 36 | int qla4xxx_get_firmware_status(struct scsi_qla_host *ha); |
36 | int qla4xxx_get_firmware_state(struct scsi_qla_host * ha); | 37 | int qla4xxx_get_firmware_state(struct scsi_qla_host *ha); |
37 | int qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha); | 38 | int qla4xxx_initialize_fw_cb(struct scsi_qla_host *ha); |
38 | 39 | ||
39 | /* FIXME: Goodness! this really wants a small struct to hold the | 40 | /* FIXME: Goodness! this really wants a small struct to hold the |
40 | * parameters. On x86 the args will get passed on the stack! */ | 41 | * 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, | |||
54 | 55 | ||
55 | void qla4xxx_mark_device_missing(struct scsi_qla_host *ha, | 56 | void qla4xxx_mark_device_missing(struct scsi_qla_host *ha, |
56 | struct ddb_entry *ddb_entry); | 57 | struct ddb_entry *ddb_entry); |
57 | u16 rd_nvram_word(struct scsi_qla_host * ha, int offset); | 58 | u16 rd_nvram_word(struct scsi_qla_host *ha, int offset); |
58 | void qla4xxx_get_crash_record(struct scsi_qla_host * ha); | 59 | void qla4xxx_get_crash_record(struct scsi_qla_host *ha); |
59 | struct ddb_entry *qla4xxx_alloc_sess(struct scsi_qla_host *ha); | 60 | struct ddb_entry *qla4xxx_alloc_sess(struct scsi_qla_host *ha); |
60 | int qla4xxx_add_sess(struct ddb_entry *); | 61 | int qla4xxx_add_sess(struct ddb_entry *); |
61 | void qla4xxx_destroy_sess(struct ddb_entry *ddb_entry); | 62 | void qla4xxx_destroy_sess(struct ddb_entry *ddb_entry); |
62 | int qla4xxx_is_nvram_configuration_valid(struct scsi_qla_host * ha); | 63 | int qla4xxx_is_nvram_configuration_valid(struct scsi_qla_host *ha); |
63 | int qla4xxx_get_fw_version(struct scsi_qla_host * ha); | 64 | int qla4xxx_get_fw_version(struct scsi_qla_host * ha); |
64 | void qla4xxx_interrupt_service_routine(struct scsi_qla_host * ha, | 65 | void qla4xxx_interrupt_service_routine(struct scsi_qla_host *ha, |
65 | uint32_t intr_status); | 66 | uint32_t intr_status); |
66 | int qla4xxx_init_rings(struct scsi_qla_host * ha); | 67 | int qla4xxx_init_rings(struct scsi_qla_host *ha); |
67 | struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha, | ||
68 | uint32_t index); | ||
69 | void qla4xxx_srb_compl(struct kref *ref); | 68 | void qla4xxx_srb_compl(struct kref *ref); |
70 | int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host * ha); | 69 | struct srb *qla4xxx_del_from_active_array(struct scsi_qla_host *ha, |
70 | uint32_t index); | ||
71 | int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host *ha); | ||
71 | int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index, | 72 | int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index, |
72 | uint32_t state, uint32_t conn_error); | 73 | uint32_t state, uint32_t conn_error); |
73 | void qla4xxx_dump_buffer(void *b, uint32_t size); | 74 | void qla4xxx_dump_buffer(void *b, uint32_t size); |
@@ -75,8 +76,65 @@ int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha, | |||
75 | struct ddb_entry *ddb_entry, int lun, uint16_t mrkr_mod); | 76 | struct ddb_entry *ddb_entry, int lun, uint16_t mrkr_mod); |
76 | int qla4_is_relogin_allowed(struct scsi_qla_host *ha, uint32_t conn_err); | 77 | int qla4_is_relogin_allowed(struct scsi_qla_host *ha, uint32_t conn_err); |
77 | 78 | ||
79 | int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, | ||
80 | uint8_t outCount, uint32_t *mbx_cmd, uint32_t *mbx_sts); | ||
81 | |||
82 | void qla4xxx_queue_iocb(struct scsi_qla_host *ha); | ||
83 | void qla4xxx_complete_iocb(struct scsi_qla_host *ha); | ||
84 | int qla4xxx_get_sys_info(struct scsi_qla_host *ha); | ||
85 | int qla4xxx_iospace_config(struct scsi_qla_host *ha); | ||
86 | void qla4xxx_pci_config(struct scsi_qla_host *ha); | ||
87 | int qla4xxx_start_firmware(struct scsi_qla_host *ha); | ||
88 | irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id); | ||
89 | uint16_t qla4xxx_rd_shdw_req_q_out(struct scsi_qla_host *ha); | ||
90 | uint16_t qla4xxx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha); | ||
91 | int qla4xxx_request_irqs(struct scsi_qla_host *ha); | ||
92 | void qla4xxx_free_irqs(struct scsi_qla_host *ha); | ||
93 | void qla4xxx_process_response_queue(struct scsi_qla_host *ha); | ||
94 | void qla4xxx_wake_dpc(struct scsi_qla_host *ha); | ||
95 | void qla4xxx_get_conn_event_log(struct scsi_qla_host *ha); | ||
96 | |||
97 | void qla4_8xxx_pci_config(struct scsi_qla_host *); | ||
98 | int qla4_8xxx_iospace_config(struct scsi_qla_host *ha); | ||
99 | int qla4_8xxx_load_risc(struct scsi_qla_host *); | ||
100 | irqreturn_t qla4_8xxx_intr_handler(int irq, void *dev_id); | ||
101 | void qla4_8xxx_queue_iocb(struct scsi_qla_host *ha); | ||
102 | void qla4_8xxx_complete_iocb(struct scsi_qla_host *ha); | ||
103 | |||
104 | int qla4_8xxx_crb_win_lock(struct scsi_qla_host *); | ||
105 | void qla4_8xxx_crb_win_unlock(struct scsi_qla_host *); | ||
106 | int qla4_8xxx_pci_get_crb_addr_2M(struct scsi_qla_host *, ulong *); | ||
107 | void qla4_8xxx_wr_32(struct scsi_qla_host *, ulong, u32); | ||
108 | int qla4_8xxx_rd_32(struct scsi_qla_host *, ulong); | ||
109 | int qla4_8xxx_pci_mem_read_2M(struct scsi_qla_host *, u64, void *, int); | ||
110 | int qla4_8xxx_pci_mem_write_2M(struct scsi_qla_host *ha, u64, void *, int); | ||
111 | int qla4_8xxx_isp_reset(struct scsi_qla_host *ha); | ||
112 | void qla4_8xxx_interrupt_service_routine(struct scsi_qla_host *ha, | ||
113 | uint32_t intr_status); | ||
114 | uint16_t qla4_8xxx_rd_shdw_req_q_out(struct scsi_qla_host *ha); | ||
115 | uint16_t qla4_8xxx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha); | ||
116 | int qla4_8xxx_get_sys_info(struct scsi_qla_host *ha); | ||
117 | void qla4_8xxx_watchdog(struct scsi_qla_host *ha); | ||
118 | int qla4_8xxx_stop_firmware(struct scsi_qla_host *ha); | ||
119 | int qla4_8xxx_get_flash_info(struct scsi_qla_host *ha); | ||
120 | void qla4_8xxx_enable_intrs(struct scsi_qla_host *ha); | ||
121 | void qla4_8xxx_disable_intrs(struct scsi_qla_host *ha); | ||
122 | int qla4_8xxx_enable_msix(struct scsi_qla_host *ha); | ||
123 | void qla4_8xxx_disable_msix(struct scsi_qla_host *ha); | ||
124 | irqreturn_t qla4_8xxx_msi_handler(int irq, void *dev_id); | ||
125 | irqreturn_t qla4_8xxx_default_intr_handler(int irq, void *dev_id); | ||
126 | irqreturn_t qla4_8xxx_msix_rsp_q(int irq, void *dev_id); | ||
127 | void qla4xxx_mark_all_devices_missing(struct scsi_qla_host *ha); | ||
128 | void qla4xxx_dead_adapter_cleanup(struct scsi_qla_host *ha); | ||
129 | int qla4_8xxx_idc_lock(struct scsi_qla_host *ha); | ||
130 | void qla4_8xxx_idc_unlock(struct scsi_qla_host *ha); | ||
131 | int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha); | ||
132 | void qla4_8xxx_need_qsnt_handler(struct scsi_qla_host *ha); | ||
133 | void qla4_8xxx_clear_drv_active(struct scsi_qla_host *ha); | ||
134 | |||
78 | extern int ql4xextended_error_logging; | 135 | extern int ql4xextended_error_logging; |
79 | extern int ql4xdiscoverywait; | 136 | extern int ql4xdiscoverywait; |
80 | extern int ql4xdontresethba; | 137 | extern int ql4xdontresethba; |
81 | extern int ql4_mod_unload; | 138 | extern int ql4xenablemsix; |
139 | |||
82 | #endif /* _QLA4x_GBL_H */ | 140 | #endif /* _QLA4x_GBL_H */ |
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index 4a332c32d71e..539546df0376 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c | |||
@@ -11,8 +11,8 @@ | |||
11 | #include "ql4_dbg.h" | 11 | #include "ql4_dbg.h" |
12 | #include "ql4_inline.h" | 12 | #include "ql4_inline.h" |
13 | 13 | ||
14 | static struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha, | 14 | static struct ddb_entry *qla4xxx_alloc_ddb(struct scsi_qla_host *ha, |
15 | uint32_t fw_ddb_index); | 15 | uint32_t fw_ddb_index); |
16 | 16 | ||
17 | static void ql4xxx_set_mac_number(struct scsi_qla_host *ha) | 17 | static void ql4xxx_set_mac_number(struct scsi_qla_host *ha) |
18 | { | 18 | { |
@@ -51,8 +51,8 @@ static void ql4xxx_set_mac_number(struct scsi_qla_host *ha) | |||
51 | * This routine deallocates and unlinks the specified ddb_entry from the | 51 | * This routine deallocates and unlinks the specified ddb_entry from the |
52 | * adapter's | 52 | * adapter's |
53 | **/ | 53 | **/ |
54 | static void qla4xxx_free_ddb(struct scsi_qla_host *ha, | 54 | void qla4xxx_free_ddb(struct scsi_qla_host *ha, |
55 | struct ddb_entry *ddb_entry) | 55 | struct ddb_entry *ddb_entry) |
56 | { | 56 | { |
57 | /* Remove device entry from list */ | 57 | /* Remove device entry from list */ |
58 | list_del_init(&ddb_entry->list); | 58 | list_del_init(&ddb_entry->list); |
@@ -86,6 +86,25 @@ void qla4xxx_free_ddb_list(struct scsi_qla_host *ha) | |||
86 | } | 86 | } |
87 | 87 | ||
88 | /** | 88 | /** |
89 | * qla4xxx_init_response_q_entries() - Initializes response queue entries. | ||
90 | * @ha: HA context | ||
91 | * | ||
92 | * Beginning of request ring has initialization control block already built | ||
93 | * by nvram config routine. | ||
94 | **/ | ||
95 | static void qla4xxx_init_response_q_entries(struct scsi_qla_host *ha) | ||
96 | { | ||
97 | uint16_t cnt; | ||
98 | struct response *pkt; | ||
99 | |||
100 | pkt = (struct response *)ha->response_ptr; | ||
101 | for (cnt = 0; cnt < RESPONSE_QUEUE_DEPTH; cnt++) { | ||
102 | pkt->signature = RESPONSE_PROCESSED; | ||
103 | pkt++; | ||
104 | } | ||
105 | } | ||
106 | |||
107 | /** | ||
89 | * qla4xxx_init_rings - initialize hw queues | 108 | * qla4xxx_init_rings - initialize hw queues |
90 | * @ha: pointer to host adapter structure. | 109 | * @ha: pointer to host adapter structure. |
91 | * | 110 | * |
@@ -109,19 +128,31 @@ int qla4xxx_init_rings(struct scsi_qla_host *ha) | |||
109 | ha->response_out = 0; | 128 | ha->response_out = 0; |
110 | ha->response_ptr = &ha->response_ring[ha->response_out]; | 129 | ha->response_ptr = &ha->response_ring[ha->response_out]; |
111 | 130 | ||
112 | /* | 131 | if (is_qla8022(ha)) { |
113 | * Initialize DMA Shadow registers. The firmware is really supposed to | 132 | writel(0, |
114 | * take care of this, but on some uniprocessor systems, the shadow | 133 | (unsigned long __iomem *)&ha->qla4_8xxx_reg->req_q_out); |
115 | * registers aren't cleared-- causing the interrupt_handler to think | 134 | writel(0, |
116 | * there are responses to be processed when there aren't. | 135 | (unsigned long __iomem *)&ha->qla4_8xxx_reg->rsp_q_in); |
117 | */ | 136 | writel(0, |
118 | ha->shadow_regs->req_q_out = __constant_cpu_to_le32(0); | 137 | (unsigned long __iomem *)&ha->qla4_8xxx_reg->rsp_q_out); |
119 | ha->shadow_regs->rsp_q_in = __constant_cpu_to_le32(0); | 138 | } else { |
120 | wmb(); | 139 | /* |
140 | * Initialize DMA Shadow registers. The firmware is really | ||
141 | * supposed to take care of this, but on some uniprocessor | ||
142 | * systems, the shadow registers aren't cleared-- causing | ||
143 | * the interrupt_handler to think there are responses to be | ||
144 | * processed when there aren't. | ||
145 | */ | ||
146 | ha->shadow_regs->req_q_out = __constant_cpu_to_le32(0); | ||
147 | ha->shadow_regs->rsp_q_in = __constant_cpu_to_le32(0); | ||
148 | wmb(); | ||
121 | 149 | ||
122 | writel(0, &ha->reg->req_q_in); | 150 | writel(0, &ha->reg->req_q_in); |
123 | writel(0, &ha->reg->rsp_q_out); | 151 | writel(0, &ha->reg->rsp_q_out); |
124 | readl(&ha->reg->rsp_q_out); | 152 | readl(&ha->reg->rsp_q_out); |
153 | } | ||
154 | |||
155 | qla4xxx_init_response_q_entries(ha); | ||
125 | 156 | ||
126 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 157 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
127 | 158 | ||
@@ -129,11 +160,11 @@ int qla4xxx_init_rings(struct scsi_qla_host *ha) | |||
129 | } | 160 | } |
130 | 161 | ||
131 | /** | 162 | /** |
132 | * qla4xxx_validate_mac_address - validate adapter MAC address(es) | 163 | * qla4xxx_get_sys_info - validate adapter MAC address(es) |
133 | * @ha: pointer to host adapter structure. | 164 | * @ha: pointer to host adapter structure. |
134 | * | 165 | * |
135 | **/ | 166 | **/ |
136 | static int qla4xxx_validate_mac_address(struct scsi_qla_host *ha) | 167 | int qla4xxx_get_sys_info(struct scsi_qla_host *ha) |
137 | { | 168 | { |
138 | struct flash_sys_info *sys_info; | 169 | struct flash_sys_info *sys_info; |
139 | dma_addr_t sys_info_dma; | 170 | dma_addr_t sys_info_dma; |
@@ -145,7 +176,7 @@ static int qla4xxx_validate_mac_address(struct scsi_qla_host *ha) | |||
145 | DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n", | 176 | DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n", |
146 | ha->host_no, __func__)); | 177 | ha->host_no, __func__)); |
147 | 178 | ||
148 | goto exit_validate_mac_no_free; | 179 | goto exit_get_sys_info_no_free; |
149 | } | 180 | } |
150 | memset(sys_info, 0, sizeof(*sys_info)); | 181 | memset(sys_info, 0, sizeof(*sys_info)); |
151 | 182 | ||
@@ -155,7 +186,7 @@ static int qla4xxx_validate_mac_address(struct scsi_qla_host *ha) | |||
155 | DEBUG2(printk("scsi%ld: %s: get_flash FLASH_OFFSET_SYS_INFO " | 186 | DEBUG2(printk("scsi%ld: %s: get_flash FLASH_OFFSET_SYS_INFO " |
156 | "failed\n", ha->host_no, __func__)); | 187 | "failed\n", ha->host_no, __func__)); |
157 | 188 | ||
158 | goto exit_validate_mac; | 189 | goto exit_get_sys_info; |
159 | } | 190 | } |
160 | 191 | ||
161 | /* Save M.A.C. address & serial_number */ | 192 | /* Save M.A.C. address & serial_number */ |
@@ -168,11 +199,11 @@ static int qla4xxx_validate_mac_address(struct scsi_qla_host *ha) | |||
168 | 199 | ||
169 | status = QLA_SUCCESS; | 200 | status = QLA_SUCCESS; |
170 | 201 | ||
171 | exit_validate_mac: | 202 | exit_get_sys_info: |
172 | dma_free_coherent(&ha->pdev->dev, sizeof(*sys_info), sys_info, | 203 | dma_free_coherent(&ha->pdev->dev, sizeof(*sys_info), sys_info, |
173 | sys_info_dma); | 204 | sys_info_dma); |
174 | 205 | ||
175 | exit_validate_mac_no_free: | 206 | exit_get_sys_info_no_free: |
176 | return status; | 207 | return status; |
177 | } | 208 | } |
178 | 209 | ||
@@ -584,21 +615,19 @@ static int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha, | |||
584 | min(sizeof(ddb_entry->link_local_ipv6_addr), | 615 | min(sizeof(ddb_entry->link_local_ipv6_addr), |
585 | sizeof(fw_ddb_entry->link_local_ipv6_addr))); | 616 | sizeof(fw_ddb_entry->link_local_ipv6_addr))); |
586 | 617 | ||
587 | DEBUG2(dev_info(&ha->pdev->dev, "%s: DDB[%d] osIdx = %d " | 618 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s: DDB[%d] State %04x" |
588 | "State %04x ConnErr %08x IP %pI6 " | 619 | " ConnErr %08x IP %pI6 " |
589 | ":%04d \"%s\"\n", | 620 | ":%04d \"%s\"\n", |
590 | __func__, fw_ddb_index, | 621 | __func__, fw_ddb_index, |
591 | ddb_entry->os_target_id, | ||
592 | ddb_entry->fw_ddb_device_state, | 622 | ddb_entry->fw_ddb_device_state, |
593 | conn_err, fw_ddb_entry->ip_addr, | 623 | conn_err, fw_ddb_entry->ip_addr, |
594 | le16_to_cpu(fw_ddb_entry->port), | 624 | le16_to_cpu(fw_ddb_entry->port), |
595 | fw_ddb_entry->iscsi_name)); | 625 | fw_ddb_entry->iscsi_name)); |
596 | } else | 626 | } else |
597 | DEBUG2(dev_info(&ha->pdev->dev, "%s: DDB[%d] osIdx = %d " | 627 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s: DDB[%d] State %04x" |
598 | "State %04x ConnErr %08x IP %pI4 " | 628 | " ConnErr %08x IP %pI4 " |
599 | ":%04d \"%s\"\n", | 629 | ":%04d \"%s\"\n", |
600 | __func__, fw_ddb_index, | 630 | __func__, fw_ddb_index, |
601 | ddb_entry->os_target_id, | ||
602 | ddb_entry->fw_ddb_device_state, | 631 | ddb_entry->fw_ddb_device_state, |
603 | conn_err, fw_ddb_entry->ip_addr, | 632 | conn_err, fw_ddb_entry->ip_addr, |
604 | le16_to_cpu(fw_ddb_entry->port), | 633 | le16_to_cpu(fw_ddb_entry->port), |
@@ -984,7 +1013,7 @@ static int qla4xxx_initialize_ddb_list(struct scsi_qla_host *ha) | |||
984 | } | 1013 | } |
985 | 1014 | ||
986 | /** | 1015 | /** |
987 | * qla4xxx_update_ddb_list - update the driver ddb list | 1016 | * qla4xxx_reinitialize_ddb_list - update the driver ddb list |
988 | * @ha: pointer to host adapter structure. | 1017 | * @ha: pointer to host adapter structure. |
989 | * | 1018 | * |
990 | * This routine obtains device information from the F/W database after | 1019 | * This routine obtains device information from the F/W database after |
@@ -1028,7 +1057,7 @@ int qla4xxx_relogin_device(struct scsi_qla_host *ha, | |||
1028 | (uint16_t)RELOGIN_TOV); | 1057 | (uint16_t)RELOGIN_TOV); |
1029 | atomic_set(&ddb_entry->relogin_timer, relogin_timer); | 1058 | atomic_set(&ddb_entry->relogin_timer, relogin_timer); |
1030 | 1059 | ||
1031 | DEBUG2(printk("scsi%ld: Relogin index [%d]. TOV=%d\n", ha->host_no, | 1060 | DEBUG2(printk("scsi%ld: Relogin ddb [%d]. TOV=%d\n", ha->host_no, |
1032 | ddb_entry->fw_ddb_index, relogin_timer)); | 1061 | ddb_entry->fw_ddb_index, relogin_timer)); |
1033 | 1062 | ||
1034 | qla4xxx_set_ddb_entry(ha, ddb_entry->fw_ddb_index, 0); | 1063 | 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) | |||
1085 | return QLA_SUCCESS; | 1114 | return QLA_SUCCESS; |
1086 | } | 1115 | } |
1087 | 1116 | ||
1088 | static void qla4x00_pci_config(struct scsi_qla_host *ha) | 1117 | /** |
1118 | * qla4_8xxx_pci_config() - Setup ISP82xx PCI configuration registers. | ||
1119 | * @ha: HA context | ||
1120 | */ | ||
1121 | void qla4_8xxx_pci_config(struct scsi_qla_host *ha) | ||
1122 | { | ||
1123 | pci_set_master(ha->pdev); | ||
1124 | } | ||
1125 | |||
1126 | void qla4xxx_pci_config(struct scsi_qla_host *ha) | ||
1089 | { | 1127 | { |
1090 | uint16_t w; | 1128 | uint16_t w; |
1091 | int status; | 1129 | int status; |
@@ -1216,7 +1254,7 @@ int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a) | |||
1216 | * This routine performs the necessary steps to start the firmware for | 1254 | * This routine performs the necessary steps to start the firmware for |
1217 | * the QLA4010 adapter. | 1255 | * the QLA4010 adapter. |
1218 | **/ | 1256 | **/ |
1219 | static int qla4xxx_start_firmware(struct scsi_qla_host *ha) | 1257 | int qla4xxx_start_firmware(struct scsi_qla_host *ha) |
1220 | { | 1258 | { |
1221 | unsigned long flags = 0; | 1259 | unsigned long flags = 0; |
1222 | uint32_t mbox_status; | 1260 | uint32_t mbox_status; |
@@ -1295,7 +1333,8 @@ static int qla4xxx_start_firmware(struct scsi_qla_host *ha) | |||
1295 | if (soft_reset) { | 1333 | if (soft_reset) { |
1296 | DEBUG(printk("scsi%ld: %s: Issue Soft Reset\n", ha->host_no, | 1334 | DEBUG(printk("scsi%ld: %s: Issue Soft Reset\n", ha->host_no, |
1297 | __func__)); | 1335 | __func__)); |
1298 | status = qla4xxx_soft_reset(ha); | 1336 | status = qla4xxx_soft_reset(ha); /* NOTE: acquires drvr |
1337 | * lock again, but ok */ | ||
1299 | if (status == QLA_ERROR) { | 1338 | if (status == QLA_ERROR) { |
1300 | DEBUG(printk("scsi%d: %s: Soft Reset failed!\n", | 1339 | DEBUG(printk("scsi%d: %s: Soft Reset failed!\n", |
1301 | ha->host_no, __func__)); | 1340 | ha->host_no, __func__)); |
@@ -1316,7 +1355,6 @@ static int qla4xxx_start_firmware(struct scsi_qla_host *ha) | |||
1316 | 1355 | ||
1317 | ql4xxx_unlock_drvr(ha); | 1356 | ql4xxx_unlock_drvr(ha); |
1318 | if (status == QLA_SUCCESS) { | 1357 | if (status == QLA_SUCCESS) { |
1319 | qla4xxx_get_fw_version(ha); | ||
1320 | if (test_and_clear_bit(AF_GET_CRASH_RECORD, &ha->flags)) | 1358 | if (test_and_clear_bit(AF_GET_CRASH_RECORD, &ha->flags)) |
1321 | qla4xxx_get_crash_record(ha); | 1359 | qla4xxx_get_crash_record(ha); |
1322 | } else { | 1360 | } else { |
@@ -1343,18 +1381,21 @@ int qla4xxx_initialize_adapter(struct scsi_qla_host *ha, | |||
1343 | int status = QLA_ERROR; | 1381 | int status = QLA_ERROR; |
1344 | int8_t ip_address[IP_ADDR_LEN] = {0} ; | 1382 | int8_t ip_address[IP_ADDR_LEN] = {0} ; |
1345 | 1383 | ||
1346 | clear_bit(AF_ONLINE, &ha->flags); | ||
1347 | ha->eeprom_cmd_data = 0; | 1384 | ha->eeprom_cmd_data = 0; |
1348 | 1385 | ||
1349 | qla4x00_pci_config(ha); | 1386 | ql4_printk(KERN_INFO, ha, "Configuring PCI space...\n"); |
1387 | ha->isp_ops->pci_config(ha); | ||
1350 | 1388 | ||
1351 | qla4xxx_disable_intrs(ha); | 1389 | ha->isp_ops->disable_intrs(ha); |
1352 | 1390 | ||
1353 | /* Initialize the Host adapter request/response queues and firmware */ | 1391 | /* Initialize the Host adapter request/response queues and firmware */ |
1354 | if (qla4xxx_start_firmware(ha) == QLA_ERROR) | 1392 | if (ha->isp_ops->start_firmware(ha) == QLA_ERROR) |
1393 | goto exit_init_hba; | ||
1394 | |||
1395 | if (qla4xxx_get_fw_version(ha) == QLA_ERROR) | ||
1355 | goto exit_init_hba; | 1396 | goto exit_init_hba; |
1356 | 1397 | ||
1357 | if (qla4xxx_validate_mac_address(ha) == QLA_ERROR) | 1398 | if (ha->isp_ops->get_sys_info(ha) == QLA_ERROR) |
1358 | goto exit_init_hba; | 1399 | goto exit_init_hba; |
1359 | 1400 | ||
1360 | if (qla4xxx_init_local_data(ha) == QLA_ERROR) | 1401 | if (qla4xxx_init_local_data(ha) == QLA_ERROR) |
@@ -1407,6 +1448,8 @@ int qla4xxx_initialize_adapter(struct scsi_qla_host *ha, | |||
1407 | exit_init_online: | 1448 | exit_init_online: |
1408 | set_bit(AF_ONLINE, &ha->flags); | 1449 | set_bit(AF_ONLINE, &ha->flags); |
1409 | exit_init_hba: | 1450 | exit_init_hba: |
1451 | DEBUG2(printk("scsi%ld: initialize adapter: %s\n", ha->host_no, | ||
1452 | status == QLA_ERROR ? "FAILED" : "SUCCEDED")); | ||
1410 | return status; | 1453 | return status; |
1411 | } | 1454 | } |
1412 | 1455 | ||
@@ -1558,9 +1601,20 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index, | |||
1558 | atomic_set(&ddb_entry->relogin_timer, 0); | 1601 | atomic_set(&ddb_entry->relogin_timer, 0); |
1559 | atomic_set(&ddb_entry->retry_relogin_timer, | 1602 | atomic_set(&ddb_entry->retry_relogin_timer, |
1560 | ddb_entry->default_time2wait + 4); | 1603 | ddb_entry->default_time2wait + 4); |
1604 | DEBUG(printk("scsi%ld: %s: ddb[%d] " | ||
1605 | "initiate relogin after %d seconds\n", | ||
1606 | ha->host_no, __func__, | ||
1607 | ddb_entry->fw_ddb_index, | ||
1608 | ddb_entry->default_time2wait + 4)); | ||
1609 | } else { | ||
1610 | DEBUG(printk("scsi%ld: %s: ddb[%d] " | ||
1611 | "relogin not initiated, state = %d, " | ||
1612 | "ddb_entry->flags = 0x%lx\n", | ||
1613 | ha->host_no, __func__, | ||
1614 | ddb_entry->fw_ddb_index, | ||
1615 | ddb_entry->fw_ddb_device_state, | ||
1616 | ddb_entry->flags)); | ||
1561 | } | 1617 | } |
1562 | } | 1618 | } |
1563 | |||
1564 | return QLA_SUCCESS; | 1619 | return QLA_SUCCESS; |
1565 | } | 1620 | } |
1566 | |||
diff --git a/drivers/scsi/qla4xxx/ql4_inline.h b/drivers/scsi/qla4xxx/ql4_inline.h index 6375eb017dd3..9471ac755000 100644 --- a/drivers/scsi/qla4xxx/ql4_inline.h +++ b/drivers/scsi/qla4xxx/ql4_inline.h | |||
@@ -29,7 +29,7 @@ qla4xxx_lookup_ddb_by_fw_index(struct scsi_qla_host *ha, uint32_t fw_ddb_index) | |||
29 | ddb_entry = ha->fw_ddb_index_map[fw_ddb_index]; | 29 | ddb_entry = ha->fw_ddb_index_map[fw_ddb_index]; |
30 | } | 30 | } |
31 | 31 | ||
32 | DEBUG3(printk("scsi%d: %s: index [%d], ddb_entry = %p\n", | 32 | DEBUG3(printk("scsi%d: %s: ddb [%d], ddb_entry = %p\n", |
33 | ha->host_no, __func__, fw_ddb_index, ddb_entry)); | 33 | ha->host_no, __func__, fw_ddb_index, ddb_entry)); |
34 | 34 | ||
35 | return ddb_entry; | 35 | return ddb_entry; |
diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c index e66f3f263f49..f89973deac5b 100644 --- a/drivers/scsi/qla4xxx/ql4_iocb.c +++ b/drivers/scsi/qla4xxx/ql4_iocb.c | |||
@@ -108,8 +108,7 @@ int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha, | |||
108 | wmb(); | 108 | wmb(); |
109 | 109 | ||
110 | /* Tell ISP it's got a new I/O request */ | 110 | /* Tell ISP it's got a new I/O request */ |
111 | writel(ha->request_in, &ha->reg->req_q_in); | 111 | ha->isp_ops->queue_iocb(ha); |
112 | readl(&ha->reg->req_q_in); | ||
113 | 112 | ||
114 | exit_send_marker: | 113 | exit_send_marker: |
115 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 114 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
@@ -194,6 +193,72 @@ static void qla4xxx_build_scsi_iocbs(struct srb *srb, | |||
194 | } | 193 | } |
195 | 194 | ||
196 | /** | 195 | /** |
196 | * qla4_8xxx_queue_iocb - Tell ISP it's got new request(s) | ||
197 | * @ha: pointer to host adapter structure. | ||
198 | * | ||
199 | * This routine notifies the ISP that one or more new request | ||
200 | * queue entries have been placed on the request queue. | ||
201 | **/ | ||
202 | void qla4_8xxx_queue_iocb(struct scsi_qla_host *ha) | ||
203 | { | ||
204 | uint32_t dbval = 0; | ||
205 | unsigned long wtime; | ||
206 | |||
207 | dbval = 0x14 | (ha->func_num << 5); | ||
208 | dbval = dbval | (0 << 8) | (ha->request_in << 16); | ||
209 | writel(dbval, (unsigned long __iomem *)ha->nx_db_wr_ptr); | ||
210 | wmb(); | ||
211 | |||
212 | wtime = jiffies + (2 * HZ); | ||
213 | while (readl((void __iomem *)ha->nx_db_rd_ptr) != dbval && | ||
214 | !time_after_eq(jiffies, wtime)) { | ||
215 | writel(dbval, (unsigned long __iomem *)ha->nx_db_wr_ptr); | ||
216 | wmb(); | ||
217 | } | ||
218 | } | ||
219 | |||
220 | /** | ||
221 | * qla4_8xxx_complete_iocb - Tell ISP we're done with response(s) | ||
222 | * @ha: pointer to host adapter structure. | ||
223 | * | ||
224 | * This routine notifies the ISP that one or more response/completion | ||
225 | * queue entries have been processed by the driver. | ||
226 | * This also clears the interrupt. | ||
227 | **/ | ||
228 | void qla4_8xxx_complete_iocb(struct scsi_qla_host *ha) | ||
229 | { | ||
230 | writel(ha->response_out, &ha->qla4_8xxx_reg->rsp_q_out); | ||
231 | readl(&ha->qla4_8xxx_reg->rsp_q_out); | ||
232 | } | ||
233 | |||
234 | /** | ||
235 | * qla4xxx_queue_iocb - Tell ISP it's got new request(s) | ||
236 | * @ha: pointer to host adapter structure. | ||
237 | * | ||
238 | * This routine is notifies the ISP that one or more new request | ||
239 | * queue entries have been placed on the request queue. | ||
240 | **/ | ||
241 | void qla4xxx_queue_iocb(struct scsi_qla_host *ha) | ||
242 | { | ||
243 | writel(ha->request_in, &ha->reg->req_q_in); | ||
244 | readl(&ha->reg->req_q_in); | ||
245 | } | ||
246 | |||
247 | /** | ||
248 | * qla4xxx_complete_iocb - Tell ISP we're done with response(s) | ||
249 | * @ha: pointer to host adapter structure. | ||
250 | * | ||
251 | * This routine is notifies the ISP that one or more response/completion | ||
252 | * queue entries have been processed by the driver. | ||
253 | * This also clears the interrupt. | ||
254 | **/ | ||
255 | void qla4xxx_complete_iocb(struct scsi_qla_host *ha) | ||
256 | { | ||
257 | writel(ha->response_out, &ha->reg->rsp_q_out); | ||
258 | readl(&ha->reg->rsp_q_out); | ||
259 | } | ||
260 | |||
261 | /** | ||
197 | * qla4xxx_send_command_to_isp - issues command to HBA | 262 | * qla4xxx_send_command_to_isp - issues command to HBA |
198 | * @ha: pointer to host adapter structure. | 263 | * @ha: pointer to host adapter structure. |
199 | * @srb: pointer to SCSI Request Block to be sent to ISP | 264 | * @srb: pointer to SCSI Request Block to be sent to ISP |
@@ -310,9 +375,7 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb) | |||
310 | srb->iocb_cnt = req_cnt; | 375 | srb->iocb_cnt = req_cnt; |
311 | ha->req_q_count -= req_cnt; | 376 | ha->req_q_count -= req_cnt; |
312 | 377 | ||
313 | /* Debug print statements */ | 378 | ha->isp_ops->queue_iocb(ha); |
314 | writel(ha->request_in, &ha->reg->req_q_in); | ||
315 | readl(&ha->reg->req_q_in); | ||
316 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 379 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
317 | 380 | ||
318 | return QLA_SUCCESS; | 381 | return QLA_SUCCESS; |
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index 596c3031483c..68d7942bf2e3 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c | |||
@@ -118,7 +118,6 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, | |||
118 | 118 | ||
119 | srb = qla4xxx_del_from_active_array(ha, le32_to_cpu(sts_entry->handle)); | 119 | srb = qla4xxx_del_from_active_array(ha, le32_to_cpu(sts_entry->handle)); |
120 | if (!srb) { | 120 | if (!srb) { |
121 | /* FIXMEdg: Don't we need to reset ISP in this case??? */ | ||
122 | DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Status Entry invalid " | 121 | DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Status Entry invalid " |
123 | "handle 0x%x, sp=%p. This cmd may have already " | 122 | "handle 0x%x, sp=%p. This cmd may have already " |
124 | "been completed.\n", ha->host_no, __func__, | 123 | "been completed.\n", ha->host_no, __func__, |
@@ -293,6 +292,10 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, | |||
293 | 292 | ||
294 | case SCS_DEVICE_LOGGED_OUT: | 293 | case SCS_DEVICE_LOGGED_OUT: |
295 | case SCS_DEVICE_UNAVAILABLE: | 294 | case SCS_DEVICE_UNAVAILABLE: |
295 | DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%d: SCS_DEVICE " | ||
296 | "state: 0x%x\n", ha->host_no, | ||
297 | cmd->device->channel, cmd->device->id, | ||
298 | cmd->device->lun, sts_entry->completionStatus)); | ||
296 | /* | 299 | /* |
297 | * Mark device missing so that we won't continue to | 300 | * Mark device missing so that we won't continue to |
298 | * send I/O to this device. We should get a ddb | 301 | * send I/O to this device. We should get a ddb |
@@ -339,16 +342,14 @@ status_entry_exit: | |||
339 | * This routine process response queue completions in interrupt context. | 342 | * This routine process response queue completions in interrupt context. |
340 | * Hardware_lock locked upon entry | 343 | * Hardware_lock locked upon entry |
341 | **/ | 344 | **/ |
342 | static void qla4xxx_process_response_queue(struct scsi_qla_host * ha) | 345 | void qla4xxx_process_response_queue(struct scsi_qla_host *ha) |
343 | { | 346 | { |
344 | uint32_t count = 0; | 347 | uint32_t count = 0; |
345 | struct srb *srb = NULL; | 348 | struct srb *srb = NULL; |
346 | struct status_entry *sts_entry; | 349 | struct status_entry *sts_entry; |
347 | 350 | ||
348 | /* Process all responses from response queue */ | 351 | /* Process all responses from response queue */ |
349 | while ((ha->response_in = | 352 | while ((ha->response_ptr->signature != RESPONSE_PROCESSED)) { |
350 | (uint16_t)le32_to_cpu(ha->shadow_regs->rsp_q_in)) != | ||
351 | ha->response_out) { | ||
352 | sts_entry = (struct status_entry *) ha->response_ptr; | 353 | sts_entry = (struct status_entry *) ha->response_ptr; |
353 | count++; | 354 | count++; |
354 | 355 | ||
@@ -413,14 +414,14 @@ static void qla4xxx_process_response_queue(struct scsi_qla_host * ha) | |||
413 | sts_entry->hdr.entryType)); | 414 | sts_entry->hdr.entryType)); |
414 | goto exit_prq_error; | 415 | goto exit_prq_error; |
415 | } | 416 | } |
417 | ((struct response *)sts_entry)->signature = RESPONSE_PROCESSED; | ||
418 | wmb(); | ||
416 | } | 419 | } |
417 | 420 | ||
418 | /* | 421 | /* |
419 | * Done with responses, update the ISP For QLA4010, this also clears | 422 | * Tell ISP we're done with response(s). This also clears the interrupt. |
420 | * the interrupt. | ||
421 | */ | 423 | */ |
422 | writel(ha->response_out, &ha->reg->rsp_q_out); | 424 | ha->isp_ops->complete_iocb(ha); |
423 | readl(&ha->reg->rsp_q_out); | ||
424 | 425 | ||
425 | return; | 426 | return; |
426 | 427 | ||
@@ -430,9 +431,7 @@ exit_prq_invalid_handle: | |||
430 | sts_entry->completionStatus)); | 431 | sts_entry->completionStatus)); |
431 | 432 | ||
432 | exit_prq_error: | 433 | exit_prq_error: |
433 | writel(ha->response_out, &ha->reg->rsp_q_out); | 434 | ha->isp_ops->complete_iocb(ha); |
434 | readl(&ha->reg->rsp_q_out); | ||
435 | |||
436 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | 435 | set_bit(DPC_RESET_HA, &ha->dpc_flags); |
437 | } | 436 | } |
438 | 437 | ||
@@ -448,7 +447,7 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, | |||
448 | uint32_t mbox_status) | 447 | uint32_t mbox_status) |
449 | { | 448 | { |
450 | int i; | 449 | int i; |
451 | uint32_t mbox_stat2, mbox_stat3; | 450 | uint32_t mbox_sts[MBOX_AEN_REG_COUNT]; |
452 | 451 | ||
453 | if ((mbox_status == MBOX_STS_BUSY) || | 452 | if ((mbox_status == MBOX_STS_BUSY) || |
454 | (mbox_status == MBOX_STS_INTERMEDIATE_COMPLETION) || | 453 | (mbox_status == MBOX_STS_INTERMEDIATE_COMPLETION) || |
@@ -460,27 +459,37 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, | |||
460 | * Copy all mailbox registers to a temporary | 459 | * Copy all mailbox registers to a temporary |
461 | * location and set mailbox command done flag | 460 | * location and set mailbox command done flag |
462 | */ | 461 | */ |
463 | for (i = 1; i < ha->mbox_status_count; i++) | 462 | for (i = 0; i < ha->mbox_status_count; i++) |
464 | ha->mbox_status[i] = | 463 | ha->mbox_status[i] = is_qla8022(ha) |
465 | readl(&ha->reg->mailbox[i]); | 464 | ? readl(&ha->qla4_8xxx_reg->mailbox_out[i]) |
465 | : readl(&ha->reg->mailbox[i]); | ||
466 | 466 | ||
467 | set_bit(AF_MBOX_COMMAND_DONE, &ha->flags); | 467 | set_bit(AF_MBOX_COMMAND_DONE, &ha->flags); |
468 | |||
469 | if (test_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags)) | ||
470 | complete(&ha->mbx_intr_comp); | ||
468 | } | 471 | } |
469 | } else if (mbox_status >> 12 == MBOX_ASYNC_EVENT_STATUS) { | 472 | } else if (mbox_status >> 12 == MBOX_ASYNC_EVENT_STATUS) { |
473 | for (i = 0; i < MBOX_AEN_REG_COUNT; i++) | ||
474 | mbox_sts[i] = is_qla8022(ha) | ||
475 | ? readl(&ha->qla4_8xxx_reg->mailbox_out[i]) | ||
476 | : readl(&ha->reg->mailbox[i]); | ||
477 | |||
470 | /* Immediately process the AENs that don't require much work. | 478 | /* Immediately process the AENs that don't require much work. |
471 | * Only queue the database_changed AENs */ | 479 | * Only queue the database_changed AENs */ |
472 | if (ha->aen_log.count < MAX_AEN_ENTRIES) { | 480 | if (ha->aen_log.count < MAX_AEN_ENTRIES) { |
473 | for (i = 0; i < MBOX_AEN_REG_COUNT; i++) | 481 | for (i = 0; i < MBOX_AEN_REG_COUNT; i++) |
474 | ha->aen_log.entry[ha->aen_log.count].mbox_sts[i] = | 482 | ha->aen_log.entry[ha->aen_log.count].mbox_sts[i] = |
475 | readl(&ha->reg->mailbox[i]); | 483 | mbox_sts[i]; |
476 | ha->aen_log.count++; | 484 | ha->aen_log.count++; |
477 | } | 485 | } |
478 | switch (mbox_status) { | 486 | switch (mbox_status) { |
479 | case MBOX_ASTS_SYSTEM_ERROR: | 487 | case MBOX_ASTS_SYSTEM_ERROR: |
480 | /* Log Mailbox registers */ | 488 | /* Log Mailbox registers */ |
489 | ql4_printk(KERN_INFO, ha, "%s: System Err\n", __func__); | ||
481 | if (ql4xdontresethba) { | 490 | if (ql4xdontresethba) { |
482 | DEBUG2(printk("%s:Dont Reset HBA\n", | 491 | DEBUG2(printk("scsi%ld: %s:Don't Reset HBA\n", |
483 | __func__)); | 492 | ha->host_no, __func__)); |
484 | } else { | 493 | } else { |
485 | set_bit(AF_GET_CRASH_RECORD, &ha->flags); | 494 | set_bit(AF_GET_CRASH_RECORD, &ha->flags); |
486 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | 495 | set_bit(DPC_RESET_HA, &ha->dpc_flags); |
@@ -502,18 +511,15 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, | |||
502 | if (test_bit(AF_INIT_DONE, &ha->flags)) | 511 | if (test_bit(AF_INIT_DONE, &ha->flags)) |
503 | set_bit(DPC_LINK_CHANGED, &ha->dpc_flags); | 512 | set_bit(DPC_LINK_CHANGED, &ha->dpc_flags); |
504 | 513 | ||
505 | DEBUG2(printk(KERN_INFO "scsi%ld: AEN %04x Adapter" | 514 | ql4_printk(KERN_INFO, ha, "%s: LINK UP\n", __func__); |
506 | " LINK UP\n", ha->host_no, | ||
507 | mbox_status)); | ||
508 | break; | 515 | break; |
509 | 516 | ||
510 | case MBOX_ASTS_LINK_DOWN: | 517 | case MBOX_ASTS_LINK_DOWN: |
511 | clear_bit(AF_LINK_UP, &ha->flags); | 518 | clear_bit(AF_LINK_UP, &ha->flags); |
512 | set_bit(DPC_LINK_CHANGED, &ha->dpc_flags); | 519 | if (test_bit(AF_INIT_DONE, &ha->flags)) |
520 | set_bit(DPC_LINK_CHANGED, &ha->dpc_flags); | ||
513 | 521 | ||
514 | DEBUG2(printk(KERN_INFO "scsi%ld: AEN %04x Adapter" | 522 | ql4_printk(KERN_INFO, ha, "%s: LINK DOWN\n", __func__); |
515 | " LINK DOWN\n", ha->host_no, | ||
516 | mbox_status)); | ||
517 | break; | 523 | break; |
518 | 524 | ||
519 | case MBOX_ASTS_HEARTBEAT: | 525 | case MBOX_ASTS_HEARTBEAT: |
@@ -539,12 +545,17 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, | |||
539 | break; | 545 | break; |
540 | 546 | ||
541 | case MBOX_ASTS_IP_ADDR_STATE_CHANGED: | 547 | case MBOX_ASTS_IP_ADDR_STATE_CHANGED: |
542 | mbox_stat2 = readl(&ha->reg->mailbox[2]); | 548 | printk("scsi%ld: AEN %04x, mbox_sts[2]=%04x, " |
543 | mbox_stat3 = readl(&ha->reg->mailbox[3]); | 549 | "mbox_sts[3]=%04x\n", ha->host_no, mbox_sts[0], |
544 | 550 | mbox_sts[2], mbox_sts[3]); | |
545 | if ((mbox_stat3 == 5) && (mbox_stat2 == 3)) | 551 | |
552 | /* mbox_sts[2] = Old ACB state | ||
553 | * mbox_sts[3] = new ACB state */ | ||
554 | if ((mbox_sts[3] == ACB_STATE_VALID) && | ||
555 | (mbox_sts[2] == ACB_STATE_TENTATIVE)) | ||
546 | set_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags); | 556 | set_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags); |
547 | else if ((mbox_stat3 == 2) && (mbox_stat2 == 5)) | 557 | else if ((mbox_sts[3] == ACB_STATE_ACQUIRING) && |
558 | (mbox_sts[2] == ACB_STATE_VALID)) | ||
548 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | 559 | set_bit(DPC_RESET_HA, &ha->dpc_flags); |
549 | break; | 560 | break; |
550 | 561 | ||
@@ -553,9 +564,8 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, | |||
553 | /* No action */ | 564 | /* No action */ |
554 | DEBUG2(printk(KERN_INFO "scsi%ld: AEN %04x, " | 565 | DEBUG2(printk(KERN_INFO "scsi%ld: AEN %04x, " |
555 | "mbox_sts[1]=%04x, mbox_sts[2]=%04x\n", | 566 | "mbox_sts[1]=%04x, mbox_sts[2]=%04x\n", |
556 | ha->host_no, mbox_status, | 567 | ha->host_no, mbox_sts[0], |
557 | readl(&ha->reg->mailbox[1]), | 568 | mbox_sts[1], mbox_sts[2])); |
558 | readl(&ha->reg->mailbox[2]))); | ||
559 | break; | 569 | break; |
560 | 570 | ||
561 | case MBOX_ASTS_SELF_TEST_FAILED: | 571 | case MBOX_ASTS_SELF_TEST_FAILED: |
@@ -563,10 +573,8 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, | |||
563 | /* No action */ | 573 | /* No action */ |
564 | DEBUG2(printk("scsi%ld: AEN %04x, mbox_sts[1]=%04x, " | 574 | DEBUG2(printk("scsi%ld: AEN %04x, mbox_sts[1]=%04x, " |
565 | "mbox_sts[2]=%04x, mbox_sts[3]=%04x\n", | 575 | "mbox_sts[2]=%04x, mbox_sts[3]=%04x\n", |
566 | ha->host_no, mbox_status, | 576 | ha->host_no, mbox_sts[0], mbox_sts[1], |
567 | readl(&ha->reg->mailbox[1]), | 577 | mbox_sts[2], mbox_sts[3])); |
568 | readl(&ha->reg->mailbox[2]), | ||
569 | readl(&ha->reg->mailbox[3]))); | ||
570 | break; | 578 | break; |
571 | 579 | ||
572 | case MBOX_ASTS_DATABASE_CHANGED: | 580 | case MBOX_ASTS_DATABASE_CHANGED: |
@@ -577,21 +585,17 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, | |||
577 | /* decrement available counter */ | 585 | /* decrement available counter */ |
578 | ha->aen_q_count--; | 586 | ha->aen_q_count--; |
579 | 587 | ||
580 | for (i = 1; i < MBOX_AEN_REG_COUNT; i++) | 588 | for (i = 0; i < MBOX_AEN_REG_COUNT; i++) |
581 | ha->aen_q[ha->aen_in].mbox_sts[i] = | 589 | ha->aen_q[ha->aen_in].mbox_sts[i] = |
582 | readl(&ha->reg->mailbox[i]); | 590 | mbox_sts[i]; |
583 | |||
584 | ha->aen_q[ha->aen_in].mbox_sts[0] = mbox_status; | ||
585 | 591 | ||
586 | /* print debug message */ | 592 | /* print debug message */ |
587 | DEBUG2(printk("scsi%ld: AEN[%d] %04x queued" | 593 | DEBUG2(printk("scsi%ld: AEN[%d] %04x queued" |
588 | " mb1:0x%x mb2:0x%x mb3:0x%x mb4:0x%x\n", | 594 | " mb1:0x%x mb2:0x%x mb3:0x%x mb4:0x%x\n", |
589 | ha->host_no, ha->aen_in, | 595 | ha->host_no, ha->aen_in, mbox_sts[0], |
590 | mbox_status, | 596 | mbox_sts[1], mbox_sts[2], mbox_sts[3], |
591 | ha->aen_q[ha->aen_in].mbox_sts[1], | 597 | mbox_sts[4])); |
592 | ha->aen_q[ha->aen_in].mbox_sts[2], | 598 | |
593 | ha->aen_q[ha->aen_in].mbox_sts[3], | ||
594 | ha->aen_q[ha->aen_in]. mbox_sts[4])); | ||
595 | /* advance pointer */ | 599 | /* advance pointer */ |
596 | ha->aen_in++; | 600 | ha->aen_in++; |
597 | if (ha->aen_in == MAX_AEN_ENTRIES) | 601 | if (ha->aen_in == MAX_AEN_ENTRIES) |
@@ -603,18 +607,16 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, | |||
603 | DEBUG2(printk("scsi%ld: %s: aen %04x, queue " | 607 | DEBUG2(printk("scsi%ld: %s: aen %04x, queue " |
604 | "overflowed! AEN LOST!!\n", | 608 | "overflowed! AEN LOST!!\n", |
605 | ha->host_no, __func__, | 609 | ha->host_no, __func__, |
606 | mbox_status)); | 610 | mbox_sts[0])); |
607 | 611 | ||
608 | DEBUG2(printk("scsi%ld: DUMP AEN QUEUE\n", | 612 | DEBUG2(printk("scsi%ld: DUMP AEN QUEUE\n", |
609 | ha->host_no)); | 613 | ha->host_no)); |
610 | 614 | ||
611 | for (i = 0; i < MAX_AEN_ENTRIES; i++) { | 615 | for (i = 0; i < MAX_AEN_ENTRIES; i++) { |
612 | DEBUG2(printk("AEN[%d] %04x %04x %04x " | 616 | DEBUG2(printk("AEN[%d] %04x %04x %04x " |
613 | "%04x\n", i, | 617 | "%04x\n", i, mbox_sts[0], |
614 | ha->aen_q[i].mbox_sts[0], | 618 | mbox_sts[1], mbox_sts[2], |
615 | ha->aen_q[i].mbox_sts[1], | 619 | mbox_sts[3])); |
616 | ha->aen_q[i].mbox_sts[2], | ||
617 | ha->aen_q[i].mbox_sts[3])); | ||
618 | } | 620 | } |
619 | } | 621 | } |
620 | break; | 622 | break; |
@@ -622,7 +624,7 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, | |||
622 | default: | 624 | default: |
623 | DEBUG2(printk(KERN_WARNING | 625 | DEBUG2(printk(KERN_WARNING |
624 | "scsi%ld: AEN %04x UNKNOWN\n", | 626 | "scsi%ld: AEN %04x UNKNOWN\n", |
625 | ha->host_no, mbox_status)); | 627 | ha->host_no, mbox_sts[0])); |
626 | break; | 628 | break; |
627 | } | 629 | } |
628 | } else { | 630 | } else { |
@@ -634,6 +636,30 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, | |||
634 | } | 636 | } |
635 | 637 | ||
636 | /** | 638 | /** |
639 | * qla4_8xxx_interrupt_service_routine - isr | ||
640 | * @ha: pointer to host adapter structure. | ||
641 | * | ||
642 | * This is the main interrupt service routine. | ||
643 | * hardware_lock locked upon entry. runs in interrupt context. | ||
644 | **/ | ||
645 | void qla4_8xxx_interrupt_service_routine(struct scsi_qla_host *ha, | ||
646 | uint32_t intr_status) | ||
647 | { | ||
648 | /* Process response queue interrupt. */ | ||
649 | if (intr_status & HSRX_RISC_IOCB_INT) | ||
650 | qla4xxx_process_response_queue(ha); | ||
651 | |||
652 | /* Process mailbox/asynch event interrupt.*/ | ||
653 | if (intr_status & HSRX_RISC_MB_INT) | ||
654 | qla4xxx_isr_decode_mailbox(ha, | ||
655 | readl(&ha->qla4_8xxx_reg->mailbox_out[0])); | ||
656 | |||
657 | /* clear the interrupt */ | ||
658 | writel(0, &ha->qla4_8xxx_reg->host_int); | ||
659 | readl(&ha->qla4_8xxx_reg->host_int); | ||
660 | } | ||
661 | |||
662 | /** | ||
637 | * qla4xxx_interrupt_service_routine - isr | 663 | * qla4xxx_interrupt_service_routine - isr |
638 | * @ha: pointer to host adapter structure. | 664 | * @ha: pointer to host adapter structure. |
639 | * | 665 | * |
@@ -660,6 +686,28 @@ void qla4xxx_interrupt_service_routine(struct scsi_qla_host * ha, | |||
660 | } | 686 | } |
661 | 687 | ||
662 | /** | 688 | /** |
689 | * qla4_8xxx_spurious_interrupt - processes spurious interrupt | ||
690 | * @ha: pointer to host adapter structure. | ||
691 | * @reqs_count: . | ||
692 | * | ||
693 | **/ | ||
694 | static void qla4_8xxx_spurious_interrupt(struct scsi_qla_host *ha, | ||
695 | uint8_t reqs_count) | ||
696 | { | ||
697 | if (reqs_count) | ||
698 | return; | ||
699 | |||
700 | DEBUG2(ql4_printk(KERN_INFO, ha, "Spurious Interrupt\n")); | ||
701 | if (is_qla8022(ha)) { | ||
702 | writel(0, &ha->qla4_8xxx_reg->host_int); | ||
703 | if (test_bit(AF_INTx_ENABLED, &ha->flags)) | ||
704 | qla4_8xxx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, | ||
705 | 0xfbff); | ||
706 | } | ||
707 | ha->spurious_int_count++; | ||
708 | } | ||
709 | |||
710 | /** | ||
663 | * qla4xxx_intr_handler - hardware interrupt handler. | 711 | * qla4xxx_intr_handler - hardware interrupt handler. |
664 | * @irq: Unused | 712 | * @irq: Unused |
665 | * @dev_id: Pointer to host adapter structure | 713 | * @dev_id: Pointer to host adapter structure |
@@ -689,15 +737,14 @@ irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id) | |||
689 | /* | 737 | /* |
690 | * Read interrupt status | 738 | * Read interrupt status |
691 | */ | 739 | */ |
692 | if (le32_to_cpu(ha->shadow_regs->rsp_q_in) != | 740 | if (ha->isp_ops->rd_shdw_rsp_q_in(ha) != |
693 | ha->response_out) | 741 | ha->response_out) |
694 | intr_status = CSR_SCSI_COMPLETION_INTR; | 742 | intr_status = CSR_SCSI_COMPLETION_INTR; |
695 | else | 743 | else |
696 | intr_status = readl(&ha->reg->ctrl_status); | 744 | intr_status = readl(&ha->reg->ctrl_status); |
697 | 745 | ||
698 | if ((intr_status & | 746 | if ((intr_status & |
699 | (CSR_SCSI_RESET_INTR|CSR_FATAL_ERROR|INTR_PENDING)) == | 747 | (CSR_SCSI_RESET_INTR|CSR_FATAL_ERROR|INTR_PENDING)) == 0) { |
700 | 0) { | ||
701 | if (reqs_count == 0) | 748 | if (reqs_count == 0) |
702 | ha->spurious_int_count++; | 749 | ha->spurious_int_count++; |
703 | break; | 750 | break; |
@@ -739,22 +786,159 @@ irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id) | |||
739 | &ha->reg->ctrl_status); | 786 | &ha->reg->ctrl_status); |
740 | readl(&ha->reg->ctrl_status); | 787 | readl(&ha->reg->ctrl_status); |
741 | 788 | ||
742 | if (!ql4_mod_unload) | 789 | if (!test_bit(AF_HBA_GOING_AWAY, &ha->flags)) |
743 | set_bit(DPC_RESET_HA_INTR, &ha->dpc_flags); | 790 | set_bit(DPC_RESET_HA_INTR, &ha->dpc_flags); |
744 | 791 | ||
745 | break; | 792 | break; |
746 | } else if (intr_status & INTR_PENDING) { | 793 | } else if (intr_status & INTR_PENDING) { |
747 | qla4xxx_interrupt_service_routine(ha, intr_status); | 794 | ha->isp_ops->interrupt_service_routine(ha, intr_status); |
748 | ha->total_io_count++; | 795 | ha->total_io_count++; |
749 | if (++reqs_count == MAX_REQS_SERVICED_PER_INTR) | 796 | if (++reqs_count == MAX_REQS_SERVICED_PER_INTR) |
750 | break; | 797 | break; |
798 | } | ||
799 | } | ||
800 | |||
801 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
802 | |||
803 | return IRQ_HANDLED; | ||
804 | } | ||
805 | |||
806 | /** | ||
807 | * qla4_8xxx_intr_handler - hardware interrupt handler. | ||
808 | * @irq: Unused | ||
809 | * @dev_id: Pointer to host adapter structure | ||
810 | **/ | ||
811 | irqreturn_t qla4_8xxx_intr_handler(int irq, void *dev_id) | ||
812 | { | ||
813 | struct scsi_qla_host *ha = dev_id; | ||
814 | uint32_t intr_status; | ||
815 | uint32_t status; | ||
816 | unsigned long flags = 0; | ||
817 | uint8_t reqs_count = 0; | ||
818 | |||
819 | ha->isr_count++; | ||
820 | status = qla4_8xxx_rd_32(ha, ISR_INT_VECTOR); | ||
821 | if (!(status & ha->nx_legacy_intr.int_vec_bit)) | ||
822 | return IRQ_NONE; | ||
823 | |||
824 | status = qla4_8xxx_rd_32(ha, ISR_INT_STATE_REG); | ||
825 | if (!ISR_IS_LEGACY_INTR_TRIGGERED(status)) { | ||
826 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
827 | "%s legacy Int not triggered\n", __func__)); | ||
828 | return IRQ_NONE; | ||
829 | } | ||
830 | |||
831 | /* clear the interrupt */ | ||
832 | qla4_8xxx_wr_32(ha, ha->nx_legacy_intr.tgt_status_reg, 0xffffffff); | ||
833 | |||
834 | /* read twice to ensure write is flushed */ | ||
835 | qla4_8xxx_rd_32(ha, ISR_INT_VECTOR); | ||
836 | qla4_8xxx_rd_32(ha, ISR_INT_VECTOR); | ||
837 | |||
838 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
839 | while (1) { | ||
840 | if (!(readl(&ha->qla4_8xxx_reg->host_int) & | ||
841 | ISRX_82XX_RISC_INT)) { | ||
842 | qla4_8xxx_spurious_interrupt(ha, reqs_count); | ||
843 | break; | ||
844 | } | ||
845 | intr_status = readl(&ha->qla4_8xxx_reg->host_status); | ||
846 | if ((intr_status & | ||
847 | (HSRX_RISC_MB_INT | HSRX_RISC_IOCB_INT)) == 0) { | ||
848 | qla4_8xxx_spurious_interrupt(ha, reqs_count); | ||
849 | break; | ||
850 | } | ||
851 | |||
852 | ha->isp_ops->interrupt_service_routine(ha, intr_status); | ||
853 | |||
854 | /* Enable Interrupt */ | ||
855 | qla4_8xxx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0xfbff); | ||
751 | 856 | ||
752 | intr_status = 0; | 857 | if (++reqs_count == MAX_REQS_SERVICED_PER_INTR) |
858 | break; | ||
859 | } | ||
860 | |||
861 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
862 | return IRQ_HANDLED; | ||
863 | } | ||
864 | |||
865 | irqreturn_t | ||
866 | qla4_8xxx_msi_handler(int irq, void *dev_id) | ||
867 | { | ||
868 | struct scsi_qla_host *ha; | ||
869 | |||
870 | ha = (struct scsi_qla_host *) dev_id; | ||
871 | if (!ha) { | ||
872 | DEBUG2(printk(KERN_INFO | ||
873 | "qla4xxx: MSIX: Interrupt with NULL host ptr\n")); | ||
874 | return IRQ_NONE; | ||
875 | } | ||
876 | |||
877 | ha->isr_count++; | ||
878 | /* clear the interrupt */ | ||
879 | qla4_8xxx_wr_32(ha, ha->nx_legacy_intr.tgt_status_reg, 0xffffffff); | ||
880 | |||
881 | /* read twice to ensure write is flushed */ | ||
882 | qla4_8xxx_rd_32(ha, ISR_INT_VECTOR); | ||
883 | qla4_8xxx_rd_32(ha, ISR_INT_VECTOR); | ||
884 | |||
885 | return qla4_8xxx_default_intr_handler(irq, dev_id); | ||
886 | } | ||
887 | |||
888 | /** | ||
889 | * qla4_8xxx_default_intr_handler - hardware interrupt handler. | ||
890 | * @irq: Unused | ||
891 | * @dev_id: Pointer to host adapter structure | ||
892 | * | ||
893 | * This interrupt handler is called directly for MSI-X, and | ||
894 | * called indirectly for MSI. | ||
895 | **/ | ||
896 | irqreturn_t | ||
897 | qla4_8xxx_default_intr_handler(int irq, void *dev_id) | ||
898 | { | ||
899 | struct scsi_qla_host *ha = dev_id; | ||
900 | unsigned long flags; | ||
901 | uint32_t intr_status; | ||
902 | uint8_t reqs_count = 0; | ||
903 | |||
904 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
905 | while (1) { | ||
906 | if (!(readl(&ha->qla4_8xxx_reg->host_int) & | ||
907 | ISRX_82XX_RISC_INT)) { | ||
908 | qla4_8xxx_spurious_interrupt(ha, reqs_count); | ||
909 | break; | ||
910 | } | ||
911 | |||
912 | intr_status = readl(&ha->qla4_8xxx_reg->host_status); | ||
913 | if ((intr_status & | ||
914 | (HSRX_RISC_MB_INT | HSRX_RISC_IOCB_INT)) == 0) { | ||
915 | qla4_8xxx_spurious_interrupt(ha, reqs_count); | ||
916 | break; | ||
753 | } | 917 | } |
918 | |||
919 | ha->isp_ops->interrupt_service_routine(ha, intr_status); | ||
920 | |||
921 | if (++reqs_count == MAX_REQS_SERVICED_PER_INTR) | ||
922 | break; | ||
754 | } | 923 | } |
755 | 924 | ||
925 | ha->isr_count++; | ||
756 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 926 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
927 | return IRQ_HANDLED; | ||
928 | } | ||
757 | 929 | ||
930 | irqreturn_t | ||
931 | qla4_8xxx_msix_rsp_q(int irq, void *dev_id) | ||
932 | { | ||
933 | struct scsi_qla_host *ha = dev_id; | ||
934 | unsigned long flags; | ||
935 | |||
936 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
937 | qla4xxx_process_response_queue(ha); | ||
938 | writel(0, &ha->qla4_8xxx_reg->host_int); | ||
939 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
940 | |||
941 | ha->isr_count++; | ||
758 | return IRQ_HANDLED; | 942 | return IRQ_HANDLED; |
759 | } | 943 | } |
760 | 944 | ||
@@ -825,7 +1009,7 @@ void qla4xxx_process_aen(struct scsi_qla_host * ha, uint8_t process_aen) | |||
825 | ((ddb_entry->default_time2wait + | 1009 | ((ddb_entry->default_time2wait + |
826 | 4) * HZ); | 1010 | 4) * HZ); |
827 | 1011 | ||
828 | DEBUG2(printk("scsi%ld: ddb index [%d] initate" | 1012 | DEBUG2(printk("scsi%ld: ddb [%d] initate" |
829 | " RELOGIN after %d seconds\n", | 1013 | " RELOGIN after %d seconds\n", |
830 | ha->host_no, | 1014 | ha->host_no, |
831 | ddb_entry->fw_ddb_index, | 1015 | ddb_entry->fw_ddb_index, |
@@ -847,3 +1031,81 @@ void qla4xxx_process_aen(struct scsi_qla_host * ha, uint8_t process_aen) | |||
847 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 1031 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
848 | } | 1032 | } |
849 | 1033 | ||
1034 | int qla4xxx_request_irqs(struct scsi_qla_host *ha) | ||
1035 | { | ||
1036 | int ret; | ||
1037 | |||
1038 | if (!is_qla8022(ha)) | ||
1039 | goto try_intx; | ||
1040 | |||
1041 | if (ql4xenablemsix == 2) | ||
1042 | goto try_msi; | ||
1043 | |||
1044 | if (ql4xenablemsix == 0 || ql4xenablemsix != 1) | ||
1045 | goto try_intx; | ||
1046 | |||
1047 | /* Trying MSI-X */ | ||
1048 | ret = qla4_8xxx_enable_msix(ha); | ||
1049 | if (!ret) { | ||
1050 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
1051 | "MSI-X: Enabled (0x%X).\n", ha->revision_id)); | ||
1052 | goto irq_attached; | ||
1053 | } | ||
1054 | |||
1055 | ql4_printk(KERN_WARNING, ha, | ||
1056 | "MSI-X: Falling back-to MSI mode -- %d.\n", ret); | ||
1057 | |||
1058 | try_msi: | ||
1059 | /* Trying MSI */ | ||
1060 | ret = pci_enable_msi(ha->pdev); | ||
1061 | if (!ret) { | ||
1062 | ret = request_irq(ha->pdev->irq, qla4_8xxx_msi_handler, | ||
1063 | IRQF_DISABLED|IRQF_SHARED, DRIVER_NAME, ha); | ||
1064 | if (!ret) { | ||
1065 | DEBUG2(ql4_printk(KERN_INFO, ha, "MSI: Enabled.\n")); | ||
1066 | set_bit(AF_MSI_ENABLED, &ha->flags); | ||
1067 | goto irq_attached; | ||
1068 | } else { | ||
1069 | ql4_printk(KERN_WARNING, ha, | ||
1070 | "MSI: Failed to reserve interrupt %d " | ||
1071 | "already in use.\n", ha->pdev->irq); | ||
1072 | pci_disable_msi(ha->pdev); | ||
1073 | } | ||
1074 | } | ||
1075 | ql4_printk(KERN_WARNING, ha, | ||
1076 | "MSI: Falling back-to INTx mode -- %d.\n", ret); | ||
1077 | |||
1078 | try_intx: | ||
1079 | /* Trying INTx */ | ||
1080 | ret = request_irq(ha->pdev->irq, ha->isp_ops->intr_handler, | ||
1081 | IRQF_DISABLED|IRQF_SHARED, DRIVER_NAME, ha); | ||
1082 | if (!ret) { | ||
1083 | DEBUG2(ql4_printk(KERN_INFO, ha, "INTx: Enabled.\n")); | ||
1084 | set_bit(AF_INTx_ENABLED, &ha->flags); | ||
1085 | goto irq_attached; | ||
1086 | |||
1087 | } else { | ||
1088 | ql4_printk(KERN_WARNING, ha, | ||
1089 | "INTx: Failed to reserve interrupt %d already in" | ||
1090 | " use.\n", ha->pdev->irq); | ||
1091 | return ret; | ||
1092 | } | ||
1093 | |||
1094 | irq_attached: | ||
1095 | set_bit(AF_IRQ_ATTACHED, &ha->flags); | ||
1096 | ha->host->irq = ha->pdev->irq; | ||
1097 | ql4_printk(KERN_INFO, ha, "%s: irq %d attached\n", | ||
1098 | __func__, ha->pdev->irq); | ||
1099 | return ret; | ||
1100 | } | ||
1101 | |||
1102 | void qla4xxx_free_irqs(struct scsi_qla_host *ha) | ||
1103 | { | ||
1104 | if (test_bit(AF_MSIX_ENABLED, &ha->flags)) | ||
1105 | qla4_8xxx_disable_msix(ha); | ||
1106 | else if (test_and_clear_bit(AF_MSI_ENABLED, &ha->flags)) { | ||
1107 | free_irq(ha->pdev->irq, ha); | ||
1108 | pci_disable_msi(ha->pdev); | ||
1109 | } else if (test_and_clear_bit(AF_INTx_ENABLED, &ha->flags)) | ||
1110 | free_irq(ha->pdev->irq, ha); | ||
1111 | } | ||
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index 54db6cbbd942..0d3a65268419 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c | |||
@@ -19,13 +19,13 @@ | |||
19 | * @mbx_cmd: data pointer for mailbox in registers. | 19 | * @mbx_cmd: data pointer for mailbox in registers. |
20 | * @mbx_sts: data pointer for mailbox out registers. | 20 | * @mbx_sts: data pointer for mailbox out registers. |
21 | * | 21 | * |
22 | * This routine sssue mailbox commands and waits for completion. | 22 | * This routine isssue mailbox commands and waits for completion. |
23 | * If outCount is 0, this routine completes successfully WITHOUT waiting | 23 | * If outCount is 0, this routine completes successfully WITHOUT waiting |
24 | * for the mailbox command to complete. | 24 | * for the mailbox command to complete. |
25 | **/ | 25 | **/ |
26 | static int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, | 26 | int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, |
27 | uint8_t outCount, uint32_t *mbx_cmd, | 27 | uint8_t outCount, uint32_t *mbx_cmd, |
28 | uint32_t *mbx_sts) | 28 | uint32_t *mbx_sts) |
29 | { | 29 | { |
30 | int status = QLA_ERROR; | 30 | int status = QLA_ERROR; |
31 | uint8_t i; | 31 | uint8_t i; |
@@ -59,32 +59,66 @@ static int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, | |||
59 | } | 59 | } |
60 | 60 | ||
61 | /* To prevent overwriting mailbox registers for a command that has | 61 | /* To prevent overwriting mailbox registers for a command that has |
62 | * not yet been serviced, check to see if a previously issued | 62 | * not yet been serviced, check to see if an active command |
63 | * mailbox command is interrupting. | 63 | * (AEN, IOCB, etc.) is interrupting, then service it. |
64 | * ----------------------------------------------------------------- | 64 | * ----------------------------------------------------------------- |
65 | */ | 65 | */ |
66 | spin_lock_irqsave(&ha->hardware_lock, flags); | 66 | spin_lock_irqsave(&ha->hardware_lock, flags); |
67 | intr_status = readl(&ha->reg->ctrl_status); | 67 | |
68 | if (intr_status & CSR_SCSI_PROCESSOR_INTR) { | 68 | if (is_qla8022(ha)) { |
69 | /* Service existing interrupt */ | 69 | intr_status = readl(&ha->qla4_8xxx_reg->host_int); |
70 | qla4xxx_interrupt_service_routine(ha, intr_status); | 70 | if (intr_status & ISRX_82XX_RISC_INT) { |
71 | clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags); | 71 | /* Service existing interrupt */ |
72 | DEBUG2(printk("scsi%ld: %s: " | ||
73 | "servicing existing interrupt\n", | ||
74 | ha->host_no, __func__)); | ||
75 | intr_status = readl(&ha->qla4_8xxx_reg->host_status); | ||
76 | ha->isp_ops->interrupt_service_routine(ha, intr_status); | ||
77 | clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags); | ||
78 | if (test_bit(AF_INTERRUPTS_ON, &ha->flags) && | ||
79 | test_bit(AF_INTx_ENABLED, &ha->flags)) | ||
80 | qla4_8xxx_wr_32(ha, | ||
81 | ha->nx_legacy_intr.tgt_mask_reg, | ||
82 | 0xfbff); | ||
83 | } | ||
84 | } else { | ||
85 | intr_status = readl(&ha->reg->ctrl_status); | ||
86 | if (intr_status & CSR_SCSI_PROCESSOR_INTR) { | ||
87 | /* Service existing interrupt */ | ||
88 | ha->isp_ops->interrupt_service_routine(ha, intr_status); | ||
89 | clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags); | ||
90 | } | ||
72 | } | 91 | } |
73 | 92 | ||
74 | /* Send the mailbox command to the firmware */ | ||
75 | ha->mbox_status_count = outCount; | 93 | ha->mbox_status_count = outCount; |
76 | for (i = 0; i < outCount; i++) | 94 | for (i = 0; i < outCount; i++) |
77 | ha->mbox_status[i] = 0; | 95 | ha->mbox_status[i] = 0; |
78 | 96 | ||
79 | /* Load all mailbox registers, except mailbox 0. */ | 97 | if (is_qla8022(ha)) { |
80 | for (i = 1; i < inCount; i++) | 98 | /* Load all mailbox registers, except mailbox 0. */ |
81 | writel(mbx_cmd[i], &ha->reg->mailbox[i]); | 99 | DEBUG5( |
100 | printk("scsi%ld: %s: Cmd ", ha->host_no, __func__); | ||
101 | for (i = 0; i < inCount; i++) | ||
102 | printk("mb%d=%04x ", i, mbx_cmd[i]); | ||
103 | printk("\n")); | ||
104 | |||
105 | for (i = 1; i < inCount; i++) | ||
106 | writel(mbx_cmd[i], &ha->qla4_8xxx_reg->mailbox_in[i]); | ||
107 | writel(mbx_cmd[0], &ha->qla4_8xxx_reg->mailbox_in[0]); | ||
108 | readl(&ha->qla4_8xxx_reg->mailbox_in[0]); | ||
109 | writel(HINT_MBX_INT_PENDING, &ha->qla4_8xxx_reg->hint); | ||
110 | } else { | ||
111 | /* Load all mailbox registers, except mailbox 0. */ | ||
112 | for (i = 1; i < inCount; i++) | ||
113 | writel(mbx_cmd[i], &ha->reg->mailbox[i]); | ||
114 | |||
115 | /* Wakeup firmware */ | ||
116 | writel(mbx_cmd[0], &ha->reg->mailbox[0]); | ||
117 | readl(&ha->reg->mailbox[0]); | ||
118 | writel(set_rmask(CSR_INTR_RISC), &ha->reg->ctrl_status); | ||
119 | readl(&ha->reg->ctrl_status); | ||
120 | } | ||
82 | 121 | ||
83 | /* Wakeup firmware */ | ||
84 | writel(mbx_cmd[0], &ha->reg->mailbox[0]); | ||
85 | readl(&ha->reg->mailbox[0]); | ||
86 | writel(set_rmask(CSR_INTR_RISC), &ha->reg->ctrl_status); | ||
87 | readl(&ha->reg->ctrl_status); | ||
88 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 122 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
89 | 123 | ||
90 | /* Wait for completion */ | 124 | /* Wait for completion */ |
@@ -98,26 +132,66 @@ static int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, | |||
98 | status = QLA_SUCCESS; | 132 | status = QLA_SUCCESS; |
99 | goto mbox_exit; | 133 | goto mbox_exit; |
100 | } | 134 | } |
101 | /* Wait for command to complete */ | ||
102 | wait_count = jiffies + MBOX_TOV * HZ; | ||
103 | while (test_bit(AF_MBOX_COMMAND_DONE, &ha->flags) == 0) { | ||
104 | if (time_after_eq(jiffies, wait_count)) | ||
105 | break; | ||
106 | 135 | ||
107 | spin_lock_irqsave(&ha->hardware_lock, flags); | 136 | /* |
108 | intr_status = readl(&ha->reg->ctrl_status); | 137 | * Wait for completion: Poll or completion queue |
109 | if (intr_status & INTR_PENDING) { | 138 | */ |
139 | if (test_bit(AF_IRQ_ATTACHED, &ha->flags) && | ||
140 | test_bit(AF_INTERRUPTS_ON, &ha->flags) && | ||
141 | test_bit(AF_ONLINE, &ha->flags) && | ||
142 | !test_bit(AF_HBA_GOING_AWAY, &ha->flags)) { | ||
143 | /* Do not poll for completion. Use completion queue */ | ||
144 | set_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags); | ||
145 | wait_for_completion_timeout(&ha->mbx_intr_comp, MBOX_TOV * HZ); | ||
146 | clear_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags); | ||
147 | } else { | ||
148 | /* Poll for command to complete */ | ||
149 | wait_count = jiffies + MBOX_TOV * HZ; | ||
150 | while (test_bit(AF_MBOX_COMMAND_DONE, &ha->flags) == 0) { | ||
151 | if (time_after_eq(jiffies, wait_count)) | ||
152 | break; | ||
110 | /* | 153 | /* |
111 | * Service the interrupt. | 154 | * Service the interrupt. |
112 | * The ISR will save the mailbox status registers | 155 | * The ISR will save the mailbox status registers |
113 | * to a temporary storage location in the adapter | 156 | * to a temporary storage location in the adapter |
114 | * structure. | 157 | * structure. |
115 | */ | 158 | */ |
116 | ha->mbox_status_count = outCount; | 159 | |
117 | qla4xxx_interrupt_service_routine(ha, intr_status); | 160 | spin_lock_irqsave(&ha->hardware_lock, flags); |
161 | if (is_qla8022(ha)) { | ||
162 | intr_status = | ||
163 | readl(&ha->qla4_8xxx_reg->host_int); | ||
164 | if (intr_status & ISRX_82XX_RISC_INT) { | ||
165 | ha->mbox_status_count = outCount; | ||
166 | intr_status = | ||
167 | readl(&ha->qla4_8xxx_reg->host_status); | ||
168 | ha->isp_ops->interrupt_service_routine( | ||
169 | ha, intr_status); | ||
170 | if (test_bit(AF_INTERRUPTS_ON, | ||
171 | &ha->flags) && | ||
172 | test_bit(AF_INTx_ENABLED, | ||
173 | &ha->flags)) | ||
174 | qla4_8xxx_wr_32(ha, | ||
175 | ha->nx_legacy_intr.tgt_mask_reg, | ||
176 | 0xfbff); | ||
177 | } | ||
178 | } else { | ||
179 | intr_status = readl(&ha->reg->ctrl_status); | ||
180 | if (intr_status & INTR_PENDING) { | ||
181 | /* | ||
182 | * Service the interrupt. | ||
183 | * The ISR will save the mailbox status | ||
184 | * registers to a temporary storage | ||
185 | * location in the adapter structure. | ||
186 | */ | ||
187 | ha->mbox_status_count = outCount; | ||
188 | ha->isp_ops->interrupt_service_routine( | ||
189 | ha, intr_status); | ||
190 | } | ||
191 | } | ||
192 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
193 | msleep(10); | ||
118 | } | 194 | } |
119 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
120 | msleep(10); | ||
121 | } | 195 | } |
122 | 196 | ||
123 | /* Check for mailbox timeout. */ | 197 | /* Check for mailbox timeout. */ |
@@ -172,7 +246,7 @@ mbox_exit: | |||
172 | return status; | 246 | return status; |
173 | } | 247 | } |
174 | 248 | ||
175 | uint8_t | 249 | static uint8_t |
176 | qla4xxx_set_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, | 250 | qla4xxx_set_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, |
177 | uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma) | 251 | uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma) |
178 | { | 252 | { |
@@ -196,7 +270,7 @@ qla4xxx_set_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, | |||
196 | return QLA_SUCCESS; | 270 | return QLA_SUCCESS; |
197 | } | 271 | } |
198 | 272 | ||
199 | uint8_t | 273 | static uint8_t |
200 | qla4xxx_get_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, | 274 | qla4xxx_get_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, |
201 | uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma) | 275 | uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma) |
202 | { | 276 | { |
@@ -218,7 +292,7 @@ qla4xxx_get_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, | |||
218 | return QLA_SUCCESS; | 292 | return QLA_SUCCESS; |
219 | } | 293 | } |
220 | 294 | ||
221 | void | 295 | static void |
222 | qla4xxx_update_local_ip(struct scsi_qla_host *ha, | 296 | qla4xxx_update_local_ip(struct scsi_qla_host *ha, |
223 | struct addr_ctrl_blk *init_fw_cb) | 297 | struct addr_ctrl_blk *init_fw_cb) |
224 | { | 298 | { |
@@ -256,7 +330,7 @@ qla4xxx_update_local_ip(struct scsi_qla_host *ha, | |||
256 | } | 330 | } |
257 | } | 331 | } |
258 | 332 | ||
259 | uint8_t | 333 | static uint8_t |
260 | qla4xxx_update_local_ifcb(struct scsi_qla_host *ha, | 334 | qla4xxx_update_local_ifcb(struct scsi_qla_host *ha, |
261 | uint32_t *mbox_cmd, | 335 | uint32_t *mbox_cmd, |
262 | uint32_t *mbox_sts, | 336 | uint32_t *mbox_sts, |
@@ -445,7 +519,7 @@ int qla4xxx_get_firmware_state(struct scsi_qla_host * ha) | |||
445 | DEBUG2(printk("scsi%ld: %s firmware_state=0x%x\n", | 519 | DEBUG2(printk("scsi%ld: %s firmware_state=0x%x\n", |
446 | ha->host_no, __func__, ha->firmware_state);) | 520 | ha->host_no, __func__, ha->firmware_state);) |
447 | 521 | ||
448 | return QLA_SUCCESS; | 522 | return QLA_SUCCESS; |
449 | } | 523 | } |
450 | 524 | ||
451 | /** | 525 | /** |
@@ -470,6 +544,10 @@ int qla4xxx_get_firmware_status(struct scsi_qla_host * ha) | |||
470 | mbox_sts[0])); | 544 | mbox_sts[0])); |
471 | return QLA_ERROR; | 545 | return QLA_ERROR; |
472 | } | 546 | } |
547 | |||
548 | ql4_printk(KERN_INFO, ha, "%ld firmare IOCBs available (%d).\n", | ||
549 | ha->host_no, mbox_cmd[2]); | ||
550 | |||
473 | return QLA_SUCCESS; | 551 | return QLA_SUCCESS; |
474 | } | 552 | } |
475 | 553 | ||
@@ -500,7 +578,7 @@ int qla4xxx_get_fwddb_entry(struct scsi_qla_host *ha, | |||
500 | 578 | ||
501 | /* Make sure the device index is valid */ | 579 | /* Make sure the device index is valid */ |
502 | if (fw_ddb_index >= MAX_DDB_ENTRIES) { | 580 | if (fw_ddb_index >= MAX_DDB_ENTRIES) { |
503 | DEBUG2(printk("scsi%ld: %s: index [%d] out of range.\n", | 581 | DEBUG2(printk("scsi%ld: %s: ddb [%d] out of range.\n", |
504 | ha->host_no, __func__, fw_ddb_index)); | 582 | ha->host_no, __func__, fw_ddb_index)); |
505 | goto exit_get_fwddb; | 583 | goto exit_get_fwddb; |
506 | } | 584 | } |
@@ -521,7 +599,7 @@ int qla4xxx_get_fwddb_entry(struct scsi_qla_host *ha, | |||
521 | goto exit_get_fwddb; | 599 | goto exit_get_fwddb; |
522 | } | 600 | } |
523 | if (fw_ddb_index != mbox_sts[1]) { | 601 | if (fw_ddb_index != mbox_sts[1]) { |
524 | DEBUG2(printk("scsi%ld: %s: index mismatch [%d] != [%d].\n", | 602 | DEBUG2(printk("scsi%ld: %s: ddb mismatch [%d] != [%d].\n", |
525 | ha->host_no, __func__, fw_ddb_index, | 603 | ha->host_no, __func__, fw_ddb_index, |
526 | mbox_sts[1])); | 604 | mbox_sts[1])); |
527 | goto exit_get_fwddb; | 605 | goto exit_get_fwddb; |
@@ -590,6 +668,7 @@ int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index, | |||
590 | { | 668 | { |
591 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | 669 | uint32_t mbox_cmd[MBOX_REG_COUNT]; |
592 | uint32_t mbox_sts[MBOX_REG_COUNT]; | 670 | uint32_t mbox_sts[MBOX_REG_COUNT]; |
671 | int status; | ||
593 | 672 | ||
594 | /* Do not wait for completion. The firmware will send us an | 673 | /* Do not wait for completion. The firmware will send us an |
595 | * ASTS_DATABASE_CHANGED (0x8014) to notify us of the login status. | 674 | * 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, | |||
603 | mbox_cmd[3] = MSDW(fw_ddb_entry_dma); | 682 | mbox_cmd[3] = MSDW(fw_ddb_entry_dma); |
604 | mbox_cmd[4] = sizeof(struct dev_db_entry); | 683 | mbox_cmd[4] = sizeof(struct dev_db_entry); |
605 | 684 | ||
606 | return qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]); | 685 | status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], |
686 | &mbox_sts[0]); | ||
687 | DEBUG2(printk("scsi%ld: %s: status=%d mbx0=0x%x mbx4=0x%x\n", | ||
688 | ha->host_no, __func__, status, mbox_sts[0], mbox_sts[4]);) | ||
689 | |||
690 | return status; | ||
607 | } | 691 | } |
608 | 692 | ||
609 | /** | 693 | /** |
@@ -817,8 +901,8 @@ int qla4xxx_abort_task(struct scsi_qla_host *ha, struct srb *srb) | |||
817 | /** | 901 | /** |
818 | * qla4xxx_reset_lun - issues LUN Reset | 902 | * qla4xxx_reset_lun - issues LUN Reset |
819 | * @ha: Pointer to host adapter structure. | 903 | * @ha: Pointer to host adapter structure. |
820 | * @db_entry: Pointer to device database entry | 904 | * @ddb_entry: Pointer to device database entry |
821 | * @un_entry: Pointer to lun entry structure | 905 | * @lun: lun number |
822 | * | 906 | * |
823 | * This routine performs a LUN RESET on the specified target/lun. | 907 | * This routine performs a LUN RESET on the specified target/lun. |
824 | * The caller must ensure that the ddb_entry and lun_entry pointers | 908 | * 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, | |||
832 | int status = QLA_SUCCESS; | 916 | int status = QLA_SUCCESS; |
833 | 917 | ||
834 | DEBUG2(printk("scsi%ld:%d:%d: lun reset issued\n", ha->host_no, | 918 | DEBUG2(printk("scsi%ld:%d:%d: lun reset issued\n", ha->host_no, |
835 | ddb_entry->os_target_id, lun)); | 919 | ddb_entry->fw_ddb_index, lun)); |
836 | 920 | ||
837 | /* | 921 | /* |
838 | * Send lun reset command to ISP, so that the ISP will return all | 922 | * 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, | |||
872 | int status = QLA_SUCCESS; | 956 | int status = QLA_SUCCESS; |
873 | 957 | ||
874 | DEBUG2(printk("scsi%ld:%d: target reset issued\n", ha->host_no, | 958 | DEBUG2(printk("scsi%ld:%d: target reset issued\n", ha->host_no, |
875 | ddb_entry->os_target_id)); | 959 | ddb_entry->fw_ddb_index)); |
876 | 960 | ||
877 | /* | 961 | /* |
878 | * Send target reset command to ISP, so that the ISP will return all | 962 | * Send target reset command to ISP, so that the ISP will return all |
diff --git a/drivers/scsi/qla4xxx/ql4_nvram.c b/drivers/scsi/qla4xxx/ql4_nvram.c index 7fe0482ecf03..f0d0fbf88aa2 100644 --- a/drivers/scsi/qla4xxx/ql4_nvram.c +++ b/drivers/scsi/qla4xxx/ql4_nvram.c | |||
@@ -149,7 +149,7 @@ static int eeprom_readword(int eepromAddr, u16 * value, | |||
149 | /* Hardware_lock must be set before calling */ | 149 | /* Hardware_lock must be set before calling */ |
150 | u16 rd_nvram_word(struct scsi_qla_host * ha, int offset) | 150 | u16 rd_nvram_word(struct scsi_qla_host * ha, int offset) |
151 | { | 151 | { |
152 | u16 val; | 152 | u16 val = 0; |
153 | 153 | ||
154 | /* NOTE: NVRAM uses half-word addresses */ | 154 | /* NOTE: NVRAM uses half-word addresses */ |
155 | eeprom_readword(offset, &val, ha); | 155 | eeprom_readword(offset, &val, ha); |
diff --git a/drivers/scsi/qla4xxx/ql4_nvram.h b/drivers/scsi/qla4xxx/ql4_nvram.h index b47b4fc59d83..7a8fc66a760d 100644 --- a/drivers/scsi/qla4xxx/ql4_nvram.h +++ b/drivers/scsi/qla4xxx/ql4_nvram.h | |||
@@ -8,9 +8,9 @@ | |||
8 | #ifndef _QL4XNVRM_H_ | 8 | #ifndef _QL4XNVRM_H_ |
9 | #define _QL4XNVRM_H_ | 9 | #define _QL4XNVRM_H_ |
10 | 10 | ||
11 | /* | 11 | /** |
12 | * AM29LV Flash definitions | 12 | * AM29LV Flash definitions |
13 | */ | 13 | **/ |
14 | #define FM93C56A_SIZE_8 0x100 | 14 | #define FM93C56A_SIZE_8 0x100 |
15 | #define FM93C56A_SIZE_16 0x80 | 15 | #define FM93C56A_SIZE_16 0x80 |
16 | #define FM93C66A_SIZE_8 0x200 | 16 | #define FM93C66A_SIZE_8 0x200 |
@@ -19,7 +19,7 @@ | |||
19 | 19 | ||
20 | #define FM93C56A_START 0x1 | 20 | #define FM93C56A_START 0x1 |
21 | 21 | ||
22 | // Commands | 22 | /* Commands */ |
23 | #define FM93C56A_READ 0x2 | 23 | #define FM93C56A_READ 0x2 |
24 | #define FM93C56A_WEN 0x0 | 24 | #define FM93C56A_WEN 0x0 |
25 | #define FM93C56A_WRITE 0x1 | 25 | #define FM93C56A_WRITE 0x1 |
@@ -62,9 +62,9 @@ | |||
62 | #define AUBURN_EEPROM_CLK_RISE 0x1 | 62 | #define AUBURN_EEPROM_CLK_RISE 0x1 |
63 | #define AUBURN_EEPROM_CLK_FALL 0x0 | 63 | #define AUBURN_EEPROM_CLK_FALL 0x0 |
64 | 64 | ||
65 | /* */ | 65 | /**/ |
66 | /* EEPROM format */ | 66 | /* EEPROM format */ |
67 | /* */ | 67 | /**/ |
68 | struct bios_params { | 68 | struct bios_params { |
69 | uint16_t SpinUpDelay:1; | 69 | uint16_t SpinUpDelay:1; |
70 | uint16_t BIOSDisable:1; | 70 | uint16_t BIOSDisable:1; |
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c new file mode 100644 index 000000000000..3e119ae78397 --- /dev/null +++ b/drivers/scsi/qla4xxx/ql4_nx.c | |||
@@ -0,0 +1,2321 @@ | |||
1 | /* | ||
2 | * QLogic iSCSI HBA Driver | ||
3 | * Copyright (c) 2003-2009 QLogic Corporation | ||
4 | * | ||
5 | * See LICENSE.qla4xxx for copyright and licensing details. | ||
6 | */ | ||
7 | #include <linux/delay.h> | ||
8 | #include <linux/pci.h> | ||
9 | #include "ql4_def.h" | ||
10 | #include "ql4_glbl.h" | ||
11 | |||
12 | #define MASK(n) DMA_BIT_MASK(n) | ||
13 | #define MN_WIN(addr) (((addr & 0x1fc0000) >> 1) | ((addr >> 25) & 0x3ff)) | ||
14 | #define OCM_WIN(addr) (((addr & 0x1ff0000) >> 1) | ((addr >> 25) & 0x3ff)) | ||
15 | #define MS_WIN(addr) (addr & 0x0ffc0000) | ||
16 | #define QLA82XX_PCI_MN_2M (0) | ||
17 | #define QLA82XX_PCI_MS_2M (0x80000) | ||
18 | #define QLA82XX_PCI_OCM0_2M (0xc0000) | ||
19 | #define VALID_OCM_ADDR(addr) (((addr) & 0x3f800) != 0x3f800) | ||
20 | #define GET_MEM_OFFS_2M(addr) (addr & MASK(18)) | ||
21 | |||
22 | /* CRB window related */ | ||
23 | #define CRB_BLK(off) ((off >> 20) & 0x3f) | ||
24 | #define CRB_SUBBLK(off) ((off >> 16) & 0xf) | ||
25 | #define CRB_WINDOW_2M (0x130060) | ||
26 | #define CRB_HI(off) ((qla4_8xxx_crb_hub_agt[CRB_BLK(off)] << 20) | \ | ||
27 | ((off) & 0xf0000)) | ||
28 | #define QLA82XX_PCI_CAMQM_2M_END (0x04800800UL) | ||
29 | #define QLA82XX_PCI_CAMQM_2M_BASE (0x000ff800UL) | ||
30 | #define CRB_INDIRECT_2M (0x1e0000UL) | ||
31 | |||
32 | static inline void __iomem * | ||
33 | qla4_8xxx_pci_base_offsetfset(struct scsi_qla_host *ha, unsigned long off) | ||
34 | { | ||
35 | if ((off < ha->first_page_group_end) && | ||
36 | (off >= ha->first_page_group_start)) | ||
37 | return (void __iomem *)(ha->nx_pcibase + off); | ||
38 | |||
39 | return NULL; | ||
40 | } | ||
41 | |||
42 | #define MAX_CRB_XFORM 60 | ||
43 | static unsigned long crb_addr_xform[MAX_CRB_XFORM]; | ||
44 | static int qla4_8xxx_crb_table_initialized; | ||
45 | |||
46 | #define qla4_8xxx_crb_addr_transform(name) \ | ||
47 | (crb_addr_xform[QLA82XX_HW_PX_MAP_CRB_##name] = \ | ||
48 | QLA82XX_HW_CRB_HUB_AGT_ADR_##name << 20) | ||
49 | static void | ||
50 | qla4_8xxx_crb_addr_transform_setup(void) | ||
51 | { | ||
52 | qla4_8xxx_crb_addr_transform(XDMA); | ||
53 | qla4_8xxx_crb_addr_transform(TIMR); | ||
54 | qla4_8xxx_crb_addr_transform(SRE); | ||
55 | qla4_8xxx_crb_addr_transform(SQN3); | ||
56 | qla4_8xxx_crb_addr_transform(SQN2); | ||
57 | qla4_8xxx_crb_addr_transform(SQN1); | ||
58 | qla4_8xxx_crb_addr_transform(SQN0); | ||
59 | qla4_8xxx_crb_addr_transform(SQS3); | ||
60 | qla4_8xxx_crb_addr_transform(SQS2); | ||
61 | qla4_8xxx_crb_addr_transform(SQS1); | ||
62 | qla4_8xxx_crb_addr_transform(SQS0); | ||
63 | qla4_8xxx_crb_addr_transform(RPMX7); | ||
64 | qla4_8xxx_crb_addr_transform(RPMX6); | ||
65 | qla4_8xxx_crb_addr_transform(RPMX5); | ||
66 | qla4_8xxx_crb_addr_transform(RPMX4); | ||
67 | qla4_8xxx_crb_addr_transform(RPMX3); | ||
68 | qla4_8xxx_crb_addr_transform(RPMX2); | ||
69 | qla4_8xxx_crb_addr_transform(RPMX1); | ||
70 | qla4_8xxx_crb_addr_transform(RPMX0); | ||
71 | qla4_8xxx_crb_addr_transform(ROMUSB); | ||
72 | qla4_8xxx_crb_addr_transform(SN); | ||
73 | qla4_8xxx_crb_addr_transform(QMN); | ||
74 | qla4_8xxx_crb_addr_transform(QMS); | ||
75 | qla4_8xxx_crb_addr_transform(PGNI); | ||
76 | qla4_8xxx_crb_addr_transform(PGND); | ||
77 | qla4_8xxx_crb_addr_transform(PGN3); | ||
78 | qla4_8xxx_crb_addr_transform(PGN2); | ||
79 | qla4_8xxx_crb_addr_transform(PGN1); | ||
80 | qla4_8xxx_crb_addr_transform(PGN0); | ||
81 | qla4_8xxx_crb_addr_transform(PGSI); | ||
82 | qla4_8xxx_crb_addr_transform(PGSD); | ||
83 | qla4_8xxx_crb_addr_transform(PGS3); | ||
84 | qla4_8xxx_crb_addr_transform(PGS2); | ||
85 | qla4_8xxx_crb_addr_transform(PGS1); | ||
86 | qla4_8xxx_crb_addr_transform(PGS0); | ||
87 | qla4_8xxx_crb_addr_transform(PS); | ||
88 | qla4_8xxx_crb_addr_transform(PH); | ||
89 | qla4_8xxx_crb_addr_transform(NIU); | ||
90 | qla4_8xxx_crb_addr_transform(I2Q); | ||
91 | qla4_8xxx_crb_addr_transform(EG); | ||
92 | qla4_8xxx_crb_addr_transform(MN); | ||
93 | qla4_8xxx_crb_addr_transform(MS); | ||
94 | qla4_8xxx_crb_addr_transform(CAS2); | ||
95 | qla4_8xxx_crb_addr_transform(CAS1); | ||
96 | qla4_8xxx_crb_addr_transform(CAS0); | ||
97 | qla4_8xxx_crb_addr_transform(CAM); | ||
98 | qla4_8xxx_crb_addr_transform(C2C1); | ||
99 | qla4_8xxx_crb_addr_transform(C2C0); | ||
100 | qla4_8xxx_crb_addr_transform(SMB); | ||
101 | qla4_8xxx_crb_addr_transform(OCM0); | ||
102 | qla4_8xxx_crb_addr_transform(I2C0); | ||
103 | |||
104 | qla4_8xxx_crb_table_initialized = 1; | ||
105 | } | ||
106 | |||
107 | static struct crb_128M_2M_block_map crb_128M_2M_map[64] = { | ||
108 | {{{0, 0, 0, 0} } }, /* 0: PCI */ | ||
109 | {{{1, 0x0100000, 0x0102000, 0x120000}, /* 1: PCIE */ | ||
110 | {1, 0x0110000, 0x0120000, 0x130000}, | ||
111 | {1, 0x0120000, 0x0122000, 0x124000}, | ||
112 | {1, 0x0130000, 0x0132000, 0x126000}, | ||
113 | {1, 0x0140000, 0x0142000, 0x128000}, | ||
114 | {1, 0x0150000, 0x0152000, 0x12a000}, | ||
115 | {1, 0x0160000, 0x0170000, 0x110000}, | ||
116 | {1, 0x0170000, 0x0172000, 0x12e000}, | ||
117 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
118 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
119 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
120 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
121 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
122 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
123 | {1, 0x01e0000, 0x01e0800, 0x122000}, | ||
124 | {0, 0x0000000, 0x0000000, 0x000000} } }, | ||
125 | {{{1, 0x0200000, 0x0210000, 0x180000} } },/* 2: MN */ | ||
126 | {{{0, 0, 0, 0} } }, /* 3: */ | ||
127 | {{{1, 0x0400000, 0x0401000, 0x169000} } },/* 4: P2NR1 */ | ||
128 | {{{1, 0x0500000, 0x0510000, 0x140000} } },/* 5: SRE */ | ||
129 | {{{1, 0x0600000, 0x0610000, 0x1c0000} } },/* 6: NIU */ | ||
130 | {{{1, 0x0700000, 0x0704000, 0x1b8000} } },/* 7: QM */ | ||
131 | {{{1, 0x0800000, 0x0802000, 0x170000}, /* 8: SQM0 */ | ||
132 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
133 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
134 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
135 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
136 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
137 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
138 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
139 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
140 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
141 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
142 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
143 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
144 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
145 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
146 | {1, 0x08f0000, 0x08f2000, 0x172000} } }, | ||
147 | {{{1, 0x0900000, 0x0902000, 0x174000}, /* 9: SQM1*/ | ||
148 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
149 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
150 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
151 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
152 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
153 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
154 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
155 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
156 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
157 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
158 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
159 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
160 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
161 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
162 | {1, 0x09f0000, 0x09f2000, 0x176000} } }, | ||
163 | {{{0, 0x0a00000, 0x0a02000, 0x178000}, /* 10: SQM2*/ | ||
164 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
165 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
166 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
167 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
168 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
169 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
170 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
171 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
172 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
173 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
174 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
175 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
176 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
177 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
178 | {1, 0x0af0000, 0x0af2000, 0x17a000} } }, | ||
179 | {{{0, 0x0b00000, 0x0b02000, 0x17c000}, /* 11: SQM3*/ | ||
180 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
181 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
182 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
183 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
184 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
185 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
186 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
187 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
188 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
189 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
190 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
191 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
192 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
193 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
194 | {1, 0x0bf0000, 0x0bf2000, 0x17e000} } }, | ||
195 | {{{1, 0x0c00000, 0x0c04000, 0x1d4000} } },/* 12: I2Q */ | ||
196 | {{{1, 0x0d00000, 0x0d04000, 0x1a4000} } },/* 13: TMR */ | ||
197 | {{{1, 0x0e00000, 0x0e04000, 0x1a0000} } },/* 14: ROMUSB */ | ||
198 | {{{1, 0x0f00000, 0x0f01000, 0x164000} } },/* 15: PEG4 */ | ||
199 | {{{0, 0x1000000, 0x1004000, 0x1a8000} } },/* 16: XDMA */ | ||
200 | {{{1, 0x1100000, 0x1101000, 0x160000} } },/* 17: PEG0 */ | ||
201 | {{{1, 0x1200000, 0x1201000, 0x161000} } },/* 18: PEG1 */ | ||
202 | {{{1, 0x1300000, 0x1301000, 0x162000} } },/* 19: PEG2 */ | ||
203 | {{{1, 0x1400000, 0x1401000, 0x163000} } },/* 20: PEG3 */ | ||
204 | {{{1, 0x1500000, 0x1501000, 0x165000} } },/* 21: P2ND */ | ||
205 | {{{1, 0x1600000, 0x1601000, 0x166000} } },/* 22: P2NI */ | ||
206 | {{{0, 0, 0, 0} } }, /* 23: */ | ||
207 | {{{0, 0, 0, 0} } }, /* 24: */ | ||
208 | {{{0, 0, 0, 0} } }, /* 25: */ | ||
209 | {{{0, 0, 0, 0} } }, /* 26: */ | ||
210 | {{{0, 0, 0, 0} } }, /* 27: */ | ||
211 | {{{0, 0, 0, 0} } }, /* 28: */ | ||
212 | {{{1, 0x1d00000, 0x1d10000, 0x190000} } },/* 29: MS */ | ||
213 | {{{1, 0x1e00000, 0x1e01000, 0x16a000} } },/* 30: P2NR2 */ | ||
214 | {{{1, 0x1f00000, 0x1f10000, 0x150000} } },/* 31: EPG */ | ||
215 | {{{0} } }, /* 32: PCI */ | ||
216 | {{{1, 0x2100000, 0x2102000, 0x120000}, /* 33: PCIE */ | ||
217 | {1, 0x2110000, 0x2120000, 0x130000}, | ||
218 | {1, 0x2120000, 0x2122000, 0x124000}, | ||
219 | {1, 0x2130000, 0x2132000, 0x126000}, | ||
220 | {1, 0x2140000, 0x2142000, 0x128000}, | ||
221 | {1, 0x2150000, 0x2152000, 0x12a000}, | ||
222 | {1, 0x2160000, 0x2170000, 0x110000}, | ||
223 | {1, 0x2170000, 0x2172000, 0x12e000}, | ||
224 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
225 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
226 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
227 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
228 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
229 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
230 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
231 | {0, 0x0000000, 0x0000000, 0x000000} } }, | ||
232 | {{{1, 0x2200000, 0x2204000, 0x1b0000} } },/* 34: CAM */ | ||
233 | {{{0} } }, /* 35: */ | ||
234 | {{{0} } }, /* 36: */ | ||
235 | {{{0} } }, /* 37: */ | ||
236 | {{{0} } }, /* 38: */ | ||
237 | {{{0} } }, /* 39: */ | ||
238 | {{{1, 0x2800000, 0x2804000, 0x1a4000} } },/* 40: TMR */ | ||
239 | {{{1, 0x2900000, 0x2901000, 0x16b000} } },/* 41: P2NR3 */ | ||
240 | {{{1, 0x2a00000, 0x2a00400, 0x1ac400} } },/* 42: RPMX1 */ | ||
241 | {{{1, 0x2b00000, 0x2b00400, 0x1ac800} } },/* 43: RPMX2 */ | ||
242 | {{{1, 0x2c00000, 0x2c00400, 0x1acc00} } },/* 44: RPMX3 */ | ||
243 | {{{1, 0x2d00000, 0x2d00400, 0x1ad000} } },/* 45: RPMX4 */ | ||
244 | {{{1, 0x2e00000, 0x2e00400, 0x1ad400} } },/* 46: RPMX5 */ | ||
245 | {{{1, 0x2f00000, 0x2f00400, 0x1ad800} } },/* 47: RPMX6 */ | ||
246 | {{{1, 0x3000000, 0x3000400, 0x1adc00} } },/* 48: RPMX7 */ | ||
247 | {{{0, 0x3100000, 0x3104000, 0x1a8000} } },/* 49: XDMA */ | ||
248 | {{{1, 0x3200000, 0x3204000, 0x1d4000} } },/* 50: I2Q */ | ||
249 | {{{1, 0x3300000, 0x3304000, 0x1a0000} } },/* 51: ROMUSB */ | ||
250 | {{{0} } }, /* 52: */ | ||
251 | {{{1, 0x3500000, 0x3500400, 0x1ac000} } },/* 53: RPMX0 */ | ||
252 | {{{1, 0x3600000, 0x3600400, 0x1ae000} } },/* 54: RPMX8 */ | ||
253 | {{{1, 0x3700000, 0x3700400, 0x1ae400} } },/* 55: RPMX9 */ | ||
254 | {{{1, 0x3800000, 0x3804000, 0x1d0000} } },/* 56: OCM0 */ | ||
255 | {{{1, 0x3900000, 0x3904000, 0x1b4000} } },/* 57: CRYPTO */ | ||
256 | {{{1, 0x3a00000, 0x3a04000, 0x1d8000} } },/* 58: SMB */ | ||
257 | {{{0} } }, /* 59: I2C0 */ | ||
258 | {{{0} } }, /* 60: I2C1 */ | ||
259 | {{{1, 0x3d00000, 0x3d04000, 0x1dc000} } },/* 61: LPC */ | ||
260 | {{{1, 0x3e00000, 0x3e01000, 0x167000} } },/* 62: P2NC */ | ||
261 | {{{1, 0x3f00000, 0x3f01000, 0x168000} } } /* 63: P2NR0 */ | ||
262 | }; | ||
263 | |||
264 | /* | ||
265 | * top 12 bits of crb internal address (hub, agent) | ||
266 | */ | ||
267 | static unsigned qla4_8xxx_crb_hub_agt[64] = { | ||
268 | 0, | ||
269 | QLA82XX_HW_CRB_HUB_AGT_ADR_PS, | ||
270 | QLA82XX_HW_CRB_HUB_AGT_ADR_MN, | ||
271 | QLA82XX_HW_CRB_HUB_AGT_ADR_MS, | ||
272 | 0, | ||
273 | QLA82XX_HW_CRB_HUB_AGT_ADR_SRE, | ||
274 | QLA82XX_HW_CRB_HUB_AGT_ADR_NIU, | ||
275 | QLA82XX_HW_CRB_HUB_AGT_ADR_QMN, | ||
276 | QLA82XX_HW_CRB_HUB_AGT_ADR_SQN0, | ||
277 | QLA82XX_HW_CRB_HUB_AGT_ADR_SQN1, | ||
278 | QLA82XX_HW_CRB_HUB_AGT_ADR_SQN2, | ||
279 | QLA82XX_HW_CRB_HUB_AGT_ADR_SQN3, | ||
280 | QLA82XX_HW_CRB_HUB_AGT_ADR_I2Q, | ||
281 | QLA82XX_HW_CRB_HUB_AGT_ADR_TIMR, | ||
282 | QLA82XX_HW_CRB_HUB_AGT_ADR_ROMUSB, | ||
283 | QLA82XX_HW_CRB_HUB_AGT_ADR_PGN4, | ||
284 | QLA82XX_HW_CRB_HUB_AGT_ADR_XDMA, | ||
285 | QLA82XX_HW_CRB_HUB_AGT_ADR_PGN0, | ||
286 | QLA82XX_HW_CRB_HUB_AGT_ADR_PGN1, | ||
287 | QLA82XX_HW_CRB_HUB_AGT_ADR_PGN2, | ||
288 | QLA82XX_HW_CRB_HUB_AGT_ADR_PGN3, | ||
289 | QLA82XX_HW_CRB_HUB_AGT_ADR_PGND, | ||
290 | QLA82XX_HW_CRB_HUB_AGT_ADR_PGNI, | ||
291 | QLA82XX_HW_CRB_HUB_AGT_ADR_PGS0, | ||
292 | QLA82XX_HW_CRB_HUB_AGT_ADR_PGS1, | ||
293 | QLA82XX_HW_CRB_HUB_AGT_ADR_PGS2, | ||
294 | QLA82XX_HW_CRB_HUB_AGT_ADR_PGS3, | ||
295 | 0, | ||
296 | QLA82XX_HW_CRB_HUB_AGT_ADR_PGSI, | ||
297 | QLA82XX_HW_CRB_HUB_AGT_ADR_SN, | ||
298 | 0, | ||
299 | QLA82XX_HW_CRB_HUB_AGT_ADR_EG, | ||
300 | 0, | ||
301 | QLA82XX_HW_CRB_HUB_AGT_ADR_PS, | ||
302 | QLA82XX_HW_CRB_HUB_AGT_ADR_CAM, | ||
303 | 0, | ||
304 | 0, | ||
305 | 0, | ||
306 | 0, | ||
307 | 0, | ||
308 | QLA82XX_HW_CRB_HUB_AGT_ADR_TIMR, | ||
309 | 0, | ||
310 | QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX1, | ||
311 | QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX2, | ||
312 | QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX3, | ||
313 | QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX4, | ||
314 | QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX5, | ||
315 | QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX6, | ||
316 | QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX7, | ||
317 | QLA82XX_HW_CRB_HUB_AGT_ADR_XDMA, | ||
318 | QLA82XX_HW_CRB_HUB_AGT_ADR_I2Q, | ||
319 | QLA82XX_HW_CRB_HUB_AGT_ADR_ROMUSB, | ||
320 | 0, | ||
321 | QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX0, | ||
322 | QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX8, | ||
323 | QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX9, | ||
324 | QLA82XX_HW_CRB_HUB_AGT_ADR_OCM0, | ||
325 | 0, | ||
326 | QLA82XX_HW_CRB_HUB_AGT_ADR_SMB, | ||
327 | QLA82XX_HW_CRB_HUB_AGT_ADR_I2C0, | ||
328 | QLA82XX_HW_CRB_HUB_AGT_ADR_I2C1, | ||
329 | 0, | ||
330 | QLA82XX_HW_CRB_HUB_AGT_ADR_PGNC, | ||
331 | 0, | ||
332 | }; | ||
333 | |||
334 | /* Device states */ | ||
335 | static char *qdev_state[] = { | ||
336 | "Unknown", | ||
337 | "Cold", | ||
338 | "Initializing", | ||
339 | "Ready", | ||
340 | "Need Reset", | ||
341 | "Need Quiescent", | ||
342 | "Failed", | ||
343 | "Quiescent", | ||
344 | }; | ||
345 | |||
346 | /* | ||
347 | * In: 'off' is offset from CRB space in 128M pci map | ||
348 | * Out: 'off' is 2M pci map addr | ||
349 | * side effect: lock crb window | ||
350 | */ | ||
351 | static void | ||
352 | qla4_8xxx_pci_set_crbwindow_2M(struct scsi_qla_host *ha, ulong *off) | ||
353 | { | ||
354 | u32 win_read; | ||
355 | |||
356 | ha->crb_win = CRB_HI(*off); | ||
357 | writel(ha->crb_win, | ||
358 | (void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase)); | ||
359 | |||
360 | /* Read back value to make sure write has gone through before trying | ||
361 | * to use it. */ | ||
362 | win_read = readl((void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase)); | ||
363 | if (win_read != ha->crb_win) { | ||
364 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
365 | "%s: Written crbwin (0x%x) != Read crbwin (0x%x)," | ||
366 | " off=0x%lx\n", __func__, ha->crb_win, win_read, *off)); | ||
367 | } | ||
368 | *off = (*off & MASK(16)) + CRB_INDIRECT_2M + ha->nx_pcibase; | ||
369 | } | ||
370 | |||
371 | void | ||
372 | qla4_8xxx_wr_32(struct scsi_qla_host *ha, ulong off, u32 data) | ||
373 | { | ||
374 | unsigned long flags = 0; | ||
375 | int rv; | ||
376 | |||
377 | rv = qla4_8xxx_pci_get_crb_addr_2M(ha, &off); | ||
378 | |||
379 | BUG_ON(rv == -1); | ||
380 | |||
381 | if (rv == 1) { | ||
382 | write_lock_irqsave(&ha->hw_lock, flags); | ||
383 | qla4_8xxx_crb_win_lock(ha); | ||
384 | qla4_8xxx_pci_set_crbwindow_2M(ha, &off); | ||
385 | } | ||
386 | |||
387 | writel(data, (void __iomem *)off); | ||
388 | |||
389 | if (rv == 1) { | ||
390 | qla4_8xxx_crb_win_unlock(ha); | ||
391 | write_unlock_irqrestore(&ha->hw_lock, flags); | ||
392 | } | ||
393 | } | ||
394 | |||
395 | int | ||
396 | qla4_8xxx_rd_32(struct scsi_qla_host *ha, ulong off) | ||
397 | { | ||
398 | unsigned long flags = 0; | ||
399 | int rv; | ||
400 | u32 data; | ||
401 | |||
402 | rv = qla4_8xxx_pci_get_crb_addr_2M(ha, &off); | ||
403 | |||
404 | BUG_ON(rv == -1); | ||
405 | |||
406 | if (rv == 1) { | ||
407 | write_lock_irqsave(&ha->hw_lock, flags); | ||
408 | qla4_8xxx_crb_win_lock(ha); | ||
409 | qla4_8xxx_pci_set_crbwindow_2M(ha, &off); | ||
410 | } | ||
411 | data = readl((void __iomem *)off); | ||
412 | |||
413 | if (rv == 1) { | ||
414 | qla4_8xxx_crb_win_unlock(ha); | ||
415 | write_unlock_irqrestore(&ha->hw_lock, flags); | ||
416 | } | ||
417 | return data; | ||
418 | } | ||
419 | |||
420 | #define CRB_WIN_LOCK_TIMEOUT 100000000 | ||
421 | |||
422 | int qla4_8xxx_crb_win_lock(struct scsi_qla_host *ha) | ||
423 | { | ||
424 | int i; | ||
425 | int done = 0, timeout = 0; | ||
426 | |||
427 | while (!done) { | ||
428 | /* acquire semaphore3 from PCI HW block */ | ||
429 | done = qla4_8xxx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM7_LOCK)); | ||
430 | if (done == 1) | ||
431 | break; | ||
432 | if (timeout >= CRB_WIN_LOCK_TIMEOUT) | ||
433 | return -1; | ||
434 | |||
435 | timeout++; | ||
436 | |||
437 | /* Yield CPU */ | ||
438 | if (!in_interrupt()) | ||
439 | schedule(); | ||
440 | else { | ||
441 | for (i = 0; i < 20; i++) | ||
442 | cpu_relax(); /*This a nop instr on i386*/ | ||
443 | } | ||
444 | } | ||
445 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_WIN_LOCK_ID, ha->func_num); | ||
446 | return 0; | ||
447 | } | ||
448 | |||
449 | void qla4_8xxx_crb_win_unlock(struct scsi_qla_host *ha) | ||
450 | { | ||
451 | qla4_8xxx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM7_UNLOCK)); | ||
452 | } | ||
453 | |||
454 | #define IDC_LOCK_TIMEOUT 100000000 | ||
455 | |||
456 | /** | ||
457 | * qla4_8xxx_idc_lock - hw_lock | ||
458 | * @ha: pointer to adapter structure | ||
459 | * | ||
460 | * General purpose lock used to synchronize access to | ||
461 | * CRB_DEV_STATE, CRB_DEV_REF_COUNT, etc. | ||
462 | **/ | ||
463 | int qla4_8xxx_idc_lock(struct scsi_qla_host *ha) | ||
464 | { | ||
465 | int i; | ||
466 | int done = 0, timeout = 0; | ||
467 | |||
468 | while (!done) { | ||
469 | /* acquire semaphore5 from PCI HW block */ | ||
470 | done = qla4_8xxx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM5_LOCK)); | ||
471 | if (done == 1) | ||
472 | break; | ||
473 | if (timeout >= IDC_LOCK_TIMEOUT) | ||
474 | return -1; | ||
475 | |||
476 | timeout++; | ||
477 | |||
478 | /* Yield CPU */ | ||
479 | if (!in_interrupt()) | ||
480 | schedule(); | ||
481 | else { | ||
482 | for (i = 0; i < 20; i++) | ||
483 | cpu_relax(); /*This a nop instr on i386*/ | ||
484 | } | ||
485 | } | ||
486 | return 0; | ||
487 | } | ||
488 | |||
489 | void qla4_8xxx_idc_unlock(struct scsi_qla_host *ha) | ||
490 | { | ||
491 | qla4_8xxx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM5_UNLOCK)); | ||
492 | } | ||
493 | |||
494 | int | ||
495 | qla4_8xxx_pci_get_crb_addr_2M(struct scsi_qla_host *ha, ulong *off) | ||
496 | { | ||
497 | struct crb_128M_2M_sub_block_map *m; | ||
498 | |||
499 | if (*off >= QLA82XX_CRB_MAX) | ||
500 | return -1; | ||
501 | |||
502 | if (*off >= QLA82XX_PCI_CAMQM && (*off < QLA82XX_PCI_CAMQM_2M_END)) { | ||
503 | *off = (*off - QLA82XX_PCI_CAMQM) + | ||
504 | QLA82XX_PCI_CAMQM_2M_BASE + ha->nx_pcibase; | ||
505 | return 0; | ||
506 | } | ||
507 | |||
508 | if (*off < QLA82XX_PCI_CRBSPACE) | ||
509 | return -1; | ||
510 | |||
511 | *off -= QLA82XX_PCI_CRBSPACE; | ||
512 | /* | ||
513 | * Try direct map | ||
514 | */ | ||
515 | |||
516 | m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)]; | ||
517 | |||
518 | if (m->valid && (m->start_128M <= *off) && (m->end_128M > *off)) { | ||
519 | *off = *off + m->start_2M - m->start_128M + ha->nx_pcibase; | ||
520 | return 0; | ||
521 | } | ||
522 | |||
523 | /* | ||
524 | * Not in direct map, use crb window | ||
525 | */ | ||
526 | return 1; | ||
527 | } | ||
528 | |||
529 | /* PCI Windowing for DDR regions. */ | ||
530 | #define QLA82XX_ADDR_IN_RANGE(addr, low, high) \ | ||
531 | (((addr) <= (high)) && ((addr) >= (low))) | ||
532 | |||
533 | /* | ||
534 | * check memory access boundary. | ||
535 | * used by test agent. support ddr access only for now | ||
536 | */ | ||
537 | static unsigned long | ||
538 | qla4_8xxx_pci_mem_bound_check(struct scsi_qla_host *ha, | ||
539 | unsigned long long addr, int size) | ||
540 | { | ||
541 | if (!QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_DDR_NET, | ||
542 | QLA82XX_ADDR_DDR_NET_MAX) || | ||
543 | !QLA82XX_ADDR_IN_RANGE(addr + size - 1, | ||
544 | QLA82XX_ADDR_DDR_NET, QLA82XX_ADDR_DDR_NET_MAX) || | ||
545 | ((size != 1) && (size != 2) && (size != 4) && (size != 8))) { | ||
546 | return 0; | ||
547 | } | ||
548 | return 1; | ||
549 | } | ||
550 | |||
551 | static int qla4_8xxx_pci_set_window_warning_count; | ||
552 | |||
553 | static unsigned long | ||
554 | qla4_8xxx_pci_set_window(struct scsi_qla_host *ha, unsigned long long addr) | ||
555 | { | ||
556 | int window; | ||
557 | u32 win_read; | ||
558 | |||
559 | if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_DDR_NET, | ||
560 | QLA82XX_ADDR_DDR_NET_MAX)) { | ||
561 | /* DDR network side */ | ||
562 | window = MN_WIN(addr); | ||
563 | ha->ddr_mn_window = window; | ||
564 | qla4_8xxx_wr_32(ha, ha->mn_win_crb | | ||
565 | QLA82XX_PCI_CRBSPACE, window); | ||
566 | win_read = qla4_8xxx_rd_32(ha, ha->mn_win_crb | | ||
567 | QLA82XX_PCI_CRBSPACE); | ||
568 | if ((win_read << 17) != window) { | ||
569 | ql4_printk(KERN_WARNING, ha, | ||
570 | "%s: Written MNwin (0x%x) != Read MNwin (0x%x)\n", | ||
571 | __func__, window, win_read); | ||
572 | } | ||
573 | addr = GET_MEM_OFFS_2M(addr) + QLA82XX_PCI_DDR_NET; | ||
574 | } else if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_OCM0, | ||
575 | QLA82XX_ADDR_OCM0_MAX)) { | ||
576 | unsigned int temp1; | ||
577 | /* if bits 19:18&17:11 are on */ | ||
578 | if ((addr & 0x00ff800) == 0xff800) { | ||
579 | printk("%s: QM access not handled.\n", __func__); | ||
580 | addr = -1UL; | ||
581 | } | ||
582 | |||
583 | window = OCM_WIN(addr); | ||
584 | ha->ddr_mn_window = window; | ||
585 | qla4_8xxx_wr_32(ha, ha->mn_win_crb | | ||
586 | QLA82XX_PCI_CRBSPACE, window); | ||
587 | win_read = qla4_8xxx_rd_32(ha, ha->mn_win_crb | | ||
588 | QLA82XX_PCI_CRBSPACE); | ||
589 | temp1 = ((window & 0x1FF) << 7) | | ||
590 | ((window & 0x0FFFE0000) >> 17); | ||
591 | if (win_read != temp1) { | ||
592 | printk("%s: Written OCMwin (0x%x) != Read" | ||
593 | " OCMwin (0x%x)\n", __func__, temp1, win_read); | ||
594 | } | ||
595 | addr = GET_MEM_OFFS_2M(addr) + QLA82XX_PCI_OCM0_2M; | ||
596 | |||
597 | } else if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_QDR_NET, | ||
598 | QLA82XX_P3_ADDR_QDR_NET_MAX)) { | ||
599 | /* QDR network side */ | ||
600 | window = MS_WIN(addr); | ||
601 | ha->qdr_sn_window = window; | ||
602 | qla4_8xxx_wr_32(ha, ha->ms_win_crb | | ||
603 | QLA82XX_PCI_CRBSPACE, window); | ||
604 | win_read = qla4_8xxx_rd_32(ha, | ||
605 | ha->ms_win_crb | QLA82XX_PCI_CRBSPACE); | ||
606 | if (win_read != window) { | ||
607 | printk("%s: Written MSwin (0x%x) != Read " | ||
608 | "MSwin (0x%x)\n", __func__, window, win_read); | ||
609 | } | ||
610 | addr = GET_MEM_OFFS_2M(addr) + QLA82XX_PCI_QDR_NET; | ||
611 | |||
612 | } else { | ||
613 | /* | ||
614 | * peg gdb frequently accesses memory that doesn't exist, | ||
615 | * this limits the chit chat so debugging isn't slowed down. | ||
616 | */ | ||
617 | if ((qla4_8xxx_pci_set_window_warning_count++ < 8) || | ||
618 | (qla4_8xxx_pci_set_window_warning_count%64 == 0)) { | ||
619 | printk("%s: Warning:%s Unknown address range!\n", | ||
620 | __func__, DRIVER_NAME); | ||
621 | } | ||
622 | addr = -1UL; | ||
623 | } | ||
624 | return addr; | ||
625 | } | ||
626 | |||
627 | /* check if address is in the same windows as the previous access */ | ||
628 | static int qla4_8xxx_pci_is_same_window(struct scsi_qla_host *ha, | ||
629 | unsigned long long addr) | ||
630 | { | ||
631 | int window; | ||
632 | unsigned long long qdr_max; | ||
633 | |||
634 | qdr_max = QLA82XX_P3_ADDR_QDR_NET_MAX; | ||
635 | |||
636 | if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_DDR_NET, | ||
637 | QLA82XX_ADDR_DDR_NET_MAX)) { | ||
638 | /* DDR network side */ | ||
639 | BUG(); /* MN access can not come here */ | ||
640 | } else if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_OCM0, | ||
641 | QLA82XX_ADDR_OCM0_MAX)) { | ||
642 | return 1; | ||
643 | } else if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_OCM1, | ||
644 | QLA82XX_ADDR_OCM1_MAX)) { | ||
645 | return 1; | ||
646 | } else if (QLA82XX_ADDR_IN_RANGE(addr, QLA82XX_ADDR_QDR_NET, | ||
647 | qdr_max)) { | ||
648 | /* QDR network side */ | ||
649 | window = ((addr - QLA82XX_ADDR_QDR_NET) >> 22) & 0x3f; | ||
650 | if (ha->qdr_sn_window == window) | ||
651 | return 1; | ||
652 | } | ||
653 | |||
654 | return 0; | ||
655 | } | ||
656 | |||
657 | static int qla4_8xxx_pci_mem_read_direct(struct scsi_qla_host *ha, | ||
658 | u64 off, void *data, int size) | ||
659 | { | ||
660 | unsigned long flags; | ||
661 | void __iomem *addr; | ||
662 | int ret = 0; | ||
663 | u64 start; | ||
664 | void __iomem *mem_ptr = NULL; | ||
665 | unsigned long mem_base; | ||
666 | unsigned long mem_page; | ||
667 | |||
668 | write_lock_irqsave(&ha->hw_lock, flags); | ||
669 | |||
670 | /* | ||
671 | * If attempting to access unknown address or straddle hw windows, | ||
672 | * do not access. | ||
673 | */ | ||
674 | start = qla4_8xxx_pci_set_window(ha, off); | ||
675 | if ((start == -1UL) || | ||
676 | (qla4_8xxx_pci_is_same_window(ha, off + size - 1) == 0)) { | ||
677 | write_unlock_irqrestore(&ha->hw_lock, flags); | ||
678 | printk(KERN_ERR"%s out of bound pci memory access. " | ||
679 | "offset is 0x%llx\n", DRIVER_NAME, off); | ||
680 | return -1; | ||
681 | } | ||
682 | |||
683 | addr = qla4_8xxx_pci_base_offsetfset(ha, start); | ||
684 | if (!addr) { | ||
685 | write_unlock_irqrestore(&ha->hw_lock, flags); | ||
686 | mem_base = pci_resource_start(ha->pdev, 0); | ||
687 | mem_page = start & PAGE_MASK; | ||
688 | /* Map two pages whenever user tries to access addresses in two | ||
689 | consecutive pages. | ||
690 | */ | ||
691 | if (mem_page != ((start + size - 1) & PAGE_MASK)) | ||
692 | mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE * 2); | ||
693 | else | ||
694 | mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE); | ||
695 | |||
696 | if (mem_ptr == NULL) { | ||
697 | *(u8 *)data = 0; | ||
698 | return -1; | ||
699 | } | ||
700 | addr = mem_ptr; | ||
701 | addr += start & (PAGE_SIZE - 1); | ||
702 | write_lock_irqsave(&ha->hw_lock, flags); | ||
703 | } | ||
704 | |||
705 | switch (size) { | ||
706 | case 1: | ||
707 | *(u8 *)data = readb(addr); | ||
708 | break; | ||
709 | case 2: | ||
710 | *(u16 *)data = readw(addr); | ||
711 | break; | ||
712 | case 4: | ||
713 | *(u32 *)data = readl(addr); | ||
714 | break; | ||
715 | case 8: | ||
716 | *(u64 *)data = readq(addr); | ||
717 | break; | ||
718 | default: | ||
719 | ret = -1; | ||
720 | break; | ||
721 | } | ||
722 | write_unlock_irqrestore(&ha->hw_lock, flags); | ||
723 | |||
724 | if (mem_ptr) | ||
725 | iounmap(mem_ptr); | ||
726 | return ret; | ||
727 | } | ||
728 | |||
729 | static int | ||
730 | qla4_8xxx_pci_mem_write_direct(struct scsi_qla_host *ha, u64 off, | ||
731 | void *data, int size) | ||
732 | { | ||
733 | unsigned long flags; | ||
734 | void __iomem *addr; | ||
735 | int ret = 0; | ||
736 | u64 start; | ||
737 | void __iomem *mem_ptr = NULL; | ||
738 | unsigned long mem_base; | ||
739 | unsigned long mem_page; | ||
740 | |||
741 | write_lock_irqsave(&ha->hw_lock, flags); | ||
742 | |||
743 | /* | ||
744 | * If attempting to access unknown address or straddle hw windows, | ||
745 | * do not access. | ||
746 | */ | ||
747 | start = qla4_8xxx_pci_set_window(ha, off); | ||
748 | if ((start == -1UL) || | ||
749 | (qla4_8xxx_pci_is_same_window(ha, off + size - 1) == 0)) { | ||
750 | write_unlock_irqrestore(&ha->hw_lock, flags); | ||
751 | printk(KERN_ERR"%s out of bound pci memory access. " | ||
752 | "offset is 0x%llx\n", DRIVER_NAME, off); | ||
753 | return -1; | ||
754 | } | ||
755 | |||
756 | addr = qla4_8xxx_pci_base_offsetfset(ha, start); | ||
757 | if (!addr) { | ||
758 | write_unlock_irqrestore(&ha->hw_lock, flags); | ||
759 | mem_base = pci_resource_start(ha->pdev, 0); | ||
760 | mem_page = start & PAGE_MASK; | ||
761 | /* Map two pages whenever user tries to access addresses in two | ||
762 | consecutive pages. | ||
763 | */ | ||
764 | if (mem_page != ((start + size - 1) & PAGE_MASK)) | ||
765 | mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE*2); | ||
766 | else | ||
767 | mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE); | ||
768 | if (mem_ptr == NULL) | ||
769 | return -1; | ||
770 | |||
771 | addr = mem_ptr; | ||
772 | addr += start & (PAGE_SIZE - 1); | ||
773 | write_lock_irqsave(&ha->hw_lock, flags); | ||
774 | } | ||
775 | |||
776 | switch (size) { | ||
777 | case 1: | ||
778 | writeb(*(u8 *)data, addr); | ||
779 | break; | ||
780 | case 2: | ||
781 | writew(*(u16 *)data, addr); | ||
782 | break; | ||
783 | case 4: | ||
784 | writel(*(u32 *)data, addr); | ||
785 | break; | ||
786 | case 8: | ||
787 | writeq(*(u64 *)data, addr); | ||
788 | break; | ||
789 | default: | ||
790 | ret = -1; | ||
791 | break; | ||
792 | } | ||
793 | write_unlock_irqrestore(&ha->hw_lock, flags); | ||
794 | if (mem_ptr) | ||
795 | iounmap(mem_ptr); | ||
796 | return ret; | ||
797 | } | ||
798 | |||
799 | #define MTU_FUDGE_FACTOR 100 | ||
800 | |||
801 | static unsigned long | ||
802 | qla4_8xxx_decode_crb_addr(unsigned long addr) | ||
803 | { | ||
804 | int i; | ||
805 | unsigned long base_addr, offset, pci_base; | ||
806 | |||
807 | if (!qla4_8xxx_crb_table_initialized) | ||
808 | qla4_8xxx_crb_addr_transform_setup(); | ||
809 | |||
810 | pci_base = ADDR_ERROR; | ||
811 | base_addr = addr & 0xfff00000; | ||
812 | offset = addr & 0x000fffff; | ||
813 | |||
814 | for (i = 0; i < MAX_CRB_XFORM; i++) { | ||
815 | if (crb_addr_xform[i] == base_addr) { | ||
816 | pci_base = i << 20; | ||
817 | break; | ||
818 | } | ||
819 | } | ||
820 | if (pci_base == ADDR_ERROR) | ||
821 | return pci_base; | ||
822 | else | ||
823 | return pci_base + offset; | ||
824 | } | ||
825 | |||
826 | static long rom_max_timeout = 100; | ||
827 | static long qla4_8xxx_rom_lock_timeout = 100; | ||
828 | |||
829 | static int | ||
830 | qla4_8xxx_rom_lock(struct scsi_qla_host *ha) | ||
831 | { | ||
832 | int i; | ||
833 | int done = 0, timeout = 0; | ||
834 | |||
835 | while (!done) { | ||
836 | /* acquire semaphore2 from PCI HW block */ | ||
837 | |||
838 | done = qla4_8xxx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_LOCK)); | ||
839 | if (done == 1) | ||
840 | break; | ||
841 | if (timeout >= qla4_8xxx_rom_lock_timeout) | ||
842 | return -1; | ||
843 | |||
844 | timeout++; | ||
845 | |||
846 | /* Yield CPU */ | ||
847 | if (!in_interrupt()) | ||
848 | schedule(); | ||
849 | else { | ||
850 | for (i = 0; i < 20; i++) | ||
851 | cpu_relax(); /*This a nop instr on i386*/ | ||
852 | } | ||
853 | } | ||
854 | qla4_8xxx_wr_32(ha, QLA82XX_ROM_LOCK_ID, ROM_LOCK_DRIVER); | ||
855 | return 0; | ||
856 | } | ||
857 | |||
858 | static void | ||
859 | qla4_8xxx_rom_unlock(struct scsi_qla_host *ha) | ||
860 | { | ||
861 | qla4_8xxx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_UNLOCK)); | ||
862 | } | ||
863 | |||
864 | static int | ||
865 | qla4_8xxx_wait_rom_done(struct scsi_qla_host *ha) | ||
866 | { | ||
867 | long timeout = 0; | ||
868 | long done = 0 ; | ||
869 | |||
870 | while (done == 0) { | ||
871 | done = qla4_8xxx_rd_32(ha, QLA82XX_ROMUSB_GLB_STATUS); | ||
872 | done &= 2; | ||
873 | timeout++; | ||
874 | if (timeout >= rom_max_timeout) { | ||
875 | printk("%s: Timeout reached waiting for rom done", | ||
876 | DRIVER_NAME); | ||
877 | return -1; | ||
878 | } | ||
879 | } | ||
880 | return 0; | ||
881 | } | ||
882 | |||
883 | static int | ||
884 | qla4_8xxx_do_rom_fast_read(struct scsi_qla_host *ha, int addr, int *valp) | ||
885 | { | ||
886 | qla4_8xxx_wr_32(ha, QLA82XX_ROMUSB_ROM_ADDRESS, addr); | ||
887 | qla4_8xxx_wr_32(ha, QLA82XX_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); | ||
888 | qla4_8xxx_wr_32(ha, QLA82XX_ROMUSB_ROM_ABYTE_CNT, 3); | ||
889 | qla4_8xxx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, 0xb); | ||
890 | if (qla4_8xxx_wait_rom_done(ha)) { | ||
891 | printk("%s: Error waiting for rom done\n", DRIVER_NAME); | ||
892 | return -1; | ||
893 | } | ||
894 | /* reset abyte_cnt and dummy_byte_cnt */ | ||
895 | qla4_8xxx_wr_32(ha, QLA82XX_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); | ||
896 | udelay(10); | ||
897 | qla4_8xxx_wr_32(ha, QLA82XX_ROMUSB_ROM_ABYTE_CNT, 0); | ||
898 | |||
899 | *valp = qla4_8xxx_rd_32(ha, QLA82XX_ROMUSB_ROM_RDATA); | ||
900 | return 0; | ||
901 | } | ||
902 | |||
903 | static int | ||
904 | qla4_8xxx_rom_fast_read(struct scsi_qla_host *ha, int addr, int *valp) | ||
905 | { | ||
906 | int ret, loops = 0; | ||
907 | |||
908 | while ((qla4_8xxx_rom_lock(ha) != 0) && (loops < 50000)) { | ||
909 | udelay(100); | ||
910 | loops++; | ||
911 | } | ||
912 | if (loops >= 50000) { | ||
913 | printk("%s: qla4_8xxx_rom_lock failed\n", DRIVER_NAME); | ||
914 | return -1; | ||
915 | } | ||
916 | ret = qla4_8xxx_do_rom_fast_read(ha, addr, valp); | ||
917 | qla4_8xxx_rom_unlock(ha); | ||
918 | return ret; | ||
919 | } | ||
920 | |||
921 | /** | ||
922 | * This routine does CRB initialize sequence | ||
923 | * to put the ISP into operational state | ||
924 | **/ | ||
925 | static int | ||
926 | qla4_8xxx_pinit_from_rom(struct scsi_qla_host *ha, int verbose) | ||
927 | { | ||
928 | int addr, val; | ||
929 | int i ; | ||
930 | struct crb_addr_pair *buf; | ||
931 | unsigned long off; | ||
932 | unsigned offset, n; | ||
933 | |||
934 | struct crb_addr_pair { | ||
935 | long addr; | ||
936 | long data; | ||
937 | }; | ||
938 | |||
939 | /* Halt all the indiviual PEGs and other blocks of the ISP */ | ||
940 | qla4_8xxx_rom_lock(ha); | ||
941 | if (test_bit(DPC_RESET_HA, &ha->dpc_flags)) | ||
942 | /* don't reset CAM block on reset */ | ||
943 | qla4_8xxx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0xfeffffff); | ||
944 | else | ||
945 | qla4_8xxx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0xffffffff); | ||
946 | |||
947 | qla4_8xxx_rom_unlock(ha); | ||
948 | |||
949 | /* Read the signature value from the flash. | ||
950 | * Offset 0: Contain signature (0xcafecafe) | ||
951 | * Offset 4: Offset and number of addr/value pairs | ||
952 | * that present in CRB initialize sequence | ||
953 | */ | ||
954 | if (qla4_8xxx_rom_fast_read(ha, 0, &n) != 0 || n != 0xcafecafeUL || | ||
955 | qla4_8xxx_rom_fast_read(ha, 4, &n) != 0) { | ||
956 | ql4_printk(KERN_WARNING, ha, | ||
957 | "[ERROR] Reading crb_init area: n: %08x\n", n); | ||
958 | return -1; | ||
959 | } | ||
960 | |||
961 | /* Offset in flash = lower 16 bits | ||
962 | * Number of enteries = upper 16 bits | ||
963 | */ | ||
964 | offset = n & 0xffffU; | ||
965 | n = (n >> 16) & 0xffffU; | ||
966 | |||
967 | /* number of addr/value pair should not exceed 1024 enteries */ | ||
968 | if (n >= 1024) { | ||
969 | ql4_printk(KERN_WARNING, ha, | ||
970 | "%s: %s:n=0x%x [ERROR] Card flash not initialized.\n", | ||
971 | DRIVER_NAME, __func__, n); | ||
972 | return -1; | ||
973 | } | ||
974 | |||
975 | ql4_printk(KERN_INFO, ha, | ||
976 | "%s: %d CRB init values found in ROM.\n", DRIVER_NAME, n); | ||
977 | |||
978 | buf = kmalloc(n * sizeof(struct crb_addr_pair), GFP_KERNEL); | ||
979 | if (buf == NULL) { | ||
980 | ql4_printk(KERN_WARNING, ha, | ||
981 | "%s: [ERROR] Unable to malloc memory.\n", DRIVER_NAME); | ||
982 | return -1; | ||
983 | } | ||
984 | |||
985 | for (i = 0; i < n; i++) { | ||
986 | if (qla4_8xxx_rom_fast_read(ha, 8*i + 4*offset, &val) != 0 || | ||
987 | qla4_8xxx_rom_fast_read(ha, 8*i + 4*offset + 4, &addr) != | ||
988 | 0) { | ||
989 | kfree(buf); | ||
990 | return -1; | ||
991 | } | ||
992 | |||
993 | buf[i].addr = addr; | ||
994 | buf[i].data = val; | ||
995 | } | ||
996 | |||
997 | for (i = 0; i < n; i++) { | ||
998 | /* Translate internal CRB initialization | ||
999 | * address to PCI bus address | ||
1000 | */ | ||
1001 | off = qla4_8xxx_decode_crb_addr((unsigned long)buf[i].addr) + | ||
1002 | QLA82XX_PCI_CRBSPACE; | ||
1003 | /* Not all CRB addr/value pair to be written, | ||
1004 | * some of them are skipped | ||
1005 | */ | ||
1006 | |||
1007 | /* skip if LS bit is set*/ | ||
1008 | if (off & 0x1) { | ||
1009 | DEBUG2(ql4_printk(KERN_WARNING, ha, | ||
1010 | "Skip CRB init replay for offset = 0x%lx\n", off)); | ||
1011 | continue; | ||
1012 | } | ||
1013 | |||
1014 | /* skipping cold reboot MAGIC */ | ||
1015 | if (off == QLA82XX_CAM_RAM(0x1fc)) | ||
1016 | continue; | ||
1017 | |||
1018 | /* do not reset PCI */ | ||
1019 | if (off == (ROMUSB_GLB + 0xbc)) | ||
1020 | continue; | ||
1021 | |||
1022 | /* skip core clock, so that firmware can increase the clock */ | ||
1023 | if (off == (ROMUSB_GLB + 0xc8)) | ||
1024 | continue; | ||
1025 | |||
1026 | /* skip the function enable register */ | ||
1027 | if (off == QLA82XX_PCIE_REG(PCIE_SETUP_FUNCTION)) | ||
1028 | continue; | ||
1029 | |||
1030 | if (off == QLA82XX_PCIE_REG(PCIE_SETUP_FUNCTION2)) | ||
1031 | continue; | ||
1032 | |||
1033 | if ((off & 0x0ff00000) == QLA82XX_CRB_SMB) | ||
1034 | continue; | ||
1035 | |||
1036 | if ((off & 0x0ff00000) == QLA82XX_CRB_DDR_NET) | ||
1037 | continue; | ||
1038 | |||
1039 | if (off == ADDR_ERROR) { | ||
1040 | ql4_printk(KERN_WARNING, ha, | ||
1041 | "%s: [ERROR] Unknown addr: 0x%08lx\n", | ||
1042 | DRIVER_NAME, buf[i].addr); | ||
1043 | continue; | ||
1044 | } | ||
1045 | |||
1046 | qla4_8xxx_wr_32(ha, off, buf[i].data); | ||
1047 | |||
1048 | /* ISP requires much bigger delay to settle down, | ||
1049 | * else crb_window returns 0xffffffff | ||
1050 | */ | ||
1051 | if (off == QLA82XX_ROMUSB_GLB_SW_RESET) | ||
1052 | msleep(1000); | ||
1053 | |||
1054 | /* ISP requires millisec delay between | ||
1055 | * successive CRB register updation | ||
1056 | */ | ||
1057 | msleep(1); | ||
1058 | } | ||
1059 | |||
1060 | kfree(buf); | ||
1061 | |||
1062 | /* Resetting the data and instruction cache */ | ||
1063 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_D+0xec, 0x1e); | ||
1064 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_D+0x4c, 8); | ||
1065 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_I+0x4c, 8); | ||
1066 | |||
1067 | /* Clear all protocol processing engines */ | ||
1068 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_0+0x8, 0); | ||
1069 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_0+0xc, 0); | ||
1070 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_1+0x8, 0); | ||
1071 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_1+0xc, 0); | ||
1072 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_2+0x8, 0); | ||
1073 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_2+0xc, 0); | ||
1074 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_3+0x8, 0); | ||
1075 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_3+0xc, 0); | ||
1076 | |||
1077 | return 0; | ||
1078 | } | ||
1079 | |||
1080 | static int qla4_8xxx_check_for_bad_spd(struct scsi_qla_host *ha) | ||
1081 | { | ||
1082 | u32 val = 0; | ||
1083 | val = qla4_8xxx_rd_32(ha, BOOT_LOADER_DIMM_STATUS) ; | ||
1084 | val &= QLA82XX_BOOT_LOADER_MN_ISSUE; | ||
1085 | if (val & QLA82XX_PEG_TUNE_MN_SPD_ZEROED) { | ||
1086 | printk("Memory DIMM SPD not programmed. Assumed valid.\n"); | ||
1087 | return 1; | ||
1088 | } else if (val) { | ||
1089 | printk("Memory DIMM type incorrect. Info:%08X.\n", val); | ||
1090 | return 2; | ||
1091 | } | ||
1092 | return 0; | ||
1093 | } | ||
1094 | |||
1095 | static int | ||
1096 | qla4_8xxx_load_from_flash(struct scsi_qla_host *ha, uint32_t image_start) | ||
1097 | { | ||
1098 | int i; | ||
1099 | long size = 0; | ||
1100 | long flashaddr, memaddr; | ||
1101 | u64 data; | ||
1102 | u32 high, low; | ||
1103 | |||
1104 | flashaddr = memaddr = ha->hw.flt_region_bootload; | ||
1105 | size = (image_start - flashaddr)/8; | ||
1106 | |||
1107 | DEBUG2(printk("scsi%ld: %s: bootldr=0x%lx, fw_image=0x%x\n", | ||
1108 | ha->host_no, __func__, flashaddr, image_start)); | ||
1109 | |||
1110 | for (i = 0; i < size; i++) { | ||
1111 | if ((qla4_8xxx_rom_fast_read(ha, flashaddr, (int *)&low)) || | ||
1112 | (qla4_8xxx_rom_fast_read(ha, flashaddr + 4, | ||
1113 | (int *)&high))) { | ||
1114 | return -1; | ||
1115 | } | ||
1116 | data = ((u64)high << 32) | low ; | ||
1117 | qla4_8xxx_pci_mem_write_2M(ha, memaddr, &data, 8); | ||
1118 | flashaddr += 8; | ||
1119 | memaddr += 8; | ||
1120 | |||
1121 | if (i%0x1000 == 0) | ||
1122 | msleep(1); | ||
1123 | |||
1124 | } | ||
1125 | |||
1126 | udelay(100); | ||
1127 | |||
1128 | read_lock(&ha->hw_lock); | ||
1129 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_PEG_NET_0 + 0x18, 0x1020); | ||
1130 | qla4_8xxx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0x80001e); | ||
1131 | read_unlock(&ha->hw_lock); | ||
1132 | |||
1133 | return 0; | ||
1134 | } | ||
1135 | |||
1136 | static int qla4_8xxx_load_fw(struct scsi_qla_host *ha, uint32_t image_start) | ||
1137 | { | ||
1138 | u32 rst; | ||
1139 | |||
1140 | qla4_8xxx_wr_32(ha, CRB_CMDPEG_STATE, 0); | ||
1141 | if (qla4_8xxx_pinit_from_rom(ha, 0) != QLA_SUCCESS) { | ||
1142 | printk(KERN_WARNING "%s: Error during CRB Initialization\n", | ||
1143 | __func__); | ||
1144 | return QLA_ERROR; | ||
1145 | } | ||
1146 | |||
1147 | udelay(500); | ||
1148 | |||
1149 | /* at this point, QM is in reset. This could be a problem if there are | ||
1150 | * incoming d* transition queue messages. QM/PCIE could wedge. | ||
1151 | * To get around this, QM is brought out of reset. | ||
1152 | */ | ||
1153 | |||
1154 | rst = qla4_8xxx_rd_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET); | ||
1155 | /* unreset qm */ | ||
1156 | rst &= ~(1 << 28); | ||
1157 | qla4_8xxx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, rst); | ||
1158 | |||
1159 | if (qla4_8xxx_load_from_flash(ha, image_start)) { | ||
1160 | printk("%s: Error trying to load fw from flash!\n", __func__); | ||
1161 | return QLA_ERROR; | ||
1162 | } | ||
1163 | |||
1164 | return QLA_SUCCESS; | ||
1165 | } | ||
1166 | |||
1167 | int | ||
1168 | qla4_8xxx_pci_mem_read_2M(struct scsi_qla_host *ha, | ||
1169 | u64 off, void *data, int size) | ||
1170 | { | ||
1171 | int i, j = 0, k, start, end, loop, sz[2], off0[2]; | ||
1172 | int shift_amount; | ||
1173 | uint32_t temp; | ||
1174 | uint64_t off8, val, mem_crb, word[2] = {0, 0}; | ||
1175 | |||
1176 | /* | ||
1177 | * If not MN, go check for MS or invalid. | ||
1178 | */ | ||
1179 | |||
1180 | if (off >= QLA82XX_ADDR_QDR_NET && off <= QLA82XX_P3_ADDR_QDR_NET_MAX) | ||
1181 | mem_crb = QLA82XX_CRB_QDR_NET; | ||
1182 | else { | ||
1183 | mem_crb = QLA82XX_CRB_DDR_NET; | ||
1184 | if (qla4_8xxx_pci_mem_bound_check(ha, off, size) == 0) | ||
1185 | return qla4_8xxx_pci_mem_read_direct(ha, | ||
1186 | off, data, size); | ||
1187 | } | ||
1188 | |||
1189 | |||
1190 | off8 = off & 0xfffffff0; | ||
1191 | off0[0] = off & 0xf; | ||
1192 | sz[0] = (size < (16 - off0[0])) ? size : (16 - off0[0]); | ||
1193 | shift_amount = 4; | ||
1194 | |||
1195 | loop = ((off0[0] + size - 1) >> shift_amount) + 1; | ||
1196 | off0[1] = 0; | ||
1197 | sz[1] = size - sz[0]; | ||
1198 | |||
1199 | for (i = 0; i < loop; i++) { | ||
1200 | temp = off8 + (i << shift_amount); | ||
1201 | qla4_8xxx_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_LO, temp); | ||
1202 | temp = 0; | ||
1203 | qla4_8xxx_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_HI, temp); | ||
1204 | temp = MIU_TA_CTL_ENABLE; | ||
1205 | qla4_8xxx_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp); | ||
1206 | temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE; | ||
1207 | qla4_8xxx_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp); | ||
1208 | |||
1209 | for (j = 0; j < MAX_CTL_CHECK; j++) { | ||
1210 | temp = qla4_8xxx_rd_32(ha, mem_crb + MIU_TEST_AGT_CTRL); | ||
1211 | if ((temp & MIU_TA_CTL_BUSY) == 0) | ||
1212 | break; | ||
1213 | } | ||
1214 | |||
1215 | if (j >= MAX_CTL_CHECK) { | ||
1216 | if (printk_ratelimit()) | ||
1217 | ql4_printk(KERN_ERR, ha, | ||
1218 | "failed to read through agent\n"); | ||
1219 | break; | ||
1220 | } | ||
1221 | |||
1222 | start = off0[i] >> 2; | ||
1223 | end = (off0[i] + sz[i] - 1) >> 2; | ||
1224 | for (k = start; k <= end; k++) { | ||
1225 | temp = qla4_8xxx_rd_32(ha, | ||
1226 | mem_crb + MIU_TEST_AGT_RDDATA(k)); | ||
1227 | word[i] |= ((uint64_t)temp << (32 * (k & 1))); | ||
1228 | } | ||
1229 | } | ||
1230 | |||
1231 | if (j >= MAX_CTL_CHECK) | ||
1232 | return -1; | ||
1233 | |||
1234 | if ((off0[0] & 7) == 0) { | ||
1235 | val = word[0]; | ||
1236 | } else { | ||
1237 | val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) | | ||
1238 | ((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8)); | ||
1239 | } | ||
1240 | |||
1241 | switch (size) { | ||
1242 | case 1: | ||
1243 | *(uint8_t *)data = val; | ||
1244 | break; | ||
1245 | case 2: | ||
1246 | *(uint16_t *)data = val; | ||
1247 | break; | ||
1248 | case 4: | ||
1249 | *(uint32_t *)data = val; | ||
1250 | break; | ||
1251 | case 8: | ||
1252 | *(uint64_t *)data = val; | ||
1253 | break; | ||
1254 | } | ||
1255 | return 0; | ||
1256 | } | ||
1257 | |||
1258 | int | ||
1259 | qla4_8xxx_pci_mem_write_2M(struct scsi_qla_host *ha, | ||
1260 | u64 off, void *data, int size) | ||
1261 | { | ||
1262 | int i, j, ret = 0, loop, sz[2], off0; | ||
1263 | int scale, shift_amount, startword; | ||
1264 | uint32_t temp; | ||
1265 | uint64_t off8, mem_crb, tmpw, word[2] = {0, 0}; | ||
1266 | |||
1267 | /* | ||
1268 | * If not MN, go check for MS or invalid. | ||
1269 | */ | ||
1270 | if (off >= QLA82XX_ADDR_QDR_NET && off <= QLA82XX_P3_ADDR_QDR_NET_MAX) | ||
1271 | mem_crb = QLA82XX_CRB_QDR_NET; | ||
1272 | else { | ||
1273 | mem_crb = QLA82XX_CRB_DDR_NET; | ||
1274 | if (qla4_8xxx_pci_mem_bound_check(ha, off, size) == 0) | ||
1275 | return qla4_8xxx_pci_mem_write_direct(ha, | ||
1276 | off, data, size); | ||
1277 | } | ||
1278 | |||
1279 | off0 = off & 0x7; | ||
1280 | sz[0] = (size < (8 - off0)) ? size : (8 - off0); | ||
1281 | sz[1] = size - sz[0]; | ||
1282 | |||
1283 | off8 = off & 0xfffffff0; | ||
1284 | loop = (((off & 0xf) + size - 1) >> 4) + 1; | ||
1285 | shift_amount = 4; | ||
1286 | scale = 2; | ||
1287 | startword = (off & 0xf)/8; | ||
1288 | |||
1289 | for (i = 0; i < loop; i++) { | ||
1290 | if (qla4_8xxx_pci_mem_read_2M(ha, off8 + | ||
1291 | (i << shift_amount), &word[i * scale], 8)) | ||
1292 | return -1; | ||
1293 | } | ||
1294 | |||
1295 | switch (size) { | ||
1296 | case 1: | ||
1297 | tmpw = *((uint8_t *)data); | ||
1298 | break; | ||
1299 | case 2: | ||
1300 | tmpw = *((uint16_t *)data); | ||
1301 | break; | ||
1302 | case 4: | ||
1303 | tmpw = *((uint32_t *)data); | ||
1304 | break; | ||
1305 | case 8: | ||
1306 | default: | ||
1307 | tmpw = *((uint64_t *)data); | ||
1308 | break; | ||
1309 | } | ||
1310 | |||
1311 | if (sz[0] == 8) | ||
1312 | word[startword] = tmpw; | ||
1313 | else { | ||
1314 | word[startword] &= | ||
1315 | ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8)); | ||
1316 | word[startword] |= tmpw << (off0 * 8); | ||
1317 | } | ||
1318 | |||
1319 | if (sz[1] != 0) { | ||
1320 | word[startword+1] &= ~(~0ULL << (sz[1] * 8)); | ||
1321 | word[startword+1] |= tmpw >> (sz[0] * 8); | ||
1322 | } | ||
1323 | |||
1324 | for (i = 0; i < loop; i++) { | ||
1325 | temp = off8 + (i << shift_amount); | ||
1326 | qla4_8xxx_wr_32(ha, mem_crb+MIU_TEST_AGT_ADDR_LO, temp); | ||
1327 | temp = 0; | ||
1328 | qla4_8xxx_wr_32(ha, mem_crb+MIU_TEST_AGT_ADDR_HI, temp); | ||
1329 | temp = word[i * scale] & 0xffffffff; | ||
1330 | qla4_8xxx_wr_32(ha, mem_crb+MIU_TEST_AGT_WRDATA_LO, temp); | ||
1331 | temp = (word[i * scale] >> 32) & 0xffffffff; | ||
1332 | qla4_8xxx_wr_32(ha, mem_crb+MIU_TEST_AGT_WRDATA_HI, temp); | ||
1333 | temp = word[i*scale + 1] & 0xffffffff; | ||
1334 | qla4_8xxx_wr_32(ha, mem_crb + MIU_TEST_AGT_WRDATA_UPPER_LO, | ||
1335 | temp); | ||
1336 | temp = (word[i*scale + 1] >> 32) & 0xffffffff; | ||
1337 | qla4_8xxx_wr_32(ha, mem_crb + MIU_TEST_AGT_WRDATA_UPPER_HI, | ||
1338 | temp); | ||
1339 | |||
1340 | temp = MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE; | ||
1341 | qla4_8xxx_wr_32(ha, mem_crb+MIU_TEST_AGT_CTRL, temp); | ||
1342 | temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE; | ||
1343 | qla4_8xxx_wr_32(ha, mem_crb+MIU_TEST_AGT_CTRL, temp); | ||
1344 | |||
1345 | for (j = 0; j < MAX_CTL_CHECK; j++) { | ||
1346 | temp = qla4_8xxx_rd_32(ha, mem_crb + MIU_TEST_AGT_CTRL); | ||
1347 | if ((temp & MIU_TA_CTL_BUSY) == 0) | ||
1348 | break; | ||
1349 | } | ||
1350 | |||
1351 | if (j >= MAX_CTL_CHECK) { | ||
1352 | if (printk_ratelimit()) | ||
1353 | ql4_printk(KERN_ERR, ha, | ||
1354 | "failed to write through agent\n"); | ||
1355 | ret = -1; | ||
1356 | break; | ||
1357 | } | ||
1358 | } | ||
1359 | |||
1360 | return ret; | ||
1361 | } | ||
1362 | |||
1363 | static int qla4_8xxx_cmdpeg_ready(struct scsi_qla_host *ha, int pegtune_val) | ||
1364 | { | ||
1365 | u32 val = 0; | ||
1366 | int retries = 60; | ||
1367 | |||
1368 | if (!pegtune_val) { | ||
1369 | do { | ||
1370 | val = qla4_8xxx_rd_32(ha, CRB_CMDPEG_STATE); | ||
1371 | if ((val == PHAN_INITIALIZE_COMPLETE) || | ||
1372 | (val == PHAN_INITIALIZE_ACK)) | ||
1373 | return 0; | ||
1374 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
1375 | schedule_timeout(500); | ||
1376 | |||
1377 | } while (--retries); | ||
1378 | |||
1379 | qla4_8xxx_check_for_bad_spd(ha); | ||
1380 | |||
1381 | if (!retries) { | ||
1382 | pegtune_val = qla4_8xxx_rd_32(ha, | ||
1383 | QLA82XX_ROMUSB_GLB_PEGTUNE_DONE); | ||
1384 | printk(KERN_WARNING "%s: init failed, " | ||
1385 | "pegtune_val = %x\n", __func__, pegtune_val); | ||
1386 | return -1; | ||
1387 | } | ||
1388 | } | ||
1389 | return 0; | ||
1390 | } | ||
1391 | |||
1392 | static int qla4_8xxx_rcvpeg_ready(struct scsi_qla_host *ha) | ||
1393 | { | ||
1394 | uint32_t state = 0; | ||
1395 | int loops = 0; | ||
1396 | |||
1397 | /* Window 1 call */ | ||
1398 | read_lock(&ha->hw_lock); | ||
1399 | state = qla4_8xxx_rd_32(ha, CRB_RCVPEG_STATE); | ||
1400 | read_unlock(&ha->hw_lock); | ||
1401 | |||
1402 | while ((state != PHAN_PEG_RCV_INITIALIZED) && (loops < 30000)) { | ||
1403 | udelay(100); | ||
1404 | /* Window 1 call */ | ||
1405 | read_lock(&ha->hw_lock); | ||
1406 | state = qla4_8xxx_rd_32(ha, CRB_RCVPEG_STATE); | ||
1407 | read_unlock(&ha->hw_lock); | ||
1408 | |||
1409 | loops++; | ||
1410 | } | ||
1411 | |||
1412 | if (loops >= 30000) { | ||
1413 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
1414 | "Receive Peg initialization not complete: 0x%x.\n", state)); | ||
1415 | return QLA_ERROR; | ||
1416 | } | ||
1417 | |||
1418 | return QLA_SUCCESS; | ||
1419 | } | ||
1420 | |||
1421 | static inline void | ||
1422 | qla4_8xxx_set_drv_active(struct scsi_qla_host *ha) | ||
1423 | { | ||
1424 | uint32_t drv_active; | ||
1425 | |||
1426 | drv_active = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); | ||
1427 | drv_active |= (1 << (ha->func_num * 4)); | ||
1428 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, drv_active); | ||
1429 | } | ||
1430 | |||
1431 | void | ||
1432 | qla4_8xxx_clear_drv_active(struct scsi_qla_host *ha) | ||
1433 | { | ||
1434 | uint32_t drv_active; | ||
1435 | |||
1436 | drv_active = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); | ||
1437 | drv_active &= ~(1 << (ha->func_num * 4)); | ||
1438 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, drv_active); | ||
1439 | } | ||
1440 | |||
1441 | static inline int | ||
1442 | qla4_8xxx_need_reset(struct scsi_qla_host *ha) | ||
1443 | { | ||
1444 | uint32_t drv_state; | ||
1445 | int rval; | ||
1446 | |||
1447 | drv_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_STATE); | ||
1448 | rval = drv_state & (1 << (ha->func_num * 4)); | ||
1449 | return rval; | ||
1450 | } | ||
1451 | |||
1452 | static inline void | ||
1453 | qla4_8xxx_set_rst_ready(struct scsi_qla_host *ha) | ||
1454 | { | ||
1455 | uint32_t drv_state; | ||
1456 | |||
1457 | drv_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_STATE); | ||
1458 | drv_state |= (1 << (ha->func_num * 4)); | ||
1459 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_STATE, drv_state); | ||
1460 | } | ||
1461 | |||
1462 | static inline void | ||
1463 | qla4_8xxx_clear_rst_ready(struct scsi_qla_host *ha) | ||
1464 | { | ||
1465 | uint32_t drv_state; | ||
1466 | |||
1467 | drv_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_STATE); | ||
1468 | drv_state &= ~(1 << (ha->func_num * 4)); | ||
1469 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_STATE, drv_state); | ||
1470 | } | ||
1471 | |||
1472 | static inline void | ||
1473 | qla4_8xxx_set_qsnt_ready(struct scsi_qla_host *ha) | ||
1474 | { | ||
1475 | uint32_t qsnt_state; | ||
1476 | |||
1477 | qsnt_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_STATE); | ||
1478 | qsnt_state |= (2 << (ha->func_num * 4)); | ||
1479 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_STATE, qsnt_state); | ||
1480 | } | ||
1481 | |||
1482 | |||
1483 | static int | ||
1484 | qla4_8xxx_start_firmware(struct scsi_qla_host *ha, uint32_t image_start) | ||
1485 | { | ||
1486 | int pcie_cap; | ||
1487 | uint16_t lnk; | ||
1488 | |||
1489 | /* scrub dma mask expansion register */ | ||
1490 | qla4_8xxx_wr_32(ha, CRB_DMA_SHIFT, 0x55555555); | ||
1491 | |||
1492 | /* Overwrite stale initialization register values */ | ||
1493 | qla4_8xxx_wr_32(ha, CRB_CMDPEG_STATE, 0); | ||
1494 | qla4_8xxx_wr_32(ha, CRB_RCVPEG_STATE, 0); | ||
1495 | qla4_8xxx_wr_32(ha, QLA82XX_PEG_HALT_STATUS1, 0); | ||
1496 | qla4_8xxx_wr_32(ha, QLA82XX_PEG_HALT_STATUS2, 0); | ||
1497 | |||
1498 | if (qla4_8xxx_load_fw(ha, image_start) != QLA_SUCCESS) { | ||
1499 | printk("%s: Error trying to start fw!\n", __func__); | ||
1500 | return QLA_ERROR; | ||
1501 | } | ||
1502 | |||
1503 | /* Handshake with the card before we register the devices. */ | ||
1504 | if (qla4_8xxx_cmdpeg_ready(ha, 0) != QLA_SUCCESS) { | ||
1505 | printk("%s: Error during card handshake!\n", __func__); | ||
1506 | return QLA_ERROR; | ||
1507 | } | ||
1508 | |||
1509 | /* Negotiated Link width */ | ||
1510 | pcie_cap = pci_find_capability(ha->pdev, PCI_CAP_ID_EXP); | ||
1511 | pci_read_config_word(ha->pdev, pcie_cap + PCI_EXP_LNKSTA, &lnk); | ||
1512 | ha->link_width = (lnk >> 4) & 0x3f; | ||
1513 | |||
1514 | /* Synchronize with Receive peg */ | ||
1515 | return qla4_8xxx_rcvpeg_ready(ha); | ||
1516 | } | ||
1517 | |||
1518 | static int | ||
1519 | qla4_8xxx_try_start_fw(struct scsi_qla_host *ha) | ||
1520 | { | ||
1521 | int rval = QLA_ERROR; | ||
1522 | |||
1523 | /* | ||
1524 | * FW Load priority: | ||
1525 | * 1) Operational firmware residing in flash. | ||
1526 | * 2) Fail | ||
1527 | */ | ||
1528 | |||
1529 | ql4_printk(KERN_INFO, ha, | ||
1530 | "FW: Retrieving flash offsets from FLT/FDT ...\n"); | ||
1531 | rval = qla4_8xxx_get_flash_info(ha); | ||
1532 | if (rval != QLA_SUCCESS) | ||
1533 | return rval; | ||
1534 | |||
1535 | ql4_printk(KERN_INFO, ha, | ||
1536 | "FW: Attempting to load firmware from flash...\n"); | ||
1537 | rval = qla4_8xxx_start_firmware(ha, ha->hw.flt_region_fw); | ||
1538 | if (rval == QLA_SUCCESS) | ||
1539 | return rval; | ||
1540 | |||
1541 | ql4_printk(KERN_ERR, ha, "FW: Load firmware from flash FAILED...\n"); | ||
1542 | |||
1543 | return rval; | ||
1544 | } | ||
1545 | |||
1546 | /** | ||
1547 | * qla4_8xxx_device_bootstrap - Initialize device, set DEV_READY, start fw | ||
1548 | * @ha: pointer to adapter structure | ||
1549 | * | ||
1550 | * Note: IDC lock must be held upon entry | ||
1551 | **/ | ||
1552 | static int | ||
1553 | qla4_8xxx_device_bootstrap(struct scsi_qla_host *ha) | ||
1554 | { | ||
1555 | int rval, i, timeout; | ||
1556 | uint32_t old_count, count; | ||
1557 | |||
1558 | if (qla4_8xxx_need_reset(ha)) | ||
1559 | goto dev_initialize; | ||
1560 | |||
1561 | old_count = qla4_8xxx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); | ||
1562 | |||
1563 | for (i = 0; i < 10; i++) { | ||
1564 | timeout = msleep_interruptible(200); | ||
1565 | if (timeout) { | ||
1566 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, | ||
1567 | QLA82XX_DEV_FAILED); | ||
1568 | return QLA_ERROR; | ||
1569 | } | ||
1570 | |||
1571 | count = qla4_8xxx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); | ||
1572 | if (count != old_count) | ||
1573 | goto dev_ready; | ||
1574 | } | ||
1575 | |||
1576 | dev_initialize: | ||
1577 | /* set to DEV_INITIALIZING */ | ||
1578 | ql4_printk(KERN_INFO, ha, "HW State: INITIALIZING\n"); | ||
1579 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_INITIALIZING); | ||
1580 | |||
1581 | /* Driver that sets device state to initializating sets IDC version */ | ||
1582 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_IDC_VERSION, QLA82XX_IDC_VERSION); | ||
1583 | |||
1584 | qla4_8xxx_idc_unlock(ha); | ||
1585 | rval = qla4_8xxx_try_start_fw(ha); | ||
1586 | qla4_8xxx_idc_lock(ha); | ||
1587 | |||
1588 | if (rval != QLA_SUCCESS) { | ||
1589 | ql4_printk(KERN_INFO, ha, "HW State: FAILED\n"); | ||
1590 | qla4_8xxx_clear_drv_active(ha); | ||
1591 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_FAILED); | ||
1592 | return rval; | ||
1593 | } | ||
1594 | |||
1595 | dev_ready: | ||
1596 | ql4_printk(KERN_INFO, ha, "HW State: READY\n"); | ||
1597 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_READY); | ||
1598 | |||
1599 | return QLA_SUCCESS; | ||
1600 | } | ||
1601 | |||
1602 | /** | ||
1603 | * qla4_8xxx_need_reset_handler - Code to start reset sequence | ||
1604 | * @ha: pointer to adapter structure | ||
1605 | * | ||
1606 | * Note: IDC lock must be held upon entry | ||
1607 | **/ | ||
1608 | static void | ||
1609 | qla4_8xxx_need_reset_handler(struct scsi_qla_host *ha) | ||
1610 | { | ||
1611 | uint32_t dev_state, drv_state, drv_active; | ||
1612 | unsigned long reset_timeout; | ||
1613 | |||
1614 | ql4_printk(KERN_INFO, ha, | ||
1615 | "Performing ISP error recovery\n"); | ||
1616 | |||
1617 | if (test_and_clear_bit(AF_ONLINE, &ha->flags)) { | ||
1618 | qla4_8xxx_idc_unlock(ha); | ||
1619 | ha->isp_ops->disable_intrs(ha); | ||
1620 | qla4_8xxx_idc_lock(ha); | ||
1621 | } | ||
1622 | |||
1623 | qla4_8xxx_set_rst_ready(ha); | ||
1624 | |||
1625 | /* wait for 10 seconds for reset ack from all functions */ | ||
1626 | reset_timeout = jiffies + (ha->nx_reset_timeout * HZ); | ||
1627 | |||
1628 | drv_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_STATE); | ||
1629 | drv_active = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); | ||
1630 | |||
1631 | ql4_printk(KERN_INFO, ha, | ||
1632 | "%s(%ld): drv_state = 0x%x, drv_active = 0x%x\n", | ||
1633 | __func__, ha->host_no, drv_state, drv_active); | ||
1634 | |||
1635 | while (drv_state != drv_active) { | ||
1636 | if (time_after_eq(jiffies, reset_timeout)) { | ||
1637 | printk("%s: RESET TIMEOUT!\n", DRIVER_NAME); | ||
1638 | break; | ||
1639 | } | ||
1640 | |||
1641 | qla4_8xxx_idc_unlock(ha); | ||
1642 | msleep(1000); | ||
1643 | qla4_8xxx_idc_lock(ha); | ||
1644 | |||
1645 | drv_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_STATE); | ||
1646 | drv_active = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); | ||
1647 | } | ||
1648 | |||
1649 | dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); | ||
1650 | ql4_printk(KERN_INFO, ha, "3:Device state is 0x%x = %s\n", dev_state, | ||
1651 | dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown"); | ||
1652 | |||
1653 | /* Force to DEV_COLD unless someone else is starting a reset */ | ||
1654 | if (dev_state != QLA82XX_DEV_INITIALIZING) { | ||
1655 | ql4_printk(KERN_INFO, ha, "HW State: COLD/RE-INIT\n"); | ||
1656 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_COLD); | ||
1657 | } | ||
1658 | } | ||
1659 | |||
1660 | /** | ||
1661 | * qla4_8xxx_need_qsnt_handler - Code to start qsnt | ||
1662 | * @ha: pointer to adapter structure | ||
1663 | **/ | ||
1664 | void | ||
1665 | qla4_8xxx_need_qsnt_handler(struct scsi_qla_host *ha) | ||
1666 | { | ||
1667 | qla4_8xxx_idc_lock(ha); | ||
1668 | qla4_8xxx_set_qsnt_ready(ha); | ||
1669 | qla4_8xxx_idc_unlock(ha); | ||
1670 | } | ||
1671 | |||
1672 | /** | ||
1673 | * qla4_8xxx_device_state_handler - Adapter state machine | ||
1674 | * @ha: pointer to host adapter structure. | ||
1675 | * | ||
1676 | * Note: IDC lock must be UNLOCKED upon entry | ||
1677 | **/ | ||
1678 | int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha) | ||
1679 | { | ||
1680 | uint32_t dev_state; | ||
1681 | int rval = QLA_SUCCESS; | ||
1682 | unsigned long dev_init_timeout; | ||
1683 | |||
1684 | if (!test_bit(AF_INIT_DONE, &ha->flags)) | ||
1685 | qla4_8xxx_set_drv_active(ha); | ||
1686 | |||
1687 | dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); | ||
1688 | ql4_printk(KERN_INFO, ha, "1:Device state is 0x%x = %s\n", dev_state, | ||
1689 | dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown"); | ||
1690 | |||
1691 | /* wait for 30 seconds for device to go ready */ | ||
1692 | dev_init_timeout = jiffies + (ha->nx_dev_init_timeout * HZ); | ||
1693 | |||
1694 | while (1) { | ||
1695 | qla4_8xxx_idc_lock(ha); | ||
1696 | |||
1697 | if (time_after_eq(jiffies, dev_init_timeout)) { | ||
1698 | ql4_printk(KERN_WARNING, ha, "Device init failed!\n"); | ||
1699 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, | ||
1700 | QLA82XX_DEV_FAILED); | ||
1701 | } | ||
1702 | |||
1703 | dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); | ||
1704 | ql4_printk(KERN_INFO, ha, | ||
1705 | "2:Device state is 0x%x = %s\n", dev_state, | ||
1706 | dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown"); | ||
1707 | |||
1708 | /* NOTE: Make sure idc unlocked upon exit of switch statement */ | ||
1709 | switch (dev_state) { | ||
1710 | case QLA82XX_DEV_READY: | ||
1711 | qla4_8xxx_idc_unlock(ha); | ||
1712 | goto exit; | ||
1713 | case QLA82XX_DEV_COLD: | ||
1714 | rval = qla4_8xxx_device_bootstrap(ha); | ||
1715 | qla4_8xxx_idc_unlock(ha); | ||
1716 | goto exit; | ||
1717 | case QLA82XX_DEV_INITIALIZING: | ||
1718 | qla4_8xxx_idc_unlock(ha); | ||
1719 | msleep(1000); | ||
1720 | break; | ||
1721 | case QLA82XX_DEV_NEED_RESET: | ||
1722 | if (!ql4xdontresethba) { | ||
1723 | qla4_8xxx_need_reset_handler(ha); | ||
1724 | /* Update timeout value after need | ||
1725 | * reset handler */ | ||
1726 | dev_init_timeout = jiffies + | ||
1727 | (ha->nx_dev_init_timeout * HZ); | ||
1728 | } | ||
1729 | qla4_8xxx_idc_unlock(ha); | ||
1730 | break; | ||
1731 | case QLA82XX_DEV_NEED_QUIESCENT: | ||
1732 | qla4_8xxx_idc_unlock(ha); | ||
1733 | /* idc locked/unlocked in handler */ | ||
1734 | qla4_8xxx_need_qsnt_handler(ha); | ||
1735 | qla4_8xxx_idc_lock(ha); | ||
1736 | /* fall thru needs idc_locked */ | ||
1737 | case QLA82XX_DEV_QUIESCENT: | ||
1738 | qla4_8xxx_idc_unlock(ha); | ||
1739 | msleep(1000); | ||
1740 | break; | ||
1741 | case QLA82XX_DEV_FAILED: | ||
1742 | qla4_8xxx_idc_unlock(ha); | ||
1743 | qla4xxx_dead_adapter_cleanup(ha); | ||
1744 | rval = QLA_ERROR; | ||
1745 | goto exit; | ||
1746 | default: | ||
1747 | qla4_8xxx_idc_unlock(ha); | ||
1748 | qla4xxx_dead_adapter_cleanup(ha); | ||
1749 | rval = QLA_ERROR; | ||
1750 | goto exit; | ||
1751 | } | ||
1752 | } | ||
1753 | exit: | ||
1754 | return rval; | ||
1755 | } | ||
1756 | |||
1757 | int qla4_8xxx_load_risc(struct scsi_qla_host *ha) | ||
1758 | { | ||
1759 | int retval; | ||
1760 | retval = qla4_8xxx_device_state_handler(ha); | ||
1761 | |||
1762 | if (retval == QLA_SUCCESS && | ||
1763 | !test_bit(AF_INIT_DONE, &ha->flags)) { | ||
1764 | retval = qla4xxx_request_irqs(ha); | ||
1765 | if (retval != QLA_SUCCESS) { | ||
1766 | ql4_printk(KERN_WARNING, ha, | ||
1767 | "Failed to reserve interrupt %d already in use.\n", | ||
1768 | ha->pdev->irq); | ||
1769 | } else { | ||
1770 | set_bit(AF_IRQ_ATTACHED, &ha->flags); | ||
1771 | ha->host->irq = ha->pdev->irq; | ||
1772 | ql4_printk(KERN_INFO, ha, "%s: irq %d attached\n", | ||
1773 | __func__, ha->pdev->irq); | ||
1774 | } | ||
1775 | } | ||
1776 | return retval; | ||
1777 | } | ||
1778 | |||
1779 | /*****************************************************************************/ | ||
1780 | /* Flash Manipulation Routines */ | ||
1781 | /*****************************************************************************/ | ||
1782 | |||
1783 | #define OPTROM_BURST_SIZE 0x1000 | ||
1784 | #define OPTROM_BURST_DWORDS (OPTROM_BURST_SIZE / 4) | ||
1785 | |||
1786 | #define FARX_DATA_FLAG BIT_31 | ||
1787 | #define FARX_ACCESS_FLASH_CONF 0x7FFD0000 | ||
1788 | #define FARX_ACCESS_FLASH_DATA 0x7FF00000 | ||
1789 | |||
1790 | static inline uint32_t | ||
1791 | flash_conf_addr(struct ql82xx_hw_data *hw, uint32_t faddr) | ||
1792 | { | ||
1793 | return hw->flash_conf_off | faddr; | ||
1794 | } | ||
1795 | |||
1796 | static inline uint32_t | ||
1797 | flash_data_addr(struct ql82xx_hw_data *hw, uint32_t faddr) | ||
1798 | { | ||
1799 | return hw->flash_data_off | faddr; | ||
1800 | } | ||
1801 | |||
1802 | static uint32_t * | ||
1803 | qla4_8xxx_read_flash_data(struct scsi_qla_host *ha, uint32_t *dwptr, | ||
1804 | uint32_t faddr, uint32_t length) | ||
1805 | { | ||
1806 | uint32_t i; | ||
1807 | uint32_t val; | ||
1808 | int loops = 0; | ||
1809 | while ((qla4_8xxx_rom_lock(ha) != 0) && (loops < 50000)) { | ||
1810 | udelay(100); | ||
1811 | cond_resched(); | ||
1812 | loops++; | ||
1813 | } | ||
1814 | if (loops >= 50000) { | ||
1815 | ql4_printk(KERN_WARNING, ha, "ROM lock failed\n"); | ||
1816 | return dwptr; | ||
1817 | } | ||
1818 | |||
1819 | /* Dword reads to flash. */ | ||
1820 | for (i = 0; i < length/4; i++, faddr += 4) { | ||
1821 | if (qla4_8xxx_do_rom_fast_read(ha, faddr, &val)) { | ||
1822 | ql4_printk(KERN_WARNING, ha, | ||
1823 | "Do ROM fast read failed\n"); | ||
1824 | goto done_read; | ||
1825 | } | ||
1826 | dwptr[i] = __constant_cpu_to_le32(val); | ||
1827 | } | ||
1828 | |||
1829 | done_read: | ||
1830 | qla4_8xxx_rom_unlock(ha); | ||
1831 | return dwptr; | ||
1832 | } | ||
1833 | |||
1834 | /** | ||
1835 | * Address and length are byte address | ||
1836 | **/ | ||
1837 | static uint8_t * | ||
1838 | qla4_8xxx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, | ||
1839 | uint32_t offset, uint32_t length) | ||
1840 | { | ||
1841 | qla4_8xxx_read_flash_data(ha, (uint32_t *)buf, offset, length); | ||
1842 | return buf; | ||
1843 | } | ||
1844 | |||
1845 | static int | ||
1846 | qla4_8xxx_find_flt_start(struct scsi_qla_host *ha, uint32_t *start) | ||
1847 | { | ||
1848 | const char *loc, *locations[] = { "DEF", "PCI" }; | ||
1849 | |||
1850 | /* | ||
1851 | * FLT-location structure resides after the last PCI region. | ||
1852 | */ | ||
1853 | |||
1854 | /* Begin with sane defaults. */ | ||
1855 | loc = locations[0]; | ||
1856 | *start = FA_FLASH_LAYOUT_ADDR_82; | ||
1857 | |||
1858 | DEBUG2(ql4_printk(KERN_INFO, ha, "FLTL[%s] = 0x%x.\n", loc, *start)); | ||
1859 | return QLA_SUCCESS; | ||
1860 | } | ||
1861 | |||
1862 | static void | ||
1863 | qla4_8xxx_get_flt_info(struct scsi_qla_host *ha, uint32_t flt_addr) | ||
1864 | { | ||
1865 | const char *loc, *locations[] = { "DEF", "FLT" }; | ||
1866 | uint16_t *wptr; | ||
1867 | uint16_t cnt, chksum; | ||
1868 | uint32_t start; | ||
1869 | struct qla_flt_header *flt; | ||
1870 | struct qla_flt_region *region; | ||
1871 | struct ql82xx_hw_data *hw = &ha->hw; | ||
1872 | |||
1873 | hw->flt_region_flt = flt_addr; | ||
1874 | wptr = (uint16_t *)ha->request_ring; | ||
1875 | flt = (struct qla_flt_header *)ha->request_ring; | ||
1876 | region = (struct qla_flt_region *)&flt[1]; | ||
1877 | qla4_8xxx_read_optrom_data(ha, (uint8_t *)ha->request_ring, | ||
1878 | flt_addr << 2, OPTROM_BURST_SIZE); | ||
1879 | if (*wptr == __constant_cpu_to_le16(0xffff)) | ||
1880 | goto no_flash_data; | ||
1881 | if (flt->version != __constant_cpu_to_le16(1)) { | ||
1882 | DEBUG2(ql4_printk(KERN_INFO, ha, "Unsupported FLT detected: " | ||
1883 | "version=0x%x length=0x%x checksum=0x%x.\n", | ||
1884 | le16_to_cpu(flt->version), le16_to_cpu(flt->length), | ||
1885 | le16_to_cpu(flt->checksum))); | ||
1886 | goto no_flash_data; | ||
1887 | } | ||
1888 | |||
1889 | cnt = (sizeof(struct qla_flt_header) + le16_to_cpu(flt->length)) >> 1; | ||
1890 | for (chksum = 0; cnt; cnt--) | ||
1891 | chksum += le16_to_cpu(*wptr++); | ||
1892 | if (chksum) { | ||
1893 | DEBUG2(ql4_printk(KERN_INFO, ha, "Inconsistent FLT detected: " | ||
1894 | "version=0x%x length=0x%x checksum=0x%x.\n", | ||
1895 | le16_to_cpu(flt->version), le16_to_cpu(flt->length), | ||
1896 | chksum)); | ||
1897 | goto no_flash_data; | ||
1898 | } | ||
1899 | |||
1900 | loc = locations[1]; | ||
1901 | cnt = le16_to_cpu(flt->length) / sizeof(struct qla_flt_region); | ||
1902 | for ( ; cnt; cnt--, region++) { | ||
1903 | /* Store addresses as DWORD offsets. */ | ||
1904 | start = le32_to_cpu(region->start) >> 2; | ||
1905 | |||
1906 | DEBUG3(ql4_printk(KERN_DEBUG, ha, "FLT[%02x]: start=0x%x " | ||
1907 | "end=0x%x size=0x%x.\n", le32_to_cpu(region->code), start, | ||
1908 | le32_to_cpu(region->end) >> 2, le32_to_cpu(region->size))); | ||
1909 | |||
1910 | switch (le32_to_cpu(region->code) & 0xff) { | ||
1911 | case FLT_REG_FDT: | ||
1912 | hw->flt_region_fdt = start; | ||
1913 | break; | ||
1914 | case FLT_REG_BOOT_CODE_82: | ||
1915 | hw->flt_region_boot = start; | ||
1916 | break; | ||
1917 | case FLT_REG_FW_82: | ||
1918 | hw->flt_region_fw = start; | ||
1919 | break; | ||
1920 | case FLT_REG_BOOTLOAD_82: | ||
1921 | hw->flt_region_bootload = start; | ||
1922 | break; | ||
1923 | } | ||
1924 | } | ||
1925 | goto done; | ||
1926 | |||
1927 | no_flash_data: | ||
1928 | /* Use hardcoded defaults. */ | ||
1929 | loc = locations[0]; | ||
1930 | |||
1931 | hw->flt_region_fdt = FA_FLASH_DESCR_ADDR_82; | ||
1932 | hw->flt_region_boot = FA_BOOT_CODE_ADDR_82; | ||
1933 | hw->flt_region_bootload = FA_BOOT_LOAD_ADDR_82; | ||
1934 | hw->flt_region_fw = FA_RISC_CODE_ADDR_82; | ||
1935 | done: | ||
1936 | DEBUG2(ql4_printk(KERN_INFO, ha, "FLT[%s]: flt=0x%x fdt=0x%x " | ||
1937 | "boot=0x%x bootload=0x%x fw=0x%x\n", loc, hw->flt_region_flt, | ||
1938 | hw->flt_region_fdt, hw->flt_region_boot, hw->flt_region_bootload, | ||
1939 | hw->flt_region_fw)); | ||
1940 | } | ||
1941 | |||
1942 | static void | ||
1943 | qla4_8xxx_get_fdt_info(struct scsi_qla_host *ha) | ||
1944 | { | ||
1945 | #define FLASH_BLK_SIZE_4K 0x1000 | ||
1946 | #define FLASH_BLK_SIZE_32K 0x8000 | ||
1947 | #define FLASH_BLK_SIZE_64K 0x10000 | ||
1948 | const char *loc, *locations[] = { "MID", "FDT" }; | ||
1949 | uint16_t cnt, chksum; | ||
1950 | uint16_t *wptr; | ||
1951 | struct qla_fdt_layout *fdt; | ||
1952 | uint16_t mid, fid; | ||
1953 | struct ql82xx_hw_data *hw = &ha->hw; | ||
1954 | |||
1955 | hw->flash_conf_off = FARX_ACCESS_FLASH_CONF; | ||
1956 | hw->flash_data_off = FARX_ACCESS_FLASH_DATA; | ||
1957 | |||
1958 | wptr = (uint16_t *)ha->request_ring; | ||
1959 | fdt = (struct qla_fdt_layout *)ha->request_ring; | ||
1960 | qla4_8xxx_read_optrom_data(ha, (uint8_t *)ha->request_ring, | ||
1961 | hw->flt_region_fdt << 2, OPTROM_BURST_SIZE); | ||
1962 | |||
1963 | if (*wptr == __constant_cpu_to_le16(0xffff)) | ||
1964 | goto no_flash_data; | ||
1965 | |||
1966 | if (fdt->sig[0] != 'Q' || fdt->sig[1] != 'L' || fdt->sig[2] != 'I' || | ||
1967 | fdt->sig[3] != 'D') | ||
1968 | goto no_flash_data; | ||
1969 | |||
1970 | for (cnt = 0, chksum = 0; cnt < sizeof(struct qla_fdt_layout) >> 1; | ||
1971 | cnt++) | ||
1972 | chksum += le16_to_cpu(*wptr++); | ||
1973 | |||
1974 | if (chksum) { | ||
1975 | DEBUG2(ql4_printk(KERN_INFO, ha, "Inconsistent FDT detected: " | ||
1976 | "checksum=0x%x id=%c version=0x%x.\n", chksum, fdt->sig[0], | ||
1977 | le16_to_cpu(fdt->version))); | ||
1978 | goto no_flash_data; | ||
1979 | } | ||
1980 | |||
1981 | loc = locations[1]; | ||
1982 | mid = le16_to_cpu(fdt->man_id); | ||
1983 | fid = le16_to_cpu(fdt->id); | ||
1984 | hw->fdt_wrt_disable = fdt->wrt_disable_bits; | ||
1985 | hw->fdt_erase_cmd = flash_conf_addr(hw, 0x0300 | fdt->erase_cmd); | ||
1986 | hw->fdt_block_size = le32_to_cpu(fdt->block_size); | ||
1987 | |||
1988 | if (fdt->unprotect_sec_cmd) { | ||
1989 | hw->fdt_unprotect_sec_cmd = flash_conf_addr(hw, 0x0300 | | ||
1990 | fdt->unprotect_sec_cmd); | ||
1991 | hw->fdt_protect_sec_cmd = fdt->protect_sec_cmd ? | ||
1992 | flash_conf_addr(hw, 0x0300 | fdt->protect_sec_cmd) : | ||
1993 | flash_conf_addr(hw, 0x0336); | ||
1994 | } | ||
1995 | goto done; | ||
1996 | |||
1997 | no_flash_data: | ||
1998 | loc = locations[0]; | ||
1999 | hw->fdt_block_size = FLASH_BLK_SIZE_64K; | ||
2000 | done: | ||
2001 | DEBUG2(ql4_printk(KERN_INFO, ha, "FDT[%s]: (0x%x/0x%x) erase=0x%x " | ||
2002 | "pro=%x upro=%x wrtd=0x%x blk=0x%x.\n", loc, mid, fid, | ||
2003 | hw->fdt_erase_cmd, hw->fdt_protect_sec_cmd, | ||
2004 | hw->fdt_unprotect_sec_cmd, hw->fdt_wrt_disable, | ||
2005 | hw->fdt_block_size)); | ||
2006 | } | ||
2007 | |||
2008 | static void | ||
2009 | qla4_8xxx_get_idc_param(struct scsi_qla_host *ha) | ||
2010 | { | ||
2011 | #define QLA82XX_IDC_PARAM_ADDR 0x003e885c | ||
2012 | uint32_t *wptr; | ||
2013 | |||
2014 | if (!is_qla8022(ha)) | ||
2015 | return; | ||
2016 | wptr = (uint32_t *)ha->request_ring; | ||
2017 | qla4_8xxx_read_optrom_data(ha, (uint8_t *)ha->request_ring, | ||
2018 | QLA82XX_IDC_PARAM_ADDR , 8); | ||
2019 | |||
2020 | if (*wptr == __constant_cpu_to_le32(0xffffffff)) { | ||
2021 | ha->nx_dev_init_timeout = ROM_DEV_INIT_TIMEOUT; | ||
2022 | ha->nx_reset_timeout = ROM_DRV_RESET_ACK_TIMEOUT; | ||
2023 | } else { | ||
2024 | ha->nx_dev_init_timeout = le32_to_cpu(*wptr++); | ||
2025 | ha->nx_reset_timeout = le32_to_cpu(*wptr); | ||
2026 | } | ||
2027 | |||
2028 | DEBUG2(ql4_printk(KERN_DEBUG, ha, | ||
2029 | "ha->nx_dev_init_timeout = %d\n", ha->nx_dev_init_timeout)); | ||
2030 | DEBUG2(ql4_printk(KERN_DEBUG, ha, | ||
2031 | "ha->nx_reset_timeout = %d\n", ha->nx_reset_timeout)); | ||
2032 | return; | ||
2033 | } | ||
2034 | |||
2035 | int | ||
2036 | qla4_8xxx_get_flash_info(struct scsi_qla_host *ha) | ||
2037 | { | ||
2038 | int ret; | ||
2039 | uint32_t flt_addr; | ||
2040 | |||
2041 | ret = qla4_8xxx_find_flt_start(ha, &flt_addr); | ||
2042 | if (ret != QLA_SUCCESS) | ||
2043 | return ret; | ||
2044 | |||
2045 | qla4_8xxx_get_flt_info(ha, flt_addr); | ||
2046 | qla4_8xxx_get_fdt_info(ha); | ||
2047 | qla4_8xxx_get_idc_param(ha); | ||
2048 | |||
2049 | return QLA_SUCCESS; | ||
2050 | } | ||
2051 | |||
2052 | /** | ||
2053 | * qla4_8xxx_stop_firmware - stops firmware on specified adapter instance | ||
2054 | * @ha: pointer to host adapter structure. | ||
2055 | * | ||
2056 | * Remarks: | ||
2057 | * For iSCSI, throws away all I/O and AENs into bit bucket, so they will | ||
2058 | * not be available after successful return. Driver must cleanup potential | ||
2059 | * outstanding I/O's after calling this funcion. | ||
2060 | **/ | ||
2061 | int | ||
2062 | qla4_8xxx_stop_firmware(struct scsi_qla_host *ha) | ||
2063 | { | ||
2064 | int status; | ||
2065 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | ||
2066 | uint32_t mbox_sts[MBOX_REG_COUNT]; | ||
2067 | |||
2068 | memset(&mbox_cmd, 0, sizeof(mbox_cmd)); | ||
2069 | memset(&mbox_sts, 0, sizeof(mbox_sts)); | ||
2070 | |||
2071 | mbox_cmd[0] = MBOX_CMD_STOP_FW; | ||
2072 | status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, | ||
2073 | &mbox_cmd[0], &mbox_sts[0]); | ||
2074 | |||
2075 | DEBUG2(printk("scsi%ld: %s: status = %d\n", ha->host_no, | ||
2076 | __func__, status)); | ||
2077 | return status; | ||
2078 | } | ||
2079 | |||
2080 | /** | ||
2081 | * qla4_8xxx_isp_reset - Resets ISP and aborts all outstanding commands. | ||
2082 | * @ha: pointer to host adapter structure. | ||
2083 | **/ | ||
2084 | int | ||
2085 | qla4_8xxx_isp_reset(struct scsi_qla_host *ha) | ||
2086 | { | ||
2087 | int rval; | ||
2088 | uint32_t dev_state; | ||
2089 | |||
2090 | qla4_8xxx_idc_lock(ha); | ||
2091 | dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); | ||
2092 | |||
2093 | if (dev_state == QLA82XX_DEV_READY) { | ||
2094 | ql4_printk(KERN_INFO, ha, "HW State: NEED RESET\n"); | ||
2095 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, | ||
2096 | QLA82XX_DEV_NEED_RESET); | ||
2097 | } else | ||
2098 | ql4_printk(KERN_INFO, ha, "HW State: DEVICE INITIALIZING\n"); | ||
2099 | |||
2100 | qla4_8xxx_idc_unlock(ha); | ||
2101 | |||
2102 | rval = qla4_8xxx_device_state_handler(ha); | ||
2103 | |||
2104 | qla4_8xxx_idc_lock(ha); | ||
2105 | qla4_8xxx_clear_rst_ready(ha); | ||
2106 | qla4_8xxx_idc_unlock(ha); | ||
2107 | |||
2108 | return rval; | ||
2109 | } | ||
2110 | |||
2111 | /** | ||
2112 | * qla4_8xxx_get_sys_info - get adapter MAC address(es) and serial number | ||
2113 | * @ha: pointer to host adapter structure. | ||
2114 | * | ||
2115 | **/ | ||
2116 | int qla4_8xxx_get_sys_info(struct scsi_qla_host *ha) | ||
2117 | { | ||
2118 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | ||
2119 | uint32_t mbox_sts[MBOX_REG_COUNT]; | ||
2120 | struct mbx_sys_info *sys_info; | ||
2121 | dma_addr_t sys_info_dma; | ||
2122 | int status = QLA_ERROR; | ||
2123 | |||
2124 | sys_info = dma_alloc_coherent(&ha->pdev->dev, sizeof(*sys_info), | ||
2125 | &sys_info_dma, GFP_KERNEL); | ||
2126 | if (sys_info == NULL) { | ||
2127 | DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n", | ||
2128 | ha->host_no, __func__)); | ||
2129 | return status; | ||
2130 | } | ||
2131 | |||
2132 | memset(sys_info, 0, sizeof(*sys_info)); | ||
2133 | memset(&mbox_cmd, 0, sizeof(mbox_cmd)); | ||
2134 | memset(&mbox_sts, 0, sizeof(mbox_sts)); | ||
2135 | |||
2136 | mbox_cmd[0] = MBOX_CMD_GET_SYS_INFO; | ||
2137 | mbox_cmd[1] = LSDW(sys_info_dma); | ||
2138 | mbox_cmd[2] = MSDW(sys_info_dma); | ||
2139 | mbox_cmd[4] = sizeof(*sys_info); | ||
2140 | |||
2141 | if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 6, &mbox_cmd[0], | ||
2142 | &mbox_sts[0]) != QLA_SUCCESS) { | ||
2143 | DEBUG2(printk("scsi%ld: %s: GET_SYS_INFO failed\n", | ||
2144 | ha->host_no, __func__)); | ||
2145 | goto exit_validate_mac82; | ||
2146 | } | ||
2147 | |||
2148 | if (mbox_sts[4] < sizeof(*sys_info)) { | ||
2149 | DEBUG2(printk("scsi%ld: %s: GET_SYS_INFO data receive" | ||
2150 | " error (%x)\n", ha->host_no, __func__, mbox_sts[4])); | ||
2151 | goto exit_validate_mac82; | ||
2152 | |||
2153 | } | ||
2154 | |||
2155 | /* Save M.A.C. address & serial_number */ | ||
2156 | memcpy(ha->my_mac, &sys_info->mac_addr[0], | ||
2157 | min(sizeof(ha->my_mac), sizeof(sys_info->mac_addr))); | ||
2158 | memcpy(ha->serial_number, &sys_info->serial_number, | ||
2159 | min(sizeof(ha->serial_number), sizeof(sys_info->serial_number))); | ||
2160 | |||
2161 | DEBUG2(printk("scsi%ld: %s: " | ||
2162 | "mac %02x:%02x:%02x:%02x:%02x:%02x " | ||
2163 | "serial %s\n", ha->host_no, __func__, | ||
2164 | ha->my_mac[0], ha->my_mac[1], ha->my_mac[2], | ||
2165 | ha->my_mac[3], ha->my_mac[4], ha->my_mac[5], | ||
2166 | ha->serial_number)); | ||
2167 | |||
2168 | status = QLA_SUCCESS; | ||
2169 | |||
2170 | exit_validate_mac82: | ||
2171 | dma_free_coherent(&ha->pdev->dev, sizeof(*sys_info), sys_info, | ||
2172 | sys_info_dma); | ||
2173 | return status; | ||
2174 | } | ||
2175 | |||
2176 | /* Interrupt handling helpers. */ | ||
2177 | |||
2178 | static int | ||
2179 | qla4_8xxx_mbx_intr_enable(struct scsi_qla_host *ha) | ||
2180 | { | ||
2181 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | ||
2182 | uint32_t mbox_sts[MBOX_REG_COUNT]; | ||
2183 | |||
2184 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s\n", __func__)); | ||
2185 | |||
2186 | memset(&mbox_cmd, 0, sizeof(mbox_cmd)); | ||
2187 | memset(&mbox_sts, 0, sizeof(mbox_sts)); | ||
2188 | mbox_cmd[0] = MBOX_CMD_ENABLE_INTRS; | ||
2189 | mbox_cmd[1] = INTR_ENABLE; | ||
2190 | if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], | ||
2191 | &mbox_sts[0]) != QLA_SUCCESS) { | ||
2192 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
2193 | "%s: MBOX_CMD_ENABLE_INTRS failed (0x%04x)\n", | ||
2194 | __func__, mbox_sts[0])); | ||
2195 | return QLA_ERROR; | ||
2196 | } | ||
2197 | return QLA_SUCCESS; | ||
2198 | } | ||
2199 | |||
2200 | static int | ||
2201 | qla4_8xxx_mbx_intr_disable(struct scsi_qla_host *ha) | ||
2202 | { | ||
2203 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | ||
2204 | uint32_t mbox_sts[MBOX_REG_COUNT]; | ||
2205 | |||
2206 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s\n", __func__)); | ||
2207 | |||
2208 | memset(&mbox_cmd, 0, sizeof(mbox_cmd)); | ||
2209 | memset(&mbox_sts, 0, sizeof(mbox_sts)); | ||
2210 | mbox_cmd[0] = MBOX_CMD_ENABLE_INTRS; | ||
2211 | mbox_cmd[1] = INTR_DISABLE; | ||
2212 | if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], | ||
2213 | &mbox_sts[0]) != QLA_SUCCESS) { | ||
2214 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
2215 | "%s: MBOX_CMD_ENABLE_INTRS failed (0x%04x)\n", | ||
2216 | __func__, mbox_sts[0])); | ||
2217 | return QLA_ERROR; | ||
2218 | } | ||
2219 | |||
2220 | return QLA_SUCCESS; | ||
2221 | } | ||
2222 | |||
2223 | void | ||
2224 | qla4_8xxx_enable_intrs(struct scsi_qla_host *ha) | ||
2225 | { | ||
2226 | qla4_8xxx_mbx_intr_enable(ha); | ||
2227 | |||
2228 | spin_lock_irq(&ha->hardware_lock); | ||
2229 | /* BIT 10 - reset */ | ||
2230 | qla4_8xxx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0xfbff); | ||
2231 | spin_unlock_irq(&ha->hardware_lock); | ||
2232 | set_bit(AF_INTERRUPTS_ON, &ha->flags); | ||
2233 | } | ||
2234 | |||
2235 | void | ||
2236 | qla4_8xxx_disable_intrs(struct scsi_qla_host *ha) | ||
2237 | { | ||
2238 | if (test_bit(AF_INTERRUPTS_ON, &ha->flags)) | ||
2239 | qla4_8xxx_mbx_intr_disable(ha); | ||
2240 | |||
2241 | spin_lock_irq(&ha->hardware_lock); | ||
2242 | /* BIT 10 - set */ | ||
2243 | qla4_8xxx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0x0400); | ||
2244 | spin_unlock_irq(&ha->hardware_lock); | ||
2245 | clear_bit(AF_INTERRUPTS_ON, &ha->flags); | ||
2246 | } | ||
2247 | |||
2248 | struct ql4_init_msix_entry { | ||
2249 | uint16_t entry; | ||
2250 | uint16_t index; | ||
2251 | const char *name; | ||
2252 | irq_handler_t handler; | ||
2253 | }; | ||
2254 | |||
2255 | static struct ql4_init_msix_entry qla4_8xxx_msix_entries[QLA_MSIX_ENTRIES] = { | ||
2256 | { QLA_MSIX_DEFAULT, QLA_MIDX_DEFAULT, | ||
2257 | "qla4xxx (default)", | ||
2258 | (irq_handler_t)qla4_8xxx_default_intr_handler }, | ||
2259 | { QLA_MSIX_RSP_Q, QLA_MIDX_RSP_Q, | ||
2260 | "qla4xxx (rsp_q)", (irq_handler_t)qla4_8xxx_msix_rsp_q }, | ||
2261 | }; | ||
2262 | |||
2263 | void | ||
2264 | qla4_8xxx_disable_msix(struct scsi_qla_host *ha) | ||
2265 | { | ||
2266 | int i; | ||
2267 | struct ql4_msix_entry *qentry; | ||
2268 | |||
2269 | for (i = 0; i < QLA_MSIX_ENTRIES; i++) { | ||
2270 | qentry = &ha->msix_entries[qla4_8xxx_msix_entries[i].index]; | ||
2271 | if (qentry->have_irq) { | ||
2272 | free_irq(qentry->msix_vector, ha); | ||
2273 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s: %s\n", | ||
2274 | __func__, qla4_8xxx_msix_entries[i].name)); | ||
2275 | } | ||
2276 | } | ||
2277 | pci_disable_msix(ha->pdev); | ||
2278 | clear_bit(AF_MSIX_ENABLED, &ha->flags); | ||
2279 | } | ||
2280 | |||
2281 | int | ||
2282 | qla4_8xxx_enable_msix(struct scsi_qla_host *ha) | ||
2283 | { | ||
2284 | int i, ret; | ||
2285 | struct msix_entry entries[QLA_MSIX_ENTRIES]; | ||
2286 | struct ql4_msix_entry *qentry; | ||
2287 | |||
2288 | for (i = 0; i < QLA_MSIX_ENTRIES; i++) | ||
2289 | entries[i].entry = qla4_8xxx_msix_entries[i].entry; | ||
2290 | |||
2291 | ret = pci_enable_msix(ha->pdev, entries, ARRAY_SIZE(entries)); | ||
2292 | if (ret) { | ||
2293 | ql4_printk(KERN_WARNING, ha, | ||
2294 | "MSI-X: Failed to enable support -- %d/%d\n", | ||
2295 | QLA_MSIX_ENTRIES, ret); | ||
2296 | goto msix_out; | ||
2297 | } | ||
2298 | set_bit(AF_MSIX_ENABLED, &ha->flags); | ||
2299 | |||
2300 | for (i = 0; i < QLA_MSIX_ENTRIES; i++) { | ||
2301 | qentry = &ha->msix_entries[qla4_8xxx_msix_entries[i].index]; | ||
2302 | qentry->msix_vector = entries[i].vector; | ||
2303 | qentry->msix_entry = entries[i].entry; | ||
2304 | qentry->have_irq = 0; | ||
2305 | ret = request_irq(qentry->msix_vector, | ||
2306 | qla4_8xxx_msix_entries[i].handler, 0, | ||
2307 | qla4_8xxx_msix_entries[i].name, ha); | ||
2308 | if (ret) { | ||
2309 | ql4_printk(KERN_WARNING, ha, | ||
2310 | "MSI-X: Unable to register handler -- %x/%d.\n", | ||
2311 | qla4_8xxx_msix_entries[i].index, ret); | ||
2312 | qla4_8xxx_disable_msix(ha); | ||
2313 | goto msix_out; | ||
2314 | } | ||
2315 | qentry->have_irq = 1; | ||
2316 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s: %s\n", | ||
2317 | __func__, qla4_8xxx_msix_entries[i].name)); | ||
2318 | } | ||
2319 | msix_out: | ||
2320 | return ret; | ||
2321 | } | ||
diff --git a/drivers/scsi/qla4xxx/ql4_nx.h b/drivers/scsi/qla4xxx/ql4_nx.h new file mode 100644 index 000000000000..931ad3f1e918 --- /dev/null +++ b/drivers/scsi/qla4xxx/ql4_nx.h | |||
@@ -0,0 +1,779 @@ | |||
1 | /* | ||
2 | * QLogic Fibre Channel HBA Driver | ||
3 | * Copyright (c) 2003-2008 QLogic Corporation | ||
4 | * | ||
5 | * See LICENSE.qla2xxx for copyright and licensing details. | ||
6 | */ | ||
7 | #ifndef __QLA_NX_H | ||
8 | #define __QLA_NX_H | ||
9 | |||
10 | /* | ||
11 | * Following are the states of the Phantom. Phantom will set them and | ||
12 | * Host will read to check if the fields are correct. | ||
13 | */ | ||
14 | #define PHAN_INITIALIZE_FAILED 0xffff | ||
15 | #define PHAN_INITIALIZE_COMPLETE 0xff01 | ||
16 | |||
17 | /* Host writes the following to notify that it has done the init-handshake */ | ||
18 | #define PHAN_INITIALIZE_ACK 0xf00f | ||
19 | #define PHAN_PEG_RCV_INITIALIZED 0xff01 | ||
20 | |||
21 | /*CRB_RELATED*/ | ||
22 | #define QLA82XX_CRB_BASE QLA82XX_CAM_RAM(0x200) | ||
23 | #define QLA82XX_REG(X) (QLA82XX_CRB_BASE+(X)) | ||
24 | |||
25 | #define CRB_CMDPEG_STATE QLA82XX_REG(0x50) | ||
26 | #define CRB_RCVPEG_STATE QLA82XX_REG(0x13c) | ||
27 | #define BOOT_LOADER_DIMM_STATUS QLA82XX_REG(0x54) | ||
28 | #define CRB_DMA_SHIFT QLA82XX_REG(0xcc) | ||
29 | |||
30 | #define QLA82XX_HW_H0_CH_HUB_ADR 0x05 | ||
31 | #define QLA82XX_HW_H1_CH_HUB_ADR 0x0E | ||
32 | #define QLA82XX_HW_H2_CH_HUB_ADR 0x03 | ||
33 | #define QLA82XX_HW_H3_CH_HUB_ADR 0x01 | ||
34 | #define QLA82XX_HW_H4_CH_HUB_ADR 0x06 | ||
35 | #define QLA82XX_HW_H5_CH_HUB_ADR 0x07 | ||
36 | #define QLA82XX_HW_H6_CH_HUB_ADR 0x08 | ||
37 | |||
38 | /* Hub 0 */ | ||
39 | #define QLA82XX_HW_MN_CRB_AGT_ADR 0x15 | ||
40 | #define QLA82XX_HW_MS_CRB_AGT_ADR 0x25 | ||
41 | |||
42 | /* Hub 1 */ | ||
43 | #define QLA82XX_HW_PS_CRB_AGT_ADR 0x73 | ||
44 | #define QLA82XX_HW_QMS_CRB_AGT_ADR 0x00 | ||
45 | #define QLA82XX_HW_RPMX3_CRB_AGT_ADR 0x0b | ||
46 | #define QLA82XX_HW_SQGS0_CRB_AGT_ADR 0x01 | ||
47 | #define QLA82XX_HW_SQGS1_CRB_AGT_ADR 0x02 | ||
48 | #define QLA82XX_HW_SQGS2_CRB_AGT_ADR 0x03 | ||
49 | #define QLA82XX_HW_SQGS3_CRB_AGT_ADR 0x04 | ||
50 | #define QLA82XX_HW_C2C0_CRB_AGT_ADR 0x58 | ||
51 | #define QLA82XX_HW_C2C1_CRB_AGT_ADR 0x59 | ||
52 | #define QLA82XX_HW_C2C2_CRB_AGT_ADR 0x5a | ||
53 | #define QLA82XX_HW_RPMX2_CRB_AGT_ADR 0x0a | ||
54 | #define QLA82XX_HW_RPMX4_CRB_AGT_ADR 0x0c | ||
55 | #define QLA82XX_HW_RPMX7_CRB_AGT_ADR 0x0f | ||
56 | #define QLA82XX_HW_RPMX9_CRB_AGT_ADR 0x12 | ||
57 | #define QLA82XX_HW_SMB_CRB_AGT_ADR 0x18 | ||
58 | |||
59 | /* Hub 2 */ | ||
60 | #define QLA82XX_HW_NIU_CRB_AGT_ADR 0x31 | ||
61 | #define QLA82XX_HW_I2C0_CRB_AGT_ADR 0x19 | ||
62 | #define QLA82XX_HW_I2C1_CRB_AGT_ADR 0x29 | ||
63 | |||
64 | #define QLA82XX_HW_SN_CRB_AGT_ADR 0x10 | ||
65 | #define QLA82XX_HW_I2Q_CRB_AGT_ADR 0x20 | ||
66 | #define QLA82XX_HW_LPC_CRB_AGT_ADR 0x22 | ||
67 | #define QLA82XX_HW_ROMUSB_CRB_AGT_ADR 0x21 | ||
68 | #define QLA82XX_HW_QM_CRB_AGT_ADR 0x66 | ||
69 | #define QLA82XX_HW_SQG0_CRB_AGT_ADR 0x60 | ||
70 | #define QLA82XX_HW_SQG1_CRB_AGT_ADR 0x61 | ||
71 | #define QLA82XX_HW_SQG2_CRB_AGT_ADR 0x62 | ||
72 | #define QLA82XX_HW_SQG3_CRB_AGT_ADR 0x63 | ||
73 | #define QLA82XX_HW_RPMX1_CRB_AGT_ADR 0x09 | ||
74 | #define QLA82XX_HW_RPMX5_CRB_AGT_ADR 0x0d | ||
75 | #define QLA82XX_HW_RPMX6_CRB_AGT_ADR 0x0e | ||
76 | #define QLA82XX_HW_RPMX8_CRB_AGT_ADR 0x11 | ||
77 | |||
78 | /* Hub 3 */ | ||
79 | #define QLA82XX_HW_PH_CRB_AGT_ADR 0x1A | ||
80 | #define QLA82XX_HW_SRE_CRB_AGT_ADR 0x50 | ||
81 | #define QLA82XX_HW_EG_CRB_AGT_ADR 0x51 | ||
82 | #define QLA82XX_HW_RPMX0_CRB_AGT_ADR 0x08 | ||
83 | |||
84 | /* Hub 4 */ | ||
85 | #define QLA82XX_HW_PEGN0_CRB_AGT_ADR 0x40 | ||
86 | #define QLA82XX_HW_PEGN1_CRB_AGT_ADR 0x41 | ||
87 | #define QLA82XX_HW_PEGN2_CRB_AGT_ADR 0x42 | ||
88 | #define QLA82XX_HW_PEGN3_CRB_AGT_ADR 0x43 | ||
89 | #define QLA82XX_HW_PEGNI_CRB_AGT_ADR 0x44 | ||
90 | #define QLA82XX_HW_PEGND_CRB_AGT_ADR 0x45 | ||
91 | #define QLA82XX_HW_PEGNC_CRB_AGT_ADR 0x46 | ||
92 | #define QLA82XX_HW_PEGR0_CRB_AGT_ADR 0x47 | ||
93 | #define QLA82XX_HW_PEGR1_CRB_AGT_ADR 0x48 | ||
94 | #define QLA82XX_HW_PEGR2_CRB_AGT_ADR 0x49 | ||
95 | #define QLA82XX_HW_PEGR3_CRB_AGT_ADR 0x4a | ||
96 | #define QLA82XX_HW_PEGN4_CRB_AGT_ADR 0x4b | ||
97 | |||
98 | /* Hub 5 */ | ||
99 | #define QLA82XX_HW_PEGS0_CRB_AGT_ADR 0x40 | ||
100 | #define QLA82XX_HW_PEGS1_CRB_AGT_ADR 0x41 | ||
101 | #define QLA82XX_HW_PEGS2_CRB_AGT_ADR 0x42 | ||
102 | #define QLA82XX_HW_PEGS3_CRB_AGT_ADR 0x43 | ||
103 | |||
104 | #define QLA82XX_HW_PEGSI_CRB_AGT_ADR 0x44 | ||
105 | #define QLA82XX_HW_PEGSD_CRB_AGT_ADR 0x45 | ||
106 | #define QLA82XX_HW_PEGSC_CRB_AGT_ADR 0x46 | ||
107 | |||
108 | /* Hub 6 */ | ||
109 | #define QLA82XX_HW_CAS0_CRB_AGT_ADR 0x46 | ||
110 | #define QLA82XX_HW_CAS1_CRB_AGT_ADR 0x47 | ||
111 | #define QLA82XX_HW_CAS2_CRB_AGT_ADR 0x48 | ||
112 | #define QLA82XX_HW_CAS3_CRB_AGT_ADR 0x49 | ||
113 | #define QLA82XX_HW_NCM_CRB_AGT_ADR 0x16 | ||
114 | #define QLA82XX_HW_TMR_CRB_AGT_ADR 0x17 | ||
115 | #define QLA82XX_HW_XDMA_CRB_AGT_ADR 0x05 | ||
116 | #define QLA82XX_HW_OCM0_CRB_AGT_ADR 0x06 | ||
117 | #define QLA82XX_HW_OCM1_CRB_AGT_ADR 0x07 | ||
118 | |||
119 | /* This field defines PCI/X adr [25:20] of agents on the CRB */ | ||
120 | /* */ | ||
121 | #define QLA82XX_HW_PX_MAP_CRB_PH 0 | ||
122 | #define QLA82XX_HW_PX_MAP_CRB_PS 1 | ||
123 | #define QLA82XX_HW_PX_MAP_CRB_MN 2 | ||
124 | #define QLA82XX_HW_PX_MAP_CRB_MS 3 | ||
125 | #define QLA82XX_HW_PX_MAP_CRB_SRE 5 | ||
126 | #define QLA82XX_HW_PX_MAP_CRB_NIU 6 | ||
127 | #define QLA82XX_HW_PX_MAP_CRB_QMN 7 | ||
128 | #define QLA82XX_HW_PX_MAP_CRB_SQN0 8 | ||
129 | #define QLA82XX_HW_PX_MAP_CRB_SQN1 9 | ||
130 | #define QLA82XX_HW_PX_MAP_CRB_SQN2 10 | ||
131 | #define QLA82XX_HW_PX_MAP_CRB_SQN3 11 | ||
132 | #define QLA82XX_HW_PX_MAP_CRB_QMS 12 | ||
133 | #define QLA82XX_HW_PX_MAP_CRB_SQS0 13 | ||
134 | #define QLA82XX_HW_PX_MAP_CRB_SQS1 14 | ||
135 | #define QLA82XX_HW_PX_MAP_CRB_SQS2 15 | ||
136 | #define QLA82XX_HW_PX_MAP_CRB_SQS3 16 | ||
137 | #define QLA82XX_HW_PX_MAP_CRB_PGN0 17 | ||
138 | #define QLA82XX_HW_PX_MAP_CRB_PGN1 18 | ||
139 | #define QLA82XX_HW_PX_MAP_CRB_PGN2 19 | ||
140 | #define QLA82XX_HW_PX_MAP_CRB_PGN3 20 | ||
141 | #define QLA82XX_HW_PX_MAP_CRB_PGN4 QLA82XX_HW_PX_MAP_CRB_SQS2 | ||
142 | #define QLA82XX_HW_PX_MAP_CRB_PGND 21 | ||
143 | #define QLA82XX_HW_PX_MAP_CRB_PGNI 22 | ||
144 | #define QLA82XX_HW_PX_MAP_CRB_PGS0 23 | ||
145 | #define QLA82XX_HW_PX_MAP_CRB_PGS1 24 | ||
146 | #define QLA82XX_HW_PX_MAP_CRB_PGS2 25 | ||
147 | #define QLA82XX_HW_PX_MAP_CRB_PGS3 26 | ||
148 | #define QLA82XX_HW_PX_MAP_CRB_PGSD 27 | ||
149 | #define QLA82XX_HW_PX_MAP_CRB_PGSI 28 | ||
150 | #define QLA82XX_HW_PX_MAP_CRB_SN 29 | ||
151 | #define QLA82XX_HW_PX_MAP_CRB_EG 31 | ||
152 | #define QLA82XX_HW_PX_MAP_CRB_PH2 32 | ||
153 | #define QLA82XX_HW_PX_MAP_CRB_PS2 33 | ||
154 | #define QLA82XX_HW_PX_MAP_CRB_CAM 34 | ||
155 | #define QLA82XX_HW_PX_MAP_CRB_CAS0 35 | ||
156 | #define QLA82XX_HW_PX_MAP_CRB_CAS1 36 | ||
157 | #define QLA82XX_HW_PX_MAP_CRB_CAS2 37 | ||
158 | #define QLA82XX_HW_PX_MAP_CRB_C2C0 38 | ||
159 | #define QLA82XX_HW_PX_MAP_CRB_C2C1 39 | ||
160 | #define QLA82XX_HW_PX_MAP_CRB_TIMR 40 | ||
161 | #define QLA82XX_HW_PX_MAP_CRB_RPMX1 42 | ||
162 | #define QLA82XX_HW_PX_MAP_CRB_RPMX2 43 | ||
163 | #define QLA82XX_HW_PX_MAP_CRB_RPMX3 44 | ||
164 | #define QLA82XX_HW_PX_MAP_CRB_RPMX4 45 | ||
165 | #define QLA82XX_HW_PX_MAP_CRB_RPMX5 46 | ||
166 | #define QLA82XX_HW_PX_MAP_CRB_RPMX6 47 | ||
167 | #define QLA82XX_HW_PX_MAP_CRB_RPMX7 48 | ||
168 | #define QLA82XX_HW_PX_MAP_CRB_XDMA 49 | ||
169 | #define QLA82XX_HW_PX_MAP_CRB_I2Q 50 | ||
170 | #define QLA82XX_HW_PX_MAP_CRB_ROMUSB 51 | ||
171 | #define QLA82XX_HW_PX_MAP_CRB_CAS3 52 | ||
172 | #define QLA82XX_HW_PX_MAP_CRB_RPMX0 53 | ||
173 | #define QLA82XX_HW_PX_MAP_CRB_RPMX8 54 | ||
174 | #define QLA82XX_HW_PX_MAP_CRB_RPMX9 55 | ||
175 | #define QLA82XX_HW_PX_MAP_CRB_OCM0 56 | ||
176 | #define QLA82XX_HW_PX_MAP_CRB_OCM1 57 | ||
177 | #define QLA82XX_HW_PX_MAP_CRB_SMB 58 | ||
178 | #define QLA82XX_HW_PX_MAP_CRB_I2C0 59 | ||
179 | #define QLA82XX_HW_PX_MAP_CRB_I2C1 60 | ||
180 | #define QLA82XX_HW_PX_MAP_CRB_LPC 61 | ||
181 | #define QLA82XX_HW_PX_MAP_CRB_PGNC 62 | ||
182 | #define QLA82XX_HW_PX_MAP_CRB_PGR0 63 | ||
183 | #define QLA82XX_HW_PX_MAP_CRB_PGR1 4 | ||
184 | #define QLA82XX_HW_PX_MAP_CRB_PGR2 30 | ||
185 | #define QLA82XX_HW_PX_MAP_CRB_PGR3 41 | ||
186 | |||
187 | /* This field defines CRB adr [31:20] of the agents */ | ||
188 | /* */ | ||
189 | |||
190 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_MN ((QLA82XX_HW_H0_CH_HUB_ADR << 7) | \ | ||
191 | QLA82XX_HW_MN_CRB_AGT_ADR) | ||
192 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PH ((QLA82XX_HW_H0_CH_HUB_ADR << 7) | \ | ||
193 | QLA82XX_HW_PH_CRB_AGT_ADR) | ||
194 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_MS ((QLA82XX_HW_H0_CH_HUB_ADR << 7) | \ | ||
195 | QLA82XX_HW_MS_CRB_AGT_ADR) | ||
196 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PS ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ | ||
197 | QLA82XX_HW_PS_CRB_AGT_ADR) | ||
198 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_SS ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ | ||
199 | QLA82XX_HW_SS_CRB_AGT_ADR) | ||
200 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX3 ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ | ||
201 | QLA82XX_HW_RPMX3_CRB_AGT_ADR) | ||
202 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_QMS ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ | ||
203 | QLA82XX_HW_QMS_CRB_AGT_ADR) | ||
204 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_SQS0 ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ | ||
205 | QLA82XX_HW_SQGS0_CRB_AGT_ADR) | ||
206 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_SQS1 ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ | ||
207 | QLA82XX_HW_SQGS1_CRB_AGT_ADR) | ||
208 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_SQS2 ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ | ||
209 | QLA82XX_HW_SQGS2_CRB_AGT_ADR) | ||
210 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_SQS3 ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ | ||
211 | QLA82XX_HW_SQGS3_CRB_AGT_ADR) | ||
212 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_C2C0 ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ | ||
213 | QLA82XX_HW_C2C0_CRB_AGT_ADR) | ||
214 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_C2C1 ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ | ||
215 | QLA82XX_HW_C2C1_CRB_AGT_ADR) | ||
216 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX2 ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ | ||
217 | QLA82XX_HW_RPMX2_CRB_AGT_ADR) | ||
218 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX4 ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ | ||
219 | QLA82XX_HW_RPMX4_CRB_AGT_ADR) | ||
220 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX7 ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ | ||
221 | QLA82XX_HW_RPMX7_CRB_AGT_ADR) | ||
222 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX9 ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ | ||
223 | QLA82XX_HW_RPMX9_CRB_AGT_ADR) | ||
224 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_SMB ((QLA82XX_HW_H1_CH_HUB_ADR << 7) | \ | ||
225 | QLA82XX_HW_SMB_CRB_AGT_ADR) | ||
226 | |||
227 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_NIU ((QLA82XX_HW_H2_CH_HUB_ADR << 7) | \ | ||
228 | QLA82XX_HW_NIU_CRB_AGT_ADR) | ||
229 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_I2C0 ((QLA82XX_HW_H2_CH_HUB_ADR << 7) | \ | ||
230 | QLA82XX_HW_I2C0_CRB_AGT_ADR) | ||
231 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_I2C1 ((QLA82XX_HW_H2_CH_HUB_ADR << 7) | \ | ||
232 | QLA82XX_HW_I2C1_CRB_AGT_ADR) | ||
233 | |||
234 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_SRE ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ | ||
235 | QLA82XX_HW_SRE_CRB_AGT_ADR) | ||
236 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_EG ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ | ||
237 | QLA82XX_HW_EG_CRB_AGT_ADR) | ||
238 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX0 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ | ||
239 | QLA82XX_HW_RPMX0_CRB_AGT_ADR) | ||
240 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_QMN ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ | ||
241 | QLA82XX_HW_QM_CRB_AGT_ADR) | ||
242 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_SQN0 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ | ||
243 | QLA82XX_HW_SQG0_CRB_AGT_ADR) | ||
244 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_SQN1 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ | ||
245 | QLA82XX_HW_SQG1_CRB_AGT_ADR) | ||
246 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_SQN2 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ | ||
247 | QLA82XX_HW_SQG2_CRB_AGT_ADR) | ||
248 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_SQN3 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ | ||
249 | QLA82XX_HW_SQG3_CRB_AGT_ADR) | ||
250 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX1 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ | ||
251 | QLA82XX_HW_RPMX1_CRB_AGT_ADR) | ||
252 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX5 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ | ||
253 | QLA82XX_HW_RPMX5_CRB_AGT_ADR) | ||
254 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX6 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ | ||
255 | QLA82XX_HW_RPMX6_CRB_AGT_ADR) | ||
256 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_RPMX8 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ | ||
257 | QLA82XX_HW_RPMX8_CRB_AGT_ADR) | ||
258 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_CAS0 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ | ||
259 | QLA82XX_HW_CAS0_CRB_AGT_ADR) | ||
260 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_CAS1 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ | ||
261 | QLA82XX_HW_CAS1_CRB_AGT_ADR) | ||
262 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_CAS2 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ | ||
263 | QLA82XX_HW_CAS2_CRB_AGT_ADR) | ||
264 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_CAS3 ((QLA82XX_HW_H3_CH_HUB_ADR << 7) | \ | ||
265 | QLA82XX_HW_CAS3_CRB_AGT_ADR) | ||
266 | |||
267 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGNI ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ | ||
268 | QLA82XX_HW_PEGNI_CRB_AGT_ADR) | ||
269 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGND ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ | ||
270 | QLA82XX_HW_PEGND_CRB_AGT_ADR) | ||
271 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGN0 ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ | ||
272 | QLA82XX_HW_PEGN0_CRB_AGT_ADR) | ||
273 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGN1 ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ | ||
274 | QLA82XX_HW_PEGN1_CRB_AGT_ADR) | ||
275 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGN2 ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ | ||
276 | QLA82XX_HW_PEGN2_CRB_AGT_ADR) | ||
277 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGN3 ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ | ||
278 | QLA82XX_HW_PEGN3_CRB_AGT_ADR) | ||
279 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGN4 ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ | ||
280 | QLA82XX_HW_PEGN4_CRB_AGT_ADR) | ||
281 | |||
282 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGNC ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ | ||
283 | QLA82XX_HW_PEGNC_CRB_AGT_ADR) | ||
284 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGR0 ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ | ||
285 | QLA82XX_HW_PEGR0_CRB_AGT_ADR) | ||
286 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGR1 ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ | ||
287 | QLA82XX_HW_PEGR1_CRB_AGT_ADR) | ||
288 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGR2 ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ | ||
289 | QLA82XX_HW_PEGR2_CRB_AGT_ADR) | ||
290 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGR3 ((QLA82XX_HW_H4_CH_HUB_ADR << 7) | \ | ||
291 | QLA82XX_HW_PEGR3_CRB_AGT_ADR) | ||
292 | |||
293 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGSI ((QLA82XX_HW_H5_CH_HUB_ADR << 7) | \ | ||
294 | QLA82XX_HW_PEGSI_CRB_AGT_ADR) | ||
295 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGSD ((QLA82XX_HW_H5_CH_HUB_ADR << 7) | \ | ||
296 | QLA82XX_HW_PEGSD_CRB_AGT_ADR) | ||
297 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGS0 ((QLA82XX_HW_H5_CH_HUB_ADR << 7) | \ | ||
298 | QLA82XX_HW_PEGS0_CRB_AGT_ADR) | ||
299 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGS1 ((QLA82XX_HW_H5_CH_HUB_ADR << 7) | \ | ||
300 | QLA82XX_HW_PEGS1_CRB_AGT_ADR) | ||
301 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGS2 ((QLA82XX_HW_H5_CH_HUB_ADR << 7) | \ | ||
302 | QLA82XX_HW_PEGS2_CRB_AGT_ADR) | ||
303 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGS3 ((QLA82XX_HW_H5_CH_HUB_ADR << 7) | \ | ||
304 | QLA82XX_HW_PEGS3_CRB_AGT_ADR) | ||
305 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_PGSC ((QLA82XX_HW_H5_CH_HUB_ADR << 7) | \ | ||
306 | QLA82XX_HW_PEGSC_CRB_AGT_ADR) | ||
307 | |||
308 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_CAM ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \ | ||
309 | QLA82XX_HW_NCM_CRB_AGT_ADR) | ||
310 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_TIMR ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \ | ||
311 | QLA82XX_HW_TMR_CRB_AGT_ADR) | ||
312 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_XDMA ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \ | ||
313 | QLA82XX_HW_XDMA_CRB_AGT_ADR) | ||
314 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_SN ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \ | ||
315 | QLA82XX_HW_SN_CRB_AGT_ADR) | ||
316 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_I2Q ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \ | ||
317 | QLA82XX_HW_I2Q_CRB_AGT_ADR) | ||
318 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_ROMUSB ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \ | ||
319 | QLA82XX_HW_ROMUSB_CRB_AGT_ADR) | ||
320 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_OCM0 ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \ | ||
321 | QLA82XX_HW_OCM0_CRB_AGT_ADR) | ||
322 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_OCM1 ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \ | ||
323 | QLA82XX_HW_OCM1_CRB_AGT_ADR) | ||
324 | #define QLA82XX_HW_CRB_HUB_AGT_ADR_LPC ((QLA82XX_HW_H6_CH_HUB_ADR << 7) | \ | ||
325 | QLA82XX_HW_LPC_CRB_AGT_ADR) | ||
326 | |||
327 | #define ROMUSB_GLB (QLA82XX_CRB_ROMUSB + 0x00000) | ||
328 | #define QLA82XX_ROMUSB_GLB_PEGTUNE_DONE (ROMUSB_GLB + 0x005c) | ||
329 | #define QLA82XX_ROMUSB_GLB_STATUS (ROMUSB_GLB + 0x0004) | ||
330 | #define QLA82XX_ROMUSB_GLB_SW_RESET (ROMUSB_GLB + 0x0008) | ||
331 | #define QLA82XX_ROMUSB_ROM_ADDRESS (ROMUSB_ROM + 0x0008) | ||
332 | #define QLA82XX_ROMUSB_ROM_WDATA (ROMUSB_ROM + 0x000c) | ||
333 | #define QLA82XX_ROMUSB_ROM_ABYTE_CNT (ROMUSB_ROM + 0x0010) | ||
334 | #define QLA82XX_ROMUSB_ROM_DUMMY_BYTE_CNT (ROMUSB_ROM + 0x0014) | ||
335 | #define QLA82XX_ROMUSB_ROM_RDATA (ROMUSB_ROM + 0x0018) | ||
336 | |||
337 | #define ROMUSB_ROM (QLA82XX_CRB_ROMUSB + 0x10000) | ||
338 | #define QLA82XX_ROMUSB_ROM_INSTR_OPCODE (ROMUSB_ROM + 0x0004) | ||
339 | #define QLA82XX_ROMUSB_GLB_CAS_RST (ROMUSB_GLB + 0x0038) | ||
340 | |||
341 | /* Lock IDs for ROM lock */ | ||
342 | #define ROM_LOCK_DRIVER 0x0d417340 | ||
343 | |||
344 | #define QLA82XX_PCI_CRB_WINDOWSIZE 0x00100000 /* all are 1MB windows */ | ||
345 | #define QLA82XX_PCI_CRB_WINDOW(A) (QLA82XX_PCI_CRBSPACE + \ | ||
346 | (A)*QLA82XX_PCI_CRB_WINDOWSIZE) | ||
347 | |||
348 | #define QLA82XX_CRB_C2C_0 \ | ||
349 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_C2C0) | ||
350 | #define QLA82XX_CRB_C2C_1 \ | ||
351 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_C2C1) | ||
352 | #define QLA82XX_CRB_C2C_2 \ | ||
353 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_C2C2) | ||
354 | #define QLA82XX_CRB_CAM \ | ||
355 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_CAM) | ||
356 | #define QLA82XX_CRB_CASPER \ | ||
357 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_CAS) | ||
358 | #define QLA82XX_CRB_CASPER_0 \ | ||
359 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_CAS0) | ||
360 | #define QLA82XX_CRB_CASPER_1 \ | ||
361 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_CAS1) | ||
362 | #define QLA82XX_CRB_CASPER_2 \ | ||
363 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_CAS2) | ||
364 | #define QLA82XX_CRB_DDR_MD \ | ||
365 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_MS) | ||
366 | #define QLA82XX_CRB_DDR_NET \ | ||
367 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_MN) | ||
368 | #define QLA82XX_CRB_EPG \ | ||
369 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_EG) | ||
370 | #define QLA82XX_CRB_I2Q \ | ||
371 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_I2Q) | ||
372 | #define QLA82XX_CRB_NIU \ | ||
373 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_NIU) | ||
374 | /* HACK upon HACK upon HACK (for PCIE builds) */ | ||
375 | #define QLA82XX_CRB_PCIX_HOST \ | ||
376 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PH) | ||
377 | #define QLA82XX_CRB_PCIX_HOST2 \ | ||
378 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PH2) | ||
379 | #define QLA82XX_CRB_PCIX_MD \ | ||
380 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PS) | ||
381 | #define QLA82XX_CRB_PCIE QLA82XX_CRB_PCIX_MD | ||
382 | /* window 1 pcie slot */ | ||
383 | #define QLA82XX_CRB_PCIE2 \ | ||
384 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PS2) | ||
385 | |||
386 | #define QLA82XX_CRB_PEG_MD_0 \ | ||
387 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGS0) | ||
388 | #define QLA82XX_CRB_PEG_MD_1 \ | ||
389 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGS1) | ||
390 | #define QLA82XX_CRB_PEG_MD_2 \ | ||
391 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGS2) | ||
392 | #define QLA82XX_CRB_PEG_MD_3 \ | ||
393 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGS3) | ||
394 | #define QLA82XX_CRB_PEG_MD_3 \ | ||
395 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGS3) | ||
396 | #define QLA82XX_CRB_PEG_MD_D \ | ||
397 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGSD) | ||
398 | #define QLA82XX_CRB_PEG_MD_I \ | ||
399 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGSI) | ||
400 | #define QLA82XX_CRB_PEG_NET_0 \ | ||
401 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGN0) | ||
402 | #define QLA82XX_CRB_PEG_NET_1 \ | ||
403 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGN1) | ||
404 | #define QLA82XX_CRB_PEG_NET_2 \ | ||
405 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGN2) | ||
406 | #define QLA82XX_CRB_PEG_NET_3 \ | ||
407 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGN3) | ||
408 | #define QLA82XX_CRB_PEG_NET_4 \ | ||
409 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGN4) | ||
410 | #define QLA82XX_CRB_PEG_NET_D \ | ||
411 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGND) | ||
412 | #define QLA82XX_CRB_PEG_NET_I \ | ||
413 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_PGNI) | ||
414 | #define QLA82XX_CRB_PQM_MD \ | ||
415 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_QMS) | ||
416 | #define QLA82XX_CRB_PQM_NET \ | ||
417 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_QMN) | ||
418 | #define QLA82XX_CRB_QDR_MD \ | ||
419 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SS) | ||
420 | #define QLA82XX_CRB_QDR_NET \ | ||
421 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SN) | ||
422 | #define QLA82XX_CRB_ROMUSB \ | ||
423 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_ROMUSB) | ||
424 | #define QLA82XX_CRB_RPMX_0 \ | ||
425 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_RPMX0) | ||
426 | #define QLA82XX_CRB_RPMX_1 \ | ||
427 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_RPMX1) | ||
428 | #define QLA82XX_CRB_RPMX_2 \ | ||
429 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_RPMX2) | ||
430 | #define QLA82XX_CRB_RPMX_3 \ | ||
431 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_RPMX3) | ||
432 | #define QLA82XX_CRB_RPMX_4 \ | ||
433 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_RPMX4) | ||
434 | #define QLA82XX_CRB_RPMX_5 \ | ||
435 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_RPMX5) | ||
436 | #define QLA82XX_CRB_RPMX_6 \ | ||
437 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_RPMX6) | ||
438 | #define QLA82XX_CRB_RPMX_7 \ | ||
439 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_RPMX7) | ||
440 | #define QLA82XX_CRB_SQM_MD_0 \ | ||
441 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SQS0) | ||
442 | #define QLA82XX_CRB_SQM_MD_1 \ | ||
443 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SQS1) | ||
444 | #define QLA82XX_CRB_SQM_MD_2 \ | ||
445 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SQS2) | ||
446 | #define QLA82XX_CRB_SQM_MD_3 \ | ||
447 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SQS3) | ||
448 | #define QLA82XX_CRB_SQM_NET_0 \ | ||
449 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SQN0) | ||
450 | #define QLA82XX_CRB_SQM_NET_1 \ | ||
451 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SQN1) | ||
452 | #define QLA82XX_CRB_SQM_NET_2 \ | ||
453 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SQN2) | ||
454 | #define QLA82XX_CRB_SQM_NET_3 \ | ||
455 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SQN3) | ||
456 | #define QLA82XX_CRB_SRE \ | ||
457 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SRE) | ||
458 | #define QLA82XX_CRB_TIMER \ | ||
459 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_TIMR) | ||
460 | #define QLA82XX_CRB_XDMA \ | ||
461 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_XDMA) | ||
462 | #define QLA82XX_CRB_I2C0 \ | ||
463 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_I2C0) | ||
464 | #define QLA82XX_CRB_I2C1 \ | ||
465 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_I2C1) | ||
466 | #define QLA82XX_CRB_OCM0 \ | ||
467 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_OCM0) | ||
468 | #define QLA82XX_CRB_SMB \ | ||
469 | QLA82XX_PCI_CRB_WINDOW(QLA82XX_HW_PX_MAP_CRB_SMB) | ||
470 | |||
471 | #define QLA82XX_CRB_MAX QLA82XX_PCI_CRB_WINDOW(64) | ||
472 | |||
473 | /* | ||
474 | * ====================== BASE ADDRESSES ON-CHIP ====================== | ||
475 | * Base addresses of major components on-chip. | ||
476 | * ====================== BASE ADDRESSES ON-CHIP ====================== | ||
477 | */ | ||
478 | #define QLA82XX_ADDR_DDR_NET (0x0000000000000000ULL) | ||
479 | #define QLA82XX_ADDR_DDR_NET_MAX (0x000000000fffffffULL) | ||
480 | |||
481 | /* Imbus address bit used to indicate a host address. This bit is | ||
482 | * eliminated by the pcie bar and bar select before presentation | ||
483 | * over pcie. */ | ||
484 | /* host memory via IMBUS */ | ||
485 | #define QLA82XX_P2_ADDR_PCIE (0x0000000800000000ULL) | ||
486 | #define QLA82XX_P3_ADDR_PCIE (0x0000008000000000ULL) | ||
487 | #define QLA82XX_ADDR_PCIE_MAX (0x0000000FFFFFFFFFULL) | ||
488 | #define QLA82XX_ADDR_OCM0 (0x0000000200000000ULL) | ||
489 | #define QLA82XX_ADDR_OCM0_MAX (0x00000002000fffffULL) | ||
490 | #define QLA82XX_ADDR_OCM1 (0x0000000200400000ULL) | ||
491 | #define QLA82XX_ADDR_OCM1_MAX (0x00000002004fffffULL) | ||
492 | #define QLA82XX_ADDR_QDR_NET (0x0000000300000000ULL) | ||
493 | |||
494 | #define QLA82XX_P2_ADDR_QDR_NET_MAX (0x00000003001fffffULL) | ||
495 | #define QLA82XX_P3_ADDR_QDR_NET_MAX (0x0000000303ffffffULL) | ||
496 | |||
497 | #define QLA82XX_PCI_CRBSPACE (unsigned long)0x06000000 | ||
498 | #define QLA82XX_PCI_DIRECT_CRB (unsigned long)0x04400000 | ||
499 | #define QLA82XX_PCI_CAMQM (unsigned long)0x04800000 | ||
500 | #define QLA82XX_PCI_CAMQM_MAX (unsigned long)0x04ffffff | ||
501 | #define QLA82XX_PCI_DDR_NET (unsigned long)0x00000000 | ||
502 | #define QLA82XX_PCI_QDR_NET (unsigned long)0x04000000 | ||
503 | #define QLA82XX_PCI_QDR_NET_MAX (unsigned long)0x043fffff | ||
504 | |||
505 | /* | ||
506 | * Register offsets for MN | ||
507 | */ | ||
508 | #define MIU_CONTROL (0x000) | ||
509 | #define MIU_TAG (0x004) | ||
510 | #define MIU_TEST_AGT_CTRL (0x090) | ||
511 | #define MIU_TEST_AGT_ADDR_LO (0x094) | ||
512 | #define MIU_TEST_AGT_ADDR_HI (0x098) | ||
513 | #define MIU_TEST_AGT_WRDATA_LO (0x0a0) | ||
514 | #define MIU_TEST_AGT_WRDATA_HI (0x0a4) | ||
515 | #define MIU_TEST_AGT_WRDATA(i) (0x0a0+(4*(i))) | ||
516 | #define MIU_TEST_AGT_RDDATA_LO (0x0a8) | ||
517 | #define MIU_TEST_AGT_RDDATA_HI (0x0ac) | ||
518 | #define MIU_TEST_AGT_RDDATA(i) (0x0a8+(4*(i))) | ||
519 | #define MIU_TEST_AGT_ADDR_MASK 0xfffffff8 | ||
520 | #define MIU_TEST_AGT_UPPER_ADDR(off) (0) | ||
521 | |||
522 | /* MIU_TEST_AGT_CTRL flags. work for SIU as well */ | ||
523 | #define MIU_TA_CTL_START 1 | ||
524 | #define MIU_TA_CTL_ENABLE 2 | ||
525 | #define MIU_TA_CTL_WRITE 4 | ||
526 | #define MIU_TA_CTL_BUSY 8 | ||
527 | |||
528 | /*CAM RAM */ | ||
529 | # define QLA82XX_CAM_RAM_BASE (QLA82XX_CRB_CAM + 0x02000) | ||
530 | # define QLA82XX_CAM_RAM(reg) (QLA82XX_CAM_RAM_BASE + (reg)) | ||
531 | |||
532 | #define QLA82XX_PEG_TUNE_MN_SPD_ZEROED 0x80000000 | ||
533 | #define QLA82XX_BOOT_LOADER_MN_ISSUE 0xff00ffff | ||
534 | #define QLA82XX_PORT_MODE_ADDR (QLA82XX_CAM_RAM(0x24)) | ||
535 | #define QLA82XX_PEG_HALT_STATUS1 (QLA82XX_CAM_RAM(0xa8)) | ||
536 | #define QLA82XX_PEG_HALT_STATUS2 (QLA82XX_CAM_RAM(0xac)) | ||
537 | #define QLA82XX_PEG_ALIVE_COUNTER (QLA82XX_CAM_RAM(0xb0)) | ||
538 | |||
539 | #define HALT_STATUS_UNRECOVERABLE 0x80000000 | ||
540 | #define HALT_STATUS_RECOVERABLE 0x40000000 | ||
541 | |||
542 | |||
543 | #define QLA82XX_ROM_LOCK_ID (QLA82XX_CAM_RAM(0x100)) | ||
544 | #define QLA82XX_CRB_WIN_LOCK_ID (QLA82XX_CAM_RAM(0x124)) | ||
545 | #define QLA82XX_FW_VERSION_MAJOR (QLA82XX_CAM_RAM(0x150)) | ||
546 | #define QLA82XX_FW_VERSION_MINOR (QLA82XX_CAM_RAM(0x154)) | ||
547 | #define QLA82XX_FW_VERSION_SUB (QLA82XX_CAM_RAM(0x158)) | ||
548 | #define QLA82XX_PCIE_REG(reg) (QLA82XX_CRB_PCIE + (reg)) | ||
549 | |||
550 | /* Driver Coexistence Defines */ | ||
551 | #define QLA82XX_CRB_DRV_ACTIVE (QLA82XX_CAM_RAM(0x138)) | ||
552 | #define QLA82XX_CRB_DEV_STATE (QLA82XX_CAM_RAM(0x140)) | ||
553 | #define QLA82XX_CRB_DEV_PART_INFO (QLA82XX_CAM_RAM(0x14c)) | ||
554 | #define QLA82XX_CRB_DRV_IDC_VERSION (QLA82XX_CAM_RAM(0x174)) | ||
555 | #define QLA82XX_CRB_DRV_STATE (QLA82XX_CAM_RAM(0x144)) | ||
556 | #define QLA82XX_CRB_DRV_SCRATCH (QLA82XX_CAM_RAM(0x148)) | ||
557 | #define QLA82XX_CRB_DEV_PART_INFO (QLA82XX_CAM_RAM(0x14c)) | ||
558 | |||
559 | /* Every driver should use these Device State */ | ||
560 | #define QLA82XX_DEV_COLD 1 | ||
561 | #define QLA82XX_DEV_INITIALIZING 2 | ||
562 | #define QLA82XX_DEV_READY 3 | ||
563 | #define QLA82XX_DEV_NEED_RESET 4 | ||
564 | #define QLA82XX_DEV_NEED_QUIESCENT 5 | ||
565 | #define QLA82XX_DEV_FAILED 6 | ||
566 | #define QLA82XX_DEV_QUIESCENT 7 | ||
567 | #define MAX_STATES 8 /* Increment if new state added */ | ||
568 | |||
569 | #define QLA82XX_IDC_VERSION 0x1 | ||
570 | #define ROM_DEV_INIT_TIMEOUT 30 | ||
571 | #define ROM_DRV_RESET_ACK_TIMEOUT 10 | ||
572 | |||
573 | #define PCIE_SETUP_FUNCTION (0x12040) | ||
574 | #define PCIE_SETUP_FUNCTION2 (0x12048) | ||
575 | |||
576 | #define QLA82XX_PCIX_PS_REG(reg) (QLA82XX_CRB_PCIX_MD + (reg)) | ||
577 | #define QLA82XX_PCIX_PS2_REG(reg) (QLA82XX_CRB_PCIE2 + (reg)) | ||
578 | |||
579 | #define PCIE_SEM2_LOCK (0x1c010) /* Flash lock */ | ||
580 | #define PCIE_SEM2_UNLOCK (0x1c014) /* Flash unlock */ | ||
581 | #define PCIE_SEM5_LOCK (0x1c028) /* Coexistence lock */ | ||
582 | #define PCIE_SEM5_UNLOCK (0x1c02c) /* Coexistence unlock */ | ||
583 | #define PCIE_SEM7_LOCK (0x1c038) /* crb win lock */ | ||
584 | #define PCIE_SEM7_UNLOCK (0x1c03c) /* crbwin unlock*/ | ||
585 | |||
586 | /* | ||
587 | * The PCI VendorID and DeviceID for our board. | ||
588 | */ | ||
589 | #define QLA82XX_MSIX_TBL_SPACE 8192 | ||
590 | #define QLA82XX_PCI_REG_MSIX_TBL 0x44 | ||
591 | #define QLA82XX_PCI_MSIX_CONTROL 0x40 | ||
592 | |||
593 | struct crb_128M_2M_sub_block_map { | ||
594 | unsigned valid; | ||
595 | unsigned start_128M; | ||
596 | unsigned end_128M; | ||
597 | unsigned start_2M; | ||
598 | }; | ||
599 | |||
600 | struct crb_128M_2M_block_map { | ||
601 | struct crb_128M_2M_sub_block_map sub_block[16]; | ||
602 | }; | ||
603 | |||
604 | struct crb_addr_pair { | ||
605 | long addr; | ||
606 | long data; | ||
607 | }; | ||
608 | |||
609 | #define ADDR_ERROR ((unsigned long) 0xffffffff) | ||
610 | #define MAX_CTL_CHECK 1000 | ||
611 | |||
612 | /*************************************************************************** | ||
613 | * PCI related defines. | ||
614 | **************************************************************************/ | ||
615 | |||
616 | /* | ||
617 | * Interrupt related defines. | ||
618 | */ | ||
619 | #define PCIX_TARGET_STATUS (0x10118) | ||
620 | #define PCIX_TARGET_STATUS_F1 (0x10160) | ||
621 | #define PCIX_TARGET_STATUS_F2 (0x10164) | ||
622 | #define PCIX_TARGET_STATUS_F3 (0x10168) | ||
623 | #define PCIX_TARGET_STATUS_F4 (0x10360) | ||
624 | #define PCIX_TARGET_STATUS_F5 (0x10364) | ||
625 | #define PCIX_TARGET_STATUS_F6 (0x10368) | ||
626 | #define PCIX_TARGET_STATUS_F7 (0x1036c) | ||
627 | |||
628 | #define PCIX_TARGET_MASK (0x10128) | ||
629 | #define PCIX_TARGET_MASK_F1 (0x10170) | ||
630 | #define PCIX_TARGET_MASK_F2 (0x10174) | ||
631 | #define PCIX_TARGET_MASK_F3 (0x10178) | ||
632 | #define PCIX_TARGET_MASK_F4 (0x10370) | ||
633 | #define PCIX_TARGET_MASK_F5 (0x10374) | ||
634 | #define PCIX_TARGET_MASK_F6 (0x10378) | ||
635 | #define PCIX_TARGET_MASK_F7 (0x1037c) | ||
636 | |||
637 | /* | ||
638 | * Message Signaled Interrupts | ||
639 | */ | ||
640 | #define PCIX_MSI_F0 (0x13000) | ||
641 | #define PCIX_MSI_F1 (0x13004) | ||
642 | #define PCIX_MSI_F2 (0x13008) | ||
643 | #define PCIX_MSI_F3 (0x1300c) | ||
644 | #define PCIX_MSI_F4 (0x13010) | ||
645 | #define PCIX_MSI_F5 (0x13014) | ||
646 | #define PCIX_MSI_F6 (0x13018) | ||
647 | #define PCIX_MSI_F7 (0x1301c) | ||
648 | #define PCIX_MSI_F(FUNC) (0x13000 + ((FUNC) * 4)) | ||
649 | |||
650 | /* | ||
651 | * | ||
652 | */ | ||
653 | #define PCIX_INT_VECTOR (0x10100) | ||
654 | #define PCIX_INT_MASK (0x10104) | ||
655 | |||
656 | /* | ||
657 | * Interrupt state machine and other bits. | ||
658 | */ | ||
659 | #define PCIE_MISCCFG_RC (0x1206c) | ||
660 | |||
661 | |||
662 | #define ISR_INT_TARGET_STATUS \ | ||
663 | (QLA82XX_PCIX_PS_REG(PCIX_TARGET_STATUS)) | ||
664 | #define ISR_INT_TARGET_STATUS_F1 \ | ||
665 | (QLA82XX_PCIX_PS_REG(PCIX_TARGET_STATUS_F1)) | ||
666 | #define ISR_INT_TARGET_STATUS_F2 \ | ||
667 | (QLA82XX_PCIX_PS_REG(PCIX_TARGET_STATUS_F2)) | ||
668 | #define ISR_INT_TARGET_STATUS_F3 \ | ||
669 | (QLA82XX_PCIX_PS_REG(PCIX_TARGET_STATUS_F3)) | ||
670 | #define ISR_INT_TARGET_STATUS_F4 \ | ||
671 | (QLA82XX_PCIX_PS_REG(PCIX_TARGET_STATUS_F4)) | ||
672 | #define ISR_INT_TARGET_STATUS_F5 \ | ||
673 | (QLA82XX_PCIX_PS_REG(PCIX_TARGET_STATUS_F5)) | ||
674 | #define ISR_INT_TARGET_STATUS_F6 \ | ||
675 | (QLA82XX_PCIX_PS_REG(PCIX_TARGET_STATUS_F6)) | ||
676 | #define ISR_INT_TARGET_STATUS_F7 \ | ||
677 | (QLA82XX_PCIX_PS_REG(PCIX_TARGET_STATUS_F7)) | ||
678 | |||
679 | #define ISR_INT_TARGET_MASK \ | ||
680 | (QLA82XX_PCIX_PS_REG(PCIX_TARGET_MASK)) | ||
681 | #define ISR_INT_TARGET_MASK_F1 \ | ||
682 | (QLA82XX_PCIX_PS_REG(PCIX_TARGET_MASK_F1)) | ||
683 | #define ISR_INT_TARGET_MASK_F2 \ | ||
684 | (QLA82XX_PCIX_PS_REG(PCIX_TARGET_MASK_F2)) | ||
685 | #define ISR_INT_TARGET_MASK_F3 \ | ||
686 | (QLA82XX_PCIX_PS_REG(PCIX_TARGET_MASK_F3)) | ||
687 | #define ISR_INT_TARGET_MASK_F4 \ | ||
688 | (QLA82XX_PCIX_PS_REG(PCIX_TARGET_MASK_F4)) | ||
689 | #define ISR_INT_TARGET_MASK_F5 \ | ||
690 | (QLA82XX_PCIX_PS_REG(PCIX_TARGET_MASK_F5)) | ||
691 | #define ISR_INT_TARGET_MASK_F6 \ | ||
692 | (QLA82XX_PCIX_PS_REG(PCIX_TARGET_MASK_F6)) | ||
693 | #define ISR_INT_TARGET_MASK_F7 \ | ||
694 | (QLA82XX_PCIX_PS_REG(PCIX_TARGET_MASK_F7)) | ||
695 | |||
696 | #define ISR_INT_VECTOR (QLA82XX_PCIX_PS_REG(PCIX_INT_VECTOR)) | ||
697 | #define ISR_INT_MASK (QLA82XX_PCIX_PS_REG(PCIX_INT_MASK)) | ||
698 | #define ISR_INT_STATE_REG (QLA82XX_PCIX_PS_REG(PCIE_MISCCFG_RC)) | ||
699 | |||
700 | #define ISR_MSI_INT_TRIGGER(FUNC) (QLA82XX_PCIX_PS_REG(PCIX_MSI_F(FUNC))) | ||
701 | |||
702 | |||
703 | #define ISR_IS_LEGACY_INTR_IDLE(VAL) (((VAL) & 0x300) == 0) | ||
704 | #define ISR_IS_LEGACY_INTR_TRIGGERED(VAL) (((VAL) & 0x300) == 0x200) | ||
705 | |||
706 | /* | ||
707 | * PCI Interrupt Vector Values. | ||
708 | */ | ||
709 | #define PCIX_INT_VECTOR_BIT_F0 0x0080 | ||
710 | #define PCIX_INT_VECTOR_BIT_F1 0x0100 | ||
711 | #define PCIX_INT_VECTOR_BIT_F2 0x0200 | ||
712 | #define PCIX_INT_VECTOR_BIT_F3 0x0400 | ||
713 | #define PCIX_INT_VECTOR_BIT_F4 0x0800 | ||
714 | #define PCIX_INT_VECTOR_BIT_F5 0x1000 | ||
715 | #define PCIX_INT_VECTOR_BIT_F6 0x2000 | ||
716 | #define PCIX_INT_VECTOR_BIT_F7 0x4000 | ||
717 | |||
718 | /* struct qla4_8xxx_legacy_intr_set defined in ql4_def.h */ | ||
719 | |||
720 | #define QLA82XX_LEGACY_INTR_CONFIG \ | ||
721 | { \ | ||
722 | { \ | ||
723 | .int_vec_bit = PCIX_INT_VECTOR_BIT_F0, \ | ||
724 | .tgt_status_reg = ISR_INT_TARGET_STATUS, \ | ||
725 | .tgt_mask_reg = ISR_INT_TARGET_MASK, \ | ||
726 | .pci_int_reg = ISR_MSI_INT_TRIGGER(0) }, \ | ||
727 | \ | ||
728 | { \ | ||
729 | .int_vec_bit = PCIX_INT_VECTOR_BIT_F1, \ | ||
730 | .tgt_status_reg = ISR_INT_TARGET_STATUS_F1, \ | ||
731 | .tgt_mask_reg = ISR_INT_TARGET_MASK_F1, \ | ||
732 | .pci_int_reg = ISR_MSI_INT_TRIGGER(1) }, \ | ||
733 | \ | ||
734 | { \ | ||
735 | .int_vec_bit = PCIX_INT_VECTOR_BIT_F2, \ | ||
736 | .tgt_status_reg = ISR_INT_TARGET_STATUS_F2, \ | ||
737 | .tgt_mask_reg = ISR_INT_TARGET_MASK_F2, \ | ||
738 | .pci_int_reg = ISR_MSI_INT_TRIGGER(2) }, \ | ||
739 | \ | ||
740 | { \ | ||
741 | .int_vec_bit = PCIX_INT_VECTOR_BIT_F3, \ | ||
742 | .tgt_status_reg = ISR_INT_TARGET_STATUS_F3, \ | ||
743 | .tgt_mask_reg = ISR_INT_TARGET_MASK_F3, \ | ||
744 | .pci_int_reg = ISR_MSI_INT_TRIGGER(3) }, \ | ||
745 | \ | ||
746 | { \ | ||
747 | .int_vec_bit = PCIX_INT_VECTOR_BIT_F4, \ | ||
748 | .tgt_status_reg = ISR_INT_TARGET_STATUS_F4, \ | ||
749 | .tgt_mask_reg = ISR_INT_TARGET_MASK_F4, \ | ||
750 | .pci_int_reg = ISR_MSI_INT_TRIGGER(4) }, \ | ||
751 | \ | ||
752 | { \ | ||
753 | .int_vec_bit = PCIX_INT_VECTOR_BIT_F5, \ | ||
754 | .tgt_status_reg = ISR_INT_TARGET_STATUS_F5, \ | ||
755 | .tgt_mask_reg = ISR_INT_TARGET_MASK_F5, \ | ||
756 | .pci_int_reg = ISR_MSI_INT_TRIGGER(5) }, \ | ||
757 | \ | ||
758 | { \ | ||
759 | .int_vec_bit = PCIX_INT_VECTOR_BIT_F6, \ | ||
760 | .tgt_status_reg = ISR_INT_TARGET_STATUS_F6, \ | ||
761 | .tgt_mask_reg = ISR_INT_TARGET_MASK_F6, \ | ||
762 | .pci_int_reg = ISR_MSI_INT_TRIGGER(6) }, \ | ||
763 | \ | ||
764 | { \ | ||
765 | .int_vec_bit = PCIX_INT_VECTOR_BIT_F7, \ | ||
766 | .tgt_status_reg = ISR_INT_TARGET_STATUS_F7, \ | ||
767 | .tgt_mask_reg = ISR_INT_TARGET_MASK_F7, \ | ||
768 | .pci_int_reg = ISR_MSI_INT_TRIGGER(7) }, \ | ||
769 | } | ||
770 | |||
771 | /* Magic number to let user know flash is programmed */ | ||
772 | #define QLA82XX_BDINFO_MAGIC 0x12345678 | ||
773 | #define FW_SIZE_OFFSET (0x3e840c) | ||
774 | |||
775 | /* QLA82XX additions */ | ||
776 | #define MIU_TEST_AGT_WRDATA_UPPER_LO (0x0b0) | ||
777 | #define MIU_TEST_AGT_WRDATA_UPPER_HI (0x0b4) | ||
778 | |||
779 | #endif | ||
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 38b1d38afca5..64a1288e06b4 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c | |||
@@ -30,22 +30,29 @@ static struct kmem_cache *srb_cachep; | |||
30 | * Module parameter information and variables | 30 | * Module parameter information and variables |
31 | */ | 31 | */ |
32 | int ql4xdiscoverywait = 60; | 32 | int ql4xdiscoverywait = 60; |
33 | module_param(ql4xdiscoverywait, int, S_IRUGO | S_IRUSR); | 33 | module_param(ql4xdiscoverywait, int, S_IRUGO | S_IWUSR); |
34 | MODULE_PARM_DESC(ql4xdiscoverywait, "Discovery wait time"); | 34 | MODULE_PARM_DESC(ql4xdiscoverywait, "Discovery wait time"); |
35 | |||
35 | int ql4xdontresethba = 0; | 36 | int ql4xdontresethba = 0; |
36 | module_param(ql4xdontresethba, int, S_IRUGO | S_IRUSR); | 37 | module_param(ql4xdontresethba, int, S_IRUGO | S_IWUSR); |
37 | MODULE_PARM_DESC(ql4xdontresethba, | 38 | MODULE_PARM_DESC(ql4xdontresethba, |
38 | "Dont reset the HBA when the driver gets 0x8002 AEN " | 39 | "Don't reset the HBA for driver recovery \n" |
39 | " default it will reset hba :0" | 40 | " 0 - It will reset HBA (Default)\n" |
40 | " set to 1 to avoid resetting HBA"); | 41 | " 1 - It will NOT reset HBA"); |
41 | 42 | ||
42 | int ql4xextended_error_logging = 0; /* 0 = off, 1 = log errors */ | 43 | int ql4xextended_error_logging = 0; /* 0 = off, 1 = log errors */ |
43 | module_param(ql4xextended_error_logging, int, S_IRUGO | S_IRUSR); | 44 | module_param(ql4xextended_error_logging, int, S_IRUGO | S_IWUSR); |
44 | MODULE_PARM_DESC(ql4xextended_error_logging, | 45 | MODULE_PARM_DESC(ql4xextended_error_logging, |
45 | "Option to enable extended error logging, " | 46 | "Option to enable extended error logging, " |
46 | "Default is 0 - no logging, 1 - debug logging"); | 47 | "Default is 0 - no logging, 1 - debug logging"); |
47 | 48 | ||
48 | int ql4_mod_unload = 0; | 49 | int ql4xenablemsix = 1; |
50 | module_param(ql4xenablemsix, int, S_IRUGO|S_IWUSR); | ||
51 | MODULE_PARM_DESC(ql4xenablemsix, | ||
52 | "Set to enable MSI or MSI-X interrupt mechanism.\n" | ||
53 | " 0 = enable INTx interrupt mechanism.\n" | ||
54 | " 1 = enable MSI-X interrupt mechanism (Default).\n" | ||
55 | " 2 = enable MSI interrupt mechanism."); | ||
49 | 56 | ||
50 | #define QL4_DEF_QDEPTH 32 | 57 | #define QL4_DEF_QDEPTH 32 |
51 | 58 | ||
@@ -83,6 +90,9 @@ static int qla4xxx_slave_configure(struct scsi_device *device); | |||
83 | static void qla4xxx_slave_destroy(struct scsi_device *sdev); | 90 | static void qla4xxx_slave_destroy(struct scsi_device *sdev); |
84 | static void qla4xxx_scan_start(struct Scsi_Host *shost); | 91 | static void qla4xxx_scan_start(struct Scsi_Host *shost); |
85 | 92 | ||
93 | static struct qla4_8xxx_legacy_intr_set legacy_intr[] = | ||
94 | QLA82XX_LEGACY_INTR_CONFIG; | ||
95 | |||
86 | static struct scsi_host_template qla4xxx_driver_template = { | 96 | static struct scsi_host_template qla4xxx_driver_template = { |
87 | .module = THIS_MODULE, | 97 | .module = THIS_MODULE, |
88 | .name = DRIVER_NAME, | 98 | .name = DRIVER_NAME, |
@@ -152,15 +162,12 @@ static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session) | |||
152 | if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) { | 162 | if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) { |
153 | atomic_set(&ddb_entry->state, DDB_STATE_DEAD); | 163 | atomic_set(&ddb_entry->state, DDB_STATE_DEAD); |
154 | 164 | ||
155 | DEBUG2(printk("scsi%ld: %s: index [%d] port down retry count " | 165 | DEBUG2(printk("scsi%ld: %s: ddb [%d] port down retry count " |
156 | "of (%d) secs exhausted, marking device DEAD.\n", | 166 | "of (%d) secs exhausted, marking device DEAD.\n", |
157 | ha->host_no, __func__, ddb_entry->fw_ddb_index, | 167 | ha->host_no, __func__, ddb_entry->fw_ddb_index, |
158 | ha->port_down_retry_count)); | 168 | ha->port_down_retry_count)); |
159 | 169 | ||
160 | DEBUG2(printk("scsi%ld: %s: scheduling dpc routine - dpc " | 170 | qla4xxx_wake_dpc(ha); |
161 | "flags = 0x%lx\n", | ||
162 | ha->host_no, __func__, ha->dpc_flags)); | ||
163 | queue_work(ha->dpc_thread, &ha->dpc_work); | ||
164 | } | 171 | } |
165 | } | 172 | } |
166 | 173 | ||
@@ -362,19 +369,37 @@ static void qla4xxx_stop_timer(struct scsi_qla_host *ha) | |||
362 | * @ha: Pointer to host adapter structure. | 369 | * @ha: Pointer to host adapter structure. |
363 | * @ddb_entry: Pointer to device database entry | 370 | * @ddb_entry: Pointer to device database entry |
364 | * | 371 | * |
365 | * This routine marks a device missing and resets the relogin retry count. | 372 | * This routine marks a device missing and close connection. |
366 | **/ | 373 | **/ |
367 | void qla4xxx_mark_device_missing(struct scsi_qla_host *ha, | 374 | void qla4xxx_mark_device_missing(struct scsi_qla_host *ha, |
368 | struct ddb_entry *ddb_entry) | 375 | struct ddb_entry *ddb_entry) |
369 | { | 376 | { |
370 | atomic_set(&ddb_entry->state, DDB_STATE_MISSING); | 377 | if ((atomic_read(&ddb_entry->state) != DDB_STATE_DEAD)) { |
371 | DEBUG3(printk("scsi%d:%d:%d: index [%d] marked MISSING\n", | 378 | atomic_set(&ddb_entry->state, DDB_STATE_MISSING); |
372 | ha->host_no, ddb_entry->bus, ddb_entry->target, | 379 | DEBUG2(printk("scsi%ld: ddb [%d] marked MISSING\n", |
373 | ddb_entry->fw_ddb_index)); | 380 | ha->host_no, ddb_entry->fw_ddb_index)); |
381 | } else | ||
382 | DEBUG2(printk("scsi%ld: ddb [%d] DEAD\n", ha->host_no, | ||
383 | ddb_entry->fw_ddb_index)) | ||
384 | |||
374 | iscsi_block_session(ddb_entry->sess); | 385 | iscsi_block_session(ddb_entry->sess); |
375 | iscsi_conn_error_event(ddb_entry->conn, ISCSI_ERR_CONN_FAILED); | 386 | iscsi_conn_error_event(ddb_entry->conn, ISCSI_ERR_CONN_FAILED); |
376 | } | 387 | } |
377 | 388 | ||
389 | /** | ||
390 | * qla4xxx_mark_all_devices_missing - mark all devices as missing. | ||
391 | * @ha: Pointer to host adapter structure. | ||
392 | * | ||
393 | * This routine marks a device missing and resets the relogin retry count. | ||
394 | **/ | ||
395 | void qla4xxx_mark_all_devices_missing(struct scsi_qla_host *ha) | ||
396 | { | ||
397 | struct ddb_entry *ddb_entry, *ddbtemp; | ||
398 | list_for_each_entry_safe(ddb_entry, ddbtemp, &ha->ddb_list, list) { | ||
399 | qla4xxx_mark_device_missing(ha, ddb_entry); | ||
400 | } | ||
401 | } | ||
402 | |||
378 | static struct srb* qla4xxx_get_new_srb(struct scsi_qla_host *ha, | 403 | static struct srb* qla4xxx_get_new_srb(struct scsi_qla_host *ha, |
379 | struct ddb_entry *ddb_entry, | 404 | struct ddb_entry *ddb_entry, |
380 | struct scsi_cmnd *cmd, | 405 | struct scsi_cmnd *cmd, |
@@ -463,7 +488,13 @@ static int qla4xxx_queuecommand(struct scsi_cmnd *cmd, | |||
463 | return SCSI_MLQUEUE_TARGET_BUSY; | 488 | return SCSI_MLQUEUE_TARGET_BUSY; |
464 | } | 489 | } |
465 | 490 | ||
466 | if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) | 491 | if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) || |
492 | test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) || | ||
493 | test_bit(DPC_RESET_HA, &ha->dpc_flags) || | ||
494 | test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags) || | ||
495 | test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags) || | ||
496 | !test_bit(AF_ONLINE, &ha->flags) || | ||
497 | test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags)) | ||
467 | goto qc_host_busy; | 498 | goto qc_host_busy; |
468 | 499 | ||
469 | spin_unlock_irq(ha->host->host_lock); | 500 | spin_unlock_irq(ha->host->host_lock); |
@@ -524,7 +555,15 @@ static void qla4xxx_mem_free(struct scsi_qla_host *ha) | |||
524 | ha->srb_mempool = NULL; | 555 | ha->srb_mempool = NULL; |
525 | 556 | ||
526 | /* release io space registers */ | 557 | /* release io space registers */ |
527 | if (ha->reg) | 558 | if (is_qla8022(ha)) { |
559 | if (ha->nx_pcibase) | ||
560 | iounmap( | ||
561 | (struct device_reg_82xx __iomem *)ha->nx_pcibase); | ||
562 | |||
563 | if (ha->nx_db_wr_ptr) | ||
564 | iounmap( | ||
565 | (struct device_reg_82xx __iomem *)ha->nx_db_wr_ptr); | ||
566 | } else if (ha->reg) | ||
528 | iounmap(ha->reg); | 567 | iounmap(ha->reg); |
529 | pci_release_regions(ha->pdev); | 568 | pci_release_regions(ha->pdev); |
530 | } | 569 | } |
@@ -600,6 +639,74 @@ mem_alloc_error_exit: | |||
600 | } | 639 | } |
601 | 640 | ||
602 | /** | 641 | /** |
642 | * qla4_8xxx_check_fw_alive - Check firmware health | ||
643 | * @ha: Pointer to host adapter structure. | ||
644 | * | ||
645 | * Context: Interrupt | ||
646 | **/ | ||
647 | static void qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha) | ||
648 | { | ||
649 | uint32_t fw_heartbeat_counter, halt_status; | ||
650 | |||
651 | fw_heartbeat_counter = qla4_8xxx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); | ||
652 | |||
653 | if (ha->fw_heartbeat_counter == fw_heartbeat_counter) { | ||
654 | ha->seconds_since_last_heartbeat++; | ||
655 | /* FW not alive after 2 seconds */ | ||
656 | if (ha->seconds_since_last_heartbeat == 2) { | ||
657 | ha->seconds_since_last_heartbeat = 0; | ||
658 | halt_status = qla4_8xxx_rd_32(ha, | ||
659 | QLA82XX_PEG_HALT_STATUS1); | ||
660 | /* Since we cannot change dev_state in interrupt | ||
661 | * context, set appropriate DPC flag then wakeup | ||
662 | * DPC */ | ||
663 | if (halt_status & HALT_STATUS_UNRECOVERABLE) | ||
664 | set_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags); | ||
665 | else { | ||
666 | printk("scsi%ld: %s: detect abort needed!\n", | ||
667 | ha->host_no, __func__); | ||
668 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | ||
669 | } | ||
670 | qla4xxx_wake_dpc(ha); | ||
671 | } | ||
672 | } | ||
673 | ha->fw_heartbeat_counter = fw_heartbeat_counter; | ||
674 | } | ||
675 | |||
676 | /** | ||
677 | * qla4_8xxx_watchdog - Poll dev state | ||
678 | * @ha: Pointer to host adapter structure. | ||
679 | * | ||
680 | * Context: Interrupt | ||
681 | **/ | ||
682 | void qla4_8xxx_watchdog(struct scsi_qla_host *ha) | ||
683 | { | ||
684 | uint32_t dev_state; | ||
685 | |||
686 | dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); | ||
687 | |||
688 | /* don't poll if reset is going on */ | ||
689 | if (!test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags)) { | ||
690 | if (dev_state == QLA82XX_DEV_NEED_RESET && | ||
691 | !test_bit(DPC_RESET_HA, &ha->dpc_flags)) { | ||
692 | printk("scsi%ld: %s: HW State: NEED RESET!\n", | ||
693 | ha->host_no, __func__); | ||
694 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | ||
695 | qla4xxx_wake_dpc(ha); | ||
696 | } else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT && | ||
697 | !test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags)) { | ||
698 | printk("scsi%ld: %s: HW State: NEED QUIES!\n", | ||
699 | ha->host_no, __func__); | ||
700 | set_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags); | ||
701 | qla4xxx_wake_dpc(ha); | ||
702 | } else { | ||
703 | /* Check firmware health */ | ||
704 | qla4_8xxx_check_fw_alive(ha); | ||
705 | } | ||
706 | } | ||
707 | } | ||
708 | |||
709 | /** | ||
603 | * qla4xxx_timer - checks every second for work to do. | 710 | * qla4xxx_timer - checks every second for work to do. |
604 | * @ha: Pointer to host adapter structure. | 711 | * @ha: Pointer to host adapter structure. |
605 | **/ | 712 | **/ |
@@ -608,6 +715,16 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) | |||
608 | struct ddb_entry *ddb_entry, *dtemp; | 715 | struct ddb_entry *ddb_entry, *dtemp; |
609 | int start_dpc = 0; | 716 | int start_dpc = 0; |
610 | 717 | ||
718 | if (test_bit(AF_HBA_GOING_AWAY, &ha->flags)) { | ||
719 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s exited. HBA GOING AWAY\n", | ||
720 | __func__)); | ||
721 | return; | ||
722 | } | ||
723 | |||
724 | if (is_qla8022(ha)) { | ||
725 | qla4_8xxx_watchdog(ha); | ||
726 | } | ||
727 | |||
611 | /* Search for relogin's to time-out and port down retry. */ | 728 | /* Search for relogin's to time-out and port down retry. */ |
612 | list_for_each_entry_safe(ddb_entry, dtemp, &ha->ddb_list, list) { | 729 | list_for_each_entry_safe(ddb_entry, dtemp, &ha->ddb_list, list) { |
613 | /* Count down time between sending relogins */ | 730 | /* Count down time between sending relogins */ |
@@ -624,7 +741,7 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) | |||
624 | set_bit(DPC_RELOGIN_DEVICE, | 741 | set_bit(DPC_RELOGIN_DEVICE, |
625 | &ha->dpc_flags); | 742 | &ha->dpc_flags); |
626 | set_bit(DF_RELOGIN, &ddb_entry->flags); | 743 | set_bit(DF_RELOGIN, &ddb_entry->flags); |
627 | DEBUG2(printk("scsi%ld: %s: index [%d]" | 744 | DEBUG2(printk("scsi%ld: %s: ddb [%d]" |
628 | " login device\n", | 745 | " login device\n", |
629 | ha->host_no, __func__, | 746 | ha->host_no, __func__, |
630 | ddb_entry->fw_ddb_index)); | 747 | ddb_entry->fw_ddb_index)); |
@@ -647,7 +764,7 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) | |||
647 | DDB_DS_SESSION_FAILED) { | 764 | DDB_DS_SESSION_FAILED) { |
648 | /* Reset retry relogin timer */ | 765 | /* Reset retry relogin timer */ |
649 | atomic_inc(&ddb_entry->relogin_retry_count); | 766 | atomic_inc(&ddb_entry->relogin_retry_count); |
650 | DEBUG2(printk("scsi%ld: index[%d] relogin" | 767 | DEBUG2(printk("scsi%ld: ddb [%d] relogin" |
651 | " timed out-retrying" | 768 | " timed out-retrying" |
652 | " relogin (%d)\n", | 769 | " relogin (%d)\n", |
653 | ha->host_no, | 770 | ha->host_no, |
@@ -656,7 +773,7 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) | |||
656 | relogin_retry_count)) | 773 | relogin_retry_count)) |
657 | ); | 774 | ); |
658 | start_dpc++; | 775 | start_dpc++; |
659 | DEBUG(printk("scsi%ld:%d:%d: index [%d] " | 776 | DEBUG(printk("scsi%ld:%d:%d: ddb [%d] " |
660 | "initate relogin after" | 777 | "initate relogin after" |
661 | " %d seconds\n", | 778 | " %d seconds\n", |
662 | ha->host_no, ddb_entry->bus, | 779 | ha->host_no, ddb_entry->bus, |
@@ -671,31 +788,35 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) | |||
671 | } | 788 | } |
672 | } | 789 | } |
673 | 790 | ||
674 | /* Check for heartbeat interval. */ | 791 | if (!is_qla8022(ha)) { |
675 | if (ha->firmware_options & FWOPT_HEARTBEAT_ENABLE && | 792 | /* Check for heartbeat interval. */ |
676 | ha->heartbeat_interval != 0) { | 793 | if (ha->firmware_options & FWOPT_HEARTBEAT_ENABLE && |
677 | ha->seconds_since_last_heartbeat++; | 794 | ha->heartbeat_interval != 0) { |
678 | if (ha->seconds_since_last_heartbeat > | 795 | ha->seconds_since_last_heartbeat++; |
679 | ha->heartbeat_interval + 2) | 796 | if (ha->seconds_since_last_heartbeat > |
680 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | 797 | ha->heartbeat_interval + 2) |
798 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | ||
799 | } | ||
681 | } | 800 | } |
682 | 801 | ||
683 | |||
684 | /* Wakeup the dpc routine for this adapter, if needed. */ | 802 | /* Wakeup the dpc routine for this adapter, if needed. */ |
685 | if ((start_dpc || | 803 | if ((start_dpc || |
686 | test_bit(DPC_RESET_HA, &ha->dpc_flags) || | 804 | test_bit(DPC_RESET_HA, &ha->dpc_flags) || |
687 | test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags) || | 805 | test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags) || |
688 | test_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags) || | 806 | test_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags) || |
689 | test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags) || | 807 | test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags) || |
690 | test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) || | 808 | test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) || |
691 | test_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags) || | 809 | test_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags) || |
692 | test_bit(DPC_LINK_CHANGED, &ha->dpc_flags) || | 810 | test_bit(DPC_LINK_CHANGED, &ha->dpc_flags) || |
811 | test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags) || | ||
812 | test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags) || | ||
693 | test_bit(DPC_AEN, &ha->dpc_flags)) && | 813 | test_bit(DPC_AEN, &ha->dpc_flags)) && |
814 | !test_bit(AF_DPC_SCHEDULED, &ha->flags) && | ||
694 | ha->dpc_thread) { | 815 | ha->dpc_thread) { |
695 | DEBUG2(printk("scsi%ld: %s: scheduling dpc routine" | 816 | DEBUG2(printk("scsi%ld: %s: scheduling dpc routine" |
696 | " - dpc flags = 0x%lx\n", | 817 | " - dpc flags = 0x%lx\n", |
697 | ha->host_no, __func__, ha->dpc_flags)); | 818 | ha->host_no, __func__, ha->dpc_flags)); |
698 | queue_work(ha->dpc_thread, &ha->dpc_work); | 819 | qla4xxx_wake_dpc(ha); |
699 | } | 820 | } |
700 | 821 | ||
701 | /* Reschedule timer thread to call us back in one second */ | 822 | /* Reschedule timer thread to call us back in one second */ |
@@ -714,16 +835,15 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) | |||
714 | static int qla4xxx_cmd_wait(struct scsi_qla_host *ha) | 835 | static int qla4xxx_cmd_wait(struct scsi_qla_host *ha) |
715 | { | 836 | { |
716 | uint32_t index = 0; | 837 | uint32_t index = 0; |
717 | int stat = QLA_SUCCESS; | ||
718 | unsigned long flags; | 838 | unsigned long flags; |
719 | struct scsi_cmnd *cmd; | 839 | struct scsi_cmnd *cmd; |
720 | int wait_cnt = WAIT_CMD_TOV; /* | ||
721 | * Initialized for 30 seconds as we | ||
722 | * expect all commands to retuned | ||
723 | * ASAP. | ||
724 | */ | ||
725 | 840 | ||
726 | while (wait_cnt) { | 841 | unsigned long wtime = jiffies + (WAIT_CMD_TOV * HZ); |
842 | |||
843 | DEBUG2(ql4_printk(KERN_INFO, ha, "Wait up to %d seconds for cmds to " | ||
844 | "complete\n", WAIT_CMD_TOV)); | ||
845 | |||
846 | while (!time_after_eq(jiffies, wtime)) { | ||
727 | spin_lock_irqsave(&ha->hardware_lock, flags); | 847 | spin_lock_irqsave(&ha->hardware_lock, flags); |
728 | /* Find a command that hasn't completed. */ | 848 | /* Find a command that hasn't completed. */ |
729 | for (index = 0; index < ha->host->can_queue; index++) { | 849 | for (index = 0; index < ha->host->can_queue; index++) { |
@@ -734,31 +854,26 @@ static int qla4xxx_cmd_wait(struct scsi_qla_host *ha) | |||
734 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 854 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
735 | 855 | ||
736 | /* If No Commands are pending, wait is complete */ | 856 | /* If No Commands are pending, wait is complete */ |
737 | if (index == ha->host->can_queue) { | 857 | if (index == ha->host->can_queue) |
738 | break; | 858 | return QLA_SUCCESS; |
739 | } | ||
740 | |||
741 | /* If we timed out on waiting for commands to come back | ||
742 | * return ERROR. | ||
743 | */ | ||
744 | wait_cnt--; | ||
745 | if (wait_cnt == 0) | ||
746 | stat = QLA_ERROR; | ||
747 | else { | ||
748 | msleep(1000); | ||
749 | } | ||
750 | } /* End of While (wait_cnt) */ | ||
751 | 859 | ||
752 | return stat; | 860 | msleep(1000); |
861 | } | ||
862 | /* If we timed out on waiting for commands to come back | ||
863 | * return ERROR. */ | ||
864 | return QLA_ERROR; | ||
753 | } | 865 | } |
754 | 866 | ||
755 | void qla4xxx_hw_reset(struct scsi_qla_host *ha) | 867 | int qla4xxx_hw_reset(struct scsi_qla_host *ha) |
756 | { | 868 | { |
757 | uint32_t ctrl_status; | 869 | uint32_t ctrl_status; |
758 | unsigned long flags = 0; | 870 | unsigned long flags = 0; |
759 | 871 | ||
760 | DEBUG2(printk(KERN_ERR "scsi%ld: %s\n", ha->host_no, __func__)); | 872 | DEBUG2(printk(KERN_ERR "scsi%ld: %s\n", ha->host_no, __func__)); |
761 | 873 | ||
874 | if (ql4xxx_lock_drvr_wait(ha) != QLA_SUCCESS) | ||
875 | return QLA_ERROR; | ||
876 | |||
762 | spin_lock_irqsave(&ha->hardware_lock, flags); | 877 | spin_lock_irqsave(&ha->hardware_lock, flags); |
763 | 878 | ||
764 | /* | 879 | /* |
@@ -774,6 +889,7 @@ void qla4xxx_hw_reset(struct scsi_qla_host *ha) | |||
774 | readl(&ha->reg->ctrl_status); | 889 | readl(&ha->reg->ctrl_status); |
775 | 890 | ||
776 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 891 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
892 | return QLA_SUCCESS; | ||
777 | } | 893 | } |
778 | 894 | ||
779 | /** | 895 | /** |
@@ -872,15 +988,16 @@ int qla4xxx_soft_reset(struct scsi_qla_host *ha) | |||
872 | } | 988 | } |
873 | 989 | ||
874 | /** | 990 | /** |
875 | * qla4xxx_flush_active_srbs - returns all outstanding i/o requests to O.S. | 991 | * qla4xxx_abort_active_cmds - returns all outstanding i/o requests to O.S. |
876 | * @ha: Pointer to host adapter structure. | 992 | * @ha: Pointer to host adapter structure. |
993 | * @res: returned scsi status | ||
877 | * | 994 | * |
878 | * This routine is called just prior to a HARD RESET to return all | 995 | * This routine is called just prior to a HARD RESET to return all |
879 | * outstanding commands back to the Operating System. | 996 | * outstanding commands back to the Operating System. |
880 | * Caller should make sure that the following locks are released | 997 | * Caller should make sure that the following locks are released |
881 | * before this calling routine: Hardware lock, and io_request_lock. | 998 | * before this calling routine: Hardware lock, and io_request_lock. |
882 | **/ | 999 | **/ |
883 | static void qla4xxx_flush_active_srbs(struct scsi_qla_host *ha) | 1000 | static void qla4xxx_abort_active_cmds(struct scsi_qla_host *ha, int res) |
884 | { | 1001 | { |
885 | struct srb *srb; | 1002 | struct srb *srb; |
886 | int i; | 1003 | int i; |
@@ -890,74 +1007,116 @@ static void qla4xxx_flush_active_srbs(struct scsi_qla_host *ha) | |||
890 | for (i = 0; i < ha->host->can_queue; i++) { | 1007 | for (i = 0; i < ha->host->can_queue; i++) { |
891 | srb = qla4xxx_del_from_active_array(ha, i); | 1008 | srb = qla4xxx_del_from_active_array(ha, i); |
892 | if (srb != NULL) { | 1009 | if (srb != NULL) { |
893 | srb->cmd->result = DID_RESET << 16; | 1010 | srb->cmd->result = res; |
894 | kref_put(&srb->srb_ref, qla4xxx_srb_compl); | 1011 | kref_put(&srb->srb_ref, qla4xxx_srb_compl); |
895 | } | 1012 | } |
896 | } | 1013 | } |
897 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 1014 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
898 | } | 1015 | } |
899 | 1016 | ||
1017 | void qla4xxx_dead_adapter_cleanup(struct scsi_qla_host *ha) | ||
1018 | { | ||
1019 | clear_bit(AF_ONLINE, &ha->flags); | ||
1020 | |||
1021 | /* Disable the board */ | ||
1022 | ql4_printk(KERN_INFO, ha, "Disabling the board\n"); | ||
1023 | set_bit(AF_HBA_GOING_AWAY, &ha->flags); | ||
1024 | |||
1025 | qla4xxx_abort_active_cmds(ha, DID_NO_CONNECT << 16); | ||
1026 | qla4xxx_mark_all_devices_missing(ha); | ||
1027 | clear_bit(AF_INIT_DONE, &ha->flags); | ||
1028 | } | ||
1029 | |||
900 | /** | 1030 | /** |
901 | * qla4xxx_recover_adapter - recovers adapter after a fatal error | 1031 | * qla4xxx_recover_adapter - recovers adapter after a fatal error |
902 | * @ha: Pointer to host adapter structure. | 1032 | * @ha: Pointer to host adapter structure. |
903 | * @renew_ddb_list: Indicates what to do with the adapter's ddb list | ||
904 | * | ||
905 | * renew_ddb_list value can be 0=preserve ddb list, 1=destroy and rebuild | ||
906 | * ddb list. | ||
907 | **/ | 1033 | **/ |
908 | static int qla4xxx_recover_adapter(struct scsi_qla_host *ha, | 1034 | static int qla4xxx_recover_adapter(struct scsi_qla_host *ha) |
909 | uint8_t renew_ddb_list) | ||
910 | { | 1035 | { |
911 | int status; | 1036 | int status = QLA_ERROR; |
1037 | uint8_t reset_chip = 0; | ||
912 | 1038 | ||
913 | /* Stall incoming I/O until we are done */ | 1039 | /* Stall incoming I/O until we are done */ |
1040 | scsi_block_requests(ha->host); | ||
914 | clear_bit(AF_ONLINE, &ha->flags); | 1041 | clear_bit(AF_ONLINE, &ha->flags); |
915 | 1042 | ||
916 | DEBUG2(printk("scsi%ld: %s calling qla4xxx_cmd_wait\n", ha->host_no, | 1043 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s: adapter OFFLINE\n", __func__)); |
917 | __func__)); | ||
918 | 1044 | ||
919 | /* Wait for outstanding commands to complete. | 1045 | set_bit(DPC_RESET_ACTIVE, &ha->dpc_flags); |
920 | * Stalls the driver for max 30 secs | ||
921 | */ | ||
922 | status = qla4xxx_cmd_wait(ha); | ||
923 | 1046 | ||
924 | qla4xxx_disable_intrs(ha); | 1047 | if (test_bit(DPC_RESET_HA, &ha->dpc_flags)) |
1048 | reset_chip = 1; | ||
925 | 1049 | ||
926 | /* Flush any pending ddb changed AENs */ | 1050 | /* For the DPC_RESET_HA_INTR case (ISP-4xxx specific) |
927 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); | 1051 | * do not reset adapter, jump to initialize_adapter */ |
1052 | if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) { | ||
1053 | status = QLA_SUCCESS; | ||
1054 | goto recover_ha_init_adapter; | ||
1055 | } | ||
928 | 1056 | ||
929 | qla4xxx_flush_active_srbs(ha); | 1057 | /* For the ISP-82xx adapter, issue a stop_firmware if invoked |
1058 | * from eh_host_reset or ioctl module */ | ||
1059 | if (is_qla8022(ha) && !reset_chip && | ||
1060 | test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags)) { | ||
1061 | |||
1062 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
1063 | "scsi%ld: %s - Performing stop_firmware...\n", | ||
1064 | ha->host_no, __func__)); | ||
1065 | status = ha->isp_ops->reset_firmware(ha); | ||
1066 | if (status == QLA_SUCCESS) { | ||
1067 | qla4xxx_cmd_wait(ha); | ||
1068 | ha->isp_ops->disable_intrs(ha); | ||
1069 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); | ||
1070 | qla4xxx_abort_active_cmds(ha, DID_RESET << 16); | ||
1071 | } else { | ||
1072 | /* If the stop_firmware fails then | ||
1073 | * reset the entire chip */ | ||
1074 | reset_chip = 1; | ||
1075 | clear_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags); | ||
1076 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | ||
1077 | } | ||
1078 | } | ||
930 | 1079 | ||
931 | /* Reset the firmware. If successful, function | 1080 | /* Issue full chip reset if recovering from a catastrophic error, |
932 | * returns with ISP interrupts enabled. | 1081 | * or if stop_firmware fails for ISP-82xx. |
933 | */ | 1082 | * This is the default case for ISP-4xxx */ |
934 | DEBUG2(printk("scsi%ld: %s - Performing soft reset..\n", | 1083 | if (!is_qla8022(ha) || reset_chip) { |
935 | ha->host_no, __func__)); | 1084 | qla4xxx_cmd_wait(ha); |
936 | if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) | 1085 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); |
937 | status = qla4xxx_soft_reset(ha); | 1086 | qla4xxx_abort_active_cmds(ha, DID_RESET << 16); |
938 | else | 1087 | DEBUG2(ql4_printk(KERN_INFO, ha, |
939 | status = QLA_ERROR; | 1088 | "scsi%ld: %s - Performing chip reset..\n", |
1089 | ha->host_no, __func__)); | ||
1090 | status = ha->isp_ops->reset_chip(ha); | ||
1091 | } | ||
940 | 1092 | ||
941 | /* Flush any pending ddb changed AENs */ | 1093 | /* Flush any pending ddb changed AENs */ |
942 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); | 1094 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); |
943 | 1095 | ||
944 | /* Re-initialize firmware. If successful, function returns | 1096 | recover_ha_init_adapter: |
945 | * with ISP interrupts enabled */ | 1097 | /* Upon successful firmware/chip reset, re-initialize the adapter */ |
946 | if (status == QLA_SUCCESS) { | 1098 | if (status == QLA_SUCCESS) { |
947 | DEBUG2(printk("scsi%ld: %s - Initializing adapter..\n", | 1099 | /* For ISP-4xxx, force function 1 to always initialize |
948 | ha->host_no, __func__)); | 1100 | * before function 3 to prevent both funcions from |
949 | 1101 | * stepping on top of the other */ | |
950 | /* If successful, AF_ONLINE flag set in | 1102 | if (!is_qla8022(ha) && (ha->mac_index == 3)) |
951 | * qla4xxx_initialize_adapter */ | 1103 | ssleep(6); |
952 | status = qla4xxx_initialize_adapter(ha, renew_ddb_list); | 1104 | |
1105 | /* NOTE: AF_ONLINE flag set upon successful completion of | ||
1106 | * qla4xxx_initialize_adapter */ | ||
1107 | status = qla4xxx_initialize_adapter(ha, PRESERVE_DDB_LIST); | ||
953 | } | 1108 | } |
954 | 1109 | ||
955 | /* Failed adapter initialization? | 1110 | /* Retry failed adapter initialization, if necessary |
956 | * Retry reset_ha only if invoked via DPC (DPC_RESET_HA) */ | 1111 | * Do not retry initialize_adapter for RESET_HA_INTR (ISP-4xxx specific) |
957 | if ((test_bit(AF_ONLINE, &ha->flags) == 0) && | 1112 | * case to prevent ping-pong resets between functions */ |
958 | (test_bit(DPC_RESET_HA, &ha->dpc_flags))) { | 1113 | if (!test_bit(AF_ONLINE, &ha->flags) && |
1114 | !test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) { | ||
959 | /* Adapter initialization failed, see if we can retry | 1115 | /* Adapter initialization failed, see if we can retry |
960 | * resetting the ha */ | 1116 | * resetting the ha. |
1117 | * Since we don't want to block the DPC for too long | ||
1118 | * with multiple resets in the same thread, | ||
1119 | * utilize DPC to retry */ | ||
961 | if (!test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags)) { | 1120 | if (!test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags)) { |
962 | ha->retry_reset_ha_cnt = MAX_RESET_HA_RETRIES; | 1121 | ha->retry_reset_ha_cnt = MAX_RESET_HA_RETRIES; |
963 | DEBUG2(printk("scsi%ld: recover adapter - retrying " | 1122 | DEBUG2(printk("scsi%ld: recover adapter - retrying " |
@@ -982,29 +1141,43 @@ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha, | |||
982 | DEBUG2(printk("scsi%ld: recover adapter " | 1141 | DEBUG2(printk("scsi%ld: recover adapter " |
983 | "failed - board disabled\n", | 1142 | "failed - board disabled\n", |
984 | ha->host_no)); | 1143 | ha->host_no)); |
985 | qla4xxx_flush_active_srbs(ha); | 1144 | qla4xxx_dead_adapter_cleanup(ha); |
986 | clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags); | 1145 | clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags); |
987 | clear_bit(DPC_RESET_HA, &ha->dpc_flags); | 1146 | clear_bit(DPC_RESET_HA, &ha->dpc_flags); |
988 | clear_bit(DPC_RESET_HA_DESTROY_DDB_LIST, | 1147 | clear_bit(DPC_RESET_HA_FW_CONTEXT, |
989 | &ha->dpc_flags); | 1148 | &ha->dpc_flags); |
990 | status = QLA_ERROR; | 1149 | status = QLA_ERROR; |
991 | } | 1150 | } |
992 | } | 1151 | } |
993 | } else { | 1152 | } else { |
994 | clear_bit(DPC_RESET_HA, &ha->dpc_flags); | 1153 | clear_bit(DPC_RESET_HA, &ha->dpc_flags); |
995 | clear_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags); | 1154 | clear_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags); |
996 | clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags); | 1155 | clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags); |
997 | } | 1156 | } |
998 | 1157 | ||
999 | ha->adapter_error_count++; | 1158 | ha->adapter_error_count++; |
1000 | 1159 | ||
1001 | if (status == QLA_SUCCESS) | 1160 | if (test_bit(AF_ONLINE, &ha->flags)) |
1002 | qla4xxx_enable_intrs(ha); | 1161 | ha->isp_ops->enable_intrs(ha); |
1162 | |||
1163 | scsi_unblock_requests(ha->host); | ||
1164 | |||
1165 | clear_bit(DPC_RESET_ACTIVE, &ha->dpc_flags); | ||
1166 | DEBUG2(printk("scsi%ld: recover adapter: %s\n", ha->host_no, | ||
1167 | status == QLA_ERROR ? "FAILED" : "SUCCEDED")); | ||
1003 | 1168 | ||
1004 | DEBUG2(printk("scsi%ld: recover adapter .. DONE\n", ha->host_no)); | ||
1005 | return status; | 1169 | return status; |
1006 | } | 1170 | } |
1007 | 1171 | ||
1172 | void qla4xxx_wake_dpc(struct scsi_qla_host *ha) | ||
1173 | { | ||
1174 | if (ha->dpc_thread && | ||
1175 | !test_bit(AF_DPC_SCHEDULED, &ha->flags)) { | ||
1176 | set_bit(AF_DPC_SCHEDULED, &ha->flags); | ||
1177 | queue_work(ha->dpc_thread, &ha->dpc_work); | ||
1178 | } | ||
1179 | } | ||
1180 | |||
1008 | /** | 1181 | /** |
1009 | * qla4xxx_do_dpc - dpc routine | 1182 | * qla4xxx_do_dpc - dpc routine |
1010 | * @data: in our case pointer to adapter structure | 1183 | * @data: in our case pointer to adapter structure |
@@ -1024,21 +1197,47 @@ static void qla4xxx_do_dpc(struct work_struct *work) | |||
1024 | int status = QLA_ERROR; | 1197 | int status = QLA_ERROR; |
1025 | 1198 | ||
1026 | DEBUG2(printk("scsi%ld: %s: DPC handler waking up." | 1199 | DEBUG2(printk("scsi%ld: %s: DPC handler waking up." |
1027 | "flags = 0x%08lx, dpc_flags = 0x%08lx ctrl_stat = 0x%08x\n", | 1200 | "flags = 0x%08lx, dpc_flags = 0x%08lx\n", |
1028 | ha->host_no, __func__, ha->flags, ha->dpc_flags, | 1201 | ha->host_no, __func__, ha->flags, ha->dpc_flags)) |
1029 | readw(&ha->reg->ctrl_status))); | ||
1030 | 1202 | ||
1031 | /* Initialization not yet finished. Don't do anything yet. */ | 1203 | /* Initialization not yet finished. Don't do anything yet. */ |
1032 | if (!test_bit(AF_INIT_DONE, &ha->flags)) | 1204 | if (!test_bit(AF_INIT_DONE, &ha->flags)) |
1033 | return; | 1205 | return; |
1034 | 1206 | ||
1035 | if (adapter_up(ha) || | 1207 | /* HBA is in the process of being permanently disabled. |
1036 | test_bit(DPC_RESET_HA, &ha->dpc_flags) || | 1208 | * Don't process anything */ |
1209 | if (test_bit(AF_HBA_GOING_AWAY, &ha->flags)) | ||
1210 | return; | ||
1211 | |||
1212 | if (is_qla8022(ha)) { | ||
1213 | if (test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags)) { | ||
1214 | qla4_8xxx_idc_lock(ha); | ||
1215 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, | ||
1216 | QLA82XX_DEV_FAILED); | ||
1217 | qla4_8xxx_idc_unlock(ha); | ||
1218 | ql4_printk(KERN_INFO, ha, "HW State: FAILED\n"); | ||
1219 | qla4_8xxx_device_state_handler(ha); | ||
1220 | } | ||
1221 | if (test_and_clear_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags)) { | ||
1222 | qla4_8xxx_need_qsnt_handler(ha); | ||
1223 | } | ||
1224 | } | ||
1225 | |||
1226 | if (!test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) && | ||
1227 | (test_bit(DPC_RESET_HA, &ha->dpc_flags) || | ||
1037 | test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) || | 1228 | test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) || |
1038 | test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags)) { | 1229 | test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags))) { |
1039 | if (test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags) || | 1230 | if (ql4xdontresethba) { |
1040 | test_bit(DPC_RESET_HA, &ha->dpc_flags)) | 1231 | DEBUG2(printk("scsi%ld: %s: Don't Reset HBA\n", |
1041 | qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST); | 1232 | ha->host_no, __func__)); |
1233 | clear_bit(DPC_RESET_HA, &ha->dpc_flags); | ||
1234 | clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags); | ||
1235 | clear_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags); | ||
1236 | goto dpc_post_reset_ha; | ||
1237 | } | ||
1238 | if (test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags) || | ||
1239 | test_bit(DPC_RESET_HA, &ha->dpc_flags)) | ||
1240 | qla4xxx_recover_adapter(ha); | ||
1042 | 1241 | ||
1043 | if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) { | 1242 | if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) { |
1044 | uint8_t wait_time = RESET_INTR_TOV; | 1243 | uint8_t wait_time = RESET_INTR_TOV; |
@@ -1053,18 +1252,18 @@ static void qla4xxx_do_dpc(struct work_struct *work) | |||
1053 | DEBUG2(printk("scsi%ld: %s: SR|FSR " | 1252 | DEBUG2(printk("scsi%ld: %s: SR|FSR " |
1054 | "bit not cleared-- resetting\n", | 1253 | "bit not cleared-- resetting\n", |
1055 | ha->host_no, __func__)); | 1254 | ha->host_no, __func__)); |
1056 | qla4xxx_flush_active_srbs(ha); | 1255 | qla4xxx_abort_active_cmds(ha, DID_RESET << 16); |
1057 | if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) { | 1256 | if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) { |
1058 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); | 1257 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); |
1059 | status = qla4xxx_initialize_adapter(ha, | 1258 | status = qla4xxx_recover_adapter(ha); |
1060 | PRESERVE_DDB_LIST); | ||
1061 | } | 1259 | } |
1062 | clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags); | 1260 | clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags); |
1063 | if (status == QLA_SUCCESS) | 1261 | if (status == QLA_SUCCESS) |
1064 | qla4xxx_enable_intrs(ha); | 1262 | ha->isp_ops->enable_intrs(ha); |
1065 | } | 1263 | } |
1066 | } | 1264 | } |
1067 | 1265 | ||
1266 | dpc_post_reset_ha: | ||
1068 | /* ---- process AEN? --- */ | 1267 | /* ---- process AEN? --- */ |
1069 | if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags)) | 1268 | if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags)) |
1070 | qla4xxx_process_aen(ha, PROCESS_ALL_AENS); | 1269 | qla4xxx_process_aen(ha, PROCESS_ALL_AENS); |
@@ -1104,11 +1303,9 @@ static void qla4xxx_do_dpc(struct work_struct *work) | |||
1104 | DDB_STATE_ONLINE); | 1303 | DDB_STATE_ONLINE); |
1105 | dev_info(&ha->pdev->dev, | 1304 | dev_info(&ha->pdev->dev, |
1106 | "scsi%ld: %s: ddb[%d]" | 1305 | "scsi%ld: %s: ddb[%d]" |
1107 | " os[%d] marked" | 1306 | " marked ONLINE\n", |
1108 | " ONLINE\n", | ||
1109 | ha->host_no, __func__, | 1307 | ha->host_no, __func__, |
1110 | ddb_entry->fw_ddb_index, | 1308 | ddb_entry->fw_ddb_index); |
1111 | ddb_entry->os_target_id); | ||
1112 | 1309 | ||
1113 | iscsi_unblock_session( | 1310 | iscsi_unblock_session( |
1114 | ddb_entry->sess); | 1311 | ddb_entry->sess); |
@@ -1144,6 +1341,7 @@ static void qla4xxx_do_dpc(struct work_struct *work) | |||
1144 | } | 1341 | } |
1145 | } | 1342 | } |
1146 | } | 1343 | } |
1344 | clear_bit(AF_DPC_SCHEDULED, &ha->flags); | ||
1147 | } | 1345 | } |
1148 | 1346 | ||
1149 | /** | 1347 | /** |
@@ -1155,30 +1353,99 @@ static void qla4xxx_free_adapter(struct scsi_qla_host *ha) | |||
1155 | 1353 | ||
1156 | if (test_bit(AF_INTERRUPTS_ON, &ha->flags)) { | 1354 | if (test_bit(AF_INTERRUPTS_ON, &ha->flags)) { |
1157 | /* Turn-off interrupts on the card. */ | 1355 | /* Turn-off interrupts on the card. */ |
1158 | qla4xxx_disable_intrs(ha); | 1356 | ha->isp_ops->disable_intrs(ha); |
1159 | } | 1357 | } |
1160 | 1358 | ||
1359 | /* Remove timer thread, if present */ | ||
1360 | if (ha->timer_active) | ||
1361 | qla4xxx_stop_timer(ha); | ||
1362 | |||
1161 | /* Kill the kernel thread for this host */ | 1363 | /* Kill the kernel thread for this host */ |
1162 | if (ha->dpc_thread) | 1364 | if (ha->dpc_thread) |
1163 | destroy_workqueue(ha->dpc_thread); | 1365 | destroy_workqueue(ha->dpc_thread); |
1164 | 1366 | ||
1165 | /* Issue Soft Reset to put firmware in unknown state */ | 1367 | /* Put firmware in known state */ |
1166 | if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) | 1368 | ha->isp_ops->reset_firmware(ha); |
1167 | qla4xxx_hw_reset(ha); | ||
1168 | 1369 | ||
1169 | /* Remove timer thread, if present */ | 1370 | if (is_qla8022(ha)) { |
1170 | if (ha->timer_active) | 1371 | qla4_8xxx_idc_lock(ha); |
1171 | qla4xxx_stop_timer(ha); | 1372 | qla4_8xxx_clear_drv_active(ha); |
1373 | qla4_8xxx_idc_unlock(ha); | ||
1374 | } | ||
1172 | 1375 | ||
1173 | /* Detach interrupts */ | 1376 | /* Detach interrupts */ |
1174 | if (test_and_clear_bit(AF_IRQ_ATTACHED, &ha->flags)) | 1377 | if (test_and_clear_bit(AF_IRQ_ATTACHED, &ha->flags)) |
1175 | free_irq(ha->pdev->irq, ha); | 1378 | qla4xxx_free_irqs(ha); |
1176 | 1379 | ||
1177 | /* free extra memory */ | 1380 | /* free extra memory */ |
1178 | qla4xxx_mem_free(ha); | 1381 | qla4xxx_mem_free(ha); |
1382 | } | ||
1383 | |||
1384 | int qla4_8xxx_iospace_config(struct scsi_qla_host *ha) | ||
1385 | { | ||
1386 | int status = 0; | ||
1387 | uint8_t revision_id; | ||
1388 | unsigned long mem_base, mem_len, db_base, db_len; | ||
1389 | struct pci_dev *pdev = ha->pdev; | ||
1390 | |||
1391 | status = pci_request_regions(pdev, DRIVER_NAME); | ||
1392 | if (status) { | ||
1393 | printk(KERN_WARNING | ||
1394 | "scsi(%ld) Failed to reserve PIO regions (%s) " | ||
1395 | "status=%d\n", ha->host_no, pci_name(pdev), status); | ||
1396 | goto iospace_error_exit; | ||
1397 | } | ||
1398 | |||
1399 | pci_read_config_byte(pdev, PCI_REVISION_ID, &revision_id); | ||
1400 | DEBUG2(printk(KERN_INFO "%s: revision-id=%d\n", | ||
1401 | __func__, revision_id)); | ||
1402 | ha->revision_id = revision_id; | ||
1179 | 1403 | ||
1180 | pci_disable_device(ha->pdev); | 1404 | /* remap phys address */ |
1405 | mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */ | ||
1406 | mem_len = pci_resource_len(pdev, 0); | ||
1407 | DEBUG2(printk(KERN_INFO "%s: ioremap from %lx a size of %lx\n", | ||
1408 | __func__, mem_base, mem_len)); | ||
1181 | 1409 | ||
1410 | /* mapping of pcibase pointer */ | ||
1411 | ha->nx_pcibase = (unsigned long)ioremap(mem_base, mem_len); | ||
1412 | if (!ha->nx_pcibase) { | ||
1413 | printk(KERN_ERR | ||
1414 | "cannot remap MMIO (%s), aborting\n", pci_name(pdev)); | ||
1415 | pci_release_regions(ha->pdev); | ||
1416 | goto iospace_error_exit; | ||
1417 | } | ||
1418 | |||
1419 | /* Mapping of IO base pointer, door bell read and write pointer */ | ||
1420 | |||
1421 | /* mapping of IO base pointer */ | ||
1422 | ha->qla4_8xxx_reg = | ||
1423 | (struct device_reg_82xx __iomem *)((uint8_t *)ha->nx_pcibase + | ||
1424 | 0xbc000 + (ha->pdev->devfn << 11)); | ||
1425 | |||
1426 | db_base = pci_resource_start(pdev, 4); /* doorbell is on bar 4 */ | ||
1427 | db_len = pci_resource_len(pdev, 4); | ||
1428 | |||
1429 | /* mapping of doorbell write pointer */ | ||
1430 | ha->nx_db_wr_ptr = (unsigned long)ioremap(db_base + | ||
1431 | (ha->pdev->devfn << 12), 4); | ||
1432 | if (!ha->nx_db_wr_ptr) { | ||
1433 | printk(KERN_ERR | ||
1434 | "cannot remap MMIO doorbell-write (%s), aborting\n", | ||
1435 | pci_name(pdev)); | ||
1436 | goto iospace_error_exit; | ||
1437 | } | ||
1438 | /* mapping of doorbell read pointer */ | ||
1439 | ha->nx_db_rd_ptr = (uint8_t *) ha->nx_pcibase + (512 * 1024) + | ||
1440 | (ha->pdev->devfn * 8); | ||
1441 | if (!ha->nx_db_rd_ptr) | ||
1442 | printk(KERN_ERR | ||
1443 | "cannot remap MMIO doorbell-read (%s), aborting\n", | ||
1444 | pci_name(pdev)); | ||
1445 | return 0; | ||
1446 | |||
1447 | iospace_error_exit: | ||
1448 | return -ENOMEM; | ||
1182 | } | 1449 | } |
1183 | 1450 | ||
1184 | /*** | 1451 | /*** |
@@ -1188,7 +1455,7 @@ static void qla4xxx_free_adapter(struct scsi_qla_host *ha) | |||
1188 | * This routines maps HBA's registers from the pci address space | 1455 | * This routines maps HBA's registers from the pci address space |
1189 | * into the kernel virtual address space for memory mapped i/o. | 1456 | * into the kernel virtual address space for memory mapped i/o. |
1190 | **/ | 1457 | **/ |
1191 | static int qla4xxx_iospace_config(struct scsi_qla_host *ha) | 1458 | int qla4xxx_iospace_config(struct scsi_qla_host *ha) |
1192 | { | 1459 | { |
1193 | unsigned long pio, pio_len, pio_flags; | 1460 | unsigned long pio, pio_len, pio_flags; |
1194 | unsigned long mmio, mmio_len, mmio_flags; | 1461 | unsigned long mmio, mmio_len, mmio_flags; |
@@ -1247,6 +1514,60 @@ iospace_error_exit: | |||
1247 | return -ENOMEM; | 1514 | return -ENOMEM; |
1248 | } | 1515 | } |
1249 | 1516 | ||
1517 | static struct isp_operations qla4xxx_isp_ops = { | ||
1518 | .iospace_config = qla4xxx_iospace_config, | ||
1519 | .pci_config = qla4xxx_pci_config, | ||
1520 | .disable_intrs = qla4xxx_disable_intrs, | ||
1521 | .enable_intrs = qla4xxx_enable_intrs, | ||
1522 | .start_firmware = qla4xxx_start_firmware, | ||
1523 | .intr_handler = qla4xxx_intr_handler, | ||
1524 | .interrupt_service_routine = qla4xxx_interrupt_service_routine, | ||
1525 | .reset_chip = qla4xxx_soft_reset, | ||
1526 | .reset_firmware = qla4xxx_hw_reset, | ||
1527 | .queue_iocb = qla4xxx_queue_iocb, | ||
1528 | .complete_iocb = qla4xxx_complete_iocb, | ||
1529 | .rd_shdw_req_q_out = qla4xxx_rd_shdw_req_q_out, | ||
1530 | .rd_shdw_rsp_q_in = qla4xxx_rd_shdw_rsp_q_in, | ||
1531 | .get_sys_info = qla4xxx_get_sys_info, | ||
1532 | }; | ||
1533 | |||
1534 | static struct isp_operations qla4_8xxx_isp_ops = { | ||
1535 | .iospace_config = qla4_8xxx_iospace_config, | ||
1536 | .pci_config = qla4_8xxx_pci_config, | ||
1537 | .disable_intrs = qla4_8xxx_disable_intrs, | ||
1538 | .enable_intrs = qla4_8xxx_enable_intrs, | ||
1539 | .start_firmware = qla4_8xxx_load_risc, | ||
1540 | .intr_handler = qla4_8xxx_intr_handler, | ||
1541 | .interrupt_service_routine = qla4_8xxx_interrupt_service_routine, | ||
1542 | .reset_chip = qla4_8xxx_isp_reset, | ||
1543 | .reset_firmware = qla4_8xxx_stop_firmware, | ||
1544 | .queue_iocb = qla4_8xxx_queue_iocb, | ||
1545 | .complete_iocb = qla4_8xxx_complete_iocb, | ||
1546 | .rd_shdw_req_q_out = qla4_8xxx_rd_shdw_req_q_out, | ||
1547 | .rd_shdw_rsp_q_in = qla4_8xxx_rd_shdw_rsp_q_in, | ||
1548 | .get_sys_info = qla4_8xxx_get_sys_info, | ||
1549 | }; | ||
1550 | |||
1551 | uint16_t qla4xxx_rd_shdw_req_q_out(struct scsi_qla_host *ha) | ||
1552 | { | ||
1553 | return (uint16_t)le32_to_cpu(ha->shadow_regs->req_q_out); | ||
1554 | } | ||
1555 | |||
1556 | uint16_t qla4_8xxx_rd_shdw_req_q_out(struct scsi_qla_host *ha) | ||
1557 | { | ||
1558 | return (uint16_t)le32_to_cpu(readl(&ha->qla4_8xxx_reg->req_q_out)); | ||
1559 | } | ||
1560 | |||
1561 | uint16_t qla4xxx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha) | ||
1562 | { | ||
1563 | return (uint16_t)le32_to_cpu(ha->shadow_regs->rsp_q_in); | ||
1564 | } | ||
1565 | |||
1566 | uint16_t qla4_8xxx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha) | ||
1567 | { | ||
1568 | return (uint16_t)le32_to_cpu(readl(&ha->qla4_8xxx_reg->rsp_q_in)); | ||
1569 | } | ||
1570 | |||
1250 | /** | 1571 | /** |
1251 | * qla4xxx_probe_adapter - callback function to probe HBA | 1572 | * qla4xxx_probe_adapter - callback function to probe HBA |
1252 | * @pdev: pointer to pci_dev structure | 1573 | * @pdev: pointer to pci_dev structure |
@@ -1264,6 +1585,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
1264 | struct scsi_qla_host *ha; | 1585 | struct scsi_qla_host *ha; |
1265 | uint8_t init_retry_count = 0; | 1586 | uint8_t init_retry_count = 0; |
1266 | char buf[34]; | 1587 | char buf[34]; |
1588 | struct qla4_8xxx_legacy_intr_set *nx_legacy_intr; | ||
1267 | 1589 | ||
1268 | if (pci_enable_device(pdev)) | 1590 | if (pci_enable_device(pdev)) |
1269 | return -1; | 1591 | return -1; |
@@ -1284,10 +1606,28 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
1284 | ha->host = host; | 1606 | ha->host = host; |
1285 | ha->host_no = host->host_no; | 1607 | ha->host_no = host->host_no; |
1286 | 1608 | ||
1609 | /* Setup Runtime configurable options */ | ||
1610 | if (is_qla8022(ha)) { | ||
1611 | ha->isp_ops = &qla4_8xxx_isp_ops; | ||
1612 | rwlock_init(&ha->hw_lock); | ||
1613 | ha->qdr_sn_window = -1; | ||
1614 | ha->ddr_mn_window = -1; | ||
1615 | ha->curr_window = 255; | ||
1616 | ha->func_num = PCI_FUNC(ha->pdev->devfn); | ||
1617 | nx_legacy_intr = &legacy_intr[ha->func_num]; | ||
1618 | ha->nx_legacy_intr.int_vec_bit = nx_legacy_intr->int_vec_bit; | ||
1619 | ha->nx_legacy_intr.tgt_status_reg = | ||
1620 | nx_legacy_intr->tgt_status_reg; | ||
1621 | ha->nx_legacy_intr.tgt_mask_reg = nx_legacy_intr->tgt_mask_reg; | ||
1622 | ha->nx_legacy_intr.pci_int_reg = nx_legacy_intr->pci_int_reg; | ||
1623 | } else { | ||
1624 | ha->isp_ops = &qla4xxx_isp_ops; | ||
1625 | } | ||
1626 | |||
1287 | /* Configure PCI I/O space. */ | 1627 | /* Configure PCI I/O space. */ |
1288 | ret = qla4xxx_iospace_config(ha); | 1628 | ret = ha->isp_ops->iospace_config(ha); |
1289 | if (ret) | 1629 | if (ret) |
1290 | goto probe_failed; | 1630 | goto probe_failed_ioconfig; |
1291 | 1631 | ||
1292 | dev_info(&ha->pdev->dev, "Found an ISP%04x, irq %d, iobase 0x%p\n", | 1632 | dev_info(&ha->pdev->dev, "Found an ISP%04x, irq %d, iobase 0x%p\n", |
1293 | pdev->device, pdev->irq, ha->reg); | 1633 | pdev->device, pdev->irq, ha->reg); |
@@ -1299,6 +1639,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
1299 | INIT_LIST_HEAD(&ha->free_srb_q); | 1639 | INIT_LIST_HEAD(&ha->free_srb_q); |
1300 | 1640 | ||
1301 | mutex_init(&ha->mbox_sem); | 1641 | mutex_init(&ha->mbox_sem); |
1642 | init_completion(&ha->mbx_intr_comp); | ||
1302 | 1643 | ||
1303 | spin_lock_init(&ha->hardware_lock); | 1644 | spin_lock_init(&ha->hardware_lock); |
1304 | 1645 | ||
@@ -1311,19 +1652,27 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
1311 | goto probe_failed; | 1652 | goto probe_failed; |
1312 | } | 1653 | } |
1313 | 1654 | ||
1655 | if (is_qla8022(ha)) | ||
1656 | (void) qla4_8xxx_get_flash_info(ha); | ||
1657 | |||
1314 | /* | 1658 | /* |
1315 | * Initialize the Host adapter request/response queues and | 1659 | * Initialize the Host adapter request/response queues and |
1316 | * firmware | 1660 | * firmware |
1317 | * NOTE: interrupts enabled upon successful completion | 1661 | * NOTE: interrupts enabled upon successful completion |
1318 | */ | 1662 | */ |
1319 | status = qla4xxx_initialize_adapter(ha, REBUILD_DDB_LIST); | 1663 | status = qla4xxx_initialize_adapter(ha, REBUILD_DDB_LIST); |
1320 | while (status == QLA_ERROR && init_retry_count++ < MAX_INIT_RETRIES) { | 1664 | while ((!test_bit(AF_ONLINE, &ha->flags)) && |
1665 | init_retry_count++ < MAX_INIT_RETRIES) { | ||
1321 | DEBUG2(printk("scsi: %s: retrying adapter initialization " | 1666 | DEBUG2(printk("scsi: %s: retrying adapter initialization " |
1322 | "(%d)\n", __func__, init_retry_count)); | 1667 | "(%d)\n", __func__, init_retry_count)); |
1323 | qla4xxx_soft_reset(ha); | 1668 | |
1669 | if (ha->isp_ops->reset_chip(ha) == QLA_ERROR) | ||
1670 | continue; | ||
1671 | |||
1324 | status = qla4xxx_initialize_adapter(ha, REBUILD_DDB_LIST); | 1672 | status = qla4xxx_initialize_adapter(ha, REBUILD_DDB_LIST); |
1325 | } | 1673 | } |
1326 | if (status == QLA_ERROR) { | 1674 | |
1675 | if (!test_bit(AF_ONLINE, &ha->flags)) { | ||
1327 | dev_warn(&ha->pdev->dev, "Failed to initialize adapter\n"); | 1676 | dev_warn(&ha->pdev->dev, "Failed to initialize adapter\n"); |
1328 | 1677 | ||
1329 | ret = -ENODEV; | 1678 | ret = -ENODEV; |
@@ -1356,18 +1705,21 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
1356 | } | 1705 | } |
1357 | INIT_WORK(&ha->dpc_work, qla4xxx_do_dpc); | 1706 | INIT_WORK(&ha->dpc_work, qla4xxx_do_dpc); |
1358 | 1707 | ||
1359 | ret = request_irq(pdev->irq, qla4xxx_intr_handler, | 1708 | /* For ISP-82XX, request_irqs is called in qla4_8xxx_load_risc |
1360 | IRQF_DISABLED | IRQF_SHARED, "qla4xxx", ha); | 1709 | * (which is called indirectly by qla4xxx_initialize_adapter), |
1361 | if (ret) { | 1710 | * so that irqs will be registered after crbinit but before |
1362 | dev_warn(&ha->pdev->dev, "Failed to reserve interrupt %d" | 1711 | * mbx_intr_enable. |
1363 | " already in use.\n", pdev->irq); | 1712 | */ |
1364 | goto probe_failed; | 1713 | if (!is_qla8022(ha)) { |
1714 | ret = qla4xxx_request_irqs(ha); | ||
1715 | if (ret) { | ||
1716 | ql4_printk(KERN_WARNING, ha, "Failed to reserve " | ||
1717 | "interrupt %d already in use.\n", pdev->irq); | ||
1718 | goto probe_failed; | ||
1719 | } | ||
1365 | } | 1720 | } |
1366 | set_bit(AF_IRQ_ATTACHED, &ha->flags); | ||
1367 | host->irq = pdev->irq; | ||
1368 | DEBUG(printk("scsi%d: irq %d attached\n", ha->host_no, ha->pdev->irq)); | ||
1369 | 1721 | ||
1370 | qla4xxx_enable_intrs(ha); | 1722 | ha->isp_ops->enable_intrs(ha); |
1371 | 1723 | ||
1372 | /* Start timer thread. */ | 1724 | /* Start timer thread. */ |
1373 | qla4xxx_start_timer(ha, qla4xxx_timer, 1); | 1725 | qla4xxx_start_timer(ha, qla4xxx_timer, 1); |
@@ -1391,6 +1743,8 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
1391 | 1743 | ||
1392 | probe_failed: | 1744 | probe_failed: |
1393 | qla4xxx_free_adapter(ha); | 1745 | qla4xxx_free_adapter(ha); |
1746 | |||
1747 | probe_failed_ioconfig: | ||
1394 | scsi_host_put(ha->host); | 1748 | scsi_host_put(ha->host); |
1395 | 1749 | ||
1396 | probe_disable_device: | 1750 | probe_disable_device: |
@@ -1409,10 +1763,7 @@ static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev) | |||
1409 | 1763 | ||
1410 | ha = pci_get_drvdata(pdev); | 1764 | ha = pci_get_drvdata(pdev); |
1411 | 1765 | ||
1412 | qla4xxx_disable_intrs(ha); | 1766 | set_bit(AF_HBA_GOING_AWAY, &ha->flags); |
1413 | |||
1414 | while (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) | ||
1415 | ssleep(1); | ||
1416 | 1767 | ||
1417 | /* remove devs from iscsi_sessions to scsi_devices */ | 1768 | /* remove devs from iscsi_sessions to scsi_devices */ |
1418 | qla4xxx_free_ddb_list(ha); | 1769 | qla4xxx_free_ddb_list(ha); |
@@ -1423,6 +1774,7 @@ static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev) | |||
1423 | 1774 | ||
1424 | scsi_host_put(ha->host); | 1775 | scsi_host_put(ha->host); |
1425 | 1776 | ||
1777 | pci_disable_device(pdev); | ||
1426 | pci_set_drvdata(pdev, NULL); | 1778 | pci_set_drvdata(pdev, NULL); |
1427 | } | 1779 | } |
1428 | 1780 | ||
@@ -1479,7 +1831,8 @@ static void qla4xxx_slave_destroy(struct scsi_device *sdev) | |||
1479 | * | 1831 | * |
1480 | * This routine removes and returns the srb at the specified index | 1832 | * This routine removes and returns the srb at the specified index |
1481 | **/ | 1833 | **/ |
1482 | struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha, uint32_t index) | 1834 | struct srb *qla4xxx_del_from_active_array(struct scsi_qla_host *ha, |
1835 | uint32_t index) | ||
1483 | { | 1836 | { |
1484 | struct srb *srb = NULL; | 1837 | struct srb *srb = NULL; |
1485 | struct scsi_cmnd *cmd = NULL; | 1838 | struct scsi_cmnd *cmd = NULL; |
@@ -1769,6 +2122,12 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd) | |||
1769 | 2122 | ||
1770 | ha = (struct scsi_qla_host *) cmd->device->host->hostdata; | 2123 | ha = (struct scsi_qla_host *) cmd->device->host->hostdata; |
1771 | 2124 | ||
2125 | if (ql4xdontresethba) { | ||
2126 | DEBUG2(printk("scsi%ld: %s: Don't Reset HBA\n", | ||
2127 | ha->host_no, __func__)); | ||
2128 | return FAILED; | ||
2129 | } | ||
2130 | |||
1772 | dev_info(&ha->pdev->dev, | 2131 | dev_info(&ha->pdev->dev, |
1773 | "scsi(%ld:%d:%d:%d): HOST RESET ISSUED.\n", ha->host_no, | 2132 | "scsi(%ld:%d:%d:%d): HOST RESET ISSUED.\n", ha->host_no, |
1774 | cmd->device->channel, cmd->device->id, cmd->device->lun); | 2133 | cmd->device->channel, cmd->device->id, cmd->device->lun); |
@@ -1781,11 +2140,14 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd) | |||
1781 | return FAILED; | 2140 | return FAILED; |
1782 | } | 2141 | } |
1783 | 2142 | ||
1784 | /* make sure the dpc thread is stopped while we reset the hba */ | 2143 | if (!test_bit(DPC_RESET_HA, &ha->dpc_flags)) { |
1785 | clear_bit(AF_ONLINE, &ha->flags); | 2144 | if (is_qla8022(ha)) |
1786 | flush_workqueue(ha->dpc_thread); | 2145 | set_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags); |
2146 | else | ||
2147 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | ||
2148 | } | ||
1787 | 2149 | ||
1788 | if (qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST) == QLA_SUCCESS) | 2150 | if (qla4xxx_recover_adapter(ha) == QLA_SUCCESS) |
1789 | return_status = SUCCESS; | 2151 | return_status = SUCCESS; |
1790 | 2152 | ||
1791 | dev_info(&ha->pdev->dev, "HOST RESET %s.\n", | 2153 | dev_info(&ha->pdev->dev, "HOST RESET %s.\n", |
@@ -1794,7 +2156,6 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd) | |||
1794 | return return_status; | 2156 | return return_status; |
1795 | } | 2157 | } |
1796 | 2158 | ||
1797 | |||
1798 | static struct pci_device_id qla4xxx_pci_tbl[] = { | 2159 | static struct pci_device_id qla4xxx_pci_tbl[] = { |
1799 | { | 2160 | { |
1800 | .vendor = PCI_VENDOR_ID_QLOGIC, | 2161 | .vendor = PCI_VENDOR_ID_QLOGIC, |
@@ -1814,6 +2175,12 @@ static struct pci_device_id qla4xxx_pci_tbl[] = { | |||
1814 | .subvendor = PCI_ANY_ID, | 2175 | .subvendor = PCI_ANY_ID, |
1815 | .subdevice = PCI_ANY_ID, | 2176 | .subdevice = PCI_ANY_ID, |
1816 | }, | 2177 | }, |
2178 | { | ||
2179 | .vendor = PCI_VENDOR_ID_QLOGIC, | ||
2180 | .device = PCI_DEVICE_ID_QLOGIC_ISP8022, | ||
2181 | .subvendor = PCI_ANY_ID, | ||
2182 | .subdevice = PCI_ANY_ID, | ||
2183 | }, | ||
1817 | {0, 0}, | 2184 | {0, 0}, |
1818 | }; | 2185 | }; |
1819 | MODULE_DEVICE_TABLE(pci, qla4xxx_pci_tbl); | 2186 | MODULE_DEVICE_TABLE(pci, qla4xxx_pci_tbl); |
@@ -1869,7 +2236,6 @@ no_srp_cache: | |||
1869 | 2236 | ||
1870 | static void __exit qla4xxx_module_exit(void) | 2237 | static void __exit qla4xxx_module_exit(void) |
1871 | { | 2238 | { |
1872 | ql4_mod_unload = 1; | ||
1873 | pci_unregister_driver(&qla4xxx_pci_driver); | 2239 | pci_unregister_driver(&qla4xxx_pci_driver); |
1874 | iscsi_unregister_transport(&qla4xxx_iscsi_transport); | 2240 | iscsi_unregister_transport(&qla4xxx_iscsi_transport); |
1875 | kmem_cache_destroy(srb_cachep); | 2241 | kmem_cache_destroy(srb_cachep); |