Commit a3b4924b authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi

Pull more SCSI updates from James Bottomley:
 "This is the set of stuff that didn't quite make the initial pull and a
  set of fixes for stuff which did.

  The new stuff is basically lpfc (nvme), qedi and aacraid. The fixes
  cover a lot of previously submitted stuff, the most important of which
  probably covers some of the failing irq vectors allocation and other
  fallout from having the SCSI command allocated as part of the block
  allocation functions"

* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (59 commits)
  scsi: qedi: Fix memory leak in tmf response processing.
  scsi: aacraid: remove redundant zero check on ret
  scsi: lpfc: use proper format string for dma_addr_t
  scsi: lpfc: use div_u64 for 64-bit division
  scsi: mac_scsi: Fix MAC_SCSI=m option when SCSI=m
  scsi: cciss: correct check map error.
  scsi: qla2xxx: fix spelling mistake: "seperator" -> "separator"
  scsi: aacraid: Fixed expander hotplug for SMART family
  scsi: mpt3sas: switch to pci_alloc_irq_vectors
  scsi: qedf: fixup compilation warning about atomic_t usage
  scsi: remove scsi_execute_req_flags
  scsi: merge __scsi_execute into scsi_execute
  scsi: simplify scsi_execute_req_flags
  scsi: make the sense header argument to scsi_test_unit_ready mandatory
  scsi: sd: improve TUR handling in sd_check_events
  scsi: always zero sshdr in scsi_normalize_sense
  scsi: scsi_dh_emc: return success in clariion_std_inquiry()
  scsi: fix memory leak of sdpk on when gd fails to allocate
  scsi: sd: make sd_devt_release() static
  scsi: qedf: Add QLogic FastLinQ offload FCoE driver framework.
  ...
parents 0b94da8d 42a70abd
......@@ -555,10 +555,9 @@ static void send_mode_select(struct work_struct *work)
(char *) h->ctlr->array_name, h->ctlr->index,
(retry_cnt == RDAC_RETRY_COUNT) ? "queueing" : "retrying");
if (scsi_execute_req_flags(sdev, cdb, DMA_TO_DEVICE,
&h->ctlr->mode_select, data_size, &sshdr,
RDAC_TIMEOUT * HZ,
RDAC_RETRIES, NULL, req_flags, 0)) {
if (scsi_execute(sdev, cdb, DMA_TO_DEVICE, &h->ctlr->mode_select,
data_size, NULL, &sshdr, RDAC_TIMEOUT * HZ,
RDAC_RETRIES, req_flags, 0, NULL)) {
err = mode_select_handle_sense(sdev, &sshdr);
if (err == SCSI_DH_RETRY && retry_cnt--)
goto retry;
......
#/*******************************************************************
# * This file is part of the Emulex Linux Device Driver for *
# * Fibre Channel Host Bus Adapters. *
# * Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
# * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
# * Copyright (C) 2004-2012 Emulex. All rights reserved. *
# * EMULEX and SLI are trademarks of Emulex. *
# * www.emulex.com *
# * www.broadcom.com *
# * *
# * This program is free software; you can redistribute it and/or *
# * modify it under the terms of version 2 of the GNU General *
......@@ -28,6 +30,7 @@ endif
obj-$(CONFIG_SCSI_LPFC) := lpfc.o
lpfc-objs := lpfc_mem.o lpfc_sli.o lpfc_ct.o lpfc_els.o lpfc_hbadisc.o \
lpfc_init.o lpfc_mbox.o lpfc_nportdisc.o lpfc_scsi.o lpfc_attr.o \
lpfc_vport.o lpfc_debugfs.o lpfc_bsg.o
lpfc-objs := lpfc_mem.o lpfc_sli.o lpfc_ct.o lpfc_els.o \
lpfc_hbadisc.o lpfc_init.o lpfc_mbox.o lpfc_nportdisc.o \
lpfc_scsi.o lpfc_attr.o lpfc_vport.o lpfc_debugfs.o lpfc_bsg.o \
lpfc_nvme.o lpfc_nvmet.o
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* www.broadcom.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
* *
* This program is free software; you can redistribute it and/or *
......@@ -20,6 +22,7 @@
*******************************************************************/
#include <scsi/scsi_host.h>
#include <linux/ktime.h>
#if defined(CONFIG_DEBUG_FS) && !defined(CONFIG_SCSI_LPFC_DEBUG_FS)
#define CONFIG_SCSI_LPFC_DEBUG_FS
......@@ -53,6 +56,7 @@ struct lpfc_sli2_slim;
#define LPFC_MAX_SG_SEG_CNT 4096 /* sg element count per scsi cmnd */
#define LPFC_MAX_SGL_SEG_CNT 512 /* SGL element count per scsi cmnd */
#define LPFC_MAX_BPL_SEG_CNT 4096 /* BPL element count per scsi cmnd */
#define LPFC_MIN_NVME_SEG_CNT 254
#define LPFC_MAX_SGE_SIZE 0x80000000 /* Maximum data allowed in a SGE */
#define LPFC_IOCB_LIST_CNT 2250 /* list of IOCBs for fast-path usage. */
......@@ -114,6 +118,20 @@ enum lpfc_polling_flags {
DISABLE_FCP_RING_INT = 0x2
};
struct perf_prof {
uint16_t cmd_cpu[40];
uint16_t rsp_cpu[40];
uint16_t qh_cpu[40];
uint16_t wqidx[40];
};
/*
* Provide for FC4 TYPE x28 - NVME. The
* bit mask for FCP and NVME is 0x8 identically
* because they are 32 bit positions distance.
*/
#define LPFC_FC4_TYPE_BITMASK 0x00000100
/* Provide DMA memory definitions the driver uses per port instance. */
struct lpfc_dmabuf {
struct list_head list;
......@@ -131,10 +149,24 @@ struct lpfc_dma_pool {
struct hbq_dmabuf {
struct lpfc_dmabuf hbuf;
struct lpfc_dmabuf dbuf;
uint32_t size;
uint16_t total_size;
uint16_t bytes_recv;
uint32_t tag;
struct lpfc_cq_event cq_event;
unsigned long time_stamp;
void *context;
};
struct rqb_dmabuf {
struct lpfc_dmabuf hbuf;
struct lpfc_dmabuf dbuf;
uint16_t total_size;
uint16_t bytes_recv;
void *context;
struct lpfc_iocbq *iocbq;
struct lpfc_sglq *sglq;
struct lpfc_queue *hrq; /* ptr to associated Header RQ */
struct lpfc_queue *drq; /* ptr to associated Data RQ */
};
/* Priority bit. Set value to exceed low water mark in lpfc_mem. */
......@@ -367,7 +399,8 @@ struct lpfc_vport {
int32_t stopped; /* HBA has not been restarted since last ERATT */
uint8_t fc_linkspeed; /* Link speed after last READ_LA */
uint32_t num_disc_nodes; /*in addition to hba_state */
uint32_t num_disc_nodes; /* in addition to hba_state */
uint32_t gidft_inp; /* cnt of outstanding GID_FTs */
uint32_t fc_nlp_cnt; /* outstanding NODELIST requests */
uint32_t fc_rscn_id_cnt; /* count of RSCNs payloads in list */
......@@ -420,7 +453,6 @@ struct lpfc_vport {
uint32_t cfg_max_scsicmpl_time;
uint32_t cfg_tgt_queue_depth;
uint32_t cfg_first_burst_size;
uint32_t dev_loss_tmo_changed;
struct fc_vport *fc_vport;
......@@ -428,6 +460,9 @@ struct lpfc_vport {
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
struct dentry *debug_disc_trc;
struct dentry *debug_nodelist;
struct dentry *debug_nvmestat;
struct dentry *debug_nvmektime;
struct dentry *debug_cpucheck;
struct dentry *vport_debugfs_root;
struct lpfc_debugfs_trc *disc_trc;
atomic_t disc_trc_cnt;
......@@ -442,6 +477,11 @@ struct lpfc_vport {
uint16_t fdmi_num_disc;
uint32_t fdmi_hba_mask;
uint32_t fdmi_port_mask;
/* There is a single nvme instance per vport. */
struct nvme_fc_local_port *localport;
uint8_t nvmei_support; /* driver supports NVME Initiator */
uint32_t last_fcp_wqidx;
};
struct hbq_s {
......@@ -459,10 +499,9 @@ struct hbq_s {
struct hbq_dmabuf *);
};
#define LPFC_MAX_HBQS 4
/* this matches the position in the lpfc_hbq_defs array */
#define LPFC_ELS_HBQ 0
#define LPFC_EXTRA_HBQ 1
#define LPFC_MAX_HBQS 1
enum hba_temp_state {
HBA_NORMAL_TEMP,
......@@ -652,6 +691,8 @@ struct lpfc_hba {
* Firmware supports Forced Link Speed
* capability
*/
#define HBA_NVME_IOQ_FLUSH 0x80000 /* NVME IO queues flushed. */
uint32_t fcp_ring_in_use; /* When polling test if intr-hndlr active*/
struct lpfc_dmabuf slim2p;
......@@ -700,6 +741,9 @@ struct lpfc_hba {
uint8_t wwpn[8];
uint32_t RandomData[7];
uint8_t fcp_embed_io;
uint8_t nvme_support; /* Firmware supports NVME */
uint8_t nvmet_support; /* driver supports NVMET */
#define LPFC_NVMET_MAX_PORTS 32
uint8_t mds_diags_support;
/* HBA Config Parameters */
......@@ -725,6 +769,14 @@ struct lpfc_hba {
uint32_t cfg_fcp_imax;
uint32_t cfg_fcp_cpu_map;
uint32_t cfg_fcp_io_channel;
uint32_t cfg_suppress_rsp;
uint32_t cfg_nvme_oas;
uint32_t cfg_nvme_io_channel;
uint32_t cfg_nvmet_mrq;
uint32_t cfg_nvmet_mrq_post;
uint32_t cfg_enable_nvmet;
uint32_t cfg_nvme_enable_fb;
uint32_t cfg_nvmet_fb_size;
uint32_t cfg_total_seg_cnt;
uint32_t cfg_sg_seg_cnt;
uint32_t cfg_sg_dma_buf_size;
......@@ -770,6 +822,13 @@ struct lpfc_hba {
#define LPFC_FDMI_SUPPORT 1 /* FDMI supported? */
uint32_t cfg_enable_SmartSAN;
uint32_t cfg_enable_mds_diags;
uint32_t cfg_enable_fc4_type;
uint32_t cfg_xri_split;
#define LPFC_ENABLE_FCP 1
#define LPFC_ENABLE_NVME 2
#define LPFC_ENABLE_BOTH 3
uint32_t io_channel_irqs; /* number of irqs for io channels */
struct nvmet_fc_target_port *targetport;
lpfc_vpd_t vpd; /* vital product data */
struct pci_dev *pcidev;
......@@ -784,11 +843,11 @@ struct lpfc_hba {
unsigned long data_flags;
uint32_t hbq_in_use; /* HBQs in use flag */
struct list_head rb_pend_list; /* Received buffers to be processed */
uint32_t hbq_count; /* Count of configured HBQs */
struct hbq_s hbqs[LPFC_MAX_HBQS]; /* local copy of hbq indicies */
atomic_t fcp_qidx; /* next work queue to post work to */
atomic_t fcp_qidx; /* next FCP WQ (RR Policy) */
atomic_t nvme_qidx; /* next NVME WQ (RR Policy) */
phys_addr_t pci_bar0_map; /* Physical address for PCI BAR0 */
phys_addr_t pci_bar1_map; /* Physical address for PCI BAR1 */
......@@ -843,9 +902,17 @@ struct lpfc_hba {
/*
* stat counters
*/
uint64_t fc4InputRequests;
uint64_t fc4OutputRequests;
uint64_t fc4ControlRequests;
uint64_t fc4ScsiInputRequests;
uint64_t fc4ScsiOutputRequests;
uint64_t fc4ScsiControlRequests;
uint64_t fc4ScsiIoCmpls;
uint64_t fc4NvmeInputRequests;
uint64_t fc4NvmeOutputRequests;
uint64_t fc4NvmeControlRequests;
uint64_t fc4NvmeIoCmpls;
uint64_t fc4NvmeLsRequests;
uint64_t fc4NvmeLsCmpls;
uint64_t bg_guard_err_cnt;
uint64_t bg_apptag_err_cnt;
uint64_t bg_reftag_err_cnt;
......@@ -856,17 +923,23 @@ struct lpfc_hba {
struct list_head lpfc_scsi_buf_list_get;
struct list_head lpfc_scsi_buf_list_put;
uint32_t total_scsi_bufs;
spinlock_t nvme_buf_list_get_lock; /* NVME buf alloc list lock */
spinlock_t nvme_buf_list_put_lock; /* NVME buf free list lock */
struct list_head lpfc_nvme_buf_list_get;
struct list_head lpfc_nvme_buf_list_put;
uint32_t total_nvme_bufs;
struct list_head lpfc_iocb_list;
uint32_t total_iocbq_bufs;
struct list_head active_rrq_list;
spinlock_t hbalock;
/* pci_mem_pools */
struct pci_pool *lpfc_scsi_dma_buf_pool;
struct pci_pool *lpfc_sg_dma_buf_pool;
struct pci_pool *lpfc_mbuf_pool;
struct pci_pool *lpfc_hrb_pool; /* header receive buffer pool */
struct pci_pool *lpfc_drb_pool; /* data receive buffer pool */
struct pci_pool *lpfc_hbq_pool; /* SLI3 hbq buffer pool */
struct pci_pool *txrdy_payload_pool;
struct lpfc_dma_pool lpfc_mbuf_safety_pool;
mempool_t *mbox_mem_pool;
......@@ -878,8 +951,6 @@ struct lpfc_hba {
enum intr_type_t intr_type;
uint32_t intr_mode;
#define LPFC_INTR_ERROR 0xFFFFFFFF
struct msix_entry msix_entries[LPFC_MSIX_VECTORS];
struct list_head port_list;
struct lpfc_vport *pport; /* physical lpfc_vport pointer */
uint16_t max_vpi; /* Maximum virtual nports */
......@@ -925,6 +996,12 @@ struct lpfc_hba {
struct dentry *debug_readApp; /* inject read app_tag errors */
struct dentry *debug_readRef; /* inject read ref_tag errors */
struct dentry *debug_nvmeio_trc;
struct lpfc_debugfs_nvmeio_trc *nvmeio_trc;
atomic_t nvmeio_trc_cnt;
uint32_t nvmeio_trc_size;
uint32_t nvmeio_trc_output_idx;
/* T10 DIF error injection */
uint32_t lpfc_injerr_wgrd_cnt;
uint32_t lpfc_injerr_wapp_cnt;
......@@ -950,7 +1027,9 @@ struct lpfc_hba {
struct dentry *idiag_ctl_acc;
struct dentry *idiag_mbx_acc;
struct dentry *idiag_ext_acc;
uint8_t lpfc_idiag_last_eq;
#endif
uint16_t nvmeio_trc_on;
/* Used for deferred freeing of ELS data buffers */
struct list_head elsbuf;
......@@ -1023,6 +1102,53 @@ struct lpfc_hba {
#define LPFC_TRANSGRESSION_LOW_RXPOWER 0x4000
uint16_t sfp_alarm;
uint16_t sfp_warning;
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
#define LPFC_CHECK_CPU_CNT 32
uint32_t cpucheck_rcv_io[LPFC_CHECK_CPU_CNT];
uint32_t cpucheck_xmt_io[LPFC_CHECK_CPU_CNT];
uint32_t cpucheck_cmpl_io[LPFC_CHECK_CPU_CNT];
uint32_t cpucheck_ccmpl_io[LPFC_CHECK_CPU_CNT];
uint16_t cpucheck_on;
#define LPFC_CHECK_OFF 0
#define LPFC_CHECK_NVME_IO 1
#define LPFC_CHECK_NVMET_RCV 2
#define LPFC_CHECK_NVMET_IO 4
uint16_t ktime_on;
uint64_t ktime_data_samples;
uint64_t ktime_status_samples;
uint64_t ktime_last_cmd;
uint64_t ktime_seg1_total;
uint64_t ktime_seg1_min;
uint64_t ktime_seg1_max;
uint64_t ktime_seg2_total;
uint64_t ktime_seg2_min;
uint64_t ktime_seg2_max;
uint64_t ktime_seg3_total;
uint64_t ktime_seg3_min;
uint64_t ktime_seg3_max;
uint64_t ktime_seg4_total;
uint64_t ktime_seg4_min;
uint64_t ktime_seg4_max;
uint64_t ktime_seg5_total;
uint64_t ktime_seg5_min;
uint64_t ktime_seg5_max;
uint64_t ktime_seg6_total;
uint64_t ktime_seg6_min;
uint64_t ktime_seg6_max;
uint64_t ktime_seg7_total;
uint64_t ktime_seg7_min;
uint64_t ktime_seg7_max;
uint64_t ktime_seg8_total;
uint64_t ktime_seg8_min;
uint64_t ktime_seg8_max;
uint64_t ktime_seg9_total;
uint64_t ktime_seg9_min;
uint64_t ktime_seg9_max;
uint64_t ktime_seg10_total;
uint64_t ktime_seg10_min;
uint64_t ktime_seg10_max;
#endif
};
static inline struct Scsi_Host *
......@@ -1093,3 +1219,11 @@ lpfc_sli_read_hs(struct lpfc_hba *phba)
return 0;
}
static inline struct lpfc_sli_ring *
lpfc_phba_elsring(struct lpfc_hba *phba)
{
if (phba->sli_rev == LPFC_SLI_REV4)
return phba->sli4_hba.els_wq->pring;
return &phba->sli.sli3_ring[LPFC_ELS_RING];
}
This diff is collapsed.
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* www.broadcom.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
* *
* This program is free software; you can redistribute it and/or *
......
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
* Copyright (C) 2009-2015 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* www.broadcom.com *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of version 2 of the GNU General *
......@@ -1704,6 +1706,7 @@ lpfc_bsg_diag_mode_enter(struct lpfc_hba *phba)
struct lpfc_vport **vports;
struct Scsi_Host *shost;
struct lpfc_sli *psli;
struct lpfc_queue *qp = NULL;
struct lpfc_sli_ring *pring;
int i = 0;
......@@ -1711,9 +1714,6 @@ lpfc_bsg_diag_mode_enter(struct lpfc_hba *phba)
if (!psli)
return -ENODEV;
pring = &psli->ring[LPFC_FCP_RING];
if (!pring)
return -ENODEV;
if ((phba->link_state == LPFC_HBA_ERROR) ||
(psli->sli_flag & LPFC_BLOCK_MGMT_IO) ||
......@@ -1732,10 +1732,18 @@ lpfc_bsg_diag_mode_enter(struct lpfc_hba *phba)
scsi_block_requests(shost);
}
while (!list_empty(&pring->txcmplq)) {
if (i++ > 500) /* wait up to 5 seconds */
if (phba->sli_rev != LPFC_SLI_REV4) {
pring = &psli->sli3_ring[LPFC_FCP_RING];
lpfc_emptyq_wait(phba, &pring->txcmplq, &phba->hbalock);
return 0;
}
list_for_each_entry(qp, &phba->sli4_hba.lpfc_wq_list, wq_list) {
pring = qp->pring;
if (!pring || (pring->ringno != LPFC_FCP_RING))
continue;
if (!lpfc_emptyq_wait(phba, &pring->txcmplq,
&pring->ring_lock))
break;
msleep(10);
}
return 0;
}
......@@ -2703,7 +2711,7 @@ static int lpfcdiag_loop_get_xri(struct lpfc_hba *phba, uint16_t rpi,
* lpfc_bsg_dma_page_alloc - allocate a bsg mbox page sized dma buffers
* @phba: Pointer to HBA context object
*
* This function allocates BSG_MBOX_SIZE (4KB) page size dma buffer and.
* This function allocates BSG_MBOX_SIZE (4KB) page size dma buffer and
* returns the pointer to the buffer.
**/
static struct lpfc_dmabuf *
......@@ -2875,8 +2883,7 @@ diag_cmd_data_alloc(struct lpfc_hba *phba,
static int lpfcdiag_loop_post_rxbufs(struct lpfc_hba *phba, uint16_t rxxri,
size_t len)
{
struct lpfc_sli *psli = &phba->sli;
struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
struct lpfc_sli_ring *pring;
struct lpfc_iocbq *cmdiocbq;
IOCB_t *cmd = NULL;
struct list_head head, *curr, *next;
......@@ -2890,6 +2897,8 @@ static int lpfcdiag_loop_post_rxbufs(struct lpfc_hba *phba, uint16_t rxxri,
int iocb_stat;
int i = 0;
pring = lpfc_phba_elsring(phba);
cmdiocbq = lpfc_sli_get_iocbq(phba);
rxbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
if (rxbmp != NULL) {
......@@ -5403,13 +5412,15 @@ lpfc_bsg_timeout(struct bsg_job *job)
struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job));
struct lpfc_hba *phba = vport->phba;
struct lpfc_iocbq *cmdiocb;
struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
struct lpfc_sli_ring *pring;
struct bsg_job_data *dd_data;
unsigned long flags;
int rc = 0;
LIST_HEAD(completions);
struct lpfc_iocbq *check_iocb, *next_iocb;
pring = lpfc_phba_elsring(phba);
/* if job's driver data is NULL, the command completed or is in the
* the process of completing. In this case, return status to request
* so the timeout is retried. This avoids double completion issues
......
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2010-2015 Emulex. All rights reserved. *
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
* Copyright (C) 2010-2015 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* www.broadcom.com *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of version 2 of the GNU General *
......
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
* Copyright (C) 2004-2011 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* www.broadcom.com *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of version 2 of the GNU General *
......
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* www.broadcom.com *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of version 2 of the GNU General *
......@@ -21,6 +23,7 @@
typedef int (*node_filter)(struct lpfc_nodelist *, void *);
struct fc_rport;
struct fc_frame_header;
void lpfc_down_link(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_sli_read_link_ste(struct lpfc_hba *);
void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t, uint16_t);
......@@ -167,6 +170,8 @@ void lpfc_hb_timeout_handler(struct lpfc_hba *);
void lpfc_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *,
struct lpfc_iocbq *);
int lpfc_ct_handle_unsol_abort(struct lpfc_hba *, struct hbq_dmabuf *);
int lpfc_issue_gidft(struct lpfc_vport *vport);
int lpfc_get_gidft_type(struct lpfc_vport *vport, struct lpfc_iocbq *iocbq);
int lpfc_ns_cmd(struct lpfc_vport *, int, uint8_t, uint32_t);
int lpfc_fdmi_cmd(struct lpfc_vport *, struct lpfc_nodelist *, int, uint32_t);
void lpfc_fdmi_num_disc_check(struct lpfc_vport *);
......@@ -186,6 +191,8 @@ void lpfc_unblock_mgmt_io(struct lpfc_hba *);
void lpfc_offline_prep(struct lpfc_hba *, int);
void lpfc_offline(struct lpfc_hba *);
void lpfc_reset_hba(struct lpfc_hba *);
int lpfc_emptyq_wait(struct lpfc_hba *phba, struct list_head *hd,
spinlock_t *slock);
int lpfc_fof_queue_create(struct lpfc_hba *);
int lpfc_fof_queue_setup(struct lpfc_hba *);
......@@ -193,7 +200,11 @@ int lpfc_fof_queue_destroy(struct lpfc_hba *);
irqreturn_t lpfc_sli4_fof_intr_handler(int, void *);
int lpfc_sli_setup(struct lpfc_hba *);
int lpfc_sli_queue_setup(struct lpfc_hba *);
int lpfc_sli4_setup(struct lpfc_hba *phba);
void lpfc_sli_queue_init(struct lpfc_hba *phba);
void lpfc_sli4_queue_init(struct lpfc_hba *phba);
struct lpfc_sli_ring *lpfc_sli4_calc_ring(struct lpfc_hba *phba,
struct lpfc_iocbq *iocbq);
void lpfc_handle_eratt(struct lpfc_hba *);
void lpfc_handle_latt(struct lpfc_hba *);
......@@ -220,6 +231,7 @@ void lpfc_reg_vfi(struct lpfcMboxq *, struct lpfc_vport *, dma_addr_t);
void lpfc_init_vpi(struct lpfc_hba *, struct lpfcMboxq *, uint16_t);
void lpfc_unreg_vfi(struct lpfcMboxq *, struct lpfc_vport *);
void lpfc_reg_fcfi(struct lpfc_hba *, struct lpfcMboxq *);
void lpfc_reg_fcfi_mrq(struct lpfc_hba *phba, struct lpfcMboxq *mbox, int mode);
void lpfc_unreg_fcfi(struct lpfcMboxq *, uint16_t);
void lpfc_resume_rpi(struct lpfcMboxq *, struct lpfc_nodelist *);
int lpfc_check_pending_fcoe_event(struct lpfc_hba *, uint8_t);
......@@ -231,8 +243,15 @@ struct hbq_dmabuf *lpfc_els_hbq_alloc(struct lpfc_hba *);
void lpfc_els_hbq_free(struct lpfc_hba *, struct hbq_dmabuf *);
struct hbq_dmabuf *lpfc_sli4_rb_alloc(struct lpfc_hba *);
void lpfc_sli4_rb_free(struct lpfc_hba *, struct hbq_dmabuf *);
struct rqb_dmabuf *lpfc_sli4_nvmet_alloc(struct lpfc_hba *phba);
void lpfc_sli4_nvmet_free(struct lpfc_hba *phba, struct rqb_dmabuf *dmab);
void lpfc_sli4_build_dflt_fcf_record(struct lpfc_hba *, struct fcf_record *,
uint16_t);
int lpfc_sli4_rq_put(struct lpfc_queue *hq, struct lpfc_queue *dq,
struct lpfc_rqe *hrqe, struct lpfc_rqe *drqe);
int lpfc_post_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *hq,
struct lpfc_queue *dq, int count);
int lpfc_free_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *hq);
void lpfc_unregister_fcf(struct lpfc_hba *);
void lpfc_unregister_fcf_rescan(struct lpfc_hba *);
void lpfc_unregister_unused_fcf(struct lpfc_hba *);
......@@ -287,6 +306,11 @@ void lpfc_sli_def_mbox_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_sli4_unreg_rpi_cmpl_clr(struct lpfc_hba *, LPFC_MBOXQ_t *);
int lpfc_sli_issue_iocb(struct lpfc_hba *, uint32_t,
struct lpfc_iocbq *, uint32_t);
int lpfc_sli4_issue_wqe(struct lpfc_hba *phba, uint32_t rnum,
struct lpfc_iocbq *iocbq);
struct lpfc_sglq *__lpfc_clear_active_sglq(struct lpfc_hba *phba, uint16_t xri);
struct lpfc_sglq *__lpfc_sli_get_nvmet_sglq(struct lpfc_hba *phba,
struct lpfc_iocbq *piocbq);
void lpfc_sli_pcimem_bcopy(void *, void *, uint32_t);
void lpfc_sli_bemem_bcopy(void *, void *, uint32_t);
void lpfc_sli_abort_iocb_ring(struct lpfc_hba *, struct lpfc_sli_ring *);
......@@ -336,8 +360,13 @@ void lpfc_sli_free_hbq(struct lpfc_hba *, struct hbq_dmabuf *);
void *lpfc_mbuf_alloc(struct lpfc_hba *, int, dma_addr_t *);
void __lpfc_mbuf_free(struct lpfc_hba *, void *, dma_addr_t);
void lpfc_mbuf_free(struct lpfc_hba *, void *, dma_addr_t);
void *lpfc_nvmet_buf_alloc(struct lpfc_hba *phba, int flags,
dma_addr_t *handle);
void lpfc_nvmet_buf_free(struct lpfc_hba *phba, void *virtp, dma_addr_t dma);
void lpfc_in_buf_free(struct lpfc_hba *, struct lpfc_dmabuf *);
void lpfc_rq_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp);
/* Function prototypes. */
const char* lpfc_info(struct Scsi_Host *);
int lpfc_scan_finished(struct Scsi_Host *, unsigned long);
......@@ -356,6 +385,7 @@ extern struct device_attribute *lpfc_hba_attrs[];
extern struct device_attribute *lpfc_vport_attrs[];
extern struct scsi_host_template lpfc_template;
extern struct scsi_host_template lpfc_template_s3;
extern struct scsi_host_template lpfc_template_nvme;
extern struct scsi_host_template lpfc_vport_template;
extern struct fc_function_template lpfc_transport_functions;
extern struct fc_function_template lpfc_vport_transport_functions;
......@@ -375,9 +405,11 @@ 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);
uint32_t, uint32_t);
extern void lpfc_debugfs_slow_ring_trc(struct lpfc_hba *, char *, uint32_t,
uint32_t, uint32_t);
uint32_t, uint32_t);
extern void lpfc_debugfs_nvme_trc(struct lpfc_hba *phba, char *fmt,
uint16_t data1, uint16_t data2, uint32_t data3);
extern struct lpfc_hbq_init *lpfc_hbq_defs[];
/* SLI4 if_type 2 externs. */
......@@ -471,7 +503,10 @@ int lpfc_issue_unreg_vfi(struct lpfc_vport *);
int lpfc_selective_reset(struct lpfc_hba *);
int lpfc_sli4_read_config(struct lpfc_hba *);
void lpfc_sli4_node_prep(struct lpfc_hba *);
int lpfc_sli4_xri_sgl_update(struct lpfc_hba *);
int lpfc_sli4_els_sgl_update(struct lpfc_hba *phba);
int lpfc_sli4_nvmet_sgl_update(struct lpfc_hba *phba);
int lpfc_sli4_scsi_sgl_update(struct lpfc_hba *phba);
int lpfc_sli4_nvme_sgl_update(struct lpfc_hba *phba);
void lpfc_free_sgl_list(struct lpfc_hba *, struct list_head *);
uint32_t lpfc_sli_port_speed_get(struct lpfc_hba *);
int lpfc_sli4_request_firmware_update(struct lpfc_hba *, uint8_t);
......@@ -496,3 +531,26 @@ bool lpfc_find_next_oas_lun(struct lpfc_hba *, struct lpfc_name *,
uint32_t *, uint32_t *);
int lpfc_sli4_dump_page_a0(struct lpfc_hba *phba, struct lpfcMboxq *mbox);
void lpfc_mbx_cmpl_rdp_page_a0(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb);
/* NVME interfaces. */
void lpfc_nvme_unregister_port(struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp);
int lpfc_nvme_register_port(struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp);
int lpfc_nvme_create_localport(struct lpfc_vport *vport);
void lpfc_nvme_destroy_localport(struct lpfc_vport *vport);
void lpfc_nvme_update_localport(struct lpfc_vport *vport);
int lpfc_nvmet_create_targetport(struct lpfc_hba *phba);
int lpfc_nvmet_update_targetport(struct lpfc_hba *phba);
void lpfc_nvmet_destroy_targetport(struct lpfc_hba *phba);
void lpfc_nvmet_unsol_ls_event(struct lpfc_hba *phba,
struct lpfc_sli_ring *pring, struct lpfc_iocbq *piocb);
void lpfc_nvmet_unsol_fcp_event(struct lpfc_hba *phba,
struct lpfc_sli_ring *pring,
struct rqb_dmabuf *nvmebuf, uint64_t isr_ts);
void lpfc_nvme_mod_param_dep(struct lpfc_hba *phba);
void lpfc_nvme_abort_fcreq_cmpl(struct lpfc_hba *phba,
struct lpfc_iocbq *cmdiocb,
struct lpfc_wcqe_complete *abts_cmpl);
extern int lpfc_enable_nvmet_cnt;
extern unsigned long long lpfc_enable_nvmet[];
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* www.broadcom.com *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of version 2 of the GNU General *
......@@ -40,8 +42,9 @@
#include "lpfc_sli4.h"
#include "lpfc_nl.h"
#include "lpfc_disc.h"
#include "lpfc_scsi.h"
#include "lpfc.h"
#include "lpfc_scsi.h"
#include "lpfc_nvme.h"
#include "lpfc_logmsg.h"
#include "lpfc_crtn.h"
#include "lpfc_version.h"
......@@ -453,8 +456,90 @@ lpfc_find_vport_by_did(struct lpfc_hba *phba, uint32_t did) {
return NULL;
}
static void
lpfc_prep_node_fc4type(struct lpfc_vport *vport, uint32_t Did, uint8_t fc4_type)
{
struct lpfc_nodelist *ndlp;
if ((vport->port_type != LPFC_NPIV_PORT) ||
!(vport->ct_flags & FC_CT_RFF_ID) || !vport->cfg_restrict_login) {
ndlp = lpfc_setup_disc_node(vport, Did);
if (ndlp && NLP_CHK_NODE_ACT(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);
/* By default, the driver expects to support FCP FC4 */
if (fc4_type == FC_TYPE_FCP)
ndlp->nlp_fc4_type |= NLP_FC4_FCP;
if (fc4_type == FC_TYPE_NVME)
ndlp->nlp_fc4_type |= NLP_FC4_NVME;
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
"0238 Process x%06x NameServer Rsp "
"Data: x%x x%x x%x x%x\n", Did,
ndlp->nlp_flag, ndlp->nlp_fc4_type,
vport->fc_flag,
vport->fc_rscn_id_cnt);
} else {
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
"Skip1 GID_FTrsp: did:x%x flg:x%x cnt:%d",
Did, vport->fc_flag, vport->fc_rscn_id_cnt);
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
"0239 Skip x%06x NameServer Rsp "
"Data: x%x x%x\n", Did,
vport->fc_flag,
vport->fc_rscn_id_cnt);
}
} else {
if (!(vport->fc_flag & FC_RSCN_MODE) ||
lpfc_rscn_payload_check(vport, Did)) {
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
"Query GID_FTrsp: did:x%x flg:x%x cnt:%d",
Did, vport->fc_flag, vport->fc_rscn_id_cnt);
/*
* This NPortID was previously a FCP target,
* Don't even bother to send GFF_ID.
*/
ndlp = lpfc_findnode_did(vport, Did);
if (ndlp && NLP_CHK_NODE_ACT(ndlp))
ndlp->nlp_fc4_type = fc4_type;
if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
ndlp->nlp_fc4_type = fc4_type;
if (ndlp->nlp_type & NLP_FCP_TARGET)
lpfc_setup_disc_node(vport, Did);
else if (lpfc_ns_cmd(vport, SLI_CTNS_GFF_ID,
0, Did) == 0)
vport->num_disc_nodes++;
else
lpfc_setup_disc_node(vport, Did);
}
} 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_vlog(vport, KERN_INFO, LOG_DISCOVERY,
"0245 Skip x%06x NameServer Rsp "
"Data: x%x x%x\n", Did,
vport->fc_flag,
vport->fc_rscn_id_cnt);
}
}
}
static int
lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size)
lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint8_t fc4_type,
uint32_t Size)
{
struct lpfc_hba *phba = vport->phba;
struct lpfc_sli_ct_request *Response =
......@@ -499,97 +584,12 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size)
*/
if ((Did != vport->fc_myDID) &&
((lpfc_find_vport_by_did(phba, Did) == NULL) ||
vport->cfg_peer_port_login)) {
if ((vport->port_type != LPFC_NPIV_PORT) ||
(!(vport->ct_flags & FC_CT_RFF_ID)) ||
(!vport->cfg_restrict_login)) {
ndlp = lpfc_setup_disc_node(vport, Did);
if (ndlp && NLP_CHK_NODE_ACT(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_vlog(vport,
KERN_INFO,
LOG_DISCOVERY,
"0238 Process "
"x%x NameServer Rsp"
"Data: x%x x%x x%x\n",
Did, ndlp->nlp_flag,
vport->fc_flag,
vport->fc_rscn_id_cnt);
} else {
lpfc_debugfs_disc_trc(vport,
LPFC_DISC_TRC_CT,
"Skip1 GID_FTrsp: "
"did:x%x flg:x%x cnt:%d",
Did, vport->fc_flag,
vport->fc_rscn_id_cnt);
lpfc_printf_vlog(vport,
KERN_INFO,
LOG_DISCOVERY,
"0239 Skip x%x "
"NameServer Rsp Data: "
"x%x x%x\n",
Did, vport->fc_flag,
vport->fc_rscn_id_cnt);
}
} else {
if (!(vport->fc_flag & FC_RSCN_MODE) ||
(lpfc_rscn_payload_check(vport, Did))) {
lpfc_debugfs_disc_trc(vport,
LPFC_DISC_TRC_CT,
"Query GID_FTrsp: "
"did:x%x flg:x%x cnt:%d",
Did, vport->fc_flag,
vport->fc_rscn_id_cnt);
/* This NPortID was previously
* a FCP target, * Don't even
* bother to send GFF_ID.
*/
ndlp = lpfc_findnode_did(vport,
Did);
if (ndlp &&
NLP_CHK_NODE_ACT(ndlp)
&& (ndlp->nlp_type &
NLP_FCP_TARGET))
lpfc_setup_disc_node
(vport, Did);
else if (lpfc_ns_cmd(vport,
SLI_CTNS_GFF_ID,
0, Did) == 0)
vport->num_disc_nodes++;
else
lpfc_setup_disc_node
(vport, Did);
}
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_vlog(vport,
KERN_INFO,
LOG_DISCOVERY,
"0245 Skip x%x "
"NameServer Rsp Data: "
"x%x x%x\n",
Did, vport->fc_flag,
vport->fc_rscn_id_cnt);
}
}
}
vport->cfg_peer_port_login))
lpfc_prep_node_fc4type(vport, Did, fc4_type);
if (CTentry & (cpu_to_be32(SLI_CT_LAST_ENTRY)))
goto nsout1;
Cnt -= sizeof(uint32_t);
}
ctptr = NULL;
......@@ -609,16 +609,18 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
IOCB_t *irsp;
struct lpfc_dmabuf *outp;
struct lpfc_dmabuf *inp;
struct lpfc_sli_ct_request *CTrsp;
struct lpfc_sli_ct_request *CTreq;
struct lpfc_nodelist *ndlp;
int rc;
int rc, type;
/* First save ndlp, before we overwrite it */
ndlp = cmdiocb->context_un.ndlp;
/* we pass cmdiocb to state machine which needs rspiocb as well */
cmdiocb->context_un.rsp_iocb = rspiocb;
inp = (struct lpfc_dmabuf *) cmdiocb->context1;
outp = (struct lpfc_dmabuf *) cmdiocb->context2;
irsp = &rspiocb->iocb;
......@@ -656,9 +658,14 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
IOERR_NO_RESOURCES)
vport->fc_ns_retry++;
type = lpfc_get_gidft_type(vport, cmdiocb);
if (type == 0)
goto out;
/* CT command is being retried */
vport->gidft_inp--;
rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_FT,
vport->fc_ns_retry, 0);
vport->fc_ns_retry, type);
if (rc == 0)
goto out;
}
......@@ -670,13 +677,18 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
irsp->ulpStatus, vport->fc_ns_retry);
} else {
/* Good status, continue checking */
CTreq = (struct lpfc_sli_ct_request *) inp->virt;
CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
if (CTrsp->CommandResponse.bits.CmdRsp ==
cpu_to_be16(SLI_CT_RESPONSE_FS_ACC)) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
"0208 NameServer Rsp Data: x%x\n",
vport->fc_flag);
lpfc_ns_rsp(vport, outp,
"0208 NameServer Rsp Data: x%x x%x\n",
vport->fc_flag,
CTreq->un.gid.Fc4Type);
lpfc_ns_rsp(vport,
outp,
CTreq->un.gid.Fc4Type,
(uint32_t) (irsp->un.genreq64.bdl.bdeSize));
} else if (CTrsp->CommandResponse.bits.CmdRsp ==
be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) {
......@@ -731,9 +743,11 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
(uint32_t) CTrsp->ReasonCode,
(uint32_t) CTrsp->Explanation);
}
vport->gidft_inp--;
}
/* Link up / RSCN discovery */
if (vport->num_disc_nodes == 0) {
if ((vport->num_disc_nodes == 0) &&
(vport->gidft_inp == 0)) {
/*
* The driver has cycled through all Nports in the RSCN payload.
* Complete the handling by cleaning up and marking the
......@@ -881,6 +895,60 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
return;
}
static void
lpfc_cmpl_ct_cmd_gft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb)
{
struct lpfc_vport *vport = cmdiocb->vport;
IOCB_t *irsp = &rspiocb->iocb;
struct lpfc_dmabuf *inp = (struct lpfc_dmabuf *)cmdiocb->context1;
struct lpfc_dmabuf *outp = (struct lpfc_dmabuf *)cmdiocb->context2;
struct lpfc_sli_ct_request *CTrsp;
int did;
struct lpfc_nodelist *ndlp;
uint32_t fc4_data_0, fc4_data_1;
did = ((struct lpfc_sli_ct_request *)inp->virt)->un.gft.PortId;
did = be32_to_cpu(did);
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
"GFT_ID cmpl: status:x%x/x%x did:x%x",
irsp->ulpStatus, irsp->un.ulpWord[4], did);
if (irsp->ulpStatus == IOSTAT_SUCCESS) {
/* Good status, continue checking */
CTrsp = (struct lpfc_sli_ct_request *)outp->virt;
fc4_data_0 = be32_to_cpu(CTrsp->un.gft_acc.fc4_types[0]);
fc4_data_1 = be32_to_cpu(CTrsp->un.gft_acc.fc4_types[1]);
lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
"3062 DID x%06x GFT Wd0 x%08x Wd1 x%08x\n",
did, fc4_data_0, fc4_data_1);
ndlp = lpfc_findnode_did(vport, did);
if (ndlp) {
/* The bitmask value for FCP and NVME FCP types is
* the same because they are 32 bits distant from
* each other in word0 and word0.
*/
if (fc4_data_0 & LPFC_FC4_TYPE_BITMASK)
ndlp->nlp_fc4_type |= NLP_FC4_FCP;
if (fc4_data_1 & LPFC_FC4_TYPE_BITMASK)
ndlp->nlp_fc4_type |= NLP_FC4_NVME;
lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
"3064 Setting ndlp %p, DID x%06x with "
"FC4 x%08x, Data: x%08x x%08x\n",
ndlp, did, ndlp->nlp_fc4_type,
FC_TYPE_FCP, FC_TYPE_NVME);
}
ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE);
lpfc_issue_els_prli(vport, ndlp, 0);
} else
lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
"3065 GFT_ID failed x%08x\n", irsp->ulpStatus);
lpfc_ct_free_iocb(phba, cmdiocb);
}
static void
lpfc_cmpl_ct(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
......@@ -1071,31 +1139,27 @@ lpfc_cmpl_ct_cmd_rff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
return;
}
/*
* Although the symbolic port name is thought to be an integer
* as of January 18, 2016, leave it as a string until more of
* the record state becomes defined.
*/
int
lpfc_vport_symbolic_port_name(struct lpfc_vport *vport, char *symbol,
size_t size)
{
int n;
uint8_t *wwn = vport->phba->wwpn;
n = snprintf(symbol, size,
"Emulex PPN-%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
wwn[0], wwn[1], wwn[2], wwn[3],
wwn[4], wwn[5], wwn[6], wwn[7]);
if (vport->port_type == LPFC_PHYSICAL_PORT)
return n;
if (n < size)
n += snprintf(symbol + n, size - n, " VPort-%d", vport->vpi);
if (n < size &&
strlen(vport->fc_vport->symbolic_name))
n += snprintf(symbol + n, size - n, " VName-%s",
vport->fc_vport->symbolic_name);
/*
* Use the lpfc board number as the Symbolic Port
* Name object. NPIV is not in play so this integer
* value is sufficient and unique per FC-ID.
*/
n = snprintf(symbol, size, "%d", vport->phba->brd_no);
return n;
}
int
lpfc_vport_symbolic_node_name(struct lpfc_vport *vport, char *symbol,
size_t size)
......@@ -1106,24 +1170,26 @@ lpfc_vport_symbolic_node_name(struct lpfc_vport *vport, char *symbol,
lpfc_decode_firmware_rev(vport->phba, fwrev, 0);
n = snprintf(symbol, size, "Emulex %s", vport->phba->ModelName);
if (size < n)
return n;
n += snprintf(symbol + n, size - n, " FV%s", fwrev);
n += snprintf(symbol + n, size - n, " FV%s", fwrev);
if (size < n)
return n;
n += snprintf(symbol + n, size - n, " DV%s", lpfc_release_version);
n += snprintf(symbol + n, size - n, " DV%s.",
lpfc_release_version);
if (size < n)
return n;
n += snprintf(symbol + n, size - n, " HN:%s", init_utsname()->nodename);
/* Note :- OS name is "Linux" */
n += snprintf(symbol + n, size - n, " HN:%s.",
init_utsname()->nodename);
if (size < n)
return n;
n += snprintf(symbol + n, size - n, " OS:%s", init_utsname()->sysname);
/* Note :- OS name is "Linux" */
n += snprintf(symbol + n, size - n, " OS:%s\n",
init_utsname()->sysname);
return n;
}
......@@ -1147,6 +1213,27 @@ lpfc_find_map_node(struct lpfc_vport *vport)
return cnt;
}
/*
* This routine will return the FC4 Type associated with the CT
* GID_FT command.
*/
int
lpfc_get_gidft_type(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb)
{
struct lpfc_sli_ct_request *CtReq;
struct lpfc_dmabuf *mp;
uint32_t type;
mp = cmdiocb->context1;
if (mp == NULL)
return 0;
CtReq = (struct lpfc_sli_ct_request *)mp->virt;
type = (uint32_t)CtReq->un.gid.Fc4Type;
if ((type != SLI_CTPT_FCP) && (type != SLI_CTPT_NVME))
return 0;
return type;
}
/*
* lpfc_ns_cmd
* Description:
......@@ -1207,8 +1294,9 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
/* NameServer Req */
lpfc_printf_vlog(vport, KERN_INFO ,LOG_DISCOVERY,
"0236 NameServer Req Data: x%x x%x x%x\n",
cmdcode, vport->fc_flag, vport->fc_rscn_id_cnt);
"0236 NameServer Req Data: x%x x%x x%x x%x\n",
cmdcode, vport->fc_flag, vport->fc_rscn_id_cnt,
context);
bpl = (struct ulp_bde64 *) bmp->virt;
memset(bpl, 0, sizeof(struct ulp_bde64));
......@@ -1219,6 +1307,8 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
bpl->tus.f.bdeSize = GID_REQUEST_SZ;
else if (cmdcode == SLI_CTNS_GFF_ID)
bpl->tus.f.bdeSize = GFF_REQUEST_SZ;
else if (cmdcode == SLI_CTNS_GFT_ID)
bpl->tus.f.bdeSize = GFT_REQUEST_SZ;
else if (cmdcode == SLI_CTNS_RFT_ID)
bpl->tus.f.bdeSize = RFT_REQUEST_SZ;
else if (cmdcode == SLI_CTNS_RNN_ID)
......@@ -1246,7 +1336,8 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
case SLI_CTNS_GID_FT:
CtReq->CommandResponse.bits.CmdRsp =
cpu_to_be16(SLI_CTNS_GID_FT);
CtReq->un.gid.Fc4Type = SLI_CTPT_FCP;
CtReq->un.gid.Fc4Type = context;
if (vport->port_state < LPFC_NS_QRY)
vport->port_state = LPFC_NS_QRY;
lpfc_set_disctmo(vport);
......@@ -1261,12 +1352,32 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
cmpl = lpfc_cmpl_ct_cmd_gff_id;
break;
case SLI_CTNS_GFT_ID:
CtReq->CommandResponse.bits.CmdRsp =
cpu_to_be16(SLI_CTNS_GFT_ID);
CtReq->un.gft.PortId = cpu_to_be32(context);
cmpl = lpfc_cmpl_ct_cmd_gft_id;
break;
case SLI_CTNS_RFT_ID:
vport->ct_flags &= ~FC_CT_RFT_ID;
CtReq->CommandResponse.bits.CmdRsp =
cpu_to_be16(SLI_CTNS_RFT_ID);
CtReq->un.rft.PortId = cpu_to_be32(vport->fc_myDID);
CtReq->un.rft.fcpReg = 1;
/* Register FC4 FCP type if enabled. */
if ((phba->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) ||
(phba->cfg_enable_fc4_type == LPFC_ENABLE_FCP))
CtReq->un.rft.fcpReg = 1;
/* Register NVME type if enabled. Defined LE and swapped.
* rsvd[0] is used as word1 because of the hard-coded
* word0 usage in the ct_request data structure.
*/
if ((phba->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) ||
(phba->cfg_enable_fc4_type == LPFC_ENABLE_NVME))
CtReq->un.rft.rsvd[0] = cpu_to_be32(0x00000100);
cmpl = lpfc_cmpl_ct_cmd_rft_id;
break;
......@@ -1316,7 +1427,31 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
cpu_to_be16(SLI_CTNS_RFF_ID);
CtReq->un.rff.PortId = cpu_to_be32(vport->fc_myDID);
CtReq->un.rff.fbits = FC4_FEATURE_INIT;
CtReq->un.rff.type_code = FC_TYPE_FCP;
/* The driver always supports FC_TYPE_FCP. However, the
* caller can specify NVME (type x28) as well. But only
* these that FC4 type is supported.
*/
if (((phba->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) ||
(phba->cfg_enable_fc4_type == LPFC_ENABLE_NVME)) &&
(context == FC_TYPE_NVME)) {
if ((vport == phba->pport) && phba->nvmet_support) {
CtReq->un.rff.fbits = (FC4_FEATURE_TARGET |
FC4_FEATURE_NVME_DISC);
lpfc_nvmet_update_targetport(phba);
} else {
lpfc_nvme_update_localport(vport);
}
CtReq->un.rff.type_code = context;
} else if (((phba->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) ||
(phba->cfg_enable_fc4_type == LPFC_ENABLE_FCP)) &&
(context == FC_TYPE_FCP))
CtReq->un.rff.type_code = context;
else
goto ns_cmd_free_bmpvirt;
cmpl = lpfc_cmpl_ct_cmd_rff_id;
break;
}
......@@ -1337,6 +1472,7 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
*/
lpfc_nlp_put(ndlp);
ns_cmd_free_bmpvirt:
lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
ns_cmd_free_bmp:
kfree(bmp);
......
This diff is collapsed.
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
* Copyright (C) 2007-2011 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* www.broadcom.com *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of version 2 of the GNU General *
......@@ -42,6 +44,22 @@
/* hbqinfo output buffer size */
#define LPFC_HBQINFO_SIZE 8192
enum {
DUMP_FCP,
DUMP_NVME,
DUMP_MBX,
DUMP_ELS,
DUMP_NVMELS,
};
/* nvmestat output buffer size */
#define LPFC_NVMESTAT_SIZE 8192
#define LPFC_NVMEKTIME_SIZE 8192
#define LPFC_CPUCHECK_SIZE 8192
#define LPFC_NVMEIO_TRC_SIZE 8192
#define LPFC_DEBUG_OUT_LINE_SZ 80
/*
* For SLI4 iDiag debugfs diagnostics tool
*/
......@@ -188,6 +206,12 @@
#define SIZE_U16 sizeof(uint16_t)
#define SIZE_U32 sizeof(uint32_t)
#define lpfc_nvmeio_data(phba, fmt, arg...) \
{ \
if (phba->nvmeio_trc_on) \
lpfc_debugfs_nvme_trc(phba, fmt, ##arg); \
}
struct lpfc_debug {
char *i_private;
char op;
......@@ -206,6 +230,13 @@ struct lpfc_debugfs_trc {
unsigned long jif;
};
struct lpfc_debugfs_nvmeio_trc {
char *fmt;
uint16_t data1;
uint16_t data2;
uint32_t data3;
};
struct lpfc_idiag_offset {
uint32_t last_rd;
};
......@@ -358,58 +389,111 @@ lpfc_debug_dump_q(struct lpfc_queue *q)
}
/**
* lpfc_debug_dump_fcp_wq - dump all entries from a fcp work queue
* lpfc_debug_dump_wq - dump all entries from the fcp or nvme work queue
* @phba: Pointer to HBA context object.
* @fcp_wqidx: Index to a FCP work queue.
* @wqidx: Index to a FCP or NVME work queue.
*
* This function dumps all entries from a FCP work queue specified by the
* @fcp_wqidx.
* This function dumps all entries from a FCP or NVME work queue specified
* by the wqidx.
**/
static inline void
lpfc_debug_dump_fcp_wq(struct lpfc_hba *phba, int fcp_wqidx)
lpfc_debug_dump_wq(struct lpfc_hba *phba, int qtype, int wqidx)
{
/* sanity check */
if (fcp_wqidx >= phba->cfg_fcp_io_channel)
struct lpfc_queue *wq;
char *qtypestr;
if (qtype == DUMP_FCP) {
wq = phba->sli4_hba.fcp_wq[wqidx];
qtypestr = "FCP";
} else if (qtype == DUMP_NVME) {
wq = phba->sli4_hba.nvme_wq[wqidx];
qtypestr = "NVME";
} else if (qtype == DUMP_MBX) {
wq = phba->sli4_hba.mbx_wq;
qtypestr = "MBX";
} else if (qtype == DUMP_ELS) {
wq = phba->sli4_hba.els_wq;
qtypestr = "ELS";
} else if (qtype == DUMP_NVMELS) {
wq = phba->sli4_hba.nvmels_wq;
qtypestr = "NVMELS";
} else
return;
printk(KERN_ERR "FCP WQ: WQ[Idx:%d|Qid:%d]\n",
fcp_wqidx, phba->sli4_hba.fcp_wq[fcp_wqidx]->queue_id);
lpfc_debug_dump_q(phba->sli4_hba.fcp_wq[fcp_wqidx]);
if (qtype == DUMP_FCP || qtype == DUMP_NVME)
pr_err("%s WQ: WQ[Idx:%d|Qid:%d]\n",
qtypestr, wqidx, wq->queue_id);
else
pr_err("%s WQ: WQ[Qid:%d]\n",
qtypestr, wq->queue_id);
lpfc_debug_dump_q(wq);
}
/**
* lpfc_debug_dump_fcp_cq - dump all entries from a fcp work queue's cmpl queue
* lpfc_debug_dump_cq - dump all entries from a fcp or nvme work queue's
* cmpl queue
* @phba: Pointer to HBA context object.
* @fcp_wqidx: Index to a FCP work queue.
* @wqidx: Index to a FCP work queue.
*
* This function dumps all entries from a FCP complete queue which is
* associated to the FCP work queue specified by the @fcp_wqidx.
* This function dumps all entries from a FCP or NVME completion queue
* which is associated to the work queue specified by the @wqidx.
**/
static inline void
lpfc_debug_dump_fcp_cq(struct lpfc_hba *phba, int fcp_wqidx)
lpfc_debug_dump_cq(struct lpfc_hba *phba, int qtype, int wqidx)
{
int fcp_cqidx, fcp_cqid;
/* sanity check */
if (fcp_wqidx >= phba->cfg_fcp_io_channel)
struct lpfc_queue *wq, *cq, *eq;
char *qtypestr;
int eqidx;
/* fcp/nvme wq and cq are 1:1, thus same indexes */
if (qtype == DUMP_FCP) {
wq = phba->sli4_hba.fcp_wq[wqidx];
cq = phba->sli4_hba.fcp_cq[wqidx];
qtypestr = "FCP";
} else if (qtype == DUMP_NVME) {
wq = phba->sli4_hba.nvme_wq[wqidx];
cq = phba->sli4_hba.nvme_cq[wqidx];
qtypestr = "NVME";
} else if (qtype == DUMP_MBX) {
wq = phba->sli4_hba.mbx_wq;
cq = phba->sli4_hba.mbx_cq;
qtypestr = "MBX";
} else if (qtype == DUMP_ELS) {
wq = phba->sli4_hba.els_wq;
cq = phba->sli4_hba.els_cq;
qtypestr = "ELS";
} else if (qtype == DUMP_NVMELS) {
wq = phba->sli4_hba.nvmels_wq;
cq = phba->sli4_hba.nvmels_cq;
qtypestr = "NVMELS";
} else
return;
fcp_cqid = phba->sli4_hba.fcp_wq[fcp_wqidx]->assoc_qid;
for (fcp_cqidx = 0; fcp_cqidx < phba->cfg_fcp_io_channel; fcp_cqidx++)
if (phba->sli4_hba.fcp_cq[fcp_cqidx]->queue_id == fcp_cqid)
for (eqidx = 0; eqidx < phba->io_channel_irqs; eqidx++) {
eq = phba->sli4_hba.hba_eq[eqidx];
if (cq->assoc_qid == eq->queue_id)
break;
if (phba->intr_type == MSIX) {
if (fcp_cqidx >= phba->cfg_fcp_io_channel)
return;
} else {
if (fcp_cqidx > 0)
return;
}
if (eqidx == phba->io_channel_irqs) {
pr_err("Couldn't find EQ for CQ. Using EQ[0]\n");
eqidx = 0;
eq = phba->sli4_hba.hba_eq[0];
}
printk(KERN_ERR "FCP CQ: WQ[Idx:%d|Qid%d]->CQ[Idx%d|Qid%d]:\n",
fcp_wqidx, phba->sli4_hba.fcp_wq[fcp_wqidx]->queue_id,
fcp_cqidx, fcp_cqid);
lpfc_debug_dump_q(phba->sli4_hba.fcp_cq[fcp_cqidx]);
if (qtype == DUMP_FCP || qtype == DUMP_NVME)
pr_err("%s CQ: WQ[Idx:%d|Qid%d]->CQ[Idx%d|Qid%d]"
"->EQ[Idx:%d|Qid:%d]:\n",
qtypestr, wqidx, wq->queue_id, wqidx, cq->queue_id,
eqidx, eq->queue_id);
else
pr_err("%s CQ: WQ[Qid:%d]->CQ[Qid:%d]"
"->EQ[Idx:%d|Qid:%d]:\n",
qtypestr, wq->queue_id, cq->queue_id,
eqidx, eq->queue_id);
lpfc_debug_dump_q(cq);
}
/**
......@@ -421,64 +505,15 @@ lpfc_debug_dump_fcp_cq(struct lpfc_hba *phba, int fcp_wqidx)
* associated to the FCP work queue specified by the @fcp_wqidx.
**/
static inline void
lpfc_debug_dump_hba_eq(struct lpfc_hba *phba, int fcp_wqidx)
lpfc_debug_dump_hba_eq(struct lpfc_hba *phba, int qidx)
{
struct lpfc_queue *qdesc;
int fcp_eqidx, fcp_eqid;
int fcp_cqidx, fcp_cqid;
struct lpfc_queue *qp;
/* sanity check */
if (fcp_wqidx >= phba->cfg_fcp_io_channel)
return;
fcp_cqid = phba->sli4_hba.fcp_wq[fcp_wqidx]->assoc_qid;
for (fcp_cqidx = 0; fcp_cqidx < phba->cfg_fcp_io_channel; fcp_cqidx++)
if (phba->sli4_hba.fcp_cq[fcp_cqidx]->queue_id == fcp_cqid)
break;
if (phba->intr_type == MSIX) {
if (fcp_cqidx >= phba->cfg_fcp_io_channel)
return;
} else {
if (fcp_cqidx > 0)
return;
}
qp = phba->sli4_hba.hba_eq[qidx];
fcp_eqidx = fcp_cqidx;
fcp_eqid = phba->sli4_hba.hba_eq[fcp_eqidx]->queue_id;
qdesc = phba->sli4_hba.hba_eq[fcp_eqidx];
pr_err("EQ[Idx:%d|Qid:%d]\n", qidx, qp->queue_id);
printk(KERN_ERR "FCP EQ: WQ[Idx:%d|Qid:%d]->CQ[Idx:%d|Qid:%d]->"
"EQ[Idx:%d|Qid:%d]\n",
fcp_wqidx, phba->sli4_hba.fcp_wq[fcp_wqidx]->queue_id,
fcp_cqidx, fcp_cqid, fcp_eqidx, fcp_eqid);
lpfc_debug_dump_q(qdesc);
}
/**
* lpfc_debug_dump_els_wq - dump all entries from the els work queue
* @phba: Pointer to HBA context object.
*
* This function dumps all entries from the ELS work queue.
**/
static inline void
lpfc_debug_dump_els_wq(struct lpfc_hba *phba)
{
printk(KERN_ERR "ELS WQ: WQ[Qid:%d]:\n",
phba->sli4_hba.els_wq->queue_id);
lpfc_debug_dump_q(phba->sli4_hba.els_wq);
}
/**
* lpfc_debug_dump_mbx_wq - dump all entries from the mbox work queue
* @phba: Pointer to HBA context object.
*
* This function dumps all entries from the MBOX work queue.
**/
static inline void
lpfc_debug_dump_mbx_wq(struct lpfc_hba *phba)
{
printk(KERN_ERR "MBX WQ: WQ[Qid:%d]\n",
phba->sli4_hba.mbx_wq->queue_id);
lpfc_debug_dump_q(phba->sli4_hba.mbx_wq);
lpfc_debug_dump_q(qp);
}
/**
......@@ -509,36 +544,6 @@ lpfc_debug_dump_hdr_rq(struct lpfc_hba *phba)
lpfc_debug_dump_q(phba->sli4_hba.hdr_rq);
}
/**
* lpfc_debug_dump_els_cq - dump all entries from the els complete queue
* @phba: Pointer to HBA context object.
*
* This function dumps all entries from the els complete queue.
**/
static inline void
lpfc_debug_dump_els_cq(struct lpfc_hba *phba)
{
printk(KERN_ERR "ELS CQ: WQ[Qid:%d]->CQ[Qid:%d]\n",
phba->sli4_hba.els_wq->queue_id,
phba->sli4_hba.els_cq->queue_id);
lpfc_debug_dump_q(phba->sli4_hba.els_cq);
}
/**
* lpfc_debug_dump_mbx_cq - dump all entries from the mbox complete queue
* @phba: Pointer to HBA context object.
*
* This function dumps all entries from the mbox complete queue.
**/
static inline void
lpfc_debug_dump_mbx_cq(struct lpfc_hba *phba)
{
printk(KERN_ERR "MBX CQ: WQ[Qid:%d]->CQ[Qid:%d]\n",
phba->sli4_hba.mbx_wq->queue_id,
phba->sli4_hba.mbx_cq->queue_id);
lpfc_debug_dump_q(phba->sli4_hba.mbx_cq);
}
/**
* lpfc_debug_dump_wq_by_id - dump all entries from a work queue by queue id
* @phba: Pointer to HBA context object.
......@@ -556,14 +561,29 @@ lpfc_debug_dump_wq_by_id(struct lpfc_hba *phba, int qid)
if (phba->sli4_hba.fcp_wq[wq_idx]->queue_id == qid)
break;
if (wq_idx < phba->cfg_fcp_io_channel) {
printk(KERN_ERR "FCP WQ[Idx:%d|Qid:%d]\n", wq_idx, qid);
pr_err("FCP WQ[Idx:%d|Qid:%d]\n", wq_idx, qid);
lpfc_debug_dump_q(phba->sli4_hba.fcp_wq[wq_idx]);
return;
}
for (wq_idx = 0; wq_idx < phba->cfg_nvme_io_channel; wq_idx++)
if (phba->sli4_hba.nvme_wq[wq_idx]->queue_id == qid)
break;
if (wq_idx < phba->cfg_nvme_io_channel) {
pr_err("NVME WQ[Idx:%d|Qid:%d]\n", wq_idx, qid);
lpfc_debug_dump_q(phba->sli4_hba.nvme_wq[wq_idx]);
return;
}
if (phba->sli4_hba.els_wq->queue_id == qid) {
printk(KERN_ERR "ELS WQ[Qid:%d]\n", qid);
pr_err("ELS WQ[Qid:%d]\n", qid);
lpfc_debug_dump_q(phba->sli4_hba.els_wq);
return;
}
if (phba->sli4_hba.nvmels_wq->queue_id == qid) {
pr_err("NVME LS WQ[Qid:%d]\n", qid);
lpfc_debug_dump_q(phba->sli4_hba.nvmels_wq);
}
}
......@@ -617,27 +637,42 @@ lpfc_debug_dump_rq_by_id(struct lpfc_hba *phba, int qid)
static inline void
lpfc_debug_dump_cq_by_id(struct lpfc_hba *phba, int qid)
{
int cq_idx = 0;
int cq_idx;
do {
for (cq_idx = 0; cq_idx < phba->cfg_fcp_io_channel; cq_idx++)
if (phba->sli4_hba.fcp_cq[cq_idx]->queue_id == qid)
break;
} while (++cq_idx < phba->cfg_fcp_io_channel);
if (cq_idx < phba->cfg_fcp_io_channel) {
printk(KERN_ERR "FCP CQ[Idx:%d|Qid:%d]\n", cq_idx, qid);
pr_err("FCP CQ[Idx:%d|Qid:%d]\n", cq_idx, qid);
lpfc_debug_dump_q(phba->sli4_hba.fcp_cq[cq_idx]);
return;
}
for (cq_idx = 0; cq_idx < phba->cfg_nvme_io_channel; cq_idx++)
if (phba->sli4_hba.nvme_cq[cq_idx]->queue_id == qid)
break;
if (cq_idx < phba->cfg_nvme_io_channel) {
pr_err("NVME CQ[Idx:%d|Qid:%d]\n", cq_idx, qid);
lpfc_debug_dump_q(phba->sli4_hba.nvme_cq[cq_idx]);
return;
}
if (phba->sli4_hba.els_cq->queue_id == qid) {
printk(KERN_ERR "ELS CQ[Qid:%d]\n", qid);
pr_err("ELS CQ[Qid:%d]\n", qid);
lpfc_debug_dump_q(phba->sli4_hba.els_cq);
return;
}
if (phba->sli4_hba.nvmels_cq->queue_id == qid) {
pr_err("NVME LS CQ[Qid:%d]\n", qid);
lpfc_debug_dump_q(phba->sli4_hba.nvmels_cq);
return;
}
if (phba->sli4_hba.mbx_cq->queue_id == qid) {
printk(KERN_ERR "MBX CQ[Qid:%d]\n", qid);
pr_err("MBX CQ[Qid:%d]\n", qid);
lpfc_debug_dump_q(phba->sli4_hba.mbx_cq);
}
}
......@@ -655,17 +690,15 @@ lpfc_debug_dump_eq_by_id(struct lpfc_hba *phba, int qid)
{
int eq_idx;
for (eq_idx = 0; eq_idx < phba->cfg_fcp_io_channel; eq_idx++) {
for (eq_idx = 0; eq_idx < phba->io_channel_irqs; eq_idx++)
if (phba->sli4_hba.hba_eq[eq_idx]->queue_id == qid)
break;
}
if (eq_idx < phba->cfg_fcp_io_channel) {
if (eq_idx < phba->io_channel_irqs) {
printk(KERN_ERR "FCP EQ[Idx:%d|Qid:%d]\n", eq_idx, qid);
lpfc_debug_dump_q(phba->sli4_hba.hba_eq[eq_idx]);
return;
}
}
void lpfc_debug_dump_all_queues(struct lpfc_hba *);
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
* Copyright (C) 2004-2013 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* www.broadcom.com *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of version 2 of the GNU General *
......@@ -86,6 +88,17 @@ struct lpfc_nodelist {
#define NLP_FABRIC 0x4 /* entry rep a Fabric entity */
#define NLP_FCP_TARGET 0x8 /* entry is an FCP target */
#define NLP_FCP_INITIATOR 0x10 /* entry is an FCP Initiator */
#define NLP_NVME_TARGET 0x20 /* entry is a NVME Target */
#define NLP_NVME_INITIATOR 0x40 /* entry is a NVME Initiator */
uint16_t nlp_fc4_type; /* FC types node supports. */
/* Assigned from GID_FF, only
* FCP (0x8) and NVME (0x28)
* supported.
*/
#define NLP_FC4_NONE 0x0
#define NLP_FC4_FCP 0x1 /* FC4 Type FCP (value x8)) */
#define NLP_FC4_NVME 0x2 /* FC4 TYPE NVME (value x28) */
uint16_t nlp_rpi;
uint16_t nlp_state; /* state transition indicator */
......@@ -107,8 +120,8 @@ struct lpfc_nodelist {
struct timer_list nlp_delayfunc; /* Used for delayed ELS cmds */
struct lpfc_hba *phba;
struct fc_rport *rport; /* Corresponding FC transport
port structure */
struct fc_rport *rport; /* scsi_transport_fc port structure */
struct lpfc_nvme_rport *nrport; /* nvme transport rport struct. */
struct lpfc_vport *vport;
struct lpfc_work_evt els_retry_evt;
struct lpfc_work_evt dev_loss_evt;
......@@ -118,6 +131,10 @@ struct lpfc_nodelist {
unsigned long last_change_time;
unsigned long *active_rrqs_xri_bitmap;
struct lpfc_scsicmd_bkt *lat_data; /* Latency data */
uint32_t fc4_prli_sent;
uint32_t upcall_flags;
uint32_t nvme_fb_size; /* NVME target's supported byte cnt */
#define NVME_FB_BIT_SHIFT 9 /* PRLI Rsp first burst in 512B units. */
};
struct lpfc_node_rrq {
struct list_head list;
......@@ -133,6 +150,7 @@ struct lpfc_node_rrq {
/* Defines for nlp_flag (uint32) */
#define NLP_IGNR_REG_CMPL 0x00000001 /* Rcvd rscn before we cmpl reg login */
#define NLP_REG_LOGIN_SEND 0x00000002 /* sent reglogin to adapter */
#define NLP_SUPPRESS_RSP 0x00000010 /* Remote NPort supports suppress rsp */
#define NLP_PLOGI_SND 0x00000020 /* sent PLOGI request for this entry */
#define NLP_PRLI_SND 0x00000040 /* sent PRLI request for this entry */
#define NLP_ADISC_SND 0x00000080 /* sent ADISC request for this entry */
......
This diff is collapsed.
This diff is collapsed.
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* www.broadcom.com *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of version 2 of the GNU General *
......@@ -44,8 +46,6 @@
#define LPFC_FCP_RING 0 /* ring 0 for FCP initiator commands */
#define LPFC_EXTRA_RING 1 /* ring 1 for other protocols */
#define LPFC_ELS_RING 2 /* ring 2 for ELS commands */
#define LPFC_FCP_NEXT_RING 3
#define LPFC_FCP_OAS_RING 3
#define SLI2_IOCB_CMD_R0_ENTRIES 172 /* SLI-2 FCP command ring entries */
#define SLI2_IOCB_RSP_R0_ENTRIES 134 /* SLI-2 FCP response ring entries */
......@@ -92,8 +92,10 @@ union CtCommandResponse {
uint32_t word;
};
#define FC4_FEATURE_INIT 0x2
#define FC4_FEATURE_TARGET 0x1
/* FC4 Feature bits for RFF_ID */
#define FC4_FEATURE_TARGET 0x1
#define FC4_FEATURE_INIT 0x2
#define FC4_FEATURE_NVME_DISC 0x4
struct lpfc_sli_ct_request {
/* Structure is in Big Endian format */
......@@ -117,6 +119,16 @@ struct lpfc_sli_ct_request {
uint8_t AreaScope;
uint8_t Fc4Type; /* for GID_FT requests */
} gid;
struct gid_ff {
uint8_t Flags;
uint8_t DomainScope;
uint8_t AreaScope;
uint8_t rsvd1;
uint8_t rsvd2;
uint8_t rsvd3;
uint8_t Fc4FBits;
uint8_t Fc4Type;
} gid_ff;
struct rft {
uint32_t PortId; /* For RFT_ID requests */
......@@ -161,6 +173,12 @@ struct lpfc_sli_ct_request {
struct gff_acc {
uint8_t fbits[128];
} gff_acc;
struct gft {
uint32_t PortId;
} gft;
struct gft_acc {
uint32_t fc4_types[8];
} gft_acc;
#define FCP_TYPE_FEATURE_OFFSET 7
struct rff {
uint32_t PortId;
......@@ -176,8 +194,12 @@ struct lpfc_sli_ct_request {
#define SLI_CT_REVISION 1
#define GID_REQUEST_SZ (offsetof(struct lpfc_sli_ct_request, un) + \
sizeof(struct gid))
#define GIDFF_REQUEST_SZ (offsetof(struct lpfc_sli_ct_request, un) + \
sizeof(struct gid_ff))
#define GFF_REQUEST_SZ (offsetof(struct lpfc_sli_ct_request, un) + \
sizeof(struct gff))
#define GFT_REQUEST_SZ (offsetof(struct lpfc_sli_ct_request, un) + \
sizeof(struct gft))
#define RFT_REQUEST_SZ (offsetof(struct lpfc_sli_ct_request, un) + \
sizeof(struct rft))
#define RFF_REQUEST_SZ (offsetof(struct lpfc_sli_ct_request, un) + \
......@@ -273,6 +295,7 @@ struct lpfc_sli_ct_request {
#define SLI_CTNS_GNN_IP 0x0153
#define SLI_CTNS_GIPA_IP 0x0156
#define SLI_CTNS_GID_FT 0x0171
#define SLI_CTNS_GID_FF 0x01F1
#define SLI_CTNS_GID_PT 0x01A1
#define SLI_CTNS_RPN_ID 0x0212
#define SLI_CTNS_RNN_ID 0x0213
......@@ -290,15 +313,16 @@ struct lpfc_sli_ct_request {
* Port Types
*/
#define SLI_CTPT_N_PORT 0x01
#define SLI_CTPT_NL_PORT 0x02
#define SLI_CTPT_FNL_PORT 0x03
#define SLI_CTPT_IP 0x04
#define SLI_CTPT_FCP 0x08
#define SLI_CTPT_NX_PORT 0x7F
#define SLI_CTPT_F_PORT 0x81
#define SLI_CTPT_FL_PORT 0x82
#define SLI_CTPT_E_PORT 0x84
#define SLI_CTPT_N_PORT 0x01
#define SLI_CTPT_NL_PORT 0x02
#define SLI_CTPT_FNL_PORT 0x03
#define SLI_CTPT_IP 0x04
#define SLI_CTPT_FCP 0x08
#define SLI_CTPT_NVME 0x28
#define SLI_CTPT_NX_PORT 0x7F
#define SLI_CTPT_F_PORT 0x81
#define SLI_CTPT_FL_PORT 0x82
#define SLI_CTPT_E_PORT 0x84
#define SLI_CT_LAST_ENTRY 0x80000000
......@@ -339,6 +363,7 @@ struct lpfc_name {
uint8_t IEEE[6]; /* FC IEEE address */
} s;
uint8_t wwn[8];
uint64_t name;
} u;
};
......@@ -492,7 +517,15 @@ struct serv_parm { /* Structure is in Big Endian format */
struct class_parms cls2;
struct class_parms cls3;
struct class_parms cls4;
uint8_t vendorVersion[16];
union {
uint8_t vendorVersion[16];
struct {
uint32_t vid;
#define LPFC_VV_EMLX_ID 0x454d4c58 /* EMLX */
uint32_t flags;
#define LPFC_VV_SUPPRESS_RSP 1
} vv;
} un;
};
/*
......@@ -551,6 +584,7 @@ struct fc_vft_header {
#define ELS_CMD_REC 0x13000000
#define ELS_CMD_RDP 0x18000000
#define ELS_CMD_PRLI 0x20100014
#define ELS_CMD_NVMEPRLI 0x20140018
#define ELS_CMD_PRLO 0x21100014
#define ELS_CMD_PRLO_ACC 0x02100014
#define ELS_CMD_PDISC 0x50000000
......@@ -590,6 +624,7 @@ struct fc_vft_header {
#define ELS_CMD_REC 0x13
#define ELS_CMD_RDP 0x18
#define ELS_CMD_PRLI 0x14001020
#define ELS_CMD_NVMEPRLI 0x18001420
#define ELS_CMD_PRLO 0x14001021
#define ELS_CMD_PRLO_ACC 0x14001002
#define ELS_CMD_PDISC 0x50
......@@ -686,6 +721,7 @@ typedef struct _PRLI { /* Structure is in Big Endian format */
uint8_t prliType; /* FC Parm Word 0, bit 24:31 */
#define PRLI_FCP_TYPE 0x08
#define PRLI_NVME_TYPE 0x28
uint8_t word0Reserved1; /* FC Parm Word 0, bit 16:23 */
#ifdef __BIG_ENDIAN_BITFIELD
......@@ -1245,8 +1281,7 @@ struct fc_rdp_opd_sfp_info {
uint8_t vendor_name[16];
uint8_t model_number[16];
uint8_t serial_number[16];
uint8_t revision[2];
uint8_t reserved[2];
uint8_t revision[4];
uint8_t date[8];
};
......@@ -1265,14 +1300,14 @@ struct fc_rdp_req_frame {
struct fc_rdp_res_frame {
uint32_t reply_sequence; /* FC word0 LS_ACC or LS_RJT */
uint32_t length; /* FC Word 1 */
struct fc_rdp_link_service_desc link_service_desc; /* Word 2 -4 */
struct fc_rdp_sfp_desc sfp_desc; /* Word 5 -9 */
struct fc_rdp_port_speed_desc portspeed_desc; /* Word 10-12 */
struct fc_rdp_link_error_status_desc link_error_desc; /* Word 13-21 */
struct fc_rdp_port_name_desc diag_port_names_desc; /* Word 22-27 */
struct fc_rdp_port_name_desc attached_port_names_desc;/* Word 28-33 */
uint32_t reply_sequence; /* FC word0 LS_ACC or LS_RJT */
uint32_t length; /* FC Word 1 */
struct fc_rdp_link_service_desc link_service_desc; /* Word 2 -4 */
struct fc_rdp_sfp_desc sfp_desc; /* Word 5 -9 */
struct fc_rdp_port_speed_desc portspeed_desc; /* Word 10 -12 */
struct fc_rdp_link_error_status_desc link_error_desc; /* Word 13 -21 */
struct fc_rdp_port_name_desc diag_port_names_desc; /* Word 22 -27 */
struct fc_rdp_port_name_desc attached_port_names_desc;/* Word 28 -33 */
struct fc_fec_rdp_desc fec_desc; /* FC word 34-37*/
struct fc_rdp_bbc_desc bbc_desc; /* FC Word 38-42*/
struct fc_rdp_oed_sfp_desc oed_temp_desc; /* FC Word 43-47*/
......@@ -1791,6 +1826,7 @@ typedef struct { /* FireFly BIU registers */
#define MBX_INIT_VFI 0xA3
#define MBX_INIT_VPI 0xA4
#define MBX_ACCESS_VDATA 0xA5
#define MBX_REG_FCFI_MRQ 0xAF
#define MBX_AUTH_PORT 0xF8
#define MBX_SECURITY_MGMT 0xF9
......
This diff is collapsed.
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* www.broadcom.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
* *
* This program is free software; you can redistribute it and/or *
......
This diff is collapsed.
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
* Copyright (C) 2004-2009 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* www.broadcom.com *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of version 2 of the GNU General *
......@@ -38,6 +40,10 @@
#define LOG_FIP 0x00020000 /* FIP events */
#define LOG_FCP_UNDER 0x00040000 /* FCP underruns errors */
#define LOG_SCSI_CMD 0x00080000 /* ALL SCSI commands */
#define LOG_NVME 0x00100000 /* NVME general events. */
#define LOG_NVME_DISC 0x00200000 /* NVME Discovery/Connect events. */
#define LOG_NVME_ABTS 0x00400000 /* NVME ABTS events. */
#define LOG_NVME_IOERR 0x00800000 /* NVME IO Error events. */
#define LOG_ALL_MSG 0xffffffff /* LOG all messages */
#define lpfc_printf_vlog(vport, level, mask, fmt, arg...) \
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment