diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_init.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 1315 |
1 files changed, 1019 insertions, 296 deletions
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 7629558eba25..a6d2559217cd 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * QLOGIC LINUX SOFTWARE | 2 | * QLOGIC LINUX SOFTWARE |
3 | * | 3 | * |
4 | * QLogic ISP2x00 device driver for Linux 2.6.x | 4 | * QLogic ISP2x00 device driver for Linux 2.6.x |
5 | * Copyright (C) 2003-2004 QLogic Corporation | 5 | * Copyright (C) 2003-2005 QLogic Corporation |
6 | * (www.qlogic.com) | 6 | * (www.qlogic.com) |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify it | 8 | * This program is free software; you can redistribute it and/or modify it |
@@ -19,6 +19,8 @@ | |||
19 | #include "qla_def.h" | 19 | #include "qla_def.h" |
20 | 20 | ||
21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
22 | #include <linux/vmalloc.h> | ||
23 | #include <linux/firmware.h> | ||
22 | #include <scsi/scsi_transport_fc.h> | 24 | #include <scsi/scsi_transport_fc.h> |
23 | 25 | ||
24 | #include "qla_devtbl.h" | 26 | #include "qla_devtbl.h" |
@@ -34,17 +36,13 @@ | |||
34 | /* | 36 | /* |
35 | * QLogic ISP2x00 Hardware Support Function Prototypes. | 37 | * QLogic ISP2x00 Hardware Support Function Prototypes. |
36 | */ | 38 | */ |
37 | static int qla2x00_pci_config(scsi_qla_host_t *); | ||
38 | static int qla2x00_isp_firmware(scsi_qla_host_t *); | 39 | static int qla2x00_isp_firmware(scsi_qla_host_t *); |
39 | static void qla2x00_reset_chip(scsi_qla_host_t *); | ||
40 | static int qla2x00_chip_diag(scsi_qla_host_t *); | ||
41 | static void qla2x00_resize_request_q(scsi_qla_host_t *); | 40 | static void qla2x00_resize_request_q(scsi_qla_host_t *); |
42 | static int qla2x00_setup_chip(scsi_qla_host_t *); | 41 | static int qla2x00_setup_chip(scsi_qla_host_t *); |
43 | static void qla2x00_init_response_q_entries(scsi_qla_host_t *); | 42 | static void qla2x00_init_response_q_entries(scsi_qla_host_t *); |
44 | static int qla2x00_init_rings(scsi_qla_host_t *); | 43 | static int qla2x00_init_rings(scsi_qla_host_t *); |
45 | static int qla2x00_fw_ready(scsi_qla_host_t *); | 44 | static int qla2x00_fw_ready(scsi_qla_host_t *); |
46 | static int qla2x00_configure_hba(scsi_qla_host_t *); | 45 | static int qla2x00_configure_hba(scsi_qla_host_t *); |
47 | static int qla2x00_nvram_config(scsi_qla_host_t *); | ||
48 | static int qla2x00_configure_loop(scsi_qla_host_t *); | 46 | static int qla2x00_configure_loop(scsi_qla_host_t *); |
49 | static int qla2x00_configure_local_loop(scsi_qla_host_t *); | 47 | static int qla2x00_configure_local_loop(scsi_qla_host_t *); |
50 | static void qla2x00_update_fcport(scsi_qla_host_t *, fc_port_t *); | 48 | static void qla2x00_update_fcport(scsi_qla_host_t *, fc_port_t *); |
@@ -55,7 +53,6 @@ static int qla2x00_fabric_dev_login(scsi_qla_host_t *, fc_port_t *, | |||
55 | uint16_t *); | 53 | uint16_t *); |
56 | 54 | ||
57 | static int qla2x00_restart_isp(scsi_qla_host_t *); | 55 | static int qla2x00_restart_isp(scsi_qla_host_t *); |
58 | static void qla2x00_reset_adapter(scsi_qla_host_t *); | ||
59 | 56 | ||
60 | /****************************************************************************/ | 57 | /****************************************************************************/ |
61 | /* QLogic ISP2x00 Hardware Support Functions. */ | 58 | /* QLogic ISP2x00 Hardware Support Functions. */ |
@@ -92,17 +89,19 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) | |||
92 | ha->isp_abort_cnt = 0; | 89 | ha->isp_abort_cnt = 0; |
93 | ha->beacon_blink_led = 0; | 90 | ha->beacon_blink_led = 0; |
94 | 91 | ||
95 | rval = qla2x00_pci_config(ha); | 92 | qla_printk(KERN_INFO, ha, "Configuring PCI space...\n"); |
93 | rval = ha->isp_ops.pci_config(ha); | ||
96 | if (rval) { | 94 | if (rval) { |
97 | DEBUG2(printk("scsi(%ld): Unable to configure PCI space=n", | 95 | DEBUG2(printk("scsi(%ld): Unable to configure PCI space=n", |
98 | ha->host_no)); | 96 | ha->host_no)); |
99 | return (rval); | 97 | return (rval); |
100 | } | 98 | } |
101 | 99 | ||
102 | qla2x00_reset_chip(ha); | 100 | ha->isp_ops.reset_chip(ha); |
103 | 101 | ||
104 | qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n"); | 102 | qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n"); |
105 | qla2x00_nvram_config(ha); | 103 | |
104 | ha->isp_ops.nvram_config(ha); | ||
106 | 105 | ||
107 | qla_printk(KERN_INFO, ha, "Verifying loaded RISC code...\n"); | 106 | qla_printk(KERN_INFO, ha, "Verifying loaded RISC code...\n"); |
108 | 107 | ||
@@ -115,7 +114,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) | |||
115 | 114 | ||
116 | /* If firmware needs to be loaded */ | 115 | /* If firmware needs to be loaded */ |
117 | if (qla2x00_isp_firmware(ha) != QLA_SUCCESS) { | 116 | if (qla2x00_isp_firmware(ha) != QLA_SUCCESS) { |
118 | if ((rval = qla2x00_chip_diag(ha)) == QLA_SUCCESS) { | 117 | if ((rval = ha->isp_ops.chip_diag(ha)) == QLA_SUCCESS) { |
119 | rval = qla2x00_setup_chip(ha); | 118 | rval = qla2x00_setup_chip(ha); |
120 | } | 119 | } |
121 | } | 120 | } |
@@ -124,16 +123,19 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) | |||
124 | (rval = qla2x00_init_rings(ha)) == QLA_SUCCESS) { | 123 | (rval = qla2x00_init_rings(ha)) == QLA_SUCCESS) { |
125 | check_fw_ready_again: | 124 | check_fw_ready_again: |
126 | /* | 125 | /* |
127 | * Wait for a successful LIP up to a maximum | 126 | * Wait for a successful LIP up to a maximum |
128 | * of (in seconds): RISC login timeout value, | 127 | * of (in seconds): RISC login timeout value, |
129 | * RISC retry count value, and port down retry | 128 | * RISC retry count value, and port down retry |
130 | * value OR a minimum of 4 seconds OR If no | 129 | * value OR a minimum of 4 seconds OR If no |
131 | * cable, only 5 seconds. | 130 | * cable, only 5 seconds. |
132 | */ | 131 | */ |
133 | rval = qla2x00_fw_ready(ha); | 132 | rval = qla2x00_fw_ready(ha); |
134 | if (rval == QLA_SUCCESS) { | 133 | if (rval == QLA_SUCCESS) { |
135 | clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); | 134 | clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); |
136 | 135 | ||
136 | /* Issue a marker after FW becomes ready. */ | ||
137 | qla2x00_marker(ha, 0, 0, MK_SYNC_ALL); | ||
138 | |||
137 | /* | 139 | /* |
138 | * Wait at most MAX_TARGET RSCNs for a stable | 140 | * Wait at most MAX_TARGET RSCNs for a stable |
139 | * link. | 141 | * link. |
@@ -177,7 +179,6 @@ check_fw_ready_again: | |||
177 | 179 | ||
178 | if (rval == QLA_SUCCESS) { | 180 | if (rval == QLA_SUCCESS) { |
179 | clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); | 181 | clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); |
180 | ha->marker_needed = 1; | ||
181 | qla2x00_marker(ha, 0, 0, MK_SYNC_ALL); | 182 | qla2x00_marker(ha, 0, 0, MK_SYNC_ALL); |
182 | ha->marker_needed = 0; | 183 | ha->marker_needed = 0; |
183 | 184 | ||
@@ -190,110 +191,190 @@ check_fw_ready_again: | |||
190 | } | 191 | } |
191 | 192 | ||
192 | /** | 193 | /** |
193 | * qla2x00_pci_config() - Setup device PCI configuration registers. | 194 | * qla2100_pci_config() - Setup ISP21xx PCI configuration registers. |
194 | * @ha: HA context | 195 | * @ha: HA context |
195 | * | 196 | * |
196 | * Returns 0 on success. | 197 | * Returns 0 on success. |
197 | */ | 198 | */ |
198 | static int | 199 | int |
199 | qla2x00_pci_config(scsi_qla_host_t *ha) | 200 | qla2100_pci_config(scsi_qla_host_t *ha) |
200 | { | 201 | { |
201 | uint16_t w, mwi; | 202 | uint16_t w, mwi; |
202 | unsigned long flags = 0; | 203 | unsigned long flags; |
203 | uint32_t cnt; | 204 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; |
204 | |||
205 | qla_printk(KERN_INFO, ha, "Configuring PCI space...\n"); | ||
206 | 205 | ||
207 | /* | ||
208 | * Turn on PCI master; for system BIOSes that don't turn it on by | ||
209 | * default. | ||
210 | */ | ||
211 | pci_set_master(ha->pdev); | 206 | pci_set_master(ha->pdev); |
212 | mwi = 0; | 207 | mwi = 0; |
213 | if (pci_set_mwi(ha->pdev)) | 208 | if (pci_set_mwi(ha->pdev)) |
214 | mwi = PCI_COMMAND_INVALIDATE; | 209 | mwi = PCI_COMMAND_INVALIDATE; |
215 | pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->revision); | 210 | pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->revision); |
216 | 211 | ||
217 | if (!ha->iobase) | ||
218 | return (QLA_FUNCTION_FAILED); | ||
219 | |||
220 | /* | ||
221 | * We want to respect framework's setting of PCI configuration space | ||
222 | * command register and also want to make sure that all bits of | ||
223 | * interest to us are properly set in command register. | ||
224 | */ | ||
225 | pci_read_config_word(ha->pdev, PCI_COMMAND, &w); | 212 | pci_read_config_word(ha->pdev, PCI_COMMAND, &w); |
226 | w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); | 213 | w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); |
214 | pci_write_config_word(ha->pdev, PCI_COMMAND, w); | ||
215 | |||
216 | /* Reset expansion ROM address decode enable */ | ||
217 | pci_read_config_word(ha->pdev, PCI_ROM_ADDRESS, &w); | ||
218 | w &= ~PCI_ROM_ADDRESS_ENABLE; | ||
219 | pci_write_config_word(ha->pdev, PCI_ROM_ADDRESS, w); | ||
227 | 220 | ||
228 | /* Get PCI bus information. */ | 221 | /* Get PCI bus information. */ |
229 | spin_lock_irqsave(&ha->hardware_lock, flags); | 222 | spin_lock_irqsave(&ha->hardware_lock, flags); |
230 | ha->pci_attr = RD_REG_WORD(&ha->iobase->ctrl_status); | 223 | ha->pci_attr = RD_REG_WORD(®->ctrl_status); |
231 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 224 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
232 | 225 | ||
233 | if (!IS_QLA2100(ha) && !IS_QLA2200(ha)) { | 226 | return QLA_SUCCESS; |
234 | pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80); | 227 | } |
235 | 228 | ||
236 | /* PCI Specification Revision 2.3 changes */ | 229 | /** |
237 | if (IS_QLA2322(ha) || IS_QLA6322(ha)) | 230 | * qla2300_pci_config() - Setup ISP23xx PCI configuration registers. |
238 | /* Command Register - Reset Interrupt Disable. */ | 231 | * @ha: HA context |
239 | w &= ~PCI_COMMAND_INTX_DISABLE; | 232 | * |
233 | * Returns 0 on success. | ||
234 | */ | ||
235 | int | ||
236 | qla2300_pci_config(scsi_qla_host_t *ha) | ||
237 | { | ||
238 | uint16_t w, mwi; | ||
239 | unsigned long flags = 0; | ||
240 | uint32_t cnt; | ||
241 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; | ||
240 | 242 | ||
241 | /* | 243 | pci_set_master(ha->pdev); |
242 | * If this is a 2300 card and not 2312, reset the | 244 | mwi = 0; |
243 | * COMMAND_INVALIDATE due to a bug in the 2300. Unfortunately, | 245 | if (pci_set_mwi(ha->pdev)) |
244 | * the 2310 also reports itself as a 2300 so we need to get the | 246 | mwi = PCI_COMMAND_INVALIDATE; |
245 | * fb revision level -- a 6 indicates it really is a 2300 and | 247 | pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->revision); |
246 | * not a 2310. | ||
247 | */ | ||
248 | if (IS_QLA2300(ha)) { | ||
249 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
250 | 248 | ||
251 | /* Pause RISC. */ | 249 | pci_read_config_word(ha->pdev, PCI_COMMAND, &w); |
252 | WRT_REG_WORD(&ha->iobase->hccr, HCCR_PAUSE_RISC); | 250 | w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); |
253 | for (cnt = 0; cnt < 30000; cnt++) { | ||
254 | if ((RD_REG_WORD(&ha->iobase->hccr) & | ||
255 | HCCR_RISC_PAUSE) != 0) | ||
256 | break; | ||
257 | |||
258 | udelay(10); | ||
259 | } | ||
260 | 251 | ||
261 | /* Select FPM registers. */ | 252 | if (IS_QLA2322(ha) || IS_QLA6322(ha)) |
262 | WRT_REG_WORD(&ha->iobase->ctrl_status, 0x20); | 253 | w &= ~PCI_COMMAND_INTX_DISABLE; |
263 | RD_REG_WORD(&ha->iobase->ctrl_status); | ||
264 | 254 | ||
265 | /* Get the fb rev level */ | 255 | /* |
266 | ha->fb_rev = RD_FB_CMD_REG(ha, ha->iobase); | 256 | * If this is a 2300 card and not 2312, reset the |
257 | * COMMAND_INVALIDATE due to a bug in the 2300. Unfortunately, | ||
258 | * the 2310 also reports itself as a 2300 so we need to get the | ||
259 | * fb revision level -- a 6 indicates it really is a 2300 and | ||
260 | * not a 2310. | ||
261 | */ | ||
262 | if (IS_QLA2300(ha)) { | ||
263 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
267 | 264 | ||
268 | if (ha->fb_rev == FPM_2300) | 265 | /* Pause RISC. */ |
269 | w &= ~PCI_COMMAND_INVALIDATE; | 266 | WRT_REG_WORD(®->hccr, HCCR_PAUSE_RISC); |
267 | for (cnt = 0; cnt < 30000; cnt++) { | ||
268 | if ((RD_REG_WORD(®->hccr) & HCCR_RISC_PAUSE) != 0) | ||
269 | break; | ||
270 | 270 | ||
271 | /* Deselect FPM registers. */ | 271 | udelay(10); |
272 | WRT_REG_WORD(&ha->iobase->ctrl_status, 0x0); | 272 | } |
273 | RD_REG_WORD(&ha->iobase->ctrl_status); | ||
274 | 273 | ||
275 | /* Release RISC module. */ | 274 | /* Select FPM registers. */ |
276 | WRT_REG_WORD(&ha->iobase->hccr, HCCR_RELEASE_RISC); | 275 | WRT_REG_WORD(®->ctrl_status, 0x20); |
277 | for (cnt = 0; cnt < 30000; cnt++) { | 276 | RD_REG_WORD(®->ctrl_status); |
278 | if ((RD_REG_WORD(&ha->iobase->hccr) & | ||
279 | HCCR_RISC_PAUSE) == 0) | ||
280 | break; | ||
281 | |||
282 | udelay(10); | ||
283 | } | ||
284 | 277 | ||
285 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 278 | /* Get the fb rev level */ |
279 | ha->fb_rev = RD_FB_CMD_REG(ha, reg); | ||
280 | |||
281 | if (ha->fb_rev == FPM_2300) | ||
282 | w &= ~PCI_COMMAND_INVALIDATE; | ||
283 | |||
284 | /* Deselect FPM registers. */ | ||
285 | WRT_REG_WORD(®->ctrl_status, 0x0); | ||
286 | RD_REG_WORD(®->ctrl_status); | ||
287 | |||
288 | /* Release RISC module. */ | ||
289 | WRT_REG_WORD(®->hccr, HCCR_RELEASE_RISC); | ||
290 | for (cnt = 0; cnt < 30000; cnt++) { | ||
291 | if ((RD_REG_WORD(®->hccr) & HCCR_RISC_PAUSE) == 0) | ||
292 | break; | ||
293 | |||
294 | udelay(10); | ||
286 | } | 295 | } |
296 | |||
297 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
287 | } | 298 | } |
299 | pci_write_config_word(ha->pdev, PCI_COMMAND, w); | ||
300 | |||
301 | pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80); | ||
288 | 302 | ||
303 | /* Reset expansion ROM address decode enable */ | ||
304 | pci_read_config_word(ha->pdev, PCI_ROM_ADDRESS, &w); | ||
305 | w &= ~PCI_ROM_ADDRESS_ENABLE; | ||
306 | pci_write_config_word(ha->pdev, PCI_ROM_ADDRESS, w); | ||
307 | |||
308 | /* Get PCI bus information. */ | ||
309 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
310 | ha->pci_attr = RD_REG_WORD(®->ctrl_status); | ||
311 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
312 | |||
313 | return QLA_SUCCESS; | ||
314 | } | ||
315 | |||
316 | /** | ||
317 | * qla24xx_pci_config() - Setup ISP24xx PCI configuration registers. | ||
318 | * @ha: HA context | ||
319 | * | ||
320 | * Returns 0 on success. | ||
321 | */ | ||
322 | int | ||
323 | qla24xx_pci_config(scsi_qla_host_t *ha) | ||
324 | { | ||
325 | uint16_t w, mwi; | ||
326 | unsigned long flags = 0; | ||
327 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; | ||
328 | int pcix_cmd_reg, pcie_dctl_reg; | ||
329 | |||
330 | pci_set_master(ha->pdev); | ||
331 | mwi = 0; | ||
332 | if (pci_set_mwi(ha->pdev)) | ||
333 | mwi = PCI_COMMAND_INVALIDATE; | ||
334 | pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->revision); | ||
335 | |||
336 | pci_read_config_word(ha->pdev, PCI_COMMAND, &w); | ||
337 | w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); | ||
338 | w &= ~PCI_COMMAND_INTX_DISABLE; | ||
289 | pci_write_config_word(ha->pdev, PCI_COMMAND, w); | 339 | pci_write_config_word(ha->pdev, PCI_COMMAND, w); |
290 | 340 | ||
341 | pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80); | ||
342 | |||
343 | /* PCI-X -- adjust Maximum Memory Read Byte Count (2048). */ | ||
344 | pcix_cmd_reg = pci_find_capability(ha->pdev, PCI_CAP_ID_PCIX); | ||
345 | if (pcix_cmd_reg) { | ||
346 | uint16_t pcix_cmd; | ||
347 | |||
348 | pcix_cmd_reg += PCI_X_CMD; | ||
349 | pci_read_config_word(ha->pdev, pcix_cmd_reg, &pcix_cmd); | ||
350 | pcix_cmd &= ~PCI_X_CMD_MAX_READ; | ||
351 | pcix_cmd |= 0x0008; | ||
352 | pci_write_config_word(ha->pdev, pcix_cmd_reg, pcix_cmd); | ||
353 | } | ||
354 | |||
355 | /* PCIe -- adjust Maximum Read Request Size (2048). */ | ||
356 | pcie_dctl_reg = pci_find_capability(ha->pdev, PCI_CAP_ID_EXP); | ||
357 | if (pcie_dctl_reg) { | ||
358 | uint16_t pcie_dctl; | ||
359 | |||
360 | pcie_dctl_reg += PCI_EXP_DEVCTL; | ||
361 | pci_read_config_word(ha->pdev, pcie_dctl_reg, &pcie_dctl); | ||
362 | pcie_dctl &= ~PCI_EXP_DEVCTL_READRQ; | ||
363 | pcie_dctl |= 0x4000; | ||
364 | pci_write_config_word(ha->pdev, pcie_dctl_reg, pcie_dctl); | ||
365 | } | ||
366 | |||
291 | /* Reset expansion ROM address decode enable */ | 367 | /* Reset expansion ROM address decode enable */ |
292 | pci_read_config_word(ha->pdev, PCI_ROM_ADDRESS, &w); | 368 | pci_read_config_word(ha->pdev, PCI_ROM_ADDRESS, &w); |
293 | w &= ~PCI_ROM_ADDRESS_ENABLE; | 369 | w &= ~PCI_ROM_ADDRESS_ENABLE; |
294 | pci_write_config_word(ha->pdev, PCI_ROM_ADDRESS, w); | 370 | pci_write_config_word(ha->pdev, PCI_ROM_ADDRESS, w); |
295 | 371 | ||
296 | return (QLA_SUCCESS); | 372 | /* Get PCI bus information. */ |
373 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
374 | ha->pci_attr = RD_REG_DWORD(®->ctrl_status); | ||
375 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
376 | |||
377 | return QLA_SUCCESS; | ||
297 | } | 378 | } |
298 | 379 | ||
299 | /** | 380 | /** |
@@ -308,7 +389,7 @@ qla2x00_isp_firmware(scsi_qla_host_t *ha) | |||
308 | int rval; | 389 | int rval; |
309 | 390 | ||
310 | /* Assume loading risc code */ | 391 | /* Assume loading risc code */ |
311 | rval = QLA_FUNCTION_FAILED; | 392 | rval = QLA_FUNCTION_FAILED; |
312 | 393 | ||
313 | if (ha->flags.disable_risc_code_load) { | 394 | if (ha->flags.disable_risc_code_load) { |
314 | DEBUG2(printk("scsi(%ld): RISC CODE NOT loaded\n", | 395 | DEBUG2(printk("scsi(%ld): RISC CODE NOT loaded\n", |
@@ -316,7 +397,9 @@ qla2x00_isp_firmware(scsi_qla_host_t *ha) | |||
316 | qla_printk(KERN_INFO, ha, "RISC CODE NOT loaded\n"); | 397 | qla_printk(KERN_INFO, ha, "RISC CODE NOT loaded\n"); |
317 | 398 | ||
318 | /* Verify checksum of loaded RISC code. */ | 399 | /* Verify checksum of loaded RISC code. */ |
319 | rval = qla2x00_verify_checksum(ha); | 400 | rval = qla2x00_verify_checksum(ha, |
401 | IS_QLA24XX(ha) || IS_QLA25XX(ha) ? RISC_SADDRESS : | ||
402 | *ha->brd_info->fw_info[0].fwstart); | ||
320 | } | 403 | } |
321 | 404 | ||
322 | if (rval) { | 405 | if (rval) { |
@@ -333,17 +416,16 @@ qla2x00_isp_firmware(scsi_qla_host_t *ha) | |||
333 | * | 416 | * |
334 | * Returns 0 on success. | 417 | * Returns 0 on success. |
335 | */ | 418 | */ |
336 | static void | 419 | void |
337 | qla2x00_reset_chip(scsi_qla_host_t *ha) | 420 | qla2x00_reset_chip(scsi_qla_host_t *ha) |
338 | { | 421 | { |
339 | unsigned long flags = 0; | 422 | unsigned long flags = 0; |
340 | device_reg_t __iomem *reg = ha->iobase; | 423 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; |
341 | uint32_t cnt; | 424 | uint32_t cnt; |
342 | unsigned long mbx_flags = 0; | 425 | unsigned long mbx_flags = 0; |
343 | uint16_t cmd; | 426 | uint16_t cmd; |
344 | 427 | ||
345 | /* Disable ISP interrupts. */ | 428 | ha->isp_ops.disable_intrs(ha); |
346 | qla2x00_disable_intrs(ha); | ||
347 | 429 | ||
348 | spin_lock_irqsave(&ha->hardware_lock, flags); | 430 | spin_lock_irqsave(&ha->hardware_lock, flags); |
349 | 431 | ||
@@ -482,16 +564,95 @@ qla2x00_reset_chip(scsi_qla_host_t *ha) | |||
482 | } | 564 | } |
483 | 565 | ||
484 | /** | 566 | /** |
567 | * qla24xx_reset_risc() - Perform full reset of ISP24xx RISC. | ||
568 | * @ha: HA context | ||
569 | * | ||
570 | * Returns 0 on success. | ||
571 | */ | ||
572 | static inline void | ||
573 | qla24xx_reset_risc(scsi_qla_host_t *ha) | ||
574 | { | ||
575 | unsigned long flags = 0; | ||
576 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; | ||
577 | uint32_t cnt, d2; | ||
578 | |||
579 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
580 | |||
581 | /* Reset RISC. */ | ||
582 | WRT_REG_DWORD(®->ctrl_status, CSRX_DMA_SHUTDOWN|MWB_4096_BYTES); | ||
583 | for (cnt = 0; cnt < 30000; cnt++) { | ||
584 | if ((RD_REG_DWORD(®->ctrl_status) & CSRX_DMA_ACTIVE) == 0) | ||
585 | break; | ||
586 | |||
587 | udelay(10); | ||
588 | } | ||
589 | |||
590 | WRT_REG_DWORD(®->ctrl_status, | ||
591 | CSRX_ISP_SOFT_RESET|CSRX_DMA_SHUTDOWN|MWB_4096_BYTES); | ||
592 | RD_REG_DWORD(®->ctrl_status); | ||
593 | |||
594 | /* Wait for firmware to complete NVRAM accesses. */ | ||
595 | udelay(5); | ||
596 | d2 = (uint32_t) RD_REG_WORD(®->mailbox0); | ||
597 | for (cnt = 10000 ; cnt && d2; cnt--) { | ||
598 | udelay(5); | ||
599 | d2 = (uint32_t) RD_REG_WORD(®->mailbox0); | ||
600 | barrier(); | ||
601 | } | ||
602 | |||
603 | udelay(20); | ||
604 | d2 = RD_REG_DWORD(®->ctrl_status); | ||
605 | for (cnt = 6000000 ; cnt && (d2 & CSRX_ISP_SOFT_RESET); cnt--) { | ||
606 | udelay(5); | ||
607 | d2 = RD_REG_DWORD(®->ctrl_status); | ||
608 | barrier(); | ||
609 | } | ||
610 | |||
611 | WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_RESET); | ||
612 | RD_REG_DWORD(®->hccr); | ||
613 | |||
614 | WRT_REG_DWORD(®->hccr, HCCRX_REL_RISC_PAUSE); | ||
615 | RD_REG_DWORD(®->hccr); | ||
616 | |||
617 | WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_RESET); | ||
618 | RD_REG_DWORD(®->hccr); | ||
619 | |||
620 | d2 = (uint32_t) RD_REG_WORD(®->mailbox0); | ||
621 | for (cnt = 6000000 ; cnt && d2; cnt--) { | ||
622 | udelay(5); | ||
623 | d2 = (uint32_t) RD_REG_WORD(®->mailbox0); | ||
624 | barrier(); | ||
625 | } | ||
626 | |||
627 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
628 | } | ||
629 | |||
630 | /** | ||
631 | * qla24xx_reset_chip() - Reset ISP24xx chip. | ||
632 | * @ha: HA context | ||
633 | * | ||
634 | * Returns 0 on success. | ||
635 | */ | ||
636 | void | ||
637 | qla24xx_reset_chip(scsi_qla_host_t *ha) | ||
638 | { | ||
639 | ha->isp_ops.disable_intrs(ha); | ||
640 | |||
641 | /* Perform RISC reset. */ | ||
642 | qla24xx_reset_risc(ha); | ||
643 | } | ||
644 | |||
645 | /** | ||
485 | * qla2x00_chip_diag() - Test chip for proper operation. | 646 | * qla2x00_chip_diag() - Test chip for proper operation. |
486 | * @ha: HA context | 647 | * @ha: HA context |
487 | * | 648 | * |
488 | * Returns 0 on success. | 649 | * Returns 0 on success. |
489 | */ | 650 | */ |
490 | static int | 651 | int |
491 | qla2x00_chip_diag(scsi_qla_host_t *ha) | 652 | qla2x00_chip_diag(scsi_qla_host_t *ha) |
492 | { | 653 | { |
493 | int rval; | 654 | int rval; |
494 | device_reg_t __iomem *reg = ha->iobase; | 655 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; |
495 | unsigned long flags = 0; | 656 | unsigned long flags = 0; |
496 | uint16_t data; | 657 | uint16_t data; |
497 | uint32_t cnt; | 658 | uint32_t cnt; |
@@ -536,7 +697,7 @@ qla2x00_chip_diag(scsi_qla_host_t *ha) | |||
536 | for (cnt = 6000000; cnt && (data == MBS_BUSY); cnt--) { | 697 | for (cnt = 6000000; cnt && (data == MBS_BUSY); cnt--) { |
537 | udelay(5); | 698 | udelay(5); |
538 | data = RD_MAILBOX_REG(ha, reg, 0); | 699 | data = RD_MAILBOX_REG(ha, reg, 0); |
539 | barrier(); | 700 | barrier(); |
540 | } | 701 | } |
541 | } else | 702 | } else |
542 | udelay(10); | 703 | udelay(10); |
@@ -607,6 +768,51 @@ chip_diag_failed: | |||
607 | } | 768 | } |
608 | 769 | ||
609 | /** | 770 | /** |
771 | * qla24xx_chip_diag() - Test ISP24xx for proper operation. | ||
772 | * @ha: HA context | ||
773 | * | ||
774 | * Returns 0 on success. | ||
775 | */ | ||
776 | int | ||
777 | qla24xx_chip_diag(scsi_qla_host_t *ha) | ||
778 | { | ||
779 | int rval; | ||
780 | |||
781 | /* Perform RISC reset. */ | ||
782 | qla24xx_reset_risc(ha); | ||
783 | |||
784 | ha->fw_transfer_size = REQUEST_ENTRY_SIZE * 1024; | ||
785 | |||
786 | rval = qla2x00_mbx_reg_test(ha); | ||
787 | if (rval) { | ||
788 | DEBUG(printk("scsi(%ld): Failed mailbox send register test\n", | ||
789 | ha->host_no)); | ||
790 | qla_printk(KERN_WARNING, ha, | ||
791 | "Failed mailbox send register test\n"); | ||
792 | } else { | ||
793 | /* Flag a successful rval */ | ||
794 | rval = QLA_SUCCESS; | ||
795 | } | ||
796 | |||
797 | return rval; | ||
798 | } | ||
799 | |||
800 | static void | ||
801 | qla2x00_alloc_fw_dump(scsi_qla_host_t *ha) | ||
802 | { | ||
803 | ha->fw_dumped = 0; | ||
804 | ha->fw_dump24_len = sizeof(struct qla24xx_fw_dump); | ||
805 | ha->fw_dump24_len += (ha->fw_memory_size - 0x100000) * sizeof(uint32_t); | ||
806 | ha->fw_dump24 = vmalloc(ha->fw_dump24_len); | ||
807 | if (ha->fw_dump24) | ||
808 | qla_printk(KERN_INFO, ha, "Allocated (%d KB) for firmware " | ||
809 | "dump...\n", ha->fw_dump24_len / 1024); | ||
810 | else | ||
811 | qla_printk(KERN_WARNING, ha, "Unable to allocate (%d KB) for " | ||
812 | "firmware dump!!!\n", ha->fw_dump24_len / 1024); | ||
813 | } | ||
814 | |||
815 | /** | ||
610 | * qla2x00_resize_request_q() - Resize request queue given available ISP memory. | 816 | * qla2x00_resize_request_q() - Resize request queue given available ISP memory. |
611 | * @ha: HA context | 817 | * @ha: HA context |
612 | * | 818 | * |
@@ -625,6 +831,9 @@ qla2x00_resize_request_q(scsi_qla_host_t *ha) | |||
625 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) | 831 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) |
626 | return; | 832 | return; |
627 | 833 | ||
834 | if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) | ||
835 | qla2x00_alloc_fw_dump(ha); | ||
836 | |||
628 | /* Retrieve IOCB counts available to the firmware. */ | 837 | /* Retrieve IOCB counts available to the firmware. */ |
629 | rval = qla2x00_get_resource_cnts(ha, NULL, NULL, NULL, &fw_iocb_cnt); | 838 | rval = qla2x00_get_resource_cnts(ha, NULL, NULL, NULL, &fw_iocb_cnt); |
630 | if (rval) | 839 | if (rval) |
@@ -668,87 +877,22 @@ qla2x00_resize_request_q(scsi_qla_host_t *ha) | |||
668 | static int | 877 | static int |
669 | qla2x00_setup_chip(scsi_qla_host_t *ha) | 878 | qla2x00_setup_chip(scsi_qla_host_t *ha) |
670 | { | 879 | { |
671 | int rval; | 880 | int rval; |
672 | uint16_t cnt; | 881 | uint32_t srisc_address = 0; |
673 | uint16_t *risc_code; | ||
674 | unsigned long risc_address; | ||
675 | unsigned long risc_code_size; | ||
676 | int num; | ||
677 | int i; | ||
678 | uint16_t *req_ring; | ||
679 | struct qla_fw_info *fw_iter; | ||
680 | |||
681 | rval = QLA_SUCCESS; | ||
682 | 882 | ||
683 | /* Load firmware sequences */ | 883 | /* Load firmware sequences */ |
684 | fw_iter = ha->brd_info->fw_info; | 884 | rval = ha->isp_ops.load_risc(ha, &srisc_address); |
685 | while (fw_iter->addressing != FW_INFO_ADDR_NOMORE) { | 885 | if (rval == QLA_SUCCESS) { |
686 | risc_code = fw_iter->fwcode; | ||
687 | risc_code_size = *fw_iter->fwlen; | ||
688 | |||
689 | if (fw_iter->addressing == FW_INFO_ADDR_NORMAL) { | ||
690 | risc_address = *fw_iter->fwstart; | ||
691 | } else { | ||
692 | /* Extended address */ | ||
693 | risc_address = *fw_iter->lfwstart; | ||
694 | } | ||
695 | |||
696 | num = 0; | ||
697 | rval = 0; | ||
698 | while (risc_code_size > 0 && !rval) { | ||
699 | cnt = (uint16_t)(ha->fw_transfer_size >> 1); | ||
700 | if (cnt > risc_code_size) | ||
701 | cnt = risc_code_size; | ||
702 | |||
703 | DEBUG7(printk("scsi(%ld): Loading risc segment@ " | ||
704 | "addr %p, number of bytes 0x%x, offset 0x%lx.\n", | ||
705 | ha->host_no, risc_code, cnt, risc_address)); | ||
706 | |||
707 | req_ring = (uint16_t *)ha->request_ring; | ||
708 | for (i = 0; i < cnt; i++) | ||
709 | req_ring[i] = cpu_to_le16(risc_code[i]); | ||
710 | |||
711 | if (fw_iter->addressing == FW_INFO_ADDR_NORMAL) { | ||
712 | rval = qla2x00_load_ram(ha, | ||
713 | ha->request_dma, risc_address, cnt); | ||
714 | } else { | ||
715 | rval = qla2x00_load_ram_ext(ha, | ||
716 | ha->request_dma, risc_address, cnt); | ||
717 | } | ||
718 | if (rval) { | ||
719 | DEBUG(printk("scsi(%ld): [ERROR] Failed to " | ||
720 | "load segment %d of firmware\n", | ||
721 | ha->host_no, num)); | ||
722 | qla_printk(KERN_WARNING, ha, | ||
723 | "[ERROR] Failed to load " | ||
724 | "segment %d of firmware\n", num); | ||
725 | |||
726 | qla2x00_dump_regs(ha); | ||
727 | break; | ||
728 | } | ||
729 | |||
730 | risc_code += cnt; | ||
731 | risc_address += cnt; | ||
732 | risc_code_size -= cnt; | ||
733 | num++; | ||
734 | } | ||
735 | |||
736 | /* Next firmware sequence */ | ||
737 | fw_iter++; | ||
738 | } | ||
739 | |||
740 | /* Verify checksum of loaded RISC code. */ | ||
741 | if (!rval) { | ||
742 | DEBUG(printk("scsi(%ld): Verifying Checksum of loaded RISC " | 886 | DEBUG(printk("scsi(%ld): Verifying Checksum of loaded RISC " |
743 | "code.\n", ha->host_no)); | 887 | "code.\n", ha->host_no)); |
744 | 888 | ||
745 | rval = qla2x00_verify_checksum(ha); | 889 | rval = qla2x00_verify_checksum(ha, srisc_address); |
746 | if (rval == QLA_SUCCESS) { | 890 | if (rval == QLA_SUCCESS) { |
747 | /* Start firmware execution. */ | 891 | /* Start firmware execution. */ |
748 | DEBUG(printk("scsi(%ld): Checksum OK, start " | 892 | DEBUG(printk("scsi(%ld): Checksum OK, start " |
749 | "firmware.\n", ha->host_no)); | 893 | "firmware.\n", ha->host_no)); |
750 | 894 | ||
751 | rval = qla2x00_execute_fw(ha); | 895 | rval = qla2x00_execute_fw(ha, srisc_address); |
752 | /* Retrieve firmware information. */ | 896 | /* Retrieve firmware information. */ |
753 | if (rval == QLA_SUCCESS && ha->fw_major_version == 0) { | 897 | if (rval == QLA_SUCCESS && ha->fw_major_version == 0) { |
754 | qla2x00_get_fw_version(ha, | 898 | qla2x00_get_fw_version(ha, |
@@ -802,7 +946,7 @@ qla2x00_init_response_q_entries(scsi_qla_host_t *ha) | |||
802 | * | 946 | * |
803 | * Returns 0 on success. | 947 | * Returns 0 on success. |
804 | */ | 948 | */ |
805 | static void | 949 | void |
806 | qla2x00_update_fw_options(scsi_qla_host_t *ha) | 950 | qla2x00_update_fw_options(scsi_qla_host_t *ha) |
807 | { | 951 | { |
808 | uint16_t swing, emphasis, tx_sens, rx_sens; | 952 | uint16_t swing, emphasis, tx_sens, rx_sens; |
@@ -828,7 +972,7 @@ qla2x00_update_fw_options(scsi_qla_host_t *ha) | |||
828 | emphasis = (ha->fw_seriallink_options[2] & | 972 | emphasis = (ha->fw_seriallink_options[2] & |
829 | (BIT_4 | BIT_3)) >> 3; | 973 | (BIT_4 | BIT_3)) >> 3; |
830 | tx_sens = ha->fw_seriallink_options[0] & | 974 | tx_sens = ha->fw_seriallink_options[0] & |
831 | (BIT_3 | BIT_2 | BIT_1 | BIT_0); | 975 | (BIT_3 | BIT_2 | BIT_1 | BIT_0); |
832 | rx_sens = (ha->fw_seriallink_options[0] & | 976 | rx_sens = (ha->fw_seriallink_options[0] & |
833 | (BIT_7 | BIT_6 | BIT_5 | BIT_4)) >> 4; | 977 | (BIT_7 | BIT_6 | BIT_5 | BIT_4)) >> 4; |
834 | ha->fw_options[10] = (emphasis << 14) | (swing << 8); | 978 | ha->fw_options[10] = (emphasis << 14) | (swing << 8); |
@@ -846,7 +990,7 @@ qla2x00_update_fw_options(scsi_qla_host_t *ha) | |||
846 | (BIT_7 | BIT_6 | BIT_5)) >> 5; | 990 | (BIT_7 | BIT_6 | BIT_5)) >> 5; |
847 | emphasis = ha->fw_seriallink_options[3] & (BIT_1 | BIT_0); | 991 | emphasis = ha->fw_seriallink_options[3] & (BIT_1 | BIT_0); |
848 | tx_sens = ha->fw_seriallink_options[1] & | 992 | tx_sens = ha->fw_seriallink_options[1] & |
849 | (BIT_3 | BIT_2 | BIT_1 | BIT_0); | 993 | (BIT_3 | BIT_2 | BIT_1 | BIT_0); |
850 | rx_sens = (ha->fw_seriallink_options[1] & | 994 | rx_sens = (ha->fw_seriallink_options[1] & |
851 | (BIT_7 | BIT_6 | BIT_5 | BIT_4)) >> 4; | 995 | (BIT_7 | BIT_6 | BIT_5 | BIT_4)) >> 4; |
852 | ha->fw_options[11] = (emphasis << 14) | (swing << 8); | 996 | ha->fw_options[11] = (emphasis << 14) | (swing << 8); |
@@ -872,6 +1016,69 @@ qla2x00_update_fw_options(scsi_qla_host_t *ha) | |||
872 | qla2x00_set_fw_options(ha, ha->fw_options); | 1016 | qla2x00_set_fw_options(ha, ha->fw_options); |
873 | } | 1017 | } |
874 | 1018 | ||
1019 | void | ||
1020 | qla24xx_update_fw_options(scsi_qla_host_t *ha) | ||
1021 | { | ||
1022 | int rval; | ||
1023 | |||
1024 | /* Update Serial Link options. */ | ||
1025 | if ((ha->fw_seriallink_options24[0] & BIT_0) == 0) | ||
1026 | return; | ||
1027 | |||
1028 | rval = qla2x00_set_serdes_params(ha, ha->fw_seriallink_options24[1], | ||
1029 | ha->fw_seriallink_options24[2], ha->fw_seriallink_options24[3]); | ||
1030 | if (rval != QLA_SUCCESS) { | ||
1031 | qla_printk(KERN_WARNING, ha, | ||
1032 | "Unable to update Serial Link options (%x).\n", rval); | ||
1033 | } | ||
1034 | } | ||
1035 | |||
1036 | void | ||
1037 | qla2x00_config_rings(struct scsi_qla_host *ha) | ||
1038 | { | ||
1039 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; | ||
1040 | |||
1041 | /* Setup ring parameters in initialization control block. */ | ||
1042 | ha->init_cb->request_q_outpointer = __constant_cpu_to_le16(0); | ||
1043 | ha->init_cb->response_q_inpointer = __constant_cpu_to_le16(0); | ||
1044 | ha->init_cb->request_q_length = cpu_to_le16(ha->request_q_length); | ||
1045 | ha->init_cb->response_q_length = cpu_to_le16(ha->response_q_length); | ||
1046 | ha->init_cb->request_q_address[0] = cpu_to_le32(LSD(ha->request_dma)); | ||
1047 | ha->init_cb->request_q_address[1] = cpu_to_le32(MSD(ha->request_dma)); | ||
1048 | ha->init_cb->response_q_address[0] = cpu_to_le32(LSD(ha->response_dma)); | ||
1049 | ha->init_cb->response_q_address[1] = cpu_to_le32(MSD(ha->response_dma)); | ||
1050 | |||
1051 | WRT_REG_WORD(ISP_REQ_Q_IN(ha, reg), 0); | ||
1052 | WRT_REG_WORD(ISP_REQ_Q_OUT(ha, reg), 0); | ||
1053 | WRT_REG_WORD(ISP_RSP_Q_IN(ha, reg), 0); | ||
1054 | WRT_REG_WORD(ISP_RSP_Q_OUT(ha, reg), 0); | ||
1055 | RD_REG_WORD(ISP_RSP_Q_OUT(ha, reg)); /* PCI Posting. */ | ||
1056 | } | ||
1057 | |||
1058 | void | ||
1059 | qla24xx_config_rings(struct scsi_qla_host *ha) | ||
1060 | { | ||
1061 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; | ||
1062 | struct init_cb_24xx *icb; | ||
1063 | |||
1064 | /* Setup ring parameters in initialization control block. */ | ||
1065 | icb = (struct init_cb_24xx *)ha->init_cb; | ||
1066 | icb->request_q_outpointer = __constant_cpu_to_le16(0); | ||
1067 | icb->response_q_inpointer = __constant_cpu_to_le16(0); | ||
1068 | icb->request_q_length = cpu_to_le16(ha->request_q_length); | ||
1069 | icb->response_q_length = cpu_to_le16(ha->response_q_length); | ||
1070 | icb->request_q_address[0] = cpu_to_le32(LSD(ha->request_dma)); | ||
1071 | icb->request_q_address[1] = cpu_to_le32(MSD(ha->request_dma)); | ||
1072 | icb->response_q_address[0] = cpu_to_le32(LSD(ha->response_dma)); | ||
1073 | icb->response_q_address[1] = cpu_to_le32(MSD(ha->response_dma)); | ||
1074 | |||
1075 | WRT_REG_DWORD(®->req_q_in, 0); | ||
1076 | WRT_REG_DWORD(®->req_q_out, 0); | ||
1077 | WRT_REG_DWORD(®->rsp_q_in, 0); | ||
1078 | WRT_REG_DWORD(®->rsp_q_out, 0); | ||
1079 | RD_REG_DWORD(®->rsp_q_out); | ||
1080 | } | ||
1081 | |||
875 | /** | 1082 | /** |
876 | * qla2x00_init_rings() - Initializes firmware. | 1083 | * qla2x00_init_rings() - Initializes firmware. |
877 | * @ha: HA context | 1084 | * @ha: HA context |
@@ -887,7 +1094,6 @@ qla2x00_init_rings(scsi_qla_host_t *ha) | |||
887 | int rval; | 1094 | int rval; |
888 | unsigned long flags = 0; | 1095 | unsigned long flags = 0; |
889 | int cnt; | 1096 | int cnt; |
890 | device_reg_t __iomem *reg = ha->iobase; | ||
891 | 1097 | ||
892 | spin_lock_irqsave(&ha->hardware_lock, flags); | 1098 | spin_lock_irqsave(&ha->hardware_lock, flags); |
893 | 1099 | ||
@@ -908,32 +1114,18 @@ qla2x00_init_rings(scsi_qla_host_t *ha) | |||
908 | ha->response_ring_ptr = ha->response_ring; | 1114 | ha->response_ring_ptr = ha->response_ring; |
909 | ha->rsp_ring_index = 0; | 1115 | ha->rsp_ring_index = 0; |
910 | 1116 | ||
911 | /* Setup ring parameters in initialization control block. */ | ||
912 | ha->init_cb->request_q_outpointer = __constant_cpu_to_le16(0); | ||
913 | ha->init_cb->response_q_inpointer = __constant_cpu_to_le16(0); | ||
914 | ha->init_cb->request_q_length = cpu_to_le16(ha->request_q_length); | ||
915 | ha->init_cb->response_q_length = cpu_to_le16(ha->response_q_length); | ||
916 | ha->init_cb->request_q_address[0] = cpu_to_le32(LSD(ha->request_dma)); | ||
917 | ha->init_cb->request_q_address[1] = cpu_to_le32(MSD(ha->request_dma)); | ||
918 | ha->init_cb->response_q_address[0] = cpu_to_le32(LSD(ha->response_dma)); | ||
919 | ha->init_cb->response_q_address[1] = cpu_to_le32(MSD(ha->response_dma)); | ||
920 | |||
921 | /* Initialize response queue entries */ | 1117 | /* Initialize response queue entries */ |
922 | qla2x00_init_response_q_entries(ha); | 1118 | qla2x00_init_response_q_entries(ha); |
923 | 1119 | ||
924 | WRT_REG_WORD(ISP_REQ_Q_IN(ha, reg), 0); | 1120 | ha->isp_ops.config_rings(ha); |
925 | WRT_REG_WORD(ISP_REQ_Q_OUT(ha, reg), 0); | ||
926 | WRT_REG_WORD(ISP_RSP_Q_IN(ha, reg), 0); | ||
927 | WRT_REG_WORD(ISP_RSP_Q_OUT(ha, reg), 0); | ||
928 | RD_REG_WORD(ISP_RSP_Q_OUT(ha, reg)); /* PCI Posting. */ | ||
929 | 1121 | ||
930 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 1122 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
931 | 1123 | ||
932 | /* Update any ISP specific firmware options before initialization. */ | 1124 | /* Update any ISP specific firmware options before initialization. */ |
933 | qla2x00_update_fw_options(ha); | 1125 | ha->isp_ops.update_fw_options(ha); |
934 | 1126 | ||
935 | DEBUG(printk("scsi(%ld): Issue init firmware.\n", ha->host_no)); | 1127 | DEBUG(printk("scsi(%ld): Issue init firmware.\n", ha->host_no)); |
936 | rval = qla2x00_init_firmware(ha, sizeof(init_cb_t)); | 1128 | rval = qla2x00_init_firmware(ha, ha->init_cb_size); |
937 | if (rval) { | 1129 | if (rval) { |
938 | DEBUG2_3(printk("scsi(%ld): Init firmware **** FAILED ****.\n", | 1130 | DEBUG2_3(printk("scsi(%ld): Init firmware **** FAILED ****.\n", |
939 | ha->host_no)); | 1131 | ha->host_no)); |
@@ -963,7 +1155,7 @@ qla2x00_fw_ready(scsi_qla_host_t *ha) | |||
963 | rval = QLA_SUCCESS; | 1155 | rval = QLA_SUCCESS; |
964 | 1156 | ||
965 | /* 20 seconds for loop down. */ | 1157 | /* 20 seconds for loop down. */ |
966 | min_wait = 20; | 1158 | min_wait = 20; |
967 | 1159 | ||
968 | /* | 1160 | /* |
969 | * Firmware should take at most one RATOV to login, plus 5 seconds for | 1161 | * Firmware should take at most one RATOV to login, plus 5 seconds for |
@@ -1009,8 +1201,8 @@ qla2x00_fw_ready(scsi_qla_host_t *ha) | |||
1009 | (fw_state >= FSTATE_LOSS_OF_SYNC || | 1201 | (fw_state >= FSTATE_LOSS_OF_SYNC || |
1010 | fw_state == FSTATE_WAIT_AL_PA)) { | 1202 | fw_state == FSTATE_WAIT_AL_PA)) { |
1011 | /* Loop down. Timeout on min_wait for states | 1203 | /* Loop down. Timeout on min_wait for states |
1012 | * other than Wait for Login. | 1204 | * other than Wait for Login. |
1013 | */ | 1205 | */ |
1014 | if (time_after_eq(jiffies, mtime)) { | 1206 | if (time_after_eq(jiffies, mtime)) { |
1015 | qla_printk(KERN_INFO, ha, | 1207 | qla_printk(KERN_INFO, ha, |
1016 | "Cable is unplugged...\n"); | 1208 | "Cable is unplugged...\n"); |
@@ -1165,41 +1357,36 @@ qla2x00_configure_hba(scsi_qla_host_t *ha) | |||
1165 | * Returns: | 1357 | * Returns: |
1166 | * 0 = success. | 1358 | * 0 = success. |
1167 | */ | 1359 | */ |
1168 | static int | 1360 | int |
1169 | qla2x00_nvram_config(scsi_qla_host_t *ha) | 1361 | qla2x00_nvram_config(scsi_qla_host_t *ha) |
1170 | { | 1362 | { |
1171 | int rval; | 1363 | int rval; |
1172 | uint8_t chksum = 0; | 1364 | uint8_t chksum = 0; |
1173 | uint16_t cnt; | 1365 | uint16_t cnt; |
1174 | uint8_t *dptr1, *dptr2; | 1366 | uint8_t *dptr1, *dptr2; |
1175 | init_cb_t *icb = ha->init_cb; | 1367 | init_cb_t *icb = ha->init_cb; |
1176 | nvram_t *nv = (nvram_t *)ha->request_ring; | 1368 | nvram_t *nv = (nvram_t *)ha->request_ring; |
1177 | uint16_t *wptr = (uint16_t *)ha->request_ring; | 1369 | uint8_t *ptr = (uint8_t *)ha->request_ring; |
1178 | device_reg_t __iomem *reg = ha->iobase; | 1370 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; |
1179 | uint8_t timer_mode; | 1371 | uint8_t timer_mode; |
1180 | 1372 | ||
1181 | rval = QLA_SUCCESS; | 1373 | rval = QLA_SUCCESS; |
1182 | 1374 | ||
1183 | /* Determine NVRAM starting address. */ | 1375 | /* Determine NVRAM starting address. */ |
1376 | ha->nvram_size = sizeof(nvram_t); | ||
1184 | ha->nvram_base = 0; | 1377 | ha->nvram_base = 0; |
1185 | if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA2300(ha)) | 1378 | if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA2300(ha)) |
1186 | if ((RD_REG_WORD(®->ctrl_status) >> 14) == 1) | 1379 | if ((RD_REG_WORD(®->ctrl_status) >> 14) == 1) |
1187 | ha->nvram_base = 0x80; | 1380 | ha->nvram_base = 0x80; |
1188 | 1381 | ||
1189 | /* Get NVRAM data and calculate checksum. */ | 1382 | /* Get NVRAM data and calculate checksum. */ |
1190 | qla2x00_lock_nvram_access(ha); | 1383 | ha->isp_ops.read_nvram(ha, ptr, ha->nvram_base, ha->nvram_size); |
1191 | for (cnt = 0; cnt < sizeof(nvram_t)/2; cnt++) { | 1384 | for (cnt = 0, chksum = 0; cnt < ha->nvram_size; cnt++) |
1192 | *wptr = cpu_to_le16(qla2x00_get_nvram_word(ha, | 1385 | chksum += *ptr++; |
1193 | (cnt+ha->nvram_base))); | ||
1194 | chksum += (uint8_t)*wptr; | ||
1195 | chksum += (uint8_t)(*wptr >> 8); | ||
1196 | wptr++; | ||
1197 | } | ||
1198 | qla2x00_unlock_nvram_access(ha); | ||
1199 | 1386 | ||
1200 | DEBUG5(printk("scsi(%ld): Contents of NVRAM\n", ha->host_no)); | 1387 | DEBUG5(printk("scsi(%ld): Contents of NVRAM\n", ha->host_no)); |
1201 | DEBUG5(qla2x00_dump_buffer((uint8_t *)ha->request_ring, | 1388 | DEBUG5(qla2x00_dump_buffer((uint8_t *)ha->request_ring, |
1202 | sizeof(nvram_t))); | 1389 | ha->nvram_size)); |
1203 | 1390 | ||
1204 | /* Bad NVRAM data, set defaults parameters. */ | 1391 | /* Bad NVRAM data, set defaults parameters. */ |
1205 | if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || | 1392 | if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || |
@@ -1214,7 +1401,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) | |||
1214 | /* | 1401 | /* |
1215 | * Set default initialization control block. | 1402 | * Set default initialization control block. |
1216 | */ | 1403 | */ |
1217 | memset(nv, 0, sizeof(nvram_t)); | 1404 | memset(nv, 0, ha->nvram_size); |
1218 | nv->parameter_block_version = ICB_VERSION; | 1405 | nv->parameter_block_version = ICB_VERSION; |
1219 | 1406 | ||
1220 | if (IS_QLA23XX(ha)) { | 1407 | if (IS_QLA23XX(ha)) { |
@@ -1274,7 +1461,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) | |||
1274 | #endif | 1461 | #endif |
1275 | 1462 | ||
1276 | /* Reset Initialization control block */ | 1463 | /* Reset Initialization control block */ |
1277 | memset(icb, 0, sizeof(init_cb_t)); | 1464 | memset(icb, 0, ha->init_cb_size); |
1278 | 1465 | ||
1279 | /* | 1466 | /* |
1280 | * Setup driver NVRAM options. | 1467 | * Setup driver NVRAM options. |
@@ -1287,6 +1474,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) | |||
1287 | if (IS_QLA23XX(ha)) { | 1474 | if (IS_QLA23XX(ha)) { |
1288 | nv->firmware_options[0] |= BIT_2; | 1475 | nv->firmware_options[0] |= BIT_2; |
1289 | nv->firmware_options[0] &= ~BIT_3; | 1476 | nv->firmware_options[0] &= ~BIT_3; |
1477 | nv->add_firmware_options[1] |= BIT_5 | BIT_4; | ||
1290 | 1478 | ||
1291 | if (IS_QLA2300(ha)) { | 1479 | if (IS_QLA2300(ha)) { |
1292 | if (ha->fb_rev == FPM_2310) { | 1480 | if (ha->fb_rev == FPM_2310) { |
@@ -1368,8 +1556,6 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) | |||
1368 | /* | 1556 | /* |
1369 | * Set host adapter parameters. | 1557 | * Set host adapter parameters. |
1370 | */ | 1558 | */ |
1371 | ha->nvram_version = nv->nvram_version; | ||
1372 | |||
1373 | ha->flags.disable_risc_code_load = ((nv->host_p[0] & BIT_4) ? 1 : 0); | 1559 | ha->flags.disable_risc_code_load = ((nv->host_p[0] & BIT_4) ? 1 : 0); |
1374 | /* Always load RISC code on non ISP2[12]00 chips. */ | 1560 | /* Always load RISC code on non ISP2[12]00 chips. */ |
1375 | if (!IS_QLA2100(ha) && !IS_QLA2200(ha)) | 1561 | if (!IS_QLA2100(ha) && !IS_QLA2200(ha)) |
@@ -1389,7 +1575,8 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) | |||
1389 | ha->serial0 = icb->port_name[5]; | 1575 | ha->serial0 = icb->port_name[5]; |
1390 | ha->serial1 = icb->port_name[6]; | 1576 | ha->serial1 = icb->port_name[6]; |
1391 | ha->serial2 = icb->port_name[7]; | 1577 | ha->serial2 = icb->port_name[7]; |
1392 | memcpy(ha->node_name, icb->node_name, WWN_SIZE); | 1578 | ha->node_name = icb->node_name; |
1579 | ha->port_name = icb->port_name; | ||
1393 | 1580 | ||
1394 | icb->execution_throttle = __constant_cpu_to_le16(0xFFFF); | 1581 | icb->execution_throttle = __constant_cpu_to_le16(0xFFFF); |
1395 | 1582 | ||
@@ -1417,7 +1604,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) | |||
1417 | * | 1604 | * |
1418 | * The driver waits for the link to come up after link down | 1605 | * The driver waits for the link to come up after link down |
1419 | * before returning I/Os to OS with "DID_NO_CONNECT". | 1606 | * before returning I/Os to OS with "DID_NO_CONNECT". |
1420 | */ | 1607 | */ |
1421 | if (nv->link_down_timeout == 0) { | 1608 | if (nv->link_down_timeout == 0) { |
1422 | ha->loop_down_abort_time = | 1609 | ha->loop_down_abort_time = |
1423 | (LOOP_DOWN_TIME - LOOP_DOWN_TIMEOUT); | 1610 | (LOOP_DOWN_TIME - LOOP_DOWN_TIMEOUT); |
@@ -1425,7 +1612,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) | |||
1425 | ha->link_down_timeout = nv->link_down_timeout; | 1612 | ha->link_down_timeout = nv->link_down_timeout; |
1426 | ha->loop_down_abort_time = | 1613 | ha->loop_down_abort_time = |
1427 | (LOOP_DOWN_TIME - ha->link_down_timeout); | 1614 | (LOOP_DOWN_TIME - ha->link_down_timeout); |
1428 | } | 1615 | } |
1429 | 1616 | ||
1430 | /* | 1617 | /* |
1431 | * Need enough time to try and get the port back. | 1618 | * Need enough time to try and get the port back. |
@@ -1527,7 +1714,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, int flags) | |||
1527 | * 2 = database was full and device was not configured. | 1714 | * 2 = database was full and device was not configured. |
1528 | */ | 1715 | */ |
1529 | static int | 1716 | static int |
1530 | qla2x00_configure_loop(scsi_qla_host_t *ha) | 1717 | qla2x00_configure_loop(scsi_qla_host_t *ha) |
1531 | { | 1718 | { |
1532 | int rval; | 1719 | int rval; |
1533 | unsigned long flags, save_flags; | 1720 | unsigned long flags, save_flags; |
@@ -1635,7 +1822,7 @@ qla2x00_configure_loop(scsi_qla_host_t *ha) | |||
1635 | * 0 = success. | 1822 | * 0 = success. |
1636 | */ | 1823 | */ |
1637 | static int | 1824 | static int |
1638 | qla2x00_configure_local_loop(scsi_qla_host_t *ha) | 1825 | qla2x00_configure_local_loop(scsi_qla_host_t *ha) |
1639 | { | 1826 | { |
1640 | int rval, rval2; | 1827 | int rval, rval2; |
1641 | int found_devs; | 1828 | int found_devs; |
@@ -1698,15 +1885,13 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha) | |||
1698 | domain = ((struct gid_list_info *)id_iter)->domain; | 1885 | domain = ((struct gid_list_info *)id_iter)->domain; |
1699 | area = ((struct gid_list_info *)id_iter)->area; | 1886 | area = ((struct gid_list_info *)id_iter)->area; |
1700 | al_pa = ((struct gid_list_info *)id_iter)->al_pa; | 1887 | al_pa = ((struct gid_list_info *)id_iter)->al_pa; |
1701 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) { | 1888 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) |
1702 | loop_id = (uint16_t) | 1889 | loop_id = (uint16_t) |
1703 | ((struct gid_list_info *)id_iter)->loop_id_2100; | 1890 | ((struct gid_list_info *)id_iter)->loop_id_2100; |
1704 | id_iter += 4; | 1891 | else |
1705 | } else { | ||
1706 | loop_id = le16_to_cpu( | 1892 | loop_id = le16_to_cpu( |
1707 | ((struct gid_list_info *)id_iter)->loop_id); | 1893 | ((struct gid_list_info *)id_iter)->loop_id); |
1708 | id_iter += 6; | 1894 | id_iter += ha->gid_list_info_size; |
1709 | } | ||
1710 | 1895 | ||
1711 | /* Bypass reserved domain fields. */ | 1896 | /* Bypass reserved domain fields. */ |
1712 | if ((domain & 0xf0) == 0xf0) | 1897 | if ((domain & 0xf0) == 0xf0) |
@@ -1792,16 +1977,16 @@ cleanup_allocation: | |||
1792 | } | 1977 | } |
1793 | 1978 | ||
1794 | static void | 1979 | static void |
1795 | qla2x00_probe_for_all_luns(scsi_qla_host_t *ha) | 1980 | qla2x00_probe_for_all_luns(scsi_qla_host_t *ha) |
1796 | { | 1981 | { |
1797 | fc_port_t *fcport; | 1982 | fc_port_t *fcport; |
1798 | 1983 | ||
1799 | qla2x00_mark_all_devices_lost(ha); | 1984 | qla2x00_mark_all_devices_lost(ha); |
1800 | list_for_each_entry(fcport, &ha->fcports, list) { | 1985 | list_for_each_entry(fcport, &ha->fcports, list) { |
1801 | if (fcport->port_type != FCT_TARGET) | 1986 | if (fcport->port_type != FCT_TARGET) |
1802 | continue; | 1987 | continue; |
1803 | 1988 | ||
1804 | qla2x00_update_fcport(ha, fcport); | 1989 | qla2x00_update_fcport(ha, fcport); |
1805 | } | 1990 | } |
1806 | } | 1991 | } |
1807 | 1992 | ||
@@ -1883,20 +2068,24 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport) | |||
1883 | rport_ids.port_id = fcport->d_id.b.domain << 16 | | 2068 | rport_ids.port_id = fcport->d_id.b.domain << 16 | |
1884 | fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa; | 2069 | fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa; |
1885 | rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; | 2070 | rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; |
2071 | fcport->rport = rport = fc_remote_port_add(ha->host, 0, &rport_ids); | ||
2072 | if (!rport) { | ||
2073 | qla_printk(KERN_WARNING, ha, | ||
2074 | "Unable to allocate fc remote port!\n"); | ||
2075 | return; | ||
2076 | } | ||
2077 | rport->dd_data = fcport; | ||
2078 | |||
2079 | rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; | ||
1886 | if (fcport->port_type == FCT_INITIATOR) | 2080 | if (fcport->port_type == FCT_INITIATOR) |
1887 | rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR; | 2081 | rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR; |
1888 | if (fcport->port_type == FCT_TARGET) | 2082 | if (fcport->port_type == FCT_TARGET) |
1889 | rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET; | 2083 | rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET; |
2084 | fc_remote_port_rolechg(rport, rport_ids.roles); | ||
1890 | 2085 | ||
1891 | fcport->rport = rport = fc_remote_port_add(ha->host, 0, &rport_ids); | 2086 | if (rport->scsi_target_id != -1 && |
1892 | if (!rport) | 2087 | rport->scsi_target_id < ha->host->max_id) |
1893 | qla_printk(KERN_WARNING, ha, | ||
1894 | "Unable to allocate fc remote port!\n"); | ||
1895 | |||
1896 | if (rport->scsi_target_id != -1 && rport->scsi_target_id < MAX_TARGETS) | ||
1897 | fcport->os_target_id = rport->scsi_target_id; | 2088 | fcport->os_target_id = rport->scsi_target_id; |
1898 | |||
1899 | rport->dd_data = fcport; | ||
1900 | } | 2089 | } |
1901 | 2090 | ||
1902 | /* | 2091 | /* |
@@ -1917,10 +2106,15 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) | |||
1917 | fc_port_t *fcport, *fcptemp; | 2106 | fc_port_t *fcport, *fcptemp; |
1918 | uint16_t next_loopid; | 2107 | uint16_t next_loopid; |
1919 | uint16_t mb[MAILBOX_REGISTER_COUNT]; | 2108 | uint16_t mb[MAILBOX_REGISTER_COUNT]; |
2109 | uint16_t loop_id; | ||
1920 | LIST_HEAD(new_fcports); | 2110 | LIST_HEAD(new_fcports); |
1921 | 2111 | ||
1922 | /* If FL port exists, then SNS is present */ | 2112 | /* If FL port exists, then SNS is present */ |
1923 | rval = qla2x00_get_port_name(ha, SNS_FL_PORT, NULL, 0); | 2113 | if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) |
2114 | loop_id = NPH_F_PORT; | ||
2115 | else | ||
2116 | loop_id = SNS_FL_PORT; | ||
2117 | rval = qla2x00_get_port_name(ha, loop_id, NULL, 0); | ||
1924 | if (rval != QLA_SUCCESS) { | 2118 | if (rval != QLA_SUCCESS) { |
1925 | DEBUG2(printk("scsi(%ld): MBC_GET_PORT_NAME Failed, No FL " | 2119 | DEBUG2(printk("scsi(%ld): MBC_GET_PORT_NAME Failed, No FL " |
1926 | "Port\n", ha->host_no)); | 2120 | "Port\n", ha->host_no)); |
@@ -1937,12 +2131,16 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) | |||
1937 | } | 2131 | } |
1938 | do { | 2132 | do { |
1939 | /* Ensure we are logged into the SNS. */ | 2133 | /* Ensure we are logged into the SNS. */ |
1940 | qla2x00_login_fabric(ha, SIMPLE_NAME_SERVER, 0xff, 0xff, 0xfc, | 2134 | if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) |
1941 | mb, BIT_1 | BIT_0); | 2135 | loop_id = NPH_SNS; |
2136 | else | ||
2137 | loop_id = SIMPLE_NAME_SERVER; | ||
2138 | ha->isp_ops.fabric_login(ha, loop_id, 0xff, 0xff, | ||
2139 | 0xfc, mb, BIT_1 | BIT_0); | ||
1942 | if (mb[0] != MBS_COMMAND_COMPLETE) { | 2140 | if (mb[0] != MBS_COMMAND_COMPLETE) { |
1943 | DEBUG2(qla_printk(KERN_INFO, ha, | 2141 | DEBUG2(qla_printk(KERN_INFO, ha, |
1944 | "Failed SNS login: loop_id=%x mb[0]=%x mb[1]=%x " | 2142 | "Failed SNS login: loop_id=%x mb[0]=%x mb[1]=%x " |
1945 | "mb[2]=%x mb[6]=%x mb[7]=%x\n", SIMPLE_NAME_SERVER, | 2143 | "mb[2]=%x mb[6]=%x mb[7]=%x\n", loop_id, |
1946 | mb[0], mb[1], mb[2], mb[6], mb[7])); | 2144 | mb[0], mb[1], mb[2], mb[6], mb[7])); |
1947 | return (QLA_SUCCESS); | 2145 | return (QLA_SUCCESS); |
1948 | } | 2146 | } |
@@ -1992,8 +2190,11 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) | |||
1992 | fcport->port_type != FCT_INITIATOR && | 2190 | fcport->port_type != FCT_INITIATOR && |
1993 | fcport->port_type != FCT_BROADCAST) { | 2191 | fcport->port_type != FCT_BROADCAST) { |
1994 | 2192 | ||
1995 | qla2x00_fabric_logout(ha, | 2193 | ha->isp_ops.fabric_logout(ha, |
1996 | fcport->loop_id); | 2194 | fcport->loop_id, |
2195 | fcport->d_id.b.domain, | ||
2196 | fcport->d_id.b.area, | ||
2197 | fcport->d_id.b.al_pa); | ||
1997 | fcport->loop_id = FC_NO_LOOP_ID; | 2198 | fcport->loop_id = FC_NO_LOOP_ID; |
1998 | } | 2199 | } |
1999 | } | 2200 | } |
@@ -2023,7 +2224,6 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) | |||
2023 | break; | 2224 | break; |
2024 | } | 2225 | } |
2025 | } | 2226 | } |
2026 | |||
2027 | /* Login and update database */ | 2227 | /* Login and update database */ |
2028 | qla2x00_fabric_dev_login(ha, fcport, &next_loopid); | 2228 | qla2x00_fabric_dev_login(ha, fcport, &next_loopid); |
2029 | } | 2229 | } |
@@ -2137,9 +2337,8 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) | |||
2137 | 2337 | ||
2138 | /* Starting free loop ID. */ | 2338 | /* Starting free loop ID. */ |
2139 | loop_id = ha->min_external_loopid; | 2339 | loop_id = ha->min_external_loopid; |
2140 | |||
2141 | for (; loop_id <= ha->last_loop_id; loop_id++) { | 2340 | for (; loop_id <= ha->last_loop_id; loop_id++) { |
2142 | if (RESERVED_LOOP_ID(loop_id)) | 2341 | if (qla2x00_is_reserved_id(ha, loop_id)) |
2143 | continue; | 2342 | continue; |
2144 | 2343 | ||
2145 | if (atomic_read(&ha->loop_down_timer) || | 2344 | if (atomic_read(&ha->loop_down_timer) || |
@@ -2238,7 +2437,9 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) | |||
2238 | (fcport->flags & FCF_TAPE_PRESENT) == 0 && | 2437 | (fcport->flags & FCF_TAPE_PRESENT) == 0 && |
2239 | fcport->port_type != FCT_INITIATOR && | 2438 | fcport->port_type != FCT_INITIATOR && |
2240 | fcport->port_type != FCT_BROADCAST) { | 2439 | fcport->port_type != FCT_BROADCAST) { |
2241 | qla2x00_fabric_logout(ha, fcport->loop_id); | 2440 | ha->isp_ops.fabric_logout(ha, fcport->loop_id, |
2441 | fcport->d_id.b.domain, fcport->d_id.b.area, | ||
2442 | fcport->d_id.b.al_pa); | ||
2242 | fcport->loop_id = FC_NO_LOOP_ID; | 2443 | fcport->loop_id = FC_NO_LOOP_ID; |
2243 | } | 2444 | } |
2244 | 2445 | ||
@@ -2309,7 +2510,7 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *ha, fc_port_t *dev) | |||
2309 | } | 2510 | } |
2310 | 2511 | ||
2311 | /* Skip reserved loop IDs. */ | 2512 | /* Skip reserved loop IDs. */ |
2312 | while (RESERVED_LOOP_ID(dev->loop_id)) { | 2513 | while (qla2x00_is_reserved_id(ha, dev->loop_id)) { |
2313 | dev->loop_id++; | 2514 | dev->loop_id++; |
2314 | } | 2515 | } |
2315 | 2516 | ||
@@ -2360,7 +2561,7 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *ha, fc_port_t *dev) | |||
2360 | * Kernel context. | 2561 | * Kernel context. |
2361 | */ | 2562 | */ |
2362 | static int | 2563 | static int |
2363 | qla2x00_device_resync(scsi_qla_host_t *ha) | 2564 | qla2x00_device_resync(scsi_qla_host_t *ha) |
2364 | { | 2565 | { |
2365 | int rval; | 2566 | int rval; |
2366 | int rval2; | 2567 | int rval2; |
@@ -2421,6 +2622,7 @@ qla2x00_device_resync(scsi_qla_host_t *ha) | |||
2421 | case 0: | 2622 | case 0: |
2422 | if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && | 2623 | if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && |
2423 | !IS_QLA6312(ha) && !IS_QLA6322(ha) && | 2624 | !IS_QLA6312(ha) && !IS_QLA6322(ha) && |
2625 | !IS_QLA24XX(ha) && !IS_QLA25XX(ha) && | ||
2424 | ha->flags.init_done) { | 2626 | ha->flags.init_done) { |
2425 | /* Handle port RSCN via asyncronous IOCBs */ | 2627 | /* Handle port RSCN via asyncronous IOCBs */ |
2426 | rval2 = qla2x00_handle_port_rscn(ha, rscn_entry, | 2628 | rval2 = qla2x00_handle_port_rscn(ha, rscn_entry, |
@@ -2489,15 +2691,24 @@ qla2x00_fabric_dev_login(scsi_qla_host_t *ha, fc_port_t *fcport, | |||
2489 | { | 2691 | { |
2490 | int rval; | 2692 | int rval; |
2491 | int retry; | 2693 | int retry; |
2694 | uint8_t opts; | ||
2492 | 2695 | ||
2493 | rval = QLA_SUCCESS; | 2696 | rval = QLA_SUCCESS; |
2494 | retry = 0; | 2697 | retry = 0; |
2495 | 2698 | ||
2496 | rval = qla2x00_fabric_login(ha, fcport, next_loopid); | 2699 | rval = qla2x00_fabric_login(ha, fcport, next_loopid); |
2497 | if (rval == QLA_SUCCESS) { | 2700 | if (rval == QLA_SUCCESS) { |
2498 | rval = qla2x00_get_port_database(ha, fcport, 0); | 2701 | /* Send an ADISC to tape devices.*/ |
2702 | opts = 0; | ||
2703 | if (fcport->flags & FCF_TAPE_PRESENT) | ||
2704 | opts |= BIT_1; | ||
2705 | rval = qla2x00_get_port_database(ha, fcport, opts); | ||
2499 | if (rval != QLA_SUCCESS) { | 2706 | if (rval != QLA_SUCCESS) { |
2500 | qla2x00_fabric_logout(ha, fcport->loop_id); | 2707 | ha->isp_ops.fabric_logout(ha, fcport->loop_id, |
2708 | fcport->d_id.b.domain, fcport->d_id.b.area, | ||
2709 | fcport->d_id.b.al_pa); | ||
2710 | qla2x00_mark_device_lost(ha, fcport, 1); | ||
2711 | |||
2501 | } else { | 2712 | } else { |
2502 | qla2x00_update_fcport(ha, fcport); | 2713 | qla2x00_update_fcport(ha, fcport); |
2503 | } | 2714 | } |
@@ -2539,16 +2750,16 @@ qla2x00_fabric_login(scsi_qla_host_t *ha, fc_port_t *fcport, | |||
2539 | fcport->d_id.b.area, fcport->d_id.b.al_pa)); | 2750 | fcport->d_id.b.area, fcport->d_id.b.al_pa)); |
2540 | 2751 | ||
2541 | /* Login fcport on switch. */ | 2752 | /* Login fcport on switch. */ |
2542 | qla2x00_login_fabric(ha, fcport->loop_id, | 2753 | ha->isp_ops.fabric_login(ha, fcport->loop_id, |
2543 | fcport->d_id.b.domain, fcport->d_id.b.area, | 2754 | fcport->d_id.b.domain, fcport->d_id.b.area, |
2544 | fcport->d_id.b.al_pa, mb, BIT_0); | 2755 | fcport->d_id.b.al_pa, mb, BIT_0); |
2545 | if (mb[0] == MBS_PORT_ID_USED) { | 2756 | if (mb[0] == MBS_PORT_ID_USED) { |
2546 | /* | 2757 | /* |
2547 | * Device has another loop ID. The firmware team | 2758 | * Device has another loop ID. The firmware team |
2548 | * recommends us to perform an implicit login with the | 2759 | * recommends the driver perform an implicit login with |
2549 | * specified ID again. The ID we just used is save here | 2760 | * the specified ID again. The ID we just used is save |
2550 | * so we return with an ID that can be tried by the | 2761 | * here so we return with an ID that can be tried by |
2551 | * next login. | 2762 | * the next login. |
2552 | */ | 2763 | */ |
2553 | retry++; | 2764 | retry++; |
2554 | tmp_loopid = fcport->loop_id; | 2765 | tmp_loopid = fcport->loop_id; |
@@ -2602,7 +2813,9 @@ qla2x00_fabric_login(scsi_qla_host_t *ha, fc_port_t *fcport, | |||
2602 | * dead. | 2813 | * dead. |
2603 | */ | 2814 | */ |
2604 | *next_loopid = fcport->loop_id; | 2815 | *next_loopid = fcport->loop_id; |
2605 | qla2x00_fabric_logout(ha, fcport->loop_id); | 2816 | ha->isp_ops.fabric_logout(ha, fcport->loop_id, |
2817 | fcport->d_id.b.domain, fcport->d_id.b.area, | ||
2818 | fcport->d_id.b.al_pa); | ||
2606 | qla2x00_mark_device_lost(ha, fcport, 1); | 2819 | qla2x00_mark_device_lost(ha, fcport, 1); |
2607 | 2820 | ||
2608 | rval = 1; | 2821 | rval = 1; |
@@ -2612,13 +2825,15 @@ qla2x00_fabric_login(scsi_qla_host_t *ha, fc_port_t *fcport, | |||
2612 | * unrecoverable / not handled error | 2825 | * unrecoverable / not handled error |
2613 | */ | 2826 | */ |
2614 | DEBUG2(printk("%s(%ld): failed=%x port_id=%02x%02x%02x " | 2827 | DEBUG2(printk("%s(%ld): failed=%x port_id=%02x%02x%02x " |
2615 | "loop_id=%x jiffies=%lx.\n", | 2828 | "loop_id=%x jiffies=%lx.\n", |
2616 | __func__, ha->host_no, mb[0], | 2829 | __func__, ha->host_no, mb[0], |
2617 | fcport->d_id.b.domain, fcport->d_id.b.area, | 2830 | fcport->d_id.b.domain, fcport->d_id.b.area, |
2618 | fcport->d_id.b.al_pa, fcport->loop_id, jiffies)); | 2831 | fcport->d_id.b.al_pa, fcport->loop_id, jiffies)); |
2619 | 2832 | ||
2620 | *next_loopid = fcport->loop_id; | 2833 | *next_loopid = fcport->loop_id; |
2621 | qla2x00_fabric_logout(ha, fcport->loop_id); | 2834 | ha->isp_ops.fabric_logout(ha, fcport->loop_id, |
2835 | fcport->d_id.b.domain, fcport->d_id.b.area, | ||
2836 | fcport->d_id.b.al_pa); | ||
2622 | fcport->loop_id = FC_NO_LOOP_ID; | 2837 | fcport->loop_id = FC_NO_LOOP_ID; |
2623 | atomic_set(&fcport->state, FCS_DEVICE_DEAD); | 2838 | atomic_set(&fcport->state, FCS_DEVICE_DEAD); |
2624 | 2839 | ||
@@ -2674,7 +2889,7 @@ qla2x00_local_device_login(scsi_qla_host_t *ha, uint16_t loop_id) | |||
2674 | * 0 = success | 2889 | * 0 = success |
2675 | */ | 2890 | */ |
2676 | int | 2891 | int |
2677 | qla2x00_loop_resync(scsi_qla_host_t *ha) | 2892 | qla2x00_loop_resync(scsi_qla_host_t *ha) |
2678 | { | 2893 | { |
2679 | int rval; | 2894 | int rval; |
2680 | uint32_t wait_time; | 2895 | uint32_t wait_time; |
@@ -2688,14 +2903,11 @@ qla2x00_loop_resync(scsi_qla_host_t *ha) | |||
2688 | /* Wait at most MAX_TARGET RSCNs for a stable link. */ | 2903 | /* Wait at most MAX_TARGET RSCNs for a stable link. */ |
2689 | wait_time = 256; | 2904 | wait_time = 256; |
2690 | do { | 2905 | do { |
2691 | /* v2.19.05b6 */ | ||
2692 | atomic_set(&ha->loop_state, LOOP_UPDATE); | 2906 | atomic_set(&ha->loop_state, LOOP_UPDATE); |
2693 | 2907 | ||
2694 | /* | 2908 | /* Issue a marker after FW becomes ready. */ |
2695 | * Issue marker command only when we are going | 2909 | qla2x00_marker(ha, 0, 0, MK_SYNC_ALL); |
2696 | * to start the I/O . | 2910 | ha->marker_needed = 0; |
2697 | */ | ||
2698 | ha->marker_needed = 1; | ||
2699 | 2911 | ||
2700 | /* Remap devices on Loop. */ | 2912 | /* Remap devices on Loop. */ |
2701 | clear_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); | 2913 | clear_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); |
@@ -2736,7 +2948,7 @@ qla2x00_rescan_fcports(scsi_qla_host_t *ha) | |||
2736 | 2948 | ||
2737 | rescan_done = 1; | 2949 | rescan_done = 1; |
2738 | } | 2950 | } |
2739 | qla2x00_probe_for_all_luns(ha); | 2951 | qla2x00_probe_for_all_luns(ha); |
2740 | } | 2952 | } |
2741 | 2953 | ||
2742 | /* | 2954 | /* |
@@ -2763,7 +2975,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) | |||
2763 | 2975 | ||
2764 | qla_printk(KERN_INFO, ha, | 2976 | qla_printk(KERN_INFO, ha, |
2765 | "Performing ISP error recovery - ha= %p.\n", ha); | 2977 | "Performing ISP error recovery - ha= %p.\n", ha); |
2766 | qla2x00_reset_chip(ha); | 2978 | ha->isp_ops.reset_chip(ha); |
2767 | 2979 | ||
2768 | atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); | 2980 | atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); |
2769 | if (atomic_read(&ha->loop_state) != LOOP_DOWN) { | 2981 | if (atomic_read(&ha->loop_state) != LOOP_DOWN) { |
@@ -2789,7 +3001,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) | |||
2789 | } | 3001 | } |
2790 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 3002 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
2791 | 3003 | ||
2792 | qla2x00_nvram_config(ha); | 3004 | ha->isp_ops.nvram_config(ha); |
2793 | 3005 | ||
2794 | if (!qla2x00_restart_isp(ha)) { | 3006 | if (!qla2x00_restart_isp(ha)) { |
2795 | clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); | 3007 | clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); |
@@ -2804,10 +3016,9 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) | |||
2804 | 3016 | ||
2805 | ha->flags.online = 1; | 3017 | ha->flags.online = 1; |
2806 | 3018 | ||
2807 | /* Enable ISP interrupts. */ | 3019 | ha->isp_ops.enable_intrs(ha); |
2808 | qla2x00_enable_intrs(ha); | ||
2809 | 3020 | ||
2810 | ha->isp_abort_cnt = 0; | 3021 | ha->isp_abort_cnt = 0; |
2811 | clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags); | 3022 | clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags); |
2812 | } else { /* failed the ISP abort */ | 3023 | } else { /* failed the ISP abort */ |
2813 | ha->flags.online = 1; | 3024 | ha->flags.online = 1; |
@@ -2816,11 +3027,11 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) | |||
2816 | qla_printk(KERN_WARNING, ha, | 3027 | qla_printk(KERN_WARNING, ha, |
2817 | "ISP error recovery failed - " | 3028 | "ISP error recovery failed - " |
2818 | "board disabled\n"); | 3029 | "board disabled\n"); |
2819 | /* | 3030 | /* |
2820 | * The next call disables the board | 3031 | * The next call disables the board |
2821 | * completely. | 3032 | * completely. |
2822 | */ | 3033 | */ |
2823 | qla2x00_reset_adapter(ha); | 3034 | ha->isp_ops.reset_adapter(ha); |
2824 | ha->flags.online = 0; | 3035 | ha->flags.online = 0; |
2825 | clear_bit(ISP_ABORT_RETRY, | 3036 | clear_bit(ISP_ABORT_RETRY, |
2826 | &ha->dpc_flags); | 3037 | &ha->dpc_flags); |
@@ -2828,7 +3039,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) | |||
2828 | } else { /* schedule another ISP abort */ | 3039 | } else { /* schedule another ISP abort */ |
2829 | ha->isp_abort_cnt--; | 3040 | ha->isp_abort_cnt--; |
2830 | DEBUG(printk("qla%ld: ISP abort - " | 3041 | DEBUG(printk("qla%ld: ISP abort - " |
2831 | "retry remainning %d\n", | 3042 | "retry remaining %d\n", |
2832 | ha->host_no, ha->isp_abort_cnt);) | 3043 | ha->host_no, ha->isp_abort_cnt);) |
2833 | status = 1; | 3044 | status = 1; |
2834 | } | 3045 | } |
@@ -2841,7 +3052,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) | |||
2841 | status = 1; | 3052 | status = 1; |
2842 | } | 3053 | } |
2843 | } | 3054 | } |
2844 | 3055 | ||
2845 | } | 3056 | } |
2846 | 3057 | ||
2847 | if (status) { | 3058 | if (status) { |
@@ -2870,43 +3081,52 @@ static int | |||
2870 | qla2x00_restart_isp(scsi_qla_host_t *ha) | 3081 | qla2x00_restart_isp(scsi_qla_host_t *ha) |
2871 | { | 3082 | { |
2872 | uint8_t status = 0; | 3083 | uint8_t status = 0; |
2873 | device_reg_t __iomem *reg = ha->iobase; | 3084 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; |
2874 | unsigned long flags = 0; | 3085 | unsigned long flags = 0; |
2875 | uint32_t wait_time; | 3086 | uint32_t wait_time; |
2876 | 3087 | ||
2877 | /* If firmware needs to be loaded */ | 3088 | /* If firmware needs to be loaded */ |
2878 | if (qla2x00_isp_firmware(ha)) { | 3089 | if (qla2x00_isp_firmware(ha)) { |
2879 | ha->flags.online = 0; | 3090 | ha->flags.online = 0; |
2880 | if (!(status = qla2x00_chip_diag(ha))) { | 3091 | if (!(status = ha->isp_ops.chip_diag(ha))) { |
2881 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) { | 3092 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) { |
2882 | status = qla2x00_setup_chip(ha); | 3093 | status = qla2x00_setup_chip(ha); |
2883 | goto done; | 3094 | goto done; |
2884 | } | 3095 | } |
2885 | 3096 | ||
2886 | reg = ha->iobase; | ||
2887 | |||
2888 | spin_lock_irqsave(&ha->hardware_lock, flags); | 3097 | spin_lock_irqsave(&ha->hardware_lock, flags); |
2889 | 3098 | ||
2890 | /* Disable SRAM, Instruction RAM and GP RAM parity. */ | 3099 | if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha)) { |
2891 | WRT_REG_WORD(®->hccr, (HCCR_ENABLE_PARITY + 0x0)); | 3100 | /* |
2892 | RD_REG_WORD(®->hccr); /* PCI Posting. */ | 3101 | * Disable SRAM, Instruction RAM and GP RAM |
3102 | * parity. | ||
3103 | */ | ||
3104 | WRT_REG_WORD(®->hccr, | ||
3105 | (HCCR_ENABLE_PARITY + 0x0)); | ||
3106 | RD_REG_WORD(®->hccr); | ||
3107 | } | ||
2893 | 3108 | ||
2894 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 3109 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
2895 | 3110 | ||
2896 | status = qla2x00_setup_chip(ha); | 3111 | status = qla2x00_setup_chip(ha); |
2897 | 3112 | ||
2898 | spin_lock_irqsave(&ha->hardware_lock, flags); | 3113 | spin_lock_irqsave(&ha->hardware_lock, flags); |
2899 | 3114 | ||
2900 | /* Enable proper parity */ | 3115 | if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha)) { |
2901 | if (IS_QLA2300(ha)) | 3116 | /* Enable proper parity */ |
2902 | /* SRAM parity */ | 3117 | if (IS_QLA2300(ha)) |
2903 | WRT_REG_WORD(®->hccr, | 3118 | /* SRAM parity */ |
2904 | (HCCR_ENABLE_PARITY + 0x1)); | 3119 | WRT_REG_WORD(®->hccr, |
2905 | else | 3120 | (HCCR_ENABLE_PARITY + 0x1)); |
2906 | /* SRAM, Instruction RAM and GP RAM parity */ | 3121 | else |
2907 | WRT_REG_WORD(®->hccr, | 3122 | /* |
2908 | (HCCR_ENABLE_PARITY + 0x7)); | 3123 | * SRAM, Instruction RAM and GP RAM |
2909 | RD_REG_WORD(®->hccr); /* PCI Posting. */ | 3124 | * parity. |
3125 | */ | ||
3126 | WRT_REG_WORD(®->hccr, | ||
3127 | (HCCR_ENABLE_PARITY + 0x7)); | ||
3128 | RD_REG_WORD(®->hccr); | ||
3129 | } | ||
2910 | 3130 | ||
2911 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 3131 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
2912 | } | 3132 | } |
@@ -2917,9 +3137,11 @@ qla2x00_restart_isp(scsi_qla_host_t *ha) | |||
2917 | clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); | 3137 | clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); |
2918 | if (!(status = qla2x00_fw_ready(ha))) { | 3138 | if (!(status = qla2x00_fw_ready(ha))) { |
2919 | DEBUG(printk("%s(): Start configure loop, " | 3139 | DEBUG(printk("%s(): Start configure loop, " |
2920 | "status = %d\n", | 3140 | "status = %d\n", __func__, status);) |
2921 | __func__, | 3141 | |
2922 | status);) | 3142 | /* Issue a marker after FW becomes ready. */ |
3143 | qla2x00_marker(ha, 0, 0, MK_SYNC_ALL); | ||
3144 | |||
2923 | ha->flags.online = 1; | 3145 | ha->flags.online = 1; |
2924 | /* Wait at most MAX_TARGET RSCNs for a stable link. */ | 3146 | /* Wait at most MAX_TARGET RSCNs for a stable link. */ |
2925 | wait_time = 256; | 3147 | wait_time = 256; |
@@ -2934,7 +3156,7 @@ qla2x00_restart_isp(scsi_qla_host_t *ha) | |||
2934 | } | 3156 | } |
2935 | 3157 | ||
2936 | /* if no cable then assume it's good */ | 3158 | /* if no cable then assume it's good */ |
2937 | if ((ha->device_flags & DFLG_NO_CABLE)) | 3159 | if ((ha->device_flags & DFLG_NO_CABLE)) |
2938 | status = 0; | 3160 | status = 0; |
2939 | 3161 | ||
2940 | DEBUG(printk("%s(): Configure loop done, status = 0x%x\n", | 3162 | DEBUG(printk("%s(): Configure loop done, status = 0x%x\n", |
@@ -2951,16 +3173,15 @@ qla2x00_restart_isp(scsi_qla_host_t *ha) | |||
2951 | * Input: | 3173 | * Input: |
2952 | * ha = adapter block pointer. | 3174 | * ha = adapter block pointer. |
2953 | */ | 3175 | */ |
2954 | static void | 3176 | void |
2955 | qla2x00_reset_adapter(scsi_qla_host_t *ha) | 3177 | qla2x00_reset_adapter(scsi_qla_host_t *ha) |
2956 | { | 3178 | { |
2957 | unsigned long flags = 0; | 3179 | unsigned long flags = 0; |
2958 | device_reg_t __iomem *reg = ha->iobase; | 3180 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; |
2959 | 3181 | ||
2960 | ha->flags.online = 0; | 3182 | ha->flags.online = 0; |
2961 | qla2x00_disable_intrs(ha); | 3183 | ha->isp_ops.disable_intrs(ha); |
2962 | 3184 | ||
2963 | /* Reset RISC processor. */ | ||
2964 | spin_lock_irqsave(&ha->hardware_lock, flags); | 3185 | spin_lock_irqsave(&ha->hardware_lock, flags); |
2965 | WRT_REG_WORD(®->hccr, HCCR_RESET_RISC); | 3186 | WRT_REG_WORD(®->hccr, HCCR_RESET_RISC); |
2966 | RD_REG_WORD(®->hccr); /* PCI Posting. */ | 3187 | RD_REG_WORD(®->hccr); /* PCI Posting. */ |
@@ -2968,3 +3189,505 @@ qla2x00_reset_adapter(scsi_qla_host_t *ha) | |||
2968 | RD_REG_WORD(®->hccr); /* PCI Posting. */ | 3189 | RD_REG_WORD(®->hccr); /* PCI Posting. */ |
2969 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 3190 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
2970 | } | 3191 | } |
3192 | |||
3193 | void | ||
3194 | qla24xx_reset_adapter(scsi_qla_host_t *ha) | ||
3195 | { | ||
3196 | unsigned long flags = 0; | ||
3197 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; | ||
3198 | |||
3199 | ha->flags.online = 0; | ||
3200 | ha->isp_ops.disable_intrs(ha); | ||
3201 | |||
3202 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
3203 | WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_RESET); | ||
3204 | RD_REG_DWORD(®->hccr); | ||
3205 | WRT_REG_DWORD(®->hccr, HCCRX_REL_RISC_PAUSE); | ||
3206 | RD_REG_DWORD(®->hccr); | ||
3207 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
3208 | } | ||
3209 | |||
3210 | int | ||
3211 | qla24xx_nvram_config(scsi_qla_host_t *ha) | ||
3212 | { | ||
3213 | int rval; | ||
3214 | struct init_cb_24xx *icb; | ||
3215 | struct nvram_24xx *nv; | ||
3216 | uint32_t *dptr; | ||
3217 | uint8_t *dptr1, *dptr2; | ||
3218 | uint32_t chksum; | ||
3219 | uint16_t cnt; | ||
3220 | |||
3221 | rval = QLA_SUCCESS; | ||
3222 | icb = (struct init_cb_24xx *)ha->init_cb; | ||
3223 | nv = (struct nvram_24xx *)ha->request_ring; | ||
3224 | |||
3225 | /* Determine NVRAM starting address. */ | ||
3226 | ha->nvram_size = sizeof(struct nvram_24xx); | ||
3227 | ha->nvram_base = FA_NVRAM_FUNC0_ADDR; | ||
3228 | if (PCI_FUNC(ha->pdev->devfn)) | ||
3229 | ha->nvram_base = FA_NVRAM_FUNC1_ADDR; | ||
3230 | |||
3231 | /* Get NVRAM data and calculate checksum. */ | ||
3232 | dptr = (uint32_t *)nv; | ||
3233 | ha->isp_ops.read_nvram(ha, (uint8_t *)dptr, ha->nvram_base, | ||
3234 | ha->nvram_size); | ||
3235 | for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++) | ||
3236 | chksum += le32_to_cpu(*dptr++); | ||
3237 | |||
3238 | DEBUG5(printk("scsi(%ld): Contents of NVRAM\n", ha->host_no)); | ||
3239 | DEBUG5(qla2x00_dump_buffer((uint8_t *)ha->request_ring, | ||
3240 | ha->nvram_size)); | ||
3241 | |||
3242 | /* Bad NVRAM data, set defaults parameters. */ | ||
3243 | if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || nv->id[2] != 'P' | ||
3244 | || nv->id[3] != ' ' || | ||
3245 | nv->nvram_version < __constant_cpu_to_le16(ICB_VERSION)) { | ||
3246 | /* Reset NVRAM data. */ | ||
3247 | qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: " | ||
3248 | "checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0], | ||
3249 | le16_to_cpu(nv->nvram_version)); | ||
3250 | qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet " | ||
3251 | "invalid -- WWPN) defaults.\n"); | ||
3252 | |||
3253 | /* | ||
3254 | * Set default initialization control block. | ||
3255 | */ | ||
3256 | memset(nv, 0, ha->nvram_size); | ||
3257 | nv->nvram_version = __constant_cpu_to_le16(ICB_VERSION); | ||
3258 | nv->version = __constant_cpu_to_le16(ICB_VERSION); | ||
3259 | nv->frame_payload_size = __constant_cpu_to_le16(2048); | ||
3260 | nv->execution_throttle = __constant_cpu_to_le16(0xFFFF); | ||
3261 | nv->exchange_count = __constant_cpu_to_le16(0); | ||
3262 | nv->hard_address = __constant_cpu_to_le16(124); | ||
3263 | nv->port_name[0] = 0x21; | ||
3264 | nv->port_name[1] = 0x00 + PCI_FUNC(ha->pdev->devfn); | ||
3265 | nv->port_name[2] = 0x00; | ||
3266 | nv->port_name[3] = 0xe0; | ||
3267 | nv->port_name[4] = 0x8b; | ||
3268 | nv->port_name[5] = 0x1c; | ||
3269 | nv->port_name[6] = 0x55; | ||
3270 | nv->port_name[7] = 0x86; | ||
3271 | nv->node_name[0] = 0x20; | ||
3272 | nv->node_name[1] = 0x00; | ||
3273 | nv->node_name[2] = 0x00; | ||
3274 | nv->node_name[3] = 0xe0; | ||
3275 | nv->node_name[4] = 0x8b; | ||
3276 | nv->node_name[5] = 0x1c; | ||
3277 | nv->node_name[6] = 0x55; | ||
3278 | nv->node_name[7] = 0x86; | ||
3279 | nv->login_retry_count = __constant_cpu_to_le16(8); | ||
3280 | nv->link_down_timeout = __constant_cpu_to_le16(200); | ||
3281 | nv->interrupt_delay_timer = __constant_cpu_to_le16(0); | ||
3282 | nv->login_timeout = __constant_cpu_to_le16(0); | ||
3283 | nv->firmware_options_1 = | ||
3284 | __constant_cpu_to_le32(BIT_14|BIT_13|BIT_2|BIT_1); | ||
3285 | nv->firmware_options_2 = __constant_cpu_to_le32(2 << 4); | ||
3286 | nv->firmware_options_2 |= __constant_cpu_to_le32(BIT_12); | ||
3287 | nv->firmware_options_3 = __constant_cpu_to_le32(2 << 13); | ||
3288 | nv->host_p = __constant_cpu_to_le32(BIT_11|BIT_10); | ||
3289 | nv->efi_parameters = __constant_cpu_to_le32(0); | ||
3290 | nv->reset_delay = 5; | ||
3291 | nv->max_luns_per_target = __constant_cpu_to_le16(128); | ||
3292 | nv->port_down_retry_count = __constant_cpu_to_le16(30); | ||
3293 | nv->link_down_timeout = __constant_cpu_to_le16(30); | ||
3294 | |||
3295 | rval = 1; | ||
3296 | } | ||
3297 | |||
3298 | /* Reset Initialization control block */ | ||
3299 | memset(icb, 0, sizeof(struct init_cb_24xx)); | ||
3300 | |||
3301 | /* Copy 1st segment. */ | ||
3302 | dptr1 = (uint8_t *)icb; | ||
3303 | dptr2 = (uint8_t *)&nv->version; | ||
3304 | cnt = (uint8_t *)&icb->response_q_inpointer - (uint8_t *)&icb->version; | ||
3305 | while (cnt--) | ||
3306 | *dptr1++ = *dptr2++; | ||
3307 | |||
3308 | icb->login_retry_count = nv->login_retry_count; | ||
3309 | icb->link_down_timeout = nv->link_down_timeout; | ||
3310 | |||
3311 | /* Copy 2nd segment. */ | ||
3312 | dptr1 = (uint8_t *)&icb->interrupt_delay_timer; | ||
3313 | dptr2 = (uint8_t *)&nv->interrupt_delay_timer; | ||
3314 | cnt = (uint8_t *)&icb->reserved_3 - | ||
3315 | (uint8_t *)&icb->interrupt_delay_timer; | ||
3316 | while (cnt--) | ||
3317 | *dptr1++ = *dptr2++; | ||
3318 | |||
3319 | /* | ||
3320 | * Setup driver NVRAM options. | ||
3321 | */ | ||
3322 | if (memcmp(nv->model_name, BINZERO, sizeof(nv->model_name)) != 0) { | ||
3323 | char *st, *en; | ||
3324 | uint16_t index; | ||
3325 | |||
3326 | strncpy(ha->model_number, nv->model_name, | ||
3327 | sizeof(nv->model_name)); | ||
3328 | st = en = ha->model_number; | ||
3329 | en += sizeof(nv->model_name) - 1; | ||
3330 | while (en > st) { | ||
3331 | if (*en != 0x20 && *en != 0x00) | ||
3332 | break; | ||
3333 | *en-- = '\0'; | ||
3334 | } | ||
3335 | |||
3336 | index = (ha->pdev->subsystem_device & 0xff); | ||
3337 | if (index < QLA_MODEL_NAMES) | ||
3338 | ha->model_desc = qla2x00_model_desc[index]; | ||
3339 | } else | ||
3340 | strcpy(ha->model_number, "QLA2462"); | ||
3341 | |||
3342 | /* Prepare nodename */ | ||
3343 | if ((icb->firmware_options_1 & BIT_14) == 0) { | ||
3344 | /* | ||
3345 | * Firmware will apply the following mask if the nodename was | ||
3346 | * not provided. | ||
3347 | */ | ||
3348 | memcpy(icb->node_name, icb->port_name, WWN_SIZE); | ||
3349 | icb->node_name[0] &= 0xF0; | ||
3350 | } | ||
3351 | |||
3352 | /* Set host adapter parameters. */ | ||
3353 | ha->flags.disable_risc_code_load = 0; | ||
3354 | ha->flags.enable_lip_reset = 1; | ||
3355 | ha->flags.enable_lip_full_login = 1; | ||
3356 | ha->flags.enable_target_reset = 1; | ||
3357 | ha->flags.enable_led_scheme = 0; | ||
3358 | |||
3359 | ha->operating_mode = | ||
3360 | (icb->firmware_options_2 & (BIT_6 | BIT_5 | BIT_4)) >> 4; | ||
3361 | |||
3362 | memcpy(ha->fw_seriallink_options24, nv->seriallink_options, | ||
3363 | sizeof(ha->fw_seriallink_options24)); | ||
3364 | |||
3365 | /* save HBA serial number */ | ||
3366 | ha->serial0 = icb->port_name[5]; | ||
3367 | ha->serial1 = icb->port_name[6]; | ||
3368 | ha->serial2 = icb->port_name[7]; | ||
3369 | ha->node_name = icb->node_name; | ||
3370 | ha->port_name = icb->port_name; | ||
3371 | |||
3372 | ha->retry_count = le16_to_cpu(nv->login_retry_count); | ||
3373 | |||
3374 | /* Set minimum login_timeout to 4 seconds. */ | ||
3375 | if (le16_to_cpu(nv->login_timeout) < ql2xlogintimeout) | ||
3376 | nv->login_timeout = cpu_to_le16(ql2xlogintimeout); | ||
3377 | if (le16_to_cpu(nv->login_timeout) < 4) | ||
3378 | nv->login_timeout = __constant_cpu_to_le16(4); | ||
3379 | ha->login_timeout = le16_to_cpu(nv->login_timeout); | ||
3380 | icb->login_timeout = cpu_to_le16(nv->login_timeout); | ||
3381 | |||
3382 | /* Set minimum RATOV to 200 tenths of a second. */ | ||
3383 | ha->r_a_tov = 200; | ||
3384 | |||
3385 | ha->loop_reset_delay = nv->reset_delay; | ||
3386 | |||
3387 | /* Link Down Timeout = 0: | ||
3388 | * | ||
3389 | * When Port Down timer expires we will start returning | ||
3390 | * I/O's to OS with "DID_NO_CONNECT". | ||
3391 | * | ||
3392 | * Link Down Timeout != 0: | ||
3393 | * | ||
3394 | * The driver waits for the link to come up after link down | ||
3395 | * before returning I/Os to OS with "DID_NO_CONNECT". | ||
3396 | */ | ||
3397 | if (le16_to_cpu(nv->link_down_timeout) == 0) { | ||
3398 | ha->loop_down_abort_time = | ||
3399 | (LOOP_DOWN_TIME - LOOP_DOWN_TIMEOUT); | ||
3400 | } else { | ||
3401 | ha->link_down_timeout = le16_to_cpu(nv->link_down_timeout); | ||
3402 | ha->loop_down_abort_time = | ||
3403 | (LOOP_DOWN_TIME - ha->link_down_timeout); | ||
3404 | } | ||
3405 | |||
3406 | /* Need enough time to try and get the port back. */ | ||
3407 | ha->port_down_retry_count = le16_to_cpu(nv->port_down_retry_count); | ||
3408 | if (qlport_down_retry) | ||
3409 | ha->port_down_retry_count = qlport_down_retry; | ||
3410 | |||
3411 | /* Set login_retry_count */ | ||
3412 | ha->login_retry_count = le16_to_cpu(nv->login_retry_count); | ||
3413 | if (ha->port_down_retry_count == | ||
3414 | le16_to_cpu(nv->port_down_retry_count) && | ||
3415 | ha->port_down_retry_count > 3) | ||
3416 | ha->login_retry_count = ha->port_down_retry_count; | ||
3417 | else if (ha->port_down_retry_count > (int)ha->login_retry_count) | ||
3418 | ha->login_retry_count = ha->port_down_retry_count; | ||
3419 | if (ql2xloginretrycount) | ||
3420 | ha->login_retry_count = ql2xloginretrycount; | ||
3421 | |||
3422 | if (rval) { | ||
3423 | DEBUG2_3(printk(KERN_WARNING | ||
3424 | "scsi(%ld): NVRAM configuration failed!\n", ha->host_no)); | ||
3425 | } | ||
3426 | return (rval); | ||
3427 | } | ||
3428 | |||
3429 | int | ||
3430 | qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) | ||
3431 | { | ||
3432 | int rval; | ||
3433 | uint16_t cnt; | ||
3434 | uint16_t *risc_code; | ||
3435 | unsigned long risc_address; | ||
3436 | unsigned long risc_code_size; | ||
3437 | int num; | ||
3438 | int i; | ||
3439 | uint16_t *req_ring; | ||
3440 | struct qla_fw_info *fw_iter; | ||
3441 | |||
3442 | rval = QLA_SUCCESS; | ||
3443 | |||
3444 | /* Load firmware sequences */ | ||
3445 | fw_iter = ha->brd_info->fw_info; | ||
3446 | *srisc_addr = *ha->brd_info->fw_info->fwstart; | ||
3447 | while (fw_iter->addressing != FW_INFO_ADDR_NOMORE) { | ||
3448 | risc_code = fw_iter->fwcode; | ||
3449 | risc_code_size = *fw_iter->fwlen; | ||
3450 | |||
3451 | if (fw_iter->addressing == FW_INFO_ADDR_NORMAL) { | ||
3452 | risc_address = *fw_iter->fwstart; | ||
3453 | } else { | ||
3454 | /* Extended address */ | ||
3455 | risc_address = *fw_iter->lfwstart; | ||
3456 | } | ||
3457 | |||
3458 | num = 0; | ||
3459 | rval = 0; | ||
3460 | while (risc_code_size > 0 && !rval) { | ||
3461 | cnt = (uint16_t)(ha->fw_transfer_size >> 1); | ||
3462 | if (cnt > risc_code_size) | ||
3463 | cnt = risc_code_size; | ||
3464 | |||
3465 | DEBUG7(printk("scsi(%ld): Loading risc segment@ " | ||
3466 | "addr %p, number of bytes 0x%x, offset 0x%lx.\n", | ||
3467 | ha->host_no, risc_code, cnt, risc_address)); | ||
3468 | |||
3469 | req_ring = (uint16_t *)ha->request_ring; | ||
3470 | for (i = 0; i < cnt; i++) | ||
3471 | req_ring[i] = cpu_to_le16(risc_code[i]); | ||
3472 | |||
3473 | if (fw_iter->addressing == FW_INFO_ADDR_NORMAL) { | ||
3474 | rval = qla2x00_load_ram(ha, ha->request_dma, | ||
3475 | risc_address, cnt); | ||
3476 | } else { | ||
3477 | rval = qla2x00_load_ram_ext(ha, | ||
3478 | ha->request_dma, risc_address, cnt); | ||
3479 | } | ||
3480 | if (rval) { | ||
3481 | DEBUG(printk("scsi(%ld): [ERROR] Failed to " | ||
3482 | "load segment %d of firmware\n", | ||
3483 | ha->host_no, num)); | ||
3484 | qla_printk(KERN_WARNING, ha, | ||
3485 | "[ERROR] Failed to load segment %d of " | ||
3486 | "firmware\n", num); | ||
3487 | |||
3488 | qla2x00_dump_regs(ha); | ||
3489 | break; | ||
3490 | } | ||
3491 | |||
3492 | risc_code += cnt; | ||
3493 | risc_address += cnt; | ||
3494 | risc_code_size -= cnt; | ||
3495 | num++; | ||
3496 | } | ||
3497 | |||
3498 | /* Next firmware sequence */ | ||
3499 | fw_iter++; | ||
3500 | } | ||
3501 | |||
3502 | return (rval); | ||
3503 | } | ||
3504 | |||
3505 | int | ||
3506 | qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr) | ||
3507 | { | ||
3508 | int rval; | ||
3509 | int segments, fragment; | ||
3510 | uint32_t faddr; | ||
3511 | uint32_t *dcode, dlen; | ||
3512 | uint32_t risc_addr; | ||
3513 | uint32_t risc_size; | ||
3514 | uint32_t i; | ||
3515 | |||
3516 | rval = QLA_SUCCESS; | ||
3517 | |||
3518 | segments = FA_RISC_CODE_SEGMENTS; | ||
3519 | faddr = FA_RISC_CODE_ADDR; | ||
3520 | dcode = (uint32_t *)ha->request_ring; | ||
3521 | *srisc_addr = 0; | ||
3522 | |||
3523 | /* Validate firmware image by checking version. */ | ||
3524 | qla24xx_read_flash_data(ha, dcode, faddr + 4, 4); | ||
3525 | for (i = 0; i < 4; i++) | ||
3526 | dcode[i] = be32_to_cpu(dcode[i]); | ||
3527 | if ((dcode[0] == 0xffffffff && dcode[1] == 0xffffffff && | ||
3528 | dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) || | ||
3529 | (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && | ||
3530 | dcode[3] == 0)) { | ||
3531 | qla_printk(KERN_WARNING, ha, | ||
3532 | "Unable to verify integrity of flash firmware image!\n"); | ||
3533 | qla_printk(KERN_WARNING, ha, | ||
3534 | "Firmware data: %08x %08x %08x %08x!\n", dcode[0], | ||
3535 | dcode[1], dcode[2], dcode[3]); | ||
3536 | |||
3537 | return QLA_FUNCTION_FAILED; | ||
3538 | } | ||
3539 | |||
3540 | while (segments && rval == QLA_SUCCESS) { | ||
3541 | /* Read segment's load information. */ | ||
3542 | qla24xx_read_flash_data(ha, dcode, faddr, 4); | ||
3543 | |||
3544 | risc_addr = be32_to_cpu(dcode[2]); | ||
3545 | *srisc_addr = *srisc_addr == 0 ? risc_addr : *srisc_addr; | ||
3546 | risc_size = be32_to_cpu(dcode[3]); | ||
3547 | |||
3548 | fragment = 0; | ||
3549 | while (risc_size > 0 && rval == QLA_SUCCESS) { | ||
3550 | dlen = (uint32_t)(ha->fw_transfer_size >> 2); | ||
3551 | if (dlen > risc_size) | ||
3552 | dlen = risc_size; | ||
3553 | |||
3554 | DEBUG7(printk("scsi(%ld): Loading risc segment@ risc " | ||
3555 | "addr %x, number of dwords 0x%x, offset 0x%x.\n", | ||
3556 | ha->host_no, risc_addr, dlen, faddr)); | ||
3557 | |||
3558 | qla24xx_read_flash_data(ha, dcode, faddr, dlen); | ||
3559 | for (i = 0; i < dlen; i++) | ||
3560 | dcode[i] = swab32(dcode[i]); | ||
3561 | |||
3562 | rval = qla2x00_load_ram_ext(ha, ha->request_dma, | ||
3563 | risc_addr, dlen); | ||
3564 | if (rval) { | ||
3565 | DEBUG(printk("scsi(%ld):[ERROR] Failed to load " | ||
3566 | "segment %d of firmware\n", ha->host_no, | ||
3567 | fragment)); | ||
3568 | qla_printk(KERN_WARNING, ha, | ||
3569 | "[ERROR] Failed to load segment %d of " | ||
3570 | "firmware\n", fragment); | ||
3571 | break; | ||
3572 | } | ||
3573 | |||
3574 | faddr += dlen; | ||
3575 | risc_addr += dlen; | ||
3576 | risc_size -= dlen; | ||
3577 | fragment++; | ||
3578 | } | ||
3579 | |||
3580 | /* Next segment. */ | ||
3581 | segments--; | ||
3582 | } | ||
3583 | |||
3584 | return rval; | ||
3585 | } | ||
3586 | |||
3587 | int | ||
3588 | qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr) | ||
3589 | { | ||
3590 | int rval; | ||
3591 | int segments, fragment; | ||
3592 | uint32_t *dcode, dlen; | ||
3593 | uint32_t risc_addr; | ||
3594 | uint32_t risc_size; | ||
3595 | uint32_t i; | ||
3596 | const struct firmware *fw_entry; | ||
3597 | uint32_t *fwcode, fwclen; | ||
3598 | |||
3599 | if (request_firmware(&fw_entry, ha->brd_info->fw_fname, | ||
3600 | &ha->pdev->dev)) { | ||
3601 | qla_printk(KERN_ERR, ha, | ||
3602 | "Firmware image file not available: '%s'\n", | ||
3603 | ha->brd_info->fw_fname); | ||
3604 | return QLA_FUNCTION_FAILED; | ||
3605 | } | ||
3606 | |||
3607 | rval = QLA_SUCCESS; | ||
3608 | |||
3609 | segments = FA_RISC_CODE_SEGMENTS; | ||
3610 | dcode = (uint32_t *)ha->request_ring; | ||
3611 | *srisc_addr = 0; | ||
3612 | fwcode = (uint32_t *)fw_entry->data; | ||
3613 | fwclen = 0; | ||
3614 | |||
3615 | /* Validate firmware image by checking version. */ | ||
3616 | if (fw_entry->size < 8 * sizeof(uint32_t)) { | ||
3617 | qla_printk(KERN_WARNING, ha, | ||
3618 | "Unable to verify integrity of flash firmware image " | ||
3619 | "(%Zd)!\n", fw_entry->size); | ||
3620 | goto fail_fw_integrity; | ||
3621 | } | ||
3622 | for (i = 0; i < 4; i++) | ||
3623 | dcode[i] = be32_to_cpu(fwcode[i + 4]); | ||
3624 | if ((dcode[0] == 0xffffffff && dcode[1] == 0xffffffff && | ||
3625 | dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) || | ||
3626 | (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && | ||
3627 | dcode[3] == 0)) { | ||
3628 | qla_printk(KERN_WARNING, ha, | ||
3629 | "Unable to verify integrity of flash firmware image!\n"); | ||
3630 | qla_printk(KERN_WARNING, ha, | ||
3631 | "Firmware data: %08x %08x %08x %08x!\n", dcode[0], | ||
3632 | dcode[1], dcode[2], dcode[3]); | ||
3633 | goto fail_fw_integrity; | ||
3634 | } | ||
3635 | |||
3636 | while (segments && rval == QLA_SUCCESS) { | ||
3637 | risc_addr = be32_to_cpu(fwcode[2]); | ||
3638 | *srisc_addr = *srisc_addr == 0 ? risc_addr : *srisc_addr; | ||
3639 | risc_size = be32_to_cpu(fwcode[3]); | ||
3640 | |||
3641 | /* Validate firmware image size. */ | ||
3642 | fwclen += risc_size * sizeof(uint32_t); | ||
3643 | if (fw_entry->size < fwclen) { | ||
3644 | qla_printk(KERN_WARNING, ha, | ||
3645 | "Unable to verify integrity of flash firmware " | ||
3646 | "image (%Zd)!\n", fw_entry->size); | ||
3647 | goto fail_fw_integrity; | ||
3648 | } | ||
3649 | |||
3650 | fragment = 0; | ||
3651 | while (risc_size > 0 && rval == QLA_SUCCESS) { | ||
3652 | dlen = (uint32_t)(ha->fw_transfer_size >> 2); | ||
3653 | if (dlen > risc_size) | ||
3654 | dlen = risc_size; | ||
3655 | |||
3656 | DEBUG7(printk("scsi(%ld): Loading risc segment@ risc " | ||
3657 | "addr %x, number of dwords 0x%x.\n", ha->host_no, | ||
3658 | risc_addr, dlen)); | ||
3659 | |||
3660 | for (i = 0; i < dlen; i++) | ||
3661 | dcode[i] = swab32(fwcode[i]); | ||
3662 | |||
3663 | rval = qla2x00_load_ram_ext(ha, ha->request_dma, | ||
3664 | risc_addr, dlen); | ||
3665 | if (rval) { | ||
3666 | DEBUG(printk("scsi(%ld):[ERROR] Failed to load " | ||
3667 | "segment %d of firmware\n", ha->host_no, | ||
3668 | fragment)); | ||
3669 | qla_printk(KERN_WARNING, ha, | ||
3670 | "[ERROR] Failed to load segment %d of " | ||
3671 | "firmware\n", fragment); | ||
3672 | break; | ||
3673 | } | ||
3674 | |||
3675 | fwcode += dlen; | ||
3676 | risc_addr += dlen; | ||
3677 | risc_size -= dlen; | ||
3678 | fragment++; | ||
3679 | } | ||
3680 | |||
3681 | /* Next segment. */ | ||
3682 | segments--; | ||
3683 | } | ||
3684 | |||
3685 | release_firmware(fw_entry); | ||
3686 | return rval; | ||
3687 | |||
3688 | fail_fw_integrity: | ||
3689 | |||
3690 | release_firmware(fw_entry); | ||
3691 | return QLA_FUNCTION_FAILED; | ||
3692 | |||
3693 | } | ||