diff options
author | James Smart <James.Smart@Emulex.Com> | 2007-06-17 20:56:39 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-06-17 23:38:11 -0400 |
commit | 858c9f6c19c6f9bf86cbbc64ce0d17c61d6131b8 (patch) | |
tree | 9591b15b4424066023e375ad0aa33fdd37e1c452 /drivers/scsi/lpfc/lpfc_attr.c | |
parent | 92d7f7b0cde3ad2260e7462b40867b57efd49851 (diff) |
[SCSI] lpfc: bug fixes
Following the NPIV support, the following changes have been accumulated
in the testing and qualification of the driver:
- Fix affinity of ELS ring to slow/deferred event processing
- Fix Ring attention masks
- Defer dev_loss_tmo timeout handling to worker thread
- Consolidate link down error classification for better error checking
- Remove unused/deprecated nlp_initiator_tmr timer
- Fix for async scan - move adapter init code back into pci_probe_one
context. Fix async scan interfaces.
- Expand validation of ability to create vports
- Extract VPI resource cnt from firmware
- Tuning of Login/Reject policies to better deal with overwhelmned targets
- Misc ELS and discovery fixes
- Export the npiv_enable attribute to sysfs
- Mailbox handling fix
- Add debugfs support
- A few other small misc fixes:
- wrong return values, double-frees, bad locking
- Added adapter failure heartbeat
Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_attr.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_attr.c | 117 |
1 files changed, 67 insertions, 50 deletions
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 5cb7924fe3d7..6a2c1ac42442 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
@@ -282,9 +282,7 @@ lpfc_issue_lip(struct Scsi_Host *shost) | |||
282 | } | 282 | } |
283 | 283 | ||
284 | lpfc_set_loopback_flag(phba); | 284 | lpfc_set_loopback_flag(phba); |
285 | if (mbxstatus == MBX_TIMEOUT) | 285 | if (mbxstatus != MBX_TIMEOUT) |
286 | pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | ||
287 | else | ||
288 | mempool_free(pmboxq, phba->mbox_mem_pool); | 286 | mempool_free(pmboxq, phba->mbox_mem_pool); |
289 | 287 | ||
290 | if (mbxstatus == MBXERR_ERROR) | 288 | if (mbxstatus == MBXERR_ERROR) |
@@ -439,30 +437,11 @@ lpfc_board_mode_store(struct class_device *cdev, const char *buf, size_t count) | |||
439 | return -EIO; | 437 | return -EIO; |
440 | } | 438 | } |
441 | 439 | ||
442 | static ssize_t | ||
443 | lpfc_max_vpi_show(struct class_device *cdev, char *buf) | ||
444 | { | ||
445 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
446 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; | ||
447 | struct lpfc_hba *phba = vport->phba; | ||
448 | |||
449 | return snprintf(buf, PAGE_SIZE, "%d\n", phba->max_vpi); | ||
450 | } | ||
451 | |||
452 | static ssize_t | ||
453 | lpfc_used_vpi_show(struct class_device *cdev, char *buf) | ||
454 | { | ||
455 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
456 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; | ||
457 | struct lpfc_hba *phba = vport->phba; | ||
458 | |||
459 | /* Don't count the physical port */ | ||
460 | return snprintf(buf, PAGE_SIZE, "%d\n", phba->vpi_cnt-1); | ||
461 | } | ||
462 | |||
463 | int | 440 | int |
464 | lpfc_get_hba_info(struct lpfc_hba *phba, uint32_t *mxri, | 441 | lpfc_get_hba_info(struct lpfc_hba *phba, |
465 | uint32_t *axri, uint32_t *mrpi, uint32_t *arpi) | 442 | uint32_t *mxri, uint32_t *axri, |
443 | uint32_t *mrpi, uint32_t *arpi, | ||
444 | uint32_t *mvpi, uint32_t *avpi) | ||
466 | { | 445 | { |
467 | struct lpfc_sli *psli = &phba->sli; | 446 | struct lpfc_sli *psli = &phba->sli; |
468 | LPFC_MBOXQ_t *pmboxq; | 447 | LPFC_MBOXQ_t *pmboxq; |
@@ -498,9 +477,7 @@ lpfc_get_hba_info(struct lpfc_hba *phba, uint32_t *mxri, | |||
498 | rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2); | 477 | rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2); |
499 | 478 | ||
500 | if (rc != MBX_SUCCESS) { | 479 | if (rc != MBX_SUCCESS) { |
501 | if (rc == MBX_TIMEOUT) | 480 | if (rc != MBX_TIMEOUT) |
502 | pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | ||
503 | else | ||
504 | mempool_free(pmboxq, phba->mbox_mem_pool); | 481 | mempool_free(pmboxq, phba->mbox_mem_pool); |
505 | return 0; | 482 | return 0; |
506 | } | 483 | } |
@@ -513,6 +490,10 @@ lpfc_get_hba_info(struct lpfc_hba *phba, uint32_t *mxri, | |||
513 | *mxri = pmb->un.varRdConfig.max_xri; | 490 | *mxri = pmb->un.varRdConfig.max_xri; |
514 | if (axri) | 491 | if (axri) |
515 | *axri = pmb->un.varRdConfig.avail_xri; | 492 | *axri = pmb->un.varRdConfig.avail_xri; |
493 | if (mvpi) | ||
494 | *mvpi = pmb->un.varRdConfig.max_vpi; | ||
495 | if (avpi) | ||
496 | *avpi = pmb->un.varRdConfig.avail_vpi; | ||
516 | 497 | ||
517 | mempool_free(pmboxq, phba->mbox_mem_pool); | 498 | mempool_free(pmboxq, phba->mbox_mem_pool); |
518 | return 1; | 499 | return 1; |
@@ -526,7 +507,7 @@ lpfc_max_rpi_show(struct class_device *cdev, char *buf) | |||
526 | struct lpfc_hba *phba = vport->phba; | 507 | struct lpfc_hba *phba = vport->phba; |
527 | uint32_t cnt; | 508 | uint32_t cnt; |
528 | 509 | ||
529 | if (lpfc_get_hba_info(phba, NULL, NULL, &cnt, NULL)) | 510 | if (lpfc_get_hba_info(phba, NULL, NULL, &cnt, NULL, NULL, NULL)) |
530 | return snprintf(buf, PAGE_SIZE, "%d\n", cnt); | 511 | return snprintf(buf, PAGE_SIZE, "%d\n", cnt); |
531 | return snprintf(buf, PAGE_SIZE, "Unknown\n"); | 512 | return snprintf(buf, PAGE_SIZE, "Unknown\n"); |
532 | } | 513 | } |
@@ -539,7 +520,7 @@ lpfc_used_rpi_show(struct class_device *cdev, char *buf) | |||
539 | struct lpfc_hba *phba = vport->phba; | 520 | struct lpfc_hba *phba = vport->phba; |
540 | uint32_t cnt, acnt; | 521 | uint32_t cnt, acnt; |
541 | 522 | ||
542 | if (lpfc_get_hba_info(phba, NULL, NULL, &cnt, &acnt)) | 523 | if (lpfc_get_hba_info(phba, NULL, NULL, &cnt, &acnt, NULL, NULL)) |
543 | return snprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt)); | 524 | return snprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt)); |
544 | return snprintf(buf, PAGE_SIZE, "Unknown\n"); | 525 | return snprintf(buf, PAGE_SIZE, "Unknown\n"); |
545 | } | 526 | } |
@@ -552,7 +533,7 @@ lpfc_max_xri_show(struct class_device *cdev, char *buf) | |||
552 | struct lpfc_hba *phba = vport->phba; | 533 | struct lpfc_hba *phba = vport->phba; |
553 | uint32_t cnt; | 534 | uint32_t cnt; |
554 | 535 | ||
555 | if (lpfc_get_hba_info(phba, &cnt, NULL, NULL, NULL)) | 536 | if (lpfc_get_hba_info(phba, &cnt, NULL, NULL, NULL, NULL, NULL)) |
556 | return snprintf(buf, PAGE_SIZE, "%d\n", cnt); | 537 | return snprintf(buf, PAGE_SIZE, "%d\n", cnt); |
557 | return snprintf(buf, PAGE_SIZE, "Unknown\n"); | 538 | return snprintf(buf, PAGE_SIZE, "Unknown\n"); |
558 | } | 539 | } |
@@ -565,7 +546,33 @@ lpfc_used_xri_show(struct class_device *cdev, char *buf) | |||
565 | struct lpfc_hba *phba = vport->phba; | 546 | struct lpfc_hba *phba = vport->phba; |
566 | uint32_t cnt, acnt; | 547 | uint32_t cnt, acnt; |
567 | 548 | ||
568 | if (lpfc_get_hba_info(phba, &cnt, &acnt, NULL, NULL)) | 549 | if (lpfc_get_hba_info(phba, &cnt, &acnt, NULL, NULL, NULL, NULL)) |
550 | return snprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt)); | ||
551 | return snprintf(buf, PAGE_SIZE, "Unknown\n"); | ||
552 | } | ||
553 | |||
554 | static ssize_t | ||
555 | lpfc_max_vpi_show(struct class_device *cdev, char *buf) | ||
556 | { | ||
557 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
558 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; | ||
559 | struct lpfc_hba *phba = vport->phba; | ||
560 | uint32_t cnt; | ||
561 | |||
562 | if (lpfc_get_hba_info(phba, NULL, NULL, NULL, NULL, &cnt, NULL)) | ||
563 | return snprintf(buf, PAGE_SIZE, "%d\n", cnt); | ||
564 | return snprintf(buf, PAGE_SIZE, "Unknown\n"); | ||
565 | } | ||
566 | |||
567 | static ssize_t | ||
568 | lpfc_used_vpi_show(struct class_device *cdev, char *buf) | ||
569 | { | ||
570 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
571 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; | ||
572 | struct lpfc_hba *phba = vport->phba; | ||
573 | uint32_t cnt, acnt; | ||
574 | |||
575 | if (lpfc_get_hba_info(phba, NULL, NULL, NULL, NULL, &cnt, &acnt)) | ||
569 | return snprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt)); | 576 | return snprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt)); |
570 | return snprintf(buf, PAGE_SIZE, "Unknown\n"); | 577 | return snprintf(buf, PAGE_SIZE, "Unknown\n"); |
571 | } | 578 | } |
@@ -995,9 +1002,7 @@ MODULE_PARM_DESC(lpfc_sli_mode, "SLI mode selector:" | |||
995 | " 2 - select SLI-2 even on SLI-3 capable HBAs," | 1002 | " 2 - select SLI-2 even on SLI-3 capable HBAs," |
996 | " 3 - select SLI-3"); | 1003 | " 3 - select SLI-3"); |
997 | 1004 | ||
998 | int lpfc_npiv_enable = 0; | 1005 | LPFC_ATTR_R(npiv_enable, 0, 0, 1, "Enable NPIV functionality"); |
999 | module_param(lpfc_npiv_enable, int, 0); | ||
1000 | MODULE_PARM_DESC(lpfc_npiv_enable, "Enable NPIV functionality"); | ||
1001 | 1006 | ||
1002 | /* | 1007 | /* |
1003 | # lpfc_nodev_tmo: If set, it will hold all I/O errors on devices that disappear | 1008 | # lpfc_nodev_tmo: If set, it will hold all I/O errors on devices that disappear |
@@ -1052,6 +1057,24 @@ lpfc_nodev_tmo_init(struct lpfc_hba *phba, int val) | |||
1052 | return -EINVAL; | 1057 | return -EINVAL; |
1053 | } | 1058 | } |
1054 | 1059 | ||
1060 | static void | ||
1061 | lpfc_update_rport_devloss_tmo(struct lpfc_hba *phba) | ||
1062 | { | ||
1063 | struct lpfc_vport *vport; | ||
1064 | struct Scsi_Host *shost; | ||
1065 | struct lpfc_nodelist *ndlp; | ||
1066 | |||
1067 | list_for_each_entry(vport, &phba->port_list, listentry) { | ||
1068 | shost = lpfc_shost_from_vport(vport); | ||
1069 | spin_lock_irq(shost->host_lock); | ||
1070 | list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) | ||
1071 | if (ndlp->rport) | ||
1072 | ndlp->rport->dev_loss_tmo = | ||
1073 | phba->cfg_devloss_tmo; | ||
1074 | spin_unlock_irq(shost->host_lock); | ||
1075 | } | ||
1076 | } | ||
1077 | |||
1055 | static int | 1078 | static int |
1056 | lpfc_nodev_tmo_set(struct lpfc_hba *phba, int val) | 1079 | lpfc_nodev_tmo_set(struct lpfc_hba *phba, int val) |
1057 | { | 1080 | { |
@@ -1067,6 +1090,7 @@ lpfc_nodev_tmo_set(struct lpfc_hba *phba, int val) | |||
1067 | if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) { | 1090 | if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) { |
1068 | phba->cfg_nodev_tmo = val; | 1091 | phba->cfg_nodev_tmo = val; |
1069 | phba->cfg_devloss_tmo = val; | 1092 | phba->cfg_devloss_tmo = val; |
1093 | lpfc_update_rport_devloss_tmo(phba); | ||
1070 | return 0; | 1094 | return 0; |
1071 | } | 1095 | } |
1072 | 1096 | ||
@@ -1102,6 +1126,7 @@ lpfc_devloss_tmo_set(struct lpfc_hba *phba, int val) | |||
1102 | phba->cfg_nodev_tmo = val; | 1126 | phba->cfg_nodev_tmo = val; |
1103 | phba->cfg_devloss_tmo = val; | 1127 | phba->cfg_devloss_tmo = val; |
1104 | phba->dev_loss_tmo_changed = 1; | 1128 | phba->dev_loss_tmo_changed = 1; |
1129 | lpfc_update_rport_devloss_tmo(phba); | ||
1105 | return 0; | 1130 | return 0; |
1106 | } | 1131 | } |
1107 | 1132 | ||
@@ -1358,6 +1383,7 @@ struct class_device_attribute *lpfc_hba_attrs[] = { | |||
1358 | &class_device_attr_lpfc_multi_ring_type, | 1383 | &class_device_attr_lpfc_multi_ring_type, |
1359 | &class_device_attr_lpfc_fdmi_on, | 1384 | &class_device_attr_lpfc_fdmi_on, |
1360 | &class_device_attr_lpfc_max_luns, | 1385 | &class_device_attr_lpfc_max_luns, |
1386 | &class_device_attr_lpfc_npiv_enable, | ||
1361 | &class_device_attr_nport_evt_cnt, | 1387 | &class_device_attr_nport_evt_cnt, |
1362 | &class_device_attr_management_version, | 1388 | &class_device_attr_management_version, |
1363 | &class_device_attr_board_mode, | 1389 | &class_device_attr_board_mode, |
@@ -1641,8 +1667,6 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count) | |||
1641 | 1667 | ||
1642 | if (rc != MBX_SUCCESS) { | 1668 | if (rc != MBX_SUCCESS) { |
1643 | if (rc == MBX_TIMEOUT) { | 1669 | if (rc == MBX_TIMEOUT) { |
1644 | phba->sysfs_mbox.mbox->mbox_cmpl = | ||
1645 | lpfc_sli_def_mbox_cmpl; | ||
1646 | phba->sysfs_mbox.mbox = NULL; | 1670 | phba->sysfs_mbox.mbox = NULL; |
1647 | } | 1671 | } |
1648 | sysfs_mbox_idle(phba); | 1672 | sysfs_mbox_idle(phba); |
@@ -1886,9 +1910,7 @@ lpfc_get_stats(struct Scsi_Host *shost) | |||
1886 | rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2); | 1910 | rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2); |
1887 | 1911 | ||
1888 | if (rc != MBX_SUCCESS) { | 1912 | if (rc != MBX_SUCCESS) { |
1889 | if (rc == MBX_TIMEOUT) | 1913 | if (rc != MBX_TIMEOUT) |
1890 | pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | ||
1891 | else | ||
1892 | mempool_free(pmboxq, phba->mbox_mem_pool); | 1914 | mempool_free(pmboxq, phba->mbox_mem_pool); |
1893 | return NULL; | 1915 | return NULL; |
1894 | } | 1916 | } |
@@ -1913,9 +1935,7 @@ lpfc_get_stats(struct Scsi_Host *shost) | |||
1913 | rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2); | 1935 | rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2); |
1914 | 1936 | ||
1915 | if (rc != MBX_SUCCESS) { | 1937 | if (rc != MBX_SUCCESS) { |
1916 | if (rc == MBX_TIMEOUT) | 1938 | if (rc != MBX_TIMEOUT) |
1917 | pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | ||
1918 | else | ||
1919 | mempool_free(pmboxq, phba->mbox_mem_pool); | 1939 | mempool_free(pmboxq, phba->mbox_mem_pool); |
1920 | return NULL; | 1940 | return NULL; |
1921 | } | 1941 | } |
@@ -1993,9 +2013,7 @@ lpfc_reset_stats(struct Scsi_Host *shost) | |||
1993 | rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2); | 2013 | rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2); |
1994 | 2014 | ||
1995 | if (rc != MBX_SUCCESS) { | 2015 | if (rc != MBX_SUCCESS) { |
1996 | if (rc == MBX_TIMEOUT) | 2016 | if (rc != MBX_TIMEOUT) |
1997 | pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | ||
1998 | else | ||
1999 | mempool_free(pmboxq, phba->mbox_mem_pool); | 2017 | mempool_free(pmboxq, phba->mbox_mem_pool); |
2000 | return; | 2018 | return; |
2001 | } | 2019 | } |
@@ -2013,9 +2031,7 @@ lpfc_reset_stats(struct Scsi_Host *shost) | |||
2013 | rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2); | 2031 | rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2); |
2014 | 2032 | ||
2015 | if (rc != MBX_SUCCESS) { | 2033 | if (rc != MBX_SUCCESS) { |
2016 | if (rc == MBX_TIMEOUT) | 2034 | if (rc != MBX_TIMEOUT) |
2017 | pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | ||
2018 | else | ||
2019 | mempool_free( pmboxq, phba->mbox_mem_pool); | 2035 | mempool_free( pmboxq, phba->mbox_mem_pool); |
2020 | return; | 2036 | return; |
2021 | } | 2037 | } |
@@ -2253,6 +2269,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) | |||
2253 | lpfc_max_luns_init(phba, lpfc_max_luns); | 2269 | lpfc_max_luns_init(phba, lpfc_max_luns); |
2254 | lpfc_poll_tmo_init(phba, lpfc_poll_tmo); | 2270 | lpfc_poll_tmo_init(phba, lpfc_poll_tmo); |
2255 | lpfc_peer_port_login_init(phba, lpfc_peer_port_login); | 2271 | lpfc_peer_port_login_init(phba, lpfc_peer_port_login); |
2272 | lpfc_npiv_enable_init(phba, lpfc_npiv_enable); | ||
2256 | lpfc_vport_restrict_login_init(phba, lpfc_vport_restrict_login); | 2273 | lpfc_vport_restrict_login_init(phba, lpfc_vport_restrict_login); |
2257 | lpfc_use_msi_init(phba, lpfc_use_msi); | 2274 | lpfc_use_msi_init(phba, lpfc_use_msi); |
2258 | lpfc_devloss_tmo_init(phba, lpfc_devloss_tmo); | 2275 | lpfc_devloss_tmo_init(phba, lpfc_devloss_tmo); |