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 | |
| 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>
| -rw-r--r-- | drivers/scsi/lpfc/Makefile | 2 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 40 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_attr.c | 117 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 16 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_ct.c | 217 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_debugfs.c | 508 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_debugfs.h | 50 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_disc.h | 3 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 410 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 276 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_hw.h | 21 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 228 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_mbox.c | 18 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_mem.c | 3 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_nportdisc.c | 63 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 1 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 208 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.h | 3 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_vport.c | 39 |
19 files changed, 1798 insertions, 425 deletions
diff --git a/drivers/scsi/lpfc/Makefile b/drivers/scsi/lpfc/Makefile index d94c9e0212a7..1c286707dd5f 100644 --- a/drivers/scsi/lpfc/Makefile +++ b/drivers/scsi/lpfc/Makefile | |||
| @@ -28,4 +28,4 @@ obj-$(CONFIG_SCSI_LPFC) := lpfc.o | |||
| 28 | 28 | ||
| 29 | lpfc-objs := lpfc_mem.o lpfc_sli.o lpfc_ct.o lpfc_els.o lpfc_hbadisc.o \ | 29 | lpfc-objs := lpfc_mem.o lpfc_sli.o lpfc_ct.o lpfc_els.o lpfc_hbadisc.o \ |
| 30 | lpfc_init.o lpfc_mbox.o lpfc_nportdisc.o lpfc_scsi.o lpfc_attr.o \ | 30 | lpfc_init.o lpfc_mbox.o lpfc_nportdisc.o lpfc_scsi.o lpfc_attr.o \ |
| 31 | lpfc_vport.o | 31 | lpfc_vport.o lpfc_debugfs.o |
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 4b9019d7d508..f8f64d6485cd 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
| @@ -23,7 +23,6 @@ | |||
| 23 | 23 | ||
| 24 | struct lpfc_sli2_slim; | 24 | struct lpfc_sli2_slim; |
| 25 | 25 | ||
| 26 | |||
| 27 | #define LPFC_MAX_TARGET 256 /* max number of targets supported */ | 26 | #define LPFC_MAX_TARGET 256 /* max number of targets supported */ |
| 28 | #define LPFC_MAX_DISC_THREADS 64 /* max outstanding discovery els | 27 | #define LPFC_MAX_DISC_THREADS 64 /* max outstanding discovery els |
| 29 | requests */ | 28 | requests */ |
| @@ -45,6 +44,9 @@ struct lpfc_sli2_slim; | |||
| 45 | /* Number of exchanges reserved for discovery to complete */ | 44 | /* Number of exchanges reserved for discovery to complete */ |
| 46 | #define LPFC_DISC_IOCB_BUFF_COUNT 20 | 45 | #define LPFC_DISC_IOCB_BUFF_COUNT 20 |
| 47 | 46 | ||
| 47 | #define LPFC_HB_MBOX_INTERVAL 5 /* Heart beat interval in seconds. */ | ||
| 48 | #define LPFC_HB_MBOX_TIMEOUT 30 /* Heart beat timeout in seconds. */ | ||
| 49 | |||
| 48 | /* Define macros for 64 bit support */ | 50 | /* Define macros for 64 bit support */ |
| 49 | #define putPaddrLow(addr) ((uint32_t) (0xffffffff & (u64)(addr))) | 51 | #define putPaddrLow(addr) ((uint32_t) (0xffffffff & (u64)(addr))) |
| 50 | #define putPaddrHigh(addr) ((uint32_t) (0xffffffff & (((u64)(addr))>>32))) | 52 | #define putPaddrHigh(addr) ((uint32_t) (0xffffffff & (((u64)(addr))>>32))) |
| @@ -308,13 +310,15 @@ struct lpfc_vport { | |||
| 308 | 310 | ||
| 309 | spinlock_t work_port_lock; | 311 | spinlock_t work_port_lock; |
| 310 | uint32_t work_port_events; /* Timeout to be handled */ | 312 | uint32_t work_port_events; /* Timeout to be handled */ |
| 311 | #define WORKER_DISC_TMO 0x1 /* Discovery timeout */ | 313 | #define WORKER_DISC_TMO 0x1 /* vport: Discovery timeout */ |
| 312 | #define WORKER_ELS_TMO 0x2 /* ELS timeout */ | 314 | #define WORKER_ELS_TMO 0x2 /* vport: ELS timeout */ |
| 313 | #define WORKER_MBOX_TMO 0x4 /* MBOX timeout */ | 315 | #define WORKER_FDMI_TMO 0x4 /* vport: FDMI timeout */ |
| 314 | #define WORKER_FDMI_TMO 0x8 /* FDMI timeout */ | 316 | |
| 315 | #define WORKER_FABRIC_BLOCK_TMO 0x10 /* fabric block timout */ | 317 | #define WORKER_MBOX_TMO 0x100 /* hba: MBOX timeout */ |
| 316 | #define WORKER_RAMP_DOWN_QUEUE 0x20 /* Decrease Q depth */ | 318 | #define WORKER_HB_TMO 0x200 /* hba: Heart beat timeout */ |
| 317 | #define WORKER_RAMP_UP_QUEUE 0x40 /* Increase Q depth */ | 319 | #define WORKER_FABRIC_BLOCK_TMO 0x400 /* hba: fabric block timout */ |
| 320 | #define WORKER_RAMP_DOWN_QUEUE 0x800 /* hba: Decrease Q depth */ | ||
| 321 | #define WORKER_RAMP_UP_QUEUE 0x1000 /* hba: Increase Q depth */ | ||
| 318 | 322 | ||
| 319 | struct timer_list fc_fdmitmo; | 323 | struct timer_list fc_fdmitmo; |
| 320 | struct timer_list els_tmofunc; | 324 | struct timer_list els_tmofunc; |
| @@ -326,6 +330,14 @@ struct lpfc_vport { | |||
| 326 | #define FC_UNLOADING 0x2 /* HBA in process of unloading drvr */ | 330 | #define FC_UNLOADING 0x2 /* HBA in process of unloading drvr */ |
| 327 | char *vname; /* Application assigned name */ | 331 | char *vname; /* Application assigned name */ |
| 328 | struct fc_vport *fc_vport; | 332 | struct fc_vport *fc_vport; |
| 333 | |||
| 334 | #ifdef CONFIG_LPFC_DEBUG_FS | ||
| 335 | struct dentry *debug_disc_trc; | ||
| 336 | struct dentry *debug_nodelist; | ||
| 337 | struct dentry *vport_debugfs_root; | ||
| 338 | struct lpfc_disc_trc *disc_trc; | ||
| 339 | atomic_t disc_trc_cnt; | ||
| 340 | #endif | ||
| 329 | }; | 341 | }; |
| 330 | 342 | ||
| 331 | struct hbq_s { | 343 | struct hbq_s { |
| @@ -408,6 +420,7 @@ struct lpfc_hba { | |||
| 408 | uint32_t cfg_hba_queue_depth; | 420 | uint32_t cfg_hba_queue_depth; |
| 409 | uint32_t cfg_peer_port_login; | 421 | uint32_t cfg_peer_port_login; |
| 410 | uint32_t cfg_vport_restrict_login; | 422 | uint32_t cfg_vport_restrict_login; |
| 423 | uint32_t cfg_npiv_enable; | ||
| 411 | uint32_t cfg_fcp_class; | 424 | uint32_t cfg_fcp_class; |
| 412 | uint32_t cfg_use_adisc; | 425 | uint32_t cfg_use_adisc; |
| 413 | uint32_t cfg_ack0; | 426 | uint32_t cfg_ack0; |
| @@ -513,10 +526,10 @@ struct lpfc_hba { | |||
| 513 | mempool_t *nlp_mem_pool; | 526 | mempool_t *nlp_mem_pool; |
| 514 | 527 | ||
| 515 | struct fc_host_statistics link_stats; | 528 | struct fc_host_statistics link_stats; |
| 529 | |||
| 516 | struct list_head port_list; | 530 | struct list_head port_list; |
| 517 | struct lpfc_vport *pport; /* physical lpfc_vport pointer */ | 531 | struct lpfc_vport *pport; /* physical lpfc_vport pointer */ |
| 518 | uint16_t max_vpi; /* Maximum virtual nports */ | 532 | uint16_t max_vpi; /* Maximum virtual nports */ |
| 519 | uint16_t vpi_cnt; /* Nport count */ | ||
| 520 | #define LPFC_MAX_VPI 100 /* Max number of VPorts supported */ | 533 | #define LPFC_MAX_VPI 100 /* Max number of VPorts supported */ |
| 521 | unsigned long *vpi_bmask; /* vpi allocation table */ | 534 | unsigned long *vpi_bmask; /* vpi allocation table */ |
| 522 | 535 | ||
| @@ -531,6 +544,15 @@ struct lpfc_hba { | |||
| 531 | unsigned long last_rsrc_error_time; | 544 | unsigned long last_rsrc_error_time; |
| 532 | unsigned long last_ramp_down_time; | 545 | unsigned long last_ramp_down_time; |
| 533 | unsigned long last_ramp_up_time; | 546 | unsigned long last_ramp_up_time; |
| 547 | #ifdef CONFIG_LPFC_DEBUG_FS | ||
| 548 | struct dentry *hba_debugfs_root; | ||
| 549 | atomic_t debugfs_vport_count; | ||
| 550 | #endif | ||
| 551 | |||
| 552 | /* Fields used for heart beat. */ | ||
| 553 | unsigned long last_completion_time; | ||
| 554 | struct timer_list hb_tmofunc; | ||
| 555 | uint8_t hb_outstanding; | ||
| 534 | }; | 556 | }; |
| 535 | 557 | ||
| 536 | static inline struct Scsi_Host * | 558 | static inline struct Scsi_Host * |
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); |
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 94e788199568..e19d1a746586 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
| @@ -23,6 +23,7 @@ typedef int (*node_filter)(struct lpfc_nodelist *ndlp, void *param); | |||
| 23 | struct fc_rport; | 23 | struct fc_rport; |
| 24 | void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t); | 24 | void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t); |
| 25 | void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *); | 25 | void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *); |
| 26 | void lpfc_heart_beat(struct lpfc_hba *, LPFC_MBOXQ_t *); | ||
| 26 | int lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, | 27 | int lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, |
| 27 | struct lpfc_dmabuf *mp); | 28 | struct lpfc_dmabuf *mp); |
| 28 | void lpfc_clear_la(struct lpfc_hba *, LPFC_MBOXQ_t *); | 29 | void lpfc_clear_la(struct lpfc_hba *, LPFC_MBOXQ_t *); |
| @@ -45,6 +46,7 @@ void lpfc_mbx_cmpl_read_la(struct lpfc_hba *, LPFC_MBOXQ_t *); | |||
| 45 | 46 | ||
| 46 | void lpfc_mbx_cmpl_clear_la(struct lpfc_hba *, LPFC_MBOXQ_t *); | 47 | void lpfc_mbx_cmpl_clear_la(struct lpfc_hba *, LPFC_MBOXQ_t *); |
| 47 | void lpfc_mbx_cmpl_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); | 48 | void lpfc_mbx_cmpl_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); |
| 49 | void lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *, LPFC_MBOXQ_t *); | ||
| 48 | void lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); | 50 | void lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); |
| 49 | void lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); | 51 | void lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); |
| 50 | void lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); | 52 | void lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); |
| @@ -85,6 +87,7 @@ void lpfc_do_scr_ns_plogi(struct lpfc_hba *, struct lpfc_vport *); | |||
| 85 | int lpfc_check_sparm(struct lpfc_vport *, struct lpfc_nodelist *, | 87 | int lpfc_check_sparm(struct lpfc_vport *, struct lpfc_nodelist *, |
| 86 | struct serv_parm *, uint32_t); | 88 | struct serv_parm *, uint32_t); |
| 87 | int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist *); | 89 | int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist *); |
| 90 | int lpfc_els_chk_latt(struct lpfc_vport *); | ||
| 88 | int lpfc_els_abort_flogi(struct lpfc_hba *); | 91 | int lpfc_els_abort_flogi(struct lpfc_hba *); |
| 89 | int lpfc_initial_flogi(struct lpfc_vport *); | 92 | int lpfc_initial_flogi(struct lpfc_vport *); |
| 90 | int lpfc_initial_fdisc(struct lpfc_vport *); | 93 | int lpfc_initial_fdisc(struct lpfc_vport *); |
| @@ -96,10 +99,11 @@ int lpfc_issue_els_logo(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t); | |||
| 96 | int lpfc_issue_els_npiv_logo(struct lpfc_vport *, struct lpfc_nodelist *); | 99 | int lpfc_issue_els_npiv_logo(struct lpfc_vport *, struct lpfc_nodelist *); |
| 97 | int lpfc_issue_els_scr(struct lpfc_vport *, uint32_t, uint8_t); | 100 | int lpfc_issue_els_scr(struct lpfc_vport *, uint32_t, uint8_t); |
| 98 | int lpfc_els_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *); | 101 | int lpfc_els_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *); |
| 102 | int lpfc_ct_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *); | ||
| 99 | int lpfc_els_rsp_acc(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *, | 103 | int lpfc_els_rsp_acc(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *, |
| 100 | struct lpfc_nodelist *, LPFC_MBOXQ_t *, uint8_t); | 104 | struct lpfc_nodelist *, LPFC_MBOXQ_t *, uint8_t); |
| 101 | int lpfc_els_rsp_reject(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *, | 105 | int lpfc_els_rsp_reject(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *, |
| 102 | struct lpfc_nodelist *); | 106 | struct lpfc_nodelist *, LPFC_MBOXQ_t *); |
| 103 | int lpfc_els_rsp_adisc_acc(struct lpfc_vport *, struct lpfc_iocbq *, | 107 | int lpfc_els_rsp_adisc_acc(struct lpfc_vport *, struct lpfc_iocbq *, |
| 104 | struct lpfc_nodelist *); | 108 | struct lpfc_nodelist *); |
| 105 | int lpfc_els_rsp_prli_acc(struct lpfc_vport *, struct lpfc_iocbq *, | 109 | int lpfc_els_rsp_prli_acc(struct lpfc_vport *, struct lpfc_iocbq *, |
| @@ -107,6 +111,7 @@ int lpfc_els_rsp_prli_acc(struct lpfc_vport *, struct lpfc_iocbq *, | |||
| 107 | void lpfc_cancel_retry_delay_tmo(struct lpfc_vport *, struct lpfc_nodelist *); | 111 | void lpfc_cancel_retry_delay_tmo(struct lpfc_vport *, struct lpfc_nodelist *); |
| 108 | void lpfc_els_retry_delay(unsigned long); | 112 | void lpfc_els_retry_delay(unsigned long); |
| 109 | void lpfc_els_retry_delay_handler(struct lpfc_nodelist *); | 113 | void lpfc_els_retry_delay_handler(struct lpfc_nodelist *); |
| 114 | void lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *); | ||
| 110 | void lpfc_els_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *, | 115 | void lpfc_els_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *, |
| 111 | struct lpfc_iocbq *); | 116 | struct lpfc_iocbq *); |
| 112 | int lpfc_els_handle_rscn(struct lpfc_vport *); | 117 | int lpfc_els_handle_rscn(struct lpfc_vport *); |
| @@ -117,6 +122,8 @@ int lpfc_els_disc_adisc(struct lpfc_vport *); | |||
| 117 | int lpfc_els_disc_plogi(struct lpfc_vport *); | 122 | int lpfc_els_disc_plogi(struct lpfc_vport *); |
| 118 | void lpfc_els_timeout(unsigned long); | 123 | void lpfc_els_timeout(unsigned long); |
| 119 | void lpfc_els_timeout_handler(struct lpfc_vport *); | 124 | void lpfc_els_timeout_handler(struct lpfc_vport *); |
| 125 | void lpfc_hb_timeout(unsigned long); | ||
| 126 | void lpfc_hb_timeout_handler(struct lpfc_hba *); | ||
| 120 | 127 | ||
| 121 | void lpfc_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *, | 128 | void lpfc_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *, |
| 122 | struct lpfc_iocbq *); | 129 | struct lpfc_iocbq *); |
| @@ -238,7 +245,6 @@ void lpfc_mbuf_free(struct lpfc_hba *, void *, dma_addr_t); | |||
| 238 | void lpfc_in_buf_free(struct lpfc_hba *, struct lpfc_dmabuf *); | 245 | void lpfc_in_buf_free(struct lpfc_hba *, struct lpfc_dmabuf *); |
| 239 | /* Function prototypes. */ | 246 | /* Function prototypes. */ |
| 240 | const char* lpfc_info(struct Scsi_Host *); | 247 | const char* lpfc_info(struct Scsi_Host *); |
| 241 | void lpfc_scan_start(struct Scsi_Host *); | ||
| 242 | int lpfc_scan_finished(struct Scsi_Host *, unsigned long); | 248 | int lpfc_scan_finished(struct Scsi_Host *, unsigned long); |
| 243 | 249 | ||
| 244 | void lpfc_get_cfgparam(struct lpfc_hba *); | 250 | void lpfc_get_cfgparam(struct lpfc_hba *); |
| @@ -249,7 +255,6 @@ extern struct scsi_host_template lpfc_template; | |||
| 249 | extern struct fc_function_template lpfc_transport_functions; | 255 | extern struct fc_function_template lpfc_transport_functions; |
| 250 | extern struct fc_function_template lpfc_vport_transport_functions; | 256 | extern struct fc_function_template lpfc_vport_transport_functions; |
| 251 | extern int lpfc_sli_mode; | 257 | extern int lpfc_sli_mode; |
| 252 | extern int lpfc_npiv_enable; | ||
| 253 | 258 | ||
| 254 | int lpfc_vport_symbolic_node_name(struct lpfc_vport *, char *, size_t); | 259 | int lpfc_vport_symbolic_node_name(struct lpfc_vport *, char *, size_t); |
| 255 | void lpfc_terminate_rport_io(struct fc_rport *); | 260 | void lpfc_terminate_rport_io(struct fc_rport *); |
| @@ -262,6 +267,11 @@ void destroy_port(struct lpfc_vport *); | |||
| 262 | int lpfc_get_instance(void); | 267 | int lpfc_get_instance(void); |
| 263 | void lpfc_host_attrib_init(struct Scsi_Host *); | 268 | void lpfc_host_attrib_init(struct Scsi_Host *); |
| 264 | 269 | ||
| 270 | extern void lpfc_debugfs_initialize(struct lpfc_vport *); | ||
| 271 | extern void lpfc_debugfs_terminate(struct lpfc_vport *); | ||
| 272 | extern void lpfc_debugfs_disc_trc(struct lpfc_vport *, int, char *, uint32_t, | ||
| 273 | uint32_t, uint32_t); | ||
| 274 | |||
| 265 | /* Interface exported by fabric iocb scheduler */ | 275 | /* Interface exported by fabric iocb scheduler */ |
| 266 | int lpfc_issue_fabric_iocb(struct lpfc_hba *, struct lpfc_iocbq *); | 276 | int lpfc_issue_fabric_iocb(struct lpfc_hba *, struct lpfc_iocbq *); |
| 267 | void lpfc_fabric_abort_vport(struct lpfc_vport *); | 277 | void lpfc_fabric_abort_vport(struct lpfc_vport *); |
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 5584f395314c..ae9d6f385a6c 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c | |||
| @@ -41,6 +41,7 @@ | |||
| 41 | #include "lpfc_crtn.h" | 41 | #include "lpfc_crtn.h" |
| 42 | #include "lpfc_version.h" | 42 | #include "lpfc_version.h" |
| 43 | #include "lpfc_vport.h" | 43 | #include "lpfc_vport.h" |
| 44 | #include "lpfc_debugfs.h" | ||
| 44 | 45 | ||
| 45 | #define HBA_PORTSPEED_UNKNOWN 0 /* Unknown - transceiver | 46 | #define HBA_PORTSPEED_UNKNOWN 0 /* Unknown - transceiver |
| 46 | * incapable of reporting */ | 47 | * incapable of reporting */ |
| @@ -251,6 +252,32 @@ lpfc_alloc_ct_rsp(struct lpfc_hba *phba, int cmdcode, struct ulp_bde64 *bpl, | |||
| 251 | return mlist; | 252 | return mlist; |
| 252 | } | 253 | } |
| 253 | 254 | ||
| 255 | int | ||
| 256 | lpfc_ct_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *ctiocb) | ||
| 257 | { | ||
| 258 | struct lpfc_dmabuf *buf_ptr; | ||
| 259 | |||
| 260 | if (ctiocb->context1) { | ||
| 261 | buf_ptr = (struct lpfc_dmabuf *) ctiocb->context1; | ||
| 262 | lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys); | ||
| 263 | kfree(buf_ptr); | ||
| 264 | ctiocb->context1 = NULL; | ||
| 265 | } | ||
| 266 | if (ctiocb->context2) { | ||
| 267 | lpfc_free_ct_rsp(phba, (struct lpfc_dmabuf *) ctiocb->context2); | ||
| 268 | ctiocb->context2 = NULL; | ||
| 269 | } | ||
| 270 | |||
| 271 | if (ctiocb->context3) { | ||
| 272 | buf_ptr = (struct lpfc_dmabuf *) ctiocb->context3; | ||
| 273 | lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys); | ||
| 274 | kfree(buf_ptr); | ||
| 275 | ctiocb->context1 = NULL; | ||
| 276 | } | ||
| 277 | lpfc_sli_release_iocbq(phba, ctiocb); | ||
| 278 | return 0; | ||
| 279 | } | ||
| 280 | |||
| 254 | static int | 281 | static int |
| 255 | lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, | 282 | lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, |
| 256 | struct lpfc_dmabuf *inp, struct lpfc_dmabuf *outp, | 283 | struct lpfc_dmabuf *inp, struct lpfc_dmabuf *outp, |
| @@ -428,6 +455,13 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size) | |||
| 428 | (!phba->cfg_vport_restrict_login)) { | 455 | (!phba->cfg_vport_restrict_login)) { |
| 429 | ndlp = lpfc_setup_disc_node(vport, Did); | 456 | ndlp = lpfc_setup_disc_node(vport, Did); |
| 430 | if (ndlp) { | 457 | if (ndlp) { |
| 458 | lpfc_debugfs_disc_trc(vport, | ||
| 459 | LPFC_DISC_TRC_CT, | ||
| 460 | "Parse GID_FTrsp: " | ||
| 461 | "did:x%x flg:x%x x%x", | ||
| 462 | Did, ndlp->nlp_flag, | ||
| 463 | vport->fc_flag); | ||
| 464 | |||
| 431 | lpfc_printf_log(phba, KERN_INFO, | 465 | lpfc_printf_log(phba, KERN_INFO, |
| 432 | LOG_DISCOVERY, | 466 | LOG_DISCOVERY, |
| 433 | "%d (%d):0238 Process " | 467 | "%d (%d):0238 Process " |
| @@ -439,6 +473,13 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size) | |||
| 439 | vport->fc_flag, | 473 | vport->fc_flag, |
| 440 | vport->fc_rscn_id_cnt); | 474 | vport->fc_rscn_id_cnt); |
| 441 | } else { | 475 | } else { |
| 476 | lpfc_debugfs_disc_trc(vport, | ||
| 477 | LPFC_DISC_TRC_CT, | ||
| 478 | "Skip1 GID_FTrsp: " | ||
| 479 | "did:x%x flg:x%x cnt:%d", | ||
| 480 | Did, vport->fc_flag, | ||
| 481 | vport->fc_rscn_id_cnt); | ||
| 482 | |||
| 442 | lpfc_printf_log(phba, KERN_INFO, | 483 | lpfc_printf_log(phba, KERN_INFO, |
| 443 | LOG_DISCOVERY, | 484 | LOG_DISCOVERY, |
| 444 | "%d (%d):0239 Skip x%x " | 485 | "%d (%d):0239 Skip x%x " |
| @@ -453,12 +494,26 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size) | |||
| 453 | } else { | 494 | } else { |
| 454 | if (!(vport->fc_flag & FC_RSCN_MODE) || | 495 | if (!(vport->fc_flag & FC_RSCN_MODE) || |
| 455 | (lpfc_rscn_payload_check(vport, Did))) { | 496 | (lpfc_rscn_payload_check(vport, Did))) { |
| 497 | lpfc_debugfs_disc_trc(vport, | ||
| 498 | LPFC_DISC_TRC_CT, | ||
| 499 | "Query GID_FTrsp: " | ||
| 500 | "did:x%x flg:x%x cnt:%d", | ||
| 501 | Did, vport->fc_flag, | ||
| 502 | vport->fc_rscn_id_cnt); | ||
| 503 | |||
| 456 | if (lpfc_ns_cmd(vport, | 504 | if (lpfc_ns_cmd(vport, |
| 457 | SLI_CTNS_GFF_ID, | 505 | SLI_CTNS_GFF_ID, |
| 458 | 0, Did) == 0) | 506 | 0, Did) == 0) |
| 459 | vport->num_disc_nodes++; | 507 | vport->num_disc_nodes++; |
| 460 | } | 508 | } |
| 461 | else { | 509 | else { |
| 510 | lpfc_debugfs_disc_trc(vport, | ||
| 511 | LPFC_DISC_TRC_CT, | ||
| 512 | "Skip2 GID_FTrsp: " | ||
| 513 | "did:x%x flg:x%x cnt:%d", | ||
| 514 | Did, vport->fc_flag, | ||
| 515 | vport->fc_rscn_id_cnt); | ||
| 516 | |||
| 462 | lpfc_printf_log(phba, KERN_INFO, | 517 | lpfc_printf_log(phba, KERN_INFO, |
| 463 | LOG_DISCOVERY, | 518 | LOG_DISCOVERY, |
| 464 | "%d (%d):0245 Skip x%x " | 519 | "%d (%d):0245 Skip x%x " |
| @@ -492,7 +547,6 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 492 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 547 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
| 493 | IOCB_t *irsp; | 548 | IOCB_t *irsp; |
| 494 | struct lpfc_dmabuf *bmp; | 549 | struct lpfc_dmabuf *bmp; |
| 495 | struct lpfc_dmabuf *inp; | ||
| 496 | struct lpfc_dmabuf *outp; | 550 | struct lpfc_dmabuf *outp; |
| 497 | struct lpfc_sli_ct_request *CTrsp; | 551 | struct lpfc_sli_ct_request *CTrsp; |
| 498 | int rc; | 552 | int rc; |
| @@ -500,31 +554,39 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 500 | /* we pass cmdiocb to state machine which needs rspiocb as well */ | 554 | /* we pass cmdiocb to state machine which needs rspiocb as well */ |
| 501 | cmdiocb->context_un.rsp_iocb = rspiocb; | 555 | cmdiocb->context_un.rsp_iocb = rspiocb; |
| 502 | 556 | ||
| 503 | inp = (struct lpfc_dmabuf *) cmdiocb->context1; | ||
| 504 | outp = (struct lpfc_dmabuf *) cmdiocb->context2; | 557 | outp = (struct lpfc_dmabuf *) cmdiocb->context2; |
| 505 | bmp = (struct lpfc_dmabuf *) cmdiocb->context3; | 558 | bmp = (struct lpfc_dmabuf *) cmdiocb->context3; |
| 559 | irsp = &rspiocb->iocb; | ||
| 560 | |||
| 561 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, | ||
| 562 | "GID_FT cmpl: status:x%x/x%x rtry:%d", | ||
| 563 | irsp->ulpStatus, irsp->un.ulpWord[4], vport->fc_ns_retry); | ||
| 506 | 564 | ||
| 507 | /* Don't bother processing response if vport is being torn down. */ | 565 | /* Don't bother processing response if vport is being torn down. */ |
| 508 | if (vport->load_flag & FC_UNLOADING) | 566 | if (vport->load_flag & FC_UNLOADING) |
| 509 | goto out; | 567 | goto out; |
| 510 | 568 | ||
| 511 | irsp = &rspiocb->iocb; | ||
| 512 | if (irsp->ulpStatus) { | ||
| 513 | if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) && | ||
| 514 | ((irsp->un.ulpWord[4] == IOERR_SLI_DOWN) || | ||
| 515 | (irsp->un.ulpWord[4] == IOERR_SLI_ABORTED))) | ||
| 516 | goto err1; | ||
| 517 | 569 | ||
| 570 | if (lpfc_els_chk_latt(vport) || lpfc_error_lost_link(irsp)) { | ||
| 571 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, | ||
| 572 | "%d (%d):0216 Link event during NS query\n", | ||
| 573 | phba->brd_no, vport->vpi); | ||
| 574 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); | ||
| 575 | goto out; | ||
| 576 | } | ||
| 577 | |||
| 578 | if (irsp->ulpStatus) { | ||
| 518 | /* Check for retry */ | 579 | /* Check for retry */ |
| 519 | if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) { | 580 | if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) { |
| 520 | vport->fc_ns_retry++; | 581 | if ((irsp->ulpStatus != IOSTAT_LOCAL_REJECT) || |
| 582 | (irsp->un.ulpWord[4] != IOERR_NO_RESOURCES)) | ||
| 583 | vport->fc_ns_retry++; | ||
| 521 | /* CT command is being retried */ | 584 | /* CT command is being retried */ |
| 522 | rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_FT, | 585 | rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_FT, |
| 523 | vport->fc_ns_retry, 0); | 586 | vport->fc_ns_retry, 0); |
| 524 | if (rc == 0) | 587 | if (rc == 0) |
| 525 | goto out; | 588 | goto out; |
| 526 | } | 589 | } |
| 527 | err1: | ||
| 528 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); | 590 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); |
| 529 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, | 591 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, |
| 530 | "%d (%d):0257 GID_FT Query error: 0x%x 0x%x\n", | 592 | "%d (%d):0257 GID_FT Query error: 0x%x 0x%x\n", |
| @@ -553,6 +615,13 @@ err1: | |||
| 553 | (uint32_t) CTrsp->ReasonCode, | 615 | (uint32_t) CTrsp->ReasonCode, |
| 554 | (uint32_t) CTrsp->Explanation, | 616 | (uint32_t) CTrsp->Explanation, |
| 555 | vport->fc_flag); | 617 | vport->fc_flag); |
| 618 | |||
| 619 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, | ||
| 620 | "GID_FT rsp err1 cmd:x%x rsn:x%x exp:x%x", | ||
| 621 | (uint32_t)CTrsp->CommandResponse.bits.CmdRsp, | ||
| 622 | (uint32_t) CTrsp->ReasonCode, | ||
| 623 | (uint32_t) CTrsp->Explanation); | ||
| 624 | |||
| 556 | } else { | 625 | } else { |
| 557 | /* NameServer Rsp Error */ | 626 | /* NameServer Rsp Error */ |
| 558 | lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, | 627 | lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, |
| @@ -563,6 +632,12 @@ err1: | |||
| 563 | (uint32_t) CTrsp->ReasonCode, | 632 | (uint32_t) CTrsp->ReasonCode, |
| 564 | (uint32_t) CTrsp->Explanation, | 633 | (uint32_t) CTrsp->Explanation, |
| 565 | vport->fc_flag); | 634 | vport->fc_flag); |
| 635 | |||
| 636 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, | ||
| 637 | "GID_FT rsp err2 cmd:x%x rsn:x%x exp:x%x", | ||
| 638 | (uint32_t)CTrsp->CommandResponse.bits.CmdRsp, | ||
| 639 | (uint32_t) CTrsp->ReasonCode, | ||
| 640 | (uint32_t) CTrsp->Explanation); | ||
| 566 | } | 641 | } |
| 567 | } | 642 | } |
| 568 | /* Link up / RSCN discovery */ | 643 | /* Link up / RSCN discovery */ |
| @@ -586,12 +661,7 @@ err1: | |||
| 586 | lpfc_disc_start(vport); | 661 | lpfc_disc_start(vport); |
| 587 | } | 662 | } |
| 588 | out: | 663 | out: |
| 589 | lpfc_free_ct_rsp(phba, outp); | 664 | lpfc_ct_free_iocb(phba, cmdiocb); |
| 590 | lpfc_mbuf_free(phba, inp->virt, inp->phys); | ||
| 591 | lpfc_mbuf_free(phba, bmp->virt, bmp->phys); | ||
| 592 | kfree(inp); | ||
| 593 | kfree(bmp); | ||
| 594 | lpfc_sli_release_iocbq(phba, cmdiocb); | ||
| 595 | return; | 665 | return; |
| 596 | } | 666 | } |
| 597 | 667 | ||
| @@ -602,7 +672,6 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 602 | struct lpfc_vport *vport = cmdiocb->vport; | 672 | struct lpfc_vport *vport = cmdiocb->vport; |
| 603 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 673 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
| 604 | IOCB_t *irsp = &rspiocb->iocb; | 674 | IOCB_t *irsp = &rspiocb->iocb; |
| 605 | struct lpfc_dmabuf *bmp = (struct lpfc_dmabuf *) cmdiocb->context3; | ||
| 606 | struct lpfc_dmabuf *inp = (struct lpfc_dmabuf *) cmdiocb->context1; | 675 | struct lpfc_dmabuf *inp = (struct lpfc_dmabuf *) cmdiocb->context1; |
| 607 | struct lpfc_dmabuf *outp = (struct lpfc_dmabuf *) cmdiocb->context2; | 676 | struct lpfc_dmabuf *outp = (struct lpfc_dmabuf *) cmdiocb->context2; |
| 608 | struct lpfc_sli_ct_request *CTrsp; | 677 | struct lpfc_sli_ct_request *CTrsp; |
| @@ -613,6 +682,10 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 613 | did = ((struct lpfc_sli_ct_request *) inp->virt)->un.gff.PortId; | 682 | did = ((struct lpfc_sli_ct_request *) inp->virt)->un.gff.PortId; |
| 614 | did = be32_to_cpu(did); | 683 | did = be32_to_cpu(did); |
| 615 | 684 | ||
| 685 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, | ||
| 686 | "GFF_ID cmpl: status:x%x/x%x did:x%x", | ||
| 687 | irsp->ulpStatus, irsp->un.ulpWord[4], did); | ||
| 688 | |||
| 616 | if (irsp->ulpStatus == IOSTAT_SUCCESS) { | 689 | if (irsp->ulpStatus == IOSTAT_SUCCESS) { |
| 617 | /* Good status, continue checking */ | 690 | /* Good status, continue checking */ |
| 618 | CTrsp = (struct lpfc_sli_ct_request *) outp->virt; | 691 | CTrsp = (struct lpfc_sli_ct_request *) outp->virt; |
| @@ -632,6 +705,15 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 632 | } | 705 | } |
| 633 | } | 706 | } |
| 634 | } | 707 | } |
| 708 | else { | ||
| 709 | lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, | ||
| 710 | "%d (%d):0267 NameServer GFF Rsp" | ||
| 711 | " x%x Error (%d %d) Data: x%x x%x\n", | ||
| 712 | phba->brd_no, vport->vpi, did, | ||
| 713 | irsp->ulpStatus, irsp->un.ulpWord[4], | ||
| 714 | vport->fc_flag, vport->fc_rscn_id_cnt) | ||
| 715 | } | ||
| 716 | |||
| 635 | /* This is a target port, unregistered port, or the GFF_ID failed */ | 717 | /* This is a target port, unregistered port, or the GFF_ID failed */ |
| 636 | ndlp = lpfc_setup_disc_node(vport, did); | 718 | ndlp = lpfc_setup_disc_node(vport, did); |
| 637 | if (ndlp) { | 719 | if (ndlp) { |
| @@ -670,13 +752,7 @@ out: | |||
| 670 | } | 752 | } |
| 671 | lpfc_disc_start(vport); | 753 | lpfc_disc_start(vport); |
| 672 | } | 754 | } |
| 673 | 755 | lpfc_ct_free_iocb(phba, cmdiocb); | |
| 674 | lpfc_free_ct_rsp(phba, outp); | ||
| 675 | lpfc_mbuf_free(phba, inp->virt, inp->phys); | ||
| 676 | lpfc_mbuf_free(phba, bmp->virt, bmp->phys); | ||
| 677 | kfree(inp); | ||
| 678 | kfree(bmp); | ||
| 679 | lpfc_sli_release_iocbq(phba, cmdiocb); | ||
| 680 | return; | 756 | return; |
| 681 | } | 757 | } |
| 682 | 758 | ||
| @@ -686,37 +762,45 @@ lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 686 | struct lpfc_iocbq *rspiocb) | 762 | struct lpfc_iocbq *rspiocb) |
| 687 | { | 763 | { |
| 688 | struct lpfc_vport *vport = cmdiocb->vport; | 764 | struct lpfc_vport *vport = cmdiocb->vport; |
| 689 | struct lpfc_dmabuf *bmp; | ||
| 690 | struct lpfc_dmabuf *inp; | 765 | struct lpfc_dmabuf *inp; |
| 691 | struct lpfc_dmabuf *outp; | 766 | struct lpfc_dmabuf *outp; |
| 692 | IOCB_t *irsp; | 767 | IOCB_t *irsp; |
| 693 | struct lpfc_sli_ct_request *CTrsp; | 768 | struct lpfc_sli_ct_request *CTrsp; |
| 694 | int cmdcode, rc; | 769 | int cmdcode, rc; |
| 695 | uint8_t retry; | 770 | uint8_t retry; |
| 771 | uint32_t latt; | ||
| 696 | 772 | ||
| 697 | /* we pass cmdiocb to state machine which needs rspiocb as well */ | 773 | /* we pass cmdiocb to state machine which needs rspiocb as well */ |
| 698 | cmdiocb->context_un.rsp_iocb = rspiocb; | 774 | cmdiocb->context_un.rsp_iocb = rspiocb; |
| 699 | 775 | ||
| 700 | inp = (struct lpfc_dmabuf *) cmdiocb->context1; | 776 | inp = (struct lpfc_dmabuf *) cmdiocb->context1; |
| 701 | outp = (struct lpfc_dmabuf *) cmdiocb->context2; | 777 | outp = (struct lpfc_dmabuf *) cmdiocb->context2; |
| 702 | bmp = (struct lpfc_dmabuf *) cmdiocb->context3; | ||
| 703 | irsp = &rspiocb->iocb; | 778 | irsp = &rspiocb->iocb; |
| 704 | 779 | ||
| 705 | cmdcode = be16_to_cpu(((struct lpfc_sli_ct_request *) inp->virt)-> | 780 | cmdcode = be16_to_cpu(((struct lpfc_sli_ct_request *) inp->virt)-> |
| 706 | CommandResponse.bits.CmdRsp); | 781 | CommandResponse.bits.CmdRsp); |
| 707 | CTrsp = (struct lpfc_sli_ct_request *) outp->virt; | 782 | CTrsp = (struct lpfc_sli_ct_request *) outp->virt; |
| 708 | 783 | ||
| 709 | /* NS request completes status <ulpStatus> CmdRsp <CmdRsp> */ | 784 | latt = lpfc_els_chk_latt(vport); |
| 785 | |||
| 786 | /* RFT request completes status <ulpStatus> CmdRsp <CmdRsp> */ | ||
| 710 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, | 787 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, |
| 711 | "%d (%d):0209 NS request %x completes " | 788 | "%d (%d):0209 RFT request completes, latt %d, " |
| 712 | "ulpStatus x%x / x%x " | 789 | "ulpStatus x%x CmdRsp x%x, Context x%x, Tag x%x\n", |
| 713 | "CmdRsp x%x, Context x%x, Tag x%x\n", | 790 | phba->brd_no, vport->vpi, latt, irsp->ulpStatus, |
| 714 | phba->brd_no, vport->vpi, | ||
| 715 | cmdcode, irsp->ulpStatus, irsp->un.ulpWord[4], | ||
| 716 | CTrsp->CommandResponse.bits.CmdRsp, | 791 | CTrsp->CommandResponse.bits.CmdRsp, |
| 717 | cmdiocb->iocb.ulpContext, cmdiocb->iocb.ulpIoTag); | 792 | cmdiocb->iocb.ulpContext, cmdiocb->iocb.ulpIoTag); |
| 718 | 793 | ||
| 794 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, | ||
| 795 | "CT cmd cmpl: status:x%x/x%x cmd:x%x", | ||
| 796 | irsp->ulpStatus, irsp->un.ulpWord[4], cmdcode); | ||
| 797 | |||
| 719 | if (irsp->ulpStatus) { | 798 | if (irsp->ulpStatus) { |
| 799 | lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, | ||
| 800 | "%d (%d):0268 NS cmd %x Error (%d %d)\n", | ||
| 801 | phba->brd_no, vport->vpi, cmdcode, | ||
| 802 | irsp->ulpStatus, irsp->un.ulpWord[4]); | ||
| 803 | |||
| 720 | if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) && | 804 | if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) && |
| 721 | ((irsp->un.ulpWord[4] == IOERR_SLI_DOWN) || | 805 | ((irsp->un.ulpWord[4] == IOERR_SLI_DOWN) || |
| 722 | (irsp->un.ulpWord[4] == IOERR_SLI_ABORTED))) | 806 | (irsp->un.ulpWord[4] == IOERR_SLI_ABORTED))) |
| @@ -736,12 +820,7 @@ lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 736 | } | 820 | } |
| 737 | 821 | ||
| 738 | out: | 822 | out: |
| 739 | lpfc_free_ct_rsp(phba, outp); | 823 | lpfc_ct_free_iocb(phba, cmdiocb); |
| 740 | lpfc_mbuf_free(phba, inp->virt, inp->phys); | ||
| 741 | lpfc_mbuf_free(phba, bmp->virt, bmp->phys); | ||
| 742 | kfree(inp); | ||
| 743 | kfree(bmp); | ||
| 744 | lpfc_sli_release_iocbq(phba, cmdiocb); | ||
| 745 | return; | 824 | return; |
| 746 | } | 825 | } |
| 747 | 826 | ||
| @@ -840,31 +919,42 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, | |||
| 840 | struct lpfc_iocbq *) = NULL; | 919 | struct lpfc_iocbq *) = NULL; |
| 841 | uint32_t rsp_size = 1024; | 920 | uint32_t rsp_size = 1024; |
| 842 | size_t size; | 921 | size_t size; |
| 922 | int rc = 0; | ||
| 843 | 923 | ||
| 844 | ndlp = lpfc_findnode_did(vport, NameServer_DID); | 924 | ndlp = lpfc_findnode_did(vport, NameServer_DID); |
| 845 | if (ndlp == NULL || ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) | 925 | if (ndlp == NULL || ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) { |
| 846 | return 1; | 926 | rc=1; |
| 927 | goto ns_cmd_exit; | ||
| 928 | } | ||
| 847 | 929 | ||
| 848 | /* fill in BDEs for command */ | 930 | /* fill in BDEs for command */ |
| 849 | /* Allocate buffer for command payload */ | 931 | /* Allocate buffer for command payload */ |
| 850 | mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL); | 932 | mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL); |
| 851 | if (!mp) | 933 | if (!mp) { |
| 934 | rc=2; | ||
| 852 | goto ns_cmd_exit; | 935 | goto ns_cmd_exit; |
| 936 | } | ||
| 853 | 937 | ||
| 854 | INIT_LIST_HEAD(&mp->list); | 938 | INIT_LIST_HEAD(&mp->list); |
| 855 | mp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(mp->phys)); | 939 | mp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(mp->phys)); |
| 856 | if (!mp->virt) | 940 | if (!mp->virt) { |
| 941 | rc=3; | ||
| 857 | goto ns_cmd_free_mp; | 942 | goto ns_cmd_free_mp; |
| 943 | } | ||
| 858 | 944 | ||
| 859 | /* Allocate buffer for Buffer ptr list */ | 945 | /* Allocate buffer for Buffer ptr list */ |
| 860 | bmp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL); | 946 | bmp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL); |
| 861 | if (!bmp) | 947 | if (!bmp) { |
| 948 | rc=4; | ||
| 862 | goto ns_cmd_free_mpvirt; | 949 | goto ns_cmd_free_mpvirt; |
| 950 | } | ||
| 863 | 951 | ||
| 864 | INIT_LIST_HEAD(&bmp->list); | 952 | INIT_LIST_HEAD(&bmp->list); |
| 865 | bmp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(bmp->phys)); | 953 | bmp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(bmp->phys)); |
| 866 | if (!bmp->virt) | 954 | if (!bmp->virt) { |
| 955 | rc=5; | ||
| 867 | goto ns_cmd_free_bmp; | 956 | goto ns_cmd_free_bmp; |
| 957 | } | ||
| 868 | 958 | ||
| 869 | /* NameServer Req */ | 959 | /* NameServer Req */ |
| 870 | lpfc_printf_log(phba, KERN_INFO ,LOG_DISCOVERY, | 960 | lpfc_printf_log(phba, KERN_INFO ,LOG_DISCOVERY, |
| @@ -970,10 +1060,15 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, | |||
| 970 | break; | 1060 | break; |
| 971 | } | 1061 | } |
| 972 | 1062 | ||
| 973 | if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, rsp_size, retry)) | 1063 | if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, rsp_size, retry)) { |
| 974 | /* On success, The cmpl function will free the buffers */ | 1064 | /* On success, The cmpl function will free the buffers */ |
| 1065 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, | ||
| 1066 | "Issue CT cmd: cmd:x%x did:x%x", | ||
| 1067 | cmdcode, ndlp->nlp_DID, 0); | ||
| 975 | return 0; | 1068 | return 0; |
| 1069 | } | ||
| 976 | 1070 | ||
| 1071 | rc=6; | ||
| 977 | lpfc_mbuf_free(phba, bmp->virt, bmp->phys); | 1072 | lpfc_mbuf_free(phba, bmp->virt, bmp->phys); |
| 978 | ns_cmd_free_bmp: | 1073 | ns_cmd_free_bmp: |
| 979 | kfree(bmp); | 1074 | kfree(bmp); |
| @@ -982,6 +1077,10 @@ ns_cmd_free_mpvirt: | |||
| 982 | ns_cmd_free_mp: | 1077 | ns_cmd_free_mp: |
| 983 | kfree(mp); | 1078 | kfree(mp); |
| 984 | ns_cmd_exit: | 1079 | ns_cmd_exit: |
| 1080 | lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, | ||
| 1081 | "%d (%d):0266 Issue NameServer Req x%x err %d Data: x%x x%x\n", | ||
| 1082 | phba->brd_no, vport->vpi, cmdcode, rc, vport->fc_flag, | ||
| 1083 | vport->fc_rscn_id_cnt); | ||
| 985 | return 1; | 1084 | return 1; |
| 986 | } | 1085 | } |
| 987 | 1086 | ||
| @@ -989,7 +1088,6 @@ static void | |||
| 989 | lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | 1088 | lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, |
| 990 | struct lpfc_iocbq * rspiocb) | 1089 | struct lpfc_iocbq * rspiocb) |
| 991 | { | 1090 | { |
| 992 | struct lpfc_dmabuf *bmp = cmdiocb->context3; | ||
| 993 | struct lpfc_dmabuf *inp = cmdiocb->context1; | 1091 | struct lpfc_dmabuf *inp = cmdiocb->context1; |
| 994 | struct lpfc_dmabuf *outp = cmdiocb->context2; | 1092 | struct lpfc_dmabuf *outp = cmdiocb->context2; |
| 995 | struct lpfc_sli_ct_request *CTrsp = outp->virt; | 1093 | struct lpfc_sli_ct_request *CTrsp = outp->virt; |
| @@ -998,6 +1096,25 @@ lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 998 | uint16_t fdmi_cmd = CTcmd->CommandResponse.bits.CmdRsp; | 1096 | uint16_t fdmi_cmd = CTcmd->CommandResponse.bits.CmdRsp; |
| 999 | uint16_t fdmi_rsp = CTrsp->CommandResponse.bits.CmdRsp; | 1097 | uint16_t fdmi_rsp = CTrsp->CommandResponse.bits.CmdRsp; |
| 1000 | struct lpfc_vport *vport = cmdiocb->vport; | 1098 | struct lpfc_vport *vport = cmdiocb->vport; |
| 1099 | IOCB_t *irsp = &rspiocb->iocb; | ||
| 1100 | uint32_t latt; | ||
| 1101 | |||
| 1102 | latt = lpfc_els_chk_latt(vport); | ||
| 1103 | |||
| 1104 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, | ||
| 1105 | "FDMI cmpl: status:x%x/x%x latt:%d", | ||
| 1106 | irsp->ulpStatus, irsp->un.ulpWord[4], latt); | ||
| 1107 | |||
| 1108 | if (latt || irsp->ulpStatus) { | ||
| 1109 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, | ||
| 1110 | "%d (%d):0229 FDMI cmd %04x failed, latt = %d " | ||
| 1111 | "ulpStatus: x%x, rid x%x\n", | ||
| 1112 | phba->brd_no, vport->vpi, | ||
| 1113 | be16_to_cpu(fdmi_cmd), latt, irsp->ulpStatus, | ||
| 1114 | irsp->un.ulpWord[4]); | ||
| 1115 | lpfc_ct_free_iocb(phba, cmdiocb); | ||
| 1116 | return; | ||
| 1117 | } | ||
| 1001 | 1118 | ||
| 1002 | ndlp = lpfc_findnode_did(vport, FDMI_DID); | 1119 | ndlp = lpfc_findnode_did(vport, FDMI_DID); |
| 1003 | if (fdmi_rsp == be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) { | 1120 | if (fdmi_rsp == be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) { |
| @@ -1024,13 +1141,7 @@ lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 1024 | lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RHBA); | 1141 | lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RHBA); |
| 1025 | break; | 1142 | break; |
| 1026 | } | 1143 | } |
| 1027 | 1144 | lpfc_ct_free_iocb(phba, cmdiocb); | |
| 1028 | lpfc_free_ct_rsp(phba, outp); | ||
| 1029 | lpfc_mbuf_free(phba, inp->virt, inp->phys); | ||
| 1030 | lpfc_mbuf_free(phba, bmp->virt, bmp->phys); | ||
| 1031 | kfree(inp); | ||
| 1032 | kfree(bmp); | ||
| 1033 | lpfc_sli_release_iocbq(phba, cmdiocb); | ||
| 1034 | return; | 1145 | return; |
| 1035 | } | 1146 | } |
| 1036 | 1147 | ||
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c new file mode 100644 index 000000000000..673cfe11cc2b --- /dev/null +++ b/drivers/scsi/lpfc/lpfc_debugfs.c | |||
| @@ -0,0 +1,508 @@ | |||
| 1 | /******************************************************************* | ||
| 2 | * This file is part of the Emulex Linux Device Driver for * | ||
| 3 | * Fibre Channel Host Bus Adapters. * | ||
| 4 | * Copyright (C) 2007 Emulex. All rights reserved. * | ||
| 5 | * EMULEX and SLI are trademarks of Emulex. * | ||
| 6 | * www.emulex.com * | ||
| 7 | * * | ||
| 8 | * This program is free software; you can redistribute it and/or * | ||
| 9 | * modify it under the terms of version 2 of the GNU General * | ||
| 10 | * Public License as published by the Free Software Foundation. * | ||
| 11 | * This program is distributed in the hope that it will be useful. * | ||
| 12 | * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * | ||
| 13 | * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * | ||
| 14 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * | ||
| 15 | * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * | ||
| 16 | * TO BE LEGALLY INVALID. See the GNU General Public License for * | ||
| 17 | * more details, a copy of which can be found in the file COPYING * | ||
| 18 | * included with this package. * | ||
| 19 | *******************************************************************/ | ||
| 20 | |||
| 21 | #include <linux/blkdev.h> | ||
| 22 | #include <linux/delay.h> | ||
| 23 | #include <linux/dma-mapping.h> | ||
| 24 | #include <linux/idr.h> | ||
| 25 | #include <linux/interrupt.h> | ||
| 26 | #include <linux/kthread.h> | ||
| 27 | #include <linux/pci.h> | ||
| 28 | #include <linux/spinlock.h> | ||
| 29 | #include <linux/ctype.h> | ||
| 30 | #include <linux/version.h> | ||
| 31 | |||
| 32 | #include <scsi/scsi.h> | ||
| 33 | #include <scsi/scsi_device.h> | ||
| 34 | #include <scsi/scsi_host.h> | ||
| 35 | #include <scsi/scsi_transport_fc.h> | ||
| 36 | |||
| 37 | #include "lpfc_hw.h" | ||
| 38 | #include "lpfc_sli.h" | ||
| 39 | #include "lpfc_disc.h" | ||
| 40 | #include "lpfc_scsi.h" | ||
| 41 | #include "lpfc.h" | ||
| 42 | #include "lpfc_logmsg.h" | ||
| 43 | #include "lpfc_crtn.h" | ||
| 44 | #include "lpfc_vport.h" | ||
| 45 | #include "lpfc_version.h" | ||
| 46 | #include "lpfc_vport.h" | ||
| 47 | #include "lpfc_debugfs.h" | ||
| 48 | |||
| 49 | #ifdef CONFIG_LPFC_DEBUG_FS | ||
| 50 | /* debugfs interface | ||
| 51 | * | ||
| 52 | * To access this interface the user should: | ||
| 53 | * # mkdir /debug | ||
| 54 | * # mount -t debugfs none /debug | ||
| 55 | * | ||
| 56 | * The lpfc debugfs directory hierachy is: | ||
| 57 | * lpfc/lpfcX/vportY | ||
| 58 | * where X is the lpfc hba unique_id | ||
| 59 | * where Y is the vport VPI on that hba | ||
| 60 | * | ||
| 61 | * Debugging services available per vport: | ||
| 62 | * discovery_trace | ||
| 63 | * This is an ACSII readable file that contains a trace of the last | ||
| 64 | * lpfc_debugfs_max_disc_trc events that happened on a specific vport. | ||
| 65 | * See lpfc_debugfs.h for different categories of | ||
| 66 | * discovery events. To enable the discovery trace, the following | ||
| 67 | * module parameters must be set: | ||
| 68 | * lpfc_debugfs_enable=1 Turns on lpfc debugfs filesystem support | ||
| 69 | * lpfc_debugfs_max_disc_trc=X Where X is the event trace depth for | ||
| 70 | * EACH vport. X MUST also be a power of 2. | ||
| 71 | * lpfc_debugfs_mask_disc_trc=Y Where Y is an event mask as defined in | ||
| 72 | * lpfc_debugfs.h . | ||
| 73 | */ | ||
| 74 | static int lpfc_debugfs_enable = 0; | ||
| 75 | module_param(lpfc_debugfs_enable, int, 0); | ||
| 76 | MODULE_PARM_DESC(lpfc_debugfs_enable, "Enable debugfs services"); | ||
| 77 | |||
| 78 | static int lpfc_debugfs_max_disc_trc = 0; /* This MUST be a power of 2 */ | ||
| 79 | module_param(lpfc_debugfs_max_disc_trc, int, 0); | ||
| 80 | MODULE_PARM_DESC(lpfc_debugfs_max_disc_trc, | ||
| 81 | "Set debugfs discovery trace depth"); | ||
| 82 | |||
| 83 | static int lpfc_debugfs_mask_disc_trc = 0; | ||
| 84 | module_param(lpfc_debugfs_mask_disc_trc, int, 0); | ||
| 85 | MODULE_PARM_DESC(lpfc_debugfs_mask_disc_trc, | ||
| 86 | "Set debugfs discovery trace mask"); | ||
| 87 | |||
| 88 | #include <linux/debugfs.h> | ||
| 89 | |||
| 90 | /* size of discovery_trace output line */ | ||
| 91 | #define LPFC_DISC_TRC_ENTRY_SIZE 80 | ||
| 92 | |||
| 93 | /* nodelist output buffer size */ | ||
| 94 | #define LPFC_NODELIST_SIZE 8192 | ||
| 95 | #define LPFC_NODELIST_ENTRY_SIZE 120 | ||
| 96 | |||
| 97 | struct lpfc_debug { | ||
| 98 | char *buffer; | ||
| 99 | int len; | ||
| 100 | }; | ||
| 101 | |||
| 102 | atomic_t lpfc_debugfs_disc_trc_cnt = ATOMIC_INIT(0); | ||
| 103 | unsigned long lpfc_debugfs_start_time = 0L; | ||
| 104 | |||
| 105 | static int | ||
| 106 | lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size) | ||
| 107 | { | ||
| 108 | int i, index, len, enable; | ||
| 109 | uint32_t ms; | ||
| 110 | struct lpfc_disc_trc *dtp; | ||
| 111 | char buffer[80]; | ||
| 112 | |||
| 113 | |||
| 114 | enable = lpfc_debugfs_enable; | ||
| 115 | lpfc_debugfs_enable = 0; | ||
| 116 | |||
| 117 | len = 0; | ||
| 118 | index = (atomic_read(&vport->disc_trc_cnt) + 1) & | ||
| 119 | (lpfc_debugfs_max_disc_trc - 1); | ||
| 120 | for (i = index; i < lpfc_debugfs_max_disc_trc; i++) { | ||
| 121 | dtp = vport->disc_trc + i; | ||
| 122 | if (!dtp->fmt) | ||
| 123 | continue; | ||
| 124 | ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time); | ||
| 125 | snprintf(buffer, 80, "%010d:%010d ms:%s\n", | ||
| 126 | dtp->seq_cnt, ms, dtp->fmt); | ||
| 127 | len += snprintf(buf+len, size-len, buffer, | ||
| 128 | dtp->data1, dtp->data2, dtp->data3); | ||
| 129 | } | ||
| 130 | for (i = 0; i < index; i++) { | ||
| 131 | dtp = vport->disc_trc + i; | ||
| 132 | if (!dtp->fmt) | ||
| 133 | continue; | ||
| 134 | ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time); | ||
| 135 | snprintf(buffer, 80, "%010d:%010d ms:%s\n", | ||
| 136 | dtp->seq_cnt, ms, dtp->fmt); | ||
| 137 | len += snprintf(buf+len, size-len, buffer, | ||
| 138 | dtp->data1, dtp->data2, dtp->data3); | ||
| 139 | } | ||
| 140 | |||
| 141 | lpfc_debugfs_enable = enable; | ||
| 142 | return len; | ||
| 143 | } | ||
| 144 | |||
| 145 | static int | ||
| 146 | lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size) | ||
| 147 | { | ||
| 148 | int len = 0; | ||
| 149 | int cnt; | ||
| 150 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
| 151 | struct lpfc_nodelist *ndlp; | ||
| 152 | unsigned char *statep, *name; | ||
| 153 | |||
| 154 | cnt = (LPFC_NODELIST_SIZE / LPFC_NODELIST_ENTRY_SIZE); | ||
| 155 | |||
| 156 | spin_lock_irq(shost->host_lock); | ||
| 157 | list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { | ||
| 158 | if (!cnt) { | ||
| 159 | len += snprintf(buf+len, size-len, | ||
| 160 | "Missing Nodelist Entries\n"); | ||
| 161 | break; | ||
| 162 | } | ||
| 163 | cnt--; | ||
| 164 | switch (ndlp->nlp_state) { | ||
| 165 | case NLP_STE_UNUSED_NODE: | ||
| 166 | statep = "UNUSED"; | ||
| 167 | break; | ||
| 168 | case NLP_STE_PLOGI_ISSUE: | ||
| 169 | statep = "PLOGI "; | ||
| 170 | break; | ||
| 171 | case NLP_STE_ADISC_ISSUE: | ||
| 172 | statep = "ADISC "; | ||
| 173 | break; | ||
| 174 | case NLP_STE_REG_LOGIN_ISSUE: | ||
| 175 | statep = "REGLOG"; | ||
| 176 | break; | ||
| 177 | case NLP_STE_PRLI_ISSUE: | ||
| 178 | statep = "PRLI "; | ||
| 179 | break; | ||
| 180 | case NLP_STE_UNMAPPED_NODE: | ||
| 181 | statep = "UNMAP "; | ||
| 182 | break; | ||
| 183 | case NLP_STE_MAPPED_NODE: | ||
| 184 | statep = "MAPPED"; | ||
| 185 | break; | ||
| 186 | case NLP_STE_NPR_NODE: | ||
| 187 | statep = "NPR "; | ||
| 188 | break; | ||
| 189 | default: | ||
| 190 | statep = "UNKNOWN"; | ||
| 191 | } | ||
| 192 | len += snprintf(buf+len, size-len, "%s DID:x%06x ", | ||
| 193 | statep, ndlp->nlp_DID); | ||
| 194 | name = (unsigned char *)&ndlp->nlp_portname; | ||
| 195 | len += snprintf(buf+len, size-len, | ||
| 196 | "WWPN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x ", | ||
| 197 | *name, *(name+1), *(name+2), *(name+3), | ||
| 198 | *(name+4), *(name+5), *(name+6), *(name+7)); | ||
| 199 | name = (unsigned char *)&ndlp->nlp_nodename; | ||
| 200 | len += snprintf(buf+len, size-len, | ||
| 201 | "WWNN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x ", | ||
| 202 | *name, *(name+1), *(name+2), *(name+3), | ||
| 203 | *(name+4), *(name+5), *(name+6), *(name+7)); | ||
| 204 | len += snprintf(buf+len, size-len, "RPI:%03d flag:x%08x ", | ||
| 205 | ndlp->nlp_rpi, ndlp->nlp_flag); | ||
| 206 | if (!ndlp->nlp_type) | ||
| 207 | len += snprintf(buf+len, size-len, "UNKNOWN_TYPE"); | ||
| 208 | if (ndlp->nlp_type & NLP_FC_NODE) | ||
| 209 | len += snprintf(buf+len, size-len, "FC_NODE "); | ||
| 210 | if (ndlp->nlp_type & NLP_FABRIC) | ||
| 211 | len += snprintf(buf+len, size-len, "FABRIC "); | ||
| 212 | if (ndlp->nlp_type & NLP_FCP_TARGET) | ||
| 213 | len += snprintf(buf+len, size-len, "FCP_TGT sid:%d ", | ||
| 214 | ndlp->nlp_sid); | ||
| 215 | if (ndlp->nlp_type & NLP_FCP_INITIATOR) | ||
| 216 | len += snprintf(buf+len, size-len, "FCP_INITIATOR"); | ||
| 217 | len += snprintf(buf+len, size-len, "\n"); | ||
| 218 | } | ||
| 219 | spin_unlock_irq(shost->host_lock); | ||
| 220 | return len; | ||
| 221 | } | ||
| 222 | #endif | ||
| 223 | |||
| 224 | |||
| 225 | inline void | ||
| 226 | lpfc_debugfs_disc_trc(struct lpfc_vport *vport, int mask, char *fmt, | ||
| 227 | uint32_t data1, uint32_t data2, uint32_t data3) | ||
| 228 | { | ||
| 229 | #ifdef CONFIG_LPFC_DEBUG_FS | ||
| 230 | struct lpfc_disc_trc *dtp; | ||
| 231 | int index; | ||
| 232 | |||
| 233 | if (!(lpfc_debugfs_mask_disc_trc & mask)) | ||
| 234 | return; | ||
| 235 | |||
| 236 | if (!lpfc_debugfs_enable || !lpfc_debugfs_max_disc_trc || | ||
| 237 | !vport || !vport->disc_trc) | ||
| 238 | return; | ||
| 239 | |||
| 240 | index = atomic_inc_return(&vport->disc_trc_cnt) & | ||
| 241 | (lpfc_debugfs_max_disc_trc - 1); | ||
| 242 | dtp = vport->disc_trc + index; | ||
| 243 | dtp->fmt = fmt; | ||
| 244 | dtp->data1 = data1; | ||
| 245 | dtp->data2 = data2; | ||
| 246 | dtp->data3 = data3; | ||
| 247 | dtp->seq_cnt = atomic_inc_return(&lpfc_debugfs_disc_trc_cnt); | ||
| 248 | dtp->jif = jiffies; | ||
| 249 | #endif | ||
| 250 | return; | ||
| 251 | } | ||
| 252 | |||
| 253 | #ifdef CONFIG_LPFC_DEBUG_FS | ||
| 254 | static int | ||
| 255 | lpfc_debugfs_disc_trc_open(struct inode *inode, struct file *file) | ||
| 256 | { | ||
| 257 | struct lpfc_vport *vport = inode->i_private; | ||
| 258 | struct lpfc_debug *debug; | ||
| 259 | int size; | ||
| 260 | int rc = -ENOMEM; | ||
| 261 | |||
| 262 | if (!lpfc_debugfs_max_disc_trc) { | ||
| 263 | rc = -ENOSPC; | ||
| 264 | goto out; | ||
| 265 | } | ||
| 266 | |||
| 267 | debug = kmalloc(sizeof(*debug), GFP_KERNEL); | ||
| 268 | if (!debug) | ||
| 269 | goto out; | ||
| 270 | |||
| 271 | /* Round to page boundry */ | ||
| 272 | size = (lpfc_debugfs_max_disc_trc * LPFC_DISC_TRC_ENTRY_SIZE); | ||
| 273 | size = PAGE_ALIGN(size); | ||
| 274 | |||
| 275 | debug->buffer = kmalloc(size, GFP_KERNEL); | ||
| 276 | if (!debug->buffer) { | ||
| 277 | kfree(debug); | ||
| 278 | goto out; | ||
| 279 | } | ||
| 280 | |||
| 281 | debug->len = lpfc_debugfs_disc_trc_data(vport, debug->buffer, size); | ||
| 282 | file->private_data = debug; | ||
| 283 | |||
| 284 | rc = 0; | ||
| 285 | out: | ||
| 286 | return rc; | ||
| 287 | } | ||
| 288 | |||
| 289 | static int | ||
| 290 | lpfc_debugfs_nodelist_open(struct inode *inode, struct file *file) | ||
| 291 | { | ||
| 292 | struct lpfc_vport *vport = inode->i_private; | ||
| 293 | struct lpfc_debug *debug; | ||
| 294 | int rc = -ENOMEM; | ||
| 295 | |||
| 296 | debug = kmalloc(sizeof(*debug), GFP_KERNEL); | ||
| 297 | if (!debug) | ||
| 298 | goto out; | ||
| 299 | |||
| 300 | /* Round to page boundry */ | ||
| 301 | debug->buffer = kmalloc(LPFC_NODELIST_SIZE, GFP_KERNEL); | ||
| 302 | if (!debug->buffer) { | ||
| 303 | kfree(debug); | ||
| 304 | goto out; | ||
| 305 | } | ||
| 306 | |||
| 307 | debug->len = lpfc_debugfs_nodelist_data(vport, debug->buffer, | ||
| 308 | LPFC_NODELIST_SIZE); | ||
| 309 | file->private_data = debug; | ||
| 310 | |||
| 311 | rc = 0; | ||
| 312 | out: | ||
| 313 | return rc; | ||
| 314 | } | ||
| 315 | |||
| 316 | static loff_t | ||
| 317 | lpfc_debugfs_lseek(struct file *file, loff_t off, int whence) | ||
| 318 | { | ||
| 319 | struct lpfc_debug *debug; | ||
| 320 | loff_t pos = -1; | ||
| 321 | |||
| 322 | debug = file->private_data; | ||
| 323 | |||
| 324 | switch (whence) { | ||
| 325 | case 0: | ||
| 326 | pos = off; | ||
| 327 | break; | ||
| 328 | case 1: | ||
| 329 | pos = file->f_pos + off; | ||
| 330 | break; | ||
| 331 | case 2: | ||
| 332 | pos = debug->len - off; | ||
| 333 | } | ||
| 334 | return (pos < 0 || pos > debug->len) ? -EINVAL : (file->f_pos = pos); | ||
| 335 | } | ||
| 336 | |||
| 337 | static ssize_t | ||
| 338 | lpfc_debugfs_read(struct file *file, char __user *buf, | ||
| 339 | size_t nbytes, loff_t *ppos) | ||
| 340 | { | ||
| 341 | struct lpfc_debug *debug = file->private_data; | ||
| 342 | return simple_read_from_buffer(buf, nbytes, ppos, debug->buffer, | ||
| 343 | debug->len); | ||
| 344 | } | ||
| 345 | |||
| 346 | static int | ||
| 347 | lpfc_debugfs_release(struct inode *inode, struct file *file) | ||
| 348 | { | ||
| 349 | struct lpfc_debug *debug = file->private_data; | ||
| 350 | |||
| 351 | kfree(debug->buffer); | ||
| 352 | kfree(debug); | ||
| 353 | |||
| 354 | return 0; | ||
| 355 | } | ||
| 356 | |||
| 357 | #undef lpfc_debugfs_op_disc_trc | ||
| 358 | static struct file_operations lpfc_debugfs_op_disc_trc = { | ||
| 359 | .owner = THIS_MODULE, | ||
| 360 | .open = lpfc_debugfs_disc_trc_open, | ||
| 361 | .llseek = lpfc_debugfs_lseek, | ||
| 362 | .read = lpfc_debugfs_read, | ||
| 363 | .release = lpfc_debugfs_release, | ||
| 364 | }; | ||
| 365 | |||
| 366 | #undef lpfc_debugfs_op_nodelist | ||
| 367 | static struct file_operations lpfc_debugfs_op_nodelist = { | ||
| 368 | .owner = THIS_MODULE, | ||
| 369 | .open = lpfc_debugfs_nodelist_open, | ||
| 370 | .llseek = lpfc_debugfs_lseek, | ||
| 371 | .read = lpfc_debugfs_read, | ||
| 372 | .release = lpfc_debugfs_release, | ||
| 373 | }; | ||
| 374 | |||
| 375 | static struct dentry *lpfc_debugfs_root = NULL; | ||
| 376 | static atomic_t lpfc_debugfs_hba_count; | ||
| 377 | #endif | ||
| 378 | |||
| 379 | inline void | ||
| 380 | lpfc_debugfs_initialize(struct lpfc_vport *vport) | ||
| 381 | { | ||
| 382 | #ifdef CONFIG_LPFC_DEBUG_FS | ||
| 383 | struct lpfc_hba *phba = vport->phba; | ||
| 384 | char name[64]; | ||
| 385 | uint32_t num, i; | ||
| 386 | |||
| 387 | if (!lpfc_debugfs_enable) | ||
| 388 | return; | ||
| 389 | |||
| 390 | if (lpfc_debugfs_max_disc_trc) { | ||
| 391 | num = lpfc_debugfs_max_disc_trc - 1; | ||
| 392 | if (num & lpfc_debugfs_max_disc_trc) { | ||
| 393 | /* Change to be a power of 2 */ | ||
| 394 | num = lpfc_debugfs_max_disc_trc; | ||
| 395 | i = 0; | ||
| 396 | while (num > 1) { | ||
| 397 | num = num >> 1; | ||
| 398 | i++; | ||
| 399 | } | ||
| 400 | lpfc_debugfs_max_disc_trc = (1 << i); | ||
| 401 | printk(KERN_ERR | ||
| 402 | "lpfc_debugfs_max_disc_trc changed to %d\n", | ||
| 403 | lpfc_debugfs_max_disc_trc); | ||
| 404 | } | ||
| 405 | } | ||
| 406 | |||
| 407 | if (!lpfc_debugfs_root) { | ||
| 408 | lpfc_debugfs_root = debugfs_create_dir("lpfc", NULL); | ||
| 409 | atomic_set(&lpfc_debugfs_hba_count, 0); | ||
| 410 | if (!lpfc_debugfs_root) | ||
| 411 | goto debug_failed; | ||
| 412 | } | ||
| 413 | |||
| 414 | snprintf(name, sizeof(name), "lpfc%d", phba->brd_no); | ||
| 415 | if (!phba->hba_debugfs_root) { | ||
| 416 | phba->hba_debugfs_root = | ||
| 417 | debugfs_create_dir(name, lpfc_debugfs_root); | ||
| 418 | if (!phba->hba_debugfs_root) | ||
| 419 | goto debug_failed; | ||
| 420 | atomic_inc(&lpfc_debugfs_hba_count); | ||
| 421 | atomic_set(&phba->debugfs_vport_count, 0); | ||
| 422 | } | ||
| 423 | |||
| 424 | snprintf(name, sizeof(name), "vport%d", vport->vpi); | ||
| 425 | if (!vport->vport_debugfs_root) { | ||
| 426 | vport->vport_debugfs_root = | ||
| 427 | debugfs_create_dir(name, phba->hba_debugfs_root); | ||
| 428 | if (!vport->vport_debugfs_root) | ||
| 429 | goto debug_failed; | ||
| 430 | atomic_inc(&phba->debugfs_vport_count); | ||
| 431 | } | ||
| 432 | |||
| 433 | if (!lpfc_debugfs_start_time) | ||
| 434 | lpfc_debugfs_start_time = jiffies; | ||
| 435 | |||
| 436 | vport->disc_trc = kmalloc( | ||
| 437 | (sizeof(struct lpfc_disc_trc) * lpfc_debugfs_max_disc_trc), | ||
| 438 | GFP_KERNEL); | ||
| 439 | |||
| 440 | if (!vport->disc_trc) | ||
| 441 | goto debug_failed; | ||
| 442 | memset(vport->disc_trc, 0, | ||
| 443 | (sizeof(struct lpfc_disc_trc) * lpfc_debugfs_max_disc_trc)); | ||
| 444 | |||
| 445 | snprintf(name, sizeof(name), "discovery_trace"); | ||
| 446 | vport->debug_disc_trc = | ||
| 447 | debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, | ||
| 448 | vport->vport_debugfs_root, | ||
| 449 | vport, &lpfc_debugfs_op_disc_trc); | ||
| 450 | if (!vport->debug_disc_trc) { | ||
| 451 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
| 452 | "%d:0409 Cannot create debugfs", | ||
| 453 | phba->brd_no); | ||
| 454 | goto debug_failed; | ||
| 455 | } | ||
| 456 | snprintf(name, sizeof(name), "nodelist"); | ||
| 457 | vport->debug_nodelist = | ||
| 458 | debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, | ||
| 459 | vport->vport_debugfs_root, | ||
| 460 | vport, &lpfc_debugfs_op_nodelist); | ||
| 461 | if (!vport->debug_nodelist) { | ||
| 462 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
| 463 | "%d:0409 Cannot create debugfs", | ||
| 464 | phba->brd_no); | ||
| 465 | goto debug_failed; | ||
| 466 | } | ||
| 467 | debug_failed: | ||
| 468 | return; | ||
| 469 | #endif | ||
| 470 | } | ||
| 471 | |||
| 472 | |||
| 473 | inline void | ||
| 474 | lpfc_debugfs_terminate(struct lpfc_vport *vport) | ||
| 475 | { | ||
| 476 | #ifdef CONFIG_LPFC_DEBUG_FS | ||
| 477 | struct lpfc_hba *phba = vport->phba; | ||
| 478 | |||
| 479 | if (vport->disc_trc) { | ||
| 480 | kfree(vport->disc_trc); | ||
| 481 | vport->disc_trc = NULL; | ||
| 482 | } | ||
| 483 | if (vport->debug_disc_trc) { | ||
| 484 | debugfs_remove(vport->debug_disc_trc); /* discovery_trace */ | ||
| 485 | vport->debug_disc_trc = NULL; | ||
| 486 | } | ||
| 487 | if (vport->debug_nodelist) { | ||
| 488 | debugfs_remove(vport->debug_nodelist); /* nodelist */ | ||
| 489 | vport->debug_nodelist = NULL; | ||
| 490 | } | ||
| 491 | if (vport->vport_debugfs_root) { | ||
| 492 | debugfs_remove(vport->vport_debugfs_root); /* vportX */ | ||
| 493 | vport->vport_debugfs_root = NULL; | ||
| 494 | atomic_dec(&phba->debugfs_vport_count); | ||
| 495 | } | ||
| 496 | if (atomic_read(&phba->debugfs_vport_count) == 0) { | ||
| 497 | debugfs_remove(vport->phba->hba_debugfs_root); /* lpfcX */ | ||
| 498 | vport->phba->hba_debugfs_root = NULL; | ||
| 499 | atomic_dec(&lpfc_debugfs_hba_count); | ||
| 500 | if (atomic_read(&lpfc_debugfs_hba_count) == 0) { | ||
| 501 | debugfs_remove(lpfc_debugfs_root); /* lpfc */ | ||
| 502 | lpfc_debugfs_root = NULL; | ||
| 503 | } | ||
| 504 | } | ||
| 505 | #endif | ||
| 506 | } | ||
| 507 | |||
| 508 | |||
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.h b/drivers/scsi/lpfc/lpfc_debugfs.h new file mode 100644 index 000000000000..fffb678426a4 --- /dev/null +++ b/drivers/scsi/lpfc/lpfc_debugfs.h | |||
| @@ -0,0 +1,50 @@ | |||
| 1 | /******************************************************************* | ||
| 2 | * This file is part of the Emulex Linux Device Driver for * | ||
| 3 | * Fibre Channel Host Bus Adapters. * | ||
| 4 | * Copyright (C) 2007 Emulex. All rights reserved. * | ||
| 5 | * EMULEX and SLI are trademarks of Emulex. * | ||
| 6 | * www.emulex.com * | ||
| 7 | * * | ||
| 8 | * This program is free software; you can redistribute it and/or * | ||
| 9 | * modify it under the terms of version 2 of the GNU General * | ||
| 10 | * Public License as published by the Free Software Foundation. * | ||
| 11 | * This program is distributed in the hope that it will be useful. * | ||
| 12 | * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * | ||
| 13 | * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * | ||
| 14 | * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * | ||
| 15 | * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * | ||
| 16 | * TO BE LEGALLY INVALID. See the GNU General Public License for * | ||
| 17 | * more details, a copy of which can be found in the file COPYING * | ||
| 18 | * included with this package. * | ||
| 19 | *******************************************************************/ | ||
| 20 | |||
| 21 | #ifndef _H_LPFC_DEBUG_FS | ||
| 22 | #define _H_LPFC_DEBUG_FS | ||
| 23 | |||
| 24 | #ifdef CONFIG_LPFC_DEBUG_FS | ||
| 25 | struct lpfc_disc_trc { | ||
| 26 | char *fmt; | ||
| 27 | uint32_t data1; | ||
| 28 | uint32_t data2; | ||
| 29 | uint32_t data3; | ||
| 30 | uint32_t seq_cnt; | ||
| 31 | unsigned long jif; | ||
| 32 | }; | ||
| 33 | #endif | ||
| 34 | |||
| 35 | /* Mask for discovery_trace */ | ||
| 36 | #define LPFC_DISC_TRC_ELS_CMD 0x1 /* Trace ELS commands */ | ||
| 37 | #define LPFC_DISC_TRC_ELS_RSP 0x2 /* Trace ELS response */ | ||
| 38 | #define LPFC_DISC_TRC_ELS_UNSOL 0x4 /* Trace ELS rcv'ed */ | ||
| 39 | #define LPFC_DISC_TRC_ELS_ALL 0x7 /* Trace ELS */ | ||
| 40 | #define LPFC_DISC_TRC_MBOX_VPORT 0x8 /* Trace vport MBOXs */ | ||
| 41 | #define LPFC_DISC_TRC_MBOX 0x10 /* Trace other MBOXs */ | ||
| 42 | #define LPFC_DISC_TRC_MBOX_ALL 0x18 /* Trace all MBOXs */ | ||
| 43 | #define LPFC_DISC_TRC_CT 0x20 /* Trace disc CT requests */ | ||
| 44 | #define LPFC_DISC_TRC_DSM 0x40 /* Trace DSM events */ | ||
| 45 | #define LPFC_DISC_TRC_RPORT 0x80 /* Trace rport events */ | ||
| 46 | #define LPFC_DISC_TRC_NODE 0x100 /* Trace ndlp state changes */ | ||
| 47 | |||
| 48 | #define LPFC_DISC_TRC_DISCOVERY 0xef /* common mask for general | ||
| 49 | * discovery */ | ||
| 50 | #endif /* H_LPFC_DEBUG_FS */ | ||
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h index f23fe1e5fbb7..aacac9ac5381 100644 --- a/drivers/scsi/lpfc/lpfc_disc.h +++ b/drivers/scsi/lpfc/lpfc_disc.h | |||
| @@ -36,6 +36,7 @@ enum lpfc_work_type { | |||
| 36 | LPFC_EVT_WARM_START, | 36 | LPFC_EVT_WARM_START, |
| 37 | LPFC_EVT_KILL, | 37 | LPFC_EVT_KILL, |
| 38 | LPFC_EVT_ELS_RETRY, | 38 | LPFC_EVT_ELS_RETRY, |
| 39 | LPFC_EVT_DEV_LOSS_DELAY, | ||
| 39 | LPFC_EVT_DEV_LOSS, | 40 | LPFC_EVT_DEV_LOSS, |
| 40 | }; | 41 | }; |
| 41 | 42 | ||
| @@ -74,7 +75,6 @@ struct lpfc_nodelist { | |||
| 74 | #define NLP_FCP_2_DEVICE 0x10 /* FCP-2 device */ | 75 | #define NLP_FCP_2_DEVICE 0x10 /* FCP-2 device */ |
| 75 | 76 | ||
| 76 | struct timer_list nlp_delayfunc; /* Used for delayed ELS cmds */ | 77 | struct timer_list nlp_delayfunc; /* Used for delayed ELS cmds */ |
| 77 | struct timer_list nlp_initiator_tmr; /* Used with dev_loss */ | ||
| 78 | struct fc_rport *rport; /* Corresponding FC transport | 78 | struct fc_rport *rport; /* Corresponding FC transport |
| 79 | port structure */ | 79 | port structure */ |
| 80 | struct lpfc_vport *vport; | 80 | struct lpfc_vport *vport; |
| @@ -101,6 +101,7 @@ struct lpfc_nodelist { | |||
| 101 | ACC */ | 101 | ACC */ |
| 102 | #define NLP_NPR_ADISC 0x2000000 /* Issue ADISC when dq'ed from | 102 | #define NLP_NPR_ADISC 0x2000000 /* Issue ADISC when dq'ed from |
| 103 | NPR list */ | 103 | NPR list */ |
| 104 | #define NLP_RM_DFLT_RPI 0x4000000 /* need to remove leftover dflt RPI */ | ||
| 104 | #define NLP_NODEV_REMOVE 0x8000000 /* Defer removal till discovery ends */ | 105 | #define NLP_NODEV_REMOVE 0x8000000 /* Defer removal till discovery ends */ |
| 105 | #define NLP_TARGET_REMOVE 0x10000000 /* Target remove in process */ | 106 | #define NLP_TARGET_REMOVE 0x10000000 /* Target remove in process */ |
| 106 | 107 | ||
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index f60c85d791c7..33fbc1666946 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #include "lpfc_logmsg.h" | 36 | #include "lpfc_logmsg.h" |
| 37 | #include "lpfc_crtn.h" | 37 | #include "lpfc_crtn.h" |
| 38 | #include "lpfc_vport.h" | 38 | #include "lpfc_vport.h" |
| 39 | #include "lpfc_debugfs.h" | ||
| 39 | 40 | ||
| 40 | static int lpfc_els_retry(struct lpfc_hba *, struct lpfc_iocbq *, | 41 | static int lpfc_els_retry(struct lpfc_hba *, struct lpfc_iocbq *, |
| 41 | struct lpfc_iocbq *); | 42 | struct lpfc_iocbq *); |
| @@ -44,7 +45,7 @@ static void lpfc_cmpl_fabric_iocb(struct lpfc_hba *, struct lpfc_iocbq *, | |||
| 44 | 45 | ||
| 45 | static int lpfc_max_els_tries = 3; | 46 | static int lpfc_max_els_tries = 3; |
| 46 | 47 | ||
| 47 | static int | 48 | int |
| 48 | lpfc_els_chk_latt(struct lpfc_vport *vport) | 49 | lpfc_els_chk_latt(struct lpfc_vport *vport) |
| 49 | { | 50 | { |
| 50 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 51 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
| @@ -353,7 +354,6 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 353 | "%d:1817 Fabric does not support NPIV " | 354 | "%d:1817 Fabric does not support NPIV " |
| 354 | "- configuring single port mode.\n", | 355 | "- configuring single port mode.\n", |
| 355 | phba->brd_no); | 356 | phba->brd_no); |
| 356 | phba->vpi_cnt = 1; | ||
| 357 | phba->link_flag &= ~LS_NPIV_FAB_SUPPORTED; | 357 | phba->link_flag &= ~LS_NPIV_FAB_SUPPORTED; |
| 358 | } | 358 | } |
| 359 | } | 359 | } |
| @@ -406,7 +406,6 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 406 | 406 | ||
| 407 | spin_lock_irq(shost->host_lock); | 407 | spin_lock_irq(shost->host_lock); |
| 408 | vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); | 408 | vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); |
| 409 | phba->vpi_cnt = 1; | ||
| 410 | spin_unlock_irq(shost->host_lock); | 409 | spin_unlock_irq(shost->host_lock); |
| 411 | 410 | ||
| 412 | phba->fc_edtov = FF_DEF_EDTOV; | 411 | phba->fc_edtov = FF_DEF_EDTOV; |
| @@ -499,6 +498,11 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 499 | goto out; | 498 | goto out; |
| 500 | } | 499 | } |
| 501 | 500 | ||
| 501 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
| 502 | "FLOGI cmpl: status:x%x/x%x state:x%x", | ||
| 503 | irsp->ulpStatus, irsp->un.ulpWord[4], | ||
| 504 | vport->port_state); | ||
| 505 | |||
| 502 | if (irsp->ulpStatus) { | 506 | if (irsp->ulpStatus) { |
| 503 | /* Check for retry */ | 507 | /* Check for retry */ |
| 504 | if (lpfc_els_retry(phba, cmdiocb, rspiocb)) | 508 | if (lpfc_els_retry(phba, cmdiocb, rspiocb)) |
| @@ -507,7 +511,6 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 507 | /* FLOGI failed, so there is no fabric */ | 511 | /* FLOGI failed, so there is no fabric */ |
| 508 | spin_lock_irq(shost->host_lock); | 512 | spin_lock_irq(shost->host_lock); |
| 509 | vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); | 513 | vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); |
| 510 | phba->vpi_cnt = 1; | ||
| 511 | spin_unlock_irq(shost->host_lock); | 514 | spin_unlock_irq(shost->host_lock); |
| 512 | 515 | ||
| 513 | /* If private loop, then allow max outstanding els to be | 516 | /* If private loop, then allow max outstanding els to be |
| @@ -560,11 +563,8 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 560 | 563 | ||
| 561 | flogifail: | 564 | flogifail: |
| 562 | lpfc_nlp_put(ndlp); | 565 | lpfc_nlp_put(ndlp); |
| 563 | phba->vpi_cnt = 1; | ||
| 564 | 566 | ||
| 565 | if (irsp->ulpStatus != IOSTAT_LOCAL_REJECT || | 567 | if (!lpfc_error_lost_link(irsp)) { |
| 566 | (irsp->un.ulpWord[4] != IOERR_SLI_ABORTED && | ||
| 567 | irsp->un.ulpWord[4] != IOERR_SLI_DOWN)) { | ||
| 568 | /* FLOGI failed, so just use loop map to make discovery list */ | 568 | /* FLOGI failed, so just use loop map to make discovery list */ |
| 569 | lpfc_disc_list_loopmap(vport); | 569 | lpfc_disc_list_loopmap(vport); |
| 570 | 570 | ||
| @@ -627,6 +627,11 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 627 | icmd->ulpCt_l = 0; | 627 | icmd->ulpCt_l = 0; |
| 628 | } | 628 | } |
| 629 | 629 | ||
| 630 | if (phba->fc_topology != TOPOLOGY_LOOP) { | ||
| 631 | icmd->un.elsreq64.myID = 0; | ||
| 632 | icmd->un.elsreq64.fl = 1; | ||
| 633 | } | ||
| 634 | |||
| 630 | tmo = phba->fc_ratov; | 635 | tmo = phba->fc_ratov; |
| 631 | phba->fc_ratov = LPFC_DISC_FLOGI_TMO; | 636 | phba->fc_ratov = LPFC_DISC_FLOGI_TMO; |
| 632 | lpfc_set_disctmo(vport); | 637 | lpfc_set_disctmo(vport); |
| @@ -634,6 +639,11 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 634 | 639 | ||
| 635 | phba->fc_stat.elsXmitFLOGI++; | 640 | phba->fc_stat.elsXmitFLOGI++; |
| 636 | elsiocb->iocb_cmpl = lpfc_cmpl_els_flogi; | 641 | elsiocb->iocb_cmpl = lpfc_cmpl_els_flogi; |
| 642 | |||
| 643 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
| 644 | "Issue FLOGI: opt:x%x", | ||
| 645 | phba->sli3_options, 0, 0); | ||
| 646 | |||
| 637 | rc = lpfc_issue_fabric_iocb(phba, elsiocb); | 647 | rc = lpfc_issue_fabric_iocb(phba, elsiocb); |
| 638 | if (rc == IOCB_ERROR) { | 648 | if (rc == IOCB_ERROR) { |
| 639 | lpfc_els_free_iocb(phba, elsiocb); | 649 | lpfc_els_free_iocb(phba, elsiocb); |
| @@ -816,6 +826,11 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 816 | cmdiocb->context_un.rsp_iocb = rspiocb; | 826 | cmdiocb->context_un.rsp_iocb = rspiocb; |
| 817 | 827 | ||
| 818 | irsp = &rspiocb->iocb; | 828 | irsp = &rspiocb->iocb; |
| 829 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
| 830 | "PLOGI cmpl: status:x%x/x%x did:x%x", | ||
| 831 | irsp->ulpStatus, irsp->un.ulpWord[4], | ||
| 832 | irsp->un.elsreq64.remoteID); | ||
| 833 | |||
| 819 | ndlp = lpfc_findnode_did(vport, irsp->un.elsreq64.remoteID); | 834 | ndlp = lpfc_findnode_did(vport, irsp->un.elsreq64.remoteID); |
| 820 | if (!ndlp) { | 835 | if (!ndlp) { |
| 821 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, | 836 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, |
| @@ -878,10 +893,7 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 878 | } | 893 | } |
| 879 | 894 | ||
| 880 | /* Do not call DSM for lpfc_els_abort'ed ELS cmds */ | 895 | /* Do not call DSM for lpfc_els_abort'ed ELS cmds */ |
| 881 | if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) && | 896 | if (lpfc_error_lost_link(irsp)) { |
| 882 | ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) || | ||
| 883 | (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) || | ||
| 884 | (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) { | ||
| 885 | rc = NLP_STE_FREED_NODE; | 897 | rc = NLP_STE_FREED_NODE; |
| 886 | } else { | 898 | } else { |
| 887 | rc = lpfc_disc_state_machine(vport, ndlp, cmdiocb, | 899 | rc = lpfc_disc_state_machine(vport, ndlp, cmdiocb, |
| @@ -966,6 +978,10 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry) | |||
| 966 | if (sp->cmn.fcphHigh < FC_PH3) | 978 | if (sp->cmn.fcphHigh < FC_PH3) |
| 967 | sp->cmn.fcphHigh = FC_PH3; | 979 | sp->cmn.fcphHigh = FC_PH3; |
| 968 | 980 | ||
| 981 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
| 982 | "Issue PLOGI: did:x%x", | ||
| 983 | did, 0, 0); | ||
| 984 | |||
| 969 | phba->fc_stat.elsXmitPLOGI++; | 985 | phba->fc_stat.elsXmitPLOGI++; |
| 970 | elsiocb->iocb_cmpl = lpfc_cmpl_els_plogi; | 986 | elsiocb->iocb_cmpl = lpfc_cmpl_els_plogi; |
| 971 | ret = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0); | 987 | ret = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0); |
| @@ -997,6 +1013,11 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 997 | ndlp->nlp_flag &= ~NLP_PRLI_SND; | 1013 | ndlp->nlp_flag &= ~NLP_PRLI_SND; |
| 998 | spin_unlock_irq(shost->host_lock); | 1014 | spin_unlock_irq(shost->host_lock); |
| 999 | 1015 | ||
| 1016 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
| 1017 | "PRLI cmpl: status:x%x/x%x did:x%x", | ||
| 1018 | irsp->ulpStatus, irsp->un.ulpWord[4], | ||
| 1019 | ndlp->nlp_DID); | ||
| 1020 | |||
| 1000 | /* PRLI completes to NPort <nlp_DID> */ | 1021 | /* PRLI completes to NPort <nlp_DID> */ |
| 1001 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | 1022 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, |
| 1002 | "%d (%d):0103 PRLI completes to NPort x%x " | 1023 | "%d (%d):0103 PRLI completes to NPort x%x " |
| @@ -1018,10 +1039,7 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 1018 | } | 1039 | } |
| 1019 | /* PRLI failed */ | 1040 | /* PRLI failed */ |
| 1020 | /* Do not call DSM for lpfc_els_abort'ed ELS cmds */ | 1041 | /* Do not call DSM for lpfc_els_abort'ed ELS cmds */ |
| 1021 | if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) && | 1042 | if (lpfc_error_lost_link(irsp)) { |
| 1022 | ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) || | ||
| 1023 | (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) || | ||
| 1024 | (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) { | ||
| 1025 | goto out; | 1043 | goto out; |
| 1026 | } else { | 1044 | } else { |
| 1027 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, | 1045 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, |
| @@ -1087,6 +1105,10 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 1087 | npr->prliType = PRLI_FCP_TYPE; | 1105 | npr->prliType = PRLI_FCP_TYPE; |
| 1088 | npr->initiatorFunc = 1; | 1106 | npr->initiatorFunc = 1; |
| 1089 | 1107 | ||
| 1108 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
| 1109 | "Issue PRLI: did:x%x", | ||
| 1110 | ndlp->nlp_DID, 0, 0); | ||
| 1111 | |||
| 1090 | phba->fc_stat.elsXmitPRLI++; | 1112 | phba->fc_stat.elsXmitPRLI++; |
| 1091 | elsiocb->iocb_cmpl = lpfc_cmpl_els_prli; | 1113 | elsiocb->iocb_cmpl = lpfc_cmpl_els_prli; |
| 1092 | spin_lock_irq(shost->host_lock); | 1114 | spin_lock_irq(shost->host_lock); |
| @@ -1133,6 +1155,8 @@ lpfc_rscn_disc(struct lpfc_vport *vport) | |||
| 1133 | { | 1155 | { |
| 1134 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 1156 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
| 1135 | 1157 | ||
| 1158 | lpfc_can_disctmo(vport); | ||
| 1159 | |||
| 1136 | /* RSCN discovery */ | 1160 | /* RSCN discovery */ |
| 1137 | /* go thru NPR nodes and issue ELS PLOGIs */ | 1161 | /* go thru NPR nodes and issue ELS PLOGIs */ |
| 1138 | if (vport->fc_npr_cnt) | 1162 | if (vport->fc_npr_cnt) |
| @@ -1170,6 +1194,11 @@ lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 1170 | irsp = &(rspiocb->iocb); | 1194 | irsp = &(rspiocb->iocb); |
| 1171 | ndlp = (struct lpfc_nodelist *) cmdiocb->context1; | 1195 | ndlp = (struct lpfc_nodelist *) cmdiocb->context1; |
| 1172 | 1196 | ||
| 1197 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
| 1198 | "ADISC cmpl: status:x%x/x%x did:x%x", | ||
| 1199 | irsp->ulpStatus, irsp->un.ulpWord[4], | ||
| 1200 | ndlp->nlp_DID); | ||
| 1201 | |||
| 1173 | /* Since ndlp can be freed in the disc state machine, note if this node | 1202 | /* Since ndlp can be freed in the disc state machine, note if this node |
| 1174 | * is being used during discovery. | 1203 | * is being used during discovery. |
| 1175 | */ | 1204 | */ |
| @@ -1208,12 +1237,9 @@ lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 1208 | } | 1237 | } |
| 1209 | /* ADISC failed */ | 1238 | /* ADISC failed */ |
| 1210 | /* Do not call DSM for lpfc_els_abort'ed ELS cmds */ | 1239 | /* Do not call DSM for lpfc_els_abort'ed ELS cmds */ |
| 1211 | if ((irsp->ulpStatus != IOSTAT_LOCAL_REJECT) || | 1240 | if (!lpfc_error_lost_link(irsp)) { |
| 1212 | ((irsp->un.ulpWord[4] != IOERR_SLI_ABORTED) && | ||
| 1213 | (irsp->un.ulpWord[4] != IOERR_LINK_DOWN) && | ||
| 1214 | (irsp->un.ulpWord[4] != IOERR_SLI_DOWN))) { | ||
| 1215 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, | 1241 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, |
| 1216 | NLP_EVT_CMPL_ADISC); | 1242 | NLP_EVT_CMPL_ADISC); |
| 1217 | } | 1243 | } |
| 1218 | } else { | 1244 | } else { |
| 1219 | /* Good status, call state machine */ | 1245 | /* Good status, call state machine */ |
| @@ -1306,6 +1332,10 @@ lpfc_issue_els_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 1306 | memcpy(&ap->nodeName, &vport->fc_nodename, sizeof(struct lpfc_name)); | 1332 | memcpy(&ap->nodeName, &vport->fc_nodename, sizeof(struct lpfc_name)); |
| 1307 | ap->DID = be32_to_cpu(vport->fc_myDID); | 1333 | ap->DID = be32_to_cpu(vport->fc_myDID); |
| 1308 | 1334 | ||
| 1335 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
| 1336 | "Issue ADISC: did:x%x", | ||
| 1337 | ndlp->nlp_DID, 0, 0); | ||
| 1338 | |||
| 1309 | phba->fc_stat.elsXmitADISC++; | 1339 | phba->fc_stat.elsXmitADISC++; |
| 1310 | elsiocb->iocb_cmpl = lpfc_cmpl_els_adisc; | 1340 | elsiocb->iocb_cmpl = lpfc_cmpl_els_adisc; |
| 1311 | spin_lock_irq(shost->host_lock); | 1341 | spin_lock_irq(shost->host_lock); |
| @@ -1340,6 +1370,11 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 1340 | ndlp->nlp_flag &= ~NLP_LOGO_SND; | 1370 | ndlp->nlp_flag &= ~NLP_LOGO_SND; |
| 1341 | spin_unlock_irq(shost->host_lock); | 1371 | spin_unlock_irq(shost->host_lock); |
| 1342 | 1372 | ||
| 1373 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
| 1374 | "LOGO cmpl: status:x%x/x%x did:x%x", | ||
| 1375 | irsp->ulpStatus, irsp->un.ulpWord[4], | ||
| 1376 | ndlp->nlp_DID); | ||
| 1377 | |||
| 1343 | /* LOGO completes to NPort <nlp_DID> */ | 1378 | /* LOGO completes to NPort <nlp_DID> */ |
| 1344 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | 1379 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, |
| 1345 | "%d (%d):0105 LOGO completes to NPort x%x " | 1380 | "%d (%d):0105 LOGO completes to NPort x%x " |
| @@ -1368,15 +1403,11 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 1368 | goto out; | 1403 | goto out; |
| 1369 | /* LOGO failed */ | 1404 | /* LOGO failed */ |
| 1370 | /* Do not call DSM for lpfc_els_abort'ed ELS cmds */ | 1405 | /* Do not call DSM for lpfc_els_abort'ed ELS cmds */ |
| 1371 | if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) && | 1406 | if (lpfc_error_lost_link(irsp)) |
| 1372 | ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) || | ||
| 1373 | (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) || | ||
| 1374 | (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) { | ||
| 1375 | goto out; | 1407 | goto out; |
| 1376 | } else { | 1408 | else |
| 1377 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, | 1409 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, |
| 1378 | NLP_EVT_CMPL_LOGO); | 1410 | NLP_EVT_CMPL_LOGO); |
| 1379 | } | ||
| 1380 | } else { | 1411 | } else { |
| 1381 | /* Good status, call state machine. | 1412 | /* Good status, call state machine. |
| 1382 | * This will unregister the rpi if needed. | 1413 | * This will unregister the rpi if needed. |
| @@ -1423,6 +1454,10 @@ lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 1423 | pcmd += sizeof(uint32_t); | 1454 | pcmd += sizeof(uint32_t); |
| 1424 | memcpy(pcmd, &vport->fc_portname, sizeof(struct lpfc_name)); | 1455 | memcpy(pcmd, &vport->fc_portname, sizeof(struct lpfc_name)); |
| 1425 | 1456 | ||
| 1457 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
| 1458 | "Issue LOGO: did:x%x", | ||
| 1459 | ndlp->nlp_DID, 0, 0); | ||
| 1460 | |||
| 1426 | phba->fc_stat.elsXmitLOGO++; | 1461 | phba->fc_stat.elsXmitLOGO++; |
| 1427 | elsiocb->iocb_cmpl = lpfc_cmpl_els_logo; | 1462 | elsiocb->iocb_cmpl = lpfc_cmpl_els_logo; |
| 1428 | spin_lock_irq(shost->host_lock); | 1463 | spin_lock_irq(shost->host_lock); |
| @@ -1449,6 +1484,11 @@ lpfc_cmpl_els_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 1449 | 1484 | ||
| 1450 | irsp = &rspiocb->iocb; | 1485 | irsp = &rspiocb->iocb; |
| 1451 | 1486 | ||
| 1487 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
| 1488 | "ELS cmd cmpl: status:x%x/x%x did:x%x", | ||
| 1489 | irsp->ulpStatus, irsp->un.ulpWord[4], | ||
| 1490 | irsp->un.elsreq64.remoteID); | ||
| 1491 | |||
| 1452 | /* ELS cmd tag <ulpIoTag> completes */ | 1492 | /* ELS cmd tag <ulpIoTag> completes */ |
| 1453 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | 1493 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, |
| 1454 | "%d (%d):0106 ELS cmd tag x%x completes Data: x%x x%x " | 1494 | "%d (%d):0106 ELS cmd tag x%x completes Data: x%x x%x " |
| @@ -1502,6 +1542,10 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) | |||
| 1502 | memset(pcmd, 0, sizeof(SCR)); | 1542 | memset(pcmd, 0, sizeof(SCR)); |
| 1503 | ((SCR *) pcmd)->Function = SCR_FUNC_FULL; | 1543 | ((SCR *) pcmd)->Function = SCR_FUNC_FULL; |
| 1504 | 1544 | ||
| 1545 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
| 1546 | "Issue SCR: did:x%x", | ||
| 1547 | ndlp->nlp_DID, 0, 0); | ||
| 1548 | |||
| 1505 | phba->fc_stat.elsXmitSCR++; | 1549 | phba->fc_stat.elsXmitSCR++; |
| 1506 | elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd; | 1550 | elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd; |
| 1507 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { | 1551 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { |
| @@ -1569,6 +1613,10 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) | |||
| 1569 | sizeof(struct lpfc_name)); | 1613 | sizeof(struct lpfc_name)); |
| 1570 | } | 1614 | } |
| 1571 | 1615 | ||
| 1616 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
| 1617 | "Issue FARPR: did:x%x", | ||
| 1618 | ndlp->nlp_DID, 0, 0); | ||
| 1619 | |||
| 1572 | phba->fc_stat.elsXmitFARPR++; | 1620 | phba->fc_stat.elsXmitFARPR++; |
| 1573 | elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd; | 1621 | elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd; |
| 1574 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { | 1622 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { |
| @@ -1763,6 +1811,10 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 1763 | return 1; | 1811 | return 1; |
| 1764 | } | 1812 | } |
| 1765 | 1813 | ||
| 1814 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
| 1815 | "Retry ELS: wd7:x%x wd4:x%x did:x%x", | ||
| 1816 | *(((uint32_t *) irsp) + 7), irsp->un.ulpWord[4], ndlp->nlp_DID); | ||
| 1817 | |||
| 1766 | switch (irsp->ulpStatus) { | 1818 | switch (irsp->ulpStatus) { |
| 1767 | case IOSTAT_FCP_RSP_ERROR: | 1819 | case IOSTAT_FCP_RSP_ERROR: |
| 1768 | case IOSTAT_REMOTE_STOP: | 1820 | case IOSTAT_REMOTE_STOP: |
| @@ -1776,10 +1828,6 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 1776 | retry = 1; | 1828 | retry = 1; |
| 1777 | break; | 1829 | break; |
| 1778 | 1830 | ||
| 1779 | case IOERR_SEQUENCE_TIMEOUT: | ||
| 1780 | retry = 1; | ||
| 1781 | break; | ||
| 1782 | |||
| 1783 | case IOERR_ILLEGAL_COMMAND: | 1831 | case IOERR_ILLEGAL_COMMAND: |
| 1784 | if ((phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) && | 1832 | if ((phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) && |
| 1785 | (cmd == ELS_CMD_FDISC)) { | 1833 | (cmd == ELS_CMD_FDISC)) { |
| @@ -1794,10 +1842,18 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 1794 | break; | 1842 | break; |
| 1795 | 1843 | ||
| 1796 | case IOERR_NO_RESOURCES: | 1844 | case IOERR_NO_RESOURCES: |
| 1845 | retry = 1; | ||
| 1846 | if (cmdiocb->retry > 100) | ||
| 1847 | delay = 100; | ||
| 1848 | maxretry = 250; | ||
| 1849 | break; | ||
| 1850 | |||
| 1851 | case IOERR_ILLEGAL_FRAME: | ||
| 1797 | delay = 100; | 1852 | delay = 100; |
| 1798 | retry = 1; | 1853 | retry = 1; |
| 1799 | break; | 1854 | break; |
| 1800 | 1855 | ||
| 1856 | case IOERR_SEQUENCE_TIMEOUT: | ||
| 1801 | case IOERR_INVALID_RPI: | 1857 | case IOERR_INVALID_RPI: |
| 1802 | retry = 1; | 1858 | retry = 1; |
| 1803 | break; | 1859 | break; |
| @@ -1852,7 +1908,8 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 1852 | break; | 1908 | break; |
| 1853 | 1909 | ||
| 1854 | case LSRJT_LOGICAL_BSY: | 1910 | case LSRJT_LOGICAL_BSY: |
| 1855 | if (cmd == ELS_CMD_PLOGI) { | 1911 | if ((cmd == ELS_CMD_PLOGI) || |
| 1912 | (cmd == ELS_CMD_PRLI)) { | ||
| 1856 | delay = 1000; | 1913 | delay = 1000; |
| 1857 | maxretry = 48; | 1914 | maxretry = 48; |
| 1858 | } else if (cmd == ELS_CMD_FDISC) { | 1915 | } else if (cmd == ELS_CMD_FDISC) { |
| @@ -1908,7 +1965,11 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 1908 | phba->brd_no, vport->vpi, | 1965 | phba->brd_no, vport->vpi, |
| 1909 | cmd, did, cmdiocb->retry, delay); | 1966 | cmd, did, cmdiocb->retry, delay); |
| 1910 | 1967 | ||
| 1911 | if ((cmd == ELS_CMD_PLOGI) || (cmd == ELS_CMD_ADISC)) { | 1968 | if (((cmd == ELS_CMD_PLOGI) || (cmd == ELS_CMD_ADISC)) && |
| 1969 | ((irsp->ulpStatus != IOSTAT_LOCAL_REJECT) || | ||
| 1970 | ((irsp->un.ulpWord[4] & 0xff) != IOERR_NO_RESOURCES))) { | ||
| 1971 | /* Don't reset timer for no resources */ | ||
| 1972 | |||
| 1912 | /* If discovery / RSCN timer is running, reset it */ | 1973 | /* If discovery / RSCN timer is running, reset it */ |
| 1913 | if (timer_pending(&vport->fc_disctmo) || | 1974 | if (timer_pending(&vport->fc_disctmo) || |
| 1914 | (vport->fc_flag & FC_RSCN_MODE)) | 1975 | (vport->fc_flag & FC_RSCN_MODE)) |
| @@ -1928,7 +1989,12 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 1928 | spin_unlock_irq(shost->host_lock); | 1989 | spin_unlock_irq(shost->host_lock); |
| 1929 | 1990 | ||
| 1930 | ndlp->nlp_prev_state = ndlp->nlp_state; | 1991 | ndlp->nlp_prev_state = ndlp->nlp_state; |
| 1931 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); | 1992 | if (cmd == ELS_CMD_PRLI) |
| 1993 | lpfc_nlp_set_state(vport, ndlp, | ||
| 1994 | NLP_STE_REG_LOGIN_ISSUE); | ||
| 1995 | else | ||
| 1996 | lpfc_nlp_set_state(vport, ndlp, | ||
| 1997 | NLP_STE_NPR_NODE); | ||
| 1932 | ndlp->nlp_last_elscmd = cmd; | 1998 | ndlp->nlp_last_elscmd = cmd; |
| 1933 | 1999 | ||
| 1934 | return 1; | 2000 | return 1; |
| @@ -2015,6 +2081,12 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 2015 | { | 2081 | { |
| 2016 | struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1; | 2082 | struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1; |
| 2017 | struct lpfc_vport *vport = cmdiocb->vport; | 2083 | struct lpfc_vport *vport = cmdiocb->vport; |
| 2084 | IOCB_t *irsp; | ||
| 2085 | |||
| 2086 | irsp = &rspiocb->iocb; | ||
| 2087 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, | ||
| 2088 | "ACC LOGO cmpl: status:x%x/x%x did:x%x", | ||
| 2089 | irsp->ulpStatus, irsp->un.ulpWord[4], ndlp->nlp_DID); | ||
| 2018 | 2090 | ||
| 2019 | /* ACC to LOGO completes to NPort <nlp_DID> */ | 2091 | /* ACC to LOGO completes to NPort <nlp_DID> */ |
| 2020 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | 2092 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, |
| @@ -2037,8 +2109,22 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 2037 | return; | 2109 | return; |
| 2038 | } | 2110 | } |
| 2039 | 2111 | ||
| 2112 | void | ||
| 2113 | lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | ||
| 2114 | { | ||
| 2115 | struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1); | ||
| 2116 | struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2; | ||
| 2117 | |||
| 2118 | pmb->context1 = NULL; | ||
| 2119 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | ||
| 2120 | kfree(mp); | ||
| 2121 | mempool_free(pmb, phba->mbox_mem_pool); | ||
| 2122 | lpfc_nlp_put(ndlp); | ||
| 2123 | return; | ||
| 2124 | } | ||
| 2125 | |||
| 2040 | static void | 2126 | static void |
| 2041 | lpfc_cmpl_els_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | 2127 | lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, |
| 2042 | struct lpfc_iocbq *rspiocb) | 2128 | struct lpfc_iocbq *rspiocb) |
| 2043 | { | 2129 | { |
| 2044 | struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1; | 2130 | struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1; |
| @@ -2066,6 +2152,11 @@ lpfc_cmpl_els_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 2066 | goto out; | 2152 | goto out; |
| 2067 | } | 2153 | } |
| 2068 | 2154 | ||
| 2155 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, | ||
| 2156 | "ACC cmpl: status:x%x/x%x did:x%x", | ||
| 2157 | irsp->ulpStatus, irsp->un.ulpWord[4], | ||
| 2158 | irsp->un.rcvels.remoteID); | ||
| 2159 | |||
| 2069 | /* ELS response tag <ulpIoTag> completes */ | 2160 | /* ELS response tag <ulpIoTag> completes */ |
| 2070 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | 2161 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, |
| 2071 | "%d (%d):0110 ELS response tag x%x completes " | 2162 | "%d (%d):0110 ELS response tag x%x completes " |
| @@ -2080,12 +2171,18 @@ lpfc_cmpl_els_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 2080 | if ((rspiocb->iocb.ulpStatus == 0) | 2171 | if ((rspiocb->iocb.ulpStatus == 0) |
| 2081 | && (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) { | 2172 | && (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) { |
| 2082 | lpfc_unreg_rpi(vport, ndlp); | 2173 | lpfc_unreg_rpi(vport, ndlp); |
| 2083 | mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login; | ||
| 2084 | mbox->context2 = lpfc_nlp_get(ndlp); | 2174 | mbox->context2 = lpfc_nlp_get(ndlp); |
| 2085 | mbox->vport = vport; | 2175 | mbox->vport = vport; |
| 2086 | ndlp->nlp_prev_state = ndlp->nlp_state; | 2176 | if (ndlp->nlp_flag & NLP_RM_DFLT_RPI) { |
| 2087 | lpfc_nlp_set_state(vport, ndlp, | 2177 | mbox->mbox_flag |= LPFC_MBX_IMED_UNREG; |
| 2178 | mbox->mbox_cmpl = lpfc_mbx_cmpl_dflt_rpi; | ||
| 2179 | } | ||
| 2180 | else { | ||
| 2181 | mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login; | ||
| 2182 | ndlp->nlp_prev_state = ndlp->nlp_state; | ||
| 2183 | lpfc_nlp_set_state(vport, ndlp, | ||
| 2088 | NLP_STE_REG_LOGIN_ISSUE); | 2184 | NLP_STE_REG_LOGIN_ISSUE); |
| 2185 | } | ||
| 2089 | if (lpfc_sli_issue_mbox(phba, mbox, | 2186 | if (lpfc_sli_issue_mbox(phba, mbox, |
| 2090 | (MBX_NOWAIT | MBX_STOP_IOCB)) | 2187 | (MBX_NOWAIT | MBX_STOP_IOCB)) |
| 2091 | != MBX_NOT_FINISHED) { | 2188 | != MBX_NOT_FINISHED) { |
| @@ -2095,15 +2192,11 @@ lpfc_cmpl_els_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 2095 | /* NOTE: we should have messages for unsuccessful | 2192 | /* NOTE: we should have messages for unsuccessful |
| 2096 | reglogin */ | 2193 | reglogin */ |
| 2097 | } else { | 2194 | } else { |
| 2098 | /* Do not call NO_LIST for lpfc_els_abort'ed ELS cmds */ | 2195 | /* Do not drop node for lpfc_els_abort'ed ELS cmds */ |
| 2099 | if (!((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) && | 2196 | if (!lpfc_error_lost_link(irsp) && |
| 2100 | ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) || | 2197 | ndlp->nlp_flag & NLP_ACC_REGLOGIN) { |
| 2101 | (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) || | 2198 | lpfc_drop_node(vport, ndlp); |
| 2102 | (irsp->un.ulpWord[4] == IOERR_SLI_DOWN)))) { | 2199 | ndlp = NULL; |
| 2103 | if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) { | ||
| 2104 | lpfc_drop_node(vport, ndlp); | ||
| 2105 | ndlp = NULL; | ||
| 2106 | } | ||
| 2107 | } | 2200 | } |
| 2108 | } | 2201 | } |
| 2109 | mp = (struct lpfc_dmabuf *) mbox->context1; | 2202 | mp = (struct lpfc_dmabuf *) mbox->context1; |
| @@ -2116,7 +2209,7 @@ lpfc_cmpl_els_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 2116 | out: | 2209 | out: |
| 2117 | if (ndlp) { | 2210 | if (ndlp) { |
| 2118 | spin_lock_irq(shost->host_lock); | 2211 | spin_lock_irq(shost->host_lock); |
| 2119 | ndlp->nlp_flag &= ~NLP_ACC_REGLOGIN; | 2212 | ndlp->nlp_flag &= ~(NLP_ACC_REGLOGIN | NLP_RM_DFLT_RPI); |
| 2120 | spin_unlock_irq(shost->host_lock); | 2213 | spin_unlock_irq(shost->host_lock); |
| 2121 | } | 2214 | } |
| 2122 | lpfc_els_free_iocb(phba, cmdiocb); | 2215 | lpfc_els_free_iocb(phba, cmdiocb); |
| @@ -2161,6 +2254,10 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, | |||
| 2161 | pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt); | 2254 | pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt); |
| 2162 | *((uint32_t *) (pcmd)) = ELS_CMD_ACC; | 2255 | *((uint32_t *) (pcmd)) = ELS_CMD_ACC; |
| 2163 | pcmd += sizeof(uint32_t); | 2256 | pcmd += sizeof(uint32_t); |
| 2257 | |||
| 2258 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, | ||
| 2259 | "Issue ACC: did:x%x flg:x%x", | ||
| 2260 | ndlp->nlp_DID, ndlp->nlp_flag, 0); | ||
| 2164 | break; | 2261 | break; |
| 2165 | case ELS_CMD_PLOGI: | 2262 | case ELS_CMD_PLOGI: |
| 2166 | cmdsize = (sizeof(struct serv_parm) + sizeof(uint32_t)); | 2263 | cmdsize = (sizeof(struct serv_parm) + sizeof(uint32_t)); |
| @@ -2179,6 +2276,10 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, | |||
| 2179 | *((uint32_t *) (pcmd)) = ELS_CMD_ACC; | 2276 | *((uint32_t *) (pcmd)) = ELS_CMD_ACC; |
| 2180 | pcmd += sizeof(uint32_t); | 2277 | pcmd += sizeof(uint32_t); |
| 2181 | memcpy(pcmd, &vport->fc_sparam, sizeof(struct serv_parm)); | 2278 | memcpy(pcmd, &vport->fc_sparam, sizeof(struct serv_parm)); |
| 2279 | |||
| 2280 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, | ||
| 2281 | "Issue ACC PLOGI: did:x%x flg:x%x", | ||
| 2282 | ndlp->nlp_DID, ndlp->nlp_flag, 0); | ||
| 2182 | break; | 2283 | break; |
| 2183 | case ELS_CMD_PRLO: | 2284 | case ELS_CMD_PRLO: |
| 2184 | cmdsize = sizeof(uint32_t) + sizeof(PRLO); | 2285 | cmdsize = sizeof(uint32_t) + sizeof(PRLO); |
| @@ -2196,6 +2297,10 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, | |||
| 2196 | *((uint32_t *) (pcmd)) = ELS_CMD_PRLO_ACC; | 2297 | *((uint32_t *) (pcmd)) = ELS_CMD_PRLO_ACC; |
| 2197 | els_pkt_ptr = (ELS_PKT *) pcmd; | 2298 | els_pkt_ptr = (ELS_PKT *) pcmd; |
| 2198 | els_pkt_ptr->un.prlo.acceptRspCode = PRLO_REQ_EXECUTED; | 2299 | els_pkt_ptr->un.prlo.acceptRspCode = PRLO_REQ_EXECUTED; |
| 2300 | |||
| 2301 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, | ||
| 2302 | "Issue ACC PRLO: did:x%x flg:x%x", | ||
| 2303 | ndlp->nlp_DID, ndlp->nlp_flag, 0); | ||
| 2199 | break; | 2304 | break; |
| 2200 | default: | 2305 | default: |
| 2201 | return 1; | 2306 | return 1; |
| @@ -2220,7 +2325,7 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, | |||
| 2220 | spin_unlock_irq(shost->host_lock); | 2325 | spin_unlock_irq(shost->host_lock); |
| 2221 | elsiocb->iocb_cmpl = lpfc_cmpl_els_logo_acc; | 2326 | elsiocb->iocb_cmpl = lpfc_cmpl_els_logo_acc; |
| 2222 | } else { | 2327 | } else { |
| 2223 | elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; | 2328 | elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; |
| 2224 | } | 2329 | } |
| 2225 | 2330 | ||
| 2226 | phba->fc_stat.elsXmitACC++; | 2331 | phba->fc_stat.elsXmitACC++; |
| @@ -2234,7 +2339,8 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, | |||
| 2234 | 2339 | ||
| 2235 | int | 2340 | int |
| 2236 | lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError, | 2341 | lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError, |
| 2237 | struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp) | 2342 | struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp, |
| 2343 | LPFC_MBOXQ_t *mbox) | ||
| 2238 | { | 2344 | { |
| 2239 | struct lpfc_hba *phba = vport->phba; | 2345 | struct lpfc_hba *phba = vport->phba; |
| 2240 | IOCB_t *icmd; | 2346 | IOCB_t *icmd; |
| @@ -2264,6 +2370,11 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError, | |||
| 2264 | pcmd += sizeof(uint32_t); | 2370 | pcmd += sizeof(uint32_t); |
| 2265 | *((uint32_t *) (pcmd)) = rejectError; | 2371 | *((uint32_t *) (pcmd)) = rejectError; |
| 2266 | 2372 | ||
| 2373 | if (mbox) { | ||
| 2374 | elsiocb->context_un.mbox = mbox; | ||
| 2375 | elsiocb->context1 = lpfc_nlp_get(ndlp); | ||
| 2376 | } | ||
| 2377 | |||
| 2267 | /* Xmit ELS RJT <err> response tag <ulpIoTag> */ | 2378 | /* Xmit ELS RJT <err> response tag <ulpIoTag> */ |
| 2268 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | 2379 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, |
| 2269 | "%d (%d):0129 Xmit ELS RJT x%x response tag x%x " | 2380 | "%d (%d):0129 Xmit ELS RJT x%x response tag x%x " |
| @@ -2273,8 +2384,12 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError, | |||
| 2273 | elsiocb->iocb.ulpContext, ndlp->nlp_DID, | 2384 | elsiocb->iocb.ulpContext, ndlp->nlp_DID, |
| 2274 | ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); | 2385 | ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); |
| 2275 | 2386 | ||
| 2387 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, | ||
| 2388 | "Issue LS_RJT: did:x%x flg:x%x err:x%x", | ||
| 2389 | ndlp->nlp_DID, ndlp->nlp_flag, rejectError); | ||
| 2390 | |||
| 2276 | phba->fc_stat.elsXmitLSRJT++; | 2391 | phba->fc_stat.elsXmitLSRJT++; |
| 2277 | elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; | 2392 | elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; |
| 2278 | rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0); | 2393 | rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0); |
| 2279 | if (rc == IOCB_ERROR) { | 2394 | if (rc == IOCB_ERROR) { |
| 2280 | lpfc_els_free_iocb(phba, elsiocb); | 2395 | lpfc_els_free_iocb(phba, elsiocb); |
| @@ -2326,8 +2441,12 @@ lpfc_els_rsp_adisc_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb, | |||
| 2326 | memcpy(&ap->nodeName, &vport->fc_nodename, sizeof(struct lpfc_name)); | 2441 | memcpy(&ap->nodeName, &vport->fc_nodename, sizeof(struct lpfc_name)); |
| 2327 | ap->DID = be32_to_cpu(vport->fc_myDID); | 2442 | ap->DID = be32_to_cpu(vport->fc_myDID); |
| 2328 | 2443 | ||
| 2444 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, | ||
| 2445 | "Issue ACC ADISC: did:x%x flg:x%x", | ||
| 2446 | ndlp->nlp_DID, ndlp->nlp_flag, 0); | ||
| 2447 | |||
| 2329 | phba->fc_stat.elsXmitACC++; | 2448 | phba->fc_stat.elsXmitACC++; |
| 2330 | elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; | 2449 | elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; |
| 2331 | rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0); | 2450 | rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0); |
| 2332 | if (rc == IOCB_ERROR) { | 2451 | if (rc == IOCB_ERROR) { |
| 2333 | lpfc_els_free_iocb(phba, elsiocb); | 2452 | lpfc_els_free_iocb(phba, elsiocb); |
| @@ -2401,8 +2520,12 @@ lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb, | |||
| 2401 | npr->prliType = PRLI_FCP_TYPE; | 2520 | npr->prliType = PRLI_FCP_TYPE; |
| 2402 | npr->initiatorFunc = 1; | 2521 | npr->initiatorFunc = 1; |
| 2403 | 2522 | ||
| 2523 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, | ||
| 2524 | "Issue ACC PRLI: did:x%x flg:x%x", | ||
| 2525 | ndlp->nlp_DID, ndlp->nlp_flag, 0); | ||
| 2526 | |||
| 2404 | phba->fc_stat.elsXmitACC++; | 2527 | phba->fc_stat.elsXmitACC++; |
| 2405 | elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; | 2528 | elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; |
| 2406 | 2529 | ||
| 2407 | rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0); | 2530 | rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0); |
| 2408 | if (rc == IOCB_ERROR) { | 2531 | if (rc == IOCB_ERROR) { |
| @@ -2479,8 +2602,12 @@ lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format, | |||
| 2479 | break; | 2602 | break; |
| 2480 | } | 2603 | } |
| 2481 | 2604 | ||
| 2605 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, | ||
| 2606 | "Issue ACC RNID: did:x%x flg:x%x", | ||
| 2607 | ndlp->nlp_DID, ndlp->nlp_flag, 0); | ||
| 2608 | |||
| 2482 | phba->fc_stat.elsXmitACC++; | 2609 | phba->fc_stat.elsXmitACC++; |
| 2483 | elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; | 2610 | elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; |
| 2484 | lpfc_nlp_put(ndlp); | 2611 | lpfc_nlp_put(ndlp); |
| 2485 | elsiocb->context1 = NULL; /* Don't need ndlp for cmpl, | 2612 | elsiocb->context1 = NULL; /* Don't need ndlp for cmpl, |
| 2486 | * it could be freed */ | 2613 | * it could be freed */ |
| @@ -2703,6 +2830,10 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
| 2703 | * Discovery processing will satisfy it. | 2830 | * Discovery processing will satisfy it. |
| 2704 | */ | 2831 | */ |
| 2705 | if (vport->port_state <= LPFC_NS_QRY) { | 2832 | if (vport->port_state <= LPFC_NS_QRY) { |
| 2833 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | ||
| 2834 | "RCV RSCN ignore: did:x%x/ste:x%x flg:x%x", | ||
| 2835 | ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag); | ||
| 2836 | |||
| 2706 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, | 2837 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, |
| 2707 | newnode); | 2838 | newnode); |
| 2708 | return 0; | 2839 | return 0; |
| @@ -2734,6 +2865,12 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
| 2734 | "%d (%d):0214 Ignore RSCN Data: x%x x%x x%x x%x\n", | 2865 | "%d (%d):0214 Ignore RSCN Data: x%x x%x x%x x%x\n", |
| 2735 | phba->brd_no, vport->vpi, vport->fc_flag, payload_len, | 2866 | phba->brd_no, vport->vpi, vport->fc_flag, payload_len, |
| 2736 | *lp, rscn_cnt); | 2867 | *lp, rscn_cnt); |
| 2868 | |||
| 2869 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | ||
| 2870 | "RCV RSCN vport: did:x%x/ste:x%x flg:x%x", | ||
| 2871 | ndlp->nlp_DID, vport->port_state, | ||
| 2872 | ndlp->nlp_flag); | ||
| 2873 | |||
| 2737 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, | 2874 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, |
| 2738 | ndlp, NULL, newnode); | 2875 | ndlp, NULL, newnode); |
| 2739 | return 0; | 2876 | return 0; |
| @@ -2744,6 +2881,10 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
| 2744 | * RSCN payload buffer, cmdiocb->context2 to process later. | 2881 | * RSCN payload buffer, cmdiocb->context2 to process later. |
| 2745 | */ | 2882 | */ |
| 2746 | if (vport->fc_flag & (FC_RSCN_MODE | FC_NDISC_ACTIVE)) { | 2883 | if (vport->fc_flag & (FC_RSCN_MODE | FC_NDISC_ACTIVE)) { |
| 2884 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | ||
| 2885 | "RCV RSCN defer: did:x%x/ste:x%x flg:x%x", | ||
| 2886 | ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag); | ||
| 2887 | |||
| 2747 | vport->fc_flag |= FC_RSCN_DEFERRED; | 2888 | vport->fc_flag |= FC_RSCN_DEFERRED; |
| 2748 | if ((rscn_cnt < FC_MAX_HOLD_RSCN) && | 2889 | if ((rscn_cnt < FC_MAX_HOLD_RSCN) && |
| 2749 | !(vport->fc_flag & FC_RSCN_DISCOVERY)) { | 2890 | !(vport->fc_flag & FC_RSCN_DISCOVERY)) { |
| @@ -2798,6 +2939,10 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
| 2798 | return 0; | 2939 | return 0; |
| 2799 | } | 2940 | } |
| 2800 | 2941 | ||
| 2942 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | ||
| 2943 | "RCV RSCN: did:x%x/ste:x%x flg:x%x", | ||
| 2944 | ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag); | ||
| 2945 | |||
| 2801 | spin_lock_irq(shost->host_lock); | 2946 | spin_lock_irq(shost->host_lock); |
| 2802 | vport->fc_flag |= FC_RSCN_MODE; | 2947 | vport->fc_flag |= FC_RSCN_MODE; |
| 2803 | spin_unlock_irq(shost->host_lock); | 2948 | spin_unlock_irq(shost->host_lock); |
| @@ -2958,7 +3103,8 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
| 2958 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | 3103 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; |
| 2959 | stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS; | 3104 | stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS; |
| 2960 | stat.un.b.vendorUnique = 0; | 3105 | stat.un.b.vendorUnique = 0; |
| 2961 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp); | 3106 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, |
| 3107 | NULL); | ||
| 2962 | return 1; | 3108 | return 1; |
| 2963 | } | 3109 | } |
| 2964 | 3110 | ||
| @@ -3001,7 +3147,8 @@ lpfc_els_rcv_rnid(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
| 3001 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | 3147 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; |
| 3002 | stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; | 3148 | stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; |
| 3003 | stat.un.b.vendorUnique = 0; | 3149 | stat.un.b.vendorUnique = 0; |
| 3004 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp); | 3150 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, |
| 3151 | NULL); | ||
| 3005 | } | 3152 | } |
| 3006 | return 0; | 3153 | return 0; |
| 3007 | } | 3154 | } |
| @@ -3017,7 +3164,7 @@ lpfc_els_rcv_lirr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
| 3017 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | 3164 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; |
| 3018 | stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; | 3165 | stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; |
| 3019 | stat.un.b.vendorUnique = 0; | 3166 | stat.un.b.vendorUnique = 0; |
| 3020 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp); | 3167 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL); |
| 3021 | return 0; | 3168 | return 0; |
| 3022 | } | 3169 | } |
| 3023 | 3170 | ||
| @@ -3089,7 +3236,7 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
| 3089 | elsiocb->iocb.ulpContext, ndlp->nlp_DID, | 3236 | elsiocb->iocb.ulpContext, ndlp->nlp_DID, |
| 3090 | ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); | 3237 | ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); |
| 3091 | 3238 | ||
| 3092 | elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; | 3239 | elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; |
| 3093 | phba->fc_stat.elsXmitACC++; | 3240 | phba->fc_stat.elsXmitACC++; |
| 3094 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) | 3241 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) |
| 3095 | lpfc_els_free_iocb(phba, elsiocb); | 3242 | lpfc_els_free_iocb(phba, elsiocb); |
| @@ -3114,7 +3261,8 @@ lpfc_els_rcv_rps(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
| 3114 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | 3261 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; |
| 3115 | stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; | 3262 | stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; |
| 3116 | stat.un.b.vendorUnique = 0; | 3263 | stat.un.b.vendorUnique = 0; |
| 3117 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp); | 3264 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, |
| 3265 | NULL); | ||
| 3118 | } | 3266 | } |
| 3119 | 3267 | ||
| 3120 | pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; | 3268 | pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; |
| @@ -3150,7 +3298,7 @@ lpfc_els_rcv_rps(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
| 3150 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | 3298 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; |
| 3151 | stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; | 3299 | stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; |
| 3152 | stat.un.b.vendorUnique = 0; | 3300 | stat.un.b.vendorUnique = 0; |
| 3153 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp); | 3301 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL); |
| 3154 | return 0; | 3302 | return 0; |
| 3155 | } | 3303 | } |
| 3156 | 3304 | ||
| @@ -3202,7 +3350,7 @@ lpfc_els_rsp_rpl_acc(struct lpfc_vport *vport, uint16_t cmdsize, | |||
| 3202 | elsiocb->iocb.ulpContext, ndlp->nlp_DID, | 3350 | elsiocb->iocb.ulpContext, ndlp->nlp_DID, |
| 3203 | ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); | 3351 | ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); |
| 3204 | 3352 | ||
| 3205 | elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; | 3353 | elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; |
| 3206 | 3354 | ||
| 3207 | phba->fc_stat.elsXmitACC++; | 3355 | phba->fc_stat.elsXmitACC++; |
| 3208 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { | 3356 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { |
| @@ -3229,7 +3377,8 @@ lpfc_els_rcv_rpl(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
| 3229 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | 3377 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; |
| 3230 | stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; | 3378 | stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; |
| 3231 | stat.un.b.vendorUnique = 0; | 3379 | stat.un.b.vendorUnique = 0; |
| 3232 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp); | 3380 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, |
| 3381 | NULL); | ||
| 3233 | } | 3382 | } |
| 3234 | 3383 | ||
| 3235 | pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; | 3384 | pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; |
| @@ -3538,9 +3687,6 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport) | |||
| 3538 | struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; | 3687 | struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; |
| 3539 | struct lpfc_iocbq *tmp_iocb, *piocb; | 3688 | struct lpfc_iocbq *tmp_iocb, *piocb; |
| 3540 | IOCB_t *cmd = NULL; | 3689 | IOCB_t *cmd = NULL; |
| 3541 | struct lpfc_dmabuf *pcmd; | ||
| 3542 | uint32_t *elscmd; | ||
| 3543 | uint32_t els_command; | ||
| 3544 | 3690 | ||
| 3545 | lpfc_fabric_abort_vport(vport); | 3691 | lpfc_fabric_abort_vport(vport); |
| 3546 | 3692 | ||
| @@ -3559,10 +3705,6 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport) | |||
| 3559 | cmd->ulpCommand == CMD_ABORT_XRI_CN) | 3705 | cmd->ulpCommand == CMD_ABORT_XRI_CN) |
| 3560 | continue; | 3706 | continue; |
| 3561 | 3707 | ||
| 3562 | pcmd = (struct lpfc_dmabuf *) piocb->context2; | ||
| 3563 | elscmd = (uint32_t *) (pcmd->virt); | ||
| 3564 | els_command = *elscmd; | ||
| 3565 | |||
| 3566 | if (piocb->vport != vport) | 3708 | if (piocb->vport != vport) |
| 3567 | continue; | 3709 | continue; |
| 3568 | 3710 | ||
| @@ -3618,8 +3760,13 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
| 3618 | if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) == 0) | 3760 | if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) == 0) |
| 3619 | lpfc_post_buffer(phba, pring, 1, 1); | 3761 | lpfc_post_buffer(phba, pring, 1, 1); |
| 3620 | 3762 | ||
| 3621 | if (icmd->ulpStatus) | 3763 | did = icmd->un.rcvels.remoteID; |
| 3764 | if (icmd->ulpStatus) { | ||
| 3765 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | ||
| 3766 | "RCV Unsol ELS: status:x%x/x%x did:x%x", | ||
| 3767 | icmd->ulpStatus, icmd->un.ulpWord[4], did); | ||
| 3622 | goto dropit; | 3768 | goto dropit; |
| 3769 | } | ||
| 3623 | 3770 | ||
| 3624 | /* Check to see if link went down during discovery */ | 3771 | /* Check to see if link went down during discovery */ |
| 3625 | if (lpfc_els_chk_latt(vport)) | 3772 | if (lpfc_els_chk_latt(vport)) |
| @@ -3629,7 +3776,6 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
| 3629 | if (vport->load_flag & FC_UNLOADING) | 3776 | if (vport->load_flag & FC_UNLOADING) |
| 3630 | goto dropit; | 3777 | goto dropit; |
| 3631 | 3778 | ||
| 3632 | did = icmd->un.rcvels.remoteID; | ||
| 3633 | ndlp = lpfc_findnode_did(vport, did); | 3779 | ndlp = lpfc_findnode_did(vport, did); |
| 3634 | if (!ndlp) { | 3780 | if (!ndlp) { |
| 3635 | /* Cannot find existing Fabric ndlp, so allocate a new one */ | 3781 | /* Cannot find existing Fabric ndlp, so allocate a new one */ |
| @@ -3662,35 +3808,51 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
| 3662 | 3808 | ||
| 3663 | switch (cmd) { | 3809 | switch (cmd) { |
| 3664 | case ELS_CMD_PLOGI: | 3810 | case ELS_CMD_PLOGI: |
| 3811 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | ||
| 3812 | "RCV PLOGI: did:x%x/ste:x%x flg:x%x", | ||
| 3813 | did, vport->port_state, ndlp->nlp_flag); | ||
| 3814 | |||
| 3665 | phba->fc_stat.elsRcvPLOGI++; | 3815 | phba->fc_stat.elsRcvPLOGI++; |
| 3666 | if ((vport->port_state < LPFC_DISC_AUTH) || | 3816 | ndlp = lpfc_plogi_confirm_nport(phba, payload, ndlp); |
| 3667 | ((vport->port_type == LPFC_NPIV_PORT && | 3817 | |
| 3668 | phba->cfg_vport_restrict_login))) { | 3818 | if (vport->port_state < LPFC_DISC_AUTH) { |
| 3669 | rjt_err = 2; | 3819 | rjt_err = LSRJT_UNABLE_TPC; |
| 3670 | break; | 3820 | break; |
| 3671 | } | 3821 | } |
| 3672 | ndlp = lpfc_plogi_confirm_nport(phba, payload, ndlp); | ||
| 3673 | lpfc_disc_state_machine(vport, ndlp, elsiocb, | 3822 | lpfc_disc_state_machine(vport, ndlp, elsiocb, |
| 3674 | NLP_EVT_RCV_PLOGI); | 3823 | NLP_EVT_RCV_PLOGI); |
| 3824 | |||
| 3675 | break; | 3825 | break; |
| 3676 | case ELS_CMD_FLOGI: | 3826 | case ELS_CMD_FLOGI: |
| 3827 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | ||
| 3828 | "RCV FLOGI: did:x%x/ste:x%x flg:x%x", | ||
| 3829 | did, vport->port_state, ndlp->nlp_flag); | ||
| 3830 | |||
| 3677 | phba->fc_stat.elsRcvFLOGI++; | 3831 | phba->fc_stat.elsRcvFLOGI++; |
| 3678 | lpfc_els_rcv_flogi(vport, elsiocb, ndlp, newnode); | 3832 | lpfc_els_rcv_flogi(vport, elsiocb, ndlp, newnode); |
| 3679 | if (newnode) | 3833 | if (newnode) |
| 3680 | lpfc_drop_node(vport, ndlp); | 3834 | lpfc_drop_node(vport, ndlp); |
| 3681 | break; | 3835 | break; |
| 3682 | case ELS_CMD_LOGO: | 3836 | case ELS_CMD_LOGO: |
| 3837 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | ||
| 3838 | "RCV LOGO: did:x%x/ste:x%x flg:x%x", | ||
| 3839 | did, vport->port_state, ndlp->nlp_flag); | ||
| 3840 | |||
| 3683 | phba->fc_stat.elsRcvLOGO++; | 3841 | phba->fc_stat.elsRcvLOGO++; |
| 3684 | if (vport->port_state < LPFC_DISC_AUTH) { | 3842 | if (vport->port_state < LPFC_DISC_AUTH) { |
| 3685 | rjt_err = 1; | 3843 | rjt_err = LSRJT_UNABLE_TPC; |
| 3686 | break; | 3844 | break; |
| 3687 | } | 3845 | } |
| 3688 | lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_LOGO); | 3846 | lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_LOGO); |
| 3689 | break; | 3847 | break; |
| 3690 | case ELS_CMD_PRLO: | 3848 | case ELS_CMD_PRLO: |
| 3849 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | ||
| 3850 | "RCV PRLO: did:x%x/ste:x%x flg:x%x", | ||
| 3851 | did, vport->port_state, ndlp->nlp_flag); | ||
| 3852 | |||
| 3691 | phba->fc_stat.elsRcvPRLO++; | 3853 | phba->fc_stat.elsRcvPRLO++; |
| 3692 | if (vport->port_state < LPFC_DISC_AUTH) { | 3854 | if (vport->port_state < LPFC_DISC_AUTH) { |
| 3693 | rjt_err = 1; | 3855 | rjt_err = LSRJT_UNABLE_TPC; |
| 3694 | break; | 3856 | break; |
| 3695 | } | 3857 | } |
| 3696 | lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_PRLO); | 3858 | lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_PRLO); |
| @@ -3702,70 +3864,114 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
| 3702 | lpfc_drop_node(vport, ndlp); | 3864 | lpfc_drop_node(vport, ndlp); |
| 3703 | break; | 3865 | break; |
| 3704 | case ELS_CMD_ADISC: | 3866 | case ELS_CMD_ADISC: |
| 3867 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | ||
| 3868 | "RCV ADISC: did:x%x/ste:x%x flg:x%x", | ||
| 3869 | did, vport->port_state, ndlp->nlp_flag); | ||
| 3870 | |||
| 3705 | phba->fc_stat.elsRcvADISC++; | 3871 | phba->fc_stat.elsRcvADISC++; |
| 3706 | if (vport->port_state < LPFC_DISC_AUTH) { | 3872 | if (vport->port_state < LPFC_DISC_AUTH) { |
| 3707 | rjt_err = 1; | 3873 | rjt_err = LSRJT_UNABLE_TPC; |
| 3708 | break; | 3874 | break; |
| 3709 | } | 3875 | } |
| 3710 | lpfc_disc_state_machine(vport, ndlp, elsiocb, | 3876 | lpfc_disc_state_machine(vport, ndlp, elsiocb, |
| 3711 | NLP_EVT_RCV_ADISC); | 3877 | NLP_EVT_RCV_ADISC); |
| 3712 | break; | 3878 | break; |
| 3713 | case ELS_CMD_PDISC: | 3879 | case ELS_CMD_PDISC: |
| 3880 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | ||
| 3881 | "RCV PDISC: did:x%x/ste:x%x flg:x%x", | ||
| 3882 | did, vport->port_state, ndlp->nlp_flag); | ||
| 3883 | |||
| 3714 | phba->fc_stat.elsRcvPDISC++; | 3884 | phba->fc_stat.elsRcvPDISC++; |
| 3715 | if (vport->port_state < LPFC_DISC_AUTH) { | 3885 | if (vport->port_state < LPFC_DISC_AUTH) { |
| 3716 | rjt_err = 1; | 3886 | rjt_err = LSRJT_UNABLE_TPC; |
| 3717 | break; | 3887 | break; |
| 3718 | } | 3888 | } |
| 3719 | lpfc_disc_state_machine(vport, ndlp, elsiocb, | 3889 | lpfc_disc_state_machine(vport, ndlp, elsiocb, |
| 3720 | NLP_EVT_RCV_PDISC); | 3890 | NLP_EVT_RCV_PDISC); |
| 3721 | break; | 3891 | break; |
| 3722 | case ELS_CMD_FARPR: | 3892 | case ELS_CMD_FARPR: |
| 3893 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | ||
| 3894 | "RCV FARPR: did:x%x/ste:x%x flg:x%x", | ||
| 3895 | did, vport->port_state, ndlp->nlp_flag); | ||
| 3896 | |||
| 3723 | phba->fc_stat.elsRcvFARPR++; | 3897 | phba->fc_stat.elsRcvFARPR++; |
| 3724 | lpfc_els_rcv_farpr(vport, elsiocb, ndlp); | 3898 | lpfc_els_rcv_farpr(vport, elsiocb, ndlp); |
| 3725 | break; | 3899 | break; |
| 3726 | case ELS_CMD_FARP: | 3900 | case ELS_CMD_FARP: |
| 3901 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | ||
| 3902 | "RCV FARP: did:x%x/ste:x%x flg:x%x", | ||
| 3903 | did, vport->port_state, ndlp->nlp_flag); | ||
| 3904 | |||
| 3727 | phba->fc_stat.elsRcvFARP++; | 3905 | phba->fc_stat.elsRcvFARP++; |
| 3728 | lpfc_els_rcv_farp(vport, elsiocb, ndlp); | 3906 | lpfc_els_rcv_farp(vport, elsiocb, ndlp); |
| 3729 | break; | 3907 | break; |
| 3730 | case ELS_CMD_FAN: | 3908 | case ELS_CMD_FAN: |
| 3909 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | ||
| 3910 | "RCV FAN: did:x%x/ste:x%x flg:x%x", | ||
| 3911 | did, vport->port_state, ndlp->nlp_flag); | ||
| 3912 | |||
| 3731 | phba->fc_stat.elsRcvFAN++; | 3913 | phba->fc_stat.elsRcvFAN++; |
| 3732 | lpfc_els_rcv_fan(vport, elsiocb, ndlp); | 3914 | lpfc_els_rcv_fan(vport, elsiocb, ndlp); |
| 3733 | break; | 3915 | break; |
| 3734 | case ELS_CMD_PRLI: | 3916 | case ELS_CMD_PRLI: |
| 3917 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | ||
| 3918 | "RCV PRLI: did:x%x/ste:x%x flg:x%x", | ||
| 3919 | did, vport->port_state, ndlp->nlp_flag); | ||
| 3920 | |||
| 3735 | phba->fc_stat.elsRcvPRLI++; | 3921 | phba->fc_stat.elsRcvPRLI++; |
| 3736 | if (vport->port_state < LPFC_DISC_AUTH) { | 3922 | if (vport->port_state < LPFC_DISC_AUTH) { |
| 3737 | rjt_err = 1; | 3923 | rjt_err = LSRJT_UNABLE_TPC; |
| 3738 | break; | 3924 | break; |
| 3739 | } | 3925 | } |
| 3740 | lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_PRLI); | 3926 | lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_PRLI); |
| 3741 | break; | 3927 | break; |
| 3742 | case ELS_CMD_LIRR: | 3928 | case ELS_CMD_LIRR: |
| 3929 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | ||
| 3930 | "RCV LIRR: did:x%x/ste:x%x flg:x%x", | ||
| 3931 | did, vport->port_state, ndlp->nlp_flag); | ||
| 3932 | |||
| 3743 | phba->fc_stat.elsRcvLIRR++; | 3933 | phba->fc_stat.elsRcvLIRR++; |
| 3744 | lpfc_els_rcv_lirr(vport, elsiocb, ndlp); | 3934 | lpfc_els_rcv_lirr(vport, elsiocb, ndlp); |
| 3745 | if (newnode) | 3935 | if (newnode) |
| 3746 | lpfc_drop_node(vport, ndlp); | 3936 | lpfc_drop_node(vport, ndlp); |
| 3747 | break; | 3937 | break; |
| 3748 | case ELS_CMD_RPS: | 3938 | case ELS_CMD_RPS: |
| 3939 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | ||
| 3940 | "RCV RPS: did:x%x/ste:x%x flg:x%x", | ||
| 3941 | did, vport->port_state, ndlp->nlp_flag); | ||
| 3942 | |||
| 3749 | phba->fc_stat.elsRcvRPS++; | 3943 | phba->fc_stat.elsRcvRPS++; |
| 3750 | lpfc_els_rcv_rps(vport, elsiocb, ndlp); | 3944 | lpfc_els_rcv_rps(vport, elsiocb, ndlp); |
| 3751 | if (newnode) | 3945 | if (newnode) |
| 3752 | lpfc_drop_node(vport, ndlp); | 3946 | lpfc_drop_node(vport, ndlp); |
| 3753 | break; | 3947 | break; |
| 3754 | case ELS_CMD_RPL: | 3948 | case ELS_CMD_RPL: |
| 3949 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | ||
| 3950 | "RCV RPL: did:x%x/ste:x%x flg:x%x", | ||
| 3951 | did, vport->port_state, ndlp->nlp_flag); | ||
| 3952 | |||
| 3755 | phba->fc_stat.elsRcvRPL++; | 3953 | phba->fc_stat.elsRcvRPL++; |
| 3756 | lpfc_els_rcv_rpl(vport, elsiocb, ndlp); | 3954 | lpfc_els_rcv_rpl(vport, elsiocb, ndlp); |
| 3757 | if (newnode) | 3955 | if (newnode) |
| 3758 | lpfc_drop_node(vport, ndlp); | 3956 | lpfc_drop_node(vport, ndlp); |
| 3759 | break; | 3957 | break; |
| 3760 | case ELS_CMD_RNID: | 3958 | case ELS_CMD_RNID: |
| 3959 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | ||
| 3960 | "RCV RNID: did:x%x/ste:x%x flg:x%x", | ||
| 3961 | did, vport->port_state, ndlp->nlp_flag); | ||
| 3962 | |||
| 3761 | phba->fc_stat.elsRcvRNID++; | 3963 | phba->fc_stat.elsRcvRNID++; |
| 3762 | lpfc_els_rcv_rnid(vport, elsiocb, ndlp); | 3964 | lpfc_els_rcv_rnid(vport, elsiocb, ndlp); |
| 3763 | if (newnode) | 3965 | if (newnode) |
| 3764 | lpfc_drop_node(vport, ndlp); | 3966 | lpfc_drop_node(vport, ndlp); |
| 3765 | break; | 3967 | break; |
| 3766 | default: | 3968 | default: |
| 3969 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | ||
| 3970 | "RCV ELS cmd: cmd:x%x did:x%x/ste:x%x", | ||
| 3971 | cmd, did, vport->port_state); | ||
| 3972 | |||
| 3767 | /* Unsupported ELS command, reject */ | 3973 | /* Unsupported ELS command, reject */ |
| 3768 | rjt_err = 2; | 3974 | rjt_err = LSRJT_INVALID_CMD; |
| 3769 | 3975 | ||
| 3770 | /* Unknown ELS command <elsCmd> received from NPORT <did> */ | 3976 | /* Unknown ELS command <elsCmd> received from NPORT <did> */ |
| 3771 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, | 3977 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, |
| @@ -3780,12 +3986,10 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
| 3780 | /* check if need to LS_RJT received ELS cmd */ | 3986 | /* check if need to LS_RJT received ELS cmd */ |
| 3781 | if (rjt_err) { | 3987 | if (rjt_err) { |
| 3782 | memset(&stat, 0, sizeof(stat)); | 3988 | memset(&stat, 0, sizeof(stat)); |
| 3783 | if (rjt_err == 1) | 3989 | stat.un.b.lsRjtRsnCode = rjt_err; |
| 3784 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | ||
| 3785 | else | ||
| 3786 | stat.un.b.lsRjtRsnCode = LSRJT_INVALID_CMD; | ||
| 3787 | stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; | 3990 | stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; |
| 3788 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, elsiocb, ndlp); | 3991 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, elsiocb, ndlp, |
| 3992 | NULL); | ||
| 3789 | if (newnode) | 3993 | if (newnode) |
| 3790 | lpfc_drop_node(vport, ndlp); | 3994 | lpfc_drop_node(vport, ndlp); |
| 3791 | } | 3995 | } |
| @@ -4044,6 +4248,10 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 4044 | lpfc_set_disctmo(piocb->vport); | 4248 | lpfc_set_disctmo(piocb->vport); |
| 4045 | } | 4249 | } |
| 4046 | 4250 | ||
| 4251 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
| 4252 | "FDISC cmpl: status:x%x/x%x prevdid:x%x", | ||
| 4253 | irsp->ulpStatus, irsp->un.ulpWord[4], vport->fc_prevDID); | ||
| 4254 | |||
| 4047 | if (irsp->ulpStatus) { | 4255 | if (irsp->ulpStatus) { |
| 4048 | /* Check for retry */ | 4256 | /* Check for retry */ |
| 4049 | if (lpfc_els_retry(phba, cmdiocb, rspiocb)) | 4257 | if (lpfc_els_retry(phba, cmdiocb, rspiocb)) |
| @@ -4054,6 +4262,7 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 4054 | "%d (%d):0124 FDISC failed. (%d/%d)\n", | 4262 | "%d (%d):0124 FDISC failed. (%d/%d)\n", |
| 4055 | phba->brd_no, vport->vpi, | 4263 | phba->brd_no, vport->vpi, |
| 4056 | irsp->ulpStatus, irsp->un.ulpWord[4]); | 4264 | irsp->ulpStatus, irsp->un.ulpWord[4]); |
| 4265 | |||
| 4057 | if (vport->fc_vport->vport_state == FC_VPORT_INITIALIZING) | 4266 | if (vport->fc_vport->vport_state == FC_VPORT_INITIALIZING) |
| 4058 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); | 4267 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); |
| 4059 | 4268 | ||
| @@ -4113,14 +4322,11 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 4113 | uint16_t cmdsize; | 4322 | uint16_t cmdsize; |
| 4114 | int did = ndlp->nlp_DID; | 4323 | int did = ndlp->nlp_DID; |
| 4115 | int rc; | 4324 | int rc; |
| 4116 | int new_ndlp = 0; | ||
| 4117 | 4325 | ||
| 4118 | cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm)); | 4326 | cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm)); |
| 4119 | elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, did, | 4327 | elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, did, |
| 4120 | ELS_CMD_FDISC); | 4328 | ELS_CMD_FDISC); |
| 4121 | if (!elsiocb) { | 4329 | if (!elsiocb) { |
| 4122 | if (new_ndlp) | ||
| 4123 | mempool_free(ndlp, phba->nlp_mem_pool); | ||
| 4124 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); | 4330 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); |
| 4125 | 4331 | ||
| 4126 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, | 4332 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, |
| @@ -4163,11 +4369,13 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 4163 | phba->fc_stat.elsXmitFDISC++; | 4369 | phba->fc_stat.elsXmitFDISC++; |
| 4164 | elsiocb->iocb_cmpl = lpfc_cmpl_els_fdisc; | 4370 | elsiocb->iocb_cmpl = lpfc_cmpl_els_fdisc; |
| 4165 | 4371 | ||
| 4372 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
| 4373 | "Issue FDISC: did:x%x", | ||
| 4374 | did, 0, 0); | ||
| 4375 | |||
| 4166 | rc = lpfc_issue_fabric_iocb(phba, elsiocb); | 4376 | rc = lpfc_issue_fabric_iocb(phba, elsiocb); |
| 4167 | if (rc == IOCB_ERROR) { | 4377 | if (rc == IOCB_ERROR) { |
| 4168 | lpfc_els_free_iocb(phba, elsiocb); | 4378 | lpfc_els_free_iocb(phba, elsiocb); |
| 4169 | if (new_ndlp) | ||
| 4170 | mempool_free(ndlp, phba->nlp_mem_pool); | ||
| 4171 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); | 4379 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); |
| 4172 | 4380 | ||
| 4173 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, | 4381 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, |
| @@ -4186,6 +4394,12 @@ lpfc_cmpl_els_npiv_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 4186 | struct lpfc_iocbq *rspiocb) | 4394 | struct lpfc_iocbq *rspiocb) |
| 4187 | { | 4395 | { |
| 4188 | struct lpfc_vport *vport = cmdiocb->vport; | 4396 | struct lpfc_vport *vport = cmdiocb->vport; |
| 4397 | IOCB_t *irsp; | ||
| 4398 | |||
| 4399 | irsp = &rspiocb->iocb; | ||
| 4400 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
| 4401 | "LOGO npiv cmpl: status:x%x/x%x did:x%x", | ||
| 4402 | irsp->ulpStatus, irsp->un.ulpWord[4], irsp->un.rcvels.remoteID); | ||
| 4189 | 4403 | ||
| 4190 | lpfc_els_free_iocb(phba, cmdiocb); | 4404 | lpfc_els_free_iocb(phba, cmdiocb); |
| 4191 | vport->unreg_vpi_cmpl = VPORT_ERROR; | 4405 | vport->unreg_vpi_cmpl = VPORT_ERROR; |
| @@ -4218,6 +4432,10 @@ lpfc_issue_els_npiv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
| 4218 | pcmd += sizeof(uint32_t); | 4432 | pcmd += sizeof(uint32_t); |
| 4219 | memcpy(pcmd, &vport->fc_portname, sizeof(struct lpfc_name)); | 4433 | memcpy(pcmd, &vport->fc_portname, sizeof(struct lpfc_name)); |
| 4220 | 4434 | ||
| 4435 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
| 4436 | "Issue LOGO npiv did:x%x flg:x%x", | ||
| 4437 | ndlp->nlp_DID, ndlp->nlp_flag, 0); | ||
| 4438 | |||
| 4221 | elsiocb->iocb_cmpl = lpfc_cmpl_els_npiv_logo; | 4439 | elsiocb->iocb_cmpl = lpfc_cmpl_els_npiv_logo; |
| 4222 | spin_lock_irq(shost->host_lock); | 4440 | spin_lock_irq(shost->host_lock); |
| 4223 | ndlp->nlp_flag |= NLP_LOGO_SND; | 4441 | ndlp->nlp_flag |= NLP_LOGO_SND; |
| @@ -4277,6 +4495,10 @@ repeat: | |||
| 4277 | iocb->iocb_cmpl = lpfc_cmpl_fabric_iocb; | 4495 | iocb->iocb_cmpl = lpfc_cmpl_fabric_iocb; |
| 4278 | iocb->iocb_flag |= LPFC_IO_FABRIC; | 4496 | iocb->iocb_flag |= LPFC_IO_FABRIC; |
| 4279 | 4497 | ||
| 4498 | lpfc_debugfs_disc_trc(iocb->vport, LPFC_DISC_TRC_ELS_CMD, | ||
| 4499 | "Fabric sched1: ste:x%x", | ||
| 4500 | iocb->vport->port_state, 0, 0); | ||
| 4501 | |||
| 4280 | ret = lpfc_sli_issue_iocb(phba, pring, iocb, 0); | 4502 | ret = lpfc_sli_issue_iocb(phba, pring, iocb, 0); |
| 4281 | 4503 | ||
| 4282 | if (ret == IOCB_ERROR) { | 4504 | if (ret == IOCB_ERROR) { |
| @@ -4387,6 +4609,10 @@ lpfc_issue_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *iocb) | |||
| 4387 | iocb->iocb_cmpl = lpfc_cmpl_fabric_iocb; | 4609 | iocb->iocb_cmpl = lpfc_cmpl_fabric_iocb; |
| 4388 | iocb->iocb_flag |= LPFC_IO_FABRIC; | 4610 | iocb->iocb_flag |= LPFC_IO_FABRIC; |
| 4389 | 4611 | ||
| 4612 | lpfc_debugfs_disc_trc(iocb->vport, LPFC_DISC_TRC_ELS_CMD, | ||
| 4613 | "Fabric sched2: ste:x%x", | ||
| 4614 | iocb->vport->port_state, 0, 0); | ||
| 4615 | |||
| 4390 | atomic_inc(&phba->fabric_iocb_count); | 4616 | atomic_inc(&phba->fabric_iocb_count); |
| 4391 | ret = lpfc_sli_issue_iocb(phba, pring, iocb, 0); | 4617 | ret = lpfc_sli_issue_iocb(phba, pring, iocb, 0); |
| 4392 | 4618 | ||
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 94ee9675b5b0..f2f4639eab59 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | #include "lpfc_logmsg.h" | 37 | #include "lpfc_logmsg.h" |
| 38 | #include "lpfc_crtn.h" | 38 | #include "lpfc_crtn.h" |
| 39 | #include "lpfc_vport.h" | 39 | #include "lpfc_vport.h" |
| 40 | #include "lpfc_debugfs.h" | ||
| 40 | 41 | ||
| 41 | /* AlpaArray for assignment of scsid for scan-down and bind_method */ | 42 | /* AlpaArray for assignment of scsid for scan-down and bind_method */ |
| 42 | static uint8_t lpfcAlpaArray[] = { | 43 | static uint8_t lpfcAlpaArray[] = { |
| @@ -77,6 +78,10 @@ lpfc_terminate_rport_io(struct fc_rport *rport) | |||
| 77 | 78 | ||
| 78 | phba = ndlp->vport->phba; | 79 | phba = ndlp->vport->phba; |
| 79 | 80 | ||
| 81 | lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_RPORT, | ||
| 82 | "rport terminate: sid:x%x did:x%x flg:x%x", | ||
| 83 | ndlp->nlp_sid, ndlp->nlp_DID, ndlp->nlp_flag); | ||
| 84 | |||
| 80 | if (ndlp->nlp_sid != NLP_NO_SID) { | 85 | if (ndlp->nlp_sid != NLP_NO_SID) { |
| 81 | lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], | 86 | lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], |
| 82 | ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT); | 87 | ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT); |
| @@ -93,12 +98,10 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) | |||
| 93 | { | 98 | { |
| 94 | struct lpfc_rport_data *rdata; | 99 | struct lpfc_rport_data *rdata; |
| 95 | struct lpfc_nodelist * ndlp; | 100 | struct lpfc_nodelist * ndlp; |
| 96 | uint8_t *name; | ||
| 97 | int warn_on = 0; | ||
| 98 | struct lpfc_hba *phba; | ||
| 99 | struct lpfc_vport *vport; | 101 | struct lpfc_vport *vport; |
| 100 | int put_node; | 102 | struct lpfc_hba *phba; |
| 101 | int put_rport; | 103 | struct completion devloss_compl; |
| 104 | struct lpfc_work_evt *evtp; | ||
| 102 | 105 | ||
| 103 | rdata = rport->dd_data; | 106 | rdata = rport->dd_data; |
| 104 | ndlp = rdata->pnode; | 107 | ndlp = rdata->pnode; |
| @@ -112,7 +115,70 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) | |||
| 112 | return; | 115 | return; |
| 113 | } | 116 | } |
| 114 | 117 | ||
| 118 | vport = ndlp->vport; | ||
| 119 | phba = vport->phba; | ||
| 120 | |||
| 121 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT, | ||
| 122 | "rport devlosscb: sid:x%x did:x%x flg:x%x", | ||
| 123 | ndlp->nlp_sid, ndlp->nlp_DID, ndlp->nlp_flag); | ||
| 124 | |||
| 125 | init_completion(&devloss_compl); | ||
| 126 | evtp = &ndlp->dev_loss_evt; | ||
| 127 | |||
| 128 | if (!list_empty(&evtp->evt_listp)) | ||
| 129 | return; | ||
| 130 | |||
| 131 | spin_lock_irq(&phba->hbalock); | ||
| 132 | evtp->evt_arg1 = ndlp; | ||
| 133 | evtp->evt_arg2 = &devloss_compl; | ||
| 134 | evtp->evt = LPFC_EVT_DEV_LOSS; | ||
| 135 | list_add_tail(&evtp->evt_listp, &phba->work_list); | ||
| 136 | if (phba->work_wait) | ||
| 137 | wake_up(phba->work_wait); | ||
| 138 | |||
| 139 | spin_unlock_irq(&phba->hbalock); | ||
| 140 | |||
| 141 | wait_for_completion(&devloss_compl); | ||
| 142 | |||
| 143 | return; | ||
| 144 | } | ||
| 145 | |||
| 146 | /* | ||
| 147 | * This function is called from the worker thread when dev_loss_tmo | ||
| 148 | * expire. | ||
| 149 | */ | ||
| 150 | void | ||
| 151 | lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) | ||
| 152 | { | ||
| 153 | struct lpfc_rport_data *rdata; | ||
| 154 | struct fc_rport *rport; | ||
| 155 | struct lpfc_vport *vport; | ||
| 156 | struct lpfc_hba *phba; | ||
| 157 | uint8_t *name; | ||
| 158 | int warn_on = 0; | ||
| 159 | |||
| 160 | rport = ndlp->rport; | ||
| 161 | |||
| 162 | if (!rport) | ||
| 163 | return; | ||
| 164 | |||
| 165 | rdata = rport->dd_data; | ||
| 166 | name = (uint8_t *) &ndlp->nlp_portname; | ||
| 167 | vport = ndlp->vport; | ||
| 168 | phba = vport->phba; | ||
| 169 | |||
| 170 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT, | ||
| 171 | "rport devlosstmo:did:x%x type:x%x id:x%x", | ||
| 172 | ndlp->nlp_DID, ndlp->nlp_type, rport->scsi_target_id); | ||
| 173 | |||
| 174 | if (!(vport->load_flag & FC_UNLOADING) && | ||
| 175 | ndlp->nlp_state == NLP_STE_MAPPED_NODE) | ||
| 176 | return; | ||
| 177 | |||
| 115 | if (ndlp->nlp_type & NLP_FABRIC) { | 178 | if (ndlp->nlp_type & NLP_FABRIC) { |
| 179 | int put_node; | ||
| 180 | int put_rport; | ||
| 181 | |||
| 116 | /* We will clean up these Nodes in linkup */ | 182 | /* We will clean up these Nodes in linkup */ |
| 117 | put_node = rdata->pnode != NULL; | 183 | put_node = rdata->pnode != NULL; |
| 118 | put_rport = ndlp->rport != NULL; | 184 | put_rport = ndlp->rport != NULL; |
| @@ -125,15 +191,6 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) | |||
| 125 | return; | 191 | return; |
| 126 | } | 192 | } |
| 127 | 193 | ||
| 128 | name = (uint8_t *)&ndlp->nlp_portname; | ||
| 129 | vport = ndlp->vport; | ||
| 130 | phba = vport->phba; | ||
| 131 | |||
| 132 | if (!(vport->load_flag & FC_UNLOADING) && | ||
| 133 | ndlp->nlp_state == NLP_STE_MAPPED_NODE) | ||
| 134 | return; | ||
| 135 | |||
| 136 | |||
| 137 | if (ndlp->nlp_sid != NLP_NO_SID) { | 194 | if (ndlp->nlp_sid != NLP_NO_SID) { |
| 138 | warn_on = 1; | 195 | warn_on = 1; |
| 139 | /* flush the target */ | 196 | /* flush the target */ |
| @@ -171,6 +228,9 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) | |||
| 171 | (ndlp->nlp_state != NLP_STE_UNMAPPED_NODE)) | 228 | (ndlp->nlp_state != NLP_STE_UNMAPPED_NODE)) |
| 172 | lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM); | 229 | lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM); |
| 173 | else { | 230 | else { |
| 231 | int put_node; | ||
| 232 | int put_rport; | ||
| 233 | |||
| 174 | put_node = rdata->pnode != NULL; | 234 | put_node = rdata->pnode != NULL; |
| 175 | put_rport = ndlp->rport != NULL; | 235 | put_rport = ndlp->rport != NULL; |
| 176 | rdata->pnode = NULL; | 236 | rdata->pnode = NULL; |
| @@ -180,7 +240,6 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) | |||
| 180 | if (put_rport) | 240 | if (put_rport) |
| 181 | put_device(&rport->dev); | 241 | put_device(&rport->dev); |
| 182 | } | 242 | } |
| 183 | return; | ||
| 184 | } | 243 | } |
| 185 | 244 | ||
| 186 | 245 | ||
| @@ -206,12 +265,17 @@ lpfc_work_list_done(struct lpfc_hba *phba) | |||
| 206 | spin_unlock_irq(&phba->hbalock); | 265 | spin_unlock_irq(&phba->hbalock); |
| 207 | free_evt = 1; | 266 | free_evt = 1; |
| 208 | switch (evtp->evt) { | 267 | switch (evtp->evt) { |
| 209 | case LPFC_EVT_DEV_LOSS: | 268 | case LPFC_EVT_DEV_LOSS_DELAY: |
| 210 | free_evt = 0; /* evt is part of ndlp */ | 269 | free_evt = 0; /* evt is part of ndlp */ |
| 211 | ndlp = (struct lpfc_nodelist *) (evtp->evt_arg1); | 270 | ndlp = (struct lpfc_nodelist *) (evtp->evt_arg1); |
| 212 | vport = ndlp->vport; | 271 | vport = ndlp->vport; |
| 213 | if (!vport) | 272 | if (!vport) |
| 214 | break; | 273 | break; |
| 274 | |||
| 275 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT, | ||
| 276 | "rport devlossdly:did:x%x flg:x%x", | ||
| 277 | ndlp->nlp_DID, ndlp->nlp_flag, 0); | ||
| 278 | |||
| 215 | if (!(vport->load_flag & FC_UNLOADING) && | 279 | if (!(vport->load_flag & FC_UNLOADING) && |
| 216 | !(ndlp->nlp_flag & NLP_DELAY_TMO) && | 280 | !(ndlp->nlp_flag & NLP_DELAY_TMO) && |
| 217 | !(ndlp->nlp_flag & NLP_NPR_2B_DISC)) { | 281 | !(ndlp->nlp_flag & NLP_NPR_2B_DISC)) { |
| @@ -224,6 +288,14 @@ lpfc_work_list_done(struct lpfc_hba *phba) | |||
| 224 | lpfc_els_retry_delay_handler(ndlp); | 288 | lpfc_els_retry_delay_handler(ndlp); |
| 225 | free_evt = 0; /* evt is part of ndlp */ | 289 | free_evt = 0; /* evt is part of ndlp */ |
| 226 | break; | 290 | break; |
| 291 | case LPFC_EVT_DEV_LOSS: | ||
| 292 | ndlp = (struct lpfc_nodelist *)(evtp->evt_arg1); | ||
| 293 | lpfc_nlp_get(ndlp); | ||
| 294 | lpfc_dev_loss_tmo_handler(ndlp); | ||
| 295 | free_evt = 0; | ||
| 296 | complete((struct completion *)(evtp->evt_arg2)); | ||
| 297 | lpfc_nlp_put(ndlp); | ||
| 298 | break; | ||
| 227 | case LPFC_EVT_ONLINE: | 299 | case LPFC_EVT_ONLINE: |
| 228 | if (phba->link_state < LPFC_LINK_DOWN) | 300 | if (phba->link_state < LPFC_LINK_DOWN) |
| 229 | *(int *) (evtp->evt_arg1) = lpfc_online(phba); | 301 | *(int *) (evtp->evt_arg1) = lpfc_online(phba); |
| @@ -272,13 +344,12 @@ lpfc_work_list_done(struct lpfc_hba *phba) | |||
| 272 | 344 | ||
| 273 | } | 345 | } |
| 274 | 346 | ||
| 275 | static void | 347 | void |
| 276 | lpfc_work_done(struct lpfc_hba *phba) | 348 | lpfc_work_done(struct lpfc_hba *phba) |
| 277 | { | 349 | { |
| 278 | struct lpfc_sli_ring *pring; | 350 | struct lpfc_sli_ring *pring; |
| 279 | uint32_t ha_copy, control, work_port_events; | 351 | uint32_t ha_copy, status, control, work_port_events; |
| 280 | struct lpfc_vport *vport; | 352 | struct lpfc_vport *vport; |
| 281 | int i; | ||
| 282 | 353 | ||
| 283 | spin_lock_irq(&phba->hbalock); | 354 | spin_lock_irq(&phba->hbalock); |
| 284 | ha_copy = phba->work_ha; | 355 | ha_copy = phba->work_ha; |
| @@ -310,6 +381,9 @@ lpfc_work_done(struct lpfc_hba *phba) | |||
| 310 | if (work_port_events & WORKER_ELS_TMO) | 381 | if (work_port_events & WORKER_ELS_TMO) |
| 311 | lpfc_els_timeout_handler(vport); | 382 | lpfc_els_timeout_handler(vport); |
| 312 | 383 | ||
| 384 | if (work_port_events & WORKER_HB_TMO) | ||
| 385 | lpfc_hb_timeout_handler(phba); | ||
| 386 | |||
| 313 | if (work_port_events & WORKER_MBOX_TMO) | 387 | if (work_port_events & WORKER_MBOX_TMO) |
| 314 | lpfc_mbox_timeout_handler(phba); | 388 | lpfc_mbox_timeout_handler(phba); |
| 315 | 389 | ||
| @@ -333,30 +407,31 @@ lpfc_work_done(struct lpfc_hba *phba) | |||
| 333 | } | 407 | } |
| 334 | spin_unlock_irq(&phba->hbalock); | 408 | spin_unlock_irq(&phba->hbalock); |
| 335 | 409 | ||
| 336 | for (i = 0; i < phba->sli.num_rings; i++, ha_copy >>= 4) { | 410 | pring = &phba->sli.ring[LPFC_ELS_RING]; |
| 337 | pring = &phba->sli.ring[i]; | 411 | status = (ha_copy & (HA_RXMASK << (4*LPFC_ELS_RING))); |
| 338 | if ((ha_copy & HA_RXATT) | 412 | status >>= (4*LPFC_ELS_RING); |
| 339 | || (pring->flag & LPFC_DEFERRED_RING_EVENT)) { | 413 | if ((status & HA_RXMASK) |
| 340 | if (pring->flag & LPFC_STOP_IOCB_MASK) { | 414 | || (pring->flag & LPFC_DEFERRED_RING_EVENT)) { |
| 341 | pring->flag |= LPFC_DEFERRED_RING_EVENT; | 415 | if (pring->flag & LPFC_STOP_IOCB_MASK) { |
| 342 | } else { | 416 | pring->flag |= LPFC_DEFERRED_RING_EVENT; |
| 343 | lpfc_sli_handle_slow_ring_event(phba, pring, | 417 | } else { |
| 344 | (ha_copy & | 418 | lpfc_sli_handle_slow_ring_event(phba, pring, |
| 345 | HA_RXMASK)); | 419 | (status & |
| 346 | pring->flag &= ~LPFC_DEFERRED_RING_EVENT; | 420 | HA_RXMASK)); |
| 347 | } | 421 | pring->flag &= ~LPFC_DEFERRED_RING_EVENT; |
| 348 | /* | 422 | } |
| 349 | * Turn on Ring interrupts | 423 | /* |
| 350 | */ | 424 | * Turn on Ring interrupts |
| 351 | spin_lock_irq(&phba->hbalock); | 425 | */ |
| 352 | control = readl(phba->HCregaddr); | 426 | spin_lock_irq(&phba->hbalock); |
| 353 | control |= (HC_R0INT_ENA << i); | 427 | control = readl(phba->HCregaddr); |
| 428 | if (!(control & (HC_R0INT_ENA << LPFC_ELS_RING))) { | ||
| 429 | control |= (HC_R0INT_ENA << LPFC_ELS_RING); | ||
| 354 | writel(control, phba->HCregaddr); | 430 | writel(control, phba->HCregaddr); |
| 355 | readl(phba->HCregaddr); /* flush */ | 431 | readl(phba->HCregaddr); /* flush */ |
| 356 | spin_unlock_irq(&phba->hbalock); | ||
| 357 | } | 432 | } |
| 433 | spin_unlock_irq(&phba->hbalock); | ||
| 358 | } | 434 | } |
| 359 | |||
| 360 | lpfc_work_list_done(phba); | 435 | lpfc_work_list_done(phba); |
| 361 | } | 436 | } |
| 362 | 437 | ||
| @@ -365,7 +440,7 @@ check_work_wait_done(struct lpfc_hba *phba) | |||
| 365 | { | 440 | { |
| 366 | struct lpfc_vport *vport; | 441 | struct lpfc_vport *vport; |
| 367 | struct lpfc_sli_ring *pring; | 442 | struct lpfc_sli_ring *pring; |
| 368 | int i, rc = 0; | 443 | int rc = 0; |
| 369 | 444 | ||
| 370 | spin_lock_irq(&phba->hbalock); | 445 | spin_lock_irq(&phba->hbalock); |
| 371 | list_for_each_entry(vport, &phba->port_list, listentry) { | 446 | list_for_each_entry(vport, &phba->port_list, listentry) { |
| @@ -380,13 +455,10 @@ check_work_wait_done(struct lpfc_hba *phba) | |||
| 380 | rc = 1; | 455 | rc = 1; |
| 381 | goto exit; | 456 | goto exit; |
| 382 | } | 457 | } |
| 383 | for (i = 0; i < phba->sli.num_rings; i++) { | 458 | |
| 384 | pring = &phba->sli.ring[i]; | 459 | pring = &phba->sli.ring[LPFC_ELS_RING]; |
| 385 | if (pring->flag & LPFC_DEFERRED_RING_EVENT) { | 460 | if (pring->flag & LPFC_DEFERRED_RING_EVENT) |
| 386 | rc = 1; | 461 | rc = 1; |
| 387 | goto exit; | ||
| 388 | } | ||
| 389 | } | ||
| 390 | exit: | 462 | exit: |
| 391 | if (rc) | 463 | if (rc) |
| 392 | phba->work_found++; | 464 | phba->work_found++; |
| @@ -506,6 +578,10 @@ lpfc_linkdown_port(struct lpfc_vport *vport) | |||
| 506 | 578 | ||
| 507 | fc_host_post_event(shost, fc_get_event_number(), FCH_EVT_LINKDOWN, 0); | 579 | fc_host_post_event(shost, fc_get_event_number(), FCH_EVT_LINKDOWN, 0); |
| 508 | 580 | ||
| 581 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
| 582 | "Link Down: state:x%x rtry:x%x flg:x%x", | ||
| 583 | vport->port_state, vport->fc_ns_retry, vport->fc_flag); | ||
| 584 | |||
| 509 | /* Cleanup any outstanding RSCN activity */ | 585 | /* Cleanup any outstanding RSCN activity */ |
| 510 | lpfc_els_flush_rscn(vport); | 586 | lpfc_els_flush_rscn(vport); |
| 511 | 587 | ||
| @@ -617,6 +693,10 @@ lpfc_linkup_port(struct lpfc_vport *vport) | |||
| 617 | if ((vport->load_flag & FC_UNLOADING) != 0) | 693 | if ((vport->load_flag & FC_UNLOADING) != 0) |
| 618 | return; | 694 | return; |
| 619 | 695 | ||
| 696 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
| 697 | "Link Up: top:x%x speed:x%x flg:x%x", | ||
| 698 | phba->fc_topology, phba->fc_linkspeed, phba->link_flag); | ||
| 699 | |||
| 620 | /* If NPIV is not enabled, only bring the physical port up */ | 700 | /* If NPIV is not enabled, only bring the physical port up */ |
| 621 | if (!(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) && | 701 | if (!(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) && |
| 622 | (vport != phba->pport)) | 702 | (vport != phba->pport)) |
| @@ -935,7 +1015,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) | |||
| 935 | } | 1015 | } |
| 936 | } else { | 1016 | } else { |
| 937 | if (!(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)) { | 1017 | if (!(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)) { |
| 938 | if (phba->max_vpi && lpfc_npiv_enable && | 1018 | if (phba->max_vpi && phba->cfg_npiv_enable && |
| 939 | (phba->sli_rev == 3)) | 1019 | (phba->sli_rev == 3)) |
| 940 | phba->sli3_options |= LPFC_SLI3_NPIV_ENABLED; | 1020 | phba->sli3_options |= LPFC_SLI3_NPIV_ENABLED; |
| 941 | } | 1021 | } |
| @@ -1124,8 +1204,6 @@ lpfc_mbx_cmpl_unreg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
| 1124 | "mb status = 0x%x\n", | 1204 | "mb status = 0x%x\n", |
| 1125 | phba->brd_no, vport->vpi, mb->mbxStatus); | 1205 | phba->brd_no, vport->vpi, mb->mbxStatus); |
| 1126 | break; | 1206 | break; |
| 1127 | default: | ||
| 1128 | phba->vpi_cnt--; | ||
| 1129 | } | 1207 | } |
| 1130 | vport->unreg_vpi_cmpl = VPORT_OK; | 1208 | vport->unreg_vpi_cmpl = VPORT_OK; |
| 1131 | mempool_free(pmb, phba->mbox_mem_pool); | 1209 | mempool_free(pmb, phba->mbox_mem_pool); |
| @@ -1182,7 +1260,6 @@ lpfc_mbx_cmpl_reg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
| 1182 | vport->fc_myDID = 0; | 1260 | vport->fc_myDID = 0; |
| 1183 | goto out; | 1261 | goto out; |
| 1184 | } | 1262 | } |
| 1185 | phba->vpi_cnt++; | ||
| 1186 | 1263 | ||
| 1187 | vport->num_disc_nodes = 0; | 1264 | vport->num_disc_nodes = 0; |
| 1188 | /* go thru NPR list and issue ELS PLOGIs */ | 1265 | /* go thru NPR list and issue ELS PLOGIs */ |
| @@ -1257,16 +1334,13 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
| 1257 | 1334 | ||
| 1258 | if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) | 1335 | if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) |
| 1259 | lpfc_initial_fdisc(next_vport); | 1336 | lpfc_initial_fdisc(next_vport); |
| 1260 | else { | 1337 | else if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) { |
| 1261 | if (phba->sli3_options & | 1338 | lpfc_vport_set_state(vport, |
| 1262 | LPFC_SLI3_NPIV_ENABLED) { | 1339 | FC_VPORT_NO_FABRIC_SUPP); |
| 1263 | lpfc_vport_set_state(vport, | 1340 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, |
| 1264 | FC_VPORT_NO_FABRIC_SUPP); | ||
| 1265 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, | ||
| 1266 | "%d (%d):0259 No NPIV Fabric " | 1341 | "%d (%d):0259 No NPIV Fabric " |
| 1267 | "support\n", | 1342 | "support\n", |
| 1268 | phba->brd_no, vport->vpi); | 1343 | phba->brd_no, vport->vpi); |
| 1269 | } | ||
| 1270 | } | 1344 | } |
| 1271 | } | 1345 | } |
| 1272 | lpfc_do_scr_ns_plogi(phba, vport); | 1346 | lpfc_do_scr_ns_plogi(phba, vport); |
| @@ -1377,6 +1451,11 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
| 1377 | ((struct lpfc_rport_data *) ndlp->rport->dd_data)->pnode == ndlp) { | 1451 | ((struct lpfc_rport_data *) ndlp->rport->dd_data)->pnode == ndlp) { |
| 1378 | lpfc_nlp_put(ndlp); | 1452 | lpfc_nlp_put(ndlp); |
| 1379 | } | 1453 | } |
| 1454 | |||
| 1455 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT, | ||
| 1456 | "rport add: did:x%x flg:x%x type x%x", | ||
| 1457 | ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type); | ||
| 1458 | |||
| 1380 | ndlp->rport = rport = fc_remote_port_add(shost, 0, &rport_ids); | 1459 | ndlp->rport = rport = fc_remote_port_add(shost, 0, &rport_ids); |
| 1381 | if (!rport || !get_device(&rport->dev)) { | 1460 | if (!rport || !get_device(&rport->dev)) { |
| 1382 | dev_printk(KERN_WARNING, &phba->pcidev->dev, | 1461 | dev_printk(KERN_WARNING, &phba->pcidev->dev, |
| @@ -1394,7 +1473,6 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
| 1394 | rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET; | 1473 | rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET; |
| 1395 | if (ndlp->nlp_type & NLP_FCP_INITIATOR) | 1474 | if (ndlp->nlp_type & NLP_FCP_INITIATOR) |
| 1396 | rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR; | 1475 | rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR; |
| 1397 | del_timer_sync(&ndlp->nlp_initiator_tmr); | ||
| 1398 | 1476 | ||
| 1399 | 1477 | ||
| 1400 | if (rport_ids.roles != FC_RPORT_ROLE_UNKNOWN) | 1478 | if (rport_ids.roles != FC_RPORT_ROLE_UNKNOWN) |
| @@ -1412,6 +1490,10 @@ lpfc_unregister_remote_port(struct lpfc_nodelist *ndlp) | |||
| 1412 | { | 1490 | { |
| 1413 | struct fc_rport *rport = ndlp->rport; | 1491 | struct fc_rport *rport = ndlp->rport; |
| 1414 | 1492 | ||
| 1493 | lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_RPORT, | ||
| 1494 | "rport delete: did:x%x flg:x%x type x%x", | ||
| 1495 | ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type); | ||
| 1496 | |||
| 1415 | fc_remote_port_delete(rport); | 1497 | fc_remote_port_delete(rport); |
| 1416 | 1498 | ||
| 1417 | return; | 1499 | return; |
| @@ -1478,20 +1560,19 @@ lpfc_nlp_state_cleanup(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 1478 | if (new_state == NLP_STE_MAPPED_NODE || | 1560 | if (new_state == NLP_STE_MAPPED_NODE || |
| 1479 | new_state == NLP_STE_UNMAPPED_NODE) { | 1561 | new_state == NLP_STE_UNMAPPED_NODE) { |
| 1480 | vport->phba->nport_event_cnt++; | 1562 | vport->phba->nport_event_cnt++; |
| 1481 | /* | 1563 | /* |
| 1482 | * Tell the fc transport about the port, if we haven't | 1564 | * Tell the fc transport about the port, if we haven't |
| 1483 | * already. If we have, and it's a scsi entity, be | 1565 | * already. If we have, and it's a scsi entity, be |
| 1484 | * sure to unblock any attached scsi devices | 1566 | * sure to unblock any attached scsi devices |
| 1485 | */ | 1567 | */ |
| 1486 | lpfc_register_remote_port(vport, ndlp); | 1568 | lpfc_register_remote_port(vport, ndlp); |
| 1487 | } | 1569 | } |
| 1488 | 1570 | /* | |
| 1489 | /* | 1571 | * if we added to Mapped list, but the remote port |
| 1490 | * if we added to Mapped list, but the remote port | 1572 | * registration failed or assigned a target id outside |
| 1491 | * registration failed or assigned a target id outside | 1573 | * our presentable range - move the node to the |
| 1492 | * our presentable range - move the node to the | 1574 | * Unmapped List |
| 1493 | * Unmapped List | 1575 | */ |
| 1494 | */ | ||
| 1495 | if (new_state == NLP_STE_MAPPED_NODE && | 1576 | if (new_state == NLP_STE_MAPPED_NODE && |
| 1496 | (!ndlp->rport || | 1577 | (!ndlp->rport || |
| 1497 | ndlp->rport->scsi_target_id == -1 || | 1578 | ndlp->rport->scsi_target_id == -1 || |
| @@ -1533,11 +1614,16 @@ lpfc_nlp_set_state(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 1533 | char name1[16], name2[16]; | 1614 | char name1[16], name2[16]; |
| 1534 | 1615 | ||
| 1535 | lpfc_printf_log(vport->phba, KERN_INFO, LOG_NODE, | 1616 | lpfc_printf_log(vport->phba, KERN_INFO, LOG_NODE, |
| 1536 | "%d:0904 NPort state transition x%06x, %s -> %s\n", | 1617 | "%d (%d):0904 NPort state transition x%06x, %s -> %s\n", |
| 1537 | vport->phba->brd_no, | 1618 | vport->phba->brd_no, vport->vpi, |
| 1538 | ndlp->nlp_DID, | 1619 | ndlp->nlp_DID, |
| 1539 | lpfc_nlp_state_name(name1, sizeof(name1), old_state), | 1620 | lpfc_nlp_state_name(name1, sizeof(name1), old_state), |
| 1540 | lpfc_nlp_state_name(name2, sizeof(name2), state)); | 1621 | lpfc_nlp_state_name(name2, sizeof(name2), state)); |
| 1622 | |||
| 1623 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_NODE, | ||
| 1624 | "node statechg did:x%x old:%d ste:%d", | ||
| 1625 | ndlp->nlp_DID, old_state, state); | ||
| 1626 | |||
| 1541 | if (old_state == NLP_STE_NPR_NODE && | 1627 | if (old_state == NLP_STE_NPR_NODE && |
| 1542 | (ndlp->nlp_flag & NLP_DELAY_TMO) != 0 && | 1628 | (ndlp->nlp_flag & NLP_DELAY_TMO) != 0 && |
| 1543 | state != NLP_STE_NPR_NODE) | 1629 | state != NLP_STE_NPR_NODE) |
| @@ -1571,7 +1657,8 @@ lpfc_dequeue_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
| 1571 | spin_lock_irq(shost->host_lock); | 1657 | spin_lock_irq(shost->host_lock); |
| 1572 | list_del_init(&ndlp->nlp_listp); | 1658 | list_del_init(&ndlp->nlp_listp); |
| 1573 | spin_unlock_irq(shost->host_lock); | 1659 | spin_unlock_irq(shost->host_lock); |
| 1574 | lpfc_nlp_state_cleanup(vport, ndlp, ndlp->nlp_state, 0); | 1660 | lpfc_nlp_state_cleanup(vport, ndlp, ndlp->nlp_state, |
| 1661 | NLP_STE_UNUSED_NODE); | ||
| 1575 | } | 1662 | } |
| 1576 | 1663 | ||
| 1577 | void | 1664 | void |
| @@ -1585,6 +1672,7 @@ lpfc_drop_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
| 1585 | lpfc_nlp_counters(vport, ndlp->nlp_state, -1); | 1672 | lpfc_nlp_counters(vport, ndlp->nlp_state, -1); |
| 1586 | spin_lock_irq(shost->host_lock); | 1673 | spin_lock_irq(shost->host_lock); |
| 1587 | list_del_init(&ndlp->nlp_listp); | 1674 | list_del_init(&ndlp->nlp_listp); |
| 1675 | ndlp->nlp_flag &= ~NLP_TARGET_REMOVE; | ||
| 1588 | spin_unlock_irq(shost->host_lock); | 1676 | spin_unlock_irq(shost->host_lock); |
| 1589 | lpfc_nlp_put(ndlp); | 1677 | lpfc_nlp_put(ndlp); |
| 1590 | } | 1678 | } |
| @@ -1609,6 +1697,13 @@ lpfc_set_disctmo(struct lpfc_vport *vport) | |||
| 1609 | tmo = ((phba->fc_ratov * 3) + 3); | 1697 | tmo = ((phba->fc_ratov * 3) + 3); |
| 1610 | } | 1698 | } |
| 1611 | 1699 | ||
| 1700 | |||
| 1701 | if (!timer_pending(&vport->fc_disctmo)) { | ||
| 1702 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
| 1703 | "set disc timer: tmo:x%x state:x%x flg:x%x", | ||
| 1704 | tmo, vport->port_state, vport->fc_flag); | ||
| 1705 | } | ||
| 1706 | |||
| 1612 | mod_timer(&vport->fc_disctmo, jiffies + HZ * tmo); | 1707 | mod_timer(&vport->fc_disctmo, jiffies + HZ * tmo); |
| 1613 | spin_lock_irq(shost->host_lock); | 1708 | spin_lock_irq(shost->host_lock); |
| 1614 | vport->fc_flag |= FC_DISC_TMO; | 1709 | vport->fc_flag |= FC_DISC_TMO; |
| @@ -1635,6 +1730,10 @@ lpfc_can_disctmo(struct lpfc_vport *vport) | |||
| 1635 | struct lpfc_hba *phba = vport->phba; | 1730 | struct lpfc_hba *phba = vport->phba; |
| 1636 | unsigned long iflags; | 1731 | unsigned long iflags; |
| 1637 | 1732 | ||
| 1733 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
| 1734 | "can disc timer: state:x%x rtry:x%x flg:x%x", | ||
| 1735 | vport->port_state, vport->fc_ns_retry, vport->fc_flag); | ||
| 1736 | |||
| 1638 | /* Turn off discovery timer if its running */ | 1737 | /* Turn off discovery timer if its running */ |
| 1639 | if (vport->fc_flag & FC_DISC_TMO) { | 1738 | if (vport->fc_flag & FC_DISC_TMO) { |
| 1640 | spin_lock_irqsave(shost->host_lock, iflags); | 1739 | spin_lock_irqsave(shost->host_lock, iflags); |
| @@ -1898,13 +1997,17 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
| 1898 | 1997 | ||
| 1899 | ndlp->nlp_last_elscmd = 0; | 1998 | ndlp->nlp_last_elscmd = 0; |
| 1900 | del_timer_sync(&ndlp->nlp_delayfunc); | 1999 | del_timer_sync(&ndlp->nlp_delayfunc); |
| 1901 | del_timer_sync(&ndlp->nlp_initiator_tmr); | ||
| 1902 | 2000 | ||
| 1903 | if (!list_empty(&ndlp->els_retry_evt.evt_listp)) | 2001 | if (!list_empty(&ndlp->els_retry_evt.evt_listp)) |
| 1904 | list_del_init(&ndlp->els_retry_evt.evt_listp); | 2002 | list_del_init(&ndlp->els_retry_evt.evt_listp); |
| 1905 | if (!list_empty(&ndlp->dev_loss_evt.evt_listp)) | 2003 | if (!list_empty(&ndlp->dev_loss_evt.evt_listp)) |
| 1906 | list_del_init(&ndlp->dev_loss_evt.evt_listp); | 2004 | list_del_init(&ndlp->dev_loss_evt.evt_listp); |
| 1907 | 2005 | ||
| 2006 | if (!list_empty(&ndlp->dev_loss_evt.evt_listp)) { | ||
| 2007 | list_del_init(&ndlp->dev_loss_evt.evt_listp); | ||
| 2008 | complete((struct completion *)(ndlp->dev_loss_evt.evt_arg2)); | ||
| 2009 | } | ||
| 2010 | |||
| 1908 | lpfc_unreg_rpi(vport, ndlp); | 2011 | lpfc_unreg_rpi(vport, ndlp); |
| 1909 | 2012 | ||
| 1910 | return 0; | 2013 | return 0; |
| @@ -2418,6 +2521,10 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) | |||
| 2418 | vport->fc_flag &= ~FC_DISC_TMO; | 2521 | vport->fc_flag &= ~FC_DISC_TMO; |
| 2419 | spin_unlock_irq(shost->host_lock); | 2522 | spin_unlock_irq(shost->host_lock); |
| 2420 | 2523 | ||
| 2524 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | ||
| 2525 | "disc timeout: state:x%x rtry:x%x flg:x%x", | ||
| 2526 | vport->port_state, vport->fc_ns_retry, vport->fc_flag); | ||
| 2527 | |||
| 2421 | switch (vport->port_state) { | 2528 | switch (vport->port_state) { |
| 2422 | 2529 | ||
| 2423 | case LPFC_LOCAL_CFG_LINK: | 2530 | case LPFC_LOCAL_CFG_LINK: |
| @@ -2743,7 +2850,7 @@ lpfc_findnode_wwpn(struct lpfc_vport *vport, struct lpfc_name *wwpn) | |||
| 2743 | spin_lock_irq(shost->host_lock); | 2850 | spin_lock_irq(shost->host_lock); |
| 2744 | ndlp = __lpfc_find_node(vport, lpfc_filter_by_wwpn, wwpn); | 2851 | ndlp = __lpfc_find_node(vport, lpfc_filter_by_wwpn, wwpn); |
| 2745 | spin_unlock_irq(shost->host_lock); | 2852 | spin_unlock_irq(shost->host_lock); |
| 2746 | return NULL; | 2853 | return ndlp; |
| 2747 | } | 2854 | } |
| 2748 | 2855 | ||
| 2749 | void | 2856 | void |
| @@ -2764,7 +2871,7 @@ lpfc_dev_loss_delay(unsigned long ptr) | |||
| 2764 | } | 2871 | } |
| 2765 | 2872 | ||
| 2766 | evtp->evt_arg1 = ndlp; | 2873 | evtp->evt_arg1 = ndlp; |
| 2767 | evtp->evt = LPFC_EVT_DEV_LOSS; | 2874 | evtp->evt = LPFC_EVT_DEV_LOSS_DELAY; |
| 2768 | list_add_tail(&evtp->evt_listp, &phba->work_list); | 2875 | list_add_tail(&evtp->evt_listp, &phba->work_list); |
| 2769 | if (phba->work_wait) | 2876 | if (phba->work_wait) |
| 2770 | lpfc_worker_wake_up(phba); | 2877 | lpfc_worker_wake_up(phba); |
| @@ -2779,9 +2886,6 @@ lpfc_nlp_init(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 2779 | memset(ndlp, 0, sizeof (struct lpfc_nodelist)); | 2886 | memset(ndlp, 0, sizeof (struct lpfc_nodelist)); |
| 2780 | INIT_LIST_HEAD(&ndlp->els_retry_evt.evt_listp); | 2887 | INIT_LIST_HEAD(&ndlp->els_retry_evt.evt_listp); |
| 2781 | INIT_LIST_HEAD(&ndlp->dev_loss_evt.evt_listp); | 2888 | INIT_LIST_HEAD(&ndlp->dev_loss_evt.evt_listp); |
| 2782 | init_timer(&ndlp->nlp_initiator_tmr); | ||
| 2783 | ndlp->nlp_initiator_tmr.function = lpfc_dev_loss_delay; | ||
| 2784 | ndlp->nlp_initiator_tmr.data = (unsigned long)ndlp; | ||
| 2785 | init_timer(&ndlp->nlp_delayfunc); | 2889 | init_timer(&ndlp->nlp_delayfunc); |
| 2786 | ndlp->nlp_delayfunc.function = lpfc_els_retry_delay; | 2890 | ndlp->nlp_delayfunc.function = lpfc_els_retry_delay; |
| 2787 | ndlp->nlp_delayfunc.data = (unsigned long)ndlp; | 2891 | ndlp->nlp_delayfunc.data = (unsigned long)ndlp; |
| @@ -2790,6 +2894,11 @@ lpfc_nlp_init(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 2790 | ndlp->nlp_sid = NLP_NO_SID; | 2894 | ndlp->nlp_sid = NLP_NO_SID; |
| 2791 | INIT_LIST_HEAD(&ndlp->nlp_listp); | 2895 | INIT_LIST_HEAD(&ndlp->nlp_listp); |
| 2792 | kref_init(&ndlp->kref); | 2896 | kref_init(&ndlp->kref); |
| 2897 | |||
| 2898 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_NODE, | ||
| 2899 | "node init: did:x%x", | ||
| 2900 | ndlp->nlp_DID, 0, 0); | ||
| 2901 | |||
| 2793 | return; | 2902 | return; |
| 2794 | } | 2903 | } |
| 2795 | 2904 | ||
| @@ -2798,6 +2907,11 @@ lpfc_nlp_release(struct kref *kref) | |||
| 2798 | { | 2907 | { |
| 2799 | struct lpfc_nodelist *ndlp = container_of(kref, struct lpfc_nodelist, | 2908 | struct lpfc_nodelist *ndlp = container_of(kref, struct lpfc_nodelist, |
| 2800 | kref); | 2909 | kref); |
| 2910 | |||
| 2911 | lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_NODE, | ||
| 2912 | "node release: did:x%x flg:x%x type:x%x", | ||
| 2913 | ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type); | ||
| 2914 | |||
| 2801 | lpfc_nlp_remove(ndlp->vport, ndlp); | 2915 | lpfc_nlp_remove(ndlp->vport, ndlp); |
| 2802 | mempool_free(ndlp, ndlp->vport->phba->nlp_mem_pool); | 2916 | mempool_free(ndlp, ndlp->vport->phba->nlp_mem_pool); |
| 2803 | } | 2917 | } |
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 7fab93d34367..c2fb59f595f3 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h | |||
| @@ -1278,6 +1278,7 @@ typedef struct { /* FireFly BIU registers */ | |||
| 1278 | #define MBX_KILL_BOARD 0x24 | 1278 | #define MBX_KILL_BOARD 0x24 |
| 1279 | #define MBX_CONFIG_FARP 0x25 | 1279 | #define MBX_CONFIG_FARP 0x25 |
| 1280 | #define MBX_BEACON 0x2A | 1280 | #define MBX_BEACON 0x2A |
| 1281 | #define MBX_HEARTBEAT 0x31 | ||
| 1281 | 1282 | ||
| 1282 | #define MBX_CONFIG_HBQ 0x7C | 1283 | #define MBX_CONFIG_HBQ 0x7C |
| 1283 | #define MBX_LOAD_AREA 0x81 | 1284 | #define MBX_LOAD_AREA 0x81 |
| @@ -1777,8 +1778,6 @@ typedef struct { | |||
| 1777 | #define LMT_4Gb 0x040 | 1778 | #define LMT_4Gb 0x040 |
| 1778 | #define LMT_8Gb 0x080 | 1779 | #define LMT_8Gb 0x080 |
| 1779 | #define LMT_10Gb 0x100 | 1780 | #define LMT_10Gb 0x100 |
| 1780 | |||
| 1781 | |||
| 1782 | uint32_t rsvd2; | 1781 | uint32_t rsvd2; |
| 1783 | uint32_t rsvd3; | 1782 | uint32_t rsvd3; |
| 1784 | uint32_t max_xri; | 1783 | uint32_t max_xri; |
| @@ -1787,7 +1786,10 @@ typedef struct { | |||
| 1787 | uint32_t avail_xri; | 1786 | uint32_t avail_xri; |
| 1788 | uint32_t avail_iocb; | 1787 | uint32_t avail_iocb; |
| 1789 | uint32_t avail_rpi; | 1788 | uint32_t avail_rpi; |
| 1790 | uint32_t default_rpi; | 1789 | uint32_t max_vpi; |
| 1790 | uint32_t rsvd4; | ||
| 1791 | uint32_t rsvd5; | ||
| 1792 | uint32_t avail_vpi; | ||
| 1791 | } READ_CONFIG_VAR; | 1793 | } READ_CONFIG_VAR; |
| 1792 | 1794 | ||
| 1793 | /* Structure for MB Command READ_RCONFIG (12) */ | 1795 | /* Structure for MB Command READ_RCONFIG (12) */ |
| @@ -3171,3 +3173,16 @@ lpfc_is_LC_HBA(unsigned short device) | |||
| 3171 | else | 3173 | else |
| 3172 | return 0; | 3174 | return 0; |
| 3173 | } | 3175 | } |
| 3176 | |||
| 3177 | /* | ||
| 3178 | * Determine if an IOCB failed because of a link event or firmware reset. | ||
| 3179 | */ | ||
| 3180 | |||
| 3181 | static inline int | ||
| 3182 | lpfc_error_lost_link(IOCB_t *iocbp) | ||
| 3183 | { | ||
| 3184 | return (iocbp->ulpStatus == IOSTAT_LOCAL_REJECT && | ||
| 3185 | (iocbp->un.ulpWord[4] == IOERR_SLI_ABORTED || | ||
| 3186 | iocbp->un.ulpWord[4] == IOERR_LINK_DOWN || | ||
| 3187 | iocbp->un.ulpWord[4] == IOERR_SLI_DOWN)); | ||
| 3188 | } | ||
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 4dd0f1aa09e8..350522cbf343 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
| @@ -391,6 +391,9 @@ lpfc_config_port_post(struct lpfc_hba *phba) | |||
| 391 | */ | 391 | */ |
| 392 | timeout = phba->fc_ratov << 1; | 392 | timeout = phba->fc_ratov << 1; |
| 393 | mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout); | 393 | mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout); |
| 394 | mod_timer(&phba->hb_tmofunc, jiffies + HZ * LPFC_HB_MBOX_INTERVAL); | ||
| 395 | phba->hb_outstanding = 0; | ||
| 396 | phba->last_completion_time = jiffies; | ||
| 394 | 397 | ||
| 395 | lpfc_init_link(phba, pmb, phba->cfg_topology, phba->cfg_link_speed); | 398 | lpfc_init_link(phba, pmb, phba->cfg_topology, phba->cfg_link_speed); |
| 396 | pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | 399 | pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; |
| @@ -485,6 +488,119 @@ lpfc_hba_down_post(struct lpfc_hba *phba) | |||
| 485 | return 0; | 488 | return 0; |
| 486 | } | 489 | } |
| 487 | 490 | ||
| 491 | /* HBA heart beat timeout handler */ | ||
| 492 | void | ||
| 493 | lpfc_hb_timeout(unsigned long ptr) | ||
| 494 | { | ||
| 495 | struct lpfc_hba *phba; | ||
| 496 | unsigned long iflag; | ||
| 497 | |||
| 498 | phba = (struct lpfc_hba *)ptr; | ||
| 499 | spin_lock_irqsave(&phba->pport->work_port_lock, iflag); | ||
| 500 | if (!(phba->pport->work_port_events & WORKER_HB_TMO)) | ||
| 501 | phba->pport->work_port_events |= WORKER_HB_TMO; | ||
| 502 | spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag); | ||
| 503 | |||
| 504 | if (phba->work_wait) | ||
| 505 | wake_up(phba->work_wait); | ||
| 506 | return; | ||
| 507 | } | ||
| 508 | |||
| 509 | static void | ||
| 510 | lpfc_hb_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq) | ||
| 511 | { | ||
| 512 | unsigned long drvr_flag; | ||
| 513 | |||
| 514 | spin_lock_irqsave(&phba->hbalock, drvr_flag); | ||
| 515 | phba->hb_outstanding = 0; | ||
| 516 | spin_unlock_irqrestore(&phba->hbalock, drvr_flag); | ||
| 517 | |||
| 518 | mempool_free(pmboxq, phba->mbox_mem_pool); | ||
| 519 | if (!(phba->pport->fc_flag & FC_OFFLINE_MODE) && | ||
| 520 | !(phba->link_state == LPFC_HBA_ERROR) && | ||
| 521 | !(phba->pport->fc_flag & FC_UNLOADING)) | ||
| 522 | mod_timer(&phba->hb_tmofunc, | ||
| 523 | jiffies + HZ * LPFC_HB_MBOX_INTERVAL); | ||
| 524 | return; | ||
| 525 | } | ||
| 526 | |||
| 527 | void | ||
| 528 | lpfc_hb_timeout_handler(struct lpfc_hba *phba) | ||
| 529 | { | ||
| 530 | LPFC_MBOXQ_t *pmboxq; | ||
| 531 | int retval; | ||
| 532 | struct lpfc_sli *psli = &phba->sli; | ||
| 533 | |||
| 534 | if ((phba->link_state == LPFC_HBA_ERROR) || | ||
| 535 | (phba->pport->fc_flag & FC_UNLOADING) || | ||
| 536 | (phba->pport->fc_flag & FC_OFFLINE_MODE)) | ||
| 537 | return; | ||
| 538 | |||
| 539 | spin_lock_irq(&phba->pport->work_port_lock); | ||
| 540 | /* If the timer is already canceled do nothing */ | ||
| 541 | if (!(phba->pport->work_port_events & WORKER_HB_TMO)) { | ||
| 542 | spin_unlock_irq(&phba->pport->work_port_lock); | ||
| 543 | return; | ||
| 544 | } | ||
| 545 | |||
| 546 | if (time_after(phba->last_completion_time + LPFC_HB_MBOX_INTERVAL * HZ, | ||
| 547 | jiffies)) { | ||
| 548 | spin_unlock_irq(&phba->pport->work_port_lock); | ||
| 549 | if (!phba->hb_outstanding) | ||
| 550 | mod_timer(&phba->hb_tmofunc, | ||
| 551 | jiffies + HZ * LPFC_HB_MBOX_INTERVAL); | ||
| 552 | else | ||
| 553 | mod_timer(&phba->hb_tmofunc, | ||
| 554 | jiffies + HZ * LPFC_HB_MBOX_TIMEOUT); | ||
| 555 | return; | ||
| 556 | } | ||
| 557 | spin_unlock_irq(&phba->pport->work_port_lock); | ||
| 558 | |||
| 559 | /* If there is no heart beat outstanding, issue a heartbeat command */ | ||
| 560 | if (!phba->hb_outstanding) { | ||
| 561 | pmboxq = mempool_alloc(phba->mbox_mem_pool,GFP_KERNEL); | ||
| 562 | if (!pmboxq) { | ||
| 563 | mod_timer(&phba->hb_tmofunc, | ||
| 564 | jiffies + HZ * LPFC_HB_MBOX_INTERVAL); | ||
| 565 | return; | ||
| 566 | } | ||
| 567 | |||
| 568 | lpfc_heart_beat(phba, pmboxq); | ||
| 569 | pmboxq->mbox_cmpl = lpfc_hb_mbox_cmpl; | ||
| 570 | pmboxq->vport = phba->pport; | ||
| 571 | retval = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT); | ||
| 572 | |||
| 573 | if (retval != MBX_BUSY && retval != MBX_SUCCESS) { | ||
| 574 | mempool_free(pmboxq, phba->mbox_mem_pool); | ||
| 575 | mod_timer(&phba->hb_tmofunc, | ||
| 576 | jiffies + HZ * LPFC_HB_MBOX_INTERVAL); | ||
| 577 | return; | ||
| 578 | } | ||
| 579 | mod_timer(&phba->hb_tmofunc, | ||
| 580 | jiffies + HZ * LPFC_HB_MBOX_TIMEOUT); | ||
| 581 | phba->hb_outstanding = 1; | ||
| 582 | return; | ||
| 583 | } else { | ||
| 584 | /* | ||
| 585 | * If heart beat timeout called with hb_outstanding set we | ||
| 586 | * need to take the HBA offline. | ||
| 587 | */ | ||
| 588 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
| 589 | "%d:0459 Adapter heartbeat failure, taking " | ||
| 590 | "this port offline.\n", phba->brd_no); | ||
| 591 | |||
| 592 | spin_lock_irq(&phba->hbalock); | ||
| 593 | psli->sli_flag &= ~LPFC_SLI2_ACTIVE; | ||
| 594 | spin_unlock_irq(&phba->hbalock); | ||
| 595 | |||
| 596 | lpfc_offline_prep(phba); | ||
| 597 | lpfc_offline(phba); | ||
| 598 | lpfc_unblock_mgmt_io(phba); | ||
| 599 | phba->link_state = LPFC_HBA_ERROR; | ||
| 600 | lpfc_hba_down_post(phba); | ||
| 601 | } | ||
| 602 | } | ||
| 603 | |||
| 488 | /************************************************************************/ | 604 | /************************************************************************/ |
| 489 | /* */ | 605 | /* */ |
| 490 | /* lpfc_handle_eratt */ | 606 | /* lpfc_handle_eratt */ |
| @@ -1190,9 +1306,6 @@ lpfc_cleanup(struct lpfc_vport *vport) | |||
| 1190 | lpfc_can_disctmo(vport); | 1306 | lpfc_can_disctmo(vport); |
| 1191 | list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) | 1307 | list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) |
| 1192 | lpfc_nlp_put(ndlp); | 1308 | lpfc_nlp_put(ndlp); |
| 1193 | |||
| 1194 | INIT_LIST_HEAD(&vport->fc_nodes); | ||
| 1195 | |||
| 1196 | return; | 1309 | return; |
| 1197 | } | 1310 | } |
| 1198 | 1311 | ||
| @@ -1238,6 +1351,8 @@ lpfc_stop_phba_timers(struct lpfc_hba *phba) | |||
| 1238 | lpfc_stop_vport_timers(vport); | 1351 | lpfc_stop_vport_timers(vport); |
| 1239 | del_timer_sync(&phba->sli.mbox_tmo); | 1352 | del_timer_sync(&phba->sli.mbox_tmo); |
| 1240 | del_timer_sync(&phba->fabric_block_timer); | 1353 | del_timer_sync(&phba->fabric_block_timer); |
| 1354 | phba->hb_outstanding = 0; | ||
| 1355 | del_timer_sync(&phba->hb_tmofunc); | ||
| 1241 | return; | 1356 | return; |
| 1242 | } | 1357 | } |
| 1243 | 1358 | ||
| @@ -1474,8 +1589,8 @@ destroy_port(struct lpfc_vport *vport) | |||
| 1474 | struct lpfc_hba *phba = vport->phba; | 1589 | struct lpfc_hba *phba = vport->phba; |
| 1475 | 1590 | ||
| 1476 | kfree(vport->vname); | 1591 | kfree(vport->vname); |
| 1477 | lpfc_free_sysfs_attr(vport); | ||
| 1478 | 1592 | ||
| 1593 | lpfc_debugfs_terminate(vport); | ||
| 1479 | fc_remove_host(shost); | 1594 | fc_remove_host(shost); |
| 1480 | scsi_remove_host(shost); | 1595 | scsi_remove_host(shost); |
| 1481 | 1596 | ||
| @@ -1500,50 +1615,29 @@ lpfc_get_instance(void) | |||
| 1500 | return instance; | 1615 | return instance; |
| 1501 | } | 1616 | } |
| 1502 | 1617 | ||
| 1503 | static void | 1618 | /* |
| 1504 | lpfc_remove_device(struct lpfc_vport *vport) | 1619 | * Note: there is no scan_start function as adapter initialization |
| 1505 | { | 1620 | * will have asynchronously kicked off the link initialization. |
| 1506 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 1621 | */ |
| 1507 | |||
| 1508 | lpfc_free_sysfs_attr(vport); | ||
| 1509 | |||
| 1510 | spin_lock_irq(shost->host_lock); | ||
| 1511 | vport->fc_flag |= FC_UNLOADING; | ||
| 1512 | spin_unlock_irq(shost->host_lock); | ||
| 1513 | |||
| 1514 | fc_remove_host(shost); | ||
| 1515 | scsi_remove_host(shost); | ||
| 1516 | } | ||
| 1517 | |||
| 1518 | void lpfc_scan_start(struct Scsi_Host *shost) | ||
| 1519 | { | ||
| 1520 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; | ||
| 1521 | struct lpfc_hba *phba = vport->phba; | ||
| 1522 | |||
| 1523 | if (lpfc_sli_hba_setup(phba)) | ||
| 1524 | goto error; | ||
| 1525 | |||
| 1526 | /* | ||
| 1527 | * hba setup may have changed the hba_queue_depth so we need to adjust | ||
| 1528 | * the value of can_queue. | ||
| 1529 | */ | ||
| 1530 | shost->can_queue = phba->cfg_hba_queue_depth - 10; | ||
| 1531 | return; | ||
| 1532 | |||
| 1533 | error: | ||
| 1534 | lpfc_remove_device(vport); | ||
| 1535 | } | ||
| 1536 | 1622 | ||
| 1537 | int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time) | 1623 | int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time) |
| 1538 | { | 1624 | { |
| 1539 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; | 1625 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; |
| 1540 | struct lpfc_hba *phba = vport->phba; | 1626 | struct lpfc_hba *phba = vport->phba; |
| 1627 | int stat = 0; | ||
| 1541 | 1628 | ||
| 1629 | spin_lock_irq(shost->host_lock); | ||
| 1630 | |||
| 1631 | if (vport->fc_flag & FC_UNLOADING) { | ||
| 1632 | stat = 1; | ||
| 1633 | goto finished; | ||
| 1634 | } | ||
| 1542 | if (time >= 30 * HZ) { | 1635 | if (time >= 30 * HZ) { |
| 1543 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | 1636 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, |
| 1544 | "%d:0461 Scanning longer than 30 " | 1637 | "%d:0461 Scanning longer than 30 " |
| 1545 | "seconds. Continuing initialization\n", | 1638 | "seconds. Continuing initialization\n", |
| 1546 | phba->brd_no); | 1639 | phba->brd_no); |
| 1640 | stat = 1; | ||
| 1547 | goto finished; | 1641 | goto finished; |
| 1548 | } | 1642 | } |
| 1549 | if (time >= 15 * HZ && phba->link_state <= LPFC_LINK_DOWN) { | 1643 | if (time >= 15 * HZ && phba->link_state <= LPFC_LINK_DOWN) { |
| @@ -1551,21 +1645,24 @@ int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time) | |||
| 1551 | "%d:0465 Link down longer than 15 " | 1645 | "%d:0465 Link down longer than 15 " |
| 1552 | "seconds. Continuing initialization\n", | 1646 | "seconds. Continuing initialization\n", |
| 1553 | phba->brd_no); | 1647 | phba->brd_no); |
| 1648 | stat = 1; | ||
| 1554 | goto finished; | 1649 | goto finished; |
| 1555 | } | 1650 | } |
| 1556 | 1651 | ||
| 1557 | if (vport->port_state != LPFC_VPORT_READY) | 1652 | if (vport->port_state != LPFC_VPORT_READY) |
| 1558 | return 0; | 1653 | goto finished; |
| 1559 | if (vport->num_disc_nodes || vport->fc_prli_sent) | 1654 | if (vport->num_disc_nodes || vport->fc_prli_sent) |
| 1560 | return 0; | 1655 | goto finished; |
| 1561 | if (vport->fc_map_cnt == 0 && time < 2 * HZ) | 1656 | if (vport->fc_map_cnt == 0 && time < 2 * HZ) |
| 1562 | return 0; | 1657 | goto finished; |
| 1563 | if ((phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE) != 0) | 1658 | if ((phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE) != 0) |
| 1564 | return 0; | 1659 | goto finished; |
| 1660 | |||
| 1661 | stat = 1; | ||
| 1565 | 1662 | ||
| 1566 | finished: | 1663 | finished: |
| 1567 | lpfc_host_attrib_init(shost); | 1664 | spin_unlock_irq(shost->host_lock); |
| 1568 | return 1; | 1665 | return stat; |
| 1569 | } | 1666 | } |
| 1570 | 1667 | ||
| 1571 | void lpfc_host_attrib_init(struct Scsi_Host *shost) | 1668 | void lpfc_host_attrib_init(struct Scsi_Host *shost) |
| @@ -1656,7 +1753,12 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
| 1656 | /* Initialize timers used by driver */ | 1753 | /* Initialize timers used by driver */ |
| 1657 | init_timer(&phba->fc_estabtmo); | 1754 | init_timer(&phba->fc_estabtmo); |
| 1658 | phba->fc_estabtmo.function = lpfc_establish_link_tmo; | 1755 | phba->fc_estabtmo.function = lpfc_establish_link_tmo; |
| 1659 | phba->fc_estabtmo.data = (unsigned long) phba; | 1756 | phba->fc_estabtmo.data = (unsigned long)phba; |
| 1757 | |||
| 1758 | init_timer(&phba->hb_tmofunc); | ||
| 1759 | phba->hb_tmofunc.function = lpfc_hb_timeout; | ||
| 1760 | phba->hb_tmofunc.data = (unsigned long)phba; | ||
| 1761 | |||
| 1660 | psli = &phba->sli; | 1762 | psli = &phba->sli; |
| 1661 | init_timer(&psli->mbox_tmo); | 1763 | init_timer(&psli->mbox_tmo); |
| 1662 | psli->mbox_tmo.function = lpfc_mbox_timeout; | 1764 | psli->mbox_tmo.function = lpfc_mbox_timeout; |
| @@ -1791,6 +1893,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
| 1791 | 1893 | ||
| 1792 | shost = lpfc_shost_from_vport(vport); | 1894 | shost = lpfc_shost_from_vport(vport); |
| 1793 | phba->pport = vport; | 1895 | phba->pport = vport; |
| 1896 | lpfc_debugfs_initialize(vport); | ||
| 1794 | 1897 | ||
| 1795 | pci_set_drvdata(pdev, shost); | 1898 | pci_set_drvdata(pdev, shost); |
| 1796 | 1899 | ||
| @@ -1820,15 +1923,32 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
| 1820 | if (lpfc_alloc_sysfs_attr(vport)) | 1923 | if (lpfc_alloc_sysfs_attr(vport)) |
| 1821 | goto out_free_irq; | 1924 | goto out_free_irq; |
| 1822 | 1925 | ||
| 1823 | scsi_scan_host(shost); | 1926 | if (lpfc_sli_hba_setup(phba)) |
| 1927 | goto out_remove_device; | ||
| 1928 | |||
| 1929 | /* | ||
| 1930 | * hba setup may have changed the hba_queue_depth so we need to adjust | ||
| 1931 | * the value of can_queue. | ||
| 1932 | */ | ||
| 1933 | shost->can_queue = phba->cfg_hba_queue_depth - 10; | ||
| 1934 | |||
| 1935 | lpfc_host_attrib_init(shost); | ||
| 1936 | |||
| 1824 | if (phba->cfg_poll & DISABLE_FCP_RING_INT) { | 1937 | if (phba->cfg_poll & DISABLE_FCP_RING_INT) { |
| 1825 | spin_lock_irq(shost->host_lock); | 1938 | spin_lock_irq(shost->host_lock); |
| 1826 | lpfc_poll_start_timer(phba); | 1939 | lpfc_poll_start_timer(phba); |
| 1827 | spin_unlock_irq(shost->host_lock); | 1940 | spin_unlock_irq(shost->host_lock); |
| 1828 | } | 1941 | } |
| 1829 | 1942 | ||
| 1943 | scsi_scan_host(shost); | ||
| 1944 | |||
| 1830 | return 0; | 1945 | return 0; |
| 1831 | 1946 | ||
| 1947 | out_remove_device: | ||
| 1948 | lpfc_free_sysfs_attr(vport); | ||
| 1949 | spin_lock_irq(shost->host_lock); | ||
| 1950 | vport->fc_flag |= FC_UNLOADING; | ||
| 1951 | spin_unlock_irq(shost->host_lock); | ||
| 1832 | out_free_irq: | 1952 | out_free_irq: |
| 1833 | lpfc_stop_phba_timers(phba); | 1953 | lpfc_stop_phba_timers(phba); |
| 1834 | phba->pport->work_port_events = 0; | 1954 | phba->pport->work_port_events = 0; |
| @@ -1865,6 +1985,8 @@ out_disable_device: | |||
| 1865 | pci_disable_device(pdev); | 1985 | pci_disable_device(pdev); |
| 1866 | out: | 1986 | out: |
| 1867 | pci_set_drvdata(pdev, NULL); | 1987 | pci_set_drvdata(pdev, NULL); |
| 1988 | if (shost) | ||
| 1989 | scsi_host_put(shost); | ||
| 1868 | return error; | 1990 | return error; |
| 1869 | } | 1991 | } |
| 1870 | 1992 | ||
| @@ -1878,6 +2000,12 @@ lpfc_pci_remove_one(struct pci_dev *pdev) | |||
| 1878 | list_for_each_entry(port_iterator, &phba->port_list, listentry) | 2000 | list_for_each_entry(port_iterator, &phba->port_list, listentry) |
| 1879 | port_iterator->load_flag |= FC_UNLOADING; | 2001 | port_iterator->load_flag |= FC_UNLOADING; |
| 1880 | 2002 | ||
| 2003 | kfree(vport->vname); | ||
| 2004 | lpfc_free_sysfs_attr(vport); | ||
| 2005 | |||
| 2006 | fc_remove_host(shost); | ||
| 2007 | scsi_remove_host(shost); | ||
| 2008 | |||
| 1881 | /* | 2009 | /* |
| 1882 | * Bring down the SLI Layer. This step disable all interrupts, | 2010 | * Bring down the SLI Layer. This step disable all interrupts, |
| 1883 | * clears the rings, discards all mailbox commands, and resets | 2011 | * clears the rings, discards all mailbox commands, and resets |
| @@ -1887,6 +2015,13 @@ lpfc_pci_remove_one(struct pci_dev *pdev) | |||
| 1887 | lpfc_sli_brdrestart(phba); | 2015 | lpfc_sli_brdrestart(phba); |
| 1888 | 2016 | ||
| 1889 | lpfc_stop_phba_timers(phba); | 2017 | lpfc_stop_phba_timers(phba); |
| 2018 | spin_lock_irq(&phba->hbalock); | ||
| 2019 | list_del_init(&vport->listentry); | ||
| 2020 | spin_unlock_irq(&phba->hbalock); | ||
| 2021 | |||
| 2022 | |||
| 2023 | lpfc_debugfs_terminate(vport); | ||
| 2024 | lpfc_cleanup(vport); | ||
| 1890 | 2025 | ||
| 1891 | kthread_stop(phba->worker_thread); | 2026 | kthread_stop(phba->worker_thread); |
| 1892 | 2027 | ||
| @@ -1894,9 +2029,8 @@ lpfc_pci_remove_one(struct pci_dev *pdev) | |||
| 1894 | free_irq(phba->pcidev->irq, phba); | 2029 | free_irq(phba->pcidev->irq, phba); |
| 1895 | pci_disable_msi(phba->pcidev); | 2030 | pci_disable_msi(phba->pcidev); |
| 1896 | 2031 | ||
| 1897 | destroy_port(vport); | ||
| 1898 | |||
| 1899 | pci_set_drvdata(pdev, NULL); | 2032 | pci_set_drvdata(pdev, NULL); |
| 2033 | scsi_host_put(shost); | ||
| 1900 | 2034 | ||
| 1901 | /* | 2035 | /* |
| 1902 | * Call scsi_free before mem_free since scsi bufs are released to their | 2036 | * Call scsi_free before mem_free since scsi bufs are released to their |
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 277eb6132e81..8f42fbfdd29e 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c | |||
| @@ -82,6 +82,22 @@ lpfc_read_nv(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | |||
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | /**********************************************/ | 84 | /**********************************************/ |
| 85 | /* lpfc_heart_beat Issue a HEART_BEAT */ | ||
| 86 | /* mailbox command */ | ||
| 87 | /**********************************************/ | ||
| 88 | void | ||
| 89 | lpfc_heart_beat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | ||
| 90 | { | ||
| 91 | MAILBOX_t *mb; | ||
| 92 | |||
| 93 | mb = &pmb->mb; | ||
| 94 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); | ||
| 95 | mb->mbxCommand = MBX_HEARTBEAT; | ||
| 96 | mb->mbxOwner = OWN_HOST; | ||
| 97 | return; | ||
| 98 | } | ||
| 99 | |||
| 100 | /**********************************************/ | ||
| 85 | /* lpfc_read_la Issue a READ LA */ | 101 | /* lpfc_read_la Issue a READ LA */ |
| 86 | /* mailbox command */ | 102 | /* mailbox command */ |
| 87 | /**********************************************/ | 103 | /**********************************************/ |
| @@ -676,7 +692,7 @@ lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
| 676 | if (phba->sli_rev == 3 && phba->vpd.sli3Feat.cerbm) { | 692 | if (phba->sli_rev == 3 && phba->vpd.sli3Feat.cerbm) { |
| 677 | mb->un.varCfgPort.cerbm = 1; /* Request HBQs */ | 693 | mb->un.varCfgPort.cerbm = 1; /* Request HBQs */ |
| 678 | mb->un.varCfgPort.max_hbq = 1; /* Requesting 2 HBQs */ | 694 | mb->un.varCfgPort.max_hbq = 1; /* Requesting 2 HBQs */ |
| 679 | if (phba->max_vpi && lpfc_npiv_enable && | 695 | if (phba->max_vpi && phba->cfg_npiv_enable && |
| 680 | phba->vpd.sli3Feat.cmv) { | 696 | phba->vpd.sli3Feat.cmv) { |
| 681 | mb->un.varCfgPort.max_vpi = phba->max_vpi; | 697 | mb->un.varCfgPort.max_vpi = phba->max_vpi; |
| 682 | mb->un.varCfgPort.cmv = 1; | 698 | mb->un.varCfgPort.cmv = 1; |
diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c index 6598e89627df..3594c469494f 100644 --- a/drivers/scsi/lpfc/lpfc_mem.c +++ b/drivers/scsi/lpfc/lpfc_mem.c | |||
| @@ -88,7 +88,8 @@ lpfc_mem_alloc(struct lpfc_hba * phba) | |||
| 88 | if (!phba->lpfc_hbq_pool) | 88 | if (!phba->lpfc_hbq_pool) |
| 89 | goto fail_free_nlp_mem_pool; | 89 | goto fail_free_nlp_mem_pool; |
| 90 | 90 | ||
| 91 | longs = (phba->max_vpi + BITS_PER_LONG - 1) / BITS_PER_LONG; | 91 | /* vpi zero is reserved for the physical port so add 1 to max */ |
| 92 | longs = ((phba->max_vpi + 1) + BITS_PER_LONG - 1) / BITS_PER_LONG; | ||
| 92 | phba->vpi_bmask = kzalloc(longs * sizeof(unsigned long), GFP_KERNEL); | 93 | phba->vpi_bmask = kzalloc(longs * sizeof(unsigned long), GFP_KERNEL); |
| 93 | if (!phba->vpi_bmask) | 94 | if (!phba->vpi_bmask) |
| 94 | goto fail_free_hbq_pool; | 95 | goto fail_free_hbq_pool; |
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 50a247602a6b..bca2f5c9b4ba 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #include "lpfc_logmsg.h" | 36 | #include "lpfc_logmsg.h" |
| 37 | #include "lpfc_crtn.h" | 37 | #include "lpfc_crtn.h" |
| 38 | #include "lpfc_vport.h" | 38 | #include "lpfc_vport.h" |
| 39 | #include "lpfc_debugfs.h" | ||
| 39 | 40 | ||
| 40 | 41 | ||
| 41 | /* Called to verify a rcv'ed ADISC was intended for us. */ | 42 | /* Called to verify a rcv'ed ADISC was intended for us. */ |
| @@ -204,11 +205,9 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) | |||
| 204 | /* First check the txq */ | 205 | /* First check the txq */ |
| 205 | spin_lock_irq(&phba->hbalock); | 206 | spin_lock_irq(&phba->hbalock); |
| 206 | list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) { | 207 | list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) { |
| 207 | /* Check to see if iocb matches the nport we are looking | 208 | /* Check to see if iocb matches the nport we are looking for */ |
| 208 | for */ | ||
| 209 | if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) { | 209 | if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) { |
| 210 | /* It matches, so deque and call compl with an | 210 | /* It matches, so deque and call compl with anp error */ |
| 211 | error */ | ||
| 212 | list_move_tail(&iocb->list, &completions); | 211 | list_move_tail(&iocb->list, &completions); |
| 213 | pring->txq_cnt--; | 212 | pring->txq_cnt--; |
| 214 | } | 213 | } |
| @@ -216,8 +215,7 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) | |||
| 216 | 215 | ||
| 217 | /* Next check the txcmplq */ | 216 | /* Next check the txcmplq */ |
| 218 | list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) { | 217 | list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) { |
| 219 | /* Check to see if iocb matches the nport we are looking | 218 | /* Check to see if iocb matches the nport we are looking for */ |
| 220 | for */ | ||
| 221 | if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) { | 219 | if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) { |
| 222 | lpfc_sli_issue_abort_iotag(phba, pring, iocb); | 220 | lpfc_sli_issue_abort_iotag(phba, pring, iocb); |
| 223 | } | 221 | } |
| @@ -282,7 +280,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 282 | stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY; | 280 | stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY; |
| 283 | stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; | 281 | stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; |
| 284 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, | 282 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, |
| 285 | ndlp); | 283 | ndlp, NULL); |
| 286 | return 0; | 284 | return 0; |
| 287 | } | 285 | } |
| 288 | } | 286 | } |
| @@ -293,7 +291,8 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 293 | /* Reject this request because invalid parameters */ | 291 | /* Reject this request because invalid parameters */ |
| 294 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | 292 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; |
| 295 | stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS; | 293 | stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS; |
| 296 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp); | 294 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, |
| 295 | NULL); | ||
| 297 | return 0; | 296 | return 0; |
| 298 | } | 297 | } |
| 299 | icmd = &cmdiocb->iocb; | 298 | icmd = &cmdiocb->iocb; |
| @@ -392,13 +391,30 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 392 | lpfc_els_abort(phba, ndlp); | 391 | lpfc_els_abort(phba, ndlp); |
| 393 | } | 392 | } |
| 394 | 393 | ||
| 394 | if ((vport->port_type == LPFC_NPIV_PORT && | ||
| 395 | phba->cfg_vport_restrict_login)) { | ||
| 396 | |||
| 397 | /* In order to preserve RPIs, we want to cleanup | ||
| 398 | * the default RPI the firmware created to rcv | ||
| 399 | * this ELS request. The only way to do this is | ||
| 400 | * to register, then unregister the RPI. | ||
| 401 | */ | ||
| 402 | spin_lock_irq(shost->host_lock); | ||
| 403 | ndlp->nlp_flag |= NLP_RM_DFLT_RPI; | ||
| 404 | spin_unlock_irq(shost->host_lock); | ||
| 405 | stat.un.b.lsRjtRsnCode = LSRJT_INVALID_CMD; | ||
| 406 | stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; | ||
| 407 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, | ||
| 408 | ndlp, mbox); | ||
| 409 | return 1; | ||
| 410 | } | ||
| 395 | lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox, 0); | 411 | lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox, 0); |
| 396 | return 1; | 412 | return 1; |
| 397 | 413 | ||
| 398 | out: | 414 | out: |
| 399 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | 415 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; |
| 400 | stat.un.b.lsRjtRsnCodeExp = LSEXP_OUT_OF_RESOURCE; | 416 | stat.un.b.lsRjtRsnCodeExp = LSEXP_OUT_OF_RESOURCE; |
| 401 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp); | 417 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL); |
| 402 | return 0; | 418 | return 0; |
| 403 | } | 419 | } |
| 404 | 420 | ||
| @@ -445,7 +461,7 @@ lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 445 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | 461 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; |
| 446 | stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS; | 462 | stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS; |
| 447 | stat.un.b.vendorUnique = 0; | 463 | stat.un.b.vendorUnique = 0; |
| 448 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp); | 464 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL); |
| 449 | 465 | ||
| 450 | /* 1 sec timeout */ | 466 | /* 1 sec timeout */ |
| 451 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ); | 467 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ); |
| @@ -535,6 +551,11 @@ lpfc_rcv_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 535 | roles |= FC_RPORT_ROLE_FCP_INITIATOR; | 551 | roles |= FC_RPORT_ROLE_FCP_INITIATOR; |
| 536 | if (ndlp->nlp_type & NLP_FCP_TARGET) | 552 | if (ndlp->nlp_type & NLP_FCP_TARGET) |
| 537 | roles |= FC_RPORT_ROLE_FCP_TARGET; | 553 | roles |= FC_RPORT_ROLE_FCP_TARGET; |
| 554 | |||
| 555 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT, | ||
| 556 | "rport rolechg: role:x%x did:x%x flg:x%x", | ||
| 557 | roles, ndlp->nlp_DID, ndlp->nlp_flag); | ||
| 558 | |||
| 538 | fc_remote_port_rolechg(rport, roles); | 559 | fc_remote_port_rolechg(rport, roles); |
| 539 | } | 560 | } |
| 540 | } | 561 | } |
| @@ -657,7 +678,8 @@ lpfc_rcv_plogi_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 657 | ours */ | 678 | ours */ |
| 658 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | 679 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; |
| 659 | stat.un.b.lsRjtRsnCodeExp = LSEXP_CMD_IN_PROGRESS; | 680 | stat.un.b.lsRjtRsnCodeExp = LSEXP_CMD_IN_PROGRESS; |
| 660 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp); | 681 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, |
| 682 | NULL); | ||
| 661 | } else { | 683 | } else { |
| 662 | lpfc_rcv_plogi(vport, ndlp, cmdiocb); | 684 | lpfc_rcv_plogi(vport, ndlp, cmdiocb); |
| 663 | } /* If our portname was less */ | 685 | } /* If our portname was less */ |
| @@ -675,7 +697,7 @@ lpfc_rcv_prli_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 675 | memset(&stat, 0, sizeof (struct ls_rjt)); | 697 | memset(&stat, 0, sizeof (struct ls_rjt)); |
| 676 | stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY; | 698 | stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY; |
| 677 | stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; | 699 | stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; |
| 678 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp); | 700 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL); |
| 679 | return ndlp->nlp_state; | 701 | return ndlp->nlp_state; |
| 680 | } | 702 | } |
| 681 | 703 | ||
| @@ -1335,6 +1357,10 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 1335 | 1357 | ||
| 1336 | irsp = &rspiocb->iocb; | 1358 | irsp = &rspiocb->iocb; |
| 1337 | if (irsp->ulpStatus) { | 1359 | if (irsp->ulpStatus) { |
| 1360 | if ((vport->port_type == LPFC_NPIV_PORT) && | ||
| 1361 | phba->cfg_vport_restrict_login) { | ||
| 1362 | goto out; | ||
| 1363 | } | ||
| 1338 | ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE; | 1364 | ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE; |
| 1339 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); | 1365 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); |
| 1340 | return ndlp->nlp_state; | 1366 | return ndlp->nlp_state; |
| @@ -1355,6 +1381,7 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 1355 | if (!(ndlp->nlp_type & NLP_FCP_TARGET) && | 1381 | if (!(ndlp->nlp_type & NLP_FCP_TARGET) && |
| 1356 | (vport->port_type == LPFC_NPIV_PORT) && | 1382 | (vport->port_type == LPFC_NPIV_PORT) && |
| 1357 | phba->cfg_vport_restrict_login) { | 1383 | phba->cfg_vport_restrict_login) { |
| 1384 | out: | ||
| 1358 | spin_lock_irq(shost->host_lock); | 1385 | spin_lock_irq(shost->host_lock); |
| 1359 | ndlp->nlp_flag |= NLP_TARGET_REMOVE; | 1386 | ndlp->nlp_flag |= NLP_TARGET_REMOVE; |
| 1360 | spin_unlock_irq(shost->host_lock); | 1387 | spin_unlock_irq(shost->host_lock); |
| @@ -1606,7 +1633,7 @@ lpfc_rcv_plogi_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 1606 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; | 1633 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; |
| 1607 | 1634 | ||
| 1608 | /* Ignore PLOGI if we have an outstanding LOGO */ | 1635 | /* Ignore PLOGI if we have an outstanding LOGO */ |
| 1609 | if (ndlp->nlp_flag & NLP_LOGO_SND) { | 1636 | if (ndlp->nlp_flag & (NLP_LOGO_SND | NLP_LOGO_ACC)) { |
| 1610 | return ndlp->nlp_state; | 1637 | return ndlp->nlp_state; |
| 1611 | } | 1638 | } |
| 1612 | 1639 | ||
| @@ -1638,7 +1665,7 @@ lpfc_rcv_prli_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 1638 | memset(&stat, 0, sizeof (struct ls_rjt)); | 1665 | memset(&stat, 0, sizeof (struct ls_rjt)); |
| 1639 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | 1666 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; |
| 1640 | stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; | 1667 | stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; |
| 1641 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp); | 1668 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL); |
| 1642 | 1669 | ||
| 1643 | if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) { | 1670 | if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) { |
| 1644 | if (ndlp->nlp_flag & NLP_NPR_ADISC) { | 1671 | if (ndlp->nlp_flag & NLP_NPR_ADISC) { |
| @@ -2035,6 +2062,10 @@ lpfc_disc_state_machine(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 2035 | phba->brd_no, vport->vpi, | 2062 | phba->brd_no, vport->vpi, |
| 2036 | evt, ndlp->nlp_DID, cur_state, ndlp->nlp_flag); | 2063 | evt, ndlp->nlp_DID, cur_state, ndlp->nlp_flag); |
| 2037 | 2064 | ||
| 2065 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM, | ||
| 2066 | "DSM in: evt:%d ste:%d did:x%x", | ||
| 2067 | evt, cur_state, ndlp->nlp_DID); | ||
| 2068 | |||
| 2038 | func = lpfc_disc_action[(cur_state * NLP_EVT_MAX_EVENT) + evt]; | 2069 | func = lpfc_disc_action[(cur_state * NLP_EVT_MAX_EVENT) + evt]; |
| 2039 | rc = (func) (vport, ndlp, arg, evt); | 2070 | rc = (func) (vport, ndlp, arg, evt); |
| 2040 | 2071 | ||
| @@ -2045,6 +2076,10 @@ lpfc_disc_state_machine(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 2045 | phba->brd_no, vport->vpi, | 2076 | phba->brd_no, vport->vpi, |
| 2046 | rc, ndlp->nlp_DID, ndlp->nlp_flag); | 2077 | rc, ndlp->nlp_DID, ndlp->nlp_flag); |
| 2047 | 2078 | ||
| 2079 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM, | ||
| 2080 | "DSM out: ste:%d did:x%x flg:x%x", | ||
| 2081 | rc, ndlp->nlp_DID, ndlp->nlp_flag); | ||
| 2082 | |||
| 2048 | lpfc_nlp_put(ndlp); | 2083 | lpfc_nlp_put(ndlp); |
| 2049 | 2084 | ||
| 2050 | return rc; | 2085 | return rc; |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index af8f8968bfba..2de4c4e1cd80 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
| @@ -1532,7 +1532,6 @@ struct scsi_host_template lpfc_template = { | |||
| 1532 | .slave_configure = lpfc_slave_configure, | 1532 | .slave_configure = lpfc_slave_configure, |
| 1533 | .slave_destroy = lpfc_slave_destroy, | 1533 | .slave_destroy = lpfc_slave_destroy, |
| 1534 | .scan_finished = lpfc_scan_finished, | 1534 | .scan_finished = lpfc_scan_finished, |
| 1535 | .scan_start = lpfc_scan_start, | ||
| 1536 | .this_id = -1, | 1535 | .this_id = -1, |
| 1537 | .sg_tablesize = LPFC_SG_SEG_CNT, | 1536 | .sg_tablesize = LPFC_SG_SEG_CNT, |
| 1538 | .cmd_per_lun = LPFC_CMD_PER_LUN, | 1537 | .cmd_per_lun = LPFC_CMD_PER_LUN, |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index a2927dc3161f..f4d5a6b00fde 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | #include "lpfc_crtn.h" | 38 | #include "lpfc_crtn.h" |
| 39 | #include "lpfc_logmsg.h" | 39 | #include "lpfc_logmsg.h" |
| 40 | #include "lpfc_compat.h" | 40 | #include "lpfc_compat.h" |
| 41 | #include "lpfc_debugfs.h" | ||
| 41 | 42 | ||
| 42 | /* | 43 | /* |
| 43 | * Define macro to log: Mailbox command x%x cannot issue Data | 44 | * Define macro to log: Mailbox command x%x cannot issue Data |
| @@ -269,20 +270,11 @@ lpfc_sli_ringtxcmpl_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
| 269 | static struct lpfc_iocbq * | 270 | static struct lpfc_iocbq * |
| 270 | lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) | 271 | lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) |
| 271 | { | 272 | { |
| 272 | struct list_head *dlp; | ||
| 273 | struct lpfc_iocbq *cmd_iocb; | 273 | struct lpfc_iocbq *cmd_iocb; |
| 274 | 274 | ||
| 275 | dlp = &pring->txq; | 275 | list_remove_head((&pring->txq), cmd_iocb, struct lpfc_iocbq, list); |
| 276 | cmd_iocb = NULL; | 276 | if (cmd_iocb != NULL) |
| 277 | list_remove_head((&pring->txq), cmd_iocb, | ||
| 278 | struct lpfc_iocbq, | ||
| 279 | list); | ||
| 280 | if (cmd_iocb) { | ||
| 281 | /* If the first ptr is not equal to the list header, | ||
| 282 | * deque the IOCBQ_t and return it. | ||
| 283 | */ | ||
| 284 | pring->txq_cnt--; | 277 | pring->txq_cnt--; |
| 285 | } | ||
| 286 | return cmd_iocb; | 278 | return cmd_iocb; |
| 287 | } | 279 | } |
| 288 | 280 | ||
| @@ -736,6 +728,7 @@ lpfc_sli_chk_mbx_command(uint8_t mbxCommand) | |||
| 736 | case MBX_LOAD_EXP_ROM: | 728 | case MBX_LOAD_EXP_ROM: |
| 737 | case MBX_REG_VPI: | 729 | case MBX_REG_VPI: |
| 738 | case MBX_UNREG_VPI: | 730 | case MBX_UNREG_VPI: |
| 731 | case MBX_HEARTBEAT: | ||
| 739 | ret = mbxCommand; | 732 | ret = mbxCommand; |
| 740 | break; | 733 | break; |
| 741 | default: | 734 | default: |
| @@ -748,15 +741,18 @@ static void | |||
| 748 | lpfc_sli_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) | 741 | lpfc_sli_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) |
| 749 | { | 742 | { |
| 750 | wait_queue_head_t *pdone_q; | 743 | wait_queue_head_t *pdone_q; |
| 744 | unsigned long drvr_flag; | ||
| 751 | 745 | ||
| 752 | /* | 746 | /* |
| 753 | * If pdone_q is empty, the driver thread gave up waiting and | 747 | * If pdone_q is empty, the driver thread gave up waiting and |
| 754 | * continued running. | 748 | * continued running. |
| 755 | */ | 749 | */ |
| 756 | pmboxq->mbox_flag |= LPFC_MBX_WAKE; | 750 | pmboxq->mbox_flag |= LPFC_MBX_WAKE; |
| 751 | spin_lock_irqsave(&phba->hbalock, drvr_flag); | ||
| 757 | pdone_q = (wait_queue_head_t *) pmboxq->context1; | 752 | pdone_q = (wait_queue_head_t *) pmboxq->context1; |
| 758 | if (pdone_q) | 753 | if (pdone_q) |
| 759 | wake_up_interruptible(pdone_q); | 754 | wake_up_interruptible(pdone_q); |
| 755 | spin_unlock_irqrestore(&phba->hbalock, drvr_flag); | ||
| 760 | return; | 756 | return; |
| 761 | } | 757 | } |
| 762 | 758 | ||
| @@ -817,6 +813,25 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba) | |||
| 817 | 813 | ||
| 818 | pmbox = &pmb->mb; | 814 | pmbox = &pmb->mb; |
| 819 | 815 | ||
| 816 | if (pmbox->mbxCommand != MBX_HEARTBEAT) { | ||
| 817 | if (pmb->vport) { | ||
| 818 | lpfc_debugfs_disc_trc(pmb->vport, | ||
| 819 | LPFC_DISC_TRC_MBOX_VPORT, | ||
| 820 | "MBOX cmpl vport: cmd:x%x mb:x%x x%x", | ||
| 821 | (uint32_t)pmbox->mbxCommand, | ||
| 822 | pmbox->un.varWords[0], | ||
| 823 | pmbox->un.varWords[1]); | ||
| 824 | } | ||
| 825 | else { | ||
| 826 | lpfc_debugfs_disc_trc(phba->pport, | ||
| 827 | LPFC_DISC_TRC_MBOX, | ||
| 828 | "MBOX cmpl: cmd:x%x mb:x%x x%x", | ||
| 829 | (uint32_t)pmbox->mbxCommand, | ||
| 830 | pmbox->un.varWords[0], | ||
| 831 | pmbox->un.varWords[1]); | ||
| 832 | } | ||
| 833 | } | ||
| 834 | |||
| 820 | /* | 835 | /* |
| 821 | * It is a fatal error if unknown mbox command completion. | 836 | * It is a fatal error if unknown mbox command completion. |
| 822 | */ | 837 | */ |
| @@ -1309,6 +1324,7 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba, | |||
| 1309 | * network byte order and pci byte orders are different. | 1324 | * network byte order and pci byte orders are different. |
| 1310 | */ | 1325 | */ |
| 1311 | entry = lpfc_resp_iocb(phba, pring); | 1326 | entry = lpfc_resp_iocb(phba, pring); |
| 1327 | phba->last_completion_time = jiffies; | ||
| 1312 | 1328 | ||
| 1313 | if (++pring->rspidx >= portRspMax) | 1329 | if (++pring->rspidx >= portRspMax) |
| 1314 | pring->rspidx = 0; | 1330 | pring->rspidx = 0; |
| @@ -1511,6 +1527,7 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba, | |||
| 1511 | */ | 1527 | */ |
| 1512 | entry = lpfc_resp_iocb(phba, pring); | 1528 | entry = lpfc_resp_iocb(phba, pring); |
| 1513 | 1529 | ||
| 1530 | phba->last_completion_time = jiffies; | ||
| 1514 | rspiocbp = __lpfc_sli_get_iocbq(phba); | 1531 | rspiocbp = __lpfc_sli_get_iocbq(phba); |
| 1515 | if (rspiocbp == NULL) { | 1532 | if (rspiocbp == NULL) { |
| 1516 | printk(KERN_ERR "%s: out of buffers! Failing " | 1533 | printk(KERN_ERR "%s: out of buffers! Failing " |
| @@ -2304,7 +2321,7 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba) | |||
| 2304 | 2321 | ||
| 2305 | switch (lpfc_sli_mode) { | 2322 | switch (lpfc_sli_mode) { |
| 2306 | case 2: | 2323 | case 2: |
| 2307 | if (lpfc_npiv_enable) { | 2324 | if (phba->cfg_npiv_enable) { |
| 2308 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT, | 2325 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT, |
| 2309 | "%d:1824 NPIV enabled: Override lpfc_sli_mode " | 2326 | "%d:1824 NPIV enabled: Override lpfc_sli_mode " |
| 2310 | "parameter (%d) to auto (0).\n", | 2327 | "parameter (%d) to auto (0).\n", |
| @@ -2573,6 +2590,21 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag) | |||
| 2573 | psli->slistat.mbox_busy++; | 2590 | psli->slistat.mbox_busy++; |
| 2574 | spin_unlock_irqrestore(&phba->hbalock, drvr_flag); | 2591 | spin_unlock_irqrestore(&phba->hbalock, drvr_flag); |
| 2575 | 2592 | ||
| 2593 | if (pmbox->vport) { | ||
| 2594 | lpfc_debugfs_disc_trc(pmbox->vport, | ||
| 2595 | LPFC_DISC_TRC_MBOX_VPORT, | ||
| 2596 | "MBOX Bsy vport: cmd:x%x mb:x%x x%x", | ||
| 2597 | (uint32_t)mb->mbxCommand, | ||
| 2598 | mb->un.varWords[0], mb->un.varWords[1]); | ||
| 2599 | } | ||
| 2600 | else { | ||
| 2601 | lpfc_debugfs_disc_trc(phba->pport, | ||
| 2602 | LPFC_DISC_TRC_MBOX, | ||
| 2603 | "MBOX Bsy: cmd:x%x mb:x%x x%x", | ||
| 2604 | (uint32_t)mb->mbxCommand, | ||
| 2605 | mb->un.varWords[0], mb->un.varWords[1]); | ||
| 2606 | } | ||
| 2607 | |||
| 2576 | return MBX_BUSY; | 2608 | return MBX_BUSY; |
| 2577 | } | 2609 | } |
| 2578 | 2610 | ||
| @@ -2618,6 +2650,23 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag) | |||
| 2618 | mb->mbxCommand, phba->pport->port_state, | 2650 | mb->mbxCommand, phba->pport->port_state, |
| 2619 | psli->sli_flag, flag); | 2651 | psli->sli_flag, flag); |
| 2620 | 2652 | ||
| 2653 | if (mb->mbxCommand != MBX_HEARTBEAT) { | ||
| 2654 | if (pmbox->vport) { | ||
| 2655 | lpfc_debugfs_disc_trc(pmbox->vport, | ||
| 2656 | LPFC_DISC_TRC_MBOX_VPORT, | ||
| 2657 | "MBOX Send vport: cmd:x%x mb:x%x x%x", | ||
| 2658 | (uint32_t)mb->mbxCommand, | ||
| 2659 | mb->un.varWords[0], mb->un.varWords[1]); | ||
| 2660 | } | ||
| 2661 | else { | ||
| 2662 | lpfc_debugfs_disc_trc(phba->pport, | ||
| 2663 | LPFC_DISC_TRC_MBOX, | ||
| 2664 | "MBOX Send: cmd:x%x mb:x%x x%x", | ||
| 2665 | (uint32_t)mb->mbxCommand, | ||
| 2666 | mb->un.varWords[0], mb->un.varWords[1]); | ||
| 2667 | } | ||
| 2668 | } | ||
| 2669 | |||
| 2621 | psli->slistat.mbox_cmd++; | 2670 | psli->slistat.mbox_cmd++; |
| 2622 | evtctr = psli->slistat.mbox_event; | 2671 | evtctr = psli->slistat.mbox_event; |
| 2623 | 2672 | ||
| @@ -2760,14 +2809,13 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag) | |||
| 2760 | /* | 2809 | /* |
| 2761 | * Caller needs to hold lock. | 2810 | * Caller needs to hold lock. |
| 2762 | */ | 2811 | */ |
| 2763 | static int | 2812 | static void |
| 2764 | __lpfc_sli_ringtx_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | 2813 | __lpfc_sli_ringtx_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, |
| 2765 | struct lpfc_iocbq *piocb) | 2814 | struct lpfc_iocbq *piocb) |
| 2766 | { | 2815 | { |
| 2767 | /* Insert the caller's iocb in the txq tail for later processing. */ | 2816 | /* Insert the caller's iocb in the txq tail for later processing. */ |
| 2768 | list_add_tail(&piocb->list, &pring->txq); | 2817 | list_add_tail(&piocb->list, &pring->txq); |
| 2769 | pring->txq_cnt++; | 2818 | pring->txq_cnt++; |
| 2770 | return 0; | ||
| 2771 | } | 2819 | } |
| 2772 | 2820 | ||
| 2773 | static struct lpfc_iocbq * | 2821 | static struct lpfc_iocbq * |
| @@ -3074,11 +3122,11 @@ lpfc_sli_queue_setup(struct lpfc_hba *phba) | |||
| 3074 | int | 3122 | int |
| 3075 | lpfc_sli_host_down(struct lpfc_vport *vport) | 3123 | lpfc_sli_host_down(struct lpfc_vport *vport) |
| 3076 | { | 3124 | { |
| 3125 | LIST_HEAD(completions); | ||
| 3077 | struct lpfc_hba *phba = vport->phba; | 3126 | struct lpfc_hba *phba = vport->phba; |
| 3078 | struct lpfc_sli *psli = &phba->sli; | 3127 | struct lpfc_sli *psli = &phba->sli; |
| 3079 | struct lpfc_sli_ring *pring; | 3128 | struct lpfc_sli_ring *pring; |
| 3080 | struct lpfc_iocbq *iocb, *next_iocb; | 3129 | struct lpfc_iocbq *iocb, *next_iocb; |
| 3081 | IOCB_t *icmd = NULL; | ||
| 3082 | int i; | 3130 | int i; |
| 3083 | unsigned long flags = 0; | 3131 | unsigned long flags = 0; |
| 3084 | uint16_t prev_pring_flag; | 3132 | uint16_t prev_pring_flag; |
| @@ -3086,31 +3134,20 @@ lpfc_sli_host_down(struct lpfc_vport *vport) | |||
| 3086 | lpfc_cleanup_discovery_resources(vport); | 3134 | lpfc_cleanup_discovery_resources(vport); |
| 3087 | 3135 | ||
| 3088 | spin_lock_irqsave(&phba->hbalock, flags); | 3136 | spin_lock_irqsave(&phba->hbalock, flags); |
| 3089 | |||
| 3090 | for (i = 0; i < psli->num_rings; i++) { | 3137 | for (i = 0; i < psli->num_rings; i++) { |
| 3091 | pring = &psli->ring[i]; | 3138 | pring = &psli->ring[i]; |
| 3092 | prev_pring_flag = pring->flag; | 3139 | prev_pring_flag = pring->flag; |
| 3093 | pring->flag |= LPFC_DEFERRED_RING_EVENT; | 3140 | if (pring->ringno == LPFC_ELS_RING) /* Only slow rings */ |
| 3094 | 3141 | pring->flag |= LPFC_DEFERRED_RING_EVENT; | |
| 3095 | /* | 3142 | /* |
| 3096 | * Error everything on the txq since these iocbs have not been | 3143 | * Error everything on the txq since these iocbs have not been |
| 3097 | * given to the FW yet. | 3144 | * given to the FW yet. |
| 3098 | */ | 3145 | */ |
| 3099 | |||
| 3100 | list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) { | 3146 | list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) { |
| 3101 | if (iocb->vport != vport) | 3147 | if (iocb->vport != vport) |
| 3102 | continue; | 3148 | continue; |
| 3103 | list_del_init(&iocb->list); | 3149 | list_move_tail(&iocb->list, &completions); |
| 3104 | pring->txq_cnt--; | 3150 | pring->txq_cnt--; |
| 3105 | if (iocb->iocb_cmpl) { | ||
| 3106 | icmd = &iocb->iocb; | ||
| 3107 | icmd->ulpStatus = IOSTAT_LOCAL_REJECT; | ||
| 3108 | icmd->un.ulpWord[4] = IOERR_SLI_DOWN; | ||
| 3109 | spin_unlock_irqrestore(&phba->hbalock, flags); | ||
| 3110 | (iocb->iocb_cmpl) (phba, iocb, iocb); | ||
| 3111 | spin_lock_irqsave(&phba->hbalock, flags); | ||
| 3112 | } else | ||
| 3113 | lpfc_sli_release_iocbq(phba, iocb); | ||
| 3114 | } | 3151 | } |
| 3115 | 3152 | ||
| 3116 | /* Next issue ABTS for everything on the txcmplq */ | 3153 | /* Next issue ABTS for everything on the txcmplq */ |
| @@ -3126,6 +3163,17 @@ lpfc_sli_host_down(struct lpfc_vport *vport) | |||
| 3126 | 3163 | ||
| 3127 | spin_unlock_irqrestore(&phba->hbalock, flags); | 3164 | spin_unlock_irqrestore(&phba->hbalock, flags); |
| 3128 | 3165 | ||
| 3166 | while (!list_empty(&completions)) { | ||
| 3167 | list_remove_head(&completions, iocb, struct lpfc_iocbq, list); | ||
| 3168 | |||
| 3169 | if (!iocb->iocb_cmpl) | ||
| 3170 | lpfc_sli_release_iocbq(phba, iocb); | ||
| 3171 | else { | ||
| 3172 | iocb->iocb.ulpStatus = IOSTAT_LOCAL_REJECT; | ||
| 3173 | iocb->iocb.un.ulpWord[4] = IOERR_SLI_DOWN; | ||
| 3174 | (iocb->iocb_cmpl) (phba, iocb, iocb); | ||
| 3175 | } | ||
| 3176 | } | ||
| 3129 | return 1; | 3177 | return 1; |
| 3130 | } | 3178 | } |
| 3131 | 3179 | ||
| @@ -3148,7 +3196,8 @@ lpfc_sli_hba_down(struct lpfc_hba *phba) | |||
| 3148 | spin_lock_irqsave(&phba->hbalock, flags); | 3196 | spin_lock_irqsave(&phba->hbalock, flags); |
| 3149 | for (i = 0; i < psli->num_rings; i++) { | 3197 | for (i = 0; i < psli->num_rings; i++) { |
| 3150 | pring = &psli->ring[i]; | 3198 | pring = &psli->ring[i]; |
| 3151 | pring->flag |= LPFC_DEFERRED_RING_EVENT; | 3199 | if (pring->ringno == LPFC_ELS_RING) /* Only slow rings */ |
| 3200 | pring->flag |= LPFC_DEFERRED_RING_EVENT; | ||
| 3152 | 3201 | ||
| 3153 | /* | 3202 | /* |
| 3154 | * Error everything on the txq since these iocbs have not been | 3203 | * Error everything on the txq since these iocbs have not been |
| @@ -3326,8 +3375,10 @@ lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
| 3326 | "x%x x%x x%x\n", | 3375 | "x%x x%x x%x\n", |
| 3327 | phba->brd_no, irsp->ulpIoTag, irsp->ulpStatus, | 3376 | phba->brd_no, irsp->ulpIoTag, irsp->ulpStatus, |
| 3328 | irsp->un.ulpWord[4], irsp->ulpTimeout); | 3377 | irsp->un.ulpWord[4], irsp->ulpTimeout); |
| 3329 | 3378 | if (cmdiocb->iocb.ulpCommand == CMD_GEN_REQUEST64_CR) | |
| 3330 | lpfc_els_free_iocb(phba, cmdiocb); | 3379 | lpfc_ct_free_iocb(phba, cmdiocb); |
| 3380 | else | ||
| 3381 | lpfc_els_free_iocb(phba, cmdiocb); | ||
| 3331 | return; | 3382 | return; |
| 3332 | } | 3383 | } |
| 3333 | 3384 | ||
| @@ -3352,10 +3403,11 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
| 3352 | (cmdiocb->iocb_flag & LPFC_DRIVER_ABORTED) != 0) | 3403 | (cmdiocb->iocb_flag & LPFC_DRIVER_ABORTED) != 0) |
| 3353 | return 0; | 3404 | return 0; |
| 3354 | 3405 | ||
| 3355 | /* If we're unloading, don't abort the iocb, but change the callback so | 3406 | /* If we're unloading, don't abort iocb on the ELS ring, but change the |
| 3356 | * that nothing happens when it finishes. | 3407 | * callback so that nothing happens when it finishes. |
| 3357 | */ | 3408 | */ |
| 3358 | if (vport->load_flag & FC_UNLOADING) { | 3409 | if ((vport->load_flag & FC_UNLOADING) && |
| 3410 | (pring->ringno == LPFC_ELS_RING)) { | ||
| 3359 | if (cmdiocb->iocb_flag & LPFC_IO_FABRIC) | 3411 | if (cmdiocb->iocb_flag & LPFC_IO_FABRIC) |
| 3360 | cmdiocb->fabric_iocb_cmpl = lpfc_ignore_els_cmpl; | 3412 | cmdiocb->fabric_iocb_cmpl = lpfc_ignore_els_cmpl; |
| 3361 | else | 3413 | else |
| @@ -3540,9 +3592,9 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba, | |||
| 3540 | &rspiocbq->iocb, sizeof(IOCB_t)); | 3592 | &rspiocbq->iocb, sizeof(IOCB_t)); |
| 3541 | 3593 | ||
| 3542 | pdone_q = cmdiocbq->context_un.wait_queue; | 3594 | pdone_q = cmdiocbq->context_un.wait_queue; |
| 3543 | spin_unlock_irqrestore(&phba->hbalock, iflags); | ||
| 3544 | if (pdone_q) | 3595 | if (pdone_q) |
| 3545 | wake_up(pdone_q); | 3596 | wake_up(pdone_q); |
| 3597 | spin_unlock_irqrestore(&phba->hbalock, iflags); | ||
| 3546 | return; | 3598 | return; |
| 3547 | } | 3599 | } |
| 3548 | 3600 | ||
| @@ -3638,6 +3690,7 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq, | |||
| 3638 | { | 3690 | { |
| 3639 | DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_q); | 3691 | DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_q); |
| 3640 | int retval; | 3692 | int retval; |
| 3693 | unsigned long flag; | ||
| 3641 | 3694 | ||
| 3642 | /* The caller must leave context1 empty. */ | 3695 | /* The caller must leave context1 empty. */ |
| 3643 | if (pmboxq->context1 != 0) | 3696 | if (pmboxq->context1 != 0) |
| @@ -3656,6 +3709,7 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq, | |||
| 3656 | pmboxq->mbox_flag & LPFC_MBX_WAKE, | 3709 | pmboxq->mbox_flag & LPFC_MBX_WAKE, |
| 3657 | timeout * HZ); | 3710 | timeout * HZ); |
| 3658 | 3711 | ||
| 3712 | spin_lock_irqsave(&phba->hbalock, flag); | ||
| 3659 | pmboxq->context1 = NULL; | 3713 | pmboxq->context1 = NULL; |
| 3660 | /* | 3714 | /* |
| 3661 | * if LPFC_MBX_WAKE flag is set the mailbox is completed | 3715 | * if LPFC_MBX_WAKE flag is set the mailbox is completed |
| @@ -3663,8 +3717,11 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq, | |||
| 3663 | */ | 3717 | */ |
| 3664 | if (pmboxq->mbox_flag & LPFC_MBX_WAKE) | 3718 | if (pmboxq->mbox_flag & LPFC_MBX_WAKE) |
| 3665 | retval = MBX_SUCCESS; | 3719 | retval = MBX_SUCCESS; |
| 3666 | else | 3720 | else { |
| 3667 | retval = MBX_TIMEOUT; | 3721 | retval = MBX_TIMEOUT; |
| 3722 | pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | ||
| 3723 | } | ||
| 3724 | spin_unlock_irqrestore(&phba->hbalock, flag); | ||
| 3668 | } | 3725 | } |
| 3669 | 3726 | ||
| 3670 | return retval; | 3727 | return retval; |
| @@ -3712,6 +3769,9 @@ lpfc_intr_handler(int irq, void *dev_id) | |||
| 3712 | uint32_t control; | 3769 | uint32_t control; |
| 3713 | 3770 | ||
| 3714 | MAILBOX_t *mbox, *pmbox; | 3771 | MAILBOX_t *mbox, *pmbox; |
| 3772 | struct lpfc_vport *vport; | ||
| 3773 | struct lpfc_nodelist *ndlp; | ||
| 3774 | struct lpfc_dmabuf *mp; | ||
| 3715 | LPFC_MBOXQ_t *pmb; | 3775 | LPFC_MBOXQ_t *pmb; |
| 3716 | int rc; | 3776 | int rc; |
| 3717 | 3777 | ||
| @@ -3780,18 +3840,23 @@ lpfc_intr_handler(int irq, void *dev_id) | |||
| 3780 | } | 3840 | } |
| 3781 | 3841 | ||
| 3782 | if (work_ha_copy & ~(HA_ERATT|HA_MBATT|HA_LATT)) { | 3842 | if (work_ha_copy & ~(HA_ERATT|HA_MBATT|HA_LATT)) { |
| 3783 | for (i = 0; i < phba->sli.num_rings; i++) { | 3843 | /* |
| 3784 | if (work_ha_copy & (HA_RXATT << (4*i))) { | 3844 | * Turn off Slow Rings interrupts, LPFC_ELS_RING is |
| 3785 | /* | 3845 | * the only slow ring. |
| 3786 | * Turn off Slow Rings interrupts | 3846 | */ |
| 3787 | */ | 3847 | status = (work_ha_copy & |
| 3788 | spin_lock(&phba->hbalock); | 3848 | (HA_RXMASK << (4*LPFC_ELS_RING))); |
| 3789 | control = readl(phba->HCregaddr); | 3849 | status >>= (4*LPFC_ELS_RING); |
| 3790 | control &= ~(HC_R0INT_ENA << i); | 3850 | if (status & HA_RXMASK) { |
| 3851 | spin_lock(&phba->hbalock); | ||
| 3852 | control = readl(phba->HCregaddr); | ||
| 3853 | if (control & (HC_R0INT_ENA << LPFC_ELS_RING)) { | ||
| 3854 | control &= | ||
| 3855 | ~(HC_R0INT_ENA << LPFC_ELS_RING); | ||
| 3791 | writel(control, phba->HCregaddr); | 3856 | writel(control, phba->HCregaddr); |
| 3792 | readl(phba->HCregaddr); /* flush */ | 3857 | readl(phba->HCregaddr); /* flush */ |
| 3793 | spin_unlock(&phba->hbalock); | ||
| 3794 | } | 3858 | } |
| 3859 | spin_unlock(&phba->hbalock); | ||
| 3795 | } | 3860 | } |
| 3796 | } | 3861 | } |
| 3797 | 3862 | ||
| @@ -3819,6 +3884,7 @@ lpfc_intr_handler(int irq, void *dev_id) | |||
| 3819 | pmb = phba->sli.mbox_active; | 3884 | pmb = phba->sli.mbox_active; |
| 3820 | pmbox = &pmb->mb; | 3885 | pmbox = &pmb->mb; |
| 3821 | mbox = &phba->slim2p->mbx; | 3886 | mbox = &phba->slim2p->mbx; |
| 3887 | vport = pmb->vport; | ||
| 3822 | 3888 | ||
| 3823 | /* First check out the status word */ | 3889 | /* First check out the status word */ |
| 3824 | lpfc_sli_pcimem_bcopy(mbox, pmbox, sizeof(uint32_t)); | 3890 | lpfc_sli_pcimem_bcopy(mbox, pmbox, sizeof(uint32_t)); |
| @@ -3833,22 +3899,54 @@ lpfc_intr_handler(int irq, void *dev_id) | |||
| 3833 | "Interrupt mbxCommand x%x " | 3899 | "Interrupt mbxCommand x%x " |
| 3834 | "mbxStatus x%x\n", | 3900 | "mbxStatus x%x\n", |
| 3835 | phba->brd_no, | 3901 | phba->brd_no, |
| 3836 | (pmb->vport | 3902 | (vport |
| 3837 | ? pmb->vport->vpi | 3903 | ? vport->vpi : 0), |
| 3838 | : 0), | ||
| 3839 | pmbox->mbxCommand, | 3904 | pmbox->mbxCommand, |
| 3840 | pmbox->mbxStatus); | 3905 | pmbox->mbxStatus); |
| 3841 | } | 3906 | } |
| 3907 | phba->last_completion_time = jiffies; | ||
| 3842 | del_timer_sync(&phba->sli.mbox_tmo); | 3908 | del_timer_sync(&phba->sli.mbox_tmo); |
| 3843 | 3909 | ||
| 3844 | spin_lock(&phba->pport->work_port_lock); | ||
| 3845 | phba->pport->work_port_events &= ~WORKER_MBOX_TMO; | ||
| 3846 | spin_unlock(&phba->pport->work_port_lock); | ||
| 3847 | phba->sli.mbox_active = NULL; | 3910 | phba->sli.mbox_active = NULL; |
| 3848 | if (pmb->mbox_cmpl) { | 3911 | if (pmb->mbox_cmpl) { |
| 3849 | lpfc_sli_pcimem_bcopy(mbox, pmbox, | 3912 | lpfc_sli_pcimem_bcopy(mbox, pmbox, |
| 3850 | MAILBOX_CMD_SIZE); | 3913 | MAILBOX_CMD_SIZE); |
| 3851 | } | 3914 | } |
| 3915 | if (pmb->mbox_flag & LPFC_MBX_IMED_UNREG) { | ||
| 3916 | pmb->mbox_flag &= ~LPFC_MBX_IMED_UNREG; | ||
| 3917 | |||
| 3918 | lpfc_debugfs_disc_trc(vport, | ||
| 3919 | LPFC_DISC_TRC_MBOX_VPORT, | ||
| 3920 | "MBOX dflt rpi: : status:x%x rpi:x%x", | ||
| 3921 | (uint32_t)pmbox->mbxStatus, | ||
| 3922 | pmbox->un.varWords[0], 0); | ||
| 3923 | |||
| 3924 | if ( !pmbox->mbxStatus) { | ||
| 3925 | mp = (struct lpfc_dmabuf *) | ||
| 3926 | (pmb->context1); | ||
| 3927 | ndlp = (struct lpfc_nodelist *) | ||
| 3928 | pmb->context2; | ||
| 3929 | |||
| 3930 | /* Reg_LOGIN of dflt RPI was successful. | ||
| 3931 | * new lets get rid of the RPI using the | ||
| 3932 | * same mbox buffer. | ||
| 3933 | */ | ||
| 3934 | lpfc_unreg_login(phba, vport->vpi, | ||
| 3935 | pmbox->un.varWords[0], pmb); | ||
| 3936 | pmb->mbox_cmpl = lpfc_mbx_cmpl_dflt_rpi; | ||
| 3937 | pmb->context1 = mp; | ||
| 3938 | pmb->context2 = ndlp; | ||
| 3939 | pmb->vport = vport; | ||
| 3940 | spin_lock(&phba->hbalock); | ||
| 3941 | phba->sli.sli_flag &= | ||
| 3942 | ~LPFC_SLI_MBOX_ACTIVE; | ||
| 3943 | spin_unlock(&phba->hbalock); | ||
| 3944 | goto send_current_mbox; | ||
| 3945 | } | ||
| 3946 | } | ||
| 3947 | spin_lock(&phba->pport->work_port_lock); | ||
| 3948 | phba->pport->work_port_events &= ~WORKER_MBOX_TMO; | ||
| 3949 | spin_unlock(&phba->pport->work_port_lock); | ||
| 3852 | lpfc_mbox_cmpl_put(phba, pmb); | 3950 | lpfc_mbox_cmpl_put(phba, pmb); |
| 3853 | } | 3951 | } |
| 3854 | if ((work_ha_copy & HA_MBATT) && | 3952 | if ((work_ha_copy & HA_MBATT) && |
| @@ -3858,7 +3956,7 @@ send_next_mbox: | |||
| 3858 | phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE; | 3956 | phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE; |
| 3859 | pmb = lpfc_mbox_get(phba); | 3957 | pmb = lpfc_mbox_get(phba); |
| 3860 | spin_unlock(&phba->hbalock); | 3958 | spin_unlock(&phba->hbalock); |
| 3861 | 3959 | send_current_mbox: | |
| 3862 | /* Process next mailbox command if there is one */ | 3960 | /* Process next mailbox command if there is one */ |
| 3863 | if (pmb != NULL) { | 3961 | if (pmb != NULL) { |
| 3864 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); | 3962 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); |
| @@ -3891,7 +3989,7 @@ send_next_mbox: | |||
| 3891 | */ | 3989 | */ |
| 3892 | status = (ha_copy & (HA_RXMASK << (4*LPFC_FCP_RING))); | 3990 | status = (ha_copy & (HA_RXMASK << (4*LPFC_FCP_RING))); |
| 3893 | status >>= (4*LPFC_FCP_RING); | 3991 | status >>= (4*LPFC_FCP_RING); |
| 3894 | if (status & HA_RXATT) | 3992 | if (status & HA_RXMASK) |
| 3895 | lpfc_sli_handle_fast_ring_event(phba, | 3993 | lpfc_sli_handle_fast_ring_event(phba, |
| 3896 | &phba->sli.ring[LPFC_FCP_RING], | 3994 | &phba->sli.ring[LPFC_FCP_RING], |
| 3897 | status); | 3995 | status); |
| @@ -3904,7 +4002,7 @@ send_next_mbox: | |||
| 3904 | */ | 4002 | */ |
| 3905 | status = (ha_copy & (HA_RXMASK << (4*LPFC_EXTRA_RING))); | 4003 | status = (ha_copy & (HA_RXMASK << (4*LPFC_EXTRA_RING))); |
| 3906 | status >>= (4*LPFC_EXTRA_RING); | 4004 | status >>= (4*LPFC_EXTRA_RING); |
| 3907 | if (status & HA_RXATT) { | 4005 | if (status & HA_RXMASK) { |
| 3908 | lpfc_sli_handle_fast_ring_event(phba, | 4006 | lpfc_sli_handle_fast_ring_event(phba, |
| 3909 | &phba->sli.ring[LPFC_EXTRA_RING], | 4007 | &phba->sli.ring[LPFC_EXTRA_RING], |
| 3910 | status); | 4008 | status); |
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h index 4c43a8fd699c..76058505795e 100644 --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h | |||
| @@ -73,7 +73,8 @@ struct lpfc_iocbq { | |||
| 73 | #define IOCB_ERROR 2 | 73 | #define IOCB_ERROR 2 |
| 74 | #define IOCB_TIMEDOUT 3 | 74 | #define IOCB_TIMEDOUT 3 |
| 75 | 75 | ||
| 76 | #define LPFC_MBX_WAKE 1 | 76 | #define LPFC_MBX_WAKE 1 |
| 77 | #define LPFC_MBX_IMED_UNREG 2 | ||
| 77 | 78 | ||
| 78 | typedef struct lpfcMboxq { | 79 | typedef struct lpfcMboxq { |
| 79 | /* MBOXQs are used in single linked lists */ | 80 | /* MBOXQs are used in single linked lists */ |
diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index 786125b7ad4c..85797dbf5478 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c | |||
| @@ -82,7 +82,8 @@ lpfc_alloc_vpi(struct lpfc_hba *phba) | |||
| 82 | int vpi; | 82 | int vpi; |
| 83 | 83 | ||
| 84 | spin_lock_irq(&phba->hbalock); | 84 | spin_lock_irq(&phba->hbalock); |
| 85 | vpi = find_next_zero_bit(phba->vpi_bmask, phba->max_vpi, 1); | 85 | /* Start at bit 1 because vpi zero is reserved for the physical port */ |
| 86 | vpi = find_next_zero_bit(phba->vpi_bmask, (phba->max_vpi + 1), 1); | ||
| 86 | if (vpi > phba->max_vpi) | 87 | if (vpi > phba->max_vpi) |
| 87 | vpi = 0; | 88 | vpi = 0; |
| 88 | else | 89 | else |
| @@ -131,7 +132,8 @@ lpfc_vport_sparm(struct lpfc_hba *phba, struct lpfc_vport *vport) | |||
| 131 | mb->mbxCommand, mb->mbxStatus, rc); | 132 | mb->mbxCommand, mb->mbxStatus, rc); |
| 132 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 133 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
| 133 | kfree(mp); | 134 | kfree(mp); |
| 134 | mempool_free(pmb, phba->mbox_mem_pool); | 135 | if (rc != MBX_TIMEOUT) |
| 136 | mempool_free(pmb, phba->mbox_mem_pool); | ||
| 135 | return -EIO; | 137 | return -EIO; |
| 136 | } | 138 | } |
| 137 | 139 | ||
| @@ -241,6 +243,8 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable) | |||
| 241 | } | 243 | } |
| 242 | 244 | ||
| 243 | vport->vpi = vpi; | 245 | vport->vpi = vpi; |
| 246 | lpfc_debugfs_initialize(vport); | ||
| 247 | |||
| 244 | if (lpfc_vport_sparm(phba, vport)) { | 248 | if (lpfc_vport_sparm(phba, vport)) { |
| 245 | lpfc_printf_log(phba, KERN_ERR, LOG_VPORT, | 249 | lpfc_printf_log(phba, KERN_ERR, LOG_VPORT, |
| 246 | "%d:1813 Create VPORT failed: vpi:%d " | 250 | "%d:1813 Create VPORT failed: vpi:%d " |
| @@ -306,8 +310,16 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable) | |||
| 306 | */ | 310 | */ |
| 307 | ndlp = lpfc_findnode_did(phba->pport, Fabric_DID); | 311 | ndlp = lpfc_findnode_did(phba->pport, Fabric_DID); |
| 308 | if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) { | 312 | if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) { |
| 309 | lpfc_set_disctmo(vport); | 313 | if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) { |
| 310 | lpfc_initial_fdisc(vport); | 314 | lpfc_set_disctmo(vport); |
| 315 | lpfc_initial_fdisc(vport); | ||
| 316 | } else { | ||
| 317 | lpfc_vport_set_state(vport, FC_VPORT_NO_FABRIC_SUPP); | ||
| 318 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, | ||
| 319 | "%d (%d):0262 No NPIV Fabric " | ||
| 320 | "support\n", | ||
| 321 | phba->brd_no, vport->vpi); | ||
| 322 | } | ||
| 311 | } else { | 323 | } else { |
| 312 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); | 324 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); |
| 313 | } | 325 | } |
| @@ -383,8 +395,16 @@ enable_vport(struct fc_vport *fc_vport) | |||
| 383 | */ | 395 | */ |
| 384 | ndlp = lpfc_findnode_did(phba->pport, Fabric_DID); | 396 | ndlp = lpfc_findnode_did(phba->pport, Fabric_DID); |
| 385 | if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) { | 397 | if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) { |
| 386 | lpfc_set_disctmo(vport); | 398 | if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) { |
| 387 | lpfc_initial_fdisc(vport); | 399 | lpfc_set_disctmo(vport); |
| 400 | lpfc_initial_fdisc(vport); | ||
| 401 | } else { | ||
| 402 | lpfc_vport_set_state(vport, FC_VPORT_NO_FABRIC_SUPP); | ||
| 403 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, | ||
| 404 | "%d (%d):0264 No NPIV Fabric " | ||
| 405 | "support\n", | ||
| 406 | phba->brd_no, vport->vpi); | ||
| 407 | } | ||
| 388 | } else { | 408 | } else { |
| 389 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); | 409 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); |
| 390 | } | 410 | } |
| @@ -441,6 +461,7 @@ lpfc_vport_delete(struct fc_vport *fc_vport) | |||
| 441 | vport->load_flag |= FC_UNLOADING; | 461 | vport->load_flag |= FC_UNLOADING; |
| 442 | 462 | ||
| 443 | kfree(vport->vname); | 463 | kfree(vport->vname); |
| 464 | lpfc_debugfs_terminate(vport); | ||
| 444 | fc_remove_host(lpfc_shost_from_vport(vport)); | 465 | fc_remove_host(lpfc_shost_from_vport(vport)); |
| 445 | scsi_remove_host(lpfc_shost_from_vport(vport)); | 466 | scsi_remove_host(lpfc_shost_from_vport(vport)); |
| 446 | 467 | ||
| @@ -476,12 +497,6 @@ skip_logo: | |||
| 476 | NLP_EVT_DEVICE_RM); | 497 | NLP_EVT_DEVICE_RM); |
| 477 | } | 498 | } |
| 478 | 499 | ||
| 479 | list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) { | ||
| 480 | /* free any ndlp's in unused state */ | ||
| 481 | if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) | ||
| 482 | lpfc_drop_node(vport, ndlp); | ||
| 483 | } | ||
| 484 | |||
| 485 | lpfc_stop_vport_timers(vport); | 500 | lpfc_stop_vport_timers(vport); |
| 486 | lpfc_unreg_all_rpis(vport); | 501 | lpfc_unreg_all_rpis(vport); |
| 487 | lpfc_unreg_default_rpis(vport); | 502 | lpfc_unreg_default_rpis(vport); |
