diff options
Diffstat (limited to 'drivers/scsi')
-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 d94c9e0212a..1c286707dd5 100644 --- a/drivers/scsi/lpfc/Makefile +++ b/drivers/scsi/lpfc/Makefile @@ -28,4 +28,4 @@ obj-$(CONFIG_SCSI_LPFC) := lpfc.o lpfc-objs := lpfc_mem.o lpfc_sli.o lpfc_ct.o lpfc_els.o lpfc_hbadisc.o \ lpfc_init.o lpfc_mbox.o lpfc_nportdisc.o lpfc_scsi.o lpfc_attr.o \ - lpfc_vport.o + lpfc_vport.o lpfc_debugfs.o diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 4b9019d7d50..f8f64d6485c 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -23,7 +23,6 @@ struct lpfc_sli2_slim; - #define LPFC_MAX_TARGET 256 /* max number of targets supported */ #define LPFC_MAX_DISC_THREADS 64 /* max outstanding discovery els requests */ @@ -45,6 +44,9 @@ struct lpfc_sli2_slim; /* Number of exchanges reserved for discovery to complete */ #define LPFC_DISC_IOCB_BUFF_COUNT 20 +#define LPFC_HB_MBOX_INTERVAL 5 /* Heart beat interval in seconds. */ +#define LPFC_HB_MBOX_TIMEOUT 30 /* Heart beat timeout in seconds. */ + /* Define macros for 64 bit support */ #define putPaddrLow(addr) ((uint32_t) (0xffffffff & (u64)(addr))) #define putPaddrHigh(addr) ((uint32_t) (0xffffffff & (((u64)(addr))>>32))) @@ -308,13 +310,15 @@ struct lpfc_vport { spinlock_t work_port_lock; uint32_t work_port_events; /* Timeout to be handled */ -#define WORKER_DISC_TMO 0x1 /* Discovery timeout */ -#define WORKER_ELS_TMO 0x2 /* ELS timeout */ -#define WORKER_MBOX_TMO 0x4 /* MBOX timeout */ -#define WORKER_FDMI_TMO 0x8 /* FDMI timeout */ -#define WORKER_FABRIC_BLOCK_TMO 0x10 /* fabric block timout */ -#define WORKER_RAMP_DOWN_QUEUE 0x20 /* Decrease Q depth */ -#define WORKER_RAMP_UP_QUEUE 0x40 /* Increase Q depth */ +#define WORKER_DISC_TMO 0x1 /* vport: Discovery timeout */ +#define WORKER_ELS_TMO 0x2 /* vport: ELS timeout */ +#define WORKER_FDMI_TMO 0x4 /* vport: FDMI timeout */ + +#define WORKER_MBOX_TMO 0x100 /* hba: MBOX timeout */ +#define WORKER_HB_TMO 0x200 /* hba: Heart beat timeout */ +#define WORKER_FABRIC_BLOCK_TMO 0x400 /* hba: fabric block timout */ +#define WORKER_RAMP_DOWN_QUEUE 0x800 /* hba: Decrease Q depth */ +#define WORKER_RAMP_UP_QUEUE 0x1000 /* hba: Increase Q depth */ struct timer_list fc_fdmitmo; struct timer_list els_tmofunc; @@ -326,6 +330,14 @@ struct lpfc_vport { #define FC_UNLOADING 0x2 /* HBA in process of unloading drvr */ char *vname; /* Application assigned name */ struct fc_vport *fc_vport; + +#ifdef CONFIG_LPFC_DEBUG_FS + struct dentry *debug_disc_trc; + struct dentry *debug_nodelist; + struct dentry *vport_debugfs_root; + struct lpfc_disc_trc *disc_trc; + atomic_t disc_trc_cnt; +#endif }; struct hbq_s { @@ -408,6 +420,7 @@ struct lpfc_hba { uint32_t cfg_hba_queue_depth; uint32_t cfg_peer_port_login; uint32_t cfg_vport_restrict_login; + uint32_t cfg_npiv_enable; uint32_t cfg_fcp_class; uint32_t cfg_use_adisc; uint32_t cfg_ack0; @@ -513,10 +526,10 @@ struct lpfc_hba { mempool_t *nlp_mem_pool; struct fc_host_statistics link_stats; + struct list_head port_list; struct lpfc_vport *pport; /* physical lpfc_vport pointer */ uint16_t max_vpi; /* Maximum virtual nports */ - uint16_t vpi_cnt; /* Nport count */ #define LPFC_MAX_VPI 100 /* Max number of VPorts supported */ unsigned long *vpi_bmask; /* vpi allocation table */ @@ -531,6 +544,15 @@ struct lpfc_hba { unsigned long last_rsrc_error_time; unsigned long last_ramp_down_time; unsigned long last_ramp_up_time; +#ifdef CONFIG_LPFC_DEBUG_FS + struct dentry *hba_debugfs_root; + atomic_t debugfs_vport_count; +#endif + + /* Fields used for heart beat. */ + unsigned long last_completion_time; + struct timer_list hb_tmofunc; + uint8_t hb_outstanding; }; static inline struct Scsi_Host * diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 5cb7924fe3d..6a2c1ac4244 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) } lpfc_set_loopback_flag(phba); - if (mbxstatus == MBX_TIMEOUT) - pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl; - else + if (mbxstatus != MBX_TIMEOUT) mempool_free(pmboxq, phba->mbox_mem_pool); if (mbxstatus == MBXERR_ERROR) @@ -439,30 +437,11 @@ lpfc_board_mode_store(struct class_device *cdev, const char *buf, size_t count) return -EIO; } -static ssize_t -lpfc_max_vpi_show(struct class_device *cdev, char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; - struct lpfc_hba *phba = vport->phba; - - return snprintf(buf, PAGE_SIZE, "%d\n", phba->max_vpi); -} - -static ssize_t -lpfc_used_vpi_show(struct class_device *cdev, char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; - struct lpfc_hba *phba = vport->phba; - - /* Don't count the physical port */ - return snprintf(buf, PAGE_SIZE, "%d\n", phba->vpi_cnt-1); -} - int -lpfc_get_hba_info(struct lpfc_hba *phba, uint32_t *mxri, - uint32_t *axri, uint32_t *mrpi, uint32_t *arpi) +lpfc_get_hba_info(struct lpfc_hba *phba, + uint32_t *mxri, uint32_t *axri, + uint32_t *mrpi, uint32_t *arpi, + uint32_t *mvpi, uint32_t *avpi) { struct lpfc_sli *psli = &phba->sli; LPFC_MBOXQ_t *pmboxq; @@ -498,9 +477,7 @@ lpfc_get_hba_info(struct lpfc_hba *phba, uint32_t *mxri, rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2); if (rc != MBX_SUCCESS) { - if (rc == MBX_TIMEOUT) - pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl; - else + if (rc != MBX_TIMEOUT) mempool_free(pmboxq, phba->mbox_mem_pool); return 0; } @@ -513,6 +490,10 @@ lpfc_get_hba_info(struct lpfc_hba *phba, uint32_t *mxri, *mxri = pmb->un.varRdConfig.max_xri; if (axri) *axri = pmb->un.varRdConfig.avail_xri; + if (mvpi) + *mvpi = pmb->un.varRdConfig.max_vpi; + if (avpi) + *avpi = pmb->un.varRdConfig.avail_vpi; mempool_free(pmboxq, phba->mbox_mem_pool); return 1; @@ -526,7 +507,7 @@ lpfc_max_rpi_show(struct class_device *cdev, char *buf) struct lpfc_hba *phba = vport->phba; uint32_t cnt; - if (lpfc_get_hba_info(phba, NULL, NULL, &cnt, NULL)) + if (lpfc_get_hba_info(phba, NULL, NULL, &cnt, NULL, NULL, NULL)) return snprintf(buf, PAGE_SIZE, "%d\n", cnt); return snprintf(buf, PAGE_SIZE, "Unknown\n"); } @@ -539,7 +520,7 @@ lpfc_used_rpi_show(struct class_device *cdev, char *buf) struct lpfc_hba *phba = vport->phba; uint32_t cnt, acnt; - if (lpfc_get_hba_info(phba, NULL, NULL, &cnt, &acnt)) + if (lpfc_get_hba_info(phba, NULL, NULL, &cnt, &acnt, NULL, NULL)) return snprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt)); return snprintf(buf, PAGE_SIZE, "Unknown\n"); } @@ -552,7 +533,7 @@ lpfc_max_xri_show(struct class_device *cdev, char *buf) struct lpfc_hba *phba = vport->phba; uint32_t cnt; - if (lpfc_get_hba_info(phba, &cnt, NULL, NULL, NULL)) + if (lpfc_get_hba_info(phba, &cnt, NULL, NULL, NULL, NULL, NULL)) return snprintf(buf, PAGE_SIZE, "%d\n", cnt); return snprintf(buf, PAGE_SIZE, "Unknown\n"); } @@ -565,7 +546,33 @@ lpfc_used_xri_show(struct class_device *cdev, char *buf) struct lpfc_hba *phba = vport->phba; uint32_t cnt, acnt; - if (lpfc_get_hba_info(phba, &cnt, &acnt, NULL, NULL)) + if (lpfc_get_hba_info(phba, &cnt, &acnt, NULL, NULL, NULL, NULL)) + return snprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt)); + return snprintf(buf, PAGE_SIZE, "Unknown\n"); +} + +static ssize_t +lpfc_max_vpi_show(struct class_device *cdev, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; + struct lpfc_hba *phba = vport->phba; + uint32_t cnt; + + if (lpfc_get_hba_info(phba, NULL, NULL, NULL, NULL, &cnt, NULL)) + return snprintf(buf, PAGE_SIZE, "%d\n", cnt); + return snprintf(buf, PAGE_SIZE, "Unknown\n"); +} + +static ssize_t +lpfc_used_vpi_show(struct class_device *cdev, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; + struct lpfc_hba *phba = vport->phba; + uint32_t cnt, acnt; + + if (lpfc_get_hba_info(phba, NULL, NULL, NULL, NULL, &cnt, &acnt)) return snprintf(buf, PAGE_SIZE, "%d\n", (cnt - acnt)); return snprintf(buf, PAGE_SIZE, "Unknown\n"); } @@ -995,9 +1002,7 @@ MODULE_PARM_DESC(lpfc_sli_mode, "SLI mode selector:" " 2 - select SLI-2 even on SLI-3 capable HBAs," " 3 - select SLI-3"); -int lpfc_npiv_enable = 0; -module_param(lpfc_npiv_enable, int, 0); -MODULE_PARM_DESC(lpfc_npiv_enable, "Enable NPIV functionality"); +LPFC_ATTR_R(npiv_enable, 0, 0, 1, "Enable NPIV functionality"); /* # 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) return -EINVAL; } +static void +lpfc_update_rport_devloss_tmo(struct lpfc_hba *phba) +{ + struct lpfc_vport *vport; + struct Scsi_Host *shost; + struct lpfc_nodelist *ndlp; + + list_for_each_entry(vport, &phba->port_list, listentry) { + shost = lpfc_shost_from_vport(vport); + spin_lock_irq(shost->host_lock); + list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) + if (ndlp->rport) + ndlp->rport->dev_loss_tmo = + phba->cfg_devloss_tmo; + spin_unlock_irq(shost->host_lock); + } +} + static int lpfc_nodev_tmo_set(struct lpfc_hba *phba, int val) { @@ -1067,6 +1090,7 @@ lpfc_nodev_tmo_set(struct lpfc_hba *phba, int val) if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) { phba->cfg_nodev_tmo = val; phba->cfg_devloss_tmo = val; + lpfc_update_rport_devloss_tmo(phba); return 0; } @@ -1102,6 +1126,7 @@ lpfc_devloss_tmo_set(struct lpfc_hba *phba, int val) phba->cfg_nodev_tmo = val; phba->cfg_devloss_tmo = val; phba->dev_loss_tmo_changed = 1; + lpfc_update_rport_devloss_tmo(phba); return 0; } @@ -1358,6 +1383,7 @@ struct class_device_attribute *lpfc_hba_attrs[] = { &class_device_attr_lpfc_multi_ring_type, &class_device_attr_lpfc_fdmi_on, &class_device_attr_lpfc_max_luns, + &class_device_attr_lpfc_npiv_enable, &class_device_attr_nport_evt_cnt, &class_device_attr_management_version, &class_device_attr_board_mode, @@ -1641,8 +1667,6 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count) if (rc != MBX_SUCCESS) { if (rc == MBX_TIMEOUT) { - phba->sysfs_mbox.mbox->mbox_cmpl = - lpfc_sli_def_mbox_cmpl; phba->sysfs_mbox.mbox = NULL; } sysfs_mbox_idle(phba); @@ -1886,9 +1910,7 @@ lpfc_get_stats(struct Scsi_Host *shost) rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2); if (rc != MBX_SUCCESS) { - if (rc == MBX_TIMEOUT) - pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl; - else + if (rc != MBX_TIMEOUT) mempool_free(pmboxq, phba->mbox_mem_pool); return NULL; } @@ -1913,9 +1935,7 @@ lpfc_get_stats(struct Scsi_Host *shost) rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2); if (rc != MBX_SUCCESS) { - if (rc == MBX_TIMEOUT) - pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl; - else + if (rc != MBX_TIMEOUT) mempool_free(pmboxq, phba->mbox_mem_pool); return NULL; } @@ -1993,9 +2013,7 @@ lpfc_reset_stats(struct Scsi_Host *shost) rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2); if (rc != MBX_SUCCESS) { - if (rc == MBX_TIMEOUT) - pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl; - else + if (rc != MBX_TIMEOUT) mempool_free(pmboxq, phba->mbox_mem_pool); return; } @@ -2013,9 +2031,7 @@ lpfc_reset_stats(struct Scsi_Host *shost) rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2); if (rc != MBX_SUCCESS) { - if (rc == MBX_TIMEOUT) - pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl; - else + if (rc != MBX_TIMEOUT) mempool_free( pmboxq, phba->mbox_mem_pool); return; } @@ -2253,6 +2269,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) lpfc_max_luns_init(phba, lpfc_max_luns); lpfc_poll_tmo_init(phba, lpfc_poll_tmo); lpfc_peer_port_login_init(phba, lpfc_peer_port_login); + lpfc_npiv_enable_init(phba, lpfc_npiv_enable); lpfc_vport_restrict_login_init(phba, lpfc_vport_restrict_login); lpfc_use_msi_init(phba, lpfc_use_msi); 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 94e78819956..e19d1a74658 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); struct fc_rport; void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t); void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *); +void lpfc_heart_beat(struct lpfc_hba *, LPFC_MBOXQ_t *); int lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, struct lpfc_dmabuf *mp); 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 *); void lpfc_mbx_cmpl_clear_la(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_mbx_cmpl_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); +void lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); 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 *); int lpfc_check_sparm(struct lpfc_vport *, struct lpfc_nodelist *, struct serv_parm *, uint32_t); int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist *); +int lpfc_els_chk_latt(struct lpfc_vport *); int lpfc_els_abort_flogi(struct lpfc_hba *); int lpfc_initial_flogi(struct lpfc_vport *); int lpfc_initial_fdisc(struct lpfc_vport *); @@ -96,10 +99,11 @@ int lpfc_issue_els_logo(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t); int lpfc_issue_els_npiv_logo(struct lpfc_vport *, struct lpfc_nodelist *); int lpfc_issue_els_scr(struct lpfc_vport *, uint32_t, uint8_t); int lpfc_els_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *); +int lpfc_ct_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *); int lpfc_els_rsp_acc(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *, struct lpfc_nodelist *, LPFC_MBOXQ_t *, uint8_t); int lpfc_els_rsp_reject(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *, - struct lpfc_nodelist *); + struct lpfc_nodelist *, LPFC_MBOXQ_t *); int lpfc_els_rsp_adisc_acc(struct lpfc_vport *, struct lpfc_iocbq *, struct lpfc_nodelist *); 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 *, void lpfc_cancel_retry_delay_tmo(struct lpfc_vport *, struct lpfc_nodelist *); void lpfc_els_retry_delay(unsigned long); void lpfc_els_retry_delay_handler(struct lpfc_nodelist *); +void lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *); void lpfc_els_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *, struct lpfc_iocbq *); int lpfc_els_handle_rscn(struct lpfc_vport *); @@ -117,6 +122,8 @@ int lpfc_els_disc_adisc(struct lpfc_vport *); int lpfc_els_disc_plogi(struct lpfc_vport *); void lpfc_els_timeout(unsigned long); void lpfc_els_timeout_handler(struct lpfc_vport *); +void lpfc_hb_timeout(unsigned long); +void lpfc_hb_timeout_handler(struct lpfc_hba *); void lpfc_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *, struct lpfc_iocbq *); @@ -238,7 +245,6 @@ void lpfc_mbuf_free(struct lpfc_hba *, void *, dma_addr_t); void lpfc_in_buf_free(struct lpfc_hba *, struct lpfc_dmabuf *); /* Function prototypes. */ const char* lpfc_info(struct Scsi_Host *); -void lpfc_scan_start(struct Scsi_Host *); int lpfc_scan_finished(struct Scsi_Host *, unsigned long); void lpfc_get_cfgparam(struct lpfc_hba *); @@ -249,7 +255,6 @@ extern struct scsi_host_template lpfc_template; extern struct fc_function_template lpfc_transport_functions; extern struct fc_function_template lpfc_vport_transport_functions; extern int lpfc_sli_mode; -extern int lpfc_npiv_enable; int lpfc_vport_symbolic_node_name(struct lpfc_vport *, char *, size_t); void lpfc_terminate_rport_io(struct fc_rport *); @@ -262,6 +267,11 @@ void destroy_port(struct lpfc_vport *); int lpfc_get_instance(void); void lpfc_host_attrib_init(struct Scsi_Host *); +extern void lpfc_debugfs_initialize(struct lpfc_vport *); +extern void lpfc_debugfs_terminate(struct lpfc_vport *); +extern void lpfc_debugfs_disc_trc(struct lpfc_vport *, int, char *, uint32_t, + uint32_t, uint32_t); + /* Interface exported by fabric iocb scheduler */ int lpfc_issue_fabric_iocb(struct lpfc_hba *, struct lpfc_iocbq *); 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 5584f395314..ae9d6f385a6 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -41,6 +41,7 @@ #include "lpfc_crtn.h" #include "lpfc_version.h" #include "lpfc_vport.h" +#include "lpfc_debugfs.h" #define HBA_PORTSPEED_UNKNOWN 0 /* Unknown - transceiver * incapable of reporting */ @@ -251,6 +252,32 @@ lpfc_alloc_ct_rsp(struct lpfc_hba *phba, int cmdcode, struct ulp_bde64 *bpl, return mlist; } +int +lpfc_ct_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *ctiocb) +{ + struct lpfc_dmabuf *buf_ptr; + + if (ctiocb->context1) { + buf_ptr = (struct lpfc_dmabuf *) ctiocb->context1; + lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys); + kfree(buf_ptr); + ctiocb->context1 = NULL; + } + if (ctiocb->context2) { + lpfc_free_ct_rsp(phba, (struct lpfc_dmabuf *) ctiocb->context2); + ctiocb->context2 = NULL; + } + + if (ctiocb->context3) { + buf_ptr = (struct lpfc_dmabuf *) ctiocb->context3; + lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys); + kfree(buf_ptr); + ctiocb->context1 = NULL; + } + lpfc_sli_release_iocbq(phba, ctiocb); + return 0; +} + static int lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, 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) (!phba->cfg_vport_restrict_login)) { ndlp = lpfc_setup_disc_node(vport, Did); if (ndlp) { + lpfc_debugfs_disc_trc(vport, + LPFC_DISC_TRC_CT, + "Parse GID_FTrsp: " + "did:x%x flg:x%x x%x", + Did, ndlp->nlp_flag, + vport->fc_flag); + lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, "%d (%d):0238 Process " @@ -439,6 +473,13 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size) vport->fc_flag, vport->fc_rscn_id_cnt); } else { + lpfc_debugfs_disc_trc(vport, + LPFC_DISC_TRC_CT, + "Skip1 GID_FTrsp: " + "did:x%x flg:x%x cnt:%d", + Did, vport->fc_flag, + vport->fc_rscn_id_cnt); + lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, "%d (%d):0239 Skip x%x " @@ -453,12 +494,26 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size) } else { if (!(vport->fc_flag & FC_RSCN_MODE) || (lpfc_rscn_payload_check(vport, Did))) { + lpfc_debugfs_disc_trc(vport, + LPFC_DISC_TRC_CT, + "Query GID_FTrsp: " + "did:x%x flg:x%x cnt:%d", + Did, vport->fc_flag, + vport->fc_rscn_id_cnt); + if (lpfc_ns_cmd(vport, SLI_CTNS_GFF_ID, 0, Did) == 0) vport->num_disc_nodes++; } else { + lpfc_debugfs_disc_trc(vport, + LPFC_DISC_TRC_CT, + "Skip2 GID_FTrsp: " + "did:x%x flg:x%x cnt:%d", + Did, vport->fc_flag, + vport->fc_rscn_id_cnt); + lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, "%d (%d):0245 Skip x%x " @@ -492,7 +547,6 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct Scsi_Host *shost = lpfc_shost_from_vport(vport); IOCB_t *irsp; struct lpfc_dmabuf *bmp; - struct lpfc_dmabuf *inp; struct lpfc_dmabuf *outp; struct lpfc_sli_ct_request *CTrsp; int rc; @@ -500,31 +554,39 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, /* we pass cmdiocb to state machine which needs rspiocb as well */ cmdiocb->context_un.rsp_iocb = rspiocb; - inp = (struct lpfc_dmabuf *) cmdiocb->context1; outp = (struct lpfc_dmabuf *) cmdiocb->context2; bmp = (struct lpfc_dmabuf *) cmdiocb->context3; + irsp = &rspiocb->iocb; + + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, + "GID_FT cmpl: status:x%x/x%x rtry:%d", + irsp->ulpStatus, irsp->un.ulpWord[4], vport->fc_ns_retry); /* Don't bother processing response if vport is being torn down. */ if (vport->load_flag & FC_UNLOADING) goto out; - irsp = &rspiocb->iocb; - if (irsp->ulpStatus) { - if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) && - ((irsp->un.ulpWord[4] == IOERR_SLI_DOWN) || - (irsp->un.ulpWord[4] == IOERR_SLI_ABORTED))) - goto err1; + if (lpfc_els_chk_latt(vport) || lpfc_error_lost_link(irsp)) { + lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, + "%d (%d):0216 Link event during NS query\n", + phba->brd_no, vport->vpi); + lpfc_vport_set_state(vport, FC_VPORT_FAILED); + goto out; + } + + if (irsp->ulpStatus) { /* Check for retry */ if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) { - vport->fc_ns_retry++; + if ((irsp->ulpStatus != IOSTAT_LOCAL_REJECT) || + (irsp->un.ulpWord[4] != IOERR_NO_RESOURCES)) + vport->fc_ns_retry++; /* CT command is being retried */ rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_FT, vport->fc_ns_retry, 0); if (rc == 0) goto out; } -err1: lpfc_vport_set_state(vport, FC_VPORT_FAILED); lpfc_printf_log(phba, KERN_ERR, LOG_ELS, "%d (%d):0257 GID_FT Query error: 0x%x 0x%x\n", @@ -553,6 +615,13 @@ err1: (uint32_t) CTrsp->ReasonCode, (uint32_t) CTrsp->Explanation, vport->fc_flag); + + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, + "GID_FT rsp err1 cmd:x%x rsn:x%x exp:x%x", + (uint32_t)CTrsp->CommandResponse.bits.CmdRsp, + (uint32_t) CTrsp->ReasonCode, + (uint32_t) CTrsp->Explanation); + } else { /* NameServer Rsp Error */ lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, @@ -563,6 +632,12 @@ err1: (uint32_t) CTrsp->ReasonCode, (uint32_t) CTrsp->Explanation, vport->fc_flag); + + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, + "GID_FT rsp err2 cmd:x%x rsn:x%x exp:x%x", + (uint32_t)CTrsp->CommandResponse.bits.CmdRsp, + (uint32_t) CTrsp->ReasonCode, + (uint32_t) CTrsp->Explanation); } } /* Link up / RSCN discovery */ @@ -586,12 +661,7 @@ err1: lpfc_disc_start(vport); } out: - lpfc_free_ct_rsp(phba, outp); - lpfc_mbuf_free(phba, inp->virt, inp->phys); - lpfc_mbuf_free(phba, bmp->virt, bmp->phys); - kfree(inp); - kfree(bmp); - lpfc_sli_release_iocbq(phba, cmdiocb); + lpfc_ct_free_iocb(phba, cmdiocb); return; } @@ -602,7 +672,6 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_vport *vport = cmdiocb->vport; struct Scsi_Host *shost = lpfc_shost_from_vport(vport); IOCB_t *irsp = &rspiocb->iocb; - struct lpfc_dmabuf *bmp = (struct lpfc_dmabuf *) cmdiocb->context3; struct lpfc_dmabuf *inp = (struct lpfc_dmabuf *) cmdiocb->context1; struct lpfc_dmabuf *outp = (struct lpfc_dmabuf *) cmdiocb->context2; struct lpfc_sli_ct_request *CTrsp; @@ -613,6 +682,10 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, did = ((struct lpfc_sli_ct_request *) inp->virt)->un.gff.PortId; did = be32_to_cpu(did); + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, + "GFF_ID cmpl: status:x%x/x%x did:x%x", + irsp->ulpStatus, irsp->un.ulpWord[4], did); + if (irsp->ulpStatus == IOSTAT_SUCCESS) { /* Good status, continue checking */ 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, } } } + else { + lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, + "%d (%d):0267 NameServer GFF Rsp" + " x%x Error (%d %d) Data: x%x x%x\n", + phba->brd_no, vport->vpi, did, + irsp->ulpStatus, irsp->un.ulpWord[4], + vport->fc_flag, vport->fc_rscn_id_cnt) + } + /* This is a target port, unregistered port, or the GFF_ID failed */ ndlp = lpfc_setup_disc_node(vport, did); if (ndlp) { @@ -670,13 +752,7 @@ out: } lpfc_disc_start(vport); } - - lpfc_free_ct_rsp(phba, outp); - lpfc_mbuf_free(phba, inp->virt, inp->phys); - lpfc_mbuf_free(phba, bmp->virt, bmp->phys); - kfree(inp); - kfree(bmp); - lpfc_sli_release_iocbq(phba, cmdiocb); + lpfc_ct_free_iocb(phba, cmdiocb); return; } @@ -686,37 +762,45 @@ lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq *rspiocb) { struct lpfc_vport *vport = cmdiocb->vport; - struct lpfc_dmabuf *bmp; struct lpfc_dmabuf *inp; struct lpfc_dmabuf *outp; IOCB_t *irsp; struct lpfc_sli_ct_request *CTrsp; int cmdcode, rc; uint8_t retry; + uint32_t latt; /* we pass cmdiocb to state machine which needs rspiocb as well */ cmdiocb->context_un.rsp_iocb = rspiocb; inp = (struct lpfc_dmabuf *) cmdiocb->context1; outp = (struct lpfc_dmabuf *) cmdiocb->context2; - bmp = (struct lpfc_dmabuf *) cmdiocb->context3; irsp = &rspiocb->iocb; cmdcode = be16_to_cpu(((struct lpfc_sli_ct_request *) inp->virt)-> CommandResponse.bits.CmdRsp); CTrsp = (struct lpfc_sli_ct_request *) outp->virt; - /* NS request completes status <ulpStatus> CmdRsp <CmdRsp> */ + latt = lpfc_els_chk_latt(vport); + + /* RFT request completes status <ulpStatus> CmdRsp <CmdRsp> */ lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d (%d):0209 NS request %x completes " - "ulpStatus x%x / x%x " - "CmdRsp x%x, Context x%x, Tag x%x\n", - phba->brd_no, vport->vpi, - cmdcode, irsp->ulpStatus, irsp->un.ulpWord[4], + "%d (%d):0209 RFT request completes, latt %d, " + "ulpStatus x%x CmdRsp x%x, Context x%x, Tag x%x\n", + phba->brd_no, vport->vpi, latt, irsp->ulpStatus, CTrsp->CommandResponse.bits.CmdRsp, cmdiocb->iocb.ulpContext, cmdiocb->iocb.ulpIoTag); + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, + "CT cmd cmpl: status:x%x/x%x cmd:x%x", + irsp->ulpStatus, irsp->un.ulpWord[4], cmdcode); + if (irsp->ulpStatus) { + lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, + "%d (%d):0268 NS cmd %x Error (%d %d)\n", + phba->brd_no, vport->vpi, cmdcode, + irsp->ulpStatus, irsp->un.ulpWord[4]); + if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) && ((irsp->un.ulpWord[4] == IOERR_SLI_DOWN) || (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, } out: - lpfc_free_ct_rsp(phba, outp); - lpfc_mbuf_free(phba, inp->virt, inp->phys); - lpfc_mbuf_free(phba, bmp->virt, bmp->phys); - kfree(inp); - kfree(bmp); - lpfc_sli_release_iocbq(phba, cmdiocb); + lpfc_ct_free_iocb(phba, cmdiocb); return; } @@ -840,31 +919,42 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, struct lpfc_iocbq *) = NULL; uint32_t rsp_size = 1024; size_t size; + int rc = 0; ndlp = lpfc_findnode_did(vport, NameServer_DID); - if (ndlp == NULL || ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) - return 1; + if (ndlp == NULL || ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) { + rc=1; + goto ns_cmd_exit; + } /* fill in BDEs for command */ /* Allocate buffer for command payload */ mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL); - if (!mp) + if (!mp) { + rc=2; goto ns_cmd_exit; + } INIT_LIST_HEAD(&mp->list); mp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(mp->phys)); - if (!mp->virt) + if (!mp->virt) { + rc=3; goto ns_cmd_free_mp; + } /* Allocate buffer for Buffer ptr list */ bmp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL); - if (!bmp) + if (!bmp) { + rc=4; goto ns_cmd_free_mpvirt; + } INIT_LIST_HEAD(&bmp->list); bmp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(bmp->phys)); - if (!bmp->virt) + if (!bmp->virt) { + rc=5; goto ns_cmd_free_bmp; + } /* NameServer Req */ lpfc_printf_log(phba, KERN_INFO ,LOG_DISCOVERY, @@ -970,10 +1060,15 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, break; } - if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, rsp_size, retry)) + if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, rsp_size, retry)) { /* On success, The cmpl function will free the buffers */ + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, + "Issue CT cmd: cmd:x%x did:x%x", + cmdcode, ndlp->nlp_DID, 0); return 0; + } + rc=6; lpfc_mbuf_free(phba, bmp->virt, bmp->phys); ns_cmd_free_bmp: kfree(bmp); @@ -982,6 +1077,10 @@ ns_cmd_free_mpvirt: ns_cmd_free_mp: kfree(mp); ns_cmd_exit: + lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, + "%d (%d):0266 Issue NameServer Req x%x err %d Data: x%x x%x\n", + phba->brd_no, vport->vpi, cmdcode, rc, vport->fc_flag, + vport->fc_rscn_id_cnt); return 1; } @@ -989,7 +1088,6 @@ static void lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq * rspiocb) { - struct lpfc_dmabuf *bmp = cmdiocb->context3; struct lpfc_dmabuf *inp = cmdiocb->context1; struct lpfc_dmabuf *outp = cmdiocb->context2; 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, uint16_t fdmi_cmd = CTcmd->CommandResponse.bits.CmdRsp; uint16_t fdmi_rsp = CTrsp->CommandResponse.bits.CmdRsp; struct lpfc_vport *vport = cmdiocb->vport; + IOCB_t *irsp = &rspiocb->iocb; + uint32_t latt; + + latt = lpfc_els_chk_latt(vport); + + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, + "FDMI cmpl: status:x%x/x%x latt:%d", + irsp->ulpStatus, irsp->un.ulpWord[4], latt); + + if (latt || irsp->ulpStatus) { + lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, + "%d (%d):0229 FDMI cmd %04x failed, latt = %d " + "ulpStatus: x%x, rid x%x\n", + phba->brd_no, vport->vpi, + be16_to_c |