diff options
Diffstat (limited to 'drivers/scsi/qla4xxx/ql4_init.c')
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_init.c | 136 |
1 files changed, 95 insertions, 41 deletions
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 | |||