mirror of
https://github.com/edk2-porting/linux-next.git
synced 2025-01-18 10:34:24 +08:00
[SCSI] lpfc 8.3.2 : Addition of SLI4 Interface - Base Support
Adds new hardware and interface definitions. Adds new interface routines - utilizing the reorganized layout of the driver. Adds SLI-4 specific functions for attachment, initialization, teardown, etc. Signed-off-by: James Smart <james.smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
This commit is contained in:
parent
3772a99175
commit
da0436e915
@ -105,9 +105,11 @@ struct lpfc_dma_pool {
|
||||
};
|
||||
|
||||
struct hbq_dmabuf {
|
||||
struct lpfc_dmabuf hbuf;
|
||||
struct lpfc_dmabuf dbuf;
|
||||
uint32_t size;
|
||||
uint32_t tag;
|
||||
struct lpfc_rcqe rcqe;
|
||||
};
|
||||
|
||||
/* Priority bit. Set value to exceed low water mark in lpfc_mem. */
|
||||
@ -141,7 +143,10 @@ typedef struct lpfc_vpd {
|
||||
} rev;
|
||||
struct {
|
||||
#ifdef __BIG_ENDIAN_BITFIELD
|
||||
uint32_t rsvd2 :24; /* Reserved */
|
||||
uint32_t rsvd3 :19; /* Reserved */
|
||||
uint32_t cdss : 1; /* Configure Data Security SLI */
|
||||
uint32_t rsvd2 : 3; /* Reserved */
|
||||
uint32_t cbg : 1; /* Configure BlockGuard */
|
||||
uint32_t cmv : 1; /* Configure Max VPIs */
|
||||
uint32_t ccrp : 1; /* Config Command Ring Polling */
|
||||
uint32_t csah : 1; /* Configure Synchronous Abort Handling */
|
||||
@ -159,7 +164,10 @@ typedef struct lpfc_vpd {
|
||||
uint32_t csah : 1; /* Configure Synchronous Abort Handling */
|
||||
uint32_t ccrp : 1; /* Config Command Ring Polling */
|
||||
uint32_t cmv : 1; /* Configure Max VPIs */
|
||||
uint32_t rsvd2 :24; /* Reserved */
|
||||
uint32_t cbg : 1; /* Configure BlockGuard */
|
||||
uint32_t rsvd2 : 3; /* Reserved */
|
||||
uint32_t cdss : 1; /* Configure Data Security SLI */
|
||||
uint32_t rsvd3 :19; /* Reserved */
|
||||
#endif
|
||||
} sli3Feat;
|
||||
} lpfc_vpd_t;
|
||||
@ -280,6 +288,9 @@ struct lpfc_vport {
|
||||
enum discovery_state port_state;
|
||||
|
||||
uint16_t vpi;
|
||||
uint16_t vfi;
|
||||
uint8_t vfi_state;
|
||||
#define LPFC_VFI_REGISTERED 0x1
|
||||
|
||||
uint32_t fc_flag; /* FC flags */
|
||||
/* Several of these flags are HBA centric and should be moved to
|
||||
@ -392,6 +403,9 @@ struct lpfc_vport {
|
||||
#endif
|
||||
uint8_t stat_data_enabled;
|
||||
uint8_t stat_data_blocked;
|
||||
struct list_head rcv_buffer_list;
|
||||
uint32_t vport_flag;
|
||||
#define STATIC_VPORT 1
|
||||
};
|
||||
|
||||
struct hbq_s {
|
||||
@ -494,6 +508,7 @@ struct lpfc_hba {
|
||||
#define LPFC_SLI3_CRP_ENABLED 0x08
|
||||
#define LPFC_SLI3_INB_ENABLED 0x10
|
||||
#define LPFC_SLI3_BG_ENABLED 0x20
|
||||
#define LPFC_SLI3_DSS_ENABLED 0x40
|
||||
uint32_t iocb_cmd_size;
|
||||
uint32_t iocb_rsp_size;
|
||||
|
||||
@ -507,8 +522,13 @@ struct lpfc_hba {
|
||||
|
||||
uint32_t hba_flag; /* hba generic flags */
|
||||
#define HBA_ERATT_HANDLED 0x1 /* This flag is set when eratt handled */
|
||||
|
||||
#define DEFER_ERATT 0x4 /* Deferred error attention in progress */
|
||||
#define DEFER_ERATT 0x2 /* Deferred error attention in progress */
|
||||
#define HBA_FCOE_SUPPORT 0x4 /* HBA function supports FCOE */
|
||||
#define HBA_RECEIVE_BUFFER 0x8 /* Rcv buffer posted to worker thread */
|
||||
#define HBA_POST_RECEIVE_BUFFER 0x10 /* Rcv buffers need to be posted */
|
||||
#define FCP_XRI_ABORT_EVENT 0x20
|
||||
#define ELS_XRI_ABORT_EVENT 0x40
|
||||
#define ASYNC_EVENT 0x80
|
||||
struct lpfc_dmabuf slim2p;
|
||||
|
||||
MAILBOX_t *mbox;
|
||||
@ -567,6 +587,9 @@ struct lpfc_hba {
|
||||
uint32_t cfg_poll;
|
||||
uint32_t cfg_poll_tmo;
|
||||
uint32_t cfg_use_msi;
|
||||
uint32_t cfg_fcp_imax;
|
||||
uint32_t cfg_fcp_wq_count;
|
||||
uint32_t cfg_fcp_eq_count;
|
||||
uint32_t cfg_sg_seg_cnt;
|
||||
uint32_t cfg_prot_sg_seg_cnt;
|
||||
uint32_t cfg_sg_dma_buf_size;
|
||||
@ -576,6 +599,8 @@ struct lpfc_hba {
|
||||
uint32_t cfg_enable_hba_reset;
|
||||
uint32_t cfg_enable_hba_heartbeat;
|
||||
uint32_t cfg_enable_bg;
|
||||
uint32_t cfg_enable_fip;
|
||||
uint32_t cfg_log_verbose;
|
||||
|
||||
lpfc_vpd_t vpd; /* vital product data */
|
||||
|
||||
@ -659,7 +684,8 @@ struct lpfc_hba {
|
||||
/* pci_mem_pools */
|
||||
struct pci_pool *lpfc_scsi_dma_buf_pool;
|
||||
struct pci_pool *lpfc_mbuf_pool;
|
||||
struct pci_pool *lpfc_hbq_pool;
|
||||
struct pci_pool *lpfc_hrb_pool; /* header receive buffer pool */
|
||||
struct pci_pool *lpfc_drb_pool; /* data receive buffer pool */
|
||||
struct lpfc_dma_pool lpfc_mbuf_safety_pool;
|
||||
|
||||
mempool_t *mbox_mem_pool;
|
||||
@ -675,6 +701,14 @@ struct lpfc_hba {
|
||||
struct lpfc_vport *pport; /* physical lpfc_vport pointer */
|
||||
uint16_t max_vpi; /* Maximum virtual nports */
|
||||
#define LPFC_MAX_VPI 0xFFFF /* Max number of VPI supported */
|
||||
uint16_t max_vports; /*
|
||||
* For IOV HBAs max_vpi can change
|
||||
* after a reset. max_vports is max
|
||||
* number of vports present. This can
|
||||
* be greater than max_vpi.
|
||||
*/
|
||||
uint16_t vpi_base;
|
||||
uint16_t vfi_base;
|
||||
unsigned long *vpi_bmask; /* vpi allocation table */
|
||||
|
||||
/* Data structure used by fabric iocb scheduler */
|
||||
@ -733,6 +767,11 @@ struct lpfc_hba {
|
||||
/* Maximum number of events that can be outstanding at any time*/
|
||||
#define LPFC_MAX_EVT_COUNT 512
|
||||
atomic_t fast_event_count;
|
||||
struct lpfc_fcf fcf;
|
||||
uint8_t fc_map[3];
|
||||
uint8_t valid_vlan;
|
||||
uint16_t vlan_id;
|
||||
struct list_head fcf_conn_rec_list;
|
||||
};
|
||||
|
||||
static inline struct Scsi_Host *
|
||||
|
@ -30,8 +30,10 @@
|
||||
#include <scsi/scsi_tcq.h>
|
||||
#include <scsi/scsi_transport_fc.h>
|
||||
|
||||
#include "lpfc_hw4.h"
|
||||
#include "lpfc_hw.h"
|
||||
#include "lpfc_sli.h"
|
||||
#include "lpfc_sli4.h"
|
||||
#include "lpfc_nl.h"
|
||||
#include "lpfc_disc.h"
|
||||
#include "lpfc_scsi.h"
|
||||
@ -828,6 +830,24 @@ lpfc_get_hba_info(struct lpfc_hba *phba,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (phba->sli_rev == LPFC_SLI_REV4) {
|
||||
rd_config = &pmboxq->u.mqe.un.rd_config;
|
||||
if (mrpi)
|
||||
*mrpi = bf_get(lpfc_mbx_rd_conf_rpi_count, rd_config);
|
||||
if (arpi)
|
||||
*arpi = bf_get(lpfc_mbx_rd_conf_rpi_count, rd_config) -
|
||||
phba->sli4_hba.max_cfg_param.rpi_used;
|
||||
if (mxri)
|
||||
*mxri = bf_get(lpfc_mbx_rd_conf_xri_count, rd_config);
|
||||
if (axri)
|
||||
*axri = bf_get(lpfc_mbx_rd_conf_xri_count, rd_config) -
|
||||
phba->sli4_hba.max_cfg_param.xri_used;
|
||||
if (mvpi)
|
||||
*mvpi = bf_get(lpfc_mbx_rd_conf_vpi_count, rd_config);
|
||||
if (avpi)
|
||||
*avpi = bf_get(lpfc_mbx_rd_conf_vpi_count, rd_config) -
|
||||
phba->sli4_hba.max_cfg_param.vpi_used;
|
||||
} else {
|
||||
if (mrpi)
|
||||
*mrpi = pmb->un.varRdConfig.max_rpi;
|
||||
if (arpi)
|
||||
@ -840,6 +860,7 @@ lpfc_get_hba_info(struct lpfc_hba *phba,
|
||||
*mvpi = pmb->un.varRdConfig.max_vpi;
|
||||
if (avpi)
|
||||
*avpi = pmb->un.varRdConfig.avail_vpi;
|
||||
}
|
||||
|
||||
mempool_free(pmboxq, phba->mbox_mem_pool);
|
||||
return 1;
|
||||
@ -2844,14 +2865,38 @@ LPFC_ATTR_RW(poll_tmo, 10, 1, 255,
|
||||
/*
|
||||
# lpfc_use_msi: Use MSI (Message Signaled Interrupts) in systems that
|
||||
# support this feature
|
||||
# 0 = MSI disabled
|
||||
# 0 = MSI disabled (default)
|
||||
# 1 = MSI enabled
|
||||
# 2 = MSI-X enabled (default)
|
||||
# Value range is [0,2]. Default value is 2.
|
||||
# 2 = MSI-X enabled
|
||||
# Value range is [0,2]. Default value is 0.
|
||||
*/
|
||||
LPFC_ATTR_R(use_msi, 2, 0, 2, "Use Message Signaled Interrupts (1) or "
|
||||
LPFC_ATTR_R(use_msi, 0, 0, 2, "Use Message Signaled Interrupts (1) or "
|
||||
"MSI-X (2), if possible");
|
||||
|
||||
/*
|
||||
# lpfc_fcp_imax: Set the maximum number of fast-path FCP interrupts per second
|
||||
#
|
||||
# Value range is [636,651042]. Default value is 10000.
|
||||
*/
|
||||
LPFC_ATTR_R(fcp_imax, LPFC_FP_DEF_IMAX, LPFC_MIM_IMAX, LPFC_DMULT_CONST,
|
||||
"Set the maximum number of fast-path FCP interrupts per second");
|
||||
|
||||
/*
|
||||
# lpfc_fcp_wq_count: Set the number of fast-path FCP work queues
|
||||
#
|
||||
# Value range is [1,31]. Default value is 4.
|
||||
*/
|
||||
LPFC_ATTR_R(fcp_wq_count, LPFC_FP_WQN_DEF, LPFC_FP_WQN_MIN, LPFC_FP_WQN_MAX,
|
||||
"Set the number of fast-path FCP work queues, if possible");
|
||||
|
||||
/*
|
||||
# lpfc_fcp_eq_count: Set the number of fast-path FCP event queues
|
||||
#
|
||||
# Value range is [1,7]. Default value is 1.
|
||||
*/
|
||||
LPFC_ATTR_R(fcp_eq_count, LPFC_FP_EQN_DEF, LPFC_FP_EQN_MIN, LPFC_FP_EQN_MAX,
|
||||
"Set the number of fast-path FCP event queues, if possible");
|
||||
|
||||
/*
|
||||
# lpfc_enable_hba_reset: Allow or prevent HBA resets to the hardware.
|
||||
# 0 = HBA resets disabled
|
||||
@ -2969,6 +3014,9 @@ struct device_attribute *lpfc_hba_attrs[] = {
|
||||
&dev_attr_lpfc_poll,
|
||||
&dev_attr_lpfc_poll_tmo,
|
||||
&dev_attr_lpfc_use_msi,
|
||||
&dev_attr_lpfc_fcp_imax,
|
||||
&dev_attr_lpfc_fcp_wq_count,
|
||||
&dev_attr_lpfc_fcp_eq_count,
|
||||
&dev_attr_lpfc_enable_bg,
|
||||
&dev_attr_lpfc_soft_wwnn,
|
||||
&dev_attr_lpfc_soft_wwpn,
|
||||
@ -4105,6 +4153,9 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
|
||||
lpfc_poll_tmo_init(phba, lpfc_poll_tmo);
|
||||
lpfc_enable_npiv_init(phba, lpfc_enable_npiv);
|
||||
lpfc_use_msi_init(phba, lpfc_use_msi);
|
||||
lpfc_fcp_imax_init(phba, lpfc_fcp_imax);
|
||||
lpfc_fcp_wq_count_init(phba, lpfc_fcp_wq_count);
|
||||
lpfc_fcp_eq_count_init(phba, lpfc_fcp_eq_count);
|
||||
lpfc_enable_hba_reset_init(phba, lpfc_enable_hba_reset);
|
||||
lpfc_enable_hba_heartbeat_init(phba, lpfc_enable_hba_heartbeat);
|
||||
lpfc_enable_bg_init(phba, lpfc_enable_bg);
|
||||
|
@ -35,17 +35,19 @@ int lpfc_config_msi(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
int lpfc_read_sparam(struct lpfc_hba *, LPFC_MBOXQ_t *, int);
|
||||
void lpfc_read_config(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
void lpfc_read_lnk_stat(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
int lpfc_reg_login(struct lpfc_hba *, uint16_t, uint32_t, uint8_t *,
|
||||
int lpfc_reg_rpi(struct lpfc_hba *, uint16_t, uint32_t, uint8_t *,
|
||||
LPFC_MBOXQ_t *, uint32_t);
|
||||
void lpfc_unreg_login(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *);
|
||||
void lpfc_unreg_did(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *);
|
||||
void lpfc_reg_vpi(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *);
|
||||
void lpfc_reg_vpi(struct lpfc_vport *, LPFC_MBOXQ_t *);
|
||||
void lpfc_unreg_vpi(struct lpfc_hba *, uint16_t, LPFC_MBOXQ_t *);
|
||||
void lpfc_init_link(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t);
|
||||
void lpfc_request_features(struct lpfc_hba *, struct lpfcMboxq *);
|
||||
|
||||
struct lpfc_vport *lpfc_find_vport_by_did(struct lpfc_hba *, uint32_t);
|
||||
void lpfc_cleanup_rpis(struct lpfc_vport *, int);
|
||||
int lpfc_linkdown(struct lpfc_hba *);
|
||||
void lpfc_linkdown_port(struct lpfc_vport *);
|
||||
void lpfc_port_link_failure(struct lpfc_vport *);
|
||||
void lpfc_mbx_cmpl_read_la(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
|
||||
@ -54,6 +56,7 @@ void lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
void lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
void lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
void lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
void lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
void lpfc_enqueue_node(struct lpfc_vport *, struct lpfc_nodelist *);
|
||||
void lpfc_dequeue_node(struct lpfc_vport *, struct lpfc_nodelist *);
|
||||
struct lpfc_nodelist *lpfc_enable_node(struct lpfc_vport *,
|
||||
@ -149,15 +152,19 @@ int lpfc_online(struct lpfc_hba *);
|
||||
void lpfc_unblock_mgmt_io(struct lpfc_hba *);
|
||||
void lpfc_offline_prep(struct lpfc_hba *);
|
||||
void lpfc_offline(struct lpfc_hba *);
|
||||
void lpfc_reset_hba(struct lpfc_hba *);
|
||||
|
||||
int lpfc_sli_setup(struct lpfc_hba *);
|
||||
int lpfc_sli_queue_setup(struct lpfc_hba *);
|
||||
|
||||
void lpfc_handle_eratt(struct lpfc_hba *);
|
||||
void lpfc_handle_latt(struct lpfc_hba *);
|
||||
irqreturn_t lpfc_intr_handler(int, void *);
|
||||
irqreturn_t lpfc_sp_intr_handler(int, void *);
|
||||
irqreturn_t lpfc_fp_intr_handler(int, void *);
|
||||
irqreturn_t lpfc_sli_intr_handler(int, void *);
|
||||
irqreturn_t lpfc_sli_sp_intr_handler(int, void *);
|
||||
irqreturn_t lpfc_sli_fp_intr_handler(int, void *);
|
||||
irqreturn_t lpfc_sli4_intr_handler(int, void *);
|
||||
irqreturn_t lpfc_sli4_sp_intr_handler(int, void *);
|
||||
irqreturn_t lpfc_sli4_fp_intr_handler(int, void *);
|
||||
|
||||
void lpfc_read_rev(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
void lpfc_config_ring(struct lpfc_hba *, int, LPFC_MBOXQ_t *);
|
||||
@ -165,16 +172,32 @@ void lpfc_config_port(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
void lpfc_kill_board(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
void lpfc_mbox_put(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
LPFC_MBOXQ_t *lpfc_mbox_get(struct lpfc_hba *);
|
||||
void __lpfc_mbox_cmpl_put(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
void lpfc_mbox_cmpl_put(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
int lpfc_mbox_cmd_check(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
int lpfc_mbox_dev_check(struct lpfc_hba *);
|
||||
int lpfc_mbox_tmo_val(struct lpfc_hba *, int);
|
||||
void lpfc_init_vfi(struct lpfcMboxq *, struct lpfc_vport *);
|
||||
void lpfc_reg_vfi(struct lpfcMboxq *, struct lpfc_vport *, dma_addr_t);
|
||||
void lpfc_init_vpi(struct lpfcMboxq *, uint16_t);
|
||||
void lpfc_unreg_vfi(struct lpfcMboxq *, uint16_t);
|
||||
void lpfc_reg_fcfi(struct lpfc_hba *, struct lpfcMboxq *);
|
||||
void lpfc_unreg_fcfi(struct lpfcMboxq *, uint16_t);
|
||||
void lpfc_resume_rpi(struct lpfcMboxq *, struct lpfc_nodelist *);
|
||||
|
||||
void lpfc_config_hbq(struct lpfc_hba *, uint32_t, struct lpfc_hbq_init *,
|
||||
uint32_t , LPFC_MBOXQ_t *);
|
||||
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 *);
|
||||
void lpfc_sli4_build_dflt_fcf_record(struct lpfc_hba *, struct fcf_record *,
|
||||
uint16_t);
|
||||
void lpfc_unregister_unused_fcf(struct lpfc_hba *);
|
||||
|
||||
int lpfc_mem_alloc(struct lpfc_hba *);
|
||||
int lpfc_mem_alloc(struct lpfc_hba *, int align);
|
||||
void lpfc_mem_free(struct lpfc_hba *);
|
||||
void lpfc_mem_free_all(struct lpfc_hba *);
|
||||
void lpfc_stop_vport_timers(struct lpfc_vport *);
|
||||
|
||||
void lpfc_poll_timeout(unsigned long ptr);
|
||||
@ -198,12 +221,13 @@ int lpfc_sli_host_down(struct lpfc_vport *);
|
||||
int lpfc_sli_hba_down(struct lpfc_hba *);
|
||||
int lpfc_sli_issue_mbox(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t);
|
||||
int lpfc_sli_handle_mb_event(struct lpfc_hba *);
|
||||
int lpfc_sli_flush_mbox_queue(struct lpfc_hba *);
|
||||
void lpfc_sli_mbox_sys_shutdown(struct lpfc_hba *);
|
||||
int lpfc_sli_check_eratt(struct lpfc_hba *);
|
||||
int lpfc_sli_handle_slow_ring_event(struct lpfc_hba *,
|
||||
void lpfc_sli_handle_slow_ring_event(struct lpfc_hba *,
|
||||
struct lpfc_sli_ring *, uint32_t);
|
||||
int lpfc_sli4_handle_received_buffer(struct lpfc_hba *);
|
||||
void lpfc_sli_def_mbox_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
int lpfc_sli_issue_iocb(struct lpfc_hba *, struct lpfc_sli_ring *,
|
||||
int lpfc_sli_issue_iocb(struct lpfc_hba *, uint32_t,
|
||||
struct lpfc_iocbq *, uint32_t);
|
||||
void lpfc_sli_pcimem_bcopy(void *, void *, uint32_t);
|
||||
void lpfc_sli_abort_iocb_ring(struct lpfc_hba *, struct lpfc_sli_ring *);
|
||||
@ -237,7 +261,7 @@ struct lpfc_nodelist *lpfc_findnode_wwpn(struct lpfc_vport *,
|
||||
|
||||
int lpfc_sli_issue_mbox_wait(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t);
|
||||
|
||||
int lpfc_sli_issue_iocb_wait(struct lpfc_hba *, struct lpfc_sli_ring *,
|
||||
int lpfc_sli_issue_iocb_wait(struct lpfc_hba *, uint32_t,
|
||||
struct lpfc_iocbq *, struct lpfc_iocbq *,
|
||||
uint32_t);
|
||||
void lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *, struct lpfc_iocbq *,
|
||||
@ -254,6 +278,12 @@ void lpfc_in_buf_free(struct lpfc_hba *, struct lpfc_dmabuf *);
|
||||
const char* lpfc_info(struct Scsi_Host *);
|
||||
int lpfc_scan_finished(struct Scsi_Host *, unsigned long);
|
||||
|
||||
int lpfc_init_api_table_setup(struct lpfc_hba *, uint8_t);
|
||||
int lpfc_sli_api_table_setup(struct lpfc_hba *, uint8_t);
|
||||
int lpfc_scsi_api_table_setup(struct lpfc_hba *, uint8_t);
|
||||
int lpfc_mbox_api_table_setup(struct lpfc_hba *, uint8_t);
|
||||
int lpfc_api_table_setup(struct lpfc_hba *, uint8_t);
|
||||
|
||||
void lpfc_get_cfgparam(struct lpfc_hba *);
|
||||
void lpfc_get_vport_cfgparam(struct lpfc_vport *);
|
||||
int lpfc_alloc_sysfs_attr(struct lpfc_vport *);
|
||||
@ -314,8 +344,15 @@ lpfc_send_els_failure_event(struct lpfc_hba *, struct lpfc_iocbq *,
|
||||
struct lpfc_iocbq *);
|
||||
struct lpfc_fast_path_event *lpfc_alloc_fast_evt(struct lpfc_hba *);
|
||||
void lpfc_free_fast_evt(struct lpfc_hba *, struct lpfc_fast_path_event *);
|
||||
void lpfc_create_static_vport(struct lpfc_hba *);
|
||||
void lpfc_stop_hba_timers(struct lpfc_hba *);
|
||||
void lpfc_stop_port(struct lpfc_hba *);
|
||||
void lpfc_parse_fcoe_conf(struct lpfc_hba *, uint8_t *, uint32_t);
|
||||
int lpfc_parse_vpd(struct lpfc_hba *, uint8_t *, int);
|
||||
void lpfc_start_fdiscs(struct lpfc_hba *phba);
|
||||
|
||||
#define ScsiResult(host_code, scsi_code) (((host_code) << 16) | scsi_code)
|
||||
#define HBA_EVENT_RSCN 5
|
||||
#define HBA_EVENT_LINK_UP 2
|
||||
#define HBA_EVENT_LINK_DOWN 3
|
||||
|
||||
|
@ -32,8 +32,10 @@
|
||||
#include <scsi/scsi_host.h>
|
||||
#include <scsi/scsi_transport_fc.h>
|
||||
|
||||
#include "lpfc_hw4.h"
|
||||
#include "lpfc_hw.h"
|
||||
#include "lpfc_sli.h"
|
||||
#include "lpfc_sli4.h"
|
||||
#include "lpfc_nl.h"
|
||||
#include "lpfc_disc.h"
|
||||
#include "lpfc_scsi.h"
|
||||
|
@ -33,8 +33,10 @@
|
||||
#include <scsi/scsi_host.h>
|
||||
#include <scsi/scsi_transport_fc.h>
|
||||
|
||||
#include "lpfc_hw4.h"
|
||||
#include "lpfc_hw.h"
|
||||
#include "lpfc_sli.h"
|
||||
#include "lpfc_sli4.h"
|
||||
#include "lpfc_nl.h"
|
||||
#include "lpfc_disc.h"
|
||||
#include "lpfc_scsi.h"
|
||||
|
@ -28,8 +28,10 @@
|
||||
#include <scsi/scsi_host.h>
|
||||
#include <scsi/scsi_transport_fc.h>
|
||||
|
||||
#include "lpfc_hw4.h"
|
||||
#include "lpfc_hw.h"
|
||||
#include "lpfc_sli.h"
|
||||
#include "lpfc_sli4.h"
|
||||
#include "lpfc_nl.h"
|
||||
#include "lpfc_disc.h"
|
||||
#include "lpfc_scsi.h"
|
||||
@ -220,7 +222,7 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
|
||||
icmd->un.elsreq64.myID = vport->fc_myDID;
|
||||
|
||||
/* For ELS_REQUEST64_CR, use the VPI by default */
|
||||
icmd->ulpContext = vport->vpi;
|
||||
icmd->ulpContext = vport->vpi + phba->vpi_base;
|
||||
icmd->ulpCt_h = 0;
|
||||
/* The CT field must be 0=INVALID_RPI for the ECHO cmd */
|
||||
if (elscmd == ELS_CMD_ECHO)
|
||||
|
@ -29,10 +29,12 @@
|
||||
#include <scsi/scsi_host.h>
|
||||
#include <scsi/scsi_transport_fc.h>
|
||||
|
||||
#include "lpfc_hw4.h"
|
||||
#include "lpfc_hw.h"
|
||||
#include "lpfc_nl.h"
|
||||
#include "lpfc_disc.h"
|
||||
#include "lpfc_sli.h"
|
||||
#include "lpfc_sli4.h"
|
||||
#include "lpfc_scsi.h"
|
||||
#include "lpfc.h"
|
||||
#include "lpfc_logmsg.h"
|
||||
@ -491,6 +493,10 @@ lpfc_work_done(struct lpfc_hba *phba)
|
||||
phba->work_ha = 0;
|
||||
spin_unlock_irq(&phba->hbalock);
|
||||
|
||||
/* First, try to post the next mailbox command to SLI4 device */
|
||||
if (phba->pci_dev_grp == LPFC_PCI_DEV_OC)
|
||||
lpfc_sli4_post_async_mbox(phba);
|
||||
|
||||
if (ha_copy & HA_ERATT)
|
||||
/* Handle the error attention event */
|
||||
lpfc_handle_eratt(phba);
|
||||
@ -501,9 +507,27 @@ lpfc_work_done(struct lpfc_hba *phba)
|
||||
if (ha_copy & HA_LATT)
|
||||
lpfc_handle_latt(phba);
|
||||
|
||||
/* Process SLI4 events */
|
||||
if (phba->pci_dev_grp == LPFC_PCI_DEV_OC) {
|
||||
if (phba->hba_flag & FCP_XRI_ABORT_EVENT)
|
||||
lpfc_sli4_fcp_xri_abort_event_proc(phba);
|
||||
if (phba->hba_flag & ELS_XRI_ABORT_EVENT)
|
||||
lpfc_sli4_els_xri_abort_event_proc(phba);
|
||||
if (phba->hba_flag & ASYNC_EVENT)
|
||||
lpfc_sli4_async_event_proc(phba);
|
||||
if (phba->hba_flag & HBA_POST_RECEIVE_BUFFER) {
|
||||
spin_lock_irq(&phba->hbalock);
|
||||
phba->hba_flag &= ~HBA_POST_RECEIVE_BUFFER;
|
||||
spin_unlock_irq(&phba->hbalock);
|
||||
lpfc_sli_hbqbuf_add_hbqs(phba, LPFC_ELS_HBQ);
|
||||
}
|
||||
if (phba->hba_flag & HBA_RECEIVE_BUFFER)
|
||||
lpfc_sli4_handle_received_buffer(phba);
|
||||
}
|
||||
|
||||
vports = lpfc_create_vport_work_array(phba);
|
||||
if (vports != NULL)
|
||||
for(i = 0; i <= phba->max_vpi; i++) {
|
||||
for (i = 0; i <= phba->max_vports; i++) {
|
||||
/*
|
||||
* We could have no vports in array if unloading, so if
|
||||
* this happens then just use the pport
|
||||
@ -2556,7 +2580,8 @@ lpfc_issue_clear_la(struct lpfc_hba *phba, struct lpfc_vport *vport)
|
||||
* clear_la then don't send it.
|
||||
*/
|
||||
if ((phba->link_state >= LPFC_CLEAR_LA) ||
|
||||
(vport->port_type != LPFC_PHYSICAL_PORT))
|
||||
(vport->port_type != LPFC_PHYSICAL_PORT) ||
|
||||
(phba->sli_rev == LPFC_SLI_REV4))
|
||||
return;
|
||||
|
||||
/* Link up discovery */
|
||||
@ -2585,7 +2610,7 @@ lpfc_issue_reg_vpi(struct lpfc_hba *phba, struct lpfc_vport *vport)
|
||||
|
||||
regvpimbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
|
||||
if (regvpimbox) {
|
||||
lpfc_reg_vpi(phba, vport->vpi, vport->fc_myDID, regvpimbox);
|
||||
lpfc_reg_vpi(vport, regvpimbox);
|
||||
regvpimbox->mbox_cmpl = lpfc_mbx_cmpl_reg_vpi;
|
||||
regvpimbox->vport = vport;
|
||||
if (lpfc_sli_issue_mbox(phba, regvpimbox, MBX_NOWAIT)
|
||||
@ -2645,7 +2670,8 @@ lpfc_disc_start(struct lpfc_vport *vport)
|
||||
*/
|
||||
if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
|
||||
!(vport->fc_flag & FC_PT2PT) &&
|
||||
!(vport->fc_flag & FC_RSCN_MODE)) {
|
||||
!(vport->fc_flag & FC_RSCN_MODE) &&
|
||||
(phba->sli_rev < LPFC_SLI_REV4)) {
|
||||
lpfc_issue_reg_vpi(phba, vport);
|
||||
return;
|
||||
}
|
||||
|
@ -470,6 +470,35 @@ struct serv_parm { /* Structure is in Big Endian format */
|
||||
uint8_t vendorVersion[16];
|
||||
};
|
||||
|
||||
/*
|
||||
* Virtual Fabric Tagging Header
|
||||
*/
|
||||
struct fc_vft_header {
|
||||
uint32_t word0;
|
||||
#define fc_vft_hdr_r_ctl_SHIFT 24
|
||||
#define fc_vft_hdr_r_ctl_MASK 0xFF
|
||||
#define fc_vft_hdr_r_ctl_WORD word0
|
||||
#define fc_vft_hdr_ver_SHIFT 22
|
||||
#define fc_vft_hdr_ver_MASK 0x3
|
||||
#define fc_vft_hdr_ver_WORD word0
|
||||
#define fc_vft_hdr_type_SHIFT 18
|
||||
#define fc_vft_hdr_type_MASK 0xF
|
||||
#define fc_vft_hdr_type_WORD word0
|
||||
#define fc_vft_hdr_e_SHIFT 16
|
||||
#define fc_vft_hdr_e_MASK 0x1
|
||||
#define fc_vft_hdr_e_WORD word0
|
||||
#define fc_vft_hdr_priority_SHIFT 13
|
||||
#define fc_vft_hdr_priority_MASK 0x7
|
||||
#define fc_vft_hdr_priority_WORD word0
|
||||
#define fc_vft_hdr_vf_id_SHIFT 1
|
||||
#define fc_vft_hdr_vf_id_MASK 0xFFF
|
||||
#define fc_vft_hdr_vf_id_WORD word0
|
||||
uint32_t word1;
|
||||
#define fc_vft_hdr_hopct_SHIFT 24
|
||||
#define fc_vft_hdr_hopct_MASK 0xFF
|
||||
#define fc_vft_hdr_hopct_WORD word1
|
||||
};
|
||||
|
||||
/*
|
||||
* Extended Link Service LS_COMMAND codes (Payload Word 0)
|
||||
*/
|
||||
@ -1152,6 +1181,9 @@ typedef struct {
|
||||
#define PCI_DEVICE_ID_HORNET 0xfe05
|
||||
#define PCI_DEVICE_ID_ZEPHYR_SCSP 0xfe11
|
||||
#define PCI_DEVICE_ID_ZEPHYR_DCSP 0xfe12
|
||||
#define PCI_VENDOR_ID_SERVERENGINE 0x19a2
|
||||
#define PCI_DEVICE_ID_TIGERSHARK 0x0704
|
||||
#define PCI_DEVICE_ID_TIGERSHARK_S 0x0705
|
||||
|
||||
#define JEDEC_ID_ADDRESS 0x0080001c
|
||||
#define FIREFLY_JEDEC_ID 0x1ACC
|
||||
@ -1342,15 +1374,21 @@ typedef struct { /* FireFly BIU registers */
|
||||
#define MBX_READ_LA64 0x95
|
||||
#define MBX_REG_VPI 0x96
|
||||
#define MBX_UNREG_VPI 0x97
|
||||
#define MBX_REG_VNPID 0x96
|
||||
#define MBX_UNREG_VNPID 0x97
|
||||
|
||||
#define MBX_WRITE_WWN 0x98
|
||||
#define MBX_SET_DEBUG 0x99
|
||||
#define MBX_LOAD_EXP_ROM 0x9C
|
||||
|
||||
#define MBX_MAX_CMDS 0x9D
|
||||
#define MBX_SLI4_CONFIG 0x9B
|
||||
#define MBX_SLI4_REQ_FTRS 0x9D
|
||||
#define MBX_MAX_CMDS 0x9E
|
||||
#define MBX_RESUME_RPI 0x9E
|
||||
#define MBX_SLI2_CMD_MASK 0x80
|
||||
#define MBX_REG_VFI 0x9F
|
||||
#define MBX_REG_FCFI 0xA0
|
||||
#define MBX_UNREG_VFI 0xA1
|
||||
#define MBX_UNREG_FCFI 0xA2
|
||||
#define MBX_INIT_VFI 0xA3
|
||||
#define MBX_INIT_VPI 0xA4
|
||||
|
||||
/* IOCB Commands */
|
||||
|
||||
@ -1440,6 +1478,16 @@ typedef struct { /* FireFly BIU registers */
|
||||
#define CMD_IOCB_LOGENTRY_CN 0x94
|
||||
#define CMD_IOCB_LOGENTRY_ASYNC_CN 0x96
|
||||
|
||||
/* Unhandled Data Security SLI Commands */
|
||||
#define DSSCMD_IWRITE64_CR 0xD8
|
||||
#define DSSCMD_IWRITE64_CX 0xD9
|
||||
#define DSSCMD_IREAD64_CR 0xDA
|
||||
#define DSSCMD_IREAD64_CX 0xDB
|
||||
#define DSSCMD_INVALIDATE_DEK 0xDC
|
||||
#define DSSCMD_SET_KEK 0xDD
|
||||
#define DSSCMD_GET_KEK_ID 0xDE
|
||||
#define DSSCMD_GEN_XFER 0xDF
|
||||
|
||||
#define CMD_MAX_IOCB_CMD 0xE6
|
||||
#define CMD_IOCB_MASK 0xff
|
||||
|
||||
@ -1466,6 +1514,7 @@ typedef struct { /* FireFly BIU registers */
|
||||
#define MBXERR_BAD_RCV_LENGTH 14
|
||||
#define MBXERR_DMA_ERROR 15
|
||||
#define MBXERR_ERROR 16
|
||||
#define MBXERR_LINK_DOWN 0x33
|
||||
#define MBX_NOT_FINISHED 255
|
||||
|
||||
#define MBX_BUSY 0xffffff /* Attempted cmd to busy Mailbox */
|
||||
@ -1504,32 +1553,6 @@ struct ulp_bde {
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ulp_bde64 { /* SLI-2 */
|
||||
union ULP_BDE_TUS {
|
||||
uint32_t w;
|
||||
struct {
|
||||
#ifdef __BIG_ENDIAN_BITFIELD
|
||||
uint32_t bdeFlags:8; /* BDE Flags 0 IS A SUPPORTED
|
||||
VALUE !! */
|
||||
uint32_t bdeSize:24; /* Size of buffer (in bytes) */
|
||||
#else /* __LITTLE_ENDIAN_BITFIELD */
|
||||
uint32_t bdeSize:24; /* Size of buffer (in bytes) */
|
||||
uint32_t bdeFlags:8; /* BDE Flags 0 IS A SUPPORTED
|
||||
VALUE !! */
|
||||
#endif
|
||||
#define BUFF_TYPE_BDE_64 0x00 /* BDE (Host_resident) */
|
||||
#define BUFF_TYPE_BDE_IMMED 0x01 /* Immediate Data BDE */
|
||||
#define BUFF_TYPE_BDE_64P 0x02 /* BDE (Port-resident) */
|
||||
#define BUFF_TYPE_BDE_64I 0x08 /* Input BDE (Host-resident) */
|
||||
#define BUFF_TYPE_BDE_64IP 0x0A /* Input BDE (Port-resident) */
|
||||
#define BUFF_TYPE_BLP_64 0x40 /* BLP (Host-resident) */
|
||||
#define BUFF_TYPE_BLP_64P 0x42 /* BLP (Port-resident) */
|
||||
} f;
|
||||
} tus;
|
||||
uint32_t addrLow;
|
||||
uint32_t addrHigh;
|
||||
};
|
||||
|
||||
typedef struct ULP_BDL { /* SLI-2 */
|
||||
#ifdef __BIG_ENDIAN_BITFIELD
|
||||
uint32_t bdeFlags:8; /* BDL Flags */
|
||||
@ -2287,7 +2310,7 @@ typedef struct {
|
||||
uint32_t rsvd3;
|
||||
uint32_t rsvd4;
|
||||
uint32_t rsvd5;
|
||||
uint16_t rsvd6;
|
||||
uint16_t vfi;
|
||||
uint16_t vpi;
|
||||
#else /* __LITTLE_ENDIAN */
|
||||
uint32_t rsvd1;
|
||||
@ -2297,7 +2320,7 @@ typedef struct {
|
||||
uint32_t rsvd4;
|
||||
uint32_t rsvd5;
|
||||
uint16_t vpi;
|
||||
uint16_t rsvd6;
|
||||
uint16_t vfi;
|
||||
#endif
|
||||
} REG_VPI_VAR;
|
||||
|
||||
@ -2457,7 +2480,7 @@ typedef struct {
|
||||
uint32_t entry_index:16;
|
||||
#endif
|
||||
|
||||
uint32_t rsvd1;
|
||||
uint32_t sli4_length;
|
||||
uint32_t word_cnt;
|
||||
uint32_t resp_offset;
|
||||
} DUMP_VAR;
|
||||
@ -2470,9 +2493,32 @@ typedef struct {
|
||||
#define DMP_RSP_OFFSET 0x14 /* word 5 contains first word of rsp */
|
||||
#define DMP_RSP_SIZE 0x6C /* maximum of 27 words of rsp data */
|
||||
|
||||
#define DMP_REGION_VPORT 0x16 /* VPort info region */
|
||||
#define DMP_VPORT_REGION_SIZE 0x200
|
||||
#define DMP_MBOX_OFFSET_WORD 0x5
|
||||
|
||||
#define DMP_REGION_FCOEPARAM 0x17 /* fcoe param region */
|
||||
#define DMP_FCOEPARAM_RGN_SIZE 0x400
|
||||
|
||||
#define WAKE_UP_PARMS_REGION_ID 4
|
||||
#define WAKE_UP_PARMS_WORD_SIZE 15
|
||||
|
||||
struct vport_rec {
|
||||
uint8_t wwpn[8];
|
||||
uint8_t wwnn[8];
|
||||
};
|
||||
|
||||
#define VPORT_INFO_SIG 0x32324752
|
||||
#define VPORT_INFO_REV_MASK 0xff
|
||||
#define VPORT_INFO_REV 0x1
|
||||
#define MAX_STATIC_VPORT_COUNT 16
|
||||
struct static_vport_info {
|
||||
uint32_t signature;
|
||||
uint32_t rev;
|
||||
struct vport_rec vport_list[MAX_STATIC_VPORT_COUNT];
|
||||
uint32_t resvd[66];
|
||||
};
|
||||
|
||||
/* Option rom version structure */
|
||||
struct prog_id {
|
||||
#ifdef __BIG_ENDIAN_BITFIELD
|
||||
@ -2697,7 +2743,9 @@ typedef struct {
|
||||
#endif
|
||||
|
||||
#ifdef __BIG_ENDIAN_BITFIELD
|
||||
uint32_t rsvd1 : 23; /* Reserved */
|
||||
uint32_t rsvd1 : 19; /* Reserved */
|
||||
uint32_t cdss : 1; /* Configure Data Security SLI */
|
||||
uint32_t rsvd2 : 3; /* Reserved */
|
||||
uint32_t cbg : 1; /* Configure BlockGuard */
|
||||
uint32_t cmv : 1; /* Configure Max VPIs */
|
||||
uint32_t ccrp : 1; /* Config Command Ring Polling */
|
||||
@ -2717,10 +2765,14 @@ typedef struct {
|
||||
uint32_t ccrp : 1; /* Config Command Ring Polling */
|
||||
uint32_t cmv : 1; /* Configure Max VPIs */
|
||||
uint32_t cbg : 1; /* Configure BlockGuard */
|
||||
uint32_t rsvd1 : 23; /* Reserved */
|
||||
uint32_t rsvd2 : 3; /* Reserved */
|
||||
uint32_t cdss : 1; /* Configure Data Security SLI */
|
||||
uint32_t rsvd1 : 19; /* Reserved */
|
||||
#endif
|
||||
#ifdef __BIG_ENDIAN_BITFIELD
|
||||
uint32_t rsvd2 : 23; /* Reserved */
|
||||
uint32_t rsvd3 : 19; /* Reserved */
|
||||
uint32_t gdss : 1; /* Configure Data Security SLI */
|
||||
uint32_t rsvd4 : 3; /* Reserved */
|
||||
uint32_t gbg : 1; /* Grant BlockGuard */
|
||||
uint32_t gmv : 1; /* Grant Max VPIs */
|
||||
uint32_t gcrp : 1; /* Grant Command Ring Polling */
|
||||
@ -2740,7 +2792,9 @@ typedef struct {
|
||||
uint32_t gcrp : 1; /* Grant Command Ring Polling */
|
||||
uint32_t gmv : 1; /* Grant Max VPIs */
|
||||
uint32_t gbg : 1; /* Grant BlockGuard */
|
||||
uint32_t rsvd2 : 23; /* Reserved */
|
||||
uint32_t rsvd4 : 3; /* Reserved */
|
||||
uint32_t gdss : 1; /* Configure Data Security SLI */
|
||||
uint32_t rsvd3 : 19; /* Reserved */
|
||||
#endif
|
||||
|
||||
#ifdef __BIG_ENDIAN_BITFIELD
|
||||
@ -2753,20 +2807,20 @@ typedef struct {
|
||||
|
||||
#ifdef __BIG_ENDIAN_BITFIELD
|
||||
uint32_t max_hbq : 16; /* Max HBQs Host expect to configure */
|
||||
uint32_t rsvd3 : 16; /* Max HBQs Host expect to configure */
|
||||
uint32_t rsvd5 : 16; /* Max HBQs Host expect to configure */
|
||||
#else /* __LITTLE_ENDIAN */
|
||||
uint32_t rsvd3 : 16; /* Max HBQs Host expect to configure */
|
||||
uint32_t rsvd5 : 16; /* Max HBQs Host expect to configure */
|
||||
uint32_t max_hbq : 16; /* Max HBQs Host expect to configure */
|
||||
#endif
|
||||
|
||||
uint32_t rsvd4; /* Reserved */
|
||||
uint32_t rsvd6; /* Reserved */
|
||||
|
||||
#ifdef __BIG_ENDIAN_BITFIELD
|
||||
uint32_t rsvd5 : 16; /* Reserved */
|
||||
uint32_t rsvd7 : 16; /* Reserved */
|
||||
uint32_t max_vpi : 16; /* Max number of virt N-Ports */
|
||||
#else /* __LITTLE_ENDIAN */
|
||||
uint32_t max_vpi : 16; /* Max number of virt N-Ports */
|
||||
uint32_t rsvd5 : 16; /* Reserved */
|
||||
uint32_t rsvd7 : 16; /* Reserved */
|
||||
#endif
|
||||
|
||||
} CONFIG_PORT_VAR;
|
||||
@ -3666,3 +3720,5 @@ lpfc_error_lost_link(IOCB_t *iocbp)
|
||||
#define MENLO_TIMEOUT 30
|
||||
#define SETVAR_MLOMNT 0x103107
|
||||
#define SETVAR_MLORST 0x103007
|
||||
|
||||
#define BPL_ALIGN_SZ 8 /* 8 byte alignment for bpl and mbufs */
|
||||
|
2141
drivers/scsi/lpfc/lpfc_hw4.h
Normal file
2141
drivers/scsi/lpfc/lpfc_hw4.h
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -28,8 +28,10 @@
|
||||
|
||||
#include <scsi/scsi.h>
|
||||
|
||||
#include "lpfc_hw4.h"
|
||||
#include "lpfc_hw.h"
|
||||
#include "lpfc_sli.h"
|
||||
#include "lpfc_sli4.h"
|
||||
#include "lpfc_nl.h"
|
||||
#include "lpfc_disc.h"
|
||||
#include "lpfc_scsi.h"
|
||||
|
@ -28,8 +28,10 @@
|
||||
|
||||
#include <scsi/scsi.h>
|
||||
|
||||
#include "lpfc_hw4.h"
|
||||
#include "lpfc_hw.h"
|
||||
#include "lpfc_sli.h"
|
||||
#include "lpfc_sli4.h"
|
||||
#include "lpfc_nl.h"
|
||||
#include "lpfc_disc.h"
|
||||
#include "lpfc_scsi.h"
|
||||
@ -45,7 +47,7 @@
|
||||
* @phba: HBA to allocate pools for
|
||||
*
|
||||
* Description: Creates and allocates PCI pools lpfc_scsi_dma_buf_pool,
|
||||
* lpfc_mbuf_pool, lpfc_hbq_pool. Creates and allocates kmalloc-backed mempools
|
||||
* lpfc_mbuf_pool, lpfc_hrb_pool. Creates and allocates kmalloc-backed mempools
|
||||
* for LPFC_MBOXQ_t and lpfc_nodelist. Also allocates the VPI bitmask.
|
||||
*
|
||||
* Notes: Not interrupt-safe. Must be called with no locks held. If any
|
||||
@ -56,19 +58,30 @@
|
||||
* -ENOMEM on failure (if any memory allocations fail)
|
||||
**/
|
||||
int
|
||||
lpfc_mem_alloc(struct lpfc_hba * phba)
|
||||
lpfc_mem_alloc(struct lpfc_hba *phba, int align)
|
||||
{
|
||||
struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool;
|
||||
int longs;
|
||||
int i;
|
||||
|
||||
phba->lpfc_scsi_dma_buf_pool = pci_pool_create("lpfc_scsi_dma_buf_pool",
|
||||
phba->pcidev, phba->cfg_sg_dma_buf_size, 8, 0);
|
||||
if (phba->sli_rev == LPFC_SLI_REV4)
|
||||
phba->lpfc_scsi_dma_buf_pool =
|
||||
pci_pool_create("lpfc_scsi_dma_buf_pool",
|
||||
phba->pcidev,
|
||||
phba->cfg_sg_dma_buf_size,
|
||||
phba->cfg_sg_dma_buf_size,
|
||||
0);
|
||||
else
|
||||
phba->lpfc_scsi_dma_buf_pool =
|
||||
pci_pool_create("lpfc_scsi_dma_buf_pool",
|
||||
phba->pcidev, phba->cfg_sg_dma_buf_size,
|
||||
align, 0);
|
||||
if (!phba->lpfc_scsi_dma_buf_pool)
|
||||
goto fail;
|
||||
|
||||
phba->lpfc_mbuf_pool = pci_pool_create("lpfc_mbuf_pool", phba->pcidev,
|
||||
LPFC_BPL_SIZE, 8,0);
|
||||
LPFC_BPL_SIZE,
|
||||
align, 0);
|
||||
if (!phba->lpfc_mbuf_pool)
|
||||
goto fail_free_dma_buf_pool;
|
||||
|
||||
@ -97,23 +110,31 @@ lpfc_mem_alloc(struct lpfc_hba * phba)
|
||||
sizeof(struct lpfc_nodelist));
|
||||
if (!phba->nlp_mem_pool)
|
||||
goto fail_free_mbox_pool;
|
||||
|
||||
phba->lpfc_hbq_pool = pci_pool_create("lpfc_hbq_pool",phba->pcidev,
|
||||
LPFC_BPL_SIZE, 8, 0);
|
||||
if (!phba->lpfc_hbq_pool)
|
||||
phba->lpfc_hrb_pool = pci_pool_create("lpfc_hrb_pool",
|
||||
phba->pcidev,
|
||||
LPFC_HDR_BUF_SIZE, align, 0);
|
||||
if (!phba->lpfc_hrb_pool)
|
||||
goto fail_free_nlp_mem_pool;
|
||||
phba->lpfc_drb_pool = pci_pool_create("lpfc_drb_pool",
|
||||
phba->pcidev,
|
||||
LPFC_DATA_BUF_SIZE, align, 0);
|
||||
if (!phba->lpfc_drb_pool)
|
||||
goto fail_free_hbq_pool;
|
||||
|
||||
/* 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);
|
||||
if (!phba->vpi_bmask)
|
||||
goto fail_free_hbq_pool;
|
||||
goto fail_free_dbq_pool;
|
||||
|
||||
return 0;
|
||||
|
||||
fail_free_dbq_pool:
|
||||
pci_pool_destroy(phba->lpfc_drb_pool);
|
||||
phba->lpfc_drb_pool = NULL;
|
||||
fail_free_hbq_pool:
|
||||
lpfc_sli_hbqbuf_free_all(phba);
|
||||
pci_pool_destroy(phba->lpfc_hbq_pool);
|
||||
pci_pool_destroy(phba->lpfc_hrb_pool);
|
||||
phba->lpfc_hrb_pool = NULL;
|
||||
fail_free_nlp_mem_pool:
|
||||
mempool_destroy(phba->nlp_mem_pool);
|
||||
phba->nlp_mem_pool = NULL;
|
||||
@ -136,27 +157,73 @@ lpfc_mem_alloc(struct lpfc_hba * phba)
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_mem_free - Frees all PCI and memory allocated by lpfc_mem_alloc
|
||||
* lpfc_mem_free - Frees memory allocated by lpfc_mem_alloc
|
||||
* @phba: HBA to free memory for
|
||||
*
|
||||
* Description: Frees PCI pools lpfc_scsi_dma_buf_pool, lpfc_mbuf_pool,
|
||||
* lpfc_hbq_pool. Frees kmalloc-backed mempools for LPFC_MBOXQ_t and
|
||||
* lpfc_nodelist. Also frees the VPI bitmask
|
||||
* Description: Free the memory allocated by lpfc_mem_alloc routine. This
|
||||
* routine is a the counterpart of lpfc_mem_alloc.
|
||||
*
|
||||
* Returns: None
|
||||
**/
|
||||
void
|
||||
lpfc_mem_free(struct lpfc_hba * phba)
|
||||
lpfc_mem_free(struct lpfc_hba *phba)
|
||||
{
|
||||
int i;
|
||||
struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool;
|
||||
|
||||
/* Free VPI bitmask memory */
|
||||
kfree(phba->vpi_bmask);
|
||||
|
||||
/* Free HBQ pools */
|
||||
lpfc_sli_hbqbuf_free_all(phba);
|
||||
pci_pool_destroy(phba->lpfc_drb_pool);
|
||||
phba->lpfc_drb_pool = NULL;
|
||||
pci_pool_destroy(phba->lpfc_hrb_pool);
|
||||
phba->lpfc_hrb_pool = NULL;
|
||||
|
||||
/* Free NLP memory pool */
|
||||
mempool_destroy(phba->nlp_mem_pool);
|
||||
phba->nlp_mem_pool = NULL;
|
||||
|
||||
/* Free mbox memory pool */
|
||||
mempool_destroy(phba->mbox_mem_pool);
|
||||
phba->mbox_mem_pool = NULL;
|
||||
|
||||
/* Free MBUF memory pool */
|
||||
for (i = 0; i < pool->current_count; i++)
|
||||
pci_pool_free(phba->lpfc_mbuf_pool, pool->elements[i].virt,
|
||||
pool->elements[i].phys);
|
||||
kfree(pool->elements);
|
||||
|
||||
pci_pool_destroy(phba->lpfc_mbuf_pool);
|
||||
phba->lpfc_mbuf_pool = NULL;
|
||||
|
||||
/* Free DMA buffer memory pool */
|
||||
pci_pool_destroy(phba->lpfc_scsi_dma_buf_pool);
|
||||
phba->lpfc_scsi_dma_buf_pool = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_mem_free_all - Frees all PCI and driver memory
|
||||
* @phba: HBA to free memory for
|
||||
*
|
||||
* Description: Free memory from PCI and driver memory pools and also those
|
||||
* used : lpfc_scsi_dma_buf_pool, lpfc_mbuf_pool, lpfc_hrb_pool. Frees
|
||||
* kmalloc-backed mempools for LPFC_MBOXQ_t and lpfc_nodelist. Also frees
|
||||
* the VPI bitmask.
|
||||
*
|
||||
* Returns: None
|
||||
**/
|
||||
void
|
||||
lpfc_mem_free_all(struct lpfc_hba *phba)
|
||||
{
|
||||
struct lpfc_sli *psli = &phba->sli;
|
||||
struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool;
|
||||
LPFC_MBOXQ_t *mbox, *next_mbox;
|
||||
struct lpfc_dmabuf *mp;
|
||||
int i;
|
||||
|
||||
kfree(phba->vpi_bmask);
|
||||
lpfc_sli_hbqbuf_free_all(phba);
|
||||
|
||||
/* Free memory used in mailbox queue back to mailbox memory pool */
|
||||
list_for_each_entry_safe(mbox, next_mbox, &psli->mboxq, list) {
|
||||
mp = (struct lpfc_dmabuf *) (mbox->context1);
|
||||
if (mp) {
|
||||
@ -166,6 +233,7 @@ lpfc_mem_free(struct lpfc_hba * phba)
|
||||
list_del(&mbox->list);
|
||||
mempool_free(mbox, phba->mbox_mem_pool);
|
||||
}
|
||||
/* Free memory used in mailbox cmpl list back to mailbox memory pool */
|
||||
list_for_each_entry_safe(mbox, next_mbox, &psli->mboxq_cmpl, list) {
|
||||
mp = (struct lpfc_dmabuf *) (mbox->context1);
|
||||
if (mp) {
|
||||
@ -175,8 +243,10 @@ lpfc_mem_free(struct lpfc_hba * phba)
|
||||
list_del(&mbox->list);
|
||||
mempool_free(mbox, phba->mbox_mem_pool);
|
||||
}
|
||||
|
||||
/* Free the active mailbox command back to the mailbox memory pool */
|
||||
spin_lock_irq(&phba->hbalock);
|
||||
psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
|
||||
spin_unlock_irq(&phba->hbalock);
|
||||
if (psli->mbox_active) {
|
||||
mbox = psli->mbox_active;
|
||||
mp = (struct lpfc_dmabuf *) (mbox->context1);
|
||||
@ -188,27 +258,14 @@ lpfc_mem_free(struct lpfc_hba * phba)
|
||||
psli->mbox_active = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < pool->current_count; i++)
|
||||
pci_pool_free(phba->lpfc_mbuf_pool, pool->elements[i].virt,
|
||||
pool->elements[i].phys);
|
||||
kfree(pool->elements);
|
||||
|
||||
pci_pool_destroy(phba->lpfc_hbq_pool);
|
||||
mempool_destroy(phba->nlp_mem_pool);
|
||||
mempool_destroy(phba->mbox_mem_pool);
|
||||
|
||||
pci_pool_destroy(phba->lpfc_scsi_dma_buf_pool);
|
||||
pci_pool_destroy(phba->lpfc_mbuf_pool);
|
||||
|
||||
phba->lpfc_hbq_pool = NULL;
|
||||
phba->nlp_mem_pool = NULL;
|
||||
phba->mbox_mem_pool = NULL;
|
||||
phba->lpfc_scsi_dma_buf_pool = NULL;
|
||||
phba->lpfc_mbuf_pool = NULL;
|
||||
/* Free and destroy all the allocated memory pools */
|
||||
lpfc_mem_free(phba);
|
||||
|
||||
/* Free the iocb lookup array */
|
||||
kfree(psli->iocbq_lookup);
|
||||
psli->iocbq_lookup = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -305,7 +362,7 @@ lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
|
||||
* lpfc_els_hbq_alloc - Allocate an HBQ buffer
|
||||
* @phba: HBA to allocate HBQ buffer for
|
||||
*
|
||||
* Description: Allocates a DMA-mapped HBQ buffer from the lpfc_hbq_pool PCI
|
||||
* Description: Allocates a DMA-mapped HBQ buffer from the lpfc_hrb_pool PCI
|
||||
* pool along a non-DMA-mapped container for it.
|
||||
*
|
||||
* Notes: Not interrupt-safe. Must be called with no locks held.
|
||||
@ -323,7 +380,7 @@ lpfc_els_hbq_alloc(struct lpfc_hba *phba)
|
||||
if (!hbqbp)
|
||||
return NULL;
|
||||
|
||||
hbqbp->dbuf.virt = pci_pool_alloc(phba->lpfc_hbq_pool, GFP_KERNEL,
|
||||
hbqbp->dbuf.virt = pci_pool_alloc(phba->lpfc_hrb_pool, GFP_KERNEL,
|
||||
&hbqbp->dbuf.phys);
|
||||
if (!hbqbp->dbuf.virt) {
|
||||
kfree(hbqbp);
|
||||
@ -334,7 +391,7 @@ lpfc_els_hbq_alloc(struct lpfc_hba *phba)
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_mem_hbq_free - Frees an HBQ buffer allocated with lpfc_els_hbq_alloc
|
||||
* lpfc_els_hbq_free - Frees an HBQ buffer allocated with lpfc_els_hbq_alloc
|
||||
* @phba: HBA buffer was allocated for
|
||||
* @hbqbp: HBQ container returned by lpfc_els_hbq_alloc
|
||||
*
|
||||
@ -348,11 +405,72 @@ lpfc_els_hbq_alloc(struct lpfc_hba *phba)
|
||||
void
|
||||
lpfc_els_hbq_free(struct lpfc_hba *phba, struct hbq_dmabuf *hbqbp)
|
||||
{
|
||||
pci_pool_free(phba->lpfc_hbq_pool, hbqbp->dbuf.virt, hbqbp->dbuf.phys);
|
||||
pci_pool_free(phba->lpfc_hrb_pool, hbqbp->dbuf.virt, hbqbp->dbuf.phys);
|
||||
kfree(hbqbp);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_sli4_rb_alloc - Allocate an SLI4 Receive buffer
|
||||
* @phba: HBA to allocate a receive buffer for
|
||||
*
|
||||
* Description: Allocates a DMA-mapped receive buffer from the lpfc_hrb_pool PCI
|
||||
* pool along a non-DMA-mapped container for it.
|
||||
*
|
||||
* Notes: Not interrupt-safe. Must be called with no locks held.
|
||||
*
|
||||
* Returns:
|
||||
* pointer to HBQ on success
|
||||
* NULL on failure
|
||||
**/
|
||||
struct hbq_dmabuf *
|
||||
lpfc_sli4_rb_alloc(struct lpfc_hba *phba)
|
||||
{
|
||||
struct hbq_dmabuf *dma_buf;
|
||||
|
||||
dma_buf = kmalloc(sizeof(struct hbq_dmabuf), GFP_KERNEL);
|
||||
if (!dma_buf)
|
||||
return NULL;
|
||||
|
||||
dma_buf->hbuf.virt = pci_pool_alloc(phba->lpfc_hrb_pool, GFP_KERNEL,
|
||||
&dma_buf->hbuf.phys);
|
||||
if (!dma_buf->hbuf.virt) {
|
||||
kfree(dma_buf);
|
||||
return NULL;
|
||||
}
|
||||
dma_buf->dbuf.virt = pci_pool_alloc(phba->lpfc_drb_pool, GFP_KERNEL,
|
||||
&dma_buf->dbuf.phys);
|
||||
if (!dma_buf->dbuf.virt) {
|
||||
pci_pool_free(phba->lpfc_hrb_pool, dma_buf->hbuf.virt,
|
||||
dma_buf->hbuf.phys);
|
||||
kfree(dma_buf);
|
||||
return NULL;
|
||||
}
|
||||
dma_buf->size = LPFC_BPL_SIZE;
|
||||
return dma_buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_sli4_rb_free - Frees a receive buffer
|
||||
* @phba: HBA buffer was allocated for
|
||||
* @dmab: DMA Buffer container returned by lpfc_sli4_hbq_alloc
|
||||
*
|
||||
* Description: Frees both the container and the DMA-mapped buffers returned by
|
||||
* lpfc_sli4_rb_alloc.
|
||||
*
|
||||
* Notes: Can be called with or without locks held.
|
||||
*
|
||||
* Returns: None
|
||||
**/
|
||||
void
|
||||
lpfc_sli4_rb_free(struct lpfc_hba *phba, struct hbq_dmabuf *dmab)
|
||||
{
|
||||
pci_pool_free(phba->lpfc_hrb_pool, dmab->hbuf.virt, dmab->hbuf.phys);
|
||||
pci_pool_free(phba->lpfc_drb_pool, dmab->dbuf.virt, dmab->dbuf.phys);
|
||||
kfree(dmab);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_in_buf_free - Free a DMA buffer
|
||||
* @phba: HBA buffer is associated with
|
||||
|
@ -28,8 +28,10 @@
|
||||
#include <scsi/scsi_host.h>
|
||||
#include <scsi/scsi_transport_fc.h>
|
||||
|
||||
#include "lpfc_hw4.h"
|
||||
#include "lpfc_hw.h"
|
||||
#include "lpfc_sli.h"
|
||||
#include "lpfc_sli4.h"
|
||||
#include "lpfc_nl.h"
|
||||
#include "lpfc_disc.h"
|
||||
#include "lpfc_scsi.h"
|
||||
|
@ -31,8 +31,10 @@
|
||||
#include <scsi/scsi_transport_fc.h>
|
||||
|
||||
#include "lpfc_version.h"
|
||||
#include "lpfc_hw4.h"
|
||||
#include "lpfc_hw.h"
|
||||
#include "lpfc_sli.h"
|
||||
#include "lpfc_sli4.h"
|
||||
#include "lpfc_nl.h"
|
||||
#include "lpfc_disc.h"
|
||||
#include "lpfc_scsi.h"
|
||||
@ -57,6 +59,8 @@ static char *dif_op_str[] = {
|
||||
"SCSI_PROT_READ_CONVERT",
|
||||
"SCSI_PROT_WRITE_CONVERT"
|
||||
};
|
||||
static void
|
||||
lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb);
|
||||
|
||||
static void
|
||||
lpfc_debug_save_data(struct scsi_cmnd *cmnd)
|
||||
@ -565,12 +569,279 @@ lpfc_new_scsi_buf_s3(struct lpfc_vport *vport, int num_to_alloc)
|
||||
}
|
||||
iocb->ulpClass = CLASS3;
|
||||
psb->status = IOSTAT_SUCCESS;
|
||||
/* Put it back into the SCSI buffer list */
|
||||
lpfc_release_scsi_buf_s4(phba, psb);
|
||||
|
||||
}
|
||||
|
||||
return bcnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_sli4_fcp_xri_aborted - Fast-path process of fcp xri abort
|
||||
* @phba: pointer to lpfc hba data structure.
|
||||
* @axri: pointer to the fcp xri abort wcqe structure.
|
||||
*
|
||||
* This routine is invoked by the worker thread to process a SLI4 fast-path
|
||||
* FCP aborted xri.
|
||||
**/
|
||||
void
|
||||
lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba,
|
||||
struct sli4_wcqe_xri_aborted *axri)
|
||||
{
|
||||
uint16_t xri = bf_get(lpfc_wcqe_xa_xri, axri);
|
||||
struct lpfc_scsi_buf *psb, *next_psb;
|
||||
unsigned long iflag = 0;
|
||||
|
||||
spin_lock_irqsave(&phba->sli4_hba.abts_scsi_buf_list_lock, iflag);
|
||||
list_for_each_entry_safe(psb, next_psb,
|
||||
&phba->sli4_hba.lpfc_abts_scsi_buf_list, list) {
|
||||
if (psb->cur_iocbq.sli4_xritag == xri) {
|
||||
list_del(&psb->list);
|
||||
psb->status = IOSTAT_SUCCESS;
|
||||
spin_unlock_irqrestore(
|
||||
&phba->sli4_hba.abts_scsi_buf_list_lock,
|
||||
iflag);
|
||||
lpfc_release_scsi_buf_s4(phba, psb);
|
||||
return;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&phba->sli4_hba.abts_scsi_buf_list_lock,
|
||||
iflag);
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_sli4_repost_scsi_sgl_list - Repsot the Scsi buffers sgl pages as block
|
||||
* @phba: pointer to lpfc hba data structure.
|
||||
*
|
||||
* This routine walks the list of scsi buffers that have been allocated and
|
||||
* repost them to the HBA by using SGL block post. This is needed after a
|
||||
* pci_function_reset/warm_start or start. The lpfc_hba_down_post_s4 routine
|
||||
* is responsible for moving all scsi buffers on the lpfc_abts_scsi_sgl_list
|
||||
* to the lpfc_scsi_buf_list. If the repost fails, reject all scsi buffers.
|
||||
*
|
||||
* Returns: 0 = success, non-zero failure.
|
||||
**/
|
||||
int
|
||||
lpfc_sli4_repost_scsi_sgl_list(struct lpfc_hba *phba)
|
||||
{
|
||||
struct lpfc_scsi_buf *psb;
|
||||
int index, status, bcnt = 0, rcnt = 0, rc = 0;
|
||||
LIST_HEAD(sblist);
|
||||
|
||||
for (index = 0; index < phba->sli4_hba.scsi_xri_cnt; index++) {
|
||||
psb = phba->sli4_hba.lpfc_scsi_psb_array[index];
|
||||
if (psb) {
|
||||
/* Remove from SCSI buffer list */
|
||||
list_del(&psb->list);
|
||||
/* Add it to a local SCSI buffer list */
|
||||
list_add_tail(&psb->list, &sblist);
|
||||
if (++rcnt == LPFC_NEMBED_MBOX_SGL_CNT) {
|
||||
bcnt = rcnt;
|
||||
rcnt = 0;
|
||||
}
|
||||
} else
|
||||
/* A hole present in the XRI array, need to skip */
|
||||
bcnt = rcnt;
|
||||
|
||||
if (index == phba->sli4_hba.scsi_xri_cnt - 1)
|
||||
/* End of XRI array for SCSI buffer, complete */
|
||||
bcnt = rcnt;
|
||||
|
||||
/* Continue until collect up to a nembed page worth of sgls */
|
||||
if (bcnt == 0)
|
||||
continue;
|
||||
/* Now, post the SCSI buffer list sgls as a block */
|
||||
status = lpfc_sli4_post_scsi_sgl_block(phba, &sblist, bcnt);
|
||||
/* Reset SCSI buffer count for next round of posting */
|
||||
bcnt = 0;
|
||||
while (!list_empty(&sblist)) {
|
||||
list_remove_head(&sblist, psb, struct lpfc_scsi_buf,
|
||||
list);
|
||||
if (status) {
|
||||
/* Put this back on the abort scsi list */
|
||||
psb->status = IOSTAT_LOCAL_REJECT;
|
||||
psb->result = IOERR_ABORT_REQUESTED;
|
||||
rc++;
|
||||
} else
|
||||
psb->status = IOSTAT_SUCCESS;
|
||||
/* Put it back into the SCSI buffer list */
|
||||
lpfc_release_scsi_buf_s4(phba, psb);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_new_scsi_buf_s4 - Scsi buffer allocator for HBA with SLI4 IF spec
|
||||
* @vport: The virtual port for which this call being executed.
|
||||
* @num_to_allocate: The requested number of buffers to allocate.
|
||||
*
|
||||
* This routine allocates a scsi buffer for device with SLI-4 interface spec,
|
||||
* the scsi buffer contains all the necessary information needed to initiate
|
||||
* a SCSI I/O.
|
||||
*
|
||||
* Return codes:
|
||||
* int - number of scsi buffers that were allocated.
|
||||
* 0 = failure, less than num_to_alloc is a partial failure.
|
||||
**/
|
||||
static int
|
||||
lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc)
|
||||
{
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
struct lpfc_scsi_buf *psb;
|
||||
struct sli4_sge *sgl;
|
||||
IOCB_t *iocb;
|
||||
dma_addr_t pdma_phys_fcp_cmd;
|
||||
dma_addr_t pdma_phys_fcp_rsp;
|
||||
dma_addr_t pdma_phys_bpl, pdma_phys_bpl1;
|
||||
uint16_t iotag, last_xritag = NO_XRI;
|
||||
int status = 0, index;
|
||||
int bcnt;
|
||||
int non_sequential_xri = 0;
|
||||
int rc = 0;
|
||||
LIST_HEAD(sblist);
|
||||
|
||||
for (bcnt = 0; bcnt < num_to_alloc; bcnt++) {
|
||||
psb = kzalloc(sizeof(struct lpfc_scsi_buf), GFP_KERNEL);
|
||||
if (!psb)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Get memory from the pci pool to map the virt space to pci bus
|
||||
* space for an I/O. The DMA buffer includes space for the
|
||||
* struct fcp_cmnd, struct fcp_rsp and the number of bde's
|
||||
* necessary to support the sg_tablesize.
|
||||
*/
|
||||
psb->data = pci_pool_alloc(phba->lpfc_scsi_dma_buf_pool,
|
||||
GFP_KERNEL, &psb->dma_handle);
|
||||
if (!psb->data) {
|
||||
kfree(psb);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Initialize virtual ptrs to dma_buf region. */
|
||||
memset(psb->data, 0, phba->cfg_sg_dma_buf_size);
|
||||
|
||||
/* Allocate iotag for psb->cur_iocbq. */
|
||||
iotag = lpfc_sli_next_iotag(phba, &psb->cur_iocbq);
|
||||
if (iotag == 0) {
|
||||
kfree(psb);
|
||||
break;
|
||||
}
|
||||
|
||||
psb->cur_iocbq.sli4_xritag = lpfc_sli4_next_xritag(phba);
|
||||
if (psb->cur_iocbq.sli4_xritag == NO_XRI) {
|
||||
pci_pool_free(phba->lpfc_scsi_dma_buf_pool,
|
||||
psb->data, psb->dma_handle);
|
||||
kfree(psb);
|
||||
break;
|
||||
}
|
||||
if (last_xritag != NO_XRI
|
||||
&& psb->cur_iocbq.sli4_xritag != (last_xritag+1)) {
|
||||
non_sequential_xri = 1;
|
||||
} else
|
||||
list_add_tail(&psb->list, &sblist);
|
||||
last_xritag = psb->cur_iocbq.sli4_xritag;
|
||||
|
||||
index = phba->sli4_hba.scsi_xri_cnt++;
|
||||
psb->cur_iocbq.iocb_flag |= LPFC_IO_FCP;
|
||||
|
||||
psb->fcp_bpl = psb->data;
|
||||
psb->fcp_cmnd = (psb->data + phba->cfg_sg_dma_buf_size)
|
||||
- (sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp));
|
||||
psb->fcp_rsp = (struct fcp_rsp *)((uint8_t *)psb->fcp_cmnd +
|
||||
sizeof(struct fcp_cmnd));
|
||||
|
||||
/* Initialize local short-hand pointers. */
|
||||
sgl = (struct sli4_sge *)psb->fcp_bpl;
|
||||
pdma_phys_bpl = psb->dma_handle;
|
||||
pdma_phys_fcp_cmd =
|
||||
(psb->dma_handle + phba->cfg_sg_dma_buf_size)
|
||||
- (sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp));
|
||||
pdma_phys_fcp_rsp = pdma_phys_fcp_cmd + sizeof(struct fcp_cmnd);
|
||||
|
||||
/*
|
||||
* The first two bdes are the FCP_CMD and FCP_RSP. The balance
|
||||
* are sg list bdes. Initialize the first two and leave the
|
||||
* rest for queuecommand.
|
||||
*/
|
||||
sgl->addr_hi = cpu_to_le32(putPaddrHigh(pdma_phys_fcp_cmd));
|
||||
sgl->addr_lo = cpu_to_le32(putPaddrLow(pdma_phys_fcp_cmd));
|
||||
bf_set(lpfc_sli4_sge_len, sgl, sizeof(struct fcp_cmnd));
|
||||
bf_set(lpfc_sli4_sge_last, sgl, 0);
|
||||
sgl->word2 = cpu_to_le32(sgl->word2);
|
||||
sgl->word3 = cpu_to_le32(sgl->word3);
|
||||
sgl++;
|
||||
|
||||
/* Setup the physical region for the FCP RSP */
|
||||
sgl->addr_hi = cpu_to_le32(putPaddrHigh(pdma_phys_fcp_rsp));
|
||||
sgl->addr_lo = cpu_to_le32(putPaddrLow(pdma_phys_fcp_rsp));
|
||||
bf_set(lpfc_sli4_sge_len, sgl, sizeof(struct fcp_rsp));
|
||||
bf_set(lpfc_sli4_sge_last, sgl, 1);
|
||||
sgl->word2 = cpu_to_le32(sgl->word2);
|
||||
sgl->word3 = cpu_to_le32(sgl->word3);
|
||||
|
||||
/*
|
||||
* Since the IOCB for the FCP I/O is built into this
|
||||
* lpfc_scsi_buf, initialize it with all known data now.
|
||||
*/
|
||||
iocb = &psb->cur_iocbq.iocb;
|
||||
iocb->un.fcpi64.bdl.ulpIoTag32 = 0;
|
||||
iocb->un.fcpi64.bdl.bdeFlags = BUFF_TYPE_BDE_64;
|
||||
/* setting the BLP size to 2 * sizeof BDE may not be correct.
|
||||
* We are setting the bpl to point to out sgl. An sgl's
|
||||
* entries are 16 bytes, a bpl entries are 12 bytes.
|
||||
*/
|
||||
iocb->un.fcpi64.bdl.bdeSize = sizeof(struct fcp_cmnd);
|
||||
iocb->un.fcpi64.bdl.addrLow = putPaddrLow(pdma_phys_fcp_cmd);
|
||||
iocb->un.fcpi64.bdl.addrHigh = putPaddrHigh(pdma_phys_fcp_cmd);
|
||||
iocb->ulpBdeCount = 1;
|
||||
iocb->ulpLe = 1;
|
||||
iocb->ulpClass = CLASS3;
|
||||
if (phba->cfg_sg_dma_buf_size > SGL_PAGE_SIZE)
|
||||
pdma_phys_bpl1 = pdma_phys_bpl + SGL_PAGE_SIZE;
|
||||
else
|
||||
pdma_phys_bpl1 = 0;
|
||||
psb->dma_phys_bpl = pdma_phys_bpl;
|
||||
phba->sli4_hba.lpfc_scsi_psb_array[index] = psb;
|
||||
if (non_sequential_xri) {
|
||||
status = lpfc_sli4_post_sgl(phba, pdma_phys_bpl,
|
||||
pdma_phys_bpl1,
|
||||
psb->cur_iocbq.sli4_xritag);
|
||||
if (status) {
|
||||
/* Put this back on the abort scsi list */
|
||||
psb->status = IOSTAT_LOCAL_REJECT;
|
||||
psb->result = IOERR_ABORT_REQUESTED;
|
||||
rc++;
|
||||
} else
|
||||
psb->status = IOSTAT_SUCCESS;
|
||||
/* Put it back into the SCSI buffer list */
|
||||
lpfc_release_scsi_buf_s4(phba, psb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bcnt) {
|
||||
status = lpfc_sli4_post_scsi_sgl_block(phba, &sblist, bcnt);
|
||||
/* Reset SCSI buffer count for next round of posting */
|
||||
while (!list_empty(&sblist)) {
|
||||
list_remove_head(&sblist, psb, struct lpfc_scsi_buf,
|
||||
list);
|
||||
if (status) {
|
||||
/* Put this back on the abort scsi list */
|
||||
psb->status = IOSTAT_LOCAL_REJECT;
|
||||
psb->result = IOERR_ABORT_REQUESTED;
|
||||
rc++;
|
||||
} else
|
||||
psb->status = IOSTAT_SUCCESS;
|
||||
/* Put it back into the SCSI buffer list */
|
||||
lpfc_release_scsi_buf_s4(phba, psb);
|
||||
}
|
||||
}
|
||||
|
||||
return bcnt + non_sequential_xri - rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_new_scsi_buf - Wrapper funciton for scsi buffer allocator
|
||||
* @vport: The virtual port for which this call being executed.
|
||||
@ -637,6 +908,39 @@ lpfc_release_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb)
|
||||
spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag);
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_release_scsi_buf_s4: Return a scsi buffer back to hba scsi buf list.
|
||||
* @phba: The Hba for which this call is being executed.
|
||||
* @psb: The scsi buffer which is being released.
|
||||
*
|
||||
* This routine releases @psb scsi buffer by adding it to tail of @phba
|
||||
* lpfc_scsi_buf_list list. For SLI4 XRI's are tied to the scsi buffer
|
||||
* and cannot be reused for at least RA_TOV amount of time if it was
|
||||
* aborted.
|
||||
**/
|
||||
static void
|
||||
lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb)
|
||||
{
|
||||
unsigned long iflag = 0;
|
||||
|
||||
if (psb->status == IOSTAT_LOCAL_REJECT
|
||||
&& psb->result == IOERR_ABORT_REQUESTED) {
|
||||
spin_lock_irqsave(&phba->sli4_hba.abts_scsi_buf_list_lock,
|
||||
iflag);
|
||||
psb->pCmd = NULL;
|
||||
list_add_tail(&psb->list,
|
||||
&phba->sli4_hba.lpfc_abts_scsi_buf_list);
|
||||
spin_unlock_irqrestore(&phba->sli4_hba.abts_scsi_buf_list_lock,
|
||||
iflag);
|
||||
} else {
|
||||
|
||||
spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
|
||||
psb->pCmd = NULL;
|
||||
list_add_tail(&psb->list, &phba->lpfc_scsi_buf_list);
|
||||
spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_release_scsi_buf: Return a scsi buffer back to hba scsi buf list.
|
||||
* @phba: The Hba for which this call is being executed.
|
||||
@ -1454,6 +1758,115 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_scsi_prep_dma_buf_s4 - DMA mapping for scsi buffer to SLI4 IF spec
|
||||
* @phba: The Hba for which this call is being executed.
|
||||
* @lpfc_cmd: The scsi buffer which is going to be mapped.
|
||||
*
|
||||
* This routine does the pci dma mapping for scatter-gather list of scsi cmnd
|
||||
* field of @lpfc_cmd for device with SLI-4 interface spec.
|
||||
*
|
||||
* Return codes:
|
||||
* 1 - Error
|
||||
* 0 - Success
|
||||
**/
|
||||
static int
|
||||
lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
|
||||
{
|
||||
struct scsi_cmnd *scsi_cmnd = lpfc_cmd->pCmd;
|
||||
struct scatterlist *sgel = NULL;
|
||||
struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd;
|
||||
struct sli4_sge *sgl = (struct sli4_sge *)lpfc_cmd->fcp_bpl;
|
||||
IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb;
|
||||
dma_addr_t physaddr;
|
||||
uint32_t num_bde = 0;
|
||||
uint32_t dma_len;
|
||||
uint32_t dma_offset = 0;
|
||||
int nseg;
|
||||
|
||||
/*
|
||||
* There are three possibilities here - use scatter-gather segment, use
|
||||
* the single mapping, or neither. Start the lpfc command prep by
|
||||
* bumping the bpl beyond the fcp_cmnd and fcp_rsp regions to the first
|
||||
* data bde entry.
|
||||
*/
|
||||
if (scsi_sg_count(scsi_cmnd)) {
|
||||
/*
|
||||
* The driver stores the segment count returned from pci_map_sg
|
||||
* because this a count of dma-mappings used to map the use_sg
|
||||
* pages. They are not guaranteed to be the same for those
|
||||
* architectures that implement an IOMMU.
|
||||
*/
|
||||
|
||||
nseg = scsi_dma_map(scsi_cmnd);
|
||||
if (unlikely(!nseg))
|
||||
return 1;
|
||||
sgl += 1;
|
||||
/* clear the last flag in the fcp_rsp map entry */
|
||||
sgl->word2 = le32_to_cpu(sgl->word2);
|
||||
bf_set(lpfc_sli4_sge_last, sgl, 0);
|
||||
sgl->word2 = cpu_to_le32(sgl->word2);
|
||||
sgl += 1;
|
||||
|
||||
lpfc_cmd->seg_cnt = nseg;
|
||||
if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) {
|
||||
printk(KERN_ERR "%s: Too many sg segments from "
|
||||
"dma_map_sg. Config %d, seg_cnt %d\n",
|
||||
__func__, phba->cfg_sg_seg_cnt,
|
||||
lpfc_cmd->seg_cnt);
|
||||
scsi_dma_unmap(scsi_cmnd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The driver established a maximum scatter-gather segment count
|
||||
* during probe that limits the number of sg elements in any
|
||||
* single scsi command. Just run through the seg_cnt and format
|
||||
* the sge's.
|
||||
* When using SLI-3 the driver will try to fit all the BDEs into
|
||||
* the IOCB. If it can't then the BDEs get added to a BPL as it
|
||||
* does for SLI-2 mode.
|
||||
*/
|
||||
scsi_for_each_sg(scsi_cmnd, sgel, nseg, num_bde) {
|
||||
physaddr = sg_dma_address(sgel);
|
||||
dma_len = sg_dma_len(sgel);
|
||||
bf_set(lpfc_sli4_sge_len, sgl, sg_dma_len(sgel));
|
||||
sgl->addr_lo = cpu_to_le32(putPaddrLow(physaddr));
|
||||
sgl->addr_hi = cpu_to_le32(putPaddrHigh(physaddr));
|
||||
if ((num_bde + 1) == nseg)
|
||||
bf_set(lpfc_sli4_sge_last, sgl, 1);
|
||||
else
|
||||
bf_set(lpfc_sli4_sge_last, sgl, 0);
|
||||
bf_set(lpfc_sli4_sge_offset, sgl, dma_offset);
|
||||
sgl->word2 = cpu_to_le32(sgl->word2);
|
||||
sgl->word3 = cpu_to_le32(sgl->word3);
|
||||
dma_offset += dma_len;
|
||||
sgl++;
|
||||
}
|
||||
} else {
|
||||
sgl += 1;
|
||||
/* clear the last flag in the fcp_rsp map entry */
|
||||
sgl->word2 = le32_to_cpu(sgl->word2);
|
||||
bf_set(lpfc_sli4_sge_last, sgl, 1);
|
||||
sgl->word2 = cpu_to_le32(sgl->word2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Finish initializing those IOCB fields that are dependent on the
|
||||
* scsi_cmnd request_buffer. Note that for SLI-2 the bdeSize is
|
||||
* explicitly reinitialized.
|
||||
* all iocb memory resources are reused.
|
||||
*/
|
||||
fcp_cmnd->fcpDl = cpu_to_be32(scsi_bufflen(scsi_cmnd));
|
||||
|
||||
/*
|
||||
* Due to difference in data length between DIF/non-DIF paths,
|
||||
* we need to set word 4 of IOCB here
|
||||
*/
|
||||
iocb_cmd->un.fcpi.fcpi_parm = scsi_bufflen(scsi_cmnd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_scsi_prep_dma_buf - Wrapper function for DMA mapping of scsi buffer
|
||||
* @phba: The Hba for which this call is being executed.
|
||||
@ -1589,6 +2002,22 @@ lpfc_scsi_unprep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb)
|
||||
psb->pCmd->sc_data_direction);
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_scsi_unprep_dma_buf_s4 - Un-map DMA mapping of SG-list for SLI4 dev
|
||||
* @phba: The Hba for which this call is being executed.
|
||||
* @psb: The scsi buffer which is going to be un-mapped.
|
||||
*
|
||||
* This routine does DMA un-mapping of scatter gather list of scsi command
|
||||
* field of @lpfc_cmd for device with SLI-4 interface spec. If we have to
|
||||
* remove the sgl for this scsi buffer then we will do it here. For now
|
||||
* we should be able to just call the sli3 unprep routine.
|
||||
**/
|
||||
static void
|
||||
lpfc_scsi_unprep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb)
|
||||
{
|
||||
lpfc_scsi_unprep_dma_buf_s3(phba, psb);
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_scsi_unprep_dma_buf - Wrapper function for unmap DMA mapping of SG-list
|
||||
* @phba: The Hba for which this call is being executed.
|
||||
@ -2128,6 +2557,29 @@ lpfc_scsi_prep_cmnd_s3(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
|
||||
piocbq->vport = vport;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_scsi_prep_cmnd_s4 - Convert scsi cmnd to FCP infor unit for SLI4 dev
|
||||
* @vport: The virtual port for which this call is being executed.
|
||||
* @lpfc_cmd: The scsi command which needs to send.
|
||||
* @pnode: Pointer to lpfc_nodelist.
|
||||
*
|
||||
* This routine initializes fcp_cmnd and iocb data structure from scsi command
|
||||
* to transfer for device with SLI4 interface spec.
|
||||
**/
|
||||
static void
|
||||
lpfc_scsi_prep_cmnd_s4(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
|
||||
struct lpfc_nodelist *pnode)
|
||||
{
|
||||
/*
|
||||
* The prep cmnd routines do not touch the sgl or its
|
||||
* entries. We may not have to do anything different.
|
||||
* I will leave this function in place until we can
|
||||
* run some IO through the driver and determine if changes
|
||||
* are needed.
|
||||
*/
|
||||
return lpfc_scsi_prep_cmnd_s3(vport, lpfc_cmd, pnode);
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_scsi_prep_cmnd - Wrapper func for convert scsi cmnd to FCP info unit
|
||||
* @vport: The virtual port for which this call is being executed.
|
||||
@ -2208,6 +2660,37 @@ lpfc_scsi_prep_task_mgmt_cmd_s3(struct lpfc_vport *vport,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_scsi_prep_task_mgmt_cmnd_s4 - Convert SLI4 scsi TM cmd to FCP info unit
|
||||
* @vport: The virtual port for which this call is being executed.
|
||||
* @lpfc_cmd: Pointer to lpfc_scsi_buf data structure.
|
||||
* @lun: Logical unit number.
|
||||
* @task_mgmt_cmd: SCSI task management command.
|
||||
*
|
||||
* This routine creates FCP information unit corresponding to @task_mgmt_cmd
|
||||
* for device with SLI-4 interface spec.
|
||||
*
|
||||
* Return codes:
|
||||
* 0 - Error
|
||||
* 1 - Success
|
||||
**/
|
||||
static int
|
||||
lpfc_scsi_prep_task_mgmt_cmd_s4(struct lpfc_vport *vport,
|
||||
struct lpfc_scsi_buf *lpfc_cmd,
|
||||
unsigned int lun,
|
||||
uint8_t task_mgmt_cmd)
|
||||
{
|
||||
/*
|
||||
* The prep cmnd routines do not touch the sgl or its
|
||||
* entries. We may not have to do anything different.
|
||||
* I will leave this function in place until we can
|
||||
* run some IO through the driver and determine if changes
|
||||
* are needed.
|
||||
*/
|
||||
return lpfc_scsi_prep_task_mgmt_cmd_s3(vport, lpfc_cmd, lun,
|
||||
task_mgmt_cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_scsi_prep_task_mgmt_cmnd - Wrapper func convert scsi TM cmd to FCP info
|
||||
* @vport: The virtual port for which this call is being executed.
|
||||
@ -2257,6 +2740,15 @@ lpfc_scsi_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp)
|
||||
lpfc_scsi_prep_task_mgmt_cmd_s3;
|
||||
phba->lpfc_release_scsi_buf = lpfc_release_scsi_buf_s3;
|
||||
break;
|
||||
case LPFC_PCI_DEV_OC:
|
||||
phba->lpfc_new_scsi_buf = lpfc_new_scsi_buf_s4;
|
||||
phba->lpfc_scsi_prep_dma_buf = lpfc_scsi_prep_dma_buf_s4;
|
||||
phba->lpfc_scsi_prep_cmnd = lpfc_scsi_prep_cmnd_s4;
|
||||
phba->lpfc_scsi_unprep_dma_buf = lpfc_scsi_unprep_dma_buf_s4;
|
||||
phba->lpfc_scsi_prep_task_mgmt_cmd =
|
||||
lpfc_scsi_prep_task_mgmt_cmd_s4;
|
||||
phba->lpfc_release_scsi_buf = lpfc_release_scsi_buf_s4;
|
||||
break;
|
||||
default:
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||
"1418 Invalid HBA PCI-device group: 0x%x\n",
|
||||
|
@ -140,6 +140,8 @@ struct lpfc_scsi_buf {
|
||||
struct fcp_rsp *fcp_rsp;
|
||||
struct ulp_bde64 *fcp_bpl;
|
||||
|
||||
dma_addr_t dma_phys_bpl;
|
||||
|
||||
/* cur_iocbq has phys of the dma-able buffer.
|
||||
* Iotag is in here
|
||||
*/
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -29,13 +29,23 @@ typedef enum _lpfc_ctx_cmd {
|
||||
LPFC_CTX_HOST
|
||||
} lpfc_ctx_cmd;
|
||||
|
||||
/* This structure is used to carry the needed response IOCB states */
|
||||
struct lpfc_sli4_rspiocb_info {
|
||||
uint8_t hw_status;
|
||||
uint8_t bfield;
|
||||
#define LPFC_XB 0x1
|
||||
#define LPFC_PV 0x2
|
||||
uint8_t priority;
|
||||
uint8_t reserved;
|
||||
};
|
||||
|
||||
/* This structure is used to handle IOCB requests / responses */
|
||||
struct lpfc_iocbq {
|
||||
/* lpfc_iocbqs are used in double linked lists */
|
||||
struct list_head list;
|
||||
struct list_head clist;
|
||||
uint16_t iotag; /* pre-assigned IO tag */
|
||||
uint16_t rsvd1;
|
||||
uint16_t sli4_xritag; /* pre-assigned XRI, (OXID) tag. */
|
||||
|
||||
IOCB_t iocb; /* IOCB cmd */
|
||||
uint8_t retry; /* retry counter for IOCB cmd - if needed */
|
||||
@ -65,7 +75,7 @@ struct lpfc_iocbq {
|
||||
struct lpfc_iocbq *);
|
||||
void (*iocb_cmpl) (struct lpfc_hba *, struct lpfc_iocbq *,
|
||||
struct lpfc_iocbq *);
|
||||
|
||||
struct lpfc_sli4_rspiocb_info sli4_info;
|
||||
};
|
||||
|
||||
#define SLI_IOCB_RET_IOCB 1 /* Return IOCB if cmd ring full */
|
||||
@ -81,14 +91,18 @@ struct lpfc_iocbq {
|
||||
typedef struct lpfcMboxq {
|
||||
/* MBOXQs are used in single linked lists */
|
||||
struct list_head list; /* ptr to next mailbox command */
|
||||
union {
|
||||
MAILBOX_t mb; /* Mailbox cmd */
|
||||
struct lpfc_vport *vport;/* virutal port pointer */
|
||||
struct lpfc_mqe mqe;
|
||||
} u;
|
||||
struct lpfc_vport *vport;/* virtual port pointer */
|
||||
void *context1; /* caller context information */
|
||||
void *context2; /* caller context information */
|
||||
|
||||
void (*mbox_cmpl) (struct lpfc_hba *, struct lpfcMboxq *);
|
||||
uint8_t mbox_flag;
|
||||
|
||||
struct lpfc_mcqe mcqe;
|
||||
struct lpfc_mbx_nembed_sge_virt *sge_array;
|
||||
} LPFC_MBOXQ_t;
|
||||
|
||||
#define MBX_POLL 1 /* poll mailbox till command done, then
|
||||
@ -234,6 +248,7 @@ struct lpfc_sli {
|
||||
#define LPFC_PROCESS_LA 0x400 /* Able to process link attention */
|
||||
#define LPFC_BLOCK_MGMT_IO 0x800 /* Don't allow mgmt mbx or iocb cmds */
|
||||
#define LPFC_MENLO_MAINT 0x1000 /* need for menl fw download */
|
||||
#define LPFC_SLI_ASYNC_MBX_BLK 0x2000 /* Async mailbox is blocked */
|
||||
|
||||
struct lpfc_sli_ring ring[LPFC_MAX_RING];
|
||||
int fcp_ring; /* ring used for FCP initiator commands */
|
||||
@ -261,6 +276,8 @@ struct lpfc_sli {
|
||||
|
||||
#define LPFC_MBOX_TMO 30 /* Sec tmo for outstanding mbox
|
||||
command */
|
||||
#define LPFC_MBOX_SLI4_CONFIG_TMO 60 /* Sec tmo for outstanding mbox
|
||||
command */
|
||||
#define LPFC_MBOX_TMO_FLASH_CMD 300 /* Sec tmo for outstanding FLASH write
|
||||
* or erase cmds. This is especially
|
||||
* long because of the potential of
|
||||
|
467
drivers/scsi/lpfc/lpfc_sli4.h
Normal file
467
drivers/scsi/lpfc/lpfc_sli4.h
Normal file
@ -0,0 +1,467 @@
|
||||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2009 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. *
|
||||
*******************************************************************/
|
||||
|
||||
#define LPFC_ACTIVE_MBOX_WAIT_CNT 100
|
||||
#define LPFC_RELEASE_NOTIFICATION_INTERVAL 32
|
||||
#define LPFC_GET_QE_REL_INT 32
|
||||
#define LPFC_RPI_LOW_WATER_MARK 10
|
||||
/* Number of SGL entries can be posted in a 4KB nonembedded mbox command */
|
||||
#define LPFC_NEMBED_MBOX_SGL_CNT 254
|
||||
|
||||
/* Multi-queue arrangement for fast-path FCP work queues */
|
||||
#define LPFC_FN_EQN_MAX 8
|
||||
#define LPFC_SP_EQN_DEF 1
|
||||
#define LPFC_FP_EQN_DEF 1
|
||||
#define LPFC_FP_EQN_MIN 1
|
||||
#define LPFC_FP_EQN_MAX (LPFC_FN_EQN_MAX - LPFC_SP_EQN_DEF)
|
||||
|
||||
#define LPFC_FN_WQN_MAX 32
|
||||
#define LPFC_SP_WQN_DEF 1
|
||||
#define LPFC_FP_WQN_DEF 4
|
||||
#define LPFC_FP_WQN_MIN 1
|
||||
#define LPFC_FP_WQN_MAX (LPFC_FN_WQN_MAX - LPFC_SP_WQN_DEF)
|
||||
|
||||
/*
|
||||
* Provide the default FCF Record attributes used by the driver
|
||||
* when nonFIP mode is configured and there is no other default
|
||||
* FCF Record attributes.
|
||||
*/
|
||||
#define LPFC_FCOE_FCF_DEF_INDEX 0
|
||||
#define LPFC_FCOE_FCF_GET_FIRST 0xFFFF
|
||||
#define LPFC_FCOE_FCF_NEXT_NONE 0xFFFF
|
||||
|
||||
/* First 3 bytes of default FCF MAC is specified by FC_MAP */
|
||||
#define LPFC_FCOE_FCF_MAC3 0xFF
|
||||
#define LPFC_FCOE_FCF_MAC4 0xFF
|
||||
#define LPFC_FCOE_FCF_MAC5 0xFE
|
||||
#define LPFC_FCOE_FCF_MAP0 0x0E
|
||||
#define LPFC_FCOE_FCF_MAP1 0xFC
|
||||
#define LPFC_FCOE_FCF_MAP2 0x00
|
||||
#define LPFC_FCOE_MAX_RCV_SIZE 0x5AC
|
||||
#define LPFC_FCOE_FKA_ADV_PER 0
|
||||
#define LPFC_FCOE_FIP_PRIORITY 0x80
|
||||
|
||||
enum lpfc_sli4_queue_type {
|
||||
LPFC_EQ,
|
||||
LPFC_GCQ,
|
||||
LPFC_MCQ,
|
||||
LPFC_WCQ,
|
||||
LPFC_RCQ,
|
||||
LPFC_MQ,
|
||||
LPFC_WQ,
|
||||
LPFC_HRQ,
|
||||
LPFC_DRQ
|
||||
};
|
||||
|
||||
/* The queue sub-type defines the functional purpose of the queue */
|
||||
enum lpfc_sli4_queue_subtype {
|
||||
LPFC_NONE,
|
||||
LPFC_MBOX,
|
||||
LPFC_FCP,
|
||||
LPFC_ELS,
|
||||
LPFC_USOL
|
||||
};
|
||||
|
||||
union sli4_qe {
|
||||
void *address;
|
||||
struct lpfc_eqe *eqe;
|
||||
struct lpfc_cqe *cqe;
|
||||
struct lpfc_mcqe *mcqe;
|
||||
struct lpfc_wcqe_complete *wcqe_complete;
|
||||
struct lpfc_wcqe_release *wcqe_release;
|
||||
struct sli4_wcqe_xri_aborted *wcqe_xri_aborted;
|
||||
struct lpfc_rcqe_complete *rcqe_complete;
|
||||
struct lpfc_mqe *mqe;
|
||||
union lpfc_wqe *wqe;
|
||||
struct lpfc_rqe *rqe;
|
||||
};
|
||||
|
||||
struct lpfc_queue {
|
||||
struct list_head list;
|
||||
enum lpfc_sli4_queue_type type;
|
||||
enum lpfc_sli4_queue_subtype subtype;
|
||||
struct lpfc_hba *phba;
|
||||
struct list_head child_list;
|
||||
uint32_t entry_count; /* Number of entries to support on the queue */
|
||||
uint32_t entry_size; /* Size of each queue entry. */
|
||||
uint32_t queue_id; /* Queue ID assigned by the hardware */
|
||||
struct list_head page_list;
|
||||
uint32_t page_count; /* Number of pages allocated for this queue */
|
||||
|
||||
uint32_t host_index; /* The host's index for putting or getting */
|
||||
uint32_t hba_index; /* The last known hba index for get or put */
|
||||
union sli4_qe qe[1]; /* array to index entries (must be last) */
|
||||
};
|
||||
|
||||
struct lpfc_cq_event {
|
||||
struct list_head list;
|
||||
union {
|
||||
struct lpfc_mcqe mcqe_cmpl;
|
||||
struct lpfc_acqe_link acqe_link;
|
||||
struct lpfc_acqe_fcoe acqe_fcoe;
|
||||
struct lpfc_acqe_dcbx acqe_dcbx;
|
||||
struct lpfc_rcqe rcqe_cmpl;
|
||||
struct sli4_wcqe_xri_aborted wcqe_axri;
|
||||
} cqe;
|
||||
};
|
||||
|
||||
struct lpfc_sli4_link {
|
||||
uint8_t speed;
|
||||
uint8_t duplex;
|
||||
uint8_t status;
|
||||
uint8_t physical;
|
||||
uint8_t fault;
|
||||
};
|
||||
|
||||
struct lpfc_fcf {
|
||||
uint8_t fabric_name[8];
|
||||
uint8_t mac_addr[6];
|
||||
uint16_t fcf_indx;
|
||||
uint16_t fcfi;
|
||||
uint32_t fcf_flag;
|
||||
#define FCF_AVAILABLE 0x01 /* FCF available for discovery */
|
||||
#define FCF_REGISTERED 0x02 /* FCF registered with FW */
|
||||
#define FCF_DISCOVERED 0x04 /* FCF discovery started */
|
||||
#define FCF_BOOT_ENABLE 0x08 /* Boot bios use this FCF */
|
||||
#define FCF_IN_USE 0x10 /* Atleast one discovery completed */
|
||||
#define FCF_VALID_VLAN 0x20 /* Use the vlan id specified */
|
||||
uint32_t priority;
|
||||
uint32_t addr_mode;
|
||||
uint16_t vlan_id;
|
||||
};
|
||||
|
||||
#define LPFC_REGION23_SIGNATURE "RG23"
|
||||
#define LPFC_REGION23_VERSION 1
|
||||
#define LPFC_REGION23_LAST_REC 0xff
|
||||
struct lpfc_fip_param_hdr {
|
||||
uint8_t type;
|
||||
#define FCOE_PARAM_TYPE 0xA0
|
||||
uint8_t length;
|
||||
#define FCOE_PARAM_LENGTH 2
|
||||
uint8_t parm_version;
|
||||
#define FIPP_VERSION 0x01
|
||||
uint8_t parm_flags;
|
||||
#define lpfc_fip_param_hdr_fipp_mode_SHIFT 6
|
||||
#define lpfc_fip_param_hdr_fipp_mode_MASK 0x3
|
||||
#define lpfc_fip_param_hdr_fipp_mode_WORD parm_flags
|
||||
#define FIPP_MODE_ON 0x2
|
||||
#define FIPP_MODE_OFF 0x0
|
||||
#define FIPP_VLAN_VALID 0x1
|
||||
};
|
||||
|
||||
struct lpfc_fcoe_params {
|
||||
uint8_t fc_map[3];
|
||||
uint8_t reserved1;
|
||||
uint16_t vlan_tag;
|
||||
uint8_t reserved[2];
|
||||
};
|
||||
|
||||
struct lpfc_fcf_conn_hdr {
|
||||
uint8_t type;
|
||||
#define FCOE_CONN_TBL_TYPE 0xA1
|
||||
uint8_t length; /* words */
|
||||
uint8_t reserved[2];
|
||||
};
|
||||
|
||||
struct lpfc_fcf_conn_rec {
|
||||
uint16_t flags;
|
||||
#define FCFCNCT_VALID 0x0001
|
||||
#define FCFCNCT_BOOT 0x0002
|
||||
#define FCFCNCT_PRIMARY 0x0004 /* if not set, Secondary */
|
||||
#define FCFCNCT_FBNM_VALID 0x0008
|
||||
#define FCFCNCT_SWNM_VALID 0x0010
|
||||
#define FCFCNCT_VLAN_VALID 0x0020
|
||||
#define FCFCNCT_AM_VALID 0x0040
|
||||
#define FCFCNCT_AM_PREFERRED 0x0080 /* if not set, AM Required */
|
||||
#define FCFCNCT_AM_SPMA 0x0100 /* if not set, FPMA */
|
||||
|
||||
uint16_t vlan_tag;
|
||||
uint8_t fabric_name[8];
|
||||
uint8_t switch_name[8];
|
||||
};
|
||||
|
||||
struct lpfc_fcf_conn_entry {
|
||||
struct list_head list;
|
||||
struct lpfc_fcf_conn_rec conn_rec;
|
||||
};
|
||||
|
||||
/*
|
||||
* Define the host's bootstrap mailbox. This structure contains
|
||||
* the member attributes needed to create, use, and destroy the
|
||||
* bootstrap mailbox region.
|
||||
*
|
||||
* The macro definitions for the bmbx data structure are defined
|
||||
* in lpfc_hw4.h with the register definition.
|
||||
*/
|
||||
struct lpfc_bmbx {
|
||||
struct lpfc_dmabuf *dmabuf;
|
||||
struct dma_address dma_address;
|
||||
void *avirt;
|
||||
dma_addr_t aphys;
|
||||
uint32_t bmbx_size;
|
||||
};
|
||||
|
||||
#define LPFC_EQE_SIZE LPFC_EQE_SIZE_4
|
||||
|
||||
#define LPFC_EQE_SIZE_4B 4
|
||||
#define LPFC_EQE_SIZE_16B 16
|
||||
#define LPFC_CQE_SIZE 16
|
||||
#define LPFC_WQE_SIZE 64
|
||||
#define LPFC_MQE_SIZE 256
|
||||
#define LPFC_RQE_SIZE 8
|
||||
|
||||
#define LPFC_EQE_DEF_COUNT 1024
|
||||
#define LPFC_CQE_DEF_COUNT 256
|
||||
#define LPFC_WQE_DEF_COUNT 64
|
||||
#define LPFC_MQE_DEF_COUNT 16
|
||||
#define LPFC_RQE_DEF_COUNT 512
|
||||
|
||||
#define LPFC_QUEUE_NOARM false
|
||||
#define LPFC_QUEUE_REARM true
|
||||
|
||||
|
||||
/*
|
||||
* SLI4 CT field defines
|
||||
*/
|
||||
#define SLI4_CT_RPI 0
|
||||
#define SLI4_CT_VPI 1
|
||||
#define SLI4_CT_VFI 2
|
||||
#define SLI4_CT_FCFI 3
|
||||
|
||||
#define LPFC_SLI4_MAX_SEGMENT_SIZE 0x10000
|
||||
|
||||
/*
|
||||
* SLI4 specific data structures
|
||||
*/
|
||||
struct lpfc_max_cfg_param {
|
||||
uint16_t max_xri;
|
||||
uint16_t xri_base;
|
||||
uint16_t xri_used;
|
||||
uint16_t max_rpi;
|
||||
uint16_t rpi_base;
|
||||
uint16_t rpi_used;
|
||||
uint16_t max_vpi;
|
||||
uint16_t vpi_base;
|
||||
uint16_t vpi_used;
|
||||
uint16_t max_vfi;
|
||||
uint16_t vfi_base;
|
||||
uint16_t vfi_used;
|
||||
uint16_t max_fcfi;
|
||||
uint16_t fcfi_base;
|
||||
uint16_t fcfi_used;
|
||||
uint16_t max_eq;
|
||||
uint16_t max_rq;
|
||||
uint16_t max_cq;
|
||||
uint16_t max_wq;
|
||||
};
|
||||
|
||||
struct lpfc_hba;
|
||||
/* SLI4 HBA multi-fcp queue handler struct */
|
||||
struct lpfc_fcp_eq_hdl {
|
||||
uint32_t idx;
|
||||
struct lpfc_hba *phba;
|
||||
};
|
||||
|
||||
/* SLI4 HBA data structure entries */
|
||||
struct lpfc_sli4_hba {
|
||||
void __iomem *conf_regs_memmap_p; /* Kernel memory mapped address for
|
||||
PCI BAR0, config space registers */
|
||||
void __iomem *ctrl_regs_memmap_p; /* Kernel memory mapped address for
|
||||
PCI BAR1, control registers */
|
||||
void __iomem *drbl_regs_memmap_p; /* Kernel memory mapped address for
|
||||
PCI BAR2, doorbell registers */
|
||||
/* BAR0 PCI config space register memory map */
|
||||
void __iomem *UERRLOregaddr; /* Address to UERR_STATUS_LO register */
|
||||
void __iomem *UERRHIregaddr; /* Address to UERR_STATUS_HI register */
|
||||
void __iomem *ONLINE0regaddr; /* Address to components of internal UE */
|
||||
void __iomem *ONLINE1regaddr; /* Address to components of internal UE */
|
||||
#define LPFC_ONLINE_NERR 0xFFFFFFFF
|
||||
void __iomem *SCRATCHPADregaddr; /* Address to scratchpad register */
|
||||
/* BAR1 FCoE function CSR register memory map */
|
||||
void __iomem *STAregaddr; /* Address to HST_STATE register */
|
||||
void __iomem *ISRregaddr; /* Address to HST_ISR register */
|
||||
void __iomem *IMRregaddr; /* Address to HST_IMR register */
|
||||
void __iomem *ISCRregaddr; /* Address to HST_ISCR register */
|
||||
/* BAR2 VF-0 doorbell register memory map */
|
||||
void __iomem *RQDBregaddr; /* Address to RQ_DOORBELL register */
|
||||
void __iomem *WQDBregaddr; /* Address to WQ_DOORBELL register */
|
||||
void __iomem *EQCQDBregaddr; /* Address to EQCQ_DOORBELL register */
|
||||
void __iomem *MQDBregaddr; /* Address to MQ_DOORBELL register */
|
||||
void __iomem *BMBXregaddr; /* Address to BootStrap MBX register */
|
||||
|
||||
struct msix_entry *msix_entries;
|
||||
uint32_t cfg_eqn;
|
||||
struct lpfc_fcp_eq_hdl *fcp_eq_hdl; /* FCP per-WQ handle */
|
||||
/* Pointers to the constructed SLI4 queues */
|
||||
struct lpfc_queue **fp_eq; /* Fast-path event queue */
|
||||
struct lpfc_queue *sp_eq; /* Slow-path event queue */
|
||||
struct lpfc_queue **fcp_wq;/* Fast-path FCP work queue */
|
||||
struct lpfc_queue *mbx_wq; /* Slow-path MBOX work queue */
|
||||
struct lpfc_queue *els_wq; /* Slow-path ELS work queue */
|
||||
struct lpfc_queue *hdr_rq; /* Slow-path Header Receive queue */
|
||||
struct lpfc_queue *dat_rq; /* Slow-path Data Receive queue */
|
||||
struct lpfc_queue **fcp_cq;/* Fast-path FCP compl queue */
|
||||
struct lpfc_queue *mbx_cq; /* Slow-path mailbox complete queue */
|
||||
struct lpfc_queue *els_cq; /* Slow-path ELS response complete queue */
|
||||
struct lpfc_queue *rxq_cq; /* Slow-path unsolicited complete queue */
|
||||
|
||||
/* Setup information for various queue parameters */
|
||||
int eq_esize;
|
||||
int eq_ecount;
|
||||
int cq_esize;
|
||||
int cq_ecount;
|
||||
int wq_esize;
|
||||
int wq_ecount;
|
||||
int mq_esize;
|
||||
int mq_ecount;
|
||||
int rq_esize;
|
||||
int rq_ecount;
|
||||
#define LPFC_SP_EQ_MAX_INTR_SEC 10000
|
||||
#define LPFC_FP_EQ_MAX_INTR_SEC 10000
|
||||
|
||||
uint32_t intr_enable;
|
||||
struct lpfc_bmbx bmbx;
|
||||
struct lpfc_max_cfg_param max_cfg_param;
|
||||
uint16_t next_xri; /* last_xri - max_cfg_param.xri_base = used */
|
||||
uint16_t next_rpi;
|
||||
uint16_t scsi_xri_max;
|
||||
uint16_t scsi_xri_cnt;
|
||||
struct list_head lpfc_free_sgl_list;
|
||||
struct list_head lpfc_sgl_list;
|
||||
struct lpfc_sglq **lpfc_els_sgl_array;
|
||||
struct list_head lpfc_abts_els_sgl_list;
|
||||
struct lpfc_scsi_buf **lpfc_scsi_psb_array;
|
||||
struct list_head lpfc_abts_scsi_buf_list;
|
||||
uint32_t total_sglq_bufs;
|
||||
struct lpfc_sglq **lpfc_sglq_active_list;
|
||||
struct list_head lpfc_rpi_hdr_list;
|
||||
unsigned long *rpi_bmask;
|
||||
uint16_t rpi_count;
|
||||
struct lpfc_sli4_flags sli4_flags;
|
||||
struct list_head sp_rspiocb_work_queue;
|
||||
struct list_head sp_cqe_event_pool;
|
||||
struct list_head sp_asynce_work_queue;
|
||||
struct list_head sp_fcp_xri_aborted_work_queue;
|
||||
struct list_head sp_els_xri_aborted_work_queue;
|
||||
struct list_head sp_unsol_work_queue;
|
||||
struct lpfc_sli4_link link_state;
|
||||
spinlock_t abts_scsi_buf_list_lock; /* list of aborted SCSI IOs */
|
||||
spinlock_t abts_sgl_list_lock; /* list of aborted els IOs */
|
||||
};
|
||||
|
||||
enum lpfc_sge_type {
|
||||
GEN_BUFF_TYPE,
|
||||
SCSI_BUFF_TYPE
|
||||
};
|
||||
|
||||
struct lpfc_sglq {
|
||||
/* lpfc_sglqs are used in double linked lists */
|
||||
struct list_head list;
|
||||
struct list_head clist;
|
||||
enum lpfc_sge_type buff_type; /* is this a scsi sgl */
|
||||
uint16_t iotag; /* pre-assigned IO tag */
|
||||
uint16_t sli4_xritag; /* pre-assigned XRI, (OXID) tag. */
|
||||
struct sli4_sge *sgl; /* pre-assigned SGL */
|
||||
void *virt; /* virtual address. */
|
||||
dma_addr_t phys; /* physical address */
|
||||
};
|
||||
|
||||
struct lpfc_rpi_hdr {
|
||||
struct list_head list;
|
||||
uint32_t len;
|
||||
struct lpfc_dmabuf *dmabuf;
|
||||
uint32_t page_count;
|
||||
uint32_t start_rpi;
|
||||
};
|
||||
|
||||
/*
|
||||
* SLI4 specific function prototypes
|
||||
*/
|
||||
int lpfc_pci_function_reset(struct lpfc_hba *);
|
||||
int lpfc_sli4_hba_setup(struct lpfc_hba *);
|
||||
int lpfc_sli4_hba_down(struct lpfc_hba *);
|
||||
int lpfc_sli4_config(struct lpfc_hba *, struct lpfcMboxq *, uint8_t,
|
||||
uint8_t, uint32_t, bool);
|
||||
void lpfc_sli4_mbox_cmd_free(struct lpfc_hba *, struct lpfcMboxq *);
|
||||
void lpfc_sli4_mbx_sge_set(struct lpfcMboxq *, uint32_t, dma_addr_t, uint32_t);
|
||||
void lpfc_sli4_mbx_sge_get(struct lpfcMboxq *, uint32_t,
|
||||
struct lpfc_mbx_sge *);
|
||||
|
||||
void lpfc_sli4_hba_reset(struct lpfc_hba *);
|
||||
struct lpfc_queue *lpfc_sli4_queue_alloc(struct lpfc_hba *, uint32_t,
|
||||
uint32_t);
|
||||
void lpfc_sli4_queue_free(struct lpfc_queue *);
|
||||
uint32_t lpfc_eq_create(struct lpfc_hba *, struct lpfc_queue *, uint16_t);
|
||||
uint32_t lpfc_cq_create(struct lpfc_hba *, struct lpfc_queue *,
|
||||
struct lpfc_queue *, uint32_t, uint32_t);
|
||||
uint32_t lpfc_mq_create(struct lpfc_hba *, struct lpfc_queue *,
|
||||
struct lpfc_queue *, uint32_t);
|
||||
uint32_t lpfc_wq_create(struct lpfc_hba *, struct lpfc_queue *,
|
||||
struct lpfc_queue *, uint32_t);
|
||||
uint32_t lpfc_rq_create(struct lpfc_hba *, struct lpfc_queue *,
|
||||
struct lpfc_queue *, struct lpfc_queue *, uint32_t);
|
||||
uint32_t lpfc_eq_destroy(struct lpfc_hba *, struct lpfc_queue *);
|
||||
uint32_t lpfc_cq_destroy(struct lpfc_hba *, struct lpfc_queue *);
|
||||
uint32_t lpfc_mq_destroy(struct lpfc_hba *, struct lpfc_queue *);
|
||||
uint32_t lpfc_wq_destroy(struct lpfc_hba *, struct lpfc_queue *);
|
||||
uint32_t lpfc_rq_destroy(struct lpfc_hba *, struct lpfc_queue *,
|
||||
struct lpfc_queue *);
|
||||
int lpfc_sli4_queue_setup(struct lpfc_hba *);
|
||||
void lpfc_sli4_queue_unset(struct lpfc_hba *);
|
||||
int lpfc_sli4_post_sgl(struct lpfc_hba *, dma_addr_t, dma_addr_t, uint16_t);
|
||||
int lpfc_sli4_repost_scsi_sgl_list(struct lpfc_hba *);
|
||||
int lpfc_sli4_remove_all_sgl_pages(struct lpfc_hba *);
|
||||
uint16_t lpfc_sli4_next_xritag(struct lpfc_hba *);
|
||||
int lpfc_sli4_post_async_mbox(struct lpfc_hba *);
|
||||
int lpfc_sli4_post_sgl_list(struct lpfc_hba *phba);
|
||||
int lpfc_sli4_post_scsi_sgl_block(struct lpfc_hba *, struct list_head *, int);
|
||||
struct lpfc_cq_event *__lpfc_sli4_cq_event_alloc(struct lpfc_hba *);
|
||||
struct lpfc_cq_event *lpfc_sli4_cq_event_alloc(struct lpfc_hba *);
|
||||
void __lpfc_sli4_cq_event_release(struct lpfc_hba *, struct lpfc_cq_event *);
|
||||
void lpfc_sli4_cq_event_release(struct lpfc_hba *, struct lpfc_cq_event *);
|
||||
int lpfc_sli4_init_rpi_hdrs(struct lpfc_hba *);
|
||||
int lpfc_sli4_post_rpi_hdr(struct lpfc_hba *, struct lpfc_rpi_hdr *);
|
||||
int lpfc_sli4_post_all_rpi_hdrs(struct lpfc_hba *);
|
||||
struct lpfc_rpi_hdr *lpfc_sli4_create_rpi_hdr(struct lpfc_hba *);
|
||||
void lpfc_sli4_remove_rpi_hdrs(struct lpfc_hba *);
|
||||
int lpfc_sli4_alloc_rpi(struct lpfc_hba *);
|
||||
void lpfc_sli4_free_rpi(struct lpfc_hba *, int);
|
||||
void lpfc_sli4_remove_rpis(struct lpfc_hba *);
|
||||
void lpfc_sli4_async_event_proc(struct lpfc_hba *);
|
||||
int lpfc_sli4_resume_rpi(struct lpfc_nodelist *);
|
||||
void lpfc_sli4_fcp_xri_abort_event_proc(struct lpfc_hba *);
|
||||
void lpfc_sli4_els_xri_abort_event_proc(struct lpfc_hba *);
|
||||
void lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *,
|
||||
struct sli4_wcqe_xri_aborted *);
|
||||
void lpfc_sli4_els_xri_aborted(struct lpfc_hba *,
|
||||
struct sli4_wcqe_xri_aborted *);
|
||||
int lpfc_sli4_brdreset(struct lpfc_hba *);
|
||||
int lpfc_sli4_add_fcf_record(struct lpfc_hba *, struct fcf_record *);
|
||||
void lpfc_sli_remove_dflt_fcf(struct lpfc_hba *);
|
||||
int lpfc_sli4_get_els_iocb_cnt(struct lpfc_hba *);
|
||||
int lpfc_sli4_init_vpi(struct lpfc_hba *, uint16_t);
|
||||
uint32_t lpfc_sli4_cq_release(struct lpfc_queue *, bool);
|
||||
uint32_t lpfc_sli4_eq_release(struct lpfc_queue *, bool);
|
||||
void lpfc_sli4_fcfi_unreg(struct lpfc_hba *, uint16_t);
|
||||
int lpfc_sli4_read_fcf_record(struct lpfc_hba *, uint16_t);
|
||||
void lpfc_mbx_cmpl_read_fcf_record(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
int lpfc_sli4_post_status_check(struct lpfc_hba *);
|
||||
uint8_t lpfc_sli4_mbox_opcode_get(struct lpfc_hba *, struct lpfcMboxq *);
|
||||
|
@ -32,8 +32,10 @@
|
||||
#include <scsi/scsi_device.h>
|
||||
#include <scsi/scsi_host.h>
|
||||
#include <scsi/scsi_transport_fc.h>
|
||||
#include "lpfc_hw4.h"
|
||||
#include "lpfc_hw.h"
|
||||
#include "lpfc_sli.h"
|
||||
#include "lpfc_sli4.h"
|
||||
#include "lpfc_nl.h"
|
||||
#include "lpfc_disc.h"
|
||||
#include "lpfc_scsi.h"
|
||||
@ -89,6 +91,8 @@ lpfc_alloc_vpi(struct lpfc_hba *phba)
|
||||
vpi = 0;
|
||||
else
|
||||
set_bit(vpi, phba->vpi_bmask);
|
||||
if (phba->sli_rev == LPFC_SLI_REV4)
|
||||
phba->sli4_hba.max_cfg_param.vpi_used++;
|
||||
spin_unlock_irq(&phba->hbalock);
|
||||
return vpi;
|
||||
}
|
||||
@ -96,8 +100,12 @@ lpfc_alloc_vpi(struct lpfc_hba *phba)
|
||||
static void
|
||||
lpfc_free_vpi(struct lpfc_hba *phba, int vpi)
|
||||
{
|
||||
if (vpi == 0)
|
||||
return;
|
||||
spin_lock_irq(&phba->hbalock);
|
||||
clear_bit(vpi, phba->vpi_bmask);
|
||||
if (phba->sli_rev == LPFC_SLI_REV4)
|
||||
phba->sli4_hba.max_cfg_param.vpi_used--;
|
||||
spin_unlock_irq(&phba->hbalock);
|
||||
}
|
||||
|
||||
@ -308,6 +316,21 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable)
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
/*
|
||||
* In SLI4, the vpi must be activated before it can be used
|
||||
* by the port.
|
||||
*/
|
||||
if (phba->sli_rev == LPFC_SLI_REV4) {
|
||||
rc = lpfc_sli4_init_vpi(phba, vpi);
|
||||
if (rc) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
|
||||
"1838 Failed to INIT_VPI on vpi %d "
|
||||
"status %d\n", vpi, rc);
|
||||
rc = VPORT_NORESOURCES;
|
||||
lpfc_free_vpi(phba, vpi);
|
||||
goto error_out;
|
||||
}
|
||||
}
|
||||
|
||||
/* Assign an unused board number */
|
||||
if ((instance = lpfc_get_instance()) < 0) {
|
||||
|
Loading…
Reference in New Issue
Block a user