[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>
This commit is contained in:
Родитель
92d7f7b0cd
Коммит
858c9f6c19
|
@ -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-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_init.o lpfc_mbox.o lpfc_nportdisc.o lpfc_scsi.o lpfc_attr.o \
|
||||||
lpfc_vport.o
|
lpfc_vport.o lpfc_debugfs.o
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
|
|
||||||
struct lpfc_sli2_slim;
|
struct lpfc_sli2_slim;
|
||||||
|
|
||||||
|
|
||||||
#define LPFC_MAX_TARGET 256 /* max number of targets supported */
|
#define LPFC_MAX_TARGET 256 /* max number of targets supported */
|
||||||
#define LPFC_MAX_DISC_THREADS 64 /* max outstanding discovery els
|
#define LPFC_MAX_DISC_THREADS 64 /* max outstanding discovery els
|
||||||
requests */
|
requests */
|
||||||
|
@ -45,6 +44,9 @@ struct lpfc_sli2_slim;
|
||||||
/* Number of exchanges reserved for discovery to complete */
|
/* Number of exchanges reserved for discovery to complete */
|
||||||
#define LPFC_DISC_IOCB_BUFF_COUNT 20
|
#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 macros for 64 bit support */
|
||||||
#define putPaddrLow(addr) ((uint32_t) (0xffffffff & (u64)(addr)))
|
#define putPaddrLow(addr) ((uint32_t) (0xffffffff & (u64)(addr)))
|
||||||
#define putPaddrHigh(addr) ((uint32_t) (0xffffffff & (((u64)(addr))>>32)))
|
#define putPaddrHigh(addr) ((uint32_t) (0xffffffff & (((u64)(addr))>>32)))
|
||||||
|
@ -308,13 +310,15 @@ struct lpfc_vport {
|
||||||
|
|
||||||
spinlock_t work_port_lock;
|
spinlock_t work_port_lock;
|
||||||
uint32_t work_port_events; /* Timeout to be handled */
|
uint32_t work_port_events; /* Timeout to be handled */
|
||||||
#define WORKER_DISC_TMO 0x1 /* Discovery timeout */
|
#define WORKER_DISC_TMO 0x1 /* vport: Discovery timeout */
|
||||||
#define WORKER_ELS_TMO 0x2 /* ELS timeout */
|
#define WORKER_ELS_TMO 0x2 /* vport: ELS timeout */
|
||||||
#define WORKER_MBOX_TMO 0x4 /* MBOX timeout */
|
#define WORKER_FDMI_TMO 0x4 /* vport: FDMI timeout */
|
||||||
#define WORKER_FDMI_TMO 0x8 /* FDMI timeout */
|
|
||||||
#define WORKER_FABRIC_BLOCK_TMO 0x10 /* fabric block timout */
|
#define WORKER_MBOX_TMO 0x100 /* hba: MBOX timeout */
|
||||||
#define WORKER_RAMP_DOWN_QUEUE 0x20 /* Decrease Q depth */
|
#define WORKER_HB_TMO 0x200 /* hba: Heart beat timeout */
|
||||||
#define WORKER_RAMP_UP_QUEUE 0x40 /* Increase Q depth */
|
#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 fc_fdmitmo;
|
||||||
struct timer_list els_tmofunc;
|
struct timer_list els_tmofunc;
|
||||||
|
@ -326,6 +330,14 @@ struct lpfc_vport {
|
||||||
#define FC_UNLOADING 0x2 /* HBA in process of unloading drvr */
|
#define FC_UNLOADING 0x2 /* HBA in process of unloading drvr */
|
||||||
char *vname; /* Application assigned name */
|
char *vname; /* Application assigned name */
|
||||||
struct fc_vport *fc_vport;
|
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 {
|
struct hbq_s {
|
||||||
|
@ -408,6 +420,7 @@ struct lpfc_hba {
|
||||||
uint32_t cfg_hba_queue_depth;
|
uint32_t cfg_hba_queue_depth;
|
||||||
uint32_t cfg_peer_port_login;
|
uint32_t cfg_peer_port_login;
|
||||||
uint32_t cfg_vport_restrict_login;
|
uint32_t cfg_vport_restrict_login;
|
||||||
|
uint32_t cfg_npiv_enable;
|
||||||
uint32_t cfg_fcp_class;
|
uint32_t cfg_fcp_class;
|
||||||
uint32_t cfg_use_adisc;
|
uint32_t cfg_use_adisc;
|
||||||
uint32_t cfg_ack0;
|
uint32_t cfg_ack0;
|
||||||
|
@ -513,10 +526,10 @@ struct lpfc_hba {
|
||||||
mempool_t *nlp_mem_pool;
|
mempool_t *nlp_mem_pool;
|
||||||
|
|
||||||
struct fc_host_statistics link_stats;
|
struct fc_host_statistics link_stats;
|
||||||
|
|
||||||
struct list_head port_list;
|
struct list_head port_list;
|
||||||
struct lpfc_vport *pport; /* physical lpfc_vport pointer */
|
struct lpfc_vport *pport; /* physical lpfc_vport pointer */
|
||||||
uint16_t max_vpi; /* Maximum virtual nports */
|
uint16_t max_vpi; /* Maximum virtual nports */
|
||||||
uint16_t vpi_cnt; /* Nport count */
|
|
||||||
#define LPFC_MAX_VPI 100 /* Max number of VPorts supported */
|
#define LPFC_MAX_VPI 100 /* Max number of VPorts supported */
|
||||||
unsigned long *vpi_bmask; /* vpi allocation table */
|
unsigned long *vpi_bmask; /* vpi allocation table */
|
||||||
|
|
||||||
|
@ -531,6 +544,15 @@ struct lpfc_hba {
|
||||||
unsigned long last_rsrc_error_time;
|
unsigned long last_rsrc_error_time;
|
||||||
unsigned long last_ramp_down_time;
|
unsigned long last_ramp_down_time;
|
||||||
unsigned long last_ramp_up_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 *
|
static inline struct Scsi_Host *
|
||||||
|
|
|
@ -282,9 +282,7 @@ lpfc_issue_lip(struct Scsi_Host *shost)
|
||||||
}
|
}
|
||||||
|
|
||||||
lpfc_set_loopback_flag(phba);
|
lpfc_set_loopback_flag(phba);
|
||||||
if (mbxstatus == MBX_TIMEOUT)
|
if (mbxstatus != MBX_TIMEOUT)
|
||||||
pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
|
|
||||||
else
|
|
||||||
mempool_free(pmboxq, phba->mbox_mem_pool);
|
mempool_free(pmboxq, phba->mbox_mem_pool);
|
||||||
|
|
||||||
if (mbxstatus == MBXERR_ERROR)
|
if (mbxstatus == MBXERR_ERROR)
|
||||||
|
@ -439,30 +437,11 @@ lpfc_board_mode_store(struct class_device *cdev, const char *buf, size_t count)
|
||||||
return -EIO;
|
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
|
int
|
||||||
lpfc_get_hba_info(struct lpfc_hba *phba, uint32_t *mxri,
|
lpfc_get_hba_info(struct lpfc_hba *phba,
|
||||||
uint32_t *axri, uint32_t *mrpi, uint32_t *arpi)
|
uint32_t *mxri, uint32_t *axri,
|
||||||
|
uint32_t *mrpi, uint32_t *arpi,
|
||||||
|
uint32_t *mvpi, uint32_t *avpi)
|
||||||
{
|
{
|
||||||
struct lpfc_sli *psli = &phba->sli;
|
struct lpfc_sli *psli = &phba->sli;
|
||||||
LPFC_MBOXQ_t *pmboxq;
|
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);
|
rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
|
||||||
|
|
||||||
if (rc != MBX_SUCCESS) {
|
if (rc != MBX_SUCCESS) {
|
||||||
if (rc == MBX_TIMEOUT)
|
if (rc != MBX_TIMEOUT)
|
||||||
pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
|
|
||||||
else
|
|
||||||
mempool_free(pmboxq, phba->mbox_mem_pool);
|
mempool_free(pmboxq, phba->mbox_mem_pool);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -513,6 +490,10 @@ lpfc_get_hba_info(struct lpfc_hba *phba, uint32_t *mxri,
|
||||||
*mxri = pmb->un.varRdConfig.max_xri;
|
*mxri = pmb->un.varRdConfig.max_xri;
|
||||||
if (axri)
|
if (axri)
|
||||||
*axri = pmb->un.varRdConfig.avail_xri;
|
*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);
|
mempool_free(pmboxq, phba->mbox_mem_pool);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -526,7 +507,7 @@ lpfc_max_rpi_show(struct class_device *cdev, char *buf)
|
||||||
struct lpfc_hba *phba = vport->phba;
|
struct lpfc_hba *phba = vport->phba;
|
||||||
uint32_t cnt;
|
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, "%d\n", cnt);
|
||||||
return snprintf(buf, PAGE_SIZE, "Unknown\n");
|
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;
|
struct lpfc_hba *phba = vport->phba;
|
||||||
uint32_t cnt, acnt;
|
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, "%d\n", (cnt - acnt));
|
||||||
return snprintf(buf, PAGE_SIZE, "Unknown\n");
|
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;
|
struct lpfc_hba *phba = vport->phba;
|
||||||
uint32_t cnt;
|
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, "%d\n", cnt);
|
||||||
return snprintf(buf, PAGE_SIZE, "Unknown\n");
|
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;
|
struct lpfc_hba *phba = vport->phba;
|
||||||
uint32_t cnt, acnt;
|
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, "%d\n", (cnt - acnt));
|
||||||
return snprintf(buf, PAGE_SIZE, "Unknown\n");
|
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,"
|
" 2 - select SLI-2 even on SLI-3 capable HBAs,"
|
||||||
" 3 - select SLI-3");
|
" 3 - select SLI-3");
|
||||||
|
|
||||||
int lpfc_npiv_enable = 0;
|
LPFC_ATTR_R(npiv_enable, 0, 0, 1, "Enable NPIV functionality");
|
||||||
module_param(lpfc_npiv_enable, int, 0);
|
|
||||||
MODULE_PARM_DESC(lpfc_npiv_enable, "Enable NPIV functionality");
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
# lpfc_nodev_tmo: If set, it will hold all I/O errors on devices that disappear
|
# 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;
|
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
|
static int
|
||||||
lpfc_nodev_tmo_set(struct lpfc_hba *phba, int val)
|
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) {
|
if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) {
|
||||||
phba->cfg_nodev_tmo = val;
|
phba->cfg_nodev_tmo = val;
|
||||||
phba->cfg_devloss_tmo = val;
|
phba->cfg_devloss_tmo = val;
|
||||||
|
lpfc_update_rport_devloss_tmo(phba);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1102,6 +1126,7 @@ lpfc_devloss_tmo_set(struct lpfc_hba *phba, int val)
|
||||||
phba->cfg_nodev_tmo = val;
|
phba->cfg_nodev_tmo = val;
|
||||||
phba->cfg_devloss_tmo = val;
|
phba->cfg_devloss_tmo = val;
|
||||||
phba->dev_loss_tmo_changed = 1;
|
phba->dev_loss_tmo_changed = 1;
|
||||||
|
lpfc_update_rport_devloss_tmo(phba);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1358,6 +1383,7 @@ struct class_device_attribute *lpfc_hba_attrs[] = {
|
||||||
&class_device_attr_lpfc_multi_ring_type,
|
&class_device_attr_lpfc_multi_ring_type,
|
||||||
&class_device_attr_lpfc_fdmi_on,
|
&class_device_attr_lpfc_fdmi_on,
|
||||||
&class_device_attr_lpfc_max_luns,
|
&class_device_attr_lpfc_max_luns,
|
||||||
|
&class_device_attr_lpfc_npiv_enable,
|
||||||
&class_device_attr_nport_evt_cnt,
|
&class_device_attr_nport_evt_cnt,
|
||||||
&class_device_attr_management_version,
|
&class_device_attr_management_version,
|
||||||
&class_device_attr_board_mode,
|
&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_SUCCESS) {
|
||||||
if (rc == MBX_TIMEOUT) {
|
if (rc == MBX_TIMEOUT) {
|
||||||
phba->sysfs_mbox.mbox->mbox_cmpl =
|
|
||||||
lpfc_sli_def_mbox_cmpl;
|
|
||||||
phba->sysfs_mbox.mbox = NULL;
|
phba->sysfs_mbox.mbox = NULL;
|
||||||
}
|
}
|
||||||
sysfs_mbox_idle(phba);
|
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);
|
rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
|
||||||
|
|
||||||
if (rc != MBX_SUCCESS) {
|
if (rc != MBX_SUCCESS) {
|
||||||
if (rc == MBX_TIMEOUT)
|
if (rc != MBX_TIMEOUT)
|
||||||
pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
|
|
||||||
else
|
|
||||||
mempool_free(pmboxq, phba->mbox_mem_pool);
|
mempool_free(pmboxq, phba->mbox_mem_pool);
|
||||||
return NULL;
|
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);
|
rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
|
||||||
|
|
||||||
if (rc != MBX_SUCCESS) {
|
if (rc != MBX_SUCCESS) {
|
||||||
if (rc == MBX_TIMEOUT)
|
if (rc != MBX_TIMEOUT)
|
||||||
pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
|
|
||||||
else
|
|
||||||
mempool_free(pmboxq, phba->mbox_mem_pool);
|
mempool_free(pmboxq, phba->mbox_mem_pool);
|
||||||
return NULL;
|
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);
|
rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
|
||||||
|
|
||||||
if (rc != MBX_SUCCESS) {
|
if (rc != MBX_SUCCESS) {
|
||||||
if (rc == MBX_TIMEOUT)
|
if (rc != MBX_TIMEOUT)
|
||||||
pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
|
|
||||||
else
|
|
||||||
mempool_free(pmboxq, phba->mbox_mem_pool);
|
mempool_free(pmboxq, phba->mbox_mem_pool);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2013,9 +2031,7 @@ lpfc_reset_stats(struct Scsi_Host *shost)
|
||||||
rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
|
rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
|
||||||
|
|
||||||
if (rc != MBX_SUCCESS) {
|
if (rc != MBX_SUCCESS) {
|
||||||
if (rc == MBX_TIMEOUT)
|
if (rc != MBX_TIMEOUT)
|
||||||
pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
|
|
||||||
else
|
|
||||||
mempool_free( pmboxq, phba->mbox_mem_pool);
|
mempool_free( pmboxq, phba->mbox_mem_pool);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2253,6 +2269,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
|
||||||
lpfc_max_luns_init(phba, lpfc_max_luns);
|
lpfc_max_luns_init(phba, lpfc_max_luns);
|
||||||
lpfc_poll_tmo_init(phba, lpfc_poll_tmo);
|
lpfc_poll_tmo_init(phba, lpfc_poll_tmo);
|
||||||
lpfc_peer_port_login_init(phba, lpfc_peer_port_login);
|
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_vport_restrict_login_init(phba, lpfc_vport_restrict_login);
|
||||||
lpfc_use_msi_init(phba, lpfc_use_msi);
|
lpfc_use_msi_init(phba, lpfc_use_msi);
|
||||||
lpfc_devloss_tmo_init(phba, lpfc_devloss_tmo);
|
lpfc_devloss_tmo_init(phba, lpfc_devloss_tmo);
|
||||||
|
|
|
@ -23,6 +23,7 @@ typedef int (*node_filter)(struct lpfc_nodelist *ndlp, void *param);
|
||||||
struct fc_rport;
|
struct fc_rport;
|
||||||
void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t);
|
void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t);
|
||||||
void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_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,
|
int lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb,
|
||||||
struct lpfc_dmabuf *mp);
|
struct lpfc_dmabuf *mp);
|
||||||
void lpfc_clear_la(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
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_clear_la(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||||
void lpfc_mbx_cmpl_reg_login(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_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_ns_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||||
void lpfc_mbx_cmpl_fdmi_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 *,
|
int lpfc_check_sparm(struct lpfc_vport *, struct lpfc_nodelist *,
|
||||||
struct serv_parm *, uint32_t);
|
struct serv_parm *, uint32_t);
|
||||||
int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist *);
|
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_els_abort_flogi(struct lpfc_hba *);
|
||||||
int lpfc_initial_flogi(struct lpfc_vport *);
|
int lpfc_initial_flogi(struct lpfc_vport *);
|
||||||
int lpfc_initial_fdisc(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_npiv_logo(struct lpfc_vport *, struct lpfc_nodelist *);
|
||||||
int lpfc_issue_els_scr(struct lpfc_vport *, uint32_t, uint8_t);
|
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_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 *,
|
int lpfc_els_rsp_acc(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *,
|
||||||
struct lpfc_nodelist *, LPFC_MBOXQ_t *, uint8_t);
|
struct lpfc_nodelist *, LPFC_MBOXQ_t *, uint8_t);
|
||||||
int lpfc_els_rsp_reject(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *,
|
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 *,
|
int lpfc_els_rsp_adisc_acc(struct lpfc_vport *, struct lpfc_iocbq *,
|
||||||
struct lpfc_nodelist *);
|
struct lpfc_nodelist *);
|
||||||
int lpfc_els_rsp_prli_acc(struct lpfc_vport *, struct lpfc_iocbq *,
|
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_cancel_retry_delay_tmo(struct lpfc_vport *, struct lpfc_nodelist *);
|
||||||
void lpfc_els_retry_delay(unsigned long);
|
void lpfc_els_retry_delay(unsigned long);
|
||||||
void lpfc_els_retry_delay_handler(struct lpfc_nodelist *);
|
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 *,
|
void lpfc_els_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *,
|
||||||
struct lpfc_iocbq *);
|
struct lpfc_iocbq *);
|
||||||
int lpfc_els_handle_rscn(struct lpfc_vport *);
|
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 *);
|
int lpfc_els_disc_plogi(struct lpfc_vport *);
|
||||||
void lpfc_els_timeout(unsigned long);
|
void lpfc_els_timeout(unsigned long);
|
||||||
void lpfc_els_timeout_handler(struct lpfc_vport *);
|
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 *,
|
void lpfc_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *,
|
||||||
struct lpfc_iocbq *);
|
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 *);
|
void lpfc_in_buf_free(struct lpfc_hba *, struct lpfc_dmabuf *);
|
||||||
/* Function prototypes. */
|
/* Function prototypes. */
|
||||||
const char* lpfc_info(struct Scsi_Host *);
|
const char* lpfc_info(struct Scsi_Host *);
|
||||||
void lpfc_scan_start(struct Scsi_Host *);
|
|
||||||
int lpfc_scan_finished(struct Scsi_Host *, unsigned long);
|
int lpfc_scan_finished(struct Scsi_Host *, unsigned long);
|
||||||
|
|
||||||
void lpfc_get_cfgparam(struct lpfc_hba *);
|
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_transport_functions;
|
||||||
extern struct fc_function_template lpfc_vport_transport_functions;
|
extern struct fc_function_template lpfc_vport_transport_functions;
|
||||||
extern int lpfc_sli_mode;
|
extern int lpfc_sli_mode;
|
||||||
extern int lpfc_npiv_enable;
|
|
||||||
|
|
||||||
int lpfc_vport_symbolic_node_name(struct lpfc_vport *, char *, size_t);
|
int lpfc_vport_symbolic_node_name(struct lpfc_vport *, char *, size_t);
|
||||||
void lpfc_terminate_rport_io(struct fc_rport *);
|
void lpfc_terminate_rport_io(struct fc_rport *);
|
||||||
|
@ -262,6 +267,11 @@ void destroy_port(struct lpfc_vport *);
|
||||||
int lpfc_get_instance(void);
|
int lpfc_get_instance(void);
|
||||||
void lpfc_host_attrib_init(struct Scsi_Host *);
|
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 */
|
/* Interface exported by fabric iocb scheduler */
|
||||||
int lpfc_issue_fabric_iocb(struct lpfc_hba *, struct lpfc_iocbq *);
|
int lpfc_issue_fabric_iocb(struct lpfc_hba *, struct lpfc_iocbq *);
|
||||||
void lpfc_fabric_abort_vport(struct lpfc_vport *);
|
void lpfc_fabric_abort_vport(struct lpfc_vport *);
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#include "lpfc_crtn.h"
|
#include "lpfc_crtn.h"
|
||||||
#include "lpfc_version.h"
|
#include "lpfc_version.h"
|
||||||
#include "lpfc_vport.h"
|
#include "lpfc_vport.h"
|
||||||
|
#include "lpfc_debugfs.h"
|
||||||
|
|
||||||
#define HBA_PORTSPEED_UNKNOWN 0 /* Unknown - transceiver
|
#define HBA_PORTSPEED_UNKNOWN 0 /* Unknown - transceiver
|
||||||
* incapable of reporting */
|
* incapable of reporting */
|
||||||
|
@ -251,6 +252,32 @@ lpfc_alloc_ct_rsp(struct lpfc_hba *phba, int cmdcode, struct ulp_bde64 *bpl,
|
||||||
return mlist;
|
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
|
static int
|
||||||
lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp,
|
lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp,
|
||||||
struct lpfc_dmabuf *inp, struct lpfc_dmabuf *outp,
|
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)) {
|
(!phba->cfg_vport_restrict_login)) {
|
||||||
ndlp = lpfc_setup_disc_node(vport, Did);
|
ndlp = lpfc_setup_disc_node(vport, Did);
|
||||||
if (ndlp) {
|
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,
|
lpfc_printf_log(phba, KERN_INFO,
|
||||||
LOG_DISCOVERY,
|
LOG_DISCOVERY,
|
||||||
"%d (%d):0238 Process "
|
"%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_flag,
|
||||||
vport->fc_rscn_id_cnt);
|
vport->fc_rscn_id_cnt);
|
||||||
} else {
|
} 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,
|
lpfc_printf_log(phba, KERN_INFO,
|
||||||
LOG_DISCOVERY,
|
LOG_DISCOVERY,
|
||||||
"%d (%d):0239 Skip x%x "
|
"%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 {
|
} else {
|
||||||
if (!(vport->fc_flag & FC_RSCN_MODE) ||
|
if (!(vport->fc_flag & FC_RSCN_MODE) ||
|
||||||
(lpfc_rscn_payload_check(vport, Did))) {
|
(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,
|
if (lpfc_ns_cmd(vport,
|
||||||
SLI_CTNS_GFF_ID,
|
SLI_CTNS_GFF_ID,
|
||||||
0, Did) == 0)
|
0, Did) == 0)
|
||||||
vport->num_disc_nodes++;
|
vport->num_disc_nodes++;
|
||||||
}
|
}
|
||||||
else {
|
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,
|
lpfc_printf_log(phba, KERN_INFO,
|
||||||
LOG_DISCOVERY,
|
LOG_DISCOVERY,
|
||||||
"%d (%d):0245 Skip x%x "
|
"%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);
|
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
|
||||||
IOCB_t *irsp;
|
IOCB_t *irsp;
|
||||||
struct lpfc_dmabuf *bmp;
|
struct lpfc_dmabuf *bmp;
|
||||||
struct lpfc_dmabuf *inp;
|
|
||||||
struct lpfc_dmabuf *outp;
|
struct lpfc_dmabuf *outp;
|
||||||
struct lpfc_sli_ct_request *CTrsp;
|
struct lpfc_sli_ct_request *CTrsp;
|
||||||
int rc;
|
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 */
|
/* we pass cmdiocb to state machine which needs rspiocb as well */
|
||||||
cmdiocb->context_un.rsp_iocb = rspiocb;
|
cmdiocb->context_un.rsp_iocb = rspiocb;
|
||||||
|
|
||||||
inp = (struct lpfc_dmabuf *) cmdiocb->context1;
|
|
||||||
outp = (struct lpfc_dmabuf *) cmdiocb->context2;
|
outp = (struct lpfc_dmabuf *) cmdiocb->context2;
|
||||||
bmp = (struct lpfc_dmabuf *) cmdiocb->context3;
|
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. */
|
/* Don't bother processing response if vport is being torn down. */
|
||||||
if (vport->load_flag & FC_UNLOADING)
|
if (vport->load_flag & FC_UNLOADING)
|
||||||
goto out;
|
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 */
|
/* Check for retry */
|
||||||
if (vport->fc_ns_retry < LPFC_MAX_NS_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 */
|
/* CT command is being retried */
|
||||||
rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_FT,
|
rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_FT,
|
||||||
vport->fc_ns_retry, 0);
|
vport->fc_ns_retry, 0);
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
err1:
|
|
||||||
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
|
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
|
||||||
lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
|
lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
|
||||||
"%d (%d):0257 GID_FT Query error: 0x%x 0x%x\n",
|
"%d (%d):0257 GID_FT Query error: 0x%x 0x%x\n",
|
||||||
|
@ -553,6 +615,13 @@ err1:
|
||||||
(uint32_t) CTrsp->ReasonCode,
|
(uint32_t) CTrsp->ReasonCode,
|
||||||
(uint32_t) CTrsp->Explanation,
|
(uint32_t) CTrsp->Explanation,
|
||||||
vport->fc_flag);
|
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 {
|
} else {
|
||||||
/* NameServer Rsp Error */
|
/* NameServer Rsp Error */
|
||||||
lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
|
lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
|
||||||
|
@ -563,6 +632,12 @@ err1:
|
||||||
(uint32_t) CTrsp->ReasonCode,
|
(uint32_t) CTrsp->ReasonCode,
|
||||||
(uint32_t) CTrsp->Explanation,
|
(uint32_t) CTrsp->Explanation,
|
||||||
vport->fc_flag);
|
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 */
|
/* Link up / RSCN discovery */
|
||||||
|
@ -586,12 +661,7 @@ err1:
|
||||||
lpfc_disc_start(vport);
|
lpfc_disc_start(vport);
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
lpfc_free_ct_rsp(phba, outp);
|
lpfc_ct_free_iocb(phba, cmdiocb);
|
||||||
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);
|
|
||||||
return;
|
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 lpfc_vport *vport = cmdiocb->vport;
|
||||||
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
|
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
|
||||||
IOCB_t *irsp = &rspiocb->iocb;
|
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 *inp = (struct lpfc_dmabuf *) cmdiocb->context1;
|
||||||
struct lpfc_dmabuf *outp = (struct lpfc_dmabuf *) cmdiocb->context2;
|
struct lpfc_dmabuf *outp = (struct lpfc_dmabuf *) cmdiocb->context2;
|
||||||
struct lpfc_sli_ct_request *CTrsp;
|
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 = ((struct lpfc_sli_ct_request *) inp->virt)->un.gff.PortId;
|
||||||
did = be32_to_cpu(did);
|
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) {
|
if (irsp->ulpStatus == IOSTAT_SUCCESS) {
|
||||||
/* Good status, continue checking */
|
/* Good status, continue checking */
|
||||||
CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
|
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 */
|
/* This is a target port, unregistered port, or the GFF_ID failed */
|
||||||
ndlp = lpfc_setup_disc_node(vport, did);
|
ndlp = lpfc_setup_disc_node(vport, did);
|
||||||
if (ndlp) {
|
if (ndlp) {
|
||||||
|
@ -670,13 +752,7 @@ out:
|
||||||
}
|
}
|
||||||
lpfc_disc_start(vport);
|
lpfc_disc_start(vport);
|
||||||
}
|
}
|
||||||
|
lpfc_ct_free_iocb(phba, cmdiocb);
|
||||||
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);
|
|
||||||
return;
|
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_iocbq *rspiocb)
|
||||||
{
|
{
|
||||||
struct lpfc_vport *vport = cmdiocb->vport;
|
struct lpfc_vport *vport = cmdiocb->vport;
|
||||||
struct lpfc_dmabuf *bmp;
|
|
||||||
struct lpfc_dmabuf *inp;
|
struct lpfc_dmabuf *inp;
|
||||||
struct lpfc_dmabuf *outp;
|
struct lpfc_dmabuf *outp;
|
||||||
IOCB_t *irsp;
|
IOCB_t *irsp;
|
||||||
struct lpfc_sli_ct_request *CTrsp;
|
struct lpfc_sli_ct_request *CTrsp;
|
||||||
int cmdcode, rc;
|
int cmdcode, rc;
|
||||||
uint8_t retry;
|
uint8_t retry;
|
||||||
|
uint32_t latt;
|
||||||
|
|
||||||
/* we pass cmdiocb to state machine which needs rspiocb as well */
|
/* we pass cmdiocb to state machine which needs rspiocb as well */
|
||||||
cmdiocb->context_un.rsp_iocb = rspiocb;
|
cmdiocb->context_un.rsp_iocb = rspiocb;
|
||||||
|
|
||||||
inp = (struct lpfc_dmabuf *) cmdiocb->context1;
|
inp = (struct lpfc_dmabuf *) cmdiocb->context1;
|
||||||
outp = (struct lpfc_dmabuf *) cmdiocb->context2;
|
outp = (struct lpfc_dmabuf *) cmdiocb->context2;
|
||||||
bmp = (struct lpfc_dmabuf *) cmdiocb->context3;
|
|
||||||
irsp = &rspiocb->iocb;
|
irsp = &rspiocb->iocb;
|
||||||
|
|
||||||
cmdcode = be16_to_cpu(((struct lpfc_sli_ct_request *) inp->virt)->
|
cmdcode = be16_to_cpu(((struct lpfc_sli_ct_request *) inp->virt)->
|
||||||
CommandResponse.bits.CmdRsp);
|
CommandResponse.bits.CmdRsp);
|
||||||
CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
|
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,
|
lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
|
||||||
"%d (%d):0209 NS request %x completes "
|
"%d (%d):0209 RFT request completes, latt %d, "
|
||||||
"ulpStatus x%x / x%x "
|
"ulpStatus x%x CmdRsp x%x, Context x%x, Tag x%x\n",
|
||||||
"CmdRsp x%x, Context x%x, Tag x%x\n",
|
phba->brd_no, vport->vpi, latt, irsp->ulpStatus,
|
||||||
phba->brd_no, vport->vpi,
|
|
||||||
cmdcode, irsp->ulpStatus, irsp->un.ulpWord[4],
|
|
||||||
CTrsp->CommandResponse.bits.CmdRsp,
|
CTrsp->CommandResponse.bits.CmdRsp,
|
||||||
cmdiocb->iocb.ulpContext, cmdiocb->iocb.ulpIoTag);
|
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) {
|
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) &&
|
if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
|
||||||
((irsp->un.ulpWord[4] == IOERR_SLI_DOWN) ||
|
((irsp->un.ulpWord[4] == IOERR_SLI_DOWN) ||
|
||||||
(irsp->un.ulpWord[4] == IOERR_SLI_ABORTED)))
|
(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:
|
out:
|
||||||
lpfc_free_ct_rsp(phba, outp);
|
lpfc_ct_free_iocb(phba, cmdiocb);
|
||||||
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);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -840,31 +919,42 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
|
||||||
struct lpfc_iocbq *) = NULL;
|
struct lpfc_iocbq *) = NULL;
|
||||||
uint32_t rsp_size = 1024;
|
uint32_t rsp_size = 1024;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
ndlp = lpfc_findnode_did(vport, NameServer_DID);
|
ndlp = lpfc_findnode_did(vport, NameServer_DID);
|
||||||
if (ndlp == NULL || ndlp->nlp_state != NLP_STE_UNMAPPED_NODE)
|
if (ndlp == NULL || ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) {
|
||||||
return 1;
|
rc=1;
|
||||||
|
goto ns_cmd_exit;
|
||||||
|
}
|
||||||
|
|
||||||
/* fill in BDEs for command */
|
/* fill in BDEs for command */
|
||||||
/* Allocate buffer for command payload */
|
/* Allocate buffer for command payload */
|
||||||
mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL);
|
mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL);
|
||||||
if (!mp)
|
if (!mp) {
|
||||||
|
rc=2;
|
||||||
goto ns_cmd_exit;
|
goto ns_cmd_exit;
|
||||||
|
}
|
||||||
|
|
||||||
INIT_LIST_HEAD(&mp->list);
|
INIT_LIST_HEAD(&mp->list);
|
||||||
mp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(mp->phys));
|
mp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(mp->phys));
|
||||||
if (!mp->virt)
|
if (!mp->virt) {
|
||||||
|
rc=3;
|
||||||
goto ns_cmd_free_mp;
|
goto ns_cmd_free_mp;
|
||||||
|
}
|
||||||
|
|
||||||
/* Allocate buffer for Buffer ptr list */
|
/* Allocate buffer for Buffer ptr list */
|
||||||
bmp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL);
|
bmp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL);
|
||||||
if (!bmp)
|
if (!bmp) {
|
||||||
|
rc=4;
|
||||||
goto ns_cmd_free_mpvirt;
|
goto ns_cmd_free_mpvirt;
|
||||||
|
}
|
||||||
|
|
||||||
INIT_LIST_HEAD(&bmp->list);
|
INIT_LIST_HEAD(&bmp->list);
|
||||||
bmp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(bmp->phys));
|
bmp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(bmp->phys));
|
||||||
if (!bmp->virt)
|
if (!bmp->virt) {
|
||||||
|
rc=5;
|
||||||
goto ns_cmd_free_bmp;
|
goto ns_cmd_free_bmp;
|
||||||
|
}
|
||||||
|
|
||||||
/* NameServer Req */
|
/* NameServer Req */
|
||||||
lpfc_printf_log(phba, KERN_INFO ,LOG_DISCOVERY,
|
lpfc_printf_log(phba, KERN_INFO ,LOG_DISCOVERY,
|
||||||
|
@ -970,10 +1060,15 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
|
||||||
break;
|
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 */
|
/* 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;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc=6;
|
||||||
lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
|
lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
|
||||||
ns_cmd_free_bmp:
|
ns_cmd_free_bmp:
|
||||||
kfree(bmp);
|
kfree(bmp);
|
||||||
|
@ -982,6 +1077,10 @@ ns_cmd_free_mpvirt:
|
||||||
ns_cmd_free_mp:
|
ns_cmd_free_mp:
|
||||||
kfree(mp);
|
kfree(mp);
|
||||||
ns_cmd_exit:
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -989,7 +1088,6 @@ static void
|
||||||
lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||||
struct lpfc_iocbq * rspiocb)
|
struct lpfc_iocbq * rspiocb)
|
||||||
{
|
{
|
||||||
struct lpfc_dmabuf *bmp = cmdiocb->context3;
|
|
||||||
struct lpfc_dmabuf *inp = cmdiocb->context1;
|
struct lpfc_dmabuf *inp = cmdiocb->context1;
|
||||||
struct lpfc_dmabuf *outp = cmdiocb->context2;
|
struct lpfc_dmabuf *outp = cmdiocb->context2;
|
||||||
struct lpfc_sli_ct_request *CTrsp = outp->virt;
|
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_cmd = CTcmd->CommandResponse.bits.CmdRsp;
|
||||||
uint16_t fdmi_rsp = CTrsp->CommandResponse.bits.CmdRsp;
|
uint16_t fdmi_rsp = CTrsp->CommandResponse.bits.CmdRsp;
|
||||||
struct lpfc_vport *vport = cmdiocb->vport;
|
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_cpu(fdmi_cmd), latt, irsp->ulpStatus,
|
||||||
|
irsp->un.ulpWord[4]);
|
||||||
|
lpfc_ct_free_iocb(phba, cmdiocb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ndlp = lpfc_findnode_did(vport, FDMI_DID);
|
ndlp = lpfc_findnode_did(vport, FDMI_DID);
|
||||||
if (fdmi_rsp == be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) {
|
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,
|
||||||
lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RHBA);
|
lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RHBA);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
lpfc_ct_free_iocb(phba, cmdiocb);
|
||||||
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);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,508 @@
|
||||||
|
/*******************************************************************
|
||||||
|
* This file is part of the Emulex Linux Device Driver for *
|
||||||
|
* Fibre Channel Host Bus Adapters. *
|
||||||
|
* Copyright (C) 2007 Emulex. All rights reserved. *
|
||||||
|
* EMULEX and SLI are trademarks of Emulex. *
|
||||||
|
* www.emulex.com *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of version 2 of the GNU General *
|
||||||
|
* Public License as published by the Free Software Foundation. *
|
||||||
|
* This program is distributed in the hope that it will be useful. *
|
||||||
|
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
|
||||||
|
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
|
||||||
|
* DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
|
||||||
|
* TO BE LEGALLY INVALID. See the GNU General Public License for *
|
||||||
|
* more details, a copy of which can be found in the file COPYING *
|
||||||
|
* included with this package. *
|
||||||
|
*******************************************************************/
|
||||||
|
|
||||||
|
#include <linux/blkdev.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/dma-mapping.h>
|
||||||
|
#include <linux/idr.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/kthread.h>
|
||||||
|
#include <linux/pci.h>
|
||||||
|
#include <linux/spinlock.h>
|
||||||
|
#include <linux/ctype.h>
|
||||||
|
#include <linux/version.h>
|
||||||
|
|
||||||
|
#include <scsi/scsi.h>
|
||||||
|
#include <scsi/scsi_device.h>
|
||||||
|
#include <scsi/scsi_host.h>
|
||||||
|
#include <scsi/scsi_transport_fc.h>
|
||||||
|
|
||||||
|
#include "lpfc_hw.h"
|
||||||
|
#include "lpfc_sli.h"
|
||||||
|
#include "lpfc_disc.h"
|
||||||
|
#include "lpfc_scsi.h"
|
||||||
|
#include "lpfc.h"
|
||||||
|
#include "lpfc_logmsg.h"
|
||||||
|
#include "lpfc_crtn.h"
|
||||||
|
#include "lpfc_vport.h"
|
||||||
|
#include "lpfc_version.h"
|
||||||
|
#include "lpfc_vport.h"
|
||||||
|
#include "lpfc_debugfs.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_LPFC_DEBUG_FS
|
||||||
|
/* debugfs interface
|
||||||
|
*
|
||||||
|
* To access this interface the user should:
|
||||||
|
* # mkdir /debug
|
||||||
|
* # mount -t debugfs none /debug
|
||||||
|
*
|
||||||
|
* The lpfc debugfs directory hierachy is:
|
||||||
|
* lpfc/lpfcX/vportY
|
||||||
|
* where X is the lpfc hba unique_id
|
||||||
|
* where Y is the vport VPI on that hba
|
||||||
|
*
|
||||||
|
* Debugging services available per vport:
|
||||||
|
* discovery_trace
|
||||||
|
* This is an ACSII readable file that contains a trace of the last
|
||||||
|
* lpfc_debugfs_max_disc_trc events that happened on a specific vport.
|
||||||
|
* See lpfc_debugfs.h for different categories of
|
||||||
|
* discovery events. To enable the discovery trace, the following
|
||||||
|
* module parameters must be set:
|
||||||
|
* lpfc_debugfs_enable=1 Turns on lpfc debugfs filesystem support
|
||||||
|
* lpfc_debugfs_max_disc_trc=X Where X is the event trace depth for
|
||||||
|
* EACH vport. X MUST also be a power of 2.
|
||||||
|
* lpfc_debugfs_mask_disc_trc=Y Where Y is an event mask as defined in
|
||||||
|
* lpfc_debugfs.h .
|
||||||
|
*/
|
||||||
|
static int lpfc_debugfs_enable = 0;
|
||||||
|
module_param(lpfc_debugfs_enable, int, 0);
|
||||||
|
MODULE_PARM_DESC(lpfc_debugfs_enable, "Enable debugfs services");
|
||||||
|
|
||||||
|
static int lpfc_debugfs_max_disc_trc = 0; /* This MUST be a power of 2 */
|
||||||
|
module_param(lpfc_debugfs_max_disc_trc, int, 0);
|
||||||
|
MODULE_PARM_DESC(lpfc_debugfs_max_disc_trc,
|
||||||
|
"Set debugfs discovery trace depth");
|
||||||
|
|
||||||
|
static int lpfc_debugfs_mask_disc_trc = 0;
|
||||||
|
module_param(lpfc_debugfs_mask_disc_trc, int, 0);
|
||||||
|
MODULE_PARM_DESC(lpfc_debugfs_mask_disc_trc,
|
||||||
|
"Set debugfs discovery trace mask");
|
||||||
|
|
||||||
|
#include <linux/debugfs.h>
|
||||||
|
|
||||||
|
/* size of discovery_trace output line */
|
||||||
|
#define LPFC_DISC_TRC_ENTRY_SIZE 80
|
||||||
|
|
||||||
|
/* nodelist output buffer size */
|
||||||
|
#define LPFC_NODELIST_SIZE 8192
|
||||||
|
#define LPFC_NODELIST_ENTRY_SIZE 120
|
||||||
|
|
||||||
|
struct lpfc_debug {
|
||||||
|
char *buffer;
|
||||||
|
int len;
|
||||||
|
};
|
||||||
|
|
||||||
|
atomic_t lpfc_debugfs_disc_trc_cnt = ATOMIC_INIT(0);
|
||||||
|
unsigned long lpfc_debugfs_start_time = 0L;
|
||||||
|
|
||||||
|
static int
|
||||||
|
lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size)
|
||||||
|
{
|
||||||
|
int i, index, len, enable;
|
||||||
|
uint32_t ms;
|
||||||
|
struct lpfc_disc_trc *dtp;
|
||||||
|
char buffer[80];
|
||||||
|
|
||||||
|
|
||||||
|
enable = lpfc_debugfs_enable;
|
||||||
|
lpfc_debugfs_enable = 0;
|
||||||
|
|
||||||
|
len = 0;
|
||||||
|
index = (atomic_read(&vport->disc_trc_cnt) + 1) &
|
||||||
|
(lpfc_debugfs_max_disc_trc - 1);
|
||||||
|
for (i = index; i < lpfc_debugfs_max_disc_trc; i++) {
|
||||||
|
dtp = vport->disc_trc + i;
|
||||||
|
if (!dtp->fmt)
|
||||||
|
continue;
|
||||||
|
ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time);
|
||||||
|
snprintf(buffer, 80, "%010d:%010d ms:%s\n",
|
||||||
|
dtp->seq_cnt, ms, dtp->fmt);
|
||||||
|
len += snprintf(buf+len, size-len, buffer,
|
||||||
|
dtp->data1, dtp->data2, dtp->data3);
|
||||||
|
}
|
||||||
|
for (i = 0; i < index; i++) {
|
||||||
|
dtp = vport->disc_trc + i;
|
||||||
|
if (!dtp->fmt)
|
||||||
|
continue;
|
||||||
|
ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time);
|
||||||
|
snprintf(buffer, 80, "%010d:%010d ms:%s\n",
|
||||||
|
dtp->seq_cnt, ms, dtp->fmt);
|
||||||
|
len += snprintf(buf+len, size-len, buffer,
|
||||||
|
dtp->data1, dtp->data2, dtp->data3);
|
||||||
|
}
|
||||||
|
|
||||||
|
lpfc_debugfs_enable = enable;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
|
||||||
|
{
|
||||||
|
int len = 0;
|
||||||
|
int cnt;
|
||||||
|
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
|
||||||
|
struct lpfc_nodelist *ndlp;
|
||||||
|
unsigned char *statep, *name;
|
||||||
|
|
||||||
|
cnt = (LPFC_NODELIST_SIZE / LPFC_NODELIST_ENTRY_SIZE);
|
||||||
|
|
||||||
|
spin_lock_irq(shost->host_lock);
|
||||||
|
list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
|
||||||
|
if (!cnt) {
|
||||||
|
len += snprintf(buf+len, size-len,
|
||||||
|
"Missing Nodelist Entries\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cnt--;
|
||||||
|
switch (ndlp->nlp_state) {
|
||||||
|
case NLP_STE_UNUSED_NODE:
|
||||||
|
statep = "UNUSED";
|
||||||
|
break;
|
||||||
|
case NLP_STE_PLOGI_ISSUE:
|
||||||
|
statep = "PLOGI ";
|
||||||
|
break;
|
||||||
|
case NLP_STE_ADISC_ISSUE:
|
||||||
|
statep = "ADISC ";
|
||||||
|
break;
|
||||||
|
case NLP_STE_REG_LOGIN_ISSUE:
|
||||||
|
statep = "REGLOG";
|
||||||
|
break;
|
||||||
|
case NLP_STE_PRLI_ISSUE:
|
||||||
|
statep = "PRLI ";
|
||||||
|
break;
|
||||||
|
case NLP_STE_UNMAPPED_NODE:
|
||||||
|
statep = "UNMAP ";
|
||||||
|
break;
|
||||||
|
case NLP_STE_MAPPED_NODE:
|
||||||
|
statep = "MAPPED";
|
||||||
|
break;
|
||||||
|
case NLP_STE_NPR_NODE:
|
||||||
|
statep = "NPR ";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
statep = "UNKNOWN";
|
||||||
|
}
|
||||||
|
len += snprintf(buf+len, size-len, "%s DID:x%06x ",
|
||||||
|
statep, ndlp->nlp_DID);
|
||||||
|
name = (unsigned char *)&ndlp->nlp_portname;
|
||||||
|
len += snprintf(buf+len, size-len,
|
||||||
|
"WWPN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x ",
|
||||||
|
*name, *(name+1), *(name+2), *(name+3),
|
||||||
|
*(name+4), *(name+5), *(name+6), *(name+7));
|
||||||
|
name = (unsigned char *)&ndlp->nlp_nodename;
|
||||||
|
len += snprintf(buf+len, size-len,
|
||||||
|
"WWNN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x ",
|
||||||
|
*name, *(name+1), *(name+2), *(name+3),
|
||||||
|
*(name+4), *(name+5), *(name+6), *(name+7));
|
||||||
|
len += snprintf(buf+len, size-len, "RPI:%03d flag:x%08x ",
|
||||||
|
ndlp->nlp_rpi, ndlp->nlp_flag);
|
||||||
|
if (!ndlp->nlp_type)
|
||||||
|
len += snprintf(buf+len, size-len, "UNKNOWN_TYPE");
|
||||||
|
if (ndlp->nlp_type & NLP_FC_NODE)
|
||||||
|
len += snprintf(buf+len, size-len, "FC_NODE ");
|
||||||
|
if (ndlp->nlp_type & NLP_FABRIC)
|
||||||
|
len += snprintf(buf+len, size-len, "FABRIC ");
|
||||||
|
if (ndlp->nlp_type & NLP_FCP_TARGET)
|
||||||
|
len += snprintf(buf+len, size-len, "FCP_TGT sid:%d ",
|
||||||
|
ndlp->nlp_sid);
|
||||||
|
if (ndlp->nlp_type & NLP_FCP_INITIATOR)
|
||||||
|
len += snprintf(buf+len, size-len, "FCP_INITIATOR");
|
||||||
|
len += snprintf(buf+len, size-len, "\n");
|
||||||
|
}
|
||||||
|
spin_unlock_irq(shost->host_lock);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
inline void
|
||||||
|
lpfc_debugfs_disc_trc(struct lpfc_vport *vport, int mask, char *fmt,
|
||||||
|
uint32_t data1, uint32_t data2, uint32_t data3)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_LPFC_DEBUG_FS
|
||||||
|
struct lpfc_disc_trc *dtp;
|
||||||
|
int index;
|
||||||
|
|
||||||
|
if (!(lpfc_debugfs_mask_disc_trc & mask))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!lpfc_debugfs_enable || !lpfc_debugfs_max_disc_trc ||
|
||||||
|
!vport || !vport->disc_trc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
index = atomic_inc_return(&vport->disc_trc_cnt) &
|
||||||
|
(lpfc_debugfs_max_disc_trc - 1);
|
||||||
|
dtp = vport->disc_trc + index;
|
||||||
|
dtp->fmt = fmt;
|
||||||
|
dtp->data1 = data1;
|
||||||
|
dtp->data2 = data2;
|
||||||
|
dtp->data3 = data3;
|
||||||
|
dtp->seq_cnt = atomic_inc_return(&lpfc_debugfs_disc_trc_cnt);
|
||||||
|
dtp->jif = jiffies;
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_LPFC_DEBUG_FS
|
||||||
|
static int
|
||||||
|
lpfc_debugfs_disc_trc_open(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
struct lpfc_vport *vport = inode->i_private;
|
||||||
|
struct lpfc_debug *debug;
|
||||||
|
int size;
|
||||||
|
int rc = -ENOMEM;
|
||||||
|
|
||||||
|
if (!lpfc_debugfs_max_disc_trc) {
|
||||||
|
rc = -ENOSPC;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug = kmalloc(sizeof(*debug), GFP_KERNEL);
|
||||||
|
if (!debug)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* Round to page boundry */
|
||||||
|
size = (lpfc_debugfs_max_disc_trc * LPFC_DISC_TRC_ENTRY_SIZE);
|
||||||
|
size = PAGE_ALIGN(size);
|
||||||
|
|
||||||
|
debug->buffer = kmalloc(size, GFP_KERNEL);
|
||||||
|
if (!debug->buffer) {
|
||||||
|
kfree(debug);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug->len = lpfc_debugfs_disc_trc_data(vport, debug->buffer, size);
|
||||||
|
file->private_data = debug;
|
||||||
|
|
||||||
|
rc = 0;
|
||||||
|
out:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
lpfc_debugfs_nodelist_open(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
struct lpfc_vport *vport = inode->i_private;
|
||||||
|
struct lpfc_debug *debug;
|
||||||
|
int rc = -ENOMEM;
|
||||||
|
|
||||||
|
debug = kmalloc(sizeof(*debug), GFP_KERNEL);
|
||||||
|
if (!debug)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* Round to page boundry */
|
||||||
|
debug->buffer = kmalloc(LPFC_NODELIST_SIZE, GFP_KERNEL);
|
||||||
|
if (!debug->buffer) {
|
||||||
|
kfree(debug);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug->len = lpfc_debugfs_nodelist_data(vport, debug->buffer,
|
||||||
|
LPFC_NODELIST_SIZE);
|
||||||
|
file->private_data = debug;
|
||||||
|
|
||||||
|
rc = 0;
|
||||||
|
out:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static loff_t
|
||||||
|
lpfc_debugfs_lseek(struct file *file, loff_t off, int whence)
|
||||||
|
{
|
||||||
|
struct lpfc_debug *debug;
|
||||||
|
loff_t pos = -1;
|
||||||
|
|
||||||
|
debug = file->private_data;
|
||||||
|
|
||||||
|
switch (whence) {
|
||||||
|
case 0:
|
||||||
|
pos = off;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
pos = file->f_pos + off;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
pos = debug->len - off;
|
||||||
|
}
|
||||||
|
return (pos < 0 || pos > debug->len) ? -EINVAL : (file->f_pos = pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t
|
||||||
|
lpfc_debugfs_read(struct file *file, char __user *buf,
|
||||||
|
size_t nbytes, loff_t *ppos)
|
||||||
|
{
|
||||||
|
struct lpfc_debug *debug = file->private_data;
|
||||||
|
return simple_read_from_buffer(buf, nbytes, ppos, debug->buffer,
|
||||||
|
debug->len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
lpfc_debugfs_release(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
struct lpfc_debug *debug = file->private_data;
|
||||||
|
|
||||||
|
kfree(debug->buffer);
|
||||||
|
kfree(debug);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef lpfc_debugfs_op_disc_trc
|
||||||
|
static struct file_operations lpfc_debugfs_op_disc_trc = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.open = lpfc_debugfs_disc_trc_open,
|
||||||
|
.llseek = lpfc_debugfs_lseek,
|
||||||
|
.read = lpfc_debugfs_read,
|
||||||
|
.release = lpfc_debugfs_release,
|
||||||
|
};
|
||||||
|
|
||||||
|
#undef lpfc_debugfs_op_nodelist
|
||||||
|
static struct file_operations lpfc_debugfs_op_nodelist = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.open = lpfc_debugfs_nodelist_open,
|
||||||
|
.llseek = lpfc_debugfs_lseek,
|
||||||
|
.read = lpfc_debugfs_read,
|
||||||
|
.release = lpfc_debugfs_release,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct dentry *lpfc_debugfs_root = NULL;
|
||||||
|
static atomic_t lpfc_debugfs_hba_count;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline void
|
||||||
|
lpfc_debugfs_initialize(struct lpfc_vport *vport)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_LPFC_DEBUG_FS
|
||||||
|
struct lpfc_hba *phba = vport->phba;
|
||||||
|
char name[64];
|
||||||
|
uint32_t num, i;
|
||||||
|
|
||||||
|
if (!lpfc_debugfs_enable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (lpfc_debugfs_max_disc_trc) {
|
||||||
|
num = lpfc_debugfs_max_disc_trc - 1;
|
||||||
|
if (num & lpfc_debugfs_max_disc_trc) {
|
||||||
|
/* Change to be a power of 2 */
|
||||||
|
num = lpfc_debugfs_max_disc_trc;
|
||||||
|
i = 0;
|
||||||
|
while (num > 1) {
|
||||||
|
num = num >> 1;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
lpfc_debugfs_max_disc_trc = (1 << i);
|
||||||
|
printk(KERN_ERR
|
||||||
|
"lpfc_debugfs_max_disc_trc changed to %d\n",
|
||||||
|
lpfc_debugfs_max_disc_trc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lpfc_debugfs_root) {
|
||||||
|
lpfc_debugfs_root = debugfs_create_dir("lpfc", NULL);
|
||||||
|
atomic_set(&lpfc_debugfs_hba_count, 0);
|
||||||
|
if (!lpfc_debugfs_root)
|
||||||
|
goto debug_failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(name, sizeof(name), "lpfc%d", phba->brd_no);
|
||||||
|
if (!phba->hba_debugfs_root) {
|
||||||
|
phba->hba_debugfs_root =
|
||||||
|
debugfs_create_dir(name, lpfc_debugfs_root);
|
||||||
|
if (!phba->hba_debugfs_root)
|
||||||
|
goto debug_failed;
|
||||||
|
atomic_inc(&lpfc_debugfs_hba_count);
|
||||||
|
atomic_set(&phba->debugfs_vport_count, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(name, sizeof(name), "vport%d", vport->vpi);
|
||||||
|
if (!vport->vport_debugfs_root) {
|
||||||
|
vport->vport_debugfs_root =
|
||||||
|
debugfs_create_dir(name, phba->hba_debugfs_root);
|
||||||
|
if (!vport->vport_debugfs_root)
|
||||||
|
goto debug_failed;
|
||||||
|
atomic_inc(&phba->debugfs_vport_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lpfc_debugfs_start_time)
|
||||||
|
lpfc_debugfs_start_time = jiffies;
|
||||||
|
|
||||||
|
vport->disc_trc = kmalloc(
|
||||||
|
(sizeof(struct lpfc_disc_trc) * lpfc_debugfs_max_disc_trc),
|
||||||
|
GFP_KERNEL);
|
||||||
|
|
||||||
|
if (!vport->disc_trc)
|
||||||
|
goto debug_failed;
|
||||||
|
memset(vport->disc_trc, 0,
|
||||||
|
(sizeof(struct lpfc_disc_trc) * lpfc_debugfs_max_disc_trc));
|
||||||
|
|
||||||
|
snprintf(name, sizeof(name), "discovery_trace");
|
||||||
|
vport->debug_disc_trc =
|
||||||
|
debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
|
||||||
|
vport->vport_debugfs_root,
|
||||||
|
vport, &lpfc_debugfs_op_disc_trc);
|
||||||
|
if (!vport->debug_disc_trc) {
|
||||||
|
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||||
|
"%d:0409 Cannot create debugfs",
|
||||||
|
phba->brd_no);
|
||||||
|
goto debug_failed;
|
||||||
|
}
|
||||||
|
snprintf(name, sizeof(name), "nodelist");
|
||||||
|
vport->debug_nodelist =
|
||||||
|
debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
|
||||||
|
vport->vport_debugfs_root,
|
||||||
|
vport, &lpfc_debugfs_op_nodelist);
|
||||||
|
if (!vport->debug_nodelist) {
|
||||||
|
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||||
|
"%d:0409 Cannot create debugfs",
|
||||||
|
phba->brd_no);
|
||||||
|
goto debug_failed;
|
||||||
|
}
|
||||||
|
debug_failed:
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void
|
||||||
|
lpfc_debugfs_terminate(struct lpfc_vport *vport)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_LPFC_DEBUG_FS
|
||||||
|
struct lpfc_hba *phba = vport->phba;
|
||||||
|
|
||||||
|
if (vport->disc_trc) {
|
||||||
|
kfree(vport->disc_trc);
|
||||||
|
vport->disc_trc = NULL;
|
||||||
|
}
|
||||||
|
if (vport->debug_disc_trc) {
|
||||||
|
debugfs_remove(vport->debug_disc_trc); /* discovery_trace */
|
||||||
|
vport->debug_disc_trc = NULL;
|
||||||
|
}
|
||||||
|
if (vport->debug_nodelist) {
|
||||||
|
debugfs_remove(vport->debug_nodelist); /* nodelist */
|
||||||
|
vport->debug_nodelist = NULL;
|
||||||
|
}
|
||||||
|
if (vport->vport_debugfs_root) {
|
||||||
|
debugfs_remove(vport->vport_debugfs_root); /* vportX */
|
||||||
|
vport->vport_debugfs_root = NULL;
|
||||||
|
atomic_dec(&phba->debugfs_vport_count);
|
||||||
|
}
|
||||||
|
if (atomic_read(&phba->debugfs_vport_count) == 0) {
|
||||||
|
debugfs_remove(vport->phba->hba_debugfs_root); /* lpfcX */
|
||||||
|
vport->phba->hba_debugfs_root = NULL;
|
||||||
|
atomic_dec(&lpfc_debugfs_hba_count);
|
||||||
|
if (atomic_read(&lpfc_debugfs_hba_count) == 0) {
|
||||||
|
debugfs_remove(lpfc_debugfs_root); /* lpfc */
|
||||||
|
lpfc_debugfs_root = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*******************************************************************
|
||||||
|
* This file is part of the Emulex Linux Device Driver for *
|
||||||
|
* Fibre Channel Host Bus Adapters. *
|
||||||
|
* Copyright (C) 2007 Emulex. All rights reserved. *
|
||||||
|
* EMULEX and SLI are trademarks of Emulex. *
|
||||||
|
* www.emulex.com *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of version 2 of the GNU General *
|
||||||
|
* Public License as published by the Free Software Foundation. *
|
||||||
|
* This program is distributed in the hope that it will be useful. *
|
||||||
|
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
|
||||||
|
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
|
||||||
|
* DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
|
||||||
|
* TO BE LEGALLY INVALID. See the GNU General Public License for *
|
||||||
|
* more details, a copy of which can be found in the file COPYING *
|
||||||
|
* included with this package. *
|
||||||
|
*******************************************************************/
|
||||||
|
|
||||||
|
#ifndef _H_LPFC_DEBUG_FS
|
||||||
|
#define _H_LPFC_DEBUG_FS
|
||||||
|
|
||||||
|
#ifdef CONFIG_LPFC_DEBUG_FS
|
||||||
|
struct lpfc_disc_trc {
|
||||||
|
char *fmt;
|
||||||
|
uint32_t data1;
|
||||||
|
uint32_t data2;
|
||||||
|
uint32_t data3;
|
||||||
|
uint32_t seq_cnt;
|
||||||
|
unsigned long jif;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Mask for discovery_trace */
|
||||||
|
#define LPFC_DISC_TRC_ELS_CMD 0x1 /* Trace ELS commands */
|
||||||
|
#define LPFC_DISC_TRC_ELS_RSP 0x2 /* Trace ELS response */
|
||||||
|
#define LPFC_DISC_TRC_ELS_UNSOL 0x4 /* Trace ELS rcv'ed */
|
||||||
|
#define LPFC_DISC_TRC_ELS_ALL 0x7 /* Trace ELS */
|
||||||
|
#define LPFC_DISC_TRC_MBOX_VPORT 0x8 /* Trace vport MBOXs */
|
||||||
|
#define LPFC_DISC_TRC_MBOX 0x10 /* Trace other MBOXs */
|
||||||
|
#define LPFC_DISC_TRC_MBOX_ALL 0x18 /* Trace all MBOXs */
|
||||||
|
#define LPFC_DISC_TRC_CT 0x20 /* Trace disc CT requests */
|
||||||
|
#define LPFC_DISC_TRC_DSM 0x40 /* Trace DSM events */
|
||||||
|
#define LPFC_DISC_TRC_RPORT 0x80 /* Trace rport events */
|
||||||
|
#define LPFC_DISC_TRC_NODE 0x100 /* Trace ndlp state changes */
|
||||||
|
|
||||||
|
#define LPFC_DISC_TRC_DISCOVERY 0xef /* common mask for general
|
||||||
|
* discovery */
|
||||||
|
#endif /* H_LPFC_DEBUG_FS */
|
|
@ -36,6 +36,7 @@ enum lpfc_work_type {
|
||||||
LPFC_EVT_WARM_START,
|
LPFC_EVT_WARM_START,
|
||||||
LPFC_EVT_KILL,
|
LPFC_EVT_KILL,
|
||||||
LPFC_EVT_ELS_RETRY,
|
LPFC_EVT_ELS_RETRY,
|
||||||
|
LPFC_EVT_DEV_LOSS_DELAY,
|
||||||
LPFC_EVT_DEV_LOSS,
|
LPFC_EVT_DEV_LOSS,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -74,7 +75,6 @@ struct lpfc_nodelist {
|
||||||
#define NLP_FCP_2_DEVICE 0x10 /* FCP-2 device */
|
#define NLP_FCP_2_DEVICE 0x10 /* FCP-2 device */
|
||||||
|
|
||||||
struct timer_list nlp_delayfunc; /* Used for delayed ELS cmds */
|
struct timer_list nlp_delayfunc; /* Used for delayed ELS cmds */
|
||||||
struct timer_list nlp_initiator_tmr; /* Used with dev_loss */
|
|
||||||
struct fc_rport *rport; /* Corresponding FC transport
|
struct fc_rport *rport; /* Corresponding FC transport
|
||||||
port structure */
|
port structure */
|
||||||
struct lpfc_vport *vport;
|
struct lpfc_vport *vport;
|
||||||
|
@ -101,6 +101,7 @@ struct lpfc_nodelist {
|
||||||
ACC */
|
ACC */
|
||||||
#define NLP_NPR_ADISC 0x2000000 /* Issue ADISC when dq'ed from
|
#define NLP_NPR_ADISC 0x2000000 /* Issue ADISC when dq'ed from
|
||||||
NPR list */
|
NPR list */
|
||||||
|
#define NLP_RM_DFLT_RPI 0x4000000 /* need to remove leftover dflt RPI */
|
||||||
#define NLP_NODEV_REMOVE 0x8000000 /* Defer removal till discovery ends */
|
#define NLP_NODEV_REMOVE 0x8000000 /* Defer removal till discovery ends */
|
||||||
#define NLP_TARGET_REMOVE 0x10000000 /* Target remove in process */
|
#define NLP_TARGET_REMOVE 0x10000000 /* Target remove in process */
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include "lpfc_logmsg.h"
|
#include "lpfc_logmsg.h"
|
||||||
#include "lpfc_crtn.h"
|
#include "lpfc_crtn.h"
|
||||||
#include "lpfc_vport.h"
|
#include "lpfc_vport.h"
|
||||||
|
#include "lpfc_debugfs.h"
|
||||||
|
|
||||||
static int lpfc_els_retry(struct lpfc_hba *, struct lpfc_iocbq *,
|
static int lpfc_els_retry(struct lpfc_hba *, struct lpfc_iocbq *,
|
||||||
struct lpfc_iocbq *);
|
struct lpfc_iocbq *);
|
||||||
|
@ -44,7 +45,7 @@ static void lpfc_cmpl_fabric_iocb(struct lpfc_hba *, struct lpfc_iocbq *,
|
||||||
|
|
||||||
static int lpfc_max_els_tries = 3;
|
static int lpfc_max_els_tries = 3;
|
||||||
|
|
||||||
static int
|
int
|
||||||
lpfc_els_chk_latt(struct lpfc_vport *vport)
|
lpfc_els_chk_latt(struct lpfc_vport *vport)
|
||||||
{
|
{
|
||||||
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
|
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,
|
||||||
"%d:1817 Fabric does not support NPIV "
|
"%d:1817 Fabric does not support NPIV "
|
||||||
"- configuring single port mode.\n",
|
"- configuring single port mode.\n",
|
||||||
phba->brd_no);
|
phba->brd_no);
|
||||||
phba->vpi_cnt = 1;
|
|
||||||
phba->link_flag &= ~LS_NPIV_FAB_SUPPORTED;
|
phba->link_flag &= ~LS_NPIV_FAB_SUPPORTED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -406,7 +406,6 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||||
|
|
||||||
spin_lock_irq(shost->host_lock);
|
spin_lock_irq(shost->host_lock);
|
||||||
vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
|
vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
|
||||||
phba->vpi_cnt = 1;
|
|
||||||
spin_unlock_irq(shost->host_lock);
|
spin_unlock_irq(shost->host_lock);
|
||||||
|
|
||||||
phba->fc_edtov = FF_DEF_EDTOV;
|
phba->fc_edtov = FF_DEF_EDTOV;
|
||||||
|
@ -499,6 +498,11 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
|
||||||
|
"FLOGI cmpl: status:x%x/x%x state:x%x",
|
||||||
|
irsp->ulpStatus, irsp->un.ulpWord[4],
|
||||||
|
vport->port_state);
|
||||||
|
|
||||||
if (irsp->ulpStatus) {
|
if (irsp->ulpStatus) {
|
||||||
/* Check for retry */
|
/* Check for retry */
|
||||||
if (lpfc_els_retry(phba, cmdiocb, rspiocb))
|
if (lpfc_els_retry(phba, cmdiocb, rspiocb))
|
||||||
|
@ -507,7 +511,6 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||||
/* FLOGI failed, so there is no fabric */
|
/* FLOGI failed, so there is no fabric */
|
||||||
spin_lock_irq(shost->host_lock);
|
spin_lock_irq(shost->host_lock);
|
||||||
vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
|
vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
|
||||||
phba->vpi_cnt = 1;
|
|
||||||
spin_unlock_irq(shost->host_lock);
|
spin_unlock_irq(shost->host_lock);
|
||||||
|
|
||||||
/* If private loop, then allow max outstanding els to be
|
/* 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,
|
||||||
|
|
||||||
flogifail:
|
flogifail:
|
||||||
lpfc_nlp_put(ndlp);
|
lpfc_nlp_put(ndlp);
|
||||||
phba->vpi_cnt = 1;
|
|
||||||
|
|
||||||
if (irsp->ulpStatus != IOSTAT_LOCAL_REJECT ||
|
if (!lpfc_error_lost_link(irsp)) {
|
||||||
(irsp->un.ulpWord[4] != IOERR_SLI_ABORTED &&
|
|
||||||
irsp->un.ulpWord[4] != IOERR_SLI_DOWN)) {
|
|
||||||
/* FLOGI failed, so just use loop map to make discovery list */
|
/* FLOGI failed, so just use loop map to make discovery list */
|
||||||
lpfc_disc_list_loopmap(vport);
|
lpfc_disc_list_loopmap(vport);
|
||||||
|
|
||||||
|
@ -627,6 +627,11 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||||
icmd->ulpCt_l = 0;
|
icmd->ulpCt_l = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (phba->fc_topology != TOPOLOGY_LOOP) {
|
||||||
|
icmd->un.elsreq64.myID = 0;
|
||||||
|
icmd->un.elsreq64.fl = 1;
|
||||||
|
}
|
||||||
|
|
||||||
tmo = phba->fc_ratov;
|
tmo = phba->fc_ratov;
|
||||||
phba->fc_ratov = LPFC_DISC_FLOGI_TMO;
|
phba->fc_ratov = LPFC_DISC_FLOGI_TMO;
|
||||||
lpfc_set_disctmo(vport);
|
lpfc_set_disctmo(vport);
|
||||||
|
@ -634,6 +639,11 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||||
|
|
||||||
phba->fc_stat.elsXmitFLOGI++;
|
phba->fc_stat.elsXmitFLOGI++;
|
||||||
elsiocb->iocb_cmpl = lpfc_cmpl_els_flogi;
|
elsiocb->iocb_cmpl = lpfc_cmpl_els_flogi;
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
|
||||||
|
"Issue FLOGI: opt:x%x",
|
||||||
|
phba->sli3_options, 0, 0);
|
||||||
|
|
||||||
rc = lpfc_issue_fabric_iocb(phba, elsiocb);
|
rc = lpfc_issue_fabric_iocb(phba, elsiocb);
|
||||||
if (rc == IOCB_ERROR) {
|
if (rc == IOCB_ERROR) {
|
||||||
lpfc_els_free_iocb(phba, elsiocb);
|
lpfc_els_free_iocb(phba, elsiocb);
|
||||||
|
@ -816,6 +826,11 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||||
cmdiocb->context_un.rsp_iocb = rspiocb;
|
cmdiocb->context_un.rsp_iocb = rspiocb;
|
||||||
|
|
||||||
irsp = &rspiocb->iocb;
|
irsp = &rspiocb->iocb;
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
|
||||||
|
"PLOGI cmpl: status:x%x/x%x did:x%x",
|
||||||
|
irsp->ulpStatus, irsp->un.ulpWord[4],
|
||||||
|
irsp->un.elsreq64.remoteID);
|
||||||
|
|
||||||
ndlp = lpfc_findnode_did(vport, irsp->un.elsreq64.remoteID);
|
ndlp = lpfc_findnode_did(vport, irsp->un.elsreq64.remoteID);
|
||||||
if (!ndlp) {
|
if (!ndlp) {
|
||||||
lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
|
lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
|
||||||
|
@ -878,10 +893,7 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
|
/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
|
||||||
if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
|
if (lpfc_error_lost_link(irsp)) {
|
||||||
((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
|
|
||||||
(irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
|
|
||||||
(irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
|
|
||||||
rc = NLP_STE_FREED_NODE;
|
rc = NLP_STE_FREED_NODE;
|
||||||
} else {
|
} else {
|
||||||
rc = lpfc_disc_state_machine(vport, ndlp, cmdiocb,
|
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)
|
||||||
if (sp->cmn.fcphHigh < FC_PH3)
|
if (sp->cmn.fcphHigh < FC_PH3)
|
||||||
sp->cmn.fcphHigh = FC_PH3;
|
sp->cmn.fcphHigh = FC_PH3;
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
|
||||||
|
"Issue PLOGI: did:x%x",
|
||||||
|
did, 0, 0);
|
||||||
|
|
||||||
phba->fc_stat.elsXmitPLOGI++;
|
phba->fc_stat.elsXmitPLOGI++;
|
||||||
elsiocb->iocb_cmpl = lpfc_cmpl_els_plogi;
|
elsiocb->iocb_cmpl = lpfc_cmpl_els_plogi;
|
||||||
ret = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
|
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,
|
||||||
ndlp->nlp_flag &= ~NLP_PRLI_SND;
|
ndlp->nlp_flag &= ~NLP_PRLI_SND;
|
||||||
spin_unlock_irq(shost->host_lock);
|
spin_unlock_irq(shost->host_lock);
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
|
||||||
|
"PRLI cmpl: status:x%x/x%x did:x%x",
|
||||||
|
irsp->ulpStatus, irsp->un.ulpWord[4],
|
||||||
|
ndlp->nlp_DID);
|
||||||
|
|
||||||
/* PRLI completes to NPort <nlp_DID> */
|
/* PRLI completes to NPort <nlp_DID> */
|
||||||
lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
|
lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
|
||||||
"%d (%d):0103 PRLI completes to NPort x%x "
|
"%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,
|
||||||
}
|
}
|
||||||
/* PRLI failed */
|
/* PRLI failed */
|
||||||
/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
|
/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
|
||||||
if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
|
if (lpfc_error_lost_link(irsp)) {
|
||||||
((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
|
|
||||||
(irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
|
|
||||||
(irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
|
|
||||||
goto out;
|
goto out;
|
||||||
} else {
|
} else {
|
||||||
lpfc_disc_state_machine(vport, ndlp, cmdiocb,
|
lpfc_disc_state_machine(vport, ndlp, cmdiocb,
|
||||||
|
@ -1087,6 +1105,10 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||||
npr->prliType = PRLI_FCP_TYPE;
|
npr->prliType = PRLI_FCP_TYPE;
|
||||||
npr->initiatorFunc = 1;
|
npr->initiatorFunc = 1;
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
|
||||||
|
"Issue PRLI: did:x%x",
|
||||||
|
ndlp->nlp_DID, 0, 0);
|
||||||
|
|
||||||
phba->fc_stat.elsXmitPRLI++;
|
phba->fc_stat.elsXmitPRLI++;
|
||||||
elsiocb->iocb_cmpl = lpfc_cmpl_els_prli;
|
elsiocb->iocb_cmpl = lpfc_cmpl_els_prli;
|
||||||
spin_lock_irq(shost->host_lock);
|
spin_lock_irq(shost->host_lock);
|
||||||
|
@ -1133,6 +1155,8 @@ lpfc_rscn_disc(struct lpfc_vport *vport)
|
||||||
{
|
{
|
||||||
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
|
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
|
||||||
|
|
||||||
|
lpfc_can_disctmo(vport);
|
||||||
|
|
||||||
/* RSCN discovery */
|
/* RSCN discovery */
|
||||||
/* go thru NPR nodes and issue ELS PLOGIs */
|
/* go thru NPR nodes and issue ELS PLOGIs */
|
||||||
if (vport->fc_npr_cnt)
|
if (vport->fc_npr_cnt)
|
||||||
|
@ -1170,6 +1194,11 @@ lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||||
irsp = &(rspiocb->iocb);
|
irsp = &(rspiocb->iocb);
|
||||||
ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
|
ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
|
||||||
|
"ADISC cmpl: status:x%x/x%x did:x%x",
|
||||||
|
irsp->ulpStatus, irsp->un.ulpWord[4],
|
||||||
|
ndlp->nlp_DID);
|
||||||
|
|
||||||
/* Since ndlp can be freed in the disc state machine, note if this node
|
/* Since ndlp can be freed in the disc state machine, note if this node
|
||||||
* is being used during discovery.
|
* is being used during discovery.
|
||||||
*/
|
*/
|
||||||
|
@ -1208,12 +1237,9 @@ lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||||
}
|
}
|
||||||
/* ADISC failed */
|
/* ADISC failed */
|
||||||
/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
|
/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
|
||||||
if ((irsp->ulpStatus != IOSTAT_LOCAL_REJECT) ||
|
if (!lpfc_error_lost_link(irsp)) {
|
||||||
((irsp->un.ulpWord[4] != IOERR_SLI_ABORTED) &&
|
|
||||||
(irsp->un.ulpWord[4] != IOERR_LINK_DOWN) &&
|
|
||||||
(irsp->un.ulpWord[4] != IOERR_SLI_DOWN))) {
|
|
||||||
lpfc_disc_state_machine(vport, ndlp, cmdiocb,
|
lpfc_disc_state_machine(vport, ndlp, cmdiocb,
|
||||||
NLP_EVT_CMPL_ADISC);
|
NLP_EVT_CMPL_ADISC);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Good status, call state machine */
|
/* Good status, call state machine */
|
||||||
|
@ -1306,6 +1332,10 @@ lpfc_issue_els_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||||
memcpy(&ap->nodeName, &vport->fc_nodename, sizeof(struct lpfc_name));
|
memcpy(&ap->nodeName, &vport->fc_nodename, sizeof(struct lpfc_name));
|
||||||
ap->DID = be32_to_cpu(vport->fc_myDID);
|
ap->DID = be32_to_cpu(vport->fc_myDID);
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
|
||||||
|
"Issue ADISC: did:x%x",
|
||||||
|
ndlp->nlp_DID, 0, 0);
|
||||||
|
|
||||||
phba->fc_stat.elsXmitADISC++;
|
phba->fc_stat.elsXmitADISC++;
|
||||||
elsiocb->iocb_cmpl = lpfc_cmpl_els_adisc;
|
elsiocb->iocb_cmpl = lpfc_cmpl_els_adisc;
|
||||||
spin_lock_irq(shost->host_lock);
|
spin_lock_irq(shost->host_lock);
|
||||||
|
@ -1340,6 +1370,11 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||||
ndlp->nlp_flag &= ~NLP_LOGO_SND;
|
ndlp->nlp_flag &= ~NLP_LOGO_SND;
|
||||||
spin_unlock_irq(shost->host_lock);
|
spin_unlock_irq(shost->host_lock);
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
|
||||||
|
"LOGO cmpl: status:x%x/x%x did:x%x",
|
||||||
|
irsp->ulpStatus, irsp->un.ulpWord[4],
|
||||||
|
ndlp->nlp_DID);
|
||||||
|
|
||||||
/* LOGO completes to NPort <nlp_DID> */
|
/* LOGO completes to NPort <nlp_DID> */
|
||||||
lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
|
lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
|
||||||
"%d (%d):0105 LOGO completes to NPort x%x "
|
"%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,
|
||||||
goto out;
|
goto out;
|
||||||
/* LOGO failed */
|
/* LOGO failed */
|
||||||
/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
|
/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
|
||||||
if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
|
if (lpfc_error_lost_link(irsp))
|
||||||
((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
|
|
||||||
(irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
|
|
||||||
(irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
|
|
||||||
goto out;
|
goto out;
|
||||||
} else {
|
else
|
||||||
lpfc_disc_state_machine(vport, ndlp, cmdiocb,
|
lpfc_disc_state_machine(vport, ndlp, cmdiocb,
|
||||||
NLP_EVT_CMPL_LOGO);
|
NLP_EVT_CMPL_LOGO);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
/* Good status, call state machine.
|
/* Good status, call state machine.
|
||||||
* This will unregister the rpi if needed.
|
* This will unregister the rpi if needed.
|
||||||
|
@ -1423,6 +1454,10 @@ lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||||
pcmd += sizeof(uint32_t);
|
pcmd += sizeof(uint32_t);
|
||||||
memcpy(pcmd, &vport->fc_portname, sizeof(struct lpfc_name));
|
memcpy(pcmd, &vport->fc_portname, sizeof(struct lpfc_name));
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
|
||||||
|
"Issue LOGO: did:x%x",
|
||||||
|
ndlp->nlp_DID, 0, 0);
|
||||||
|
|
||||||
phba->fc_stat.elsXmitLOGO++;
|
phba->fc_stat.elsXmitLOGO++;
|
||||||
elsiocb->iocb_cmpl = lpfc_cmpl_els_logo;
|
elsiocb->iocb_cmpl = lpfc_cmpl_els_logo;
|
||||||
spin_lock_irq(shost->host_lock);
|
spin_lock_irq(shost->host_lock);
|
||||||
|
@ -1449,6 +1484,11 @@ lpfc_cmpl_els_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||||
|
|
||||||
irsp = &rspiocb->iocb;
|
irsp = &rspiocb->iocb;
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
|
||||||
|
"ELS cmd cmpl: status:x%x/x%x did:x%x",
|
||||||
|
irsp->ulpStatus, irsp->un.ulpWord[4],
|
||||||
|
irsp->un.elsreq64.remoteID);
|
||||||
|
|
||||||
/* ELS cmd tag <ulpIoTag> completes */
|
/* ELS cmd tag <ulpIoTag> completes */
|
||||||
lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
|
lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
|
||||||
"%d (%d):0106 ELS cmd tag x%x completes Data: x%x x%x "
|
"%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)
|
||||||
memset(pcmd, 0, sizeof(SCR));
|
memset(pcmd, 0, sizeof(SCR));
|
||||||
((SCR *) pcmd)->Function = SCR_FUNC_FULL;
|
((SCR *) pcmd)->Function = SCR_FUNC_FULL;
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
|
||||||
|
"Issue SCR: did:x%x",
|
||||||
|
ndlp->nlp_DID, 0, 0);
|
||||||
|
|
||||||
phba->fc_stat.elsXmitSCR++;
|
phba->fc_stat.elsXmitSCR++;
|
||||||
elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd;
|
elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd;
|
||||||
if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
|
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)
|
||||||
sizeof(struct lpfc_name));
|
sizeof(struct lpfc_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
|
||||||
|
"Issue FARPR: did:x%x",
|
||||||
|
ndlp->nlp_DID, 0, 0);
|
||||||
|
|
||||||
phba->fc_stat.elsXmitFARPR++;
|
phba->fc_stat.elsXmitFARPR++;
|
||||||
elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd;
|
elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd;
|
||||||
if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
|
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,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
|
||||||
|
"Retry ELS: wd7:x%x wd4:x%x did:x%x",
|
||||||
|
*(((uint32_t *) irsp) + 7), irsp->un.ulpWord[4], ndlp->nlp_DID);
|
||||||
|
|
||||||
switch (irsp->ulpStatus) {
|
switch (irsp->ulpStatus) {
|
||||||
case IOSTAT_FCP_RSP_ERROR:
|
case IOSTAT_FCP_RSP_ERROR:
|
||||||
case IOSTAT_REMOTE_STOP:
|
case IOSTAT_REMOTE_STOP:
|
||||||
|
@ -1776,10 +1828,6 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||||
retry = 1;
|
retry = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOERR_SEQUENCE_TIMEOUT:
|
|
||||||
retry = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case IOERR_ILLEGAL_COMMAND:
|
case IOERR_ILLEGAL_COMMAND:
|
||||||
if ((phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) &&
|
if ((phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) &&
|
||||||
(cmd == ELS_CMD_FDISC)) {
|
(cmd == ELS_CMD_FDISC)) {
|
||||||
|
@ -1794,10 +1842,18 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOERR_NO_RESOURCES:
|
case IOERR_NO_RESOURCES:
|
||||||
|
retry = 1;
|
||||||
|
if (cmdiocb->retry > 100)
|
||||||
|
delay = 100;
|
||||||
|
maxretry = 250;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IOERR_ILLEGAL_FRAME:
|
||||||
delay = 100;
|
delay = 100;
|
||||||
retry = 1;
|
retry = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case IOERR_SEQUENCE_TIMEOUT:
|
||||||
case IOERR_INVALID_RPI:
|
case IOERR_INVALID_RPI:
|
||||||
retry = 1;
|
retry = 1;
|
||||||
break;
|
break;
|
||||||
|
@ -1852,7 +1908,8 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LSRJT_LOGICAL_BSY:
|
case LSRJT_LOGICAL_BSY:
|
||||||
if (cmd == ELS_CMD_PLOGI) {
|
if ((cmd == ELS_CMD_PLOGI) ||
|
||||||
|
(cmd == ELS_CMD_PRLI)) {
|
||||||
delay = 1000;
|
delay = 1000;
|
||||||
maxretry = 48;
|
maxretry = 48;
|
||||||
} else if (cmd == ELS_CMD_FDISC) {
|
} else if (cmd == ELS_CMD_FDISC) {
|
||||||
|
@ -1908,7 +1965,11 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||||
phba->brd_no, vport->vpi,
|
phba->brd_no, vport->vpi,
|
||||||
cmd, did, cmdiocb->retry, delay);
|
cmd, did, cmdiocb->retry, delay);
|
||||||
|
|
||||||
if ((cmd == ELS_CMD_PLOGI) || (cmd == ELS_CMD_ADISC)) {
|
if (((cmd == ELS_CMD_PLOGI) || (cmd == ELS_CMD_ADISC)) &&
|
||||||
|
((irsp->ulpStatus != IOSTAT_LOCAL_REJECT) ||
|
||||||
|
((irsp->un.ulpWord[4] & 0xff) != IOERR_NO_RESOURCES))) {
|
||||||
|
/* Don't reset timer for no resources */
|
||||||
|
|
||||||
/* If discovery / RSCN timer is running, reset it */
|
/* If discovery / RSCN timer is running, reset it */
|
||||||
if (timer_pending(&vport->fc_disctmo) ||
|
if (timer_pending(&vport->fc_disctmo) ||
|
||||||
(vport->fc_flag & FC_RSCN_MODE))
|
(vport->fc_flag & FC_RSCN_MODE))
|
||||||
|
@ -1928,7 +1989,12 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||||
spin_unlock_irq(shost->host_lock);
|
spin_unlock_irq(shost->host_lock);
|
||||||
|
|
||||||
ndlp->nlp_prev_state = ndlp->nlp_state;
|
ndlp->nlp_prev_state = ndlp->nlp_state;
|
||||||
lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
|
if (cmd == ELS_CMD_PRLI)
|
||||||
|
lpfc_nlp_set_state(vport, ndlp,
|
||||||
|
NLP_STE_REG_LOGIN_ISSUE);
|
||||||
|
else
|
||||||
|
lpfc_nlp_set_state(vport, ndlp,
|
||||||
|
NLP_STE_NPR_NODE);
|
||||||
ndlp->nlp_last_elscmd = cmd;
|
ndlp->nlp_last_elscmd = cmd;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -2015,6 +2081,12 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||||
{
|
{
|
||||||
struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
|
struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
|
||||||
struct lpfc_vport *vport = cmdiocb->vport;
|
struct lpfc_vport *vport = cmdiocb->vport;
|
||||||
|
IOCB_t *irsp;
|
||||||
|
|
||||||
|
irsp = &rspiocb->iocb;
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
|
||||||
|
"ACC LOGO cmpl: status:x%x/x%x did:x%x",
|
||||||
|
irsp->ulpStatus, irsp->un.ulpWord[4], ndlp->nlp_DID);
|
||||||
|
|
||||||
/* ACC to LOGO completes to NPort <nlp_DID> */
|
/* ACC to LOGO completes to NPort <nlp_DID> */
|
||||||
lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
|
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,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
|
||||||
|
{
|
||||||
|
struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
|
||||||
|
struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
|
||||||
|
|
||||||
|
pmb->context1 = NULL;
|
||||||
|
lpfc_mbuf_free(phba, mp->virt, mp->phys);
|
||||||
|
kfree(mp);
|
||||||
|
mempool_free(pmb, phba->mbox_mem_pool);
|
||||||
|
lpfc_nlp_put(ndlp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
lpfc_cmpl_els_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||||
struct lpfc_iocbq *rspiocb)
|
struct lpfc_iocbq *rspiocb)
|
||||||
{
|
{
|
||||||
struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
|
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,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
|
||||||
|
"ACC cmpl: status:x%x/x%x did:x%x",
|
||||||
|
irsp->ulpStatus, irsp->un.ulpWord[4],
|
||||||
|
irsp->un.rcvels.remoteID);
|
||||||
|
|
||||||
/* ELS response tag <ulpIoTag> completes */
|
/* ELS response tag <ulpIoTag> completes */
|
||||||
lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
|
lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
|
||||||
"%d (%d):0110 ELS response tag x%x completes "
|
"%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,
|
||||||
if ((rspiocb->iocb.ulpStatus == 0)
|
if ((rspiocb->iocb.ulpStatus == 0)
|
||||||
&& (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) {
|
&& (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) {
|
||||||
lpfc_unreg_rpi(vport, ndlp);
|
lpfc_unreg_rpi(vport, ndlp);
|
||||||
mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
|
|
||||||
mbox->context2 = lpfc_nlp_get(ndlp);
|
mbox->context2 = lpfc_nlp_get(ndlp);
|
||||||
mbox->vport = vport;
|
mbox->vport = vport;
|
||||||
ndlp->nlp_prev_state = ndlp->nlp_state;
|
if (ndlp->nlp_flag & NLP_RM_DFLT_RPI) {
|
||||||
lpfc_nlp_set_state(vport, ndlp,
|
mbox->mbox_flag |= LPFC_MBX_IMED_UNREG;
|
||||||
|
mbox->mbox_cmpl = lpfc_mbx_cmpl_dflt_rpi;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
|
||||||
|
ndlp->nlp_prev_state = ndlp->nlp_state;
|
||||||
|
lpfc_nlp_set_state(vport, ndlp,
|
||||||
NLP_STE_REG_LOGIN_ISSUE);
|
NLP_STE_REG_LOGIN_ISSUE);
|
||||||
|
}
|
||||||
if (lpfc_sli_issue_mbox(phba, mbox,
|
if (lpfc_sli_issue_mbox(phba, mbox,
|
||||||
(MBX_NOWAIT | MBX_STOP_IOCB))
|
(MBX_NOWAIT | MBX_STOP_IOCB))
|
||||||
!= MBX_NOT_FINISHED) {
|
!= MBX_NOT_FINISHED) {
|
||||||
|
@ -2095,15 +2192,11 @@ lpfc_cmpl_els_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||||
/* NOTE: we should have messages for unsuccessful
|
/* NOTE: we should have messages for unsuccessful
|
||||||
reglogin */
|
reglogin */
|
||||||
} else {
|
} else {
|
||||||
/* Do not call NO_LIST for lpfc_els_abort'ed ELS cmds */
|
/* Do not drop node for lpfc_els_abort'ed ELS cmds */
|
||||||
if (!((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
|
if (!lpfc_error_lost_link(irsp) &&
|
||||||
((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
|
ndlp->nlp_flag & NLP_ACC_REGLOGIN) {
|
||||||
(irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
|
lpfc_drop_node(vport, ndlp);
|
||||||
(irsp->un.ulpWord[4] == IOERR_SLI_DOWN)))) {
|
ndlp = NULL;
|
||||||
if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) {
|
|
||||||
lpfc_drop_node(vport, ndlp);
|
|
||||||
ndlp = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mp = (struct lpfc_dmabuf *) mbox->context1;
|
mp = (struct lpfc_dmabuf *) mbox->context1;
|
||||||
|
@ -2116,7 +2209,7 @@ lpfc_cmpl_els_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||||
out:
|
out:
|
||||||
if (ndlp) {
|
if (ndlp) {
|
||||||
spin_lock_irq(shost->host_lock);
|
spin_lock_irq(shost->host_lock);
|
||||||
ndlp->nlp_flag &= ~NLP_ACC_REGLOGIN;
|
ndlp->nlp_flag &= ~(NLP_ACC_REGLOGIN | NLP_RM_DFLT_RPI);
|
||||||
spin_unlock_irq(shost->host_lock);
|
spin_unlock_irq(shost->host_lock);
|
||||||
}
|
}
|
||||||
lpfc_els_free_iocb(phba, cmdiocb);
|
lpfc_els_free_iocb(phba, cmdiocb);
|
||||||
|
@ -2161,6 +2254,10 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
|
||||||
pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
|
pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
|
||||||
*((uint32_t *) (pcmd)) = ELS_CMD_ACC;
|
*((uint32_t *) (pcmd)) = ELS_CMD_ACC;
|
||||||
pcmd += sizeof(uint32_t);
|
pcmd += sizeof(uint32_t);
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
|
||||||
|
"Issue ACC: did:x%x flg:x%x",
|
||||||
|
ndlp->nlp_DID, ndlp->nlp_flag, 0);
|
||||||
break;
|
break;
|
||||||
case ELS_CMD_PLOGI:
|
case ELS_CMD_PLOGI:
|
||||||
cmdsize = (sizeof(struct serv_parm) + sizeof(uint32_t));
|
cmdsize = (sizeof(struct serv_parm) + sizeof(uint32_t));
|
||||||
|
@ -2179,6 +2276,10 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
|
||||||
*((uint32_t *) (pcmd)) = ELS_CMD_ACC;
|
*((uint32_t *) (pcmd)) = ELS_CMD_ACC;
|
||||||
pcmd += sizeof(uint32_t);
|
pcmd += sizeof(uint32_t);
|
||||||
memcpy(pcmd, &vport->fc_sparam, sizeof(struct serv_parm));
|
memcpy(pcmd, &vport->fc_sparam, sizeof(struct serv_parm));
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
|
||||||
|
"Issue ACC PLOGI: did:x%x flg:x%x",
|
||||||
|
ndlp->nlp_DID, ndlp->nlp_flag, 0);
|
||||||
break;
|
break;
|
||||||
case ELS_CMD_PRLO:
|
case ELS_CMD_PRLO:
|
||||||
cmdsize = sizeof(uint32_t) + sizeof(PRLO);
|
cmdsize = sizeof(uint32_t) + sizeof(PRLO);
|
||||||
|
@ -2196,6 +2297,10 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
|
||||||
*((uint32_t *) (pcmd)) = ELS_CMD_PRLO_ACC;
|
*((uint32_t *) (pcmd)) = ELS_CMD_PRLO_ACC;
|
||||||
els_pkt_ptr = (ELS_PKT *) pcmd;
|
els_pkt_ptr = (ELS_PKT *) pcmd;
|
||||||
els_pkt_ptr->un.prlo.acceptRspCode = PRLO_REQ_EXECUTED;
|
els_pkt_ptr->un.prlo.acceptRspCode = PRLO_REQ_EXECUTED;
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
|
||||||
|
"Issue ACC PRLO: did:x%x flg:x%x",
|
||||||
|
ndlp->nlp_DID, ndlp->nlp_flag, 0);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -2220,7 +2325,7 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
|
||||||
spin_unlock_irq(shost->host_lock);
|
spin_unlock_irq(shost->host_lock);
|
||||||
elsiocb->iocb_cmpl = lpfc_cmpl_els_logo_acc;
|
elsiocb->iocb_cmpl = lpfc_cmpl_els_logo_acc;
|
||||||
} else {
|
} else {
|
||||||
elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
|
elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
|
||||||
}
|
}
|
||||||
|
|
||||||
phba->fc_stat.elsXmitACC++;
|
phba->fc_stat.elsXmitACC++;
|
||||||
|
@ -2234,7 +2339,8 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
|
||||||
|
|
||||||
int
|
int
|
||||||
lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError,
|
lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError,
|
||||||
struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp)
|
struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp,
|
||||||
|
LPFC_MBOXQ_t *mbox)
|
||||||
{
|
{
|
||||||
struct lpfc_hba *phba = vport->phba;
|
struct lpfc_hba *phba = vport->phba;
|
||||||
IOCB_t *icmd;
|
IOCB_t *icmd;
|
||||||
|
@ -2264,6 +2370,11 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError,
|
||||||
pcmd += sizeof(uint32_t);
|
pcmd += sizeof(uint32_t);
|
||||||
*((uint32_t *) (pcmd)) = rejectError;
|
*((uint32_t *) (pcmd)) = rejectError;
|
||||||
|
|
||||||
|
if (mbox) {
|
||||||
|
elsiocb->context_un.mbox = mbox;
|
||||||
|
elsiocb->context1 = lpfc_nlp_get(ndlp);
|
||||||
|
}
|
||||||
|
|
||||||
/* Xmit ELS RJT <err> response tag <ulpIoTag> */
|
/* Xmit ELS RJT <err> response tag <ulpIoTag> */
|
||||||
lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
|
lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
|
||||||
"%d (%d):0129 Xmit ELS RJT x%x response tag x%x "
|
"%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,
|
||||||
elsiocb->iocb.ulpContext, ndlp->nlp_DID,
|
elsiocb->iocb.ulpContext, ndlp->nlp_DID,
|
||||||
ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
|
ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
|
||||||
|
"Issue LS_RJT: did:x%x flg:x%x err:x%x",
|
||||||
|
ndlp->nlp_DID, ndlp->nlp_flag, rejectError);
|
||||||
|
|
||||||
phba->fc_stat.elsXmitLSRJT++;
|
phba->fc_stat.elsXmitLSRJT++;
|
||||||
elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
|
elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
|
||||||
rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
|
rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
|
||||||
if (rc == IOCB_ERROR) {
|
if (rc == IOCB_ERROR) {
|
||||||
lpfc_els_free_iocb(phba, elsiocb);
|
lpfc_els_free_iocb(phba, elsiocb);
|
||||||
|
@ -2326,8 +2441,12 @@ lpfc_els_rsp_adisc_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
|
||||||
memcpy(&ap->nodeName, &vport->fc_nodename, sizeof(struct lpfc_name));
|
memcpy(&ap->nodeName, &vport->fc_nodename, sizeof(struct lpfc_name));
|
||||||
ap->DID = be32_to_cpu(vport->fc_myDID);
|
ap->DID = be32_to_cpu(vport->fc_myDID);
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
|
||||||
|
"Issue ACC ADISC: did:x%x flg:x%x",
|
||||||
|
ndlp->nlp_DID, ndlp->nlp_flag, 0);
|
||||||
|
|
||||||
phba->fc_stat.elsXmitACC++;
|
phba->fc_stat.elsXmitACC++;
|
||||||
elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
|
elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
|
||||||
rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
|
rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
|
||||||
if (rc == IOCB_ERROR) {
|
if (rc == IOCB_ERROR) {
|
||||||
lpfc_els_free_iocb(phba, elsiocb);
|
lpfc_els_free_iocb(phba, elsiocb);
|
||||||
|
@ -2401,8 +2520,12 @@ lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
|
||||||
npr->prliType = PRLI_FCP_TYPE;
|
npr->prliType = PRLI_FCP_TYPE;
|
||||||
npr->initiatorFunc = 1;
|
npr->initiatorFunc = 1;
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
|
||||||
|
"Issue ACC PRLI: did:x%x flg:x%x",
|
||||||
|
ndlp->nlp_DID, ndlp->nlp_flag, 0);
|
||||||
|
|
||||||
phba->fc_stat.elsXmitACC++;
|
phba->fc_stat.elsXmitACC++;
|
||||||
elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
|
elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
|
||||||
|
|
||||||
rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
|
rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
|
||||||
if (rc == IOCB_ERROR) {
|
if (rc == IOCB_ERROR) {
|
||||||
|
@ -2479,8 +2602,12 @@ lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
|
||||||
|
"Issue ACC RNID: did:x%x flg:x%x",
|
||||||
|
ndlp->nlp_DID, ndlp->nlp_flag, 0);
|
||||||
|
|
||||||
phba->fc_stat.elsXmitACC++;
|
phba->fc_stat.elsXmitACC++;
|
||||||
elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
|
elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
|
||||||
lpfc_nlp_put(ndlp);
|
lpfc_nlp_put(ndlp);
|
||||||
elsiocb->context1 = NULL; /* Don't need ndlp for cmpl,
|
elsiocb->context1 = NULL; /* Don't need ndlp for cmpl,
|
||||||
* it could be freed */
|
* it could be freed */
|
||||||
|
@ -2703,6 +2830,10 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
||||||
* Discovery processing will satisfy it.
|
* Discovery processing will satisfy it.
|
||||||
*/
|
*/
|
||||||
if (vport->port_state <= LPFC_NS_QRY) {
|
if (vport->port_state <= LPFC_NS_QRY) {
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
|
||||||
|
"RCV RSCN ignore: did:x%x/ste:x%x flg:x%x",
|
||||||
|
ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag);
|
||||||
|
|
||||||
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL,
|
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL,
|
||||||
newnode);
|
newnode);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2734,6 +2865,12 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
||||||
"%d (%d):0214 Ignore RSCN Data: x%x x%x x%x x%x\n",
|
"%d (%d):0214 Ignore RSCN Data: x%x x%x x%x x%x\n",
|
||||||
phba->brd_no, vport->vpi, vport->fc_flag, payload_len,
|
phba->brd_no, vport->vpi, vport->fc_flag, payload_len,
|
||||||
*lp, rscn_cnt);
|
*lp, rscn_cnt);
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
|
||||||
|
"RCV RSCN vport: did:x%x/ste:x%x flg:x%x",
|
||||||
|
ndlp->nlp_DID, vport->port_state,
|
||||||
|
ndlp->nlp_flag);
|
||||||
|
|
||||||
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb,
|
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb,
|
||||||
ndlp, NULL, newnode);
|
ndlp, NULL, newnode);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2744,6 +2881,10 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
||||||
* RSCN payload buffer, cmdiocb->context2 to process later.
|
* RSCN payload buffer, cmdiocb->context2 to process later.
|
||||||
*/
|
*/
|
||||||
if (vport->fc_flag & (FC_RSCN_MODE | FC_NDISC_ACTIVE)) {
|
if (vport->fc_flag & (FC_RSCN_MODE | FC_NDISC_ACTIVE)) {
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
|
||||||
|
"RCV RSCN defer: did:x%x/ste:x%x flg:x%x",
|
||||||
|
ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag);
|
||||||
|
|
||||||
vport->fc_flag |= FC_RSCN_DEFERRED;
|
vport->fc_flag |= FC_RSCN_DEFERRED;
|
||||||
if ((rscn_cnt < FC_MAX_HOLD_RSCN) &&
|
if ((rscn_cnt < FC_MAX_HOLD_RSCN) &&
|
||||||
!(vport->fc_flag & FC_RSCN_DISCOVERY)) {
|
!(vport->fc_flag & FC_RSCN_DISCOVERY)) {
|
||||||
|
@ -2798,6 +2939,10 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
|
||||||
|
"RCV RSCN: did:x%x/ste:x%x flg:x%x",
|
||||||
|
ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag);
|
||||||
|
|
||||||
spin_lock_irq(shost->host_lock);
|
spin_lock_irq(shost->host_lock);
|
||||||
vport->fc_flag |= FC_RSCN_MODE;
|
vport->fc_flag |= FC_RSCN_MODE;
|
||||||
spin_unlock_irq(shost->host_lock);
|
spin_unlock_irq(shost->host_lock);
|
||||||
|
@ -2958,7 +3103,8 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
||||||
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
|
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
|
||||||
stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
|
stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
|
||||||
stat.un.b.vendorUnique = 0;
|
stat.un.b.vendorUnique = 0;
|
||||||
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp);
|
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
|
||||||
|
NULL);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3001,7 +3147,8 @@ lpfc_els_rcv_rnid(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
||||||
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
|
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
|
||||||
stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
|
stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
|
||||||
stat.un.b.vendorUnique = 0;
|
stat.un.b.vendorUnique = 0;
|
||||||
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp);
|
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -3017,7 +3164,7 @@ lpfc_els_rcv_lirr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
||||||
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
|
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
|
||||||
stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
|
stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
|
||||||
stat.un.b.vendorUnique = 0;
|
stat.un.b.vendorUnique = 0;
|
||||||
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp);
|
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3089,7 +3236,7 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
|
||||||
elsiocb->iocb.ulpContext, ndlp->nlp_DID,
|
elsiocb->iocb.ulpContext, ndlp->nlp_DID,
|
||||||
ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
|
ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
|
||||||
|
|
||||||
elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
|
elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
|
||||||
phba->fc_stat.elsXmitACC++;
|
phba->fc_stat.elsXmitACC++;
|
||||||
if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR)
|
if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR)
|
||||||
lpfc_els_free_iocb(phba, elsiocb);
|
lpfc_els_free_iocb(phba, elsiocb);
|
||||||
|
@ -3114,7 +3261,8 @@ lpfc_els_rcv_rps(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
||||||
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
|
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
|
||||||
stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
|
stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
|
||||||
stat.un.b.vendorUnique = 0;
|
stat.un.b.vendorUnique = 0;
|
||||||
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp);
|
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
|
pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
|
||||||
|
@ -3150,7 +3298,7 @@ lpfc_els_rcv_rps(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
||||||
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
|
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
|
||||||
stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
|
stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
|
||||||
stat.un.b.vendorUnique = 0;
|
stat.un.b.vendorUnique = 0;
|
||||||
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp);
|
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3202,7 +3350,7 @@ lpfc_els_rsp_rpl_acc(struct lpfc_vport *vport, uint16_t cmdsize,
|
||||||
elsiocb->iocb.ulpContext, ndlp->nlp_DID,
|
elsiocb->iocb.ulpContext, ndlp->nlp_DID,
|
||||||
ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
|
ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
|
||||||
|
|
||||||
elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
|
elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
|
||||||
|
|
||||||
phba->fc_stat.elsXmitACC++;
|
phba->fc_stat.elsXmitACC++;
|
||||||
if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
|
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,
|
||||||
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
|
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
|
||||||
stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
|
stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
|
||||||
stat.un.b.vendorUnique = 0;
|
stat.un.b.vendorUnique = 0;
|
||||||
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp);
|
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
|
pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
|
||||||
|
@ -3538,9 +3687,6 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport)
|
||||||
struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
|
struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
|
||||||
struct lpfc_iocbq *tmp_iocb, *piocb;
|
struct lpfc_iocbq *tmp_iocb, *piocb;
|
||||||
IOCB_t *cmd = NULL;
|
IOCB_t *cmd = NULL;
|
||||||
struct lpfc_dmabuf *pcmd;
|
|
||||||
uint32_t *elscmd;
|
|
||||||
uint32_t els_command;
|
|
||||||
|
|
||||||
lpfc_fabric_abort_vport(vport);
|
lpfc_fabric_abort_vport(vport);
|
||||||
|
|
||||||
|
@ -3559,10 +3705,6 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport)
|
||||||
cmd->ulpCommand == CMD_ABORT_XRI_CN)
|
cmd->ulpCommand == CMD_ABORT_XRI_CN)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
pcmd = (struct lpfc_dmabuf *) piocb->context2;
|
|
||||||
elscmd = (uint32_t *) (pcmd->virt);
|
|
||||||
els_command = *elscmd;
|
|
||||||
|
|
||||||
if (piocb->vport != vport)
|
if (piocb->vport != vport)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -3618,8 +3760,13 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
||||||
if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) == 0)
|
if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) == 0)
|
||||||
lpfc_post_buffer(phba, pring, 1, 1);
|
lpfc_post_buffer(phba, pring, 1, 1);
|
||||||
|
|
||||||
if (icmd->ulpStatus)
|
did = icmd->un.rcvels.remoteID;
|
||||||
|
if (icmd->ulpStatus) {
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
|
||||||
|
"RCV Unsol ELS: status:x%x/x%x did:x%x",
|
||||||
|
icmd->ulpStatus, icmd->un.ulpWord[4], did);
|
||||||
goto dropit;
|
goto dropit;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check to see if link went down during discovery */
|
/* Check to see if link went down during discovery */
|
||||||
if (lpfc_els_chk_latt(vport))
|
if (lpfc_els_chk_latt(vport))
|
||||||
|
@ -3629,7 +3776,6 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
||||||
if (vport->load_flag & FC_UNLOADING)
|
if (vport->load_flag & FC_UNLOADING)
|
||||||
goto dropit;
|
goto dropit;
|
||||||
|
|
||||||
did = icmd->un.rcvels.remoteID;
|
|
||||||
ndlp = lpfc_findnode_did(vport, did);
|
ndlp = lpfc_findnode_did(vport, did);
|
||||||
if (!ndlp) {
|
if (!ndlp) {
|
||||||
/* Cannot find existing Fabric ndlp, so allocate a new one */
|
/* 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,
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case ELS_CMD_PLOGI:
|
case ELS_CMD_PLOGI:
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
|
||||||
|
"RCV PLOGI: did:x%x/ste:x%x flg:x%x",
|
||||||
|
did, vport->port_state, ndlp->nlp_flag);
|
||||||
|
|
||||||
phba->fc_stat.elsRcvPLOGI++;
|
phba->fc_stat.elsRcvPLOGI++;
|
||||||
if ((vport->port_state < LPFC_DISC_AUTH) ||
|
ndlp = lpfc_plogi_confirm_nport(phba, payload, ndlp);
|
||||||
((vport->port_type == LPFC_NPIV_PORT &&
|
|
||||||
phba->cfg_vport_restrict_login))) {
|
if (vport->port_state < LPFC_DISC_AUTH) {
|
||||||
rjt_err = 2;
|
rjt_err = LSRJT_UNABLE_TPC;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ndlp = lpfc_plogi_confirm_nport(phba, payload, ndlp);
|
|
||||||
lpfc_disc_state_machine(vport, ndlp, elsiocb,
|
lpfc_disc_state_machine(vport, ndlp, elsiocb,
|
||||||
NLP_EVT_RCV_PLOGI);
|
NLP_EVT_RCV_PLOGI);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ELS_CMD_FLOGI:
|
case ELS_CMD_FLOGI:
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
|
||||||
|
"RCV FLOGI: did:x%x/ste:x%x flg:x%x",
|
||||||
|
did, vport->port_state, ndlp->nlp_flag);
|
||||||
|
|
||||||
phba->fc_stat.elsRcvFLOGI++;
|
phba->fc_stat.elsRcvFLOGI++;
|
||||||
lpfc_els_rcv_flogi(vport, elsiocb, ndlp, newnode);
|
lpfc_els_rcv_flogi(vport, elsiocb, ndlp, newnode);
|
||||||
if (newnode)
|
if (newnode)
|
||||||
lpfc_drop_node(vport, ndlp);
|
lpfc_drop_node(vport, ndlp);
|
||||||
break;
|
break;
|
||||||
case ELS_CMD_LOGO:
|
case ELS_CMD_LOGO:
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
|
||||||
|
"RCV LOGO: did:x%x/ste:x%x flg:x%x",
|
||||||
|
did, vport->port_state, ndlp->nlp_flag);
|
||||||
|
|
||||||
phba->fc_stat.elsRcvLOGO++;
|
phba->fc_stat.elsRcvLOGO++;
|
||||||
if (vport->port_state < LPFC_DISC_AUTH) {
|
if (vport->port_state < LPFC_DISC_AUTH) {
|
||||||
rjt_err = 1;
|
rjt_err = LSRJT_UNABLE_TPC;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_LOGO);
|
lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_LOGO);
|
||||||
break;
|
break;
|
||||||
case ELS_CMD_PRLO:
|
case ELS_CMD_PRLO:
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
|
||||||
|
"RCV PRLO: did:x%x/ste:x%x flg:x%x",
|
||||||
|
did, vport->port_state, ndlp->nlp_flag);
|
||||||
|
|
||||||
phba->fc_stat.elsRcvPRLO++;
|
phba->fc_stat.elsRcvPRLO++;
|
||||||
if (vport->port_state < LPFC_DISC_AUTH) {
|
if (vport->port_state < LPFC_DISC_AUTH) {
|
||||||
rjt_err = 1;
|
rjt_err = LSRJT_UNABLE_TPC;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_PRLO);
|
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,
|
||||||
lpfc_drop_node(vport, ndlp);
|
lpfc_drop_node(vport, ndlp);
|
||||||
break;
|
break;
|
||||||
case ELS_CMD_ADISC:
|
case ELS_CMD_ADISC:
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
|
||||||
|
"RCV ADISC: did:x%x/ste:x%x flg:x%x",
|
||||||
|
did, vport->port_state, ndlp->nlp_flag);
|
||||||
|
|
||||||
phba->fc_stat.elsRcvADISC++;
|
phba->fc_stat.elsRcvADISC++;
|
||||||
if (vport->port_state < LPFC_DISC_AUTH) {
|
if (vport->port_state < LPFC_DISC_AUTH) {
|
||||||
rjt_err = 1;
|
rjt_err = LSRJT_UNABLE_TPC;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
lpfc_disc_state_machine(vport, ndlp, elsiocb,
|
lpfc_disc_state_machine(vport, ndlp, elsiocb,
|
||||||
NLP_EVT_RCV_ADISC);
|
NLP_EVT_RCV_ADISC);
|
||||||
break;
|
break;
|
||||||
case ELS_CMD_PDISC:
|
case ELS_CMD_PDISC:
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
|
||||||
|
"RCV PDISC: did:x%x/ste:x%x flg:x%x",
|
||||||
|
did, vport->port_state, ndlp->nlp_flag);
|
||||||
|
|
||||||
phba->fc_stat.elsRcvPDISC++;
|
phba->fc_stat.elsRcvPDISC++;
|
||||||
if (vport->port_state < LPFC_DISC_AUTH) {
|
if (vport->port_state < LPFC_DISC_AUTH) {
|
||||||
rjt_err = 1;
|
rjt_err = LSRJT_UNABLE_TPC;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
lpfc_disc_state_machine(vport, ndlp, elsiocb,
|
lpfc_disc_state_machine(vport, ndlp, elsiocb,
|
||||||
NLP_EVT_RCV_PDISC);
|
NLP_EVT_RCV_PDISC);
|
||||||
break;
|
break;
|
||||||
case ELS_CMD_FARPR:
|
case ELS_CMD_FARPR:
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
|
||||||
|
"RCV FARPR: did:x%x/ste:x%x flg:x%x",
|
||||||
|
did, vport->port_state, ndlp->nlp_flag);
|
||||||
|
|
||||||
phba->fc_stat.elsRcvFARPR++;
|
phba->fc_stat.elsRcvFARPR++;
|
||||||
lpfc_els_rcv_farpr(vport, elsiocb, ndlp);
|
lpfc_els_rcv_farpr(vport, elsiocb, ndlp);
|
||||||
break;
|
break;
|
||||||
case ELS_CMD_FARP:
|
case ELS_CMD_FARP:
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
|
||||||
|
"RCV FARP: did:x%x/ste:x%x flg:x%x",
|
||||||
|
did, vport->port_state, ndlp->nlp_flag);
|
||||||
|
|
||||||
phba->fc_stat.elsRcvFARP++;
|
phba->fc_stat.elsRcvFARP++;
|
||||||
lpfc_els_rcv_farp(vport, elsiocb, ndlp);
|
lpfc_els_rcv_farp(vport, elsiocb, ndlp);
|
||||||
break;
|
break;
|
||||||
case ELS_CMD_FAN:
|
case ELS_CMD_FAN:
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
|
||||||
|
"RCV FAN: did:x%x/ste:x%x flg:x%x",
|
||||||
|
did, vport->port_state, ndlp->nlp_flag);
|
||||||
|
|
||||||
phba->fc_stat.elsRcvFAN++;
|
phba->fc_stat.elsRcvFAN++;
|
||||||
lpfc_els_rcv_fan(vport, elsiocb, ndlp);
|
lpfc_els_rcv_fan(vport, elsiocb, ndlp);
|
||||||
break;
|
break;
|
||||||
case ELS_CMD_PRLI:
|
case ELS_CMD_PRLI:
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
|
||||||
|
"RCV PRLI: did:x%x/ste:x%x flg:x%x",
|
||||||
|
did, vport->port_state, ndlp->nlp_flag);
|
||||||
|
|
||||||
phba->fc_stat.elsRcvPRLI++;
|
phba->fc_stat.elsRcvPRLI++;
|
||||||
if (vport->port_state < LPFC_DISC_AUTH) {
|
if (vport->port_state < LPFC_DISC_AUTH) {
|
||||||
rjt_err = 1;
|
rjt_err = LSRJT_UNABLE_TPC;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_PRLI);
|
lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_PRLI);
|
||||||
break;
|
break;
|
||||||
case ELS_CMD_LIRR:
|
case ELS_CMD_LIRR:
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
|
||||||
|
"RCV LIRR: did:x%x/ste:x%x flg:x%x",
|
||||||
|
did, vport->port_state, ndlp->nlp_flag);
|
||||||
|
|
||||||
phba->fc_stat.elsRcvLIRR++;
|
phba->fc_stat.elsRcvLIRR++;
|
||||||
lpfc_els_rcv_lirr(vport, elsiocb, ndlp);
|
lpfc_els_rcv_lirr(vport, elsiocb, ndlp);
|
||||||
if (newnode)
|
if (newnode)
|
||||||
lpfc_drop_node(vport, ndlp);
|
lpfc_drop_node(vport, ndlp);
|
||||||
break;
|
break;
|
||||||
case ELS_CMD_RPS:
|
case ELS_CMD_RPS:
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
|
||||||
|
"RCV RPS: did:x%x/ste:x%x flg:x%x",
|
||||||
|
did, vport->port_state, ndlp->nlp_flag);
|
||||||
|
|
||||||
phba->fc_stat.elsRcvRPS++;
|
phba->fc_stat.elsRcvRPS++;
|
||||||
lpfc_els_rcv_rps(vport, elsiocb, ndlp);
|
lpfc_els_rcv_rps(vport, elsiocb, ndlp);
|
||||||
if (newnode)
|
if (newnode)
|
||||||
lpfc_drop_node(vport, ndlp);
|
lpfc_drop_node(vport, ndlp);
|
||||||
break;
|
break;
|
||||||
case ELS_CMD_RPL:
|
case ELS_CMD_RPL:
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
|
||||||
|
"RCV RPL: did:x%x/ste:x%x flg:x%x",
|
||||||
|
did, vport->port_state, ndlp->nlp_flag);
|
||||||
|
|
||||||
phba->fc_stat.elsRcvRPL++;
|
phba->fc_stat.elsRcvRPL++;
|
||||||
lpfc_els_rcv_rpl(vport, elsiocb, ndlp);
|
lpfc_els_rcv_rpl(vport, elsiocb, ndlp);
|
||||||
if (newnode)
|
if (newnode)
|
||||||
lpfc_drop_node(vport, ndlp);
|
lpfc_drop_node(vport, ndlp);
|
||||||
break;
|
break;
|
||||||
case ELS_CMD_RNID:
|
case ELS_CMD_RNID:
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
|
||||||
|
"RCV RNID: did:x%x/ste:x%x flg:x%x",
|
||||||
|
did, vport->port_state, ndlp->nlp_flag);
|
||||||
|
|
||||||
phba->fc_stat.elsRcvRNID++;
|
phba->fc_stat.elsRcvRNID++;
|
||||||
lpfc_els_rcv_rnid(vport, elsiocb, ndlp);
|
lpfc_els_rcv_rnid(vport, elsiocb, ndlp);
|
||||||
if (newnode)
|
if (newnode)
|
||||||
lpfc_drop_node(vport, ndlp);
|
lpfc_drop_node(vport, ndlp);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
|
||||||
|
"RCV ELS cmd: cmd:x%x did:x%x/ste:x%x",
|
||||||
|
cmd, did, vport->port_state);
|
||||||
|
|
||||||
/* Unsupported ELS command, reject */
|
/* Unsupported ELS command, reject */
|
||||||
rjt_err = 2;
|
rjt_err = LSRJT_INVALID_CMD;
|
||||||
|
|
||||||
/* Unknown ELS command <elsCmd> received from NPORT <did> */
|
/* Unknown ELS command <elsCmd> received from NPORT <did> */
|
||||||
lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
|
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,
|
||||||
/* check if need to LS_RJT received ELS cmd */
|
/* check if need to LS_RJT received ELS cmd */
|
||||||
if (rjt_err) {
|
if (rjt_err) {
|
||||||
memset(&stat, 0, sizeof(stat));
|
memset(&stat, 0, sizeof(stat));
|
||||||
if (rjt_err == 1)
|
stat.un.b.lsRjtRsnCode = rjt_err;
|
||||||
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
|
|
||||||
else
|
|
||||||
stat.un.b.lsRjtRsnCode = LSRJT_INVALID_CMD;
|
|
||||||
stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
|
stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
|
||||||
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, elsiocb, ndlp);
|
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, elsiocb, ndlp,
|
||||||
|
NULL);
|
||||||
if (newnode)
|
if (newnode)
|
||||||
lpfc_drop_node(vport, ndlp);
|
lpfc_drop_node(vport, ndlp);
|
||||||
}
|
}
|
||||||
|
@ -4044,6 +4248,10 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||||
lpfc_set_disctmo(piocb->vport);
|
lpfc_set_disctmo(piocb->vport);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
|
||||||
|
"FDISC cmpl: status:x%x/x%x prevdid:x%x",
|
||||||
|
irsp->ulpStatus, irsp->un.ulpWord[4], vport->fc_prevDID);
|
||||||
|
|
||||||
if (irsp->ulpStatus) {
|
if (irsp->ulpStatus) {
|
||||||
/* Check for retry */
|
/* Check for retry */
|
||||||
if (lpfc_els_retry(phba, cmdiocb, rspiocb))
|
if (lpfc_els_retry(phba, cmdiocb, rspiocb))
|
||||||
|
@ -4054,6 +4262,7 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
||||||
"%d (%d):0124 FDISC failed. (%d/%d)\n",
|
"%d (%d):0124 FDISC failed. (%d/%d)\n",
|
||||||
phba->brd_no, vport->vpi,
|
phba->brd_no, vport->vpi,
|
||||||
irsp->ulpStatus, irsp->un.ulpWord[4]);
|
irsp->ulpStatus, irsp->un.ulpWord[4]);
|
||||||
|
|
||||||
if (vport->fc_vport->vport_state == FC_VPORT_INITIALIZING)
|
if (vport->fc_vport->vport_state == FC_VPORT_INITIALIZING)
|
||||||
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
|
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
|
||||||
|
|
||||||
|
@ -4113,14 +4322,11 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||||
uint16_t cmdsize;
|
uint16_t cmdsize;
|
||||||
int did = ndlp->nlp_DID;
|
int did = ndlp->nlp_DID;
|
||||||
int rc;
|
int rc;
|
||||||
int new_ndlp = 0;
|
|
||||||
|
|
||||||
cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm));
|
cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm));
|
||||||
elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, did,
|
elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, did,
|
||||||
ELS_CMD_FDISC);
|
ELS_CMD_FDISC);
|
||||||
if (!elsiocb) {
|
if (!elsiocb) {
|
||||||
if (new_ndlp)
|
|
||||||
mempool_free(ndlp, phba->nlp_mem_pool);
|
|
||||||
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
|
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
|
||||||
|
|
||||||
lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
|
lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
|
||||||
|
@ -4163,11 +4369,13 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||||
phba->fc_stat.elsXmitFDISC++;
|
phba->fc_stat.elsXmitFDISC++;
|
||||||
elsiocb->iocb_cmpl = lpfc_cmpl_els_fdisc;
|
elsiocb->iocb_cmpl = lpfc_cmpl_els_fdisc;
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
|
||||||
|
"Issue FDISC: did:x%x",
|
||||||
|
did, 0, 0);
|
||||||
|
|
||||||
rc = lpfc_issue_fabric_iocb(phba, elsiocb);
|
rc = lpfc_issue_fabric_iocb(phba, elsiocb);
|
||||||
if (rc == IOCB_ERROR) {
|
if (rc == IOCB_ERROR) {
|
||||||
lpfc_els_free_iocb(phba, elsiocb);
|
lpfc_els_free_iocb(phba, elsiocb);
|
||||||
if (new_ndlp)
|
|
||||||
mempool_free(ndlp, phba->nlp_mem_pool);
|
|
||||||
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
|
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
|
||||||
|
|
||||||
lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
|
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,
|
||||||
struct lpfc_iocbq *rspiocb)
|
struct lpfc_iocbq *rspiocb)
|
||||||
{
|
{
|
||||||
struct lpfc_vport *vport = cmdiocb->vport;
|
struct lpfc_vport *vport = cmdiocb->vport;
|
||||||
|
IOCB_t *irsp;
|
||||||
|
|
||||||
|
irsp = &rspiocb->iocb;
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
|
||||||
|
"LOGO npiv cmpl: status:x%x/x%x did:x%x",
|
||||||
|
irsp->ulpStatus, irsp->un.ulpWord[4], irsp->un.rcvels.remoteID);
|
||||||
|
|
||||||
lpfc_els_free_iocb(phba, cmdiocb);
|
lpfc_els_free_iocb(phba, cmdiocb);
|
||||||
vport->unreg_vpi_cmpl = VPORT_ERROR;
|
vport->unreg_vpi_cmpl = VPORT_ERROR;
|
||||||
|
@ -4218,6 +4432,10 @@ lpfc_issue_els_npiv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
|
||||||
pcmd += sizeof(uint32_t);
|
pcmd += sizeof(uint32_t);
|
||||||
memcpy(pcmd, &vport->fc_portname, sizeof(struct lpfc_name));
|
memcpy(pcmd, &vport->fc_portname, sizeof(struct lpfc_name));
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
|
||||||
|
"Issue LOGO npiv did:x%x flg:x%x",
|
||||||
|
ndlp->nlp_DID, ndlp->nlp_flag, 0);
|
||||||
|
|
||||||
elsiocb->iocb_cmpl = lpfc_cmpl_els_npiv_logo;
|
elsiocb->iocb_cmpl = lpfc_cmpl_els_npiv_logo;
|
||||||
spin_lock_irq(shost->host_lock);
|
spin_lock_irq(shost->host_lock);
|
||||||
ndlp->nlp_flag |= NLP_LOGO_SND;
|
ndlp->nlp_flag |= NLP_LOGO_SND;
|
||||||
|
@ -4277,6 +4495,10 @@ repeat:
|
||||||
iocb->iocb_cmpl = lpfc_cmpl_fabric_iocb;
|
iocb->iocb_cmpl = lpfc_cmpl_fabric_iocb;
|
||||||
iocb->iocb_flag |= LPFC_IO_FABRIC;
|
iocb->iocb_flag |= LPFC_IO_FABRIC;
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(iocb->vport, LPFC_DISC_TRC_ELS_CMD,
|
||||||
|
"Fabric sched1: ste:x%x",
|
||||||
|
iocb->vport->port_state, 0, 0);
|
||||||
|
|
||||||
ret = lpfc_sli_issue_iocb(phba, pring, iocb, 0);
|
ret = lpfc_sli_issue_iocb(phba, pring, iocb, 0);
|
||||||
|
|
||||||
if (ret == IOCB_ERROR) {
|
if (ret == IOCB_ERROR) {
|
||||||
|
@ -4387,6 +4609,10 @@ lpfc_issue_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *iocb)
|
||||||
iocb->iocb_cmpl = lpfc_cmpl_fabric_iocb;
|
iocb->iocb_cmpl = lpfc_cmpl_fabric_iocb;
|
||||||
iocb->iocb_flag |= LPFC_IO_FABRIC;
|
iocb->iocb_flag |= LPFC_IO_FABRIC;
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(iocb->vport, LPFC_DISC_TRC_ELS_CMD,
|
||||||
|
"Fabric sched2: ste:x%x",
|
||||||
|
iocb->vport->port_state, 0, 0);
|
||||||
|
|
||||||
atomic_inc(&phba->fabric_iocb_count);
|
atomic_inc(&phba->fabric_iocb_count);
|
||||||
ret = lpfc_sli_issue_iocb(phba, pring, iocb, 0);
|
ret = lpfc_sli_issue_iocb(phba, pring, iocb, 0);
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include "lpfc_logmsg.h"
|
#include "lpfc_logmsg.h"
|
||||||
#include "lpfc_crtn.h"
|
#include "lpfc_crtn.h"
|
||||||
#include "lpfc_vport.h"
|
#include "lpfc_vport.h"
|
||||||
|
#include "lpfc_debugfs.h"
|
||||||
|
|
||||||
/* AlpaArray for assignment of scsid for scan-down and bind_method */
|
/* AlpaArray for assignment of scsid for scan-down and bind_method */
|
||||||
static uint8_t lpfcAlpaArray[] = {
|
static uint8_t lpfcAlpaArray[] = {
|
||||||
|
@ -77,6 +78,10 @@ lpfc_terminate_rport_io(struct fc_rport *rport)
|
||||||
|
|
||||||
phba = ndlp->vport->phba;
|
phba = ndlp->vport->phba;
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_RPORT,
|
||||||
|
"rport terminate: sid:x%x did:x%x flg:x%x",
|
||||||
|
ndlp->nlp_sid, ndlp->nlp_DID, ndlp->nlp_flag);
|
||||||
|
|
||||||
if (ndlp->nlp_sid != NLP_NO_SID) {
|
if (ndlp->nlp_sid != NLP_NO_SID) {
|
||||||
lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
|
lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
|
||||||
ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT);
|
ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT);
|
||||||
|
@ -93,12 +98,10 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
|
||||||
{
|
{
|
||||||
struct lpfc_rport_data *rdata;
|
struct lpfc_rport_data *rdata;
|
||||||
struct lpfc_nodelist * ndlp;
|
struct lpfc_nodelist * ndlp;
|
||||||
uint8_t *name;
|
|
||||||
int warn_on = 0;
|
|
||||||
struct lpfc_hba *phba;
|
|
||||||
struct lpfc_vport *vport;
|
struct lpfc_vport *vport;
|
||||||
int put_node;
|
struct lpfc_hba *phba;
|
||||||
int put_rport;
|
struct completion devloss_compl;
|
||||||
|
struct lpfc_work_evt *evtp;
|
||||||
|
|
||||||
rdata = rport->dd_data;
|
rdata = rport->dd_data;
|
||||||
ndlp = rdata->pnode;
|
ndlp = rdata->pnode;
|
||||||
|
@ -112,7 +115,70 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vport = ndlp->vport;
|
||||||
|
phba = vport->phba;
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT,
|
||||||
|
"rport devlosscb: sid:x%x did:x%x flg:x%x",
|
||||||
|
ndlp->nlp_sid, ndlp->nlp_DID, ndlp->nlp_flag);
|
||||||
|
|
||||||
|
init_completion(&devloss_compl);
|
||||||
|
evtp = &ndlp->dev_loss_evt;
|
||||||
|
|
||||||
|
if (!list_empty(&evtp->evt_listp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
spin_lock_irq(&phba->hbalock);
|
||||||
|
evtp->evt_arg1 = ndlp;
|
||||||
|
evtp->evt_arg2 = &devloss_compl;
|
||||||
|
evtp->evt = LPFC_EVT_DEV_LOSS;
|
||||||
|
list_add_tail(&evtp->evt_listp, &phba->work_list);
|
||||||
|
if (phba->work_wait)
|
||||||
|
wake_up(phba->work_wait);
|
||||||
|
|
||||||
|
spin_unlock_irq(&phba->hbalock);
|
||||||
|
|
||||||
|
wait_for_completion(&devloss_compl);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function is called from the worker thread when dev_loss_tmo
|
||||||
|
* expire.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
|
||||||
|
{
|
||||||
|
struct lpfc_rport_data *rdata;
|
||||||
|
struct fc_rport *rport;
|
||||||
|
struct lpfc_vport *vport;
|
||||||
|
struct lpfc_hba *phba;
|
||||||
|
uint8_t *name;
|
||||||
|
int warn_on = 0;
|
||||||
|
|
||||||
|
rport = ndlp->rport;
|
||||||
|
|
||||||
|
if (!rport)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rdata = rport->dd_data;
|
||||||
|
name = (uint8_t *) &ndlp->nlp_portname;
|
||||||
|
vport = ndlp->vport;
|
||||||
|
phba = vport->phba;
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT,
|
||||||
|
"rport devlosstmo:did:x%x type:x%x id:x%x",
|
||||||
|
ndlp->nlp_DID, ndlp->nlp_type, rport->scsi_target_id);
|
||||||
|
|
||||||
|
if (!(vport->load_flag & FC_UNLOADING) &&
|
||||||
|
ndlp->nlp_state == NLP_STE_MAPPED_NODE)
|
||||||
|
return;
|
||||||
|
|
||||||
if (ndlp->nlp_type & NLP_FABRIC) {
|
if (ndlp->nlp_type & NLP_FABRIC) {
|
||||||
|
int put_node;
|
||||||
|
int put_rport;
|
||||||
|
|
||||||
/* We will clean up these Nodes in linkup */
|
/* We will clean up these Nodes in linkup */
|
||||||
put_node = rdata->pnode != NULL;
|
put_node = rdata->pnode != NULL;
|
||||||
put_rport = ndlp->rport != NULL;
|
put_rport = ndlp->rport != NULL;
|
||||||
|
@ -125,15 +191,6 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
name = (uint8_t *)&ndlp->nlp_portname;
|
|
||||||
vport = ndlp->vport;
|
|
||||||
phba = vport->phba;
|
|
||||||
|
|
||||||
if (!(vport->load_flag & FC_UNLOADING) &&
|
|
||||||
ndlp->nlp_state == NLP_STE_MAPPED_NODE)
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
|
||||||
if (ndlp->nlp_sid != NLP_NO_SID) {
|
if (ndlp->nlp_sid != NLP_NO_SID) {
|
||||||
warn_on = 1;
|
warn_on = 1;
|
||||||
/* flush the target */
|
/* flush the target */
|
||||||
|
@ -171,6 +228,9 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
|
||||||
(ndlp->nlp_state != NLP_STE_UNMAPPED_NODE))
|
(ndlp->nlp_state != NLP_STE_UNMAPPED_NODE))
|
||||||
lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM);
|
lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM);
|
||||||
else {
|
else {
|
||||||
|
int put_node;
|
||||||
|
int put_rport;
|
||||||
|
|
||||||
put_node = rdata->pnode != NULL;
|
put_node = rdata->pnode != NULL;
|
||||||
put_rport = ndlp->rport != NULL;
|
put_rport = ndlp->rport != NULL;
|
||||||
rdata->pnode = NULL;
|
rdata->pnode = NULL;
|
||||||
|
@ -180,7 +240,6 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
|
||||||
if (put_rport)
|
if (put_rport)
|
||||||
put_device(&rport->dev);
|
put_device(&rport->dev);
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -206,12 +265,17 @@ lpfc_work_list_done(struct lpfc_hba *phba)
|
||||||
spin_unlock_irq(&phba->hbalock);
|
spin_unlock_irq(&phba->hbalock);
|
||||||
free_evt = 1;
|
free_evt = 1;
|
||||||
switch (evtp->evt) {
|
switch (evtp->evt) {
|
||||||
case LPFC_EVT_DEV_LOSS:
|
case LPFC_EVT_DEV_LOSS_DELAY:
|
||||||
free_evt = 0; /* evt is part of ndlp */
|
free_evt = 0; /* evt is part of ndlp */
|
||||||
ndlp = (struct lpfc_nodelist *) (evtp->evt_arg1);
|
ndlp = (struct lpfc_nodelist *) (evtp->evt_arg1);
|
||||||
vport = ndlp->vport;
|
vport = ndlp->vport;
|
||||||
if (!vport)
|
if (!vport)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT,
|
||||||
|
"rport devlossdly:did:x%x flg:x%x",
|
||||||
|
ndlp->nlp_DID, ndlp->nlp_flag, 0);
|
||||||
|
|
||||||
if (!(vport->load_flag & FC_UNLOADING) &&
|
if (!(vport->load_flag & FC_UNLOADING) &&
|
||||||
!(ndlp->nlp_flag & NLP_DELAY_TMO) &&
|
!(ndlp->nlp_flag & NLP_DELAY_TMO) &&
|
||||||
!(ndlp->nlp_flag & NLP_NPR_2B_DISC)) {
|
!(ndlp->nlp_flag & NLP_NPR_2B_DISC)) {
|
||||||
|
@ -224,6 +288,14 @@ lpfc_work_list_done(struct lpfc_hba *phba)
|
||||||
lpfc_els_retry_delay_handler(ndlp);
|
lpfc_els_retry_delay_handler(ndlp);
|
||||||
free_evt = 0; /* evt is part of ndlp */
|
free_evt = 0; /* evt is part of ndlp */
|
||||||
break;
|
break;
|
||||||
|
case LPFC_EVT_DEV_LOSS:
|
||||||
|
ndlp = (struct lpfc_nodelist *)(evtp->evt_arg1);
|
||||||
|
lpfc_nlp_get(ndlp);
|
||||||
|
lpfc_dev_loss_tmo_handler(ndlp);
|
||||||
|
free_evt = 0;
|
||||||
|
complete((struct completion *)(evtp->evt_arg2));
|
||||||
|
lpfc_nlp_put(ndlp);
|
||||||
|
break;
|
||||||
case LPFC_EVT_ONLINE:
|
case LPFC_EVT_ONLINE:
|
||||||
if (phba->link_state < LPFC_LINK_DOWN)
|
if (phba->link_state < LPFC_LINK_DOWN)
|
||||||
*(int *) (evtp->evt_arg1) = lpfc_online(phba);
|
*(int *) (evtp->evt_arg1) = lpfc_online(phba);
|
||||||
|
@ -272,13 +344,12 @@ lpfc_work_list_done(struct lpfc_hba *phba)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
lpfc_work_done(struct lpfc_hba *phba)
|
lpfc_work_done(struct lpfc_hba *phba)
|
||||||
{
|
{
|
||||||
struct lpfc_sli_ring *pring;
|
struct lpfc_sli_ring *pring;
|
||||||
uint32_t ha_copy, control, work_port_events;
|
uint32_t ha_copy, status, control, work_port_events;
|
||||||
struct lpfc_vport *vport;
|
struct lpfc_vport *vport;
|
||||||
int i;
|
|
||||||
|
|
||||||
spin_lock_irq(&phba->hbalock);
|
spin_lock_irq(&phba->hbalock);
|
||||||
ha_copy = phba->work_ha;
|
ha_copy = phba->work_ha;
|
||||||
|
@ -310,6 +381,9 @@ lpfc_work_done(struct lpfc_hba *phba)
|
||||||
if (work_port_events & WORKER_ELS_TMO)
|
if (work_port_events & WORKER_ELS_TMO)
|
||||||
lpfc_els_timeout_handler(vport);
|
lpfc_els_timeout_handler(vport);
|
||||||
|
|
||||||
|
if (work_port_events & WORKER_HB_TMO)
|
||||||
|
lpfc_hb_timeout_handler(phba);
|
||||||
|
|
||||||
if (work_port_events & WORKER_MBOX_TMO)
|
if (work_port_events & WORKER_MBOX_TMO)
|
||||||
lpfc_mbox_timeout_handler(phba);
|
lpfc_mbox_timeout_handler(phba);
|
||||||
|
|
||||||
|
@ -333,30 +407,31 @@ lpfc_work_done(struct lpfc_hba *phba)
|
||||||
}
|
}
|
||||||
spin_unlock_irq(&phba->hbalock);
|
spin_unlock_irq(&phba->hbalock);
|
||||||
|
|
||||||
for (i = 0; i < phba->sli.num_rings; i++, ha_copy >>= 4) {
|
pring = &phba->sli.ring[LPFC_ELS_RING];
|
||||||
pring = &phba->sli.ring[i];
|
status = (ha_copy & (HA_RXMASK << (4*LPFC_ELS_RING)));
|
||||||
if ((ha_copy & HA_RXATT)
|
status >>= (4*LPFC_ELS_RING);
|
||||||
|| (pring->flag & LPFC_DEFERRED_RING_EVENT)) {
|
if ((status & HA_RXMASK)
|
||||||
if (pring->flag & LPFC_STOP_IOCB_MASK) {
|
|| (pring->flag & LPFC_DEFERRED_RING_EVENT)) {
|
||||||
pring->flag |= LPFC_DEFERRED_RING_EVENT;
|
if (pring->flag & LPFC_STOP_IOCB_MASK) {
|
||||||
} else {
|
pring->flag |= LPFC_DEFERRED_RING_EVENT;
|
||||||
lpfc_sli_handle_slow_ring_event(phba, pring,
|
} else {
|
||||||
(ha_copy &
|
lpfc_sli_handle_slow_ring_event(phba, pring,
|
||||||
HA_RXMASK));
|
(status &
|
||||||
pring->flag &= ~LPFC_DEFERRED_RING_EVENT;
|
HA_RXMASK));
|
||||||
}
|
pring->flag &= ~LPFC_DEFERRED_RING_EVENT;
|
||||||
/*
|
}
|
||||||
* Turn on Ring interrupts
|
/*
|
||||||
*/
|
* Turn on Ring interrupts
|
||||||
spin_lock_irq(&phba->hbalock);
|
*/
|
||||||
control = readl(phba->HCregaddr);
|
spin_lock_irq(&phba->hbalock);
|
||||||
control |= (HC_R0INT_ENA << i);
|
control = readl(phba->HCregaddr);
|
||||||
|
if (!(control & (HC_R0INT_ENA << LPFC_ELS_RING))) {
|
||||||
|
control |= (HC_R0INT_ENA << LPFC_ELS_RING);
|
||||||
writel(control, phba->HCregaddr);
|
writel(control, phba->HCregaddr);
|
||||||
readl(phba->HCregaddr); /* flush */
|
readl(phba->HCregaddr); /* flush */
|
||||||
spin_unlock_irq(&phba->hbalock);
|
|
||||||
}
|
}
|
||||||
|
spin_unlock_irq(&phba->hbalock);
|
||||||
}
|
}
|
||||||
|
|
||||||
lpfc_work_list_done(phba);
|
lpfc_work_list_done(phba);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,7 +440,7 @@ check_work_wait_done(struct lpfc_hba *phba)
|
||||||
{
|
{
|
||||||
struct lpfc_vport *vport;
|
struct lpfc_vport *vport;
|
||||||
struct lpfc_sli_ring *pring;
|
struct lpfc_sli_ring *pring;
|
||||||
int i, rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
spin_lock_irq(&phba->hbalock);
|
spin_lock_irq(&phba->hbalock);
|
||||||
list_for_each_entry(vport, &phba->port_list, listentry) {
|
list_for_each_entry(vport, &phba->port_list, listentry) {
|
||||||
|
@ -380,13 +455,10 @@ check_work_wait_done(struct lpfc_hba *phba)
|
||||||
rc = 1;
|
rc = 1;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
for (i = 0; i < phba->sli.num_rings; i++) {
|
|
||||||
pring = &phba->sli.ring[i];
|
pring = &phba->sli.ring[LPFC_ELS_RING];
|
||||||
if (pring->flag & LPFC_DEFERRED_RING_EVENT) {
|
if (pring->flag & LPFC_DEFERRED_RING_EVENT)
|
||||||
rc = 1;
|
rc = 1;
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exit:
|
exit:
|
||||||
if (rc)
|
if (rc)
|
||||||
phba->work_found++;
|
phba->work_found++;
|
||||||
|
@ -506,6 +578,10 @@ lpfc_linkdown_port(struct lpfc_vport *vport)
|
||||||
|
|
||||||
fc_host_post_event(shost, fc_get_event_number(), FCH_EVT_LINKDOWN, 0);
|
fc_host_post_event(shost, fc_get_event_number(), FCH_EVT_LINKDOWN, 0);
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
|
||||||
|
"Link Down: state:x%x rtry:x%x flg:x%x",
|
||||||
|
vport->port_state, vport->fc_ns_retry, vport->fc_flag);
|
||||||
|
|
||||||
/* Cleanup any outstanding RSCN activity */
|
/* Cleanup any outstanding RSCN activity */
|
||||||
lpfc_els_flush_rscn(vport);
|
lpfc_els_flush_rscn(vport);
|
||||||
|
|
||||||
|
@ -617,6 +693,10 @@ lpfc_linkup_port(struct lpfc_vport *vport)
|
||||||
if ((vport->load_flag & FC_UNLOADING) != 0)
|
if ((vport->load_flag & FC_UNLOADING) != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
|
||||||
|
"Link Up: top:x%x speed:x%x flg:x%x",
|
||||||
|
phba->fc_topology, phba->fc_linkspeed, phba->link_flag);
|
||||||
|
|
||||||
/* If NPIV is not enabled, only bring the physical port up */
|
/* If NPIV is not enabled, only bring the physical port up */
|
||||||
if (!(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
|
if (!(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
|
||||||
(vport != phba->pport))
|
(vport != phba->pport))
|
||||||
|
@ -935,7 +1015,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)) {
|
if (!(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)) {
|
||||||
if (phba->max_vpi && lpfc_npiv_enable &&
|
if (phba->max_vpi && phba->cfg_npiv_enable &&
|
||||||
(phba->sli_rev == 3))
|
(phba->sli_rev == 3))
|
||||||
phba->sli3_options |= LPFC_SLI3_NPIV_ENABLED;
|
phba->sli3_options |= LPFC_SLI3_NPIV_ENABLED;
|
||||||
}
|
}
|
||||||
|
@ -1124,8 +1204,6 @@ lpfc_mbx_cmpl_unreg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
|
||||||
"mb status = 0x%x\n",
|
"mb status = 0x%x\n",
|
||||||
phba->brd_no, vport->vpi, mb->mbxStatus);
|
phba->brd_no, vport->vpi, mb->mbxStatus);
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
phba->vpi_cnt--;
|
|
||||||
}
|
}
|
||||||
vport->unreg_vpi_cmpl = VPORT_OK;
|
vport->unreg_vpi_cmpl = VPORT_OK;
|
||||||
mempool_free(pmb, phba->mbox_mem_pool);
|
mempool_free(pmb, phba->mbox_mem_pool);
|
||||||
|
@ -1182,7 +1260,6 @@ lpfc_mbx_cmpl_reg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
|
||||||
vport->fc_myDID = 0;
|
vport->fc_myDID = 0;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
phba->vpi_cnt++;
|
|
||||||
|
|
||||||
vport->num_disc_nodes = 0;
|
vport->num_disc_nodes = 0;
|
||||||
/* go thru NPR list and issue ELS PLOGIs */
|
/* 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)
|
||||||
|
|
||||||
if (phba->link_flag & LS_NPIV_FAB_SUPPORTED)
|
if (phba->link_flag & LS_NPIV_FAB_SUPPORTED)
|
||||||
lpfc_initial_fdisc(next_vport);
|
lpfc_initial_fdisc(next_vport);
|
||||||
else {
|
else if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
|
||||||
if (phba->sli3_options &
|
lpfc_vport_set_state(vport,
|
||||||
LPFC_SLI3_NPIV_ENABLED) {
|
FC_VPORT_NO_FABRIC_SUPP);
|
||||||
lpfc_vport_set_state(vport,
|
lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
|
||||||
FC_VPORT_NO_FABRIC_SUPP);
|
|
||||||
lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
|
|
||||||
"%d (%d):0259 No NPIV Fabric "
|
"%d (%d):0259 No NPIV Fabric "
|
||||||
"support\n",
|
"support\n",
|
||||||
phba->brd_no, vport->vpi);
|
phba->brd_no, vport->vpi);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lpfc_do_scr_ns_plogi(phba, vport);
|
lpfc_do_scr_ns_plogi(phba, vport);
|
||||||
|
@ -1377,6 +1451,11 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
|
||||||
((struct lpfc_rport_data *) ndlp->rport->dd_data)->pnode == ndlp) {
|
((struct lpfc_rport_data *) ndlp->rport->dd_data)->pnode == ndlp) {
|
||||||
lpfc_nlp_put(ndlp);
|
lpfc_nlp_put(ndlp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT,
|
||||||
|
"rport add: did:x%x flg:x%x type x%x",
|
||||||
|
ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type);
|
||||||
|
|
||||||
ndlp->rport = rport = fc_remote_port_add(shost, 0, &rport_ids);
|
ndlp->rport = rport = fc_remote_port_add(shost, 0, &rport_ids);
|
||||||
if (!rport || !get_device(&rport->dev)) {
|
if (!rport || !get_device(&rport->dev)) {
|
||||||
dev_printk(KERN_WARNING, &phba->pcidev->dev,
|
dev_printk(KERN_WARNING, &phba->pcidev->dev,
|
||||||
|
@ -1394,7 +1473,6 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
|
||||||
rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
|
rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
|
||||||
if (ndlp->nlp_type & NLP_FCP_INITIATOR)
|
if (ndlp->nlp_type & NLP_FCP_INITIATOR)
|
||||||
rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;
|
rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;
|
||||||
del_timer_sync(&ndlp->nlp_initiator_tmr);
|
|
||||||
|
|
||||||
|
|
||||||
if (rport_ids.roles != FC_RPORT_ROLE_UNKNOWN)
|
if (rport_ids.roles != FC_RPORT_ROLE_UNKNOWN)
|
||||||
|
@ -1412,6 +1490,10 @@ lpfc_unregister_remote_port(struct lpfc_nodelist *ndlp)
|
||||||
{
|
{
|
||||||
struct fc_rport *rport = ndlp->rport;
|
struct fc_rport *rport = ndlp->rport;
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_RPORT,
|
||||||
|
"rport delete: did:x%x flg:x%x type x%x",
|
||||||
|
ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type);
|
||||||
|
|
||||||
fc_remote_port_delete(rport);
|
fc_remote_port_delete(rport);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -1478,20 +1560,19 @@ lpfc_nlp_state_cleanup(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||||
if (new_state == NLP_STE_MAPPED_NODE ||
|
if (new_state == NLP_STE_MAPPED_NODE ||
|
||||||
new_state == NLP_STE_UNMAPPED_NODE) {
|
new_state == NLP_STE_UNMAPPED_NODE) {
|
||||||
vport->phba->nport_event_cnt++;
|
vport->phba->nport_event_cnt++;
|
||||||
/*
|
/*
|
||||||
* Tell the fc transport about the port, if we haven't
|
* Tell the fc transport about the port, if we haven't
|
||||||
* already. If we have, and it's a scsi entity, be
|
* already. If we have, and it's a scsi entity, be
|
||||||
* sure to unblock any attached scsi devices
|
* sure to unblock any attached scsi devices
|
||||||
*/
|
*/
|
||||||
lpfc_register_remote_port(vport, ndlp);
|
lpfc_register_remote_port(vport, ndlp);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
/*
|
* if we added to Mapped list, but the remote port
|
||||||
* if we added to Mapped list, but the remote port
|
* registration failed or assigned a target id outside
|
||||||
* registration failed or assigned a target id outside
|
* our presentable range - move the node to the
|
||||||
* our presentable range - move the node to the
|
* Unmapped List
|
||||||
* Unmapped List
|
*/
|
||||||
*/
|
|
||||||
if (new_state == NLP_STE_MAPPED_NODE &&
|
if (new_state == NLP_STE_MAPPED_NODE &&
|
||||||
(!ndlp->rport ||
|
(!ndlp->rport ||
|
||||||
ndlp->rport->scsi_target_id == -1 ||
|
ndlp->rport->scsi_target_id == -1 ||
|
||||||
|
@ -1533,11 +1614,16 @@ lpfc_nlp_set_state(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||||
char name1[16], name2[16];
|
char name1[16], name2[16];
|
||||||
|
|
||||||
lpfc_printf_log(vport->phba, KERN_INFO, LOG_NODE,
|
lpfc_printf_log(vport->phba, KERN_INFO, LOG_NODE,
|
||||||
"%d:0904 NPort state transition x%06x, %s -> %s\n",
|
"%d (%d):0904 NPort state transition x%06x, %s -> %s\n",
|
||||||
vport->phba->brd_no,
|
vport->phba->brd_no, vport->vpi,
|
||||||
ndlp->nlp_DID,
|
ndlp->nlp_DID,
|
||||||
lpfc_nlp_state_name(name1, sizeof(name1), old_state),
|
lpfc_nlp_state_name(name1, sizeof(name1), old_state),
|
||||||
lpfc_nlp_state_name(name2, sizeof(name2), state));
|
lpfc_nlp_state_name(name2, sizeof(name2), state));
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_NODE,
|
||||||
|
"node statechg did:x%x old:%d ste:%d",
|
||||||
|
ndlp->nlp_DID, old_state, state);
|
||||||
|
|
||||||
if (old_state == NLP_STE_NPR_NODE &&
|
if (old_state == NLP_STE_NPR_NODE &&
|
||||||
(ndlp->nlp_flag & NLP_DELAY_TMO) != 0 &&
|
(ndlp->nlp_flag & NLP_DELAY_TMO) != 0 &&
|
||||||
state != NLP_STE_NPR_NODE)
|
state != NLP_STE_NPR_NODE)
|
||||||
|
@ -1571,7 +1657,8 @@ lpfc_dequeue_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
|
||||||
spin_lock_irq(shost->host_lock);
|
spin_lock_irq(shost->host_lock);
|
||||||
list_del_init(&ndlp->nlp_listp);
|
list_del_init(&ndlp->nlp_listp);
|
||||||
spin_unlock_irq(shost->host_lock);
|
spin_unlock_irq(shost->host_lock);
|
||||||
lpfc_nlp_state_cleanup(vport, ndlp, ndlp->nlp_state, 0);
|
lpfc_nlp_state_cleanup(vport, ndlp, ndlp->nlp_state,
|
||||||
|
NLP_STE_UNUSED_NODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1585,6 +1672,7 @@ lpfc_drop_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
|
||||||
lpfc_nlp_counters(vport, ndlp->nlp_state, -1);
|
lpfc_nlp_counters(vport, ndlp->nlp_state, -1);
|
||||||
spin_lock_irq(shost->host_lock);
|
spin_lock_irq(shost->host_lock);
|
||||||
list_del_init(&ndlp->nlp_listp);
|
list_del_init(&ndlp->nlp_listp);
|
||||||
|
ndlp->nlp_flag &= ~NLP_TARGET_REMOVE;
|
||||||
spin_unlock_irq(shost->host_lock);
|
spin_unlock_irq(shost->host_lock);
|
||||||
lpfc_nlp_put(ndlp);
|
lpfc_nlp_put(ndlp);
|
||||||
}
|
}
|
||||||
|
@ -1609,6 +1697,13 @@ lpfc_set_disctmo(struct lpfc_vport *vport)
|
||||||
tmo = ((phba->fc_ratov * 3) + 3);
|
tmo = ((phba->fc_ratov * 3) + 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!timer_pending(&vport->fc_disctmo)) {
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
|
||||||
|
"set disc timer: tmo:x%x state:x%x flg:x%x",
|
||||||
|
tmo, vport->port_state, vport->fc_flag);
|
||||||
|
}
|
||||||
|
|
||||||
mod_timer(&vport->fc_disctmo, jiffies + HZ * tmo);
|
mod_timer(&vport->fc_disctmo, jiffies + HZ * tmo);
|
||||||
spin_lock_irq(shost->host_lock);
|
spin_lock_irq(shost->host_lock);
|
||||||
vport->fc_flag |= FC_DISC_TMO;
|
vport->fc_flag |= FC_DISC_TMO;
|
||||||
|
@ -1635,6 +1730,10 @@ lpfc_can_disctmo(struct lpfc_vport *vport)
|
||||||
struct lpfc_hba *phba = vport->phba;
|
struct lpfc_hba *phba = vport->phba;
|
||||||
unsigned long iflags;
|
unsigned long iflags;
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
|
||||||
|
"can disc timer: state:x%x rtry:x%x flg:x%x",
|
||||||
|
vport->port_state, vport->fc_ns_retry, vport->fc_flag);
|
||||||
|
|
||||||
/* Turn off discovery timer if its running */
|
/* Turn off discovery timer if its running */
|
||||||
if (vport->fc_flag & FC_DISC_TMO) {
|
if (vport->fc_flag & FC_DISC_TMO) {
|
||||||
spin_lock_irqsave(shost->host_lock, iflags);
|
spin_lock_irqsave(shost->host_lock, iflags);
|
||||||
|
@ -1898,13 +1997,17 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
|
||||||
|
|
||||||
ndlp->nlp_last_elscmd = 0;
|
ndlp->nlp_last_elscmd = 0;
|
||||||
del_timer_sync(&ndlp->nlp_delayfunc);
|
del_timer_sync(&ndlp->nlp_delayfunc);
|
||||||
del_timer_sync(&ndlp->nlp_initiator_tmr);
|
|
||||||
|
|
||||||
if (!list_empty(&ndlp->els_retry_evt.evt_listp))
|
if (!list_empty(&ndlp->els_retry_evt.evt_listp))
|
||||||
list_del_init(&ndlp->els_retry_evt.evt_listp);
|
list_del_init(&ndlp->els_retry_evt.evt_listp);
|
||||||
if (!list_empty(&ndlp->dev_loss_evt.evt_listp))
|
if (!list_empty(&ndlp->dev_loss_evt.evt_listp))
|
||||||
list_del_init(&ndlp->dev_loss_evt.evt_listp);
|
list_del_init(&ndlp->dev_loss_evt.evt_listp);
|
||||||
|
|
||||||
|
if (!list_empty(&ndlp->dev_loss_evt.evt_listp)) {
|
||||||
|
list_del_init(&ndlp->dev_loss_evt.evt_listp);
|
||||||
|
complete((struct completion *)(ndlp->dev_loss_evt.evt_arg2));
|
||||||
|
}
|
||||||
|
|
||||||
lpfc_unreg_rpi(vport, ndlp);
|
lpfc_unreg_rpi(vport, ndlp);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2418,6 +2521,10 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport)
|
||||||
vport->fc_flag &= ~FC_DISC_TMO;
|
vport->fc_flag &= ~FC_DISC_TMO;
|
||||||
spin_unlock_irq(shost->host_lock);
|
spin_unlock_irq(shost->host_lock);
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
|
||||||
|
"disc timeout: state:x%x rtry:x%x flg:x%x",
|
||||||
|
vport->port_state, vport->fc_ns_retry, vport->fc_flag);
|
||||||
|
|
||||||
switch (vport->port_state) {
|
switch (vport->port_state) {
|
||||||
|
|
||||||
case LPFC_LOCAL_CFG_LINK:
|
case LPFC_LOCAL_CFG_LINK:
|
||||||
|
@ -2743,7 +2850,7 @@ lpfc_findnode_wwpn(struct lpfc_vport *vport, struct lpfc_name *wwpn)
|
||||||
spin_lock_irq(shost->host_lock);
|
spin_lock_irq(shost->host_lock);
|
||||||
ndlp = __lpfc_find_node(vport, lpfc_filter_by_wwpn, wwpn);
|
ndlp = __lpfc_find_node(vport, lpfc_filter_by_wwpn, wwpn);
|
||||||
spin_unlock_irq(shost->host_lock);
|
spin_unlock_irq(shost->host_lock);
|
||||||
return NULL;
|
return ndlp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -2764,7 +2871,7 @@ lpfc_dev_loss_delay(unsigned long ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
evtp->evt_arg1 = ndlp;
|
evtp->evt_arg1 = ndlp;
|
||||||
evtp->evt = LPFC_EVT_DEV_LOSS;
|
evtp->evt = LPFC_EVT_DEV_LOSS_DELAY;
|
||||||
list_add_tail(&evtp->evt_listp, &phba->work_list);
|
list_add_tail(&evtp->evt_listp, &phba->work_list);
|
||||||
if (phba->work_wait)
|
if (phba->work_wait)
|
||||||
lpfc_worker_wake_up(phba);
|
lpfc_worker_wake_up(phba);
|
||||||
|
@ -2779,9 +2886,6 @@ lpfc_nlp_init(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||||
memset(ndlp, 0, sizeof (struct lpfc_nodelist));
|
memset(ndlp, 0, sizeof (struct lpfc_nodelist));
|
||||||
INIT_LIST_HEAD(&ndlp->els_retry_evt.evt_listp);
|
INIT_LIST_HEAD(&ndlp->els_retry_evt.evt_listp);
|
||||||
INIT_LIST_HEAD(&ndlp->dev_loss_evt.evt_listp);
|
INIT_LIST_HEAD(&ndlp->dev_loss_evt.evt_listp);
|
||||||
init_timer(&ndlp->nlp_initiator_tmr);
|
|
||||||
ndlp->nlp_initiator_tmr.function = lpfc_dev_loss_delay;
|
|
||||||
ndlp->nlp_initiator_tmr.data = (unsigned long)ndlp;
|
|
||||||
init_timer(&ndlp->nlp_delayfunc);
|
init_timer(&ndlp->nlp_delayfunc);
|
||||||
ndlp->nlp_delayfunc.function = lpfc_els_retry_delay;
|
ndlp->nlp_delayfunc.function = lpfc_els_retry_delay;
|
||||||
ndlp->nlp_delayfunc.data = (unsigned long)ndlp;
|
ndlp->nlp_delayfunc.data = (unsigned long)ndlp;
|
||||||
|
@ -2790,6 +2894,11 @@ lpfc_nlp_init(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||||
ndlp->nlp_sid = NLP_NO_SID;
|
ndlp->nlp_sid = NLP_NO_SID;
|
||||||
INIT_LIST_HEAD(&ndlp->nlp_listp);
|
INIT_LIST_HEAD(&ndlp->nlp_listp);
|
||||||
kref_init(&ndlp->kref);
|
kref_init(&ndlp->kref);
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_NODE,
|
||||||
|
"node init: did:x%x",
|
||||||
|
ndlp->nlp_DID, 0, 0);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2798,6 +2907,11 @@ lpfc_nlp_release(struct kref *kref)
|
||||||
{
|
{
|
||||||
struct lpfc_nodelist *ndlp = container_of(kref, struct lpfc_nodelist,
|
struct lpfc_nodelist *ndlp = container_of(kref, struct lpfc_nodelist,
|
||||||
kref);
|
kref);
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_NODE,
|
||||||
|
"node release: did:x%x flg:x%x type:x%x",
|
||||||
|
ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type);
|
||||||
|
|
||||||
lpfc_nlp_remove(ndlp->vport, ndlp);
|
lpfc_nlp_remove(ndlp->vport, ndlp);
|
||||||
mempool_free(ndlp, ndlp->vport->phba->nlp_mem_pool);
|
mempool_free(ndlp, ndlp->vport->phba->nlp_mem_pool);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1278,6 +1278,7 @@ typedef struct { /* FireFly BIU registers */
|
||||||
#define MBX_KILL_BOARD 0x24
|
#define MBX_KILL_BOARD 0x24
|
||||||
#define MBX_CONFIG_FARP 0x25
|
#define MBX_CONFIG_FARP 0x25
|
||||||
#define MBX_BEACON 0x2A
|
#define MBX_BEACON 0x2A
|
||||||
|
#define MBX_HEARTBEAT 0x31
|
||||||
|
|
||||||
#define MBX_CONFIG_HBQ 0x7C
|
#define MBX_CONFIG_HBQ 0x7C
|
||||||
#define MBX_LOAD_AREA 0x81
|
#define MBX_LOAD_AREA 0x81
|
||||||
|
@ -1777,8 +1778,6 @@ typedef struct {
|
||||||
#define LMT_4Gb 0x040
|
#define LMT_4Gb 0x040
|
||||||
#define LMT_8Gb 0x080
|
#define LMT_8Gb 0x080
|
||||||
#define LMT_10Gb 0x100
|
#define LMT_10Gb 0x100
|
||||||
|
|
||||||
|
|
||||||
uint32_t rsvd2;
|
uint32_t rsvd2;
|
||||||
uint32_t rsvd3;
|
uint32_t rsvd3;
|
||||||
uint32_t max_xri;
|
uint32_t max_xri;
|
||||||
|
@ -1787,7 +1786,10 @@ typedef struct {
|
||||||
uint32_t avail_xri;
|
uint32_t avail_xri;
|
||||||
uint32_t avail_iocb;
|
uint32_t avail_iocb;
|
||||||
uint32_t avail_rpi;
|
uint32_t avail_rpi;
|
||||||
uint32_t default_rpi;
|
uint32_t max_vpi;
|
||||||
|
uint32_t rsvd4;
|
||||||
|
uint32_t rsvd5;
|
||||||
|
uint32_t avail_vpi;
|
||||||
} READ_CONFIG_VAR;
|
} READ_CONFIG_VAR;
|
||||||
|
|
||||||
/* Structure for MB Command READ_RCONFIG (12) */
|
/* Structure for MB Command READ_RCONFIG (12) */
|
||||||
|
@ -3171,3 +3173,16 @@ lpfc_is_LC_HBA(unsigned short device)
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine if an IOCB failed because of a link event or firmware reset.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
lpfc_error_lost_link(IOCB_t *iocbp)
|
||||||
|
{
|
||||||
|
return (iocbp->ulpStatus == IOSTAT_LOCAL_REJECT &&
|
||||||
|
(iocbp->un.ulpWord[4] == IOERR_SLI_ABORTED ||
|
||||||
|
iocbp->un.ulpWord[4] == IOERR_LINK_DOWN ||
|
||||||
|
iocbp->un.ulpWord[4] == IOERR_SLI_DOWN));
|
||||||
|
}
|
||||||
|
|
|
@ -391,6 +391,9 @@ lpfc_config_port_post(struct lpfc_hba *phba)
|
||||||
*/
|
*/
|
||||||
timeout = phba->fc_ratov << 1;
|
timeout = phba->fc_ratov << 1;
|
||||||
mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout);
|
mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout);
|
||||||
|
mod_timer(&phba->hb_tmofunc, jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
|
||||||
|
phba->hb_outstanding = 0;
|
||||||
|
phba->last_completion_time = jiffies;
|
||||||
|
|
||||||
lpfc_init_link(phba, pmb, phba->cfg_topology, phba->cfg_link_speed);
|
lpfc_init_link(phba, pmb, phba->cfg_topology, phba->cfg_link_speed);
|
||||||
pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
|
pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
|
||||||
|
@ -485,6 +488,119 @@ lpfc_hba_down_post(struct lpfc_hba *phba)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* HBA heart beat timeout handler */
|
||||||
|
void
|
||||||
|
lpfc_hb_timeout(unsigned long ptr)
|
||||||
|
{
|
||||||
|
struct lpfc_hba *phba;
|
||||||
|
unsigned long iflag;
|
||||||
|
|
||||||
|
phba = (struct lpfc_hba *)ptr;
|
||||||
|
spin_lock_irqsave(&phba->pport->work_port_lock, iflag);
|
||||||
|
if (!(phba->pport->work_port_events & WORKER_HB_TMO))
|
||||||
|
phba->pport->work_port_events |= WORKER_HB_TMO;
|
||||||
|
spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag);
|
||||||
|
|
||||||
|
if (phba->work_wait)
|
||||||
|
wake_up(phba->work_wait);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
lpfc_hb_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq)
|
||||||
|
{
|
||||||
|
unsigned long drvr_flag;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&phba->hbalock, drvr_flag);
|
||||||
|
phba->hb_outstanding = 0;
|
||||||
|
spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
|
||||||
|
|
||||||
|
mempool_free(pmboxq, phba->mbox_mem_pool);
|
||||||
|
if (!(phba->pport->fc_flag & FC_OFFLINE_MODE) &&
|
||||||
|
!(phba->link_state == LPFC_HBA_ERROR) &&
|
||||||
|
!(phba->pport->fc_flag & FC_UNLOADING))
|
||||||
|
mod_timer(&phba->hb_tmofunc,
|
||||||
|
jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
lpfc_hb_timeout_handler(struct lpfc_hba *phba)
|
||||||
|
{
|
||||||
|
LPFC_MBOXQ_t *pmboxq;
|
||||||
|
int retval;
|
||||||
|
struct lpfc_sli *psli = &phba->sli;
|
||||||
|
|
||||||
|
if ((phba->link_state == LPFC_HBA_ERROR) ||
|
||||||
|
(phba->pport->fc_flag & FC_UNLOADING) ||
|
||||||
|
(phba->pport->fc_flag & FC_OFFLINE_MODE))
|
||||||
|
return;
|
||||||
|
|
||||||
|
spin_lock_irq(&phba->pport->work_port_lock);
|
||||||
|
/* If the timer is already canceled do nothing */
|
||||||
|
if (!(phba->pport->work_port_events & WORKER_HB_TMO)) {
|
||||||
|
spin_unlock_irq(&phba->pport->work_port_lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (time_after(phba->last_completion_time + LPFC_HB_MBOX_INTERVAL * HZ,
|
||||||
|
jiffies)) {
|
||||||
|
spin_unlock_irq(&phba->pport->work_port_lock);
|
||||||
|
if (!phba->hb_outstanding)
|
||||||
|
mod_timer(&phba->hb_tmofunc,
|
||||||
|
jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
|
||||||
|
else
|
||||||
|
mod_timer(&phba->hb_tmofunc,
|
||||||
|
jiffies + HZ * LPFC_HB_MBOX_TIMEOUT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
spin_unlock_irq(&phba->pport->work_port_lock);
|
||||||
|
|
||||||
|
/* If there is no heart beat outstanding, issue a heartbeat command */
|
||||||
|
if (!phba->hb_outstanding) {
|
||||||
|
pmboxq = mempool_alloc(phba->mbox_mem_pool,GFP_KERNEL);
|
||||||
|
if (!pmboxq) {
|
||||||
|
mod_timer(&phba->hb_tmofunc,
|
||||||
|
jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lpfc_heart_beat(phba, pmboxq);
|
||||||
|
pmboxq->mbox_cmpl = lpfc_hb_mbox_cmpl;
|
||||||
|
pmboxq->vport = phba->pport;
|
||||||
|
retval = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT);
|
||||||
|
|
||||||
|
if (retval != MBX_BUSY && retval != MBX_SUCCESS) {
|
||||||
|
mempool_free(pmboxq, phba->mbox_mem_pool);
|
||||||
|
mod_timer(&phba->hb_tmofunc,
|
||||||
|
jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mod_timer(&phba->hb_tmofunc,
|
||||||
|
jiffies + HZ * LPFC_HB_MBOX_TIMEOUT);
|
||||||
|
phba->hb_outstanding = 1;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* If heart beat timeout called with hb_outstanding set we
|
||||||
|
* need to take the HBA offline.
|
||||||
|
*/
|
||||||
|
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||||
|
"%d:0459 Adapter heartbeat failure, taking "
|
||||||
|
"this port offline.\n", phba->brd_no);
|
||||||
|
|
||||||
|
spin_lock_irq(&phba->hbalock);
|
||||||
|
psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
|
||||||
|
spin_unlock_irq(&phba->hbalock);
|
||||||
|
|
||||||
|
lpfc_offline_prep(phba);
|
||||||
|
lpfc_offline(phba);
|
||||||
|
lpfc_unblock_mgmt_io(phba);
|
||||||
|
phba->link_state = LPFC_HBA_ERROR;
|
||||||
|
lpfc_hba_down_post(phba);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* lpfc_handle_eratt */
|
/* lpfc_handle_eratt */
|
||||||
|
@ -1190,9 +1306,6 @@ lpfc_cleanup(struct lpfc_vport *vport)
|
||||||
lpfc_can_disctmo(vport);
|
lpfc_can_disctmo(vport);
|
||||||
list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp)
|
list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp)
|
||||||
lpfc_nlp_put(ndlp);
|
lpfc_nlp_put(ndlp);
|
||||||
|
|
||||||
INIT_LIST_HEAD(&vport->fc_nodes);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1238,6 +1351,8 @@ lpfc_stop_phba_timers(struct lpfc_hba *phba)
|
||||||
lpfc_stop_vport_timers(vport);
|
lpfc_stop_vport_timers(vport);
|
||||||
del_timer_sync(&phba->sli.mbox_tmo);
|
del_timer_sync(&phba->sli.mbox_tmo);
|
||||||
del_timer_sync(&phba->fabric_block_timer);
|
del_timer_sync(&phba->fabric_block_timer);
|
||||||
|
phba->hb_outstanding = 0;
|
||||||
|
del_timer_sync(&phba->hb_tmofunc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1474,8 +1589,8 @@ destroy_port(struct lpfc_vport *vport)
|
||||||
struct lpfc_hba *phba = vport->phba;
|
struct lpfc_hba *phba = vport->phba;
|
||||||
|
|
||||||
kfree(vport->vname);
|
kfree(vport->vname);
|
||||||
lpfc_free_sysfs_attr(vport);
|
|
||||||
|
|
||||||
|
lpfc_debugfs_terminate(vport);
|
||||||
fc_remove_host(shost);
|
fc_remove_host(shost);
|
||||||
scsi_remove_host(shost);
|
scsi_remove_host(shost);
|
||||||
|
|
||||||
|
@ -1500,50 +1615,29 @@ lpfc_get_instance(void)
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
/*
|
||||||
lpfc_remove_device(struct lpfc_vport *vport)
|
* Note: there is no scan_start function as adapter initialization
|
||||||
{
|
* will have asynchronously kicked off the link initialization.
|
||||||
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
|
*/
|
||||||
|
|
||||||
lpfc_free_sysfs_attr(vport);
|
|
||||||
|
|
||||||
spin_lock_irq(shost->host_lock);
|
|
||||||
vport->fc_flag |= FC_UNLOADING;
|
|
||||||
spin_unlock_irq(shost->host_lock);
|
|
||||||
|
|
||||||
fc_remove_host(shost);
|
|
||||||
scsi_remove_host(shost);
|
|
||||||
}
|
|
||||||
|
|
||||||
void lpfc_scan_start(struct Scsi_Host *shost)
|
|
||||||
{
|
|
||||||
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
|
|
||||||
struct lpfc_hba *phba = vport->phba;
|
|
||||||
|
|
||||||
if (lpfc_sli_hba_setup(phba))
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* hba setup may have changed the hba_queue_depth so we need to adjust
|
|
||||||
* the value of can_queue.
|
|
||||||
*/
|
|
||||||
shost->can_queue = phba->cfg_hba_queue_depth - 10;
|
|
||||||
return;
|
|
||||||
|
|
||||||
error:
|
|
||||||
lpfc_remove_device(vport);
|
|
||||||
}
|
|
||||||
|
|
||||||
int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time)
|
int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time)
|
||||||
{
|
{
|
||||||
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
|
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
|
||||||
struct lpfc_hba *phba = vport->phba;
|
struct lpfc_hba *phba = vport->phba;
|
||||||
|
int stat = 0;
|
||||||
|
|
||||||
|
spin_lock_irq(shost->host_lock);
|
||||||
|
|
||||||
|
if (vport->fc_flag & FC_UNLOADING) {
|
||||||
|
stat = 1;
|
||||||
|
goto finished;
|
||||||
|
}
|
||||||
if (time >= 30 * HZ) {
|
if (time >= 30 * HZ) {
|
||||||
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
|
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
|
||||||
"%d:0461 Scanning longer than 30 "
|
"%d:0461 Scanning longer than 30 "
|
||||||
"seconds. Continuing initialization\n",
|
"seconds. Continuing initialization\n",
|
||||||
phba->brd_no);
|
phba->brd_no);
|
||||||
|
stat = 1;
|
||||||
goto finished;
|
goto finished;
|
||||||
}
|
}
|
||||||
if (time >= 15 * HZ && phba->link_state <= LPFC_LINK_DOWN) {
|
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)
|
||||||
"%d:0465 Link down longer than 15 "
|
"%d:0465 Link down longer than 15 "
|
||||||
"seconds. Continuing initialization\n",
|
"seconds. Continuing initialization\n",
|
||||||
phba->brd_no);
|
phba->brd_no);
|
||||||
|
stat = 1;
|
||||||
goto finished;
|
goto finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vport->port_state != LPFC_VPORT_READY)
|
if (vport->port_state != LPFC_VPORT_READY)
|
||||||
return 0;
|
goto finished;
|
||||||
if (vport->num_disc_nodes || vport->fc_prli_sent)
|
if (vport->num_disc_nodes || vport->fc_prli_sent)
|
||||||
return 0;
|
goto finished;
|
||||||
if (vport->fc_map_cnt == 0 && time < 2 * HZ)
|
if (vport->fc_map_cnt == 0 && time < 2 * HZ)
|
||||||
return 0;
|
goto finished;
|
||||||
if ((phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE) != 0)
|
if ((phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE) != 0)
|
||||||
return 0;
|
goto finished;
|
||||||
|
|
||||||
|
stat = 1;
|
||||||
|
|
||||||
finished:
|
finished:
|
||||||
lpfc_host_attrib_init(shost);
|
spin_unlock_irq(shost->host_lock);
|
||||||
return 1;
|
return stat;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lpfc_host_attrib_init(struct Scsi_Host *shost)
|
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)
|
||||||
/* Initialize timers used by driver */
|
/* Initialize timers used by driver */
|
||||||
init_timer(&phba->fc_estabtmo);
|
init_timer(&phba->fc_estabtmo);
|
||||||
phba->fc_estabtmo.function = lpfc_establish_link_tmo;
|
phba->fc_estabtmo.function = lpfc_establish_link_tmo;
|
||||||
phba->fc_estabtmo.data = (unsigned long) phba;
|
phba->fc_estabtmo.data = (unsigned long)phba;
|
||||||
|
|
||||||
|
init_timer(&phba->hb_tmofunc);
|
||||||
|
phba->hb_tmofunc.function = lpfc_hb_timeout;
|
||||||
|
phba->hb_tmofunc.data = (unsigned long)phba;
|
||||||
|
|
||||||
psli = &phba->sli;
|
psli = &phba->sli;
|
||||||
init_timer(&psli->mbox_tmo);
|
init_timer(&psli->mbox_tmo);
|
||||||
psli->mbox_tmo.function = lpfc_mbox_timeout;
|
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)
|
||||||
|
|
||||||
shost = lpfc_shost_from_vport(vport);
|
shost = lpfc_shost_from_vport(vport);
|
||||||
phba->pport = vport;
|
phba->pport = vport;
|
||||||
|
lpfc_debugfs_initialize(vport);
|
||||||
|
|
||||||
pci_set_drvdata(pdev, shost);
|
pci_set_drvdata(pdev, shost);
|
||||||
|
|
||||||
|
@ -1820,15 +1923,32 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
|
||||||
if (lpfc_alloc_sysfs_attr(vport))
|
if (lpfc_alloc_sysfs_attr(vport))
|
||||||
goto out_free_irq;
|
goto out_free_irq;
|
||||||
|
|
||||||
scsi_scan_host(shost);
|
if (lpfc_sli_hba_setup(phba))
|
||||||
|
goto out_remove_device;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* hba setup may have changed the hba_queue_depth so we need to adjust
|
||||||
|
* the value of can_queue.
|
||||||
|
*/
|
||||||
|
shost->can_queue = phba->cfg_hba_queue_depth - 10;
|
||||||
|
|
||||||
|
lpfc_host_attrib_init(shost);
|
||||||
|
|
||||||
if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
|
if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
|
||||||
spin_lock_irq(shost->host_lock);
|
spin_lock_irq(shost->host_lock);
|
||||||
lpfc_poll_start_timer(phba);
|
lpfc_poll_start_timer(phba);
|
||||||
spin_unlock_irq(shost->host_lock);
|
spin_unlock_irq(shost->host_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scsi_scan_host(shost);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
out_remove_device:
|
||||||
|
lpfc_free_sysfs_attr(vport);
|
||||||
|
spin_lock_irq(shost->host_lock);
|
||||||
|
vport->fc_flag |= FC_UNLOADING;
|
||||||
|
spin_unlock_irq(shost->host_lock);
|
||||||
out_free_irq:
|
out_free_irq:
|
||||||
lpfc_stop_phba_timers(phba);
|
lpfc_stop_phba_timers(phba);
|
||||||
phba->pport->work_port_events = 0;
|
phba->pport->work_port_events = 0;
|
||||||
|
@ -1865,6 +1985,8 @@ out_disable_device:
|
||||||
pci_disable_device(pdev);
|
pci_disable_device(pdev);
|
||||||
out:
|
out:
|
||||||
pci_set_drvdata(pdev, NULL);
|
pci_set_drvdata(pdev, NULL);
|
||||||
|
if (shost)
|
||||||
|
scsi_host_put(shost);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1878,6 +2000,12 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
|
||||||
list_for_each_entry(port_iterator, &phba->port_list, listentry)
|
list_for_each_entry(port_iterator, &phba->port_list, listentry)
|
||||||
port_iterator->load_flag |= FC_UNLOADING;
|
port_iterator->load_flag |= FC_UNLOADING;
|
||||||
|
|
||||||
|
kfree(vport->vname);
|
||||||
|
lpfc_free_sysfs_attr(vport);
|
||||||
|
|
||||||
|
fc_remove_host(shost);
|
||||||
|
scsi_remove_host(shost);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Bring down the SLI Layer. This step disable all interrupts,
|
* Bring down the SLI Layer. This step disable all interrupts,
|
||||||
* clears the rings, discards all mailbox commands, and resets
|
* clears the rings, discards all mailbox commands, and resets
|
||||||
|
@ -1887,6 +2015,13 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
|
||||||
lpfc_sli_brdrestart(phba);
|
lpfc_sli_brdrestart(phba);
|
||||||
|
|
||||||
lpfc_stop_phba_timers(phba);
|
lpfc_stop_phba_timers(phba);
|
||||||
|
spin_lock_irq(&phba->hbalock);
|
||||||
|
list_del_init(&vport->listentry);
|
||||||
|
spin_unlock_irq(&phba->hbalock);
|
||||||
|
|
||||||
|
|
||||||
|
lpfc_debugfs_terminate(vport);
|
||||||
|
lpfc_cleanup(vport);
|
||||||
|
|
||||||
kthread_stop(phba->worker_thread);
|
kthread_stop(phba->worker_thread);
|
||||||
|
|
||||||
|
@ -1894,9 +2029,8 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
|
||||||
free_irq(phba->pcidev->irq, phba);
|
free_irq(phba->pcidev->irq, phba);
|
||||||
pci_disable_msi(phba->pcidev);
|
pci_disable_msi(phba->pcidev);
|
||||||
|
|
||||||
destroy_port(vport);
|
|
||||||
|
|
||||||
pci_set_drvdata(pdev, NULL);
|
pci_set_drvdata(pdev, NULL);
|
||||||
|
scsi_host_put(shost);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Call scsi_free before mem_free since scsi bufs are released to their
|
* Call scsi_free before mem_free since scsi bufs are released to their
|
||||||
|
|
|
@ -81,6 +81,22 @@ lpfc_read_nv(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**********************************************/
|
||||||
|
/* lpfc_heart_beat Issue a HEART_BEAT */
|
||||||
|
/* mailbox command */
|
||||||
|
/**********************************************/
|
||||||
|
void
|
||||||
|
lpfc_heart_beat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
|
||||||
|
{
|
||||||
|
MAILBOX_t *mb;
|
||||||
|
|
||||||
|
mb = &pmb->mb;
|
||||||
|
memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
|
||||||
|
mb->mbxCommand = MBX_HEARTBEAT;
|
||||||
|
mb->mbxOwner = OWN_HOST;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/**********************************************/
|
/**********************************************/
|
||||||
/* lpfc_read_la Issue a READ LA */
|
/* lpfc_read_la Issue a READ LA */
|
||||||
/* mailbox command */
|
/* mailbox command */
|
||||||
|
@ -676,7 +692,7 @@ lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
|
||||||
if (phba->sli_rev == 3 && phba->vpd.sli3Feat.cerbm) {
|
if (phba->sli_rev == 3 && phba->vpd.sli3Feat.cerbm) {
|
||||||
mb->un.varCfgPort.cerbm = 1; /* Request HBQs */
|
mb->un.varCfgPort.cerbm = 1; /* Request HBQs */
|
||||||
mb->un.varCfgPort.max_hbq = 1; /* Requesting 2 HBQs */
|
mb->un.varCfgPort.max_hbq = 1; /* Requesting 2 HBQs */
|
||||||
if (phba->max_vpi && lpfc_npiv_enable &&
|
if (phba->max_vpi && phba->cfg_npiv_enable &&
|
||||||
phba->vpd.sli3Feat.cmv) {
|
phba->vpd.sli3Feat.cmv) {
|
||||||
mb->un.varCfgPort.max_vpi = phba->max_vpi;
|
mb->un.varCfgPort.max_vpi = phba->max_vpi;
|
||||||
mb->un.varCfgPort.cmv = 1;
|
mb->un.varCfgPort.cmv = 1;
|
||||||
|
|
|
@ -88,7 +88,8 @@ lpfc_mem_alloc(struct lpfc_hba * phba)
|
||||||
if (!phba->lpfc_hbq_pool)
|
if (!phba->lpfc_hbq_pool)
|
||||||
goto fail_free_nlp_mem_pool;
|
goto fail_free_nlp_mem_pool;
|
||||||
|
|
||||||
longs = (phba->max_vpi + BITS_PER_LONG - 1) / BITS_PER_LONG;
|
/* vpi zero is reserved for the physical port so add 1 to max */
|
||||||
|
longs = ((phba->max_vpi + 1) + BITS_PER_LONG - 1) / BITS_PER_LONG;
|
||||||
phba->vpi_bmask = kzalloc(longs * sizeof(unsigned long), GFP_KERNEL);
|
phba->vpi_bmask = kzalloc(longs * sizeof(unsigned long), GFP_KERNEL);
|
||||||
if (!phba->vpi_bmask)
|
if (!phba->vpi_bmask)
|
||||||
goto fail_free_hbq_pool;
|
goto fail_free_hbq_pool;
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include "lpfc_logmsg.h"
|
#include "lpfc_logmsg.h"
|
||||||
#include "lpfc_crtn.h"
|
#include "lpfc_crtn.h"
|
||||||
#include "lpfc_vport.h"
|
#include "lpfc_vport.h"
|
||||||
|
#include "lpfc_debugfs.h"
|
||||||
|
|
||||||
|
|
||||||
/* Called to verify a rcv'ed ADISC was intended for us. */
|
/* 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)
|
||||||
/* First check the txq */
|
/* First check the txq */
|
||||||
spin_lock_irq(&phba->hbalock);
|
spin_lock_irq(&phba->hbalock);
|
||||||
list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
|
list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
|
||||||
/* Check to see if iocb matches the nport we are looking
|
/* Check to see if iocb matches the nport we are looking for */
|
||||||
for */
|
|
||||||
if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) {
|
if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) {
|
||||||
/* It matches, so deque and call compl with an
|
/* It matches, so deque and call compl with anp error */
|
||||||
error */
|
|
||||||
list_move_tail(&iocb->list, &completions);
|
list_move_tail(&iocb->list, &completions);
|
||||||
pring->txq_cnt--;
|
pring->txq_cnt--;
|
||||||
}
|
}
|
||||||
|
@ -216,8 +215,7 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
|
||||||
|
|
||||||
/* Next check the txcmplq */
|
/* Next check the txcmplq */
|
||||||
list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) {
|
list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) {
|
||||||
/* Check to see if iocb matches the nport we are looking
|
/* Check to see if iocb matches the nport we are looking for */
|
||||||
for */
|
|
||||||
if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) {
|
if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) {
|
||||||
lpfc_sli_issue_abort_iotag(phba, pring, iocb);
|
lpfc_sli_issue_abort_iotag(phba, pring, iocb);
|
||||||
}
|
}
|
||||||
|
@ -282,7 +280,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||||
stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY;
|
stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY;
|
||||||
stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
|
stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
|
||||||
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb,
|
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb,
|
||||||
ndlp);
|
ndlp, NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -293,7 +291,8 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||||
/* Reject this request because invalid parameters */
|
/* Reject this request because invalid parameters */
|
||||||
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
|
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
|
||||||
stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
|
stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
|
||||||
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp);
|
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
|
||||||
|
NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
icmd = &cmdiocb->iocb;
|
icmd = &cmdiocb->iocb;
|
||||||
|
@ -392,13 +391,30 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||||
lpfc_els_abort(phba, ndlp);
|
lpfc_els_abort(phba, ndlp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((vport->port_type == LPFC_NPIV_PORT &&
|
||||||
|
phba->cfg_vport_restrict_login)) {
|
||||||
|
|
||||||
|
/* In order to preserve RPIs, we want to cleanup
|
||||||
|
* the default RPI the firmware created to rcv
|
||||||
|
* this ELS request. The only way to do this is
|
||||||
|
* to register, then unregister the RPI.
|
||||||
|
*/
|
||||||
|
spin_lock_irq(shost->host_lock);
|
||||||
|
ndlp->nlp_flag |= NLP_RM_DFLT_RPI;
|
||||||
|
spin_unlock_irq(shost->host_lock);
|
||||||
|
stat.un.b.lsRjtRsnCode = LSRJT_INVALID_CMD;
|
||||||
|
stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
|
||||||
|
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb,
|
||||||
|
ndlp, mbox);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox, 0);
|
lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox, 0);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
|
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
|
||||||
stat.un.b.lsRjtRsnCodeExp = LSEXP_OUT_OF_RESOURCE;
|
stat.un.b.lsRjtRsnCodeExp = LSEXP_OUT_OF_RESOURCE;
|
||||||
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp);
|
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -445,7 +461,7 @@ lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||||
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
|
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
|
||||||
stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
|
stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
|
||||||
stat.un.b.vendorUnique = 0;
|
stat.un.b.vendorUnique = 0;
|
||||||
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp);
|
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
|
||||||
|
|
||||||
/* 1 sec timeout */
|
/* 1 sec timeout */
|
||||||
mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
|
mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
|
||||||
|
@ -535,6 +551,11 @@ lpfc_rcv_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||||
roles |= FC_RPORT_ROLE_FCP_INITIATOR;
|
roles |= FC_RPORT_ROLE_FCP_INITIATOR;
|
||||||
if (ndlp->nlp_type & NLP_FCP_TARGET)
|
if (ndlp->nlp_type & NLP_FCP_TARGET)
|
||||||
roles |= FC_RPORT_ROLE_FCP_TARGET;
|
roles |= FC_RPORT_ROLE_FCP_TARGET;
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT,
|
||||||
|
"rport rolechg: role:x%x did:x%x flg:x%x",
|
||||||
|
roles, ndlp->nlp_DID, ndlp->nlp_flag);
|
||||||
|
|
||||||
fc_remote_port_rolechg(rport, roles);
|
fc_remote_port_rolechg(rport, roles);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -657,7 +678,8 @@ lpfc_rcv_plogi_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||||
ours */
|
ours */
|
||||||
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
|
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
|
||||||
stat.un.b.lsRjtRsnCodeExp = LSEXP_CMD_IN_PROGRESS;
|
stat.un.b.lsRjtRsnCodeExp = LSEXP_CMD_IN_PROGRESS;
|
||||||
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp);
|
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
|
||||||
|
NULL);
|
||||||
} else {
|
} else {
|
||||||
lpfc_rcv_plogi(vport, ndlp, cmdiocb);
|
lpfc_rcv_plogi(vport, ndlp, cmdiocb);
|
||||||
} /* If our portname was less */
|
} /* If our portname was less */
|
||||||
|
@ -675,7 +697,7 @@ lpfc_rcv_prli_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||||
memset(&stat, 0, sizeof (struct ls_rjt));
|
memset(&stat, 0, sizeof (struct ls_rjt));
|
||||||
stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY;
|
stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY;
|
||||||
stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
|
stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
|
||||||
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp);
|
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
|
||||||
return ndlp->nlp_state;
|
return ndlp->nlp_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1335,6 +1357,10 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||||
|
|
||||||
irsp = &rspiocb->iocb;
|
irsp = &rspiocb->iocb;
|
||||||
if (irsp->ulpStatus) {
|
if (irsp->ulpStatus) {
|
||||||
|
if ((vport->port_type == LPFC_NPIV_PORT) &&
|
||||||
|
phba->cfg_vport_restrict_login) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
|
ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
|
||||||
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
|
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
|
||||||
return ndlp->nlp_state;
|
return ndlp->nlp_state;
|
||||||
|
@ -1355,6 +1381,7 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||||
if (!(ndlp->nlp_type & NLP_FCP_TARGET) &&
|
if (!(ndlp->nlp_type & NLP_FCP_TARGET) &&
|
||||||
(vport->port_type == LPFC_NPIV_PORT) &&
|
(vport->port_type == LPFC_NPIV_PORT) &&
|
||||||
phba->cfg_vport_restrict_login) {
|
phba->cfg_vport_restrict_login) {
|
||||||
|
out:
|
||||||
spin_lock_irq(shost->host_lock);
|
spin_lock_irq(shost->host_lock);
|
||||||
ndlp->nlp_flag |= NLP_TARGET_REMOVE;
|
ndlp->nlp_flag |= NLP_TARGET_REMOVE;
|
||||||
spin_unlock_irq(shost->host_lock);
|
spin_unlock_irq(shost->host_lock);
|
||||||
|
@ -1606,7 +1633,7 @@ lpfc_rcv_plogi_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||||
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
|
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
|
||||||
|
|
||||||
/* Ignore PLOGI if we have an outstanding LOGO */
|
/* Ignore PLOGI if we have an outstanding LOGO */
|
||||||
if (ndlp->nlp_flag & NLP_LOGO_SND) {
|
if (ndlp->nlp_flag & (NLP_LOGO_SND | NLP_LOGO_ACC)) {
|
||||||
return ndlp->nlp_state;
|
return ndlp->nlp_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1638,7 +1665,7 @@ lpfc_rcv_prli_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||||
memset(&stat, 0, sizeof (struct ls_rjt));
|
memset(&stat, 0, sizeof (struct ls_rjt));
|
||||||
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
|
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
|
||||||
stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
|
stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
|
||||||
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp);
|
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
|
||||||
|
|
||||||
if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
|
if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
|
||||||
if (ndlp->nlp_flag & NLP_NPR_ADISC) {
|
if (ndlp->nlp_flag & NLP_NPR_ADISC) {
|
||||||
|
@ -2035,6 +2062,10 @@ lpfc_disc_state_machine(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||||
phba->brd_no, vport->vpi,
|
phba->brd_no, vport->vpi,
|
||||||
evt, ndlp->nlp_DID, cur_state, ndlp->nlp_flag);
|
evt, ndlp->nlp_DID, cur_state, ndlp->nlp_flag);
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM,
|
||||||
|
"DSM in: evt:%d ste:%d did:x%x",
|
||||||
|
evt, cur_state, ndlp->nlp_DID);
|
||||||
|
|
||||||
func = lpfc_disc_action[(cur_state * NLP_EVT_MAX_EVENT) + evt];
|
func = lpfc_disc_action[(cur_state * NLP_EVT_MAX_EVENT) + evt];
|
||||||
rc = (func) (vport, ndlp, arg, evt);
|
rc = (func) (vport, ndlp, arg, evt);
|
||||||
|
|
||||||
|
@ -2045,6 +2076,10 @@ lpfc_disc_state_machine(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
|
||||||
phba->brd_no, vport->vpi,
|
phba->brd_no, vport->vpi,
|
||||||
rc, ndlp->nlp_DID, ndlp->nlp_flag);
|
rc, ndlp->nlp_DID, ndlp->nlp_flag);
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM,
|
||||||
|
"DSM out: ste:%d did:x%x flg:x%x",
|
||||||
|
rc, ndlp->nlp_DID, ndlp->nlp_flag);
|
||||||
|
|
||||||
lpfc_nlp_put(ndlp);
|
lpfc_nlp_put(ndlp);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -1532,7 +1532,6 @@ struct scsi_host_template lpfc_template = {
|
||||||
.slave_configure = lpfc_slave_configure,
|
.slave_configure = lpfc_slave_configure,
|
||||||
.slave_destroy = lpfc_slave_destroy,
|
.slave_destroy = lpfc_slave_destroy,
|
||||||
.scan_finished = lpfc_scan_finished,
|
.scan_finished = lpfc_scan_finished,
|
||||||
.scan_start = lpfc_scan_start,
|
|
||||||
.this_id = -1,
|
.this_id = -1,
|
||||||
.sg_tablesize = LPFC_SG_SEG_CNT,
|
.sg_tablesize = LPFC_SG_SEG_CNT,
|
||||||
.cmd_per_lun = LPFC_CMD_PER_LUN,
|
.cmd_per_lun = LPFC_CMD_PER_LUN,
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include "lpfc_crtn.h"
|
#include "lpfc_crtn.h"
|
||||||
#include "lpfc_logmsg.h"
|
#include "lpfc_logmsg.h"
|
||||||
#include "lpfc_compat.h"
|
#include "lpfc_compat.h"
|
||||||
|
#include "lpfc_debugfs.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define macro to log: Mailbox command x%x cannot issue Data
|
* 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,
|
||||||
static struct lpfc_iocbq *
|
static struct lpfc_iocbq *
|
||||||
lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
|
lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
|
||||||
{
|
{
|
||||||
struct list_head *dlp;
|
|
||||||
struct lpfc_iocbq *cmd_iocb;
|
struct lpfc_iocbq *cmd_iocb;
|
||||||
|
|
||||||
dlp = &pring->txq;
|
list_remove_head((&pring->txq), cmd_iocb, struct lpfc_iocbq, list);
|
||||||
cmd_iocb = NULL;
|
if (cmd_iocb != NULL)
|
||||||
list_remove_head((&pring->txq), cmd_iocb,
|
|
||||||
struct lpfc_iocbq,
|
|
||||||
list);
|
|
||||||
if (cmd_iocb) {
|
|
||||||
/* If the first ptr is not equal to the list header,
|
|
||||||
* deque the IOCBQ_t and return it.
|
|
||||||
*/
|
|
||||||
pring->txq_cnt--;
|
pring->txq_cnt--;
|
||||||
}
|
|
||||||
return cmd_iocb;
|
return cmd_iocb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -736,6 +728,7 @@ lpfc_sli_chk_mbx_command(uint8_t mbxCommand)
|
||||||
case MBX_LOAD_EXP_ROM:
|
case MBX_LOAD_EXP_ROM:
|
||||||
case MBX_REG_VPI:
|
case MBX_REG_VPI:
|
||||||
case MBX_UNREG_VPI:
|
case MBX_UNREG_VPI:
|
||||||
|
case MBX_HEARTBEAT:
|
||||||
ret = mbxCommand;
|
ret = mbxCommand;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -748,15 +741,18 @@ static void
|
||||||
lpfc_sli_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
|
lpfc_sli_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
|
||||||
{
|
{
|
||||||
wait_queue_head_t *pdone_q;
|
wait_queue_head_t *pdone_q;
|
||||||
|
unsigned long drvr_flag;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If pdone_q is empty, the driver thread gave up waiting and
|
* If pdone_q is empty, the driver thread gave up waiting and
|
||||||
* continued running.
|
* continued running.
|
||||||
*/
|
*/
|
||||||
pmboxq->mbox_flag |= LPFC_MBX_WAKE;
|
pmboxq->mbox_flag |= LPFC_MBX_WAKE;
|
||||||
|
spin_lock_irqsave(&phba->hbalock, drvr_flag);
|
||||||
pdone_q = (wait_queue_head_t *) pmboxq->context1;
|
pdone_q = (wait_queue_head_t *) pmboxq->context1;
|
||||||
if (pdone_q)
|
if (pdone_q)
|
||||||
wake_up_interruptible(pdone_q);
|
wake_up_interruptible(pdone_q);
|
||||||
|
spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -817,6 +813,25 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba)
|
||||||
|
|
||||||
pmbox = &pmb->mb;
|
pmbox = &pmb->mb;
|
||||||
|
|
||||||
|
if (pmbox->mbxCommand != MBX_HEARTBEAT) {
|
||||||
|
if (pmb->vport) {
|
||||||
|
lpfc_debugfs_disc_trc(pmb->vport,
|
||||||
|
LPFC_DISC_TRC_MBOX_VPORT,
|
||||||
|
"MBOX cmpl vport: cmd:x%x mb:x%x x%x",
|
||||||
|
(uint32_t)pmbox->mbxCommand,
|
||||||
|
pmbox->un.varWords[0],
|
||||||
|
pmbox->un.varWords[1]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lpfc_debugfs_disc_trc(phba->pport,
|
||||||
|
LPFC_DISC_TRC_MBOX,
|
||||||
|
"MBOX cmpl: cmd:x%x mb:x%x x%x",
|
||||||
|
(uint32_t)pmbox->mbxCommand,
|
||||||
|
pmbox->un.varWords[0],
|
||||||
|
pmbox->un.varWords[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* It is a fatal error if unknown mbox command completion.
|
* It is a fatal error if unknown mbox command completion.
|
||||||
*/
|
*/
|
||||||
|
@ -1309,6 +1324,7 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba,
|
||||||
* network byte order and pci byte orders are different.
|
* network byte order and pci byte orders are different.
|
||||||
*/
|
*/
|
||||||
entry = lpfc_resp_iocb(phba, pring);
|
entry = lpfc_resp_iocb(phba, pring);
|
||||||
|
phba->last_completion_time = jiffies;
|
||||||
|
|
||||||
if (++pring->rspidx >= portRspMax)
|
if (++pring->rspidx >= portRspMax)
|
||||||
pring->rspidx = 0;
|
pring->rspidx = 0;
|
||||||
|
@ -1511,6 +1527,7 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba,
|
||||||
*/
|
*/
|
||||||
entry = lpfc_resp_iocb(phba, pring);
|
entry = lpfc_resp_iocb(phba, pring);
|
||||||
|
|
||||||
|
phba->last_completion_time = jiffies;
|
||||||
rspiocbp = __lpfc_sli_get_iocbq(phba);
|
rspiocbp = __lpfc_sli_get_iocbq(phba);
|
||||||
if (rspiocbp == NULL) {
|
if (rspiocbp == NULL) {
|
||||||
printk(KERN_ERR "%s: out of buffers! Failing "
|
printk(KERN_ERR "%s: out of buffers! Failing "
|
||||||
|
@ -2304,7 +2321,7 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba)
|
||||||
|
|
||||||
switch (lpfc_sli_mode) {
|
switch (lpfc_sli_mode) {
|
||||||
case 2:
|
case 2:
|
||||||
if (lpfc_npiv_enable) {
|
if (phba->cfg_npiv_enable) {
|
||||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT,
|
lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT,
|
||||||
"%d:1824 NPIV enabled: Override lpfc_sli_mode "
|
"%d:1824 NPIV enabled: Override lpfc_sli_mode "
|
||||||
"parameter (%d) to auto (0).\n",
|
"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)
|
||||||
psli->slistat.mbox_busy++;
|
psli->slistat.mbox_busy++;
|
||||||
spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
|
spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
|
||||||
|
|
||||||
|
if (pmbox->vport) {
|
||||||
|
lpfc_debugfs_disc_trc(pmbox->vport,
|
||||||
|
LPFC_DISC_TRC_MBOX_VPORT,
|
||||||
|
"MBOX Bsy vport: cmd:x%x mb:x%x x%x",
|
||||||
|
(uint32_t)mb->mbxCommand,
|
||||||
|
mb->un.varWords[0], mb->un.varWords[1]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lpfc_debugfs_disc_trc(phba->pport,
|
||||||
|
LPFC_DISC_TRC_MBOX,
|
||||||
|
"MBOX Bsy: cmd:x%x mb:x%x x%x",
|
||||||
|
(uint32_t)mb->mbxCommand,
|
||||||
|
mb->un.varWords[0], mb->un.varWords[1]);
|
||||||
|
}
|
||||||
|
|
||||||
return MBX_BUSY;
|
return MBX_BUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2618,6 +2650,23 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
|
||||||
mb->mbxCommand, phba->pport->port_state,
|
mb->mbxCommand, phba->pport->port_state,
|
||||||
psli->sli_flag, flag);
|
psli->sli_flag, flag);
|
||||||
|
|
||||||
|
if (mb->mbxCommand != MBX_HEARTBEAT) {
|
||||||
|
if (pmbox->vport) {
|
||||||
|
lpfc_debugfs_disc_trc(pmbox->vport,
|
||||||
|
LPFC_DISC_TRC_MBOX_VPORT,
|
||||||
|
"MBOX Send vport: cmd:x%x mb:x%x x%x",
|
||||||
|
(uint32_t)mb->mbxCommand,
|
||||||
|
mb->un.varWords[0], mb->un.varWords[1]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lpfc_debugfs_disc_trc(phba->pport,
|
||||||
|
LPFC_DISC_TRC_MBOX,
|
||||||
|
"MBOX Send: cmd:x%x mb:x%x x%x",
|
||||||
|
(uint32_t)mb->mbxCommand,
|
||||||
|
mb->un.varWords[0], mb->un.varWords[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
psli->slistat.mbox_cmd++;
|
psli->slistat.mbox_cmd++;
|
||||||
evtctr = psli->slistat.mbox_event;
|
evtctr = psli->slistat.mbox_event;
|
||||||
|
|
||||||
|
@ -2760,14 +2809,13 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag)
|
||||||
/*
|
/*
|
||||||
* Caller needs to hold lock.
|
* Caller needs to hold lock.
|
||||||
*/
|
*/
|
||||||
static int
|
static void
|
||||||
__lpfc_sli_ringtx_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
__lpfc_sli_ringtx_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
||||||
struct lpfc_iocbq *piocb)
|
struct lpfc_iocbq *piocb)
|
||||||
{
|
{
|
||||||
/* Insert the caller's iocb in the txq tail for later processing. */
|
/* Insert the caller's iocb in the txq tail for later processing. */
|
||||||
list_add_tail(&piocb->list, &pring->txq);
|
list_add_tail(&piocb->list, &pring->txq);
|
||||||
pring->txq_cnt++;
|
pring->txq_cnt++;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct lpfc_iocbq *
|
static struct lpfc_iocbq *
|
||||||
|
@ -3074,11 +3122,11 @@ lpfc_sli_queue_setup(struct lpfc_hba *phba)
|
||||||
int
|
int
|
||||||
lpfc_sli_host_down(struct lpfc_vport *vport)
|
lpfc_sli_host_down(struct lpfc_vport *vport)
|
||||||
{
|
{
|
||||||
|
LIST_HEAD(completions);
|
||||||
struct lpfc_hba *phba = vport->phba;
|
struct lpfc_hba *phba = vport->phba;
|
||||||
struct lpfc_sli *psli = &phba->sli;
|
struct lpfc_sli *psli = &phba->sli;
|
||||||
struct lpfc_sli_ring *pring;
|
struct lpfc_sli_ring *pring;
|
||||||
struct lpfc_iocbq *iocb, *next_iocb;
|
struct lpfc_iocbq *iocb, *next_iocb;
|
||||||
IOCB_t *icmd = NULL;
|
|
||||||
int i;
|
int i;
|
||||||
unsigned long flags = 0;
|
unsigned long flags = 0;
|
||||||
uint16_t prev_pring_flag;
|
uint16_t prev_pring_flag;
|
||||||
|
@ -3086,31 +3134,20 @@ lpfc_sli_host_down(struct lpfc_vport *vport)
|
||||||
lpfc_cleanup_discovery_resources(vport);
|
lpfc_cleanup_discovery_resources(vport);
|
||||||
|
|
||||||
spin_lock_irqsave(&phba->hbalock, flags);
|
spin_lock_irqsave(&phba->hbalock, flags);
|
||||||
|
|
||||||
for (i = 0; i < psli->num_rings; i++) {
|
for (i = 0; i < psli->num_rings; i++) {
|
||||||
pring = &psli->ring[i];
|
pring = &psli->ring[i];
|
||||||
prev_pring_flag = pring->flag;
|
prev_pring_flag = pring->flag;
|
||||||
pring->flag |= LPFC_DEFERRED_RING_EVENT;
|
if (pring->ringno == LPFC_ELS_RING) /* Only slow rings */
|
||||||
|
pring->flag |= LPFC_DEFERRED_RING_EVENT;
|
||||||
/*
|
/*
|
||||||
* Error everything on the txq since these iocbs have not been
|
* Error everything on the txq since these iocbs have not been
|
||||||
* given to the FW yet.
|
* given to the FW yet.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
|
list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
|
||||||
if (iocb->vport != vport)
|
if (iocb->vport != vport)
|
||||||
continue;
|
continue;
|
||||||
list_del_init(&iocb->list);
|
list_move_tail(&iocb->list, &completions);
|
||||||
pring->txq_cnt--;
|
pring->txq_cnt--;
|
||||||
if (iocb->iocb_cmpl) {
|
|
||||||
icmd = &iocb->iocb;
|
|
||||||
icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
|
|
||||||
icmd->un.ulpWord[4] = IOERR_SLI_DOWN;
|
|
||||||
spin_unlock_irqrestore(&phba->hbalock, flags);
|
|
||||||
(iocb->iocb_cmpl) (phba, iocb, iocb);
|
|
||||||
spin_lock_irqsave(&phba->hbalock, flags);
|
|
||||||
} else
|
|
||||||
lpfc_sli_release_iocbq(phba, iocb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Next issue ABTS for everything on the txcmplq */
|
/* Next issue ABTS for everything on the txcmplq */
|
||||||
|
@ -3126,6 +3163,17 @@ lpfc_sli_host_down(struct lpfc_vport *vport)
|
||||||
|
|
||||||
spin_unlock_irqrestore(&phba->hbalock, flags);
|
spin_unlock_irqrestore(&phba->hbalock, flags);
|
||||||
|
|
||||||
|
while (!list_empty(&completions)) {
|
||||||
|
list_remove_head(&completions, iocb, struct lpfc_iocbq, list);
|
||||||
|
|
||||||
|
if (!iocb->iocb_cmpl)
|
||||||
|
lpfc_sli_release_iocbq(phba, iocb);
|
||||||
|
else {
|
||||||
|
iocb->iocb.ulpStatus = IOSTAT_LOCAL_REJECT;
|
||||||
|
iocb->iocb.un.ulpWord[4] = IOERR_SLI_DOWN;
|
||||||
|
(iocb->iocb_cmpl) (phba, iocb, iocb);
|
||||||
|
}
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3148,7 +3196,8 @@ lpfc_sli_hba_down(struct lpfc_hba *phba)
|
||||||
spin_lock_irqsave(&phba->hbalock, flags);
|
spin_lock_irqsave(&phba->hbalock, flags);
|
||||||
for (i = 0; i < psli->num_rings; i++) {
|
for (i = 0; i < psli->num_rings; i++) {
|
||||||
pring = &psli->ring[i];
|
pring = &psli->ring[i];
|
||||||
pring->flag |= LPFC_DEFERRED_RING_EVENT;
|
if (pring->ringno == LPFC_ELS_RING) /* Only slow rings */
|
||||||
|
pring->flag |= LPFC_DEFERRED_RING_EVENT;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Error everything on the txq since these iocbs have not been
|
* 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,
|
||||||
"x%x x%x x%x\n",
|
"x%x x%x x%x\n",
|
||||||
phba->brd_no, irsp->ulpIoTag, irsp->ulpStatus,
|
phba->brd_no, irsp->ulpIoTag, irsp->ulpStatus,
|
||||||
irsp->un.ulpWord[4], irsp->ulpTimeout);
|
irsp->un.ulpWord[4], irsp->ulpTimeout);
|
||||||
|
if (cmdiocb->iocb.ulpCommand == CMD_GEN_REQUEST64_CR)
|
||||||
lpfc_els_free_iocb(phba, cmdiocb);
|
lpfc_ct_free_iocb(phba, cmdiocb);
|
||||||
|
else
|
||||||
|
lpfc_els_free_iocb(phba, cmdiocb);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3352,10 +3403,11 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
||||||
(cmdiocb->iocb_flag & LPFC_DRIVER_ABORTED) != 0)
|
(cmdiocb->iocb_flag & LPFC_DRIVER_ABORTED) != 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* If we're unloading, don't abort the iocb, but change the callback so
|
/* If we're unloading, don't abort iocb on the ELS ring, but change the
|
||||||
* that nothing happens when it finishes.
|
* callback so that nothing happens when it finishes.
|
||||||
*/
|
*/
|
||||||
if (vport->load_flag & FC_UNLOADING) {
|
if ((vport->load_flag & FC_UNLOADING) &&
|
||||||
|
(pring->ringno == LPFC_ELS_RING)) {
|
||||||
if (cmdiocb->iocb_flag & LPFC_IO_FABRIC)
|
if (cmdiocb->iocb_flag & LPFC_IO_FABRIC)
|
||||||
cmdiocb->fabric_iocb_cmpl = lpfc_ignore_els_cmpl;
|
cmdiocb->fabric_iocb_cmpl = lpfc_ignore_els_cmpl;
|
||||||
else
|
else
|
||||||
|
@ -3540,9 +3592,9 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba,
|
||||||
&rspiocbq->iocb, sizeof(IOCB_t));
|
&rspiocbq->iocb, sizeof(IOCB_t));
|
||||||
|
|
||||||
pdone_q = cmdiocbq->context_un.wait_queue;
|
pdone_q = cmdiocbq->context_un.wait_queue;
|
||||||
spin_unlock_irqrestore(&phba->hbalock, iflags);
|
|
||||||
if (pdone_q)
|
if (pdone_q)
|
||||||
wake_up(pdone_q);
|
wake_up(pdone_q);
|
||||||
|
spin_unlock_irqrestore(&phba->hbalock, iflags);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3638,6 +3690,7 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq,
|
||||||
{
|
{
|
||||||
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_q);
|
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_q);
|
||||||
int retval;
|
int retval;
|
||||||
|
unsigned long flag;
|
||||||
|
|
||||||
/* The caller must leave context1 empty. */
|
/* The caller must leave context1 empty. */
|
||||||
if (pmboxq->context1 != 0)
|
if (pmboxq->context1 != 0)
|
||||||
|
@ -3656,6 +3709,7 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq,
|
||||||
pmboxq->mbox_flag & LPFC_MBX_WAKE,
|
pmboxq->mbox_flag & LPFC_MBX_WAKE,
|
||||||
timeout * HZ);
|
timeout * HZ);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&phba->hbalock, flag);
|
||||||
pmboxq->context1 = NULL;
|
pmboxq->context1 = NULL;
|
||||||
/*
|
/*
|
||||||
* if LPFC_MBX_WAKE flag is set the mailbox is completed
|
* 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,
|
||||||
*/
|
*/
|
||||||
if (pmboxq->mbox_flag & LPFC_MBX_WAKE)
|
if (pmboxq->mbox_flag & LPFC_MBX_WAKE)
|
||||||
retval = MBX_SUCCESS;
|
retval = MBX_SUCCESS;
|
||||||
else
|
else {
|
||||||
retval = MBX_TIMEOUT;
|
retval = MBX_TIMEOUT;
|
||||||
|
pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&phba->hbalock, flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -3712,6 +3769,9 @@ lpfc_intr_handler(int irq, void *dev_id)
|
||||||
uint32_t control;
|
uint32_t control;
|
||||||
|
|
||||||
MAILBOX_t *mbox, *pmbox;
|
MAILBOX_t *mbox, *pmbox;
|
||||||
|
struct lpfc_vport *vport;
|
||||||
|
struct lpfc_nodelist *ndlp;
|
||||||
|
struct lpfc_dmabuf *mp;
|
||||||
LPFC_MBOXQ_t *pmb;
|
LPFC_MBOXQ_t *pmb;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
@ -3780,18 +3840,23 @@ lpfc_intr_handler(int irq, void *dev_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (work_ha_copy & ~(HA_ERATT|HA_MBATT|HA_LATT)) {
|
if (work_ha_copy & ~(HA_ERATT|HA_MBATT|HA_LATT)) {
|
||||||
for (i = 0; i < phba->sli.num_rings; i++) {
|
/*
|
||||||
if (work_ha_copy & (HA_RXATT << (4*i))) {
|
* Turn off Slow Rings interrupts, LPFC_ELS_RING is
|
||||||
/*
|
* the only slow ring.
|
||||||
* Turn off Slow Rings interrupts
|
*/
|
||||||
*/
|
status = (work_ha_copy &
|
||||||
spin_lock(&phba->hbalock);
|
(HA_RXMASK << (4*LPFC_ELS_RING)));
|
||||||
control = readl(phba->HCregaddr);
|
status >>= (4*LPFC_ELS_RING);
|
||||||
control &= ~(HC_R0INT_ENA << i);
|
if (status & HA_RXMASK) {
|
||||||
|
spin_lock(&phba->hbalock);
|
||||||
|
control = readl(phba->HCregaddr);
|
||||||
|
if (control & (HC_R0INT_ENA << LPFC_ELS_RING)) {
|
||||||
|
control &=
|
||||||
|
~(HC_R0INT_ENA << LPFC_ELS_RING);
|
||||||
writel(control, phba->HCregaddr);
|
writel(control, phba->HCregaddr);
|
||||||
readl(phba->HCregaddr); /* flush */
|
readl(phba->HCregaddr); /* flush */
|
||||||
spin_unlock(&phba->hbalock);
|
|
||||||
}
|
}
|
||||||
|
spin_unlock(&phba->hbalock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3819,6 +3884,7 @@ lpfc_intr_handler(int irq, void *dev_id)
|
||||||
pmb = phba->sli.mbox_active;
|
pmb = phba->sli.mbox_active;
|
||||||
pmbox = &pmb->mb;
|
pmbox = &pmb->mb;
|
||||||
mbox = &phba->slim2p->mbx;
|
mbox = &phba->slim2p->mbx;
|
||||||
|
vport = pmb->vport;
|
||||||
|
|
||||||
/* First check out the status word */
|
/* First check out the status word */
|
||||||
lpfc_sli_pcimem_bcopy(mbox, pmbox, sizeof(uint32_t));
|
lpfc_sli_pcimem_bcopy(mbox, pmbox, sizeof(uint32_t));
|
||||||
|
@ -3833,22 +3899,54 @@ lpfc_intr_handler(int irq, void *dev_id)
|
||||||
"Interrupt mbxCommand x%x "
|
"Interrupt mbxCommand x%x "
|
||||||
"mbxStatus x%x\n",
|
"mbxStatus x%x\n",
|
||||||
phba->brd_no,
|
phba->brd_no,
|
||||||
(pmb->vport
|
(vport
|
||||||
? pmb->vport->vpi
|
? vport->vpi : 0),
|
||||||
: 0),
|
|
||||||
pmbox->mbxCommand,
|
pmbox->mbxCommand,
|
||||||
pmbox->mbxStatus);
|
pmbox->mbxStatus);
|
||||||
}
|
}
|
||||||
|
phba->last_completion_time = jiffies;
|
||||||
del_timer_sync(&phba->sli.mbox_tmo);
|
del_timer_sync(&phba->sli.mbox_tmo);
|
||||||
|
|
||||||
spin_lock(&phba->pport->work_port_lock);
|
|
||||||
phba->pport->work_port_events &= ~WORKER_MBOX_TMO;
|
|
||||||
spin_unlock(&phba->pport->work_port_lock);
|
|
||||||
phba->sli.mbox_active = NULL;
|
phba->sli.mbox_active = NULL;
|
||||||
if (pmb->mbox_cmpl) {
|
if (pmb->mbox_cmpl) {
|
||||||
lpfc_sli_pcimem_bcopy(mbox, pmbox,
|
lpfc_sli_pcimem_bcopy(mbox, pmbox,
|
||||||
MAILBOX_CMD_SIZE);
|
MAILBOX_CMD_SIZE);
|
||||||
}
|
}
|
||||||
|
if (pmb->mbox_flag & LPFC_MBX_IMED_UNREG) {
|
||||||
|
pmb->mbox_flag &= ~LPFC_MBX_IMED_UNREG;
|
||||||
|
|
||||||
|
lpfc_debugfs_disc_trc(vport,
|
||||||
|
LPFC_DISC_TRC_MBOX_VPORT,
|
||||||
|
"MBOX dflt rpi: : status:x%x rpi:x%x",
|
||||||
|
(uint32_t)pmbox->mbxStatus,
|
||||||
|
pmbox->un.varWords[0], 0);
|
||||||
|
|
||||||
|
if ( !pmbox->mbxStatus) {
|
||||||
|
mp = (struct lpfc_dmabuf *)
|
||||||
|
(pmb->context1);
|
||||||
|
ndlp = (struct lpfc_nodelist *)
|
||||||
|
pmb->context2;
|
||||||
|
|
||||||
|
/* Reg_LOGIN of dflt RPI was successful.
|
||||||
|
* new lets get rid of the RPI using the
|
||||||
|
* same mbox buffer.
|
||||||
|
*/
|
||||||
|
lpfc_unreg_login(phba, vport->vpi,
|
||||||
|
pmbox->un.varWords[0], pmb);
|
||||||
|
pmb->mbox_cmpl = lpfc_mbx_cmpl_dflt_rpi;
|
||||||
|
pmb->context1 = mp;
|
||||||
|
pmb->context2 = ndlp;
|
||||||
|
pmb->vport = vport;
|
||||||
|
spin_lock(&phba->hbalock);
|
||||||
|
phba->sli.sli_flag &=
|
||||||
|
~LPFC_SLI_MBOX_ACTIVE;
|
||||||
|
spin_unlock(&phba->hbalock);
|
||||||
|
goto send_current_mbox;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spin_lock(&phba->pport->work_port_lock);
|
||||||
|
phba->pport->work_port_events &= ~WORKER_MBOX_TMO;
|
||||||
|
spin_unlock(&phba->pport->work_port_lock);
|
||||||
lpfc_mbox_cmpl_put(phba, pmb);
|
lpfc_mbox_cmpl_put(phba, pmb);
|
||||||
}
|
}
|
||||||
if ((work_ha_copy & HA_MBATT) &&
|
if ((work_ha_copy & HA_MBATT) &&
|
||||||
|
@ -3858,7 +3956,7 @@ send_next_mbox:
|
||||||
phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
|
phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
|
||||||
pmb = lpfc_mbox_get(phba);
|
pmb = lpfc_mbox_get(phba);
|
||||||
spin_unlock(&phba->hbalock);
|
spin_unlock(&phba->hbalock);
|
||||||
|
send_current_mbox:
|
||||||
/* Process next mailbox command if there is one */
|
/* Process next mailbox command if there is one */
|
||||||
if (pmb != NULL) {
|
if (pmb != NULL) {
|
||||||
rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
|
rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
|
||||||
|
@ -3891,7 +3989,7 @@ send_next_mbox:
|
||||||
*/
|
*/
|
||||||
status = (ha_copy & (HA_RXMASK << (4*LPFC_FCP_RING)));
|
status = (ha_copy & (HA_RXMASK << (4*LPFC_FCP_RING)));
|
||||||
status >>= (4*LPFC_FCP_RING);
|
status >>= (4*LPFC_FCP_RING);
|
||||||
if (status & HA_RXATT)
|
if (status & HA_RXMASK)
|
||||||
lpfc_sli_handle_fast_ring_event(phba,
|
lpfc_sli_handle_fast_ring_event(phba,
|
||||||
&phba->sli.ring[LPFC_FCP_RING],
|
&phba->sli.ring[LPFC_FCP_RING],
|
||||||
status);
|
status);
|
||||||
|
@ -3904,7 +4002,7 @@ send_next_mbox:
|
||||||
*/
|
*/
|
||||||
status = (ha_copy & (HA_RXMASK << (4*LPFC_EXTRA_RING)));
|
status = (ha_copy & (HA_RXMASK << (4*LPFC_EXTRA_RING)));
|
||||||
status >>= (4*LPFC_EXTRA_RING);
|
status >>= (4*LPFC_EXTRA_RING);
|
||||||
if (status & HA_RXATT) {
|
if (status & HA_RXMASK) {
|
||||||
lpfc_sli_handle_fast_ring_event(phba,
|
lpfc_sli_handle_fast_ring_event(phba,
|
||||||
&phba->sli.ring[LPFC_EXTRA_RING],
|
&phba->sli.ring[LPFC_EXTRA_RING],
|
||||||
status);
|
status);
|
||||||
|
|
|
@ -73,7 +73,8 @@ struct lpfc_iocbq {
|
||||||
#define IOCB_ERROR 2
|
#define IOCB_ERROR 2
|
||||||
#define IOCB_TIMEDOUT 3
|
#define IOCB_TIMEDOUT 3
|
||||||
|
|
||||||
#define LPFC_MBX_WAKE 1
|
#define LPFC_MBX_WAKE 1
|
||||||
|
#define LPFC_MBX_IMED_UNREG 2
|
||||||
|
|
||||||
typedef struct lpfcMboxq {
|
typedef struct lpfcMboxq {
|
||||||
/* MBOXQs are used in single linked lists */
|
/* MBOXQs are used in single linked lists */
|
||||||
|
|
|
@ -82,7 +82,8 @@ lpfc_alloc_vpi(struct lpfc_hba *phba)
|
||||||
int vpi;
|
int vpi;
|
||||||
|
|
||||||
spin_lock_irq(&phba->hbalock);
|
spin_lock_irq(&phba->hbalock);
|
||||||
vpi = find_next_zero_bit(phba->vpi_bmask, phba->max_vpi, 1);
|
/* Start at bit 1 because vpi zero is reserved for the physical port */
|
||||||
|
vpi = find_next_zero_bit(phba->vpi_bmask, (phba->max_vpi + 1), 1);
|
||||||
if (vpi > phba->max_vpi)
|
if (vpi > phba->max_vpi)
|
||||||
vpi = 0;
|
vpi = 0;
|
||||||
else
|
else
|
||||||
|
@ -131,7 +132,8 @@ lpfc_vport_sparm(struct lpfc_hba *phba, struct lpfc_vport *vport)
|
||||||
mb->mbxCommand, mb->mbxStatus, rc);
|
mb->mbxCommand, mb->mbxStatus, rc);
|
||||||
lpfc_mbuf_free(phba, mp->virt, mp->phys);
|
lpfc_mbuf_free(phba, mp->virt, mp->phys);
|
||||||
kfree(mp);
|
kfree(mp);
|
||||||
mempool_free(pmb, phba->mbox_mem_pool);
|
if (rc != MBX_TIMEOUT)
|
||||||
|
mempool_free(pmb, phba->mbox_mem_pool);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,6 +243,8 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable)
|
||||||
}
|
}
|
||||||
|
|
||||||
vport->vpi = vpi;
|
vport->vpi = vpi;
|
||||||
|
lpfc_debugfs_initialize(vport);
|
||||||
|
|
||||||
if (lpfc_vport_sparm(phba, vport)) {
|
if (lpfc_vport_sparm(phba, vport)) {
|
||||||
lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
|
lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
|
||||||
"%d:1813 Create VPORT failed: vpi:%d "
|
"%d:1813 Create VPORT failed: vpi:%d "
|
||||||
|
@ -306,8 +310,16 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable)
|
||||||
*/
|
*/
|
||||||
ndlp = lpfc_findnode_did(phba->pport, Fabric_DID);
|
ndlp = lpfc_findnode_did(phba->pport, Fabric_DID);
|
||||||
if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
|
if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
|
||||||
lpfc_set_disctmo(vport);
|
if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) {
|
||||||
lpfc_initial_fdisc(vport);
|
lpfc_set_disctmo(vport);
|
||||||
|
lpfc_initial_fdisc(vport);
|
||||||
|
} else {
|
||||||
|
lpfc_vport_set_state(vport, FC_VPORT_NO_FABRIC_SUPP);
|
||||||
|
lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
|
||||||
|
"%d (%d):0262 No NPIV Fabric "
|
||||||
|
"support\n",
|
||||||
|
phba->brd_no, vport->vpi);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
|
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
|
||||||
}
|
}
|
||||||
|
@ -383,8 +395,16 @@ enable_vport(struct fc_vport *fc_vport)
|
||||||
*/
|
*/
|
||||||
ndlp = lpfc_findnode_did(phba->pport, Fabric_DID);
|
ndlp = lpfc_findnode_did(phba->pport, Fabric_DID);
|
||||||
if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
|
if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
|
||||||
lpfc_set_disctmo(vport);
|
if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) {
|
||||||
lpfc_initial_fdisc(vport);
|
lpfc_set_disctmo(vport);
|
||||||
|
lpfc_initial_fdisc(vport);
|
||||||
|
} else {
|
||||||
|
lpfc_vport_set_state(vport, FC_VPORT_NO_FABRIC_SUPP);
|
||||||
|
lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
|
||||||
|
"%d (%d):0264 No NPIV Fabric "
|
||||||
|
"support\n",
|
||||||
|
phba->brd_no, vport->vpi);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
|
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
|
||||||
}
|
}
|
||||||
|
@ -441,6 +461,7 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
|
||||||
vport->load_flag |= FC_UNLOADING;
|
vport->load_flag |= FC_UNLOADING;
|
||||||
|
|
||||||
kfree(vport->vname);
|
kfree(vport->vname);
|
||||||
|
lpfc_debugfs_terminate(vport);
|
||||||
fc_remove_host(lpfc_shost_from_vport(vport));
|
fc_remove_host(lpfc_shost_from_vport(vport));
|
||||||
scsi_remove_host(lpfc_shost_from_vport(vport));
|
scsi_remove_host(lpfc_shost_from_vport(vport));
|
||||||
|
|
||||||
|
@ -476,12 +497,6 @@ skip_logo:
|
||||||
NLP_EVT_DEVICE_RM);
|
NLP_EVT_DEVICE_RM);
|
||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
|
|
||||||
/* free any ndlp's in unused state */
|
|
||||||
if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
|
|
||||||
lpfc_drop_node(vport, ndlp);
|
|
||||||
}
|
|
||||||
|
|
||||||
lpfc_stop_vport_timers(vport);
|
lpfc_stop_vport_timers(vport);
|
||||||
lpfc_unreg_all_rpis(vport);
|
lpfc_unreg_all_rpis(vport);
|
||||||
lpfc_unreg_default_rpis(vport);
|
lpfc_unreg_default_rpis(vport);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче