diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 10:19:18 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 10:19:18 -0400 |
commit | 33cf23b0a535475aead57707cb9f4fe135a93544 (patch) | |
tree | 67e14f77f0eeab847a26a6cbfcb44eecb5fa2fda /drivers/scsi/qla4xxx/ql4_init.c | |
parent | 7a9b149212f3716c598afe973b6261fd58453b7a (diff) | |
parent | 95bb335c0ebe96afe926387a1ef3a096bd884a82 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (182 commits)
[SCSI] aacraid: add an ifdef'd device delete case instead of taking the device offline
[SCSI] aacraid: prohibit access to array container space
[SCSI] aacraid: add support for handling ATA pass-through commands.
[SCSI] aacraid: expose physical devices for models with newer firmware
[SCSI] aacraid: respond automatically to volumes added by config tool
[SCSI] fcoe: fix fcoe module ref counting
[SCSI] libfcoe: FIP Keep-Alive messages for VPorts are sent with incorrect port_id and wwn
[SCSI] libfcoe: Fix incorrect MAC address clearing
[SCSI] fcoe: fix a circular locking issue with rtnl and sysfs mutex
[SCSI] libfc: Move the port_id into lport
[SCSI] fcoe: move link speed checking into its own routine
[SCSI] libfc: Remove extra pointer check
[SCSI] libfc: Remove unused fc_get_host_port_type
[SCSI] fcoe: fixes wrong error exit in fcoe_create
[SCSI] libfc: set seq_id for incoming sequence
[SCSI] qla2xxx: Updates to ISP82xx support.
[SCSI] qla2xxx: Optionally disable target reset.
[SCSI] qla2xxx: ensure flash operation and host reset via sg_reset are mutually exclusive
[SCSI] qla2xxx: Silence bogus warning by gcc for wrap and did.
[SCSI] qla2xxx: T10 DIF support added.
...
Diffstat (limited to 'drivers/scsi/qla4xxx/ql4_init.c')
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_init.c | 374 |
1 files changed, 285 insertions, 89 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index 92329a461c6..5510df8a7fa 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c | |||
@@ -189,6 +189,78 @@ static int qla4xxx_init_local_data(struct scsi_qla_host *ha) | |||
189 | return qla4xxx_get_firmware_status(ha); | 189 | return qla4xxx_get_firmware_status(ha); |
190 | } | 190 | } |
191 | 191 | ||
192 | static uint8_t | ||
193 | qla4xxx_wait_for_ip_config(struct scsi_qla_host *ha) | ||
194 | { | ||
195 | uint8_t ipv4_wait = 0; | ||
196 | uint8_t ipv6_wait = 0; | ||
197 | int8_t ip_address[IPv6_ADDR_LEN] = {0} ; | ||
198 | |||
199 | /* If both IPv4 & IPv6 are enabled, possibly only one | ||
200 | * IP address may be acquired, so check to see if we | ||
201 | * need to wait for another */ | ||
202 | if (is_ipv4_enabled(ha) && is_ipv6_enabled(ha)) { | ||
203 | if (((ha->addl_fw_state & FW_ADDSTATE_DHCPv4_ENABLED) != 0) && | ||
204 | ((ha->addl_fw_state & | ||
205 | FW_ADDSTATE_DHCPv4_LEASE_ACQUIRED) == 0)) { | ||
206 | ipv4_wait = 1; | ||
207 | } | ||
208 | if (((ha->ipv6_addl_options & | ||
209 | IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE) != 0) && | ||
210 | ((ha->ipv6_link_local_state == IP_ADDRSTATE_ACQUIRING) || | ||
211 | (ha->ipv6_addr0_state == IP_ADDRSTATE_ACQUIRING) || | ||
212 | (ha->ipv6_addr1_state == IP_ADDRSTATE_ACQUIRING))) { | ||
213 | |||
214 | ipv6_wait = 1; | ||
215 | |||
216 | if ((ha->ipv6_link_local_state == | ||
217 | IP_ADDRSTATE_PREFERRED) || | ||
218 | (ha->ipv6_addr0_state == IP_ADDRSTATE_PREFERRED) || | ||
219 | (ha->ipv6_addr1_state == IP_ADDRSTATE_PREFERRED)) { | ||
220 | DEBUG2(printk(KERN_INFO "scsi%ld: %s: " | ||
221 | "Preferred IP configured." | ||
222 | " Don't wait!\n", ha->host_no, | ||
223 | __func__)); | ||
224 | ipv6_wait = 0; | ||
225 | } | ||
226 | if (memcmp(&ha->ipv6_default_router_addr, ip_address, | ||
227 | IPv6_ADDR_LEN) == 0) { | ||
228 | DEBUG2(printk(KERN_INFO "scsi%ld: %s: " | ||
229 | "No Router configured. " | ||
230 | "Don't wait!\n", ha->host_no, | ||
231 | __func__)); | ||
232 | ipv6_wait = 0; | ||
233 | } | ||
234 | if ((ha->ipv6_default_router_state == | ||
235 | IPV6_RTRSTATE_MANUAL) && | ||
236 | (ha->ipv6_link_local_state == | ||
237 | IP_ADDRSTATE_TENTATIVE) && | ||
238 | (memcmp(&ha->ipv6_link_local_addr, | ||
239 | &ha->ipv6_default_router_addr, 4) == 0)) { | ||
240 | DEBUG2(printk("scsi%ld: %s: LinkLocal Router & " | ||
241 | "IP configured. Don't wait!\n", | ||
242 | ha->host_no, __func__)); | ||
243 | ipv6_wait = 0; | ||
244 | } | ||
245 | } | ||
246 | if (ipv4_wait || ipv6_wait) { | ||
247 | DEBUG2(printk("scsi%ld: %s: Wait for additional " | ||
248 | "IP(s) \"", ha->host_no, __func__)); | ||
249 | if (ipv4_wait) | ||
250 | DEBUG2(printk("IPv4 ")); | ||
251 | if (ha->ipv6_link_local_state == IP_ADDRSTATE_ACQUIRING) | ||
252 | DEBUG2(printk("IPv6LinkLocal ")); | ||
253 | if (ha->ipv6_addr0_state == IP_ADDRSTATE_ACQUIRING) | ||
254 | DEBUG2(printk("IPv6Addr0 ")); | ||
255 | if (ha->ipv6_addr1_state == IP_ADDRSTATE_ACQUIRING) | ||
256 | DEBUG2(printk("IPv6Addr1 ")); | ||
257 | DEBUG2(printk("\"\n")); | ||
258 | } | ||
259 | } | ||
260 | |||
261 | return ipv4_wait|ipv6_wait; | ||
262 | } | ||
263 | |||
192 | static int qla4xxx_fw_ready(struct scsi_qla_host *ha) | 264 | static int qla4xxx_fw_ready(struct scsi_qla_host *ha) |
193 | { | 265 | { |
194 | uint32_t timeout_count; | 266 | uint32_t timeout_count; |
@@ -226,38 +298,80 @@ static int qla4xxx_fw_ready(struct scsi_qla_host *ha) | |||
226 | continue; | 298 | continue; |
227 | } | 299 | } |
228 | 300 | ||
301 | if (ha->firmware_state & FW_STATE_WAIT_AUTOCONNECT) { | ||
302 | DEBUG2(printk(KERN_INFO "scsi%ld: %s: fwstate:" | ||
303 | "AUTOCONNECT in progress\n", | ||
304 | ha->host_no, __func__)); | ||
305 | } | ||
306 | |||
307 | if (ha->firmware_state & FW_STATE_CONFIGURING_IP) { | ||
308 | DEBUG2(printk(KERN_INFO "scsi%ld: %s: fwstate:" | ||
309 | " CONFIGURING IP\n", | ||
310 | ha->host_no, __func__)); | ||
311 | /* | ||
312 | * Check for link state after 15 secs and if link is | ||
313 | * still DOWN then, cable is unplugged. Ignore "DHCP | ||
314 | * in Progress/CONFIGURING IP" bit to check if firmware | ||
315 | * is in ready state or not after 15 secs. | ||
316 | * This is applicable for both 2.x & 3.x firmware | ||
317 | */ | ||
318 | if (timeout_count <= (ADAPTER_INIT_TOV - 15)) { | ||
319 | if (ha->addl_fw_state & FW_ADDSTATE_LINK_UP) { | ||
320 | DEBUG2(printk(KERN_INFO "scsi%ld: %s:" | ||
321 | " LINK UP (Cable plugged)\n", | ||
322 | ha->host_no, __func__)); | ||
323 | } else if (ha->firmware_state & | ||
324 | (FW_STATE_CONFIGURING_IP | | ||
325 | FW_STATE_READY)) { | ||
326 | DEBUG2(printk(KERN_INFO "scsi%ld: %s: " | ||
327 | "LINK DOWN (Cable unplugged)\n", | ||
328 | ha->host_no, __func__)); | ||
329 | ha->firmware_state = FW_STATE_READY; | ||
330 | } | ||
331 | } | ||
332 | } | ||
333 | |||
229 | if (ha->firmware_state == FW_STATE_READY) { | 334 | if (ha->firmware_state == FW_STATE_READY) { |
230 | DEBUG2(dev_info(&ha->pdev->dev, "Firmware Ready..\n")); | 335 | /* If DHCP IP Addr is available, retrieve it now. */ |
231 | /* The firmware is ready to process SCSI commands. */ | 336 | if (test_and_clear_bit(DPC_GET_DHCP_IP_ADDR, |
232 | DEBUG2(dev_info(&ha->pdev->dev, | 337 | &ha->dpc_flags)) |
233 | "scsi%ld: %s: MEDIA TYPE - %s\n", | 338 | qla4xxx_get_dhcp_ip_address(ha); |
234 | ha->host_no, | 339 | |
235 | __func__, (ha->addl_fw_state & | 340 | if (!qla4xxx_wait_for_ip_config(ha) || |
236 | FW_ADDSTATE_OPTICAL_MEDIA) | 341 | timeout_count == 1) { |
237 | != 0 ? "OPTICAL" : "COPPER")); | 342 | DEBUG2(dev_info(&ha->pdev->dev, |
238 | DEBUG2(dev_info(&ha->pdev->dev, | 343 | "Firmware Ready..\n")); |
239 | "scsi%ld: %s: DHCP STATE Enabled " | 344 | /* The firmware is ready to process SCSI |
240 | "%s\n", | 345 | commands. */ |
241 | ha->host_no, __func__, | 346 | DEBUG2(dev_info(&ha->pdev->dev, |
242 | (ha->addl_fw_state & | 347 | "scsi%ld: %s: MEDIA TYPE" |
243 | FW_ADDSTATE_DHCP_ENABLED) != 0 ? | 348 | " - %s\n", ha->host_no, |
244 | "YES" : "NO")); | 349 | __func__, (ha->addl_fw_state & |
245 | DEBUG2(dev_info(&ha->pdev->dev, | 350 | FW_ADDSTATE_OPTICAL_MEDIA) |
246 | "scsi%ld: %s: LINK %s\n", | 351 | != 0 ? "OPTICAL" : "COPPER")); |
247 | ha->host_no, __func__, | 352 | DEBUG2(dev_info(&ha->pdev->dev, |
248 | (ha->addl_fw_state & | 353 | "scsi%ld: %s: DHCPv4 STATE" |
249 | FW_ADDSTATE_LINK_UP) != 0 ? | 354 | " Enabled %s\n", ha->host_no, |
250 | "UP" : "DOWN")); | 355 | __func__, (ha->addl_fw_state & |
251 | DEBUG2(dev_info(&ha->pdev->dev, | 356 | FW_ADDSTATE_DHCPv4_ENABLED) != 0 ? |
252 | "scsi%ld: %s: iSNS Service " | 357 | "YES" : "NO")); |
253 | "Started %s\n", | 358 | DEBUG2(dev_info(&ha->pdev->dev, |
254 | ha->host_no, __func__, | 359 | "scsi%ld: %s: LINK %s\n", |
255 | (ha->addl_fw_state & | 360 | ha->host_no, __func__, |
256 | FW_ADDSTATE_ISNS_SVC_ENABLED) != 0 ? | 361 | (ha->addl_fw_state & |
257 | "YES" : "NO")); | 362 | FW_ADDSTATE_LINK_UP) != 0 ? |
258 | 363 | "UP" : "DOWN")); | |
259 | ready = 1; | 364 | DEBUG2(dev_info(&ha->pdev->dev, |
260 | break; | 365 | "scsi%ld: %s: iSNS Service " |
366 | "Started %s\n", | ||
367 | ha->host_no, __func__, | ||
368 | (ha->addl_fw_state & | ||
369 | FW_ADDSTATE_ISNS_SVC_ENABLED) != 0 ? | ||
370 | "YES" : "NO")); | ||
371 | |||
372 | ready = 1; | ||
373 | break; | ||
374 | } | ||
261 | } | 375 | } |
262 | DEBUG2(printk("scsi%ld: %s: waiting on fw, state=%x:%x - " | 376 | DEBUG2(printk("scsi%ld: %s: waiting on fw, state=%x:%x - " |
263 | "seconds expired= %d\n", ha->host_no, __func__, | 377 | "seconds expired= %d\n", ha->host_no, __func__, |
@@ -272,15 +386,19 @@ static int qla4xxx_fw_ready(struct scsi_qla_host *ha) | |||
272 | msleep(1000); | 386 | msleep(1000); |
273 | } /* end of for */ | 387 | } /* end of for */ |
274 | 388 | ||
275 | if (timeout_count == 0) | 389 | if (timeout_count <= 0) |
276 | DEBUG2(printk("scsi%ld: %s: FW Initialization timed out!\n", | 390 | DEBUG2(printk("scsi%ld: %s: FW Initialization timed out!\n", |
277 | ha->host_no, __func__)); | 391 | ha->host_no, __func__)); |
278 | 392 | ||
279 | if (ha->firmware_state & FW_STATE_DHCP_IN_PROGRESS) { | 393 | if (ha->firmware_state & FW_STATE_CONFIGURING_IP) { |
280 | DEBUG2(printk("scsi%ld: %s: FW is reporting its waiting to" | 394 | DEBUG2(printk("scsi%ld: %s: FW initialized, but is reporting " |
281 | " grab an IP address from DHCP server\n", | 395 | "it's waiting to configure an IP address\n", |
282 | ha->host_no, __func__)); | 396 | ha->host_no, __func__)); |
283 | ready = 1; | 397 | ready = 1; |
398 | } else if (ha->firmware_state & FW_STATE_WAIT_AUTOCONNECT) { | ||
399 | DEBUG2(printk("scsi%ld: %s: FW initialized, but " | ||
400 | "auto-discovery still in process\n", | ||
401 | ha->host_no, __func__)); | ||
284 | } | 402 | } |
285 | 403 | ||
286 | return ready; | 404 | return ready; |
@@ -387,6 +505,7 @@ static int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha, | |||
387 | struct dev_db_entry *fw_ddb_entry = NULL; | 505 | struct dev_db_entry *fw_ddb_entry = NULL; |
388 | dma_addr_t fw_ddb_entry_dma; | 506 | dma_addr_t fw_ddb_entry_dma; |
389 | int status = QLA_ERROR; | 507 | int status = QLA_ERROR; |
508 | uint32_t conn_err; | ||
390 | 509 | ||
391 | if (ddb_entry == NULL) { | 510 | if (ddb_entry == NULL) { |
392 | DEBUG2(printk("scsi%ld: %s: ddb_entry is NULL\n", ha->host_no, | 511 | DEBUG2(printk("scsi%ld: %s: ddb_entry is NULL\n", ha->host_no, |
@@ -407,7 +526,7 @@ static int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha, | |||
407 | 526 | ||
408 | if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, fw_ddb_entry, | 527 | if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, fw_ddb_entry, |
409 | fw_ddb_entry_dma, NULL, NULL, | 528 | fw_ddb_entry_dma, NULL, NULL, |
410 | &ddb_entry->fw_ddb_device_state, NULL, | 529 | &ddb_entry->fw_ddb_device_state, &conn_err, |
411 | &ddb_entry->tcp_source_port_num, | 530 | &ddb_entry->tcp_source_port_num, |
412 | &ddb_entry->connection_id) == | 531 | &ddb_entry->connection_id) == |
413 | QLA_ERROR) { | 532 | QLA_ERROR) { |
@@ -419,6 +538,7 @@ static int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha, | |||
419 | } | 538 | } |
420 | 539 | ||
421 | status = QLA_SUCCESS; | 540 | status = QLA_SUCCESS; |
541 | ddb_entry->options = le16_to_cpu(fw_ddb_entry->options); | ||
422 | ddb_entry->target_session_id = le16_to_cpu(fw_ddb_entry->tsid); | 542 | ddb_entry->target_session_id = le16_to_cpu(fw_ddb_entry->tsid); |
423 | ddb_entry->task_mgmt_timeout = | 543 | ddb_entry->task_mgmt_timeout = |
424 | le16_to_cpu(fw_ddb_entry->def_timeout); | 544 | le16_to_cpu(fw_ddb_entry->def_timeout); |
@@ -442,11 +562,44 @@ static int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha, | |||
442 | memcpy(&ddb_entry->ip_addr[0], &fw_ddb_entry->ip_addr[0], | 562 | memcpy(&ddb_entry->ip_addr[0], &fw_ddb_entry->ip_addr[0], |
443 | min(sizeof(ddb_entry->ip_addr), sizeof(fw_ddb_entry->ip_addr))); | 563 | min(sizeof(ddb_entry->ip_addr), sizeof(fw_ddb_entry->ip_addr))); |
444 | 564 | ||
445 | DEBUG2(printk("scsi%ld: %s: ddb[%d] - State= %x status= %d.\n", | 565 | ddb_entry->iscsi_max_burst_len = fw_ddb_entry->iscsi_max_burst_len; |
446 | ha->host_no, __func__, fw_ddb_index, | 566 | ddb_entry->iscsi_max_outsnd_r2t = fw_ddb_entry->iscsi_max_outsnd_r2t; |
447 | ddb_entry->fw_ddb_device_state, status)); | 567 | ddb_entry->iscsi_first_burst_len = fw_ddb_entry->iscsi_first_burst_len; |
448 | 568 | ddb_entry->iscsi_max_rcv_data_seg_len = | |
449 | exit_update_ddb: | 569 | fw_ddb_entry->iscsi_max_rcv_data_seg_len; |
570 | ddb_entry->iscsi_max_snd_data_seg_len = | ||
571 | fw_ddb_entry->iscsi_max_snd_data_seg_len; | ||
572 | |||
573 | if (ddb_entry->options & DDB_OPT_IPV6_DEVICE) { | ||
574 | memcpy(&ddb_entry->remote_ipv6_addr, | ||
575 | fw_ddb_entry->ip_addr, | ||
576 | min(sizeof(ddb_entry->remote_ipv6_addr), | ||
577 | sizeof(fw_ddb_entry->ip_addr))); | ||
578 | memcpy(&ddb_entry->link_local_ipv6_addr, | ||
579 | fw_ddb_entry->link_local_ipv6_addr, | ||
580 | min(sizeof(ddb_entry->link_local_ipv6_addr), | ||
581 | sizeof(fw_ddb_entry->link_local_ipv6_addr))); | ||
582 | |||
583 | DEBUG2(dev_info(&ha->pdev->dev, "%s: DDB[%d] osIdx = %d " | ||
584 | "State %04x ConnErr %08x IP %pI6 " | ||
585 | ":%04d \"%s\"\n", | ||
586 | __func__, fw_ddb_index, | ||
587 | ddb_entry->os_target_id, | ||
588 | ddb_entry->fw_ddb_device_state, | ||
589 | conn_err, fw_ddb_entry->ip_addr, | ||
590 | le16_to_cpu(fw_ddb_entry->port), | ||
591 | fw_ddb_entry->iscsi_name)); | ||
592 | } else | ||
593 | DEBUG2(dev_info(&ha->pdev->dev, "%s: DDB[%d] osIdx = %d " | ||
594 | "State %04x ConnErr %08x IP %pI4 " | ||
595 | ":%04d \"%s\"\n", | ||
596 | __func__, fw_ddb_index, | ||
597 | ddb_entry->os_target_id, | ||
598 | ddb_entry->fw_ddb_device_state, | ||
599 | conn_err, fw_ddb_entry->ip_addr, | ||
600 | le16_to_cpu(fw_ddb_entry->port), | ||
601 | fw_ddb_entry->iscsi_name)); | ||
602 | exit_update_ddb: | ||
450 | if (fw_ddb_entry) | 603 | if (fw_ddb_entry) |
451 | dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), | 604 | dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), |
452 | fw_ddb_entry, fw_ddb_entry_dma); | 605 | fw_ddb_entry, fw_ddb_entry_dma); |
@@ -492,6 +645,40 @@ static struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha, | |||
492 | } | 645 | } |
493 | 646 | ||
494 | /** | 647 | /** |
648 | * qla4_is_relogin_allowed - Are we allowed to login? | ||
649 | * @ha: Pointer to host adapter structure. | ||
650 | * @conn_err: Last connection error associated with the ddb | ||
651 | * | ||
652 | * This routine tests the given connection error to determine if | ||
653 | * we are allowed to login. | ||
654 | **/ | ||
655 | int qla4_is_relogin_allowed(struct scsi_qla_host *ha, uint32_t conn_err) | ||
656 | { | ||
657 | uint32_t err_code, login_rsp_sts_class; | ||
658 | int relogin = 1; | ||
659 | |||
660 | err_code = ((conn_err & 0x00ff0000) >> 16); | ||
661 | login_rsp_sts_class = ((conn_err & 0x0000ff00) >> 8); | ||
662 | if (err_code == 0x1c || err_code == 0x06) { | ||
663 | DEBUG2(dev_info(&ha->pdev->dev, | ||
664 | ": conn_err=0x%08x, send target completed" | ||
665 | " or access denied failure\n", conn_err)); | ||
666 | relogin = 0; | ||
667 | } | ||
668 | if ((err_code == 0x08) && (login_rsp_sts_class == 0x02)) { | ||
669 | /* Login Response PDU returned an error. | ||
670 | Login Response Status in Error Code Detail | ||
671 | indicates login should not be retried.*/ | ||
672 | DEBUG2(dev_info(&ha->pdev->dev, | ||
673 | ": conn_err=0x%08x, do not retry relogin\n", | ||
674 | conn_err)); | ||
675 | relogin = 0; | ||
676 | } | ||
677 | |||
678 | return relogin; | ||
679 | } | ||
680 | |||
681 | /** | ||
495 | * qla4xxx_configure_ddbs - builds driver ddb list | 682 | * qla4xxx_configure_ddbs - builds driver ddb list |
496 | * @ha: Pointer to host adapter structure. | 683 | * @ha: Pointer to host adapter structure. |
497 | * | 684 | * |
@@ -505,18 +692,30 @@ static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha) | |||
505 | uint32_t fw_ddb_index = 0; | 692 | uint32_t fw_ddb_index = 0; |
506 | uint32_t next_fw_ddb_index = 0; | 693 | uint32_t next_fw_ddb_index = 0; |
507 | uint32_t ddb_state; | 694 | uint32_t ddb_state; |
508 | uint32_t conn_err, err_code; | 695 | uint32_t conn_err; |
509 | struct ddb_entry *ddb_entry; | 696 | struct ddb_entry *ddb_entry; |
697 | struct dev_db_entry *fw_ddb_entry = NULL; | ||
698 | dma_addr_t fw_ddb_entry_dma; | ||
699 | uint32_t ipv6_device; | ||
510 | uint32_t new_tgt; | 700 | uint32_t new_tgt; |
511 | 701 | ||
702 | fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), | ||
703 | &fw_ddb_entry_dma, GFP_KERNEL); | ||
704 | if (fw_ddb_entry == NULL) { | ||
705 | DEBUG2(dev_info(&ha->pdev->dev, "%s: DMA alloc failed\n", | ||
706 | __func__)); | ||
707 | return QLA_ERROR; | ||
708 | } | ||
709 | |||
512 | dev_info(&ha->pdev->dev, "Initializing DDBs ...\n"); | 710 | dev_info(&ha->pdev->dev, "Initializing DDBs ...\n"); |
513 | for (fw_ddb_index = 0; fw_ddb_index < MAX_DDB_ENTRIES; | 711 | for (fw_ddb_index = 0; fw_ddb_index < MAX_DDB_ENTRIES; |
514 | fw_ddb_index = next_fw_ddb_index) { | 712 | fw_ddb_index = next_fw_ddb_index) { |
515 | /* First, let's see if a device exists here */ | 713 | /* First, let's see if a device exists here */ |
516 | if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, NULL, 0, NULL, | 714 | if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, fw_ddb_entry, |
517 | &next_fw_ddb_index, &ddb_state, | 715 | 0, NULL, &next_fw_ddb_index, |
518 | &conn_err, NULL, NULL) == | 716 | &ddb_state, &conn_err, |
519 | QLA_ERROR) { | 717 | NULL, NULL) == |
718 | QLA_ERROR) { | ||
520 | DEBUG2(printk("scsi%ld: %s: get_ddb_entry, " | 719 | DEBUG2(printk("scsi%ld: %s: get_ddb_entry, " |
521 | "fw_ddb_index %d failed", ha->host_no, | 720 | "fw_ddb_index %d failed", ha->host_no, |
522 | __func__, fw_ddb_index)); | 721 | __func__, fw_ddb_index)); |
@@ -533,18 +732,19 @@ static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha) | |||
533 | /* Try and login to device */ | 732 | /* Try and login to device */ |
534 | DEBUG2(printk("scsi%ld: %s: Login to DDB[%d]\n", | 733 | DEBUG2(printk("scsi%ld: %s: Login to DDB[%d]\n", |
535 | ha->host_no, __func__, fw_ddb_index)); | 734 | ha->host_no, __func__, fw_ddb_index)); |
536 | err_code = ((conn_err & 0x00ff0000) >> 16); | 735 | ipv6_device = le16_to_cpu(fw_ddb_entry->options) & |
537 | if (err_code == 0x1c || err_code == 0x06) { | 736 | DDB_OPT_IPV6_DEVICE; |
538 | DEBUG2(printk("scsi%ld: %s send target " | 737 | if (qla4_is_relogin_allowed(ha, conn_err) && |
539 | "completed " | 738 | ((!ipv6_device && |
540 | "or access denied failure\n", | 739 | *((uint32_t *)fw_ddb_entry->ip_addr)) |
541 | ha->host_no, __func__)); | 740 | || ipv6_device)) { |
542 | } else { | ||
543 | qla4xxx_set_ddb_entry(ha, fw_ddb_index, 0); | 741 | qla4xxx_set_ddb_entry(ha, fw_ddb_index, 0); |
544 | if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, | 742 | if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, |
545 | NULL, 0, NULL, &next_fw_ddb_index, | 743 | NULL, 0, NULL, |
546 | &ddb_state, &conn_err, NULL, NULL) | 744 | &next_fw_ddb_index, |
547 | == QLA_ERROR) { | 745 | &ddb_state, &conn_err, |
746 | NULL, NULL) | ||
747 | == QLA_ERROR) { | ||
548 | DEBUG2(printk("scsi%ld: %s:" | 748 | DEBUG2(printk("scsi%ld: %s:" |
549 | "get_ddb_entry %d failed\n", | 749 | "get_ddb_entry %d failed\n", |
550 | ha->host_no, | 750 | ha->host_no, |
@@ -599,7 +799,6 @@ next_one: | |||
599 | struct qla4_relog_scan { | 799 | struct qla4_relog_scan { |
600 | int halt_wait; | 800 | int halt_wait; |
601 | uint32_t conn_err; | 801 | uint32_t conn_err; |
602 | uint32_t err_code; | ||
603 | uint32_t fw_ddb_index; | 802 | uint32_t fw_ddb_index; |
604 | uint32_t next_fw_ddb_index; | 803 | uint32_t next_fw_ddb_index; |
605 | uint32_t fw_ddb_device_state; | 804 | uint32_t fw_ddb_device_state; |
@@ -609,18 +808,7 @@ static int qla4_test_rdy(struct scsi_qla_host *ha, struct qla4_relog_scan *rs) | |||
609 | { | 808 | { |
610 | struct ddb_entry *ddb_entry; | 809 | struct ddb_entry *ddb_entry; |
611 | 810 | ||
612 | /* | 811 | if (qla4_is_relogin_allowed(ha, rs->conn_err)) { |
613 | * Don't want to do a relogin if connection | ||
614 | * error is 0x1c. | ||
615 | */ | ||
616 | rs->err_code = ((rs->conn_err & 0x00ff0000) >> 16); | ||
617 | if (rs->err_code == 0x1c || rs->err_code == 0x06) { | ||
618 | DEBUG2(printk( | ||
619 | "scsi%ld: %s send target" | ||
620 | " completed or " | ||
621 | "access denied failure\n", | ||
622 | ha->host_no, __func__)); | ||
623 | } else { | ||
624 | /* We either have a device that is in | 812 | /* We either have a device that is in |
625 | * the process of relogging in or a | 813 | * the process of relogging in or a |
626 | * device that is waiting to be | 814 | * device that is waiting to be |
@@ -908,7 +1096,7 @@ static void qla4x00_pci_config(struct scsi_qla_host *ha) | |||
908 | static int qla4xxx_start_firmware_from_flash(struct scsi_qla_host *ha) | 1096 | static int qla4xxx_start_firmware_from_flash(struct scsi_qla_host *ha) |
909 | { | 1097 | { |
910 | int status = QLA_ERROR; | 1098 | int status = QLA_ERROR; |
911 | uint32_t max_wait_time; | 1099 | unsigned long max_wait_time; |
912 | unsigned long flags; | 1100 | unsigned long flags; |
913 | uint32_t mbox_status; | 1101 | uint32_t mbox_status; |
914 | 1102 | ||
@@ -940,7 +1128,10 @@ static int qla4xxx_start_firmware_from_flash(struct scsi_qla_host *ha) | |||
940 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 1128 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
941 | 1129 | ||
942 | /* Wait for firmware to come UP. */ | 1130 | /* Wait for firmware to come UP. */ |
943 | max_wait_time = FIRMWARE_UP_TOV * 4; | 1131 | DEBUG2(printk(KERN_INFO "scsi%ld: %s: Wait up to %d seconds for " |
1132 | "boot firmware to complete...\n", | ||
1133 | ha->host_no, __func__, FIRMWARE_UP_TOV)); | ||
1134 | max_wait_time = jiffies + (FIRMWARE_UP_TOV * HZ); | ||
944 | do { | 1135 | do { |
945 | uint32_t ctrl_status; | 1136 | uint32_t ctrl_status; |
946 | 1137 | ||
@@ -954,16 +1145,15 @@ static int qla4xxx_start_firmware_from_flash(struct scsi_qla_host *ha) | |||
954 | if (mbox_status == MBOX_STS_COMMAND_COMPLETE) | 1145 | if (mbox_status == MBOX_STS_COMMAND_COMPLETE) |
955 | break; | 1146 | break; |
956 | 1147 | ||
957 | DEBUG2(printk("scsi%ld: %s: Waiting for boot firmware to " | 1148 | DEBUG2(printk(KERN_INFO "scsi%ld: %s: Waiting for boot " |
958 | "complete... ctrl_sts=0x%x, remaining=%d\n", | 1149 | "firmware to complete... ctrl_sts=0x%x\n", |
959 | ha->host_no, __func__, ctrl_status, | 1150 | ha->host_no, __func__, ctrl_status)); |
960 | max_wait_time)); | ||
961 | 1151 | ||
962 | msleep(250); | 1152 | msleep_interruptible(250); |
963 | } while ((max_wait_time--)); | 1153 | } while (!time_after_eq(jiffies, max_wait_time)); |
964 | 1154 | ||
965 | if (mbox_status == MBOX_STS_COMMAND_COMPLETE) { | 1155 | if (mbox_status == MBOX_STS_COMMAND_COMPLETE) { |
966 | DEBUG(printk("scsi%ld: %s: Firmware has started\n", | 1156 | DEBUG(printk(KERN_INFO "scsi%ld: %s: Firmware has started\n", |
967 | ha->host_no, __func__)); | 1157 | ha->host_no, __func__)); |
968 | 1158 | ||
969 | spin_lock_irqsave(&ha->hardware_lock, flags); | 1159 | spin_lock_irqsave(&ha->hardware_lock, flags); |
@@ -1141,6 +1331,7 @@ int qla4xxx_initialize_adapter(struct scsi_qla_host *ha, | |||
1141 | int status = QLA_ERROR; | 1331 | int status = QLA_ERROR; |
1142 | int8_t ip_address[IP_ADDR_LEN] = {0} ; | 1332 | int8_t ip_address[IP_ADDR_LEN] = {0} ; |
1143 | 1333 | ||
1334 | clear_bit(AF_ONLINE, &ha->flags); | ||
1144 | ha->eeprom_cmd_data = 0; | 1335 | ha->eeprom_cmd_data = 0; |
1145 | 1336 | ||
1146 | qla4x00_pci_config(ha); | 1337 | qla4x00_pci_config(ha); |
@@ -1166,7 +1357,7 @@ int qla4xxx_initialize_adapter(struct scsi_qla_host *ha, | |||
1166 | * the ddb_list and wait for DHCP lease acquired aen to come in | 1357 | * the ddb_list and wait for DHCP lease acquired aen to come in |
1167 | * followed by 0x8014 aen" to trigger the tgt discovery process. | 1358 | * followed by 0x8014 aen" to trigger the tgt discovery process. |
1168 | */ | 1359 | */ |
1169 | if (ha->firmware_state & FW_STATE_DHCP_IN_PROGRESS) | 1360 | if (ha->firmware_state & FW_STATE_CONFIGURING_IP) |
1170 | goto exit_init_online; | 1361 | goto exit_init_online; |
1171 | 1362 | ||
1172 | /* Skip device discovery if ip and subnet is zero */ | 1363 | /* Skip device discovery if ip and subnet is zero */ |
@@ -1270,8 +1461,8 @@ static void qla4xxx_add_device_dynamically(struct scsi_qla_host *ha, | |||
1270 | * | 1461 | * |
1271 | * This routine processes a Decive Database Changed AEN Event. | 1462 | * This routine processes a Decive Database Changed AEN Event. |
1272 | **/ | 1463 | **/ |
1273 | int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, | 1464 | int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index, |
1274 | uint32_t fw_ddb_index, uint32_t state) | 1465 | uint32_t state, uint32_t conn_err) |
1275 | { | 1466 | { |
1276 | struct ddb_entry * ddb_entry; | 1467 | struct ddb_entry * ddb_entry; |
1277 | uint32_t old_fw_ddb_device_state; | 1468 | uint32_t old_fw_ddb_device_state; |
@@ -1318,19 +1509,24 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, | |||
1318 | * the device came back. | 1509 | * the device came back. |
1319 | */ | 1510 | */ |
1320 | } else { | 1511 | } else { |
1321 | /* Device went away, try to relogin. */ | 1512 | /* Device went away, mark device missing */ |
1322 | /* Mark device missing */ | 1513 | if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE) { |
1323 | if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE) | 1514 | DEBUG2(dev_info(&ha->pdev->dev, "%s mark missing " |
1515 | "ddb_entry 0x%p sess 0x%p conn 0x%p\n", | ||
1516 | __func__, ddb_entry, | ||
1517 | ddb_entry->sess, ddb_entry->conn)); | ||
1324 | qla4xxx_mark_device_missing(ha, ddb_entry); | 1518 | qla4xxx_mark_device_missing(ha, ddb_entry); |
1519 | } | ||
1520 | |||
1325 | /* | 1521 | /* |
1326 | * Relogin if device state changed to a not active state. | 1522 | * Relogin if device state changed to a not active state. |
1327 | * However, do not relogin if this aen is a result of an IOCTL | 1523 | * However, do not relogin if a RELOGIN is in process, or |
1328 | * logout (DF_NO_RELOGIN) or if this is a discovered device. | 1524 | * we are not allowed to relogin to this DDB. |
1329 | */ | 1525 | */ |
1330 | if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_FAILED && | 1526 | if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_FAILED && |
1331 | !test_bit(DF_RELOGIN, &ddb_entry->flags) && | 1527 | !test_bit(DF_RELOGIN, &ddb_entry->flags) && |
1332 | !test_bit(DF_NO_RELOGIN, &ddb_entry->flags) && | 1528 | !test_bit(DF_NO_RELOGIN, &ddb_entry->flags) && |
1333 | !test_bit(DF_ISNS_DISCOVERED, &ddb_entry->flags)) { | 1529 | qla4_is_relogin_allowed(ha, conn_err)) { |
1334 | /* | 1530 | /* |
1335 | * This triggers a relogin. After the relogin_timer | 1531 | * This triggers a relogin. After the relogin_timer |
1336 | * expires, the relogin gets scheduled. We must wait a | 1532 | * expires, the relogin gets scheduled. We must wait a |
@@ -1338,7 +1534,7 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, | |||
1338 | * with failed device_state or a logout response before | 1534 | * with failed device_state or a logout response before |
1339 | * we can issue another relogin. | 1535 | * we can issue another relogin. |
1340 | */ | 1536 | */ |
1341 | /* Firmware padds this timeout: (time2wait +1). | 1537 | /* Firmware pads this timeout: (time2wait +1). |
1342 | * Driver retry to login should be longer than F/W. | 1538 | * Driver retry to login should be longer than F/W. |
1343 | * Otherwise F/W will fail | 1539 | * Otherwise F/W will fail |
1344 | * set_ddb() mbx cmd with 0x4005 since it still | 1540 | * set_ddb() mbx cmd with 0x4005 since it still |