diff options
author | James Smart <James.Smart@Emulex.Com> | 2007-06-17 20:56:39 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-06-17 23:38:11 -0400 |
commit | 858c9f6c19c6f9bf86cbbc64ce0d17c61d6131b8 (patch) | |
tree | 9591b15b4424066023e375ad0aa33fdd37e1c452 /drivers | |
parent | 92d7f7b0cde3ad2260e7462b40867b57efd49851 (diff) |
[SCSI] lpfc: bug fixes
Following the NPIV support, the following changes have been accumulated
in the testing and qualification of the driver:
- Fix affinity of ELS ring to slow/deferred event processing
- Fix Ring attention masks
- Defer dev_loss_tmo timeout handling to worker thread
- Consolidate link down error classification for better error checking
- Remove unused/deprecated nlp_initiator_tmr timer
- Fix for async scan - move adapter init code back into pci_probe_one
context. Fix async scan interfaces.
- Expand validation of ability to create vports
- Extract VPI resource cnt from firmware
- Tuning of Login/Reject policies to better deal with overwhelmned targets
- Misc ELS and discovery fixes
- Export the npiv_enable attribute to sysfs
- Mailbox handling fix
- Add debugfs support
- A few other small misc fixes:
- wrong return values, double-frees, bad locking
- Added adapter failure heartbeat
Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers')
-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); |