Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
+36
View File
@@ -0,0 +1,36 @@
#/*******************************************************************
# * This file is part of the Emulex Linux Device Driver for *
# * Fibre Channel Host Bus Adapters. *
# * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
# * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
# * Copyright (C) 2004-2012 Emulex. All rights reserved. *
# * EMULEX and SLI are trademarks of Emulex. *
# * 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 *
# * 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. *
# *******************************************************************/
######################################################################
ccflags-$(GCOV) := -fprofile-arcs -ftest-coverage
ccflags-$(GCOV) += -O0
ifdef WARNINGS_BECOME_ERRORS
ccflags-y += -Werror
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_nvme.o lpfc_nvmet.o lpfc_vmid.o
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+128
View File
@@ -0,0 +1,128 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.broadcom.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
* *
* 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_ATTR(name, defval, minval, maxval, desc) \
static uint lpfc_##name = defval;\
module_param(lpfc_##name, uint, S_IRUGO);\
MODULE_PARM_DESC(lpfc_##name, desc);\
lpfc_param_init(name, defval, minval, maxval)
#define LPFC_ATTR_R(name, defval, minval, maxval, desc) \
static uint lpfc_##name = defval;\
module_param(lpfc_##name, uint, S_IRUGO);\
MODULE_PARM_DESC(lpfc_##name, desc);\
lpfc_param_show(name)\
lpfc_param_init(name, defval, minval, maxval)\
static DEVICE_ATTR(lpfc_##name, S_IRUGO, lpfc_##name##_show, NULL)
#define LPFC_ATTR_RW(name, defval, minval, maxval, desc) \
static uint lpfc_##name = defval;\
module_param(lpfc_##name, uint, S_IRUGO);\
MODULE_PARM_DESC(lpfc_##name, desc);\
lpfc_param_show(name)\
lpfc_param_init(name, defval, minval, maxval)\
lpfc_param_set(name, defval, minval, maxval)\
lpfc_param_store(name)\
static DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
lpfc_##name##_show, lpfc_##name##_store)
#define LPFC_BBCR_ATTR_RW(name, defval, minval, maxval, desc) \
static uint lpfc_##name = defval;\
module_param(lpfc_##name, uint, 0444);\
MODULE_PARM_DESC(lpfc_##name, desc);\
lpfc_param_show(name)\
lpfc_param_init(name, defval, minval, maxval)\
lpfc_param_store(name)\
static DEVICE_ATTR(lpfc_##name, 0444 | 0644,\
lpfc_##name##_show, lpfc_##name##_store)
#define LPFC_ATTR_HEX_R(name, defval, minval, maxval, desc) \
static uint lpfc_##name = defval;\
module_param(lpfc_##name, uint, S_IRUGO);\
MODULE_PARM_DESC(lpfc_##name, desc);\
lpfc_param_hex_show(name)\
lpfc_param_init(name, defval, minval, maxval)\
static DEVICE_ATTR(lpfc_##name, S_IRUGO, lpfc_##name##_show, NULL)
#define LPFC_ATTR_HEX_RW(name, defval, minval, maxval, desc) \
static uint lpfc_##name = defval;\
module_param(lpfc_##name, uint, S_IRUGO);\
MODULE_PARM_DESC(lpfc_##name, desc);\
lpfc_param_hex_show(name)\
lpfc_param_init(name, defval, minval, maxval)\
lpfc_param_set(name, defval, minval, maxval)\
lpfc_param_store(name)\
static DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
lpfc_##name##_show, lpfc_##name##_store)
#define LPFC_VPORT_ATTR(name, defval, minval, maxval, desc) \
static uint lpfc_##name = defval;\
module_param(lpfc_##name, uint, S_IRUGO);\
MODULE_PARM_DESC(lpfc_##name, desc);\
lpfc_vport_param_init(name, defval, minval, maxval)
#define LPFC_VPORT_ATTR_R(name, defval, minval, maxval, desc) \
static uint lpfc_##name = defval;\
module_param(lpfc_##name, uint, S_IRUGO);\
MODULE_PARM_DESC(lpfc_##name, desc);\
lpfc_vport_param_show(name)\
lpfc_vport_param_init(name, defval, minval, maxval)\
static DEVICE_ATTR(lpfc_##name, S_IRUGO, lpfc_##name##_show, NULL)
#define LPFC_VPORT_ULL_ATTR_R(name, defval, minval, maxval, desc) \
static uint64_t lpfc_##name = defval;\
module_param(lpfc_##name, ullong, S_IRUGO);\
MODULE_PARM_DESC(lpfc_##name, desc);\
lpfc_vport_param_show(name)\
lpfc_vport_param_init(name, defval, minval, maxval)\
static DEVICE_ATTR(lpfc_##name, S_IRUGO, lpfc_##name##_show, NULL)
#define LPFC_VPORT_ATTR_RW(name, defval, minval, maxval, desc) \
static uint lpfc_##name = defval;\
module_param(lpfc_##name, uint, S_IRUGO);\
MODULE_PARM_DESC(lpfc_##name, desc);\
lpfc_vport_param_show(name)\
lpfc_vport_param_init(name, defval, minval, maxval)\
lpfc_vport_param_set(name, defval, minval, maxval)\
lpfc_vport_param_store(name)\
static DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
lpfc_##name##_show, lpfc_##name##_store)
#define LPFC_VPORT_ATTR_HEX_R(name, defval, minval, maxval, desc) \
static uint lpfc_##name = defval;\
module_param(lpfc_##name, uint, S_IRUGO);\
MODULE_PARM_DESC(lpfc_##name, desc);\
lpfc_vport_param_hex_show(name)\
lpfc_vport_param_init(name, defval, minval, maxval)\
static DEVICE_ATTR(lpfc_##name, S_IRUGO, lpfc_##name##_show, NULL)
#define LPFC_VPORT_ATTR_HEX_RW(name, defval, minval, maxval, desc) \
static uint lpfc_##name = defval;\
module_param(lpfc_##name, uint, S_IRUGO);\
MODULE_PARM_DESC(lpfc_##name, desc);\
lpfc_vport_param_hex_show(name)\
lpfc_vport_param_init(name, defval, minval, maxval)\
lpfc_vport_param_set(name, defval, minval, maxval)\
lpfc_vport_param_store(name)\
static DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
lpfc_##name##_show, lpfc_##name##_store)
File diff suppressed because it is too large Load Diff
+402
View File
@@ -0,0 +1,402 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017-2024 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2010-2015 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* 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 *
* 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. *
*******************************************************************/
/* bsg definitions
* No pointers to user data are allowed, all application buffers and sizes will
* derived through the bsg interface.
*
* These are the vendor unique structures passed in using the bsg
* FC_BSG_HST_VENDOR message code type.
*/
#define LPFC_BSG_VENDOR_SET_CT_EVENT 1
#define LPFC_BSG_VENDOR_GET_CT_EVENT 2
#define LPFC_BSG_VENDOR_SEND_MGMT_RESP 3
#define LPFC_BSG_VENDOR_DIAG_MODE 4
#define LPFC_BSG_VENDOR_DIAG_RUN_LOOPBACK 5
#define LPFC_BSG_VENDOR_GET_MGMT_REV 6
#define LPFC_BSG_VENDOR_MBOX 7
#define LPFC_BSG_VENDOR_DIAG_MODE_END 10
#define LPFC_BSG_VENDOR_LINK_DIAG_TEST 11
#define LPFC_BSG_VENDOR_FORCED_LINK_SPEED 14
#define LPFC_BSG_VENDOR_RAS_GET_LWPD 16
#define LPFC_BSG_VENDOR_RAS_GET_FWLOG 17
#define LPFC_BSG_VENDOR_RAS_GET_CONFIG 18
#define LPFC_BSG_VENDOR_RAS_SET_CONFIG 19
#define LPFC_BSG_VENDOR_GET_TRUNK_INFO 20
#define LPFC_BSG_VENDOR_GET_CGNBUF_INFO 21
struct set_ct_event {
uint32_t command;
uint32_t type_mask;
uint32_t ev_req_id;
uint32_t ev_reg_id;
};
struct get_ct_event {
uint32_t command;
uint32_t ev_reg_id;
uint32_t ev_req_id;
};
struct get_ct_event_reply {
uint32_t immed_data;
uint32_t type;
};
struct send_mgmt_resp {
uint32_t command;
uint32_t tag;
};
#define DISABLE_LOOP_BACK 0x0 /* disables loop back */
#define INTERNAL_LOOP_BACK 0x1 /* adapter short cuts the loop internally */
#define EXTERNAL_LOOP_BACK 0x2 /* requires an external loopback plug */
struct diag_mode_set {
uint32_t command;
uint32_t type;
uint32_t timeout;
uint32_t physical_link;
};
struct sli4_link_diag {
uint32_t command;
uint32_t timeout;
uint32_t test_id;
uint32_t loops;
uint32_t test_version;
uint32_t error_action;
};
struct diag_mode_test {
uint32_t command;
};
struct diag_status {
uint32_t mbox_status;
uint32_t shdr_status;
uint32_t shdr_add_status;
};
#define LPFC_WWNN_TYPE 0
#define LPFC_WWPN_TYPE 1
struct get_mgmt_rev {
uint32_t command;
};
#define MANAGEMENT_MAJOR_REV 1
#define MANAGEMENT_MINOR_REV 1
/* the MgmtRevInfo structure */
struct MgmtRevInfo {
uint32_t a_Major;
uint32_t a_Minor;
};
struct get_mgmt_rev_reply {
struct MgmtRevInfo info;
};
#define BSG_MBOX_SIZE 4096 /* mailbox command plus extended data */
/* BSG mailbox request header */
struct dfc_mbox_req {
uint32_t command;
uint32_t mbOffset;
uint32_t inExtWLen;
uint32_t outExtWLen;
uint32_t extMboxTag;
uint32_t extSeqNum;
};
/*
* macros and data structures for handling sli-config mailbox command
* pass-through support, this header file is shared between user and
* kernel spaces, note the set of macros are duplicates from lpfc_hw4.h,
* with macro names prefixed with bsg_, as the macros defined in
* lpfc_hw4.h are not accessible from user space.
*/
/* Macros to deal with bit fields. Each bit field must have 3 #defines
* associated with it (_SHIFT, _MASK, and _WORD).
* EG. For a bit field that is in the 7th bit of the "field4" field of a
* structure and is 2 bits in size the following #defines must exist:
* struct temp {
* uint32_t field1;
* uint32_t field2;
* uint32_t field3;
* uint32_t field4;
* #define example_bit_field_SHIFT 7
* #define example_bit_field_MASK 0x03
* #define example_bit_field_WORD field4
* uint32_t field5;
* };
* Then the macros below may be used to get or set the value of that field.
* EG. To get the value of the bit field from the above example:
* struct temp t1;
* value = bsg_bf_get(example_bit_field, &t1);
* And then to set that bit field:
* bsg_bf_set(example_bit_field, &t1, 2);
* Or clear that bit field:
* bsg_bf_set(example_bit_field, &t1, 0);
*/
#define bsg_bf_get_le32(name, ptr) \
((le32_to_cpu((ptr)->name##_WORD) >> name##_SHIFT) & name##_MASK)
#define bsg_bf_get(name, ptr) \
(((ptr)->name##_WORD >> name##_SHIFT) & name##_MASK)
#define bsg_bf_set_le32(name, ptr, value) \
((ptr)->name##_WORD = cpu_to_le32(((((value) & \
name##_MASK) << name##_SHIFT) | (le32_to_cpu((ptr)->name##_WORD) & \
~(name##_MASK << name##_SHIFT)))))
#define bsg_bf_set(name, ptr, value) \
((ptr)->name##_WORD = ((((value) & name##_MASK) << name##_SHIFT) | \
((ptr)->name##_WORD & ~(name##_MASK << name##_SHIFT))))
/*
* The sli_config structure specified here is based on the following
* restriction:
*
* -- SLI_CONFIG EMB=0, carrying MSEs, will carry subcommands without
* carrying HBD.
* -- SLI_CONFIG EMB=1, not carrying MSE, will carry subcommands with or
* without carrying HBDs.
*/
struct lpfc_sli_config_mse {
uint32_t pa_lo;
uint32_t pa_hi;
uint32_t buf_len;
#define lpfc_mbox_sli_config_mse_len_SHIFT 0
#define lpfc_mbox_sli_config_mse_len_MASK 0xffffff
#define lpfc_mbox_sli_config_mse_len_WORD buf_len
};
struct lpfc_sli_config_hbd {
uint32_t buf_len;
#define lpfc_mbox_sli_config_ecmn_hbd_len_SHIFT 0
#define lpfc_mbox_sli_config_ecmn_hbd_len_MASK 0xffffff
#define lpfc_mbox_sli_config_ecmn_hbd_len_WORD buf_len
uint32_t pa_lo;
uint32_t pa_hi;
};
struct lpfc_sli_config_hdr {
uint32_t word1;
#define lpfc_mbox_hdr_emb_SHIFT 0
#define lpfc_mbox_hdr_emb_MASK 0x00000001
#define lpfc_mbox_hdr_emb_WORD word1
#define lpfc_mbox_hdr_mse_cnt_SHIFT 3
#define lpfc_mbox_hdr_mse_cnt_MASK 0x0000001f
#define lpfc_mbox_hdr_mse_cnt_WORD word1
uint32_t payload_length;
uint32_t tag_lo;
uint32_t tag_hi;
uint32_t reserved5;
};
#define LPFC_CSF_BOOT_DEV 0x1D
#define LPFC_CSF_QUERY 0
#define LPFC_CSF_SAVE 1
struct lpfc_sli_config_emb0_subsys {
struct lpfc_sli_config_hdr sli_config_hdr;
#define LPFC_MBX_SLI_CONFIG_MAX_MSE 19
struct lpfc_sli_config_mse mse[LPFC_MBX_SLI_CONFIG_MAX_MSE];
uint32_t padding;
uint32_t word64;
#define lpfc_emb0_subcmnd_opcode_SHIFT 0
#define lpfc_emb0_subcmnd_opcode_MASK 0xff
#define lpfc_emb0_subcmnd_opcode_WORD word64
#define lpfc_emb0_subcmnd_subsys_SHIFT 8
#define lpfc_emb0_subcmnd_subsys_MASK 0xff
#define lpfc_emb0_subcmnd_subsys_WORD word64
/* Subsystem FCOE (0x0C) OpCodes */
#define SLI_CONFIG_SUBSYS_FCOE 0x0C
#define FCOE_OPCODE_READ_FCF 0x08
#define FCOE_OPCODE_ADD_FCF 0x09
#define FCOE_OPCODE_SET_DPORT_MODE 0x27
#define FCOE_OPCODE_GET_DPORT_RESULTS 0x28
uint32_t timeout; /* comn_set_feature timeout */
uint32_t request_length; /* comn_set_feature request len */
uint32_t version; /* comn_set_feature version */
uint32_t word68; /* comn_set_feature feature */
#define lpfc_emb0_subcmnd_csf_feat_SHIFT 0
#define lpfc_emb0_subcmnd_csf_feat_MASK 0xffffffff
#define lpfc_emb0_subcmnd_csf_feat_WORD word68
#define lpfc_emb0_subcmnd_rd_obj_des_rd_len_SHIFT 0
#define lpfc_emb0_subcmnd_rd_obj_des_rd_len_MASK 0x00ffffff
#define lpfc_emb0_subcmnd_rd_obj_des_rd_len_WORD word68
uint32_t word69; /* comn_set_feature parameter len */
uint32_t word70; /* comn_set_feature parameter val0 */
#define lpfc_emb0_subcmnd_csf_p0_SHIFT 0
#define lpfc_emb0_subcmnd_csf_p0_MASK 0x3
#define lpfc_emb0_subcmnd_csf_p0_WORD word70
uint32_t reserved71[25];
uint32_t word96; /* rd_obj hbd_count */
#define lpfc_emb0_subcmnd_rd_obj_hbd_cnt_SHIFT 0
#define lpfc_emb0_subcmnd_rd_obj_hbd_cnt_MASK 0xffffffff
#define lpfc_emb0_subcmnd_rd_obj_hbd_cnt_WORD word96
#define LPFC_EMB0_MAX_RD_OBJ_HBD_CNT 31
struct lpfc_sli_config_hbd hbd[LPFC_EMB0_MAX_RD_OBJ_HBD_CNT];
uint32_t word190;
uint32_t word191;
};
struct lpfc_sli_config_emb1_subsys {
struct lpfc_sli_config_hdr sli_config_hdr;
uint32_t word6;
#define lpfc_emb1_subcmnd_opcode_SHIFT 0
#define lpfc_emb1_subcmnd_opcode_MASK 0xff
#define lpfc_emb1_subcmnd_opcode_WORD word6
#define lpfc_emb1_subcmnd_subsys_SHIFT 8
#define lpfc_emb1_subcmnd_subsys_MASK 0xff
#define lpfc_emb1_subcmnd_subsys_WORD word6
/* Subsystem COMN (0x01) OpCodes */
#define SLI_CONFIG_SUBSYS_COMN 0x01
#define COMN_OPCODE_GET_PROFILE_CONFIG 0xA4
#define COMN_OPCODE_READ_OBJECT 0xAB
#define COMN_OPCODE_WRITE_OBJECT 0xAC
#define COMN_OPCODE_READ_OBJECT_LIST 0xAD
#define COMN_OPCODE_DELETE_OBJECT 0xAE
#define COMN_OPCODE_SET_FEATURES 0xBF
#define COMN_OPCODE_GET_CNTL_ADDL_ATTRIBUTES 0x79
#define COMN_OPCODE_GET_CNTL_ATTRIBUTES 0x20
uint32_t timeout;
uint32_t request_length;
uint32_t word9;
#define lpfc_subcmnd_version_SHIFT 0
#define lpfc_subcmnd_version_MASK 0xff
#define lpfc_subcmnd_version_WORD word9
uint32_t word10;
#define lpfc_subcmnd_ask_rd_len_SHIFT 0
#define lpfc_subcmnd_ask_rd_len_MASK 0xffffff
#define lpfc_subcmnd_ask_rd_len_WORD word10
uint32_t rd_offset;
uint32_t obj_name[26];
uint32_t hbd_count;
#define LPFC_MBX_SLI_CONFIG_MAX_HBD 8
struct lpfc_sli_config_hbd hbd[LPFC_MBX_SLI_CONFIG_MAX_HBD];
};
struct lpfc_sli_config_mbox {
uint32_t word0;
#define lpfc_mqe_status_SHIFT 16
#define lpfc_mqe_status_MASK 0x0000FFFF
#define lpfc_mqe_status_WORD word0
#define lpfc_mqe_command_SHIFT 8
#define lpfc_mqe_command_MASK 0x000000FF
#define lpfc_mqe_command_WORD word0
union {
struct lpfc_sli_config_emb0_subsys sli_config_emb0_subsys;
struct lpfc_sli_config_emb1_subsys sli_config_emb1_subsys;
} un;
};
#define LPFC_FORCED_LINK_SPEED_NOT_SUPPORTED 0
#define LPFC_FORCED_LINK_SPEED_SUPPORTED 1
struct get_forced_link_speed_support {
uint32_t command;
};
struct forced_link_speed_support_reply {
uint8_t supported;
};
struct lpfc_bsg_ras_req {
uint32_t command;
};
struct lpfc_bsg_get_fwlog_req {
uint32_t command;
uint32_t read_size;
uint32_t read_offset;
};
struct lpfc_bsg_get_ras_lwpd {
uint32_t offset;
uint32_t wrap_count;
};
struct lpfc_bsg_set_ras_config_req {
uint32_t command;
uint8_t action;
#define LPFC_RASACTION_STOP_LOGGING 0x00
#define LPFC_RASACTION_START_LOGGING 0x01
uint8_t log_level;
};
struct lpfc_bsg_get_ras_config_reply {
uint8_t state;
#define LPFC_RASLOG_STATE_STOPPED 0x00
#define LPFC_RASLOG_STATE_RUNNING 0x01
uint8_t log_level;
uint32_t log_buff_sz;
};
struct lpfc_trunk_info {
uint32_t word0;
#define lpfc_trunk_info_link_status_SHIFT 0
#define lpfc_trunk_info_link_status_MASK 1
#define lpfc_trunk_info_link_status_WORD word0
#define lpfc_trunk_info_trunk_active0_SHIFT 8
#define lpfc_trunk_info_trunk_active0_MASK 1
#define lpfc_trunk_info_trunk_active0_WORD word0
#define lpfc_trunk_info_trunk_active1_SHIFT 9
#define lpfc_trunk_info_trunk_active1_MASK 1
#define lpfc_trunk_info_trunk_active1_WORD word0
#define lpfc_trunk_info_trunk_active2_SHIFT 10
#define lpfc_trunk_info_trunk_active2_MASK 1
#define lpfc_trunk_info_trunk_active2_WORD word0
#define lpfc_trunk_info_trunk_active3_SHIFT 11
#define lpfc_trunk_info_trunk_active3_MASK 1
#define lpfc_trunk_info_trunk_active3_WORD word0
#define lpfc_trunk_info_trunk_config0_SHIFT 12
#define lpfc_trunk_info_trunk_config0_MASK 1
#define lpfc_trunk_info_trunk_config0_WORD word0
#define lpfc_trunk_info_trunk_config1_SHIFT 13
#define lpfc_trunk_info_trunk_config1_MASK 1
#define lpfc_trunk_info_trunk_config1_WORD word0
#define lpfc_trunk_info_trunk_config2_SHIFT 14
#define lpfc_trunk_info_trunk_config2_MASK 1
#define lpfc_trunk_info_trunk_config2_WORD word0
#define lpfc_trunk_info_trunk_config3_SHIFT 15
#define lpfc_trunk_info_trunk_config3_MASK 1
#define lpfc_trunk_info_trunk_config3_WORD word0
uint16_t port_speed;
uint16_t logical_speed;
uint32_t reserved3;
};
struct get_trunk_info_req {
uint32_t command;
};
struct get_cgnbuf_info_req {
uint32_t command;
uint32_t read_size;
uint32_t reset;
#define LPFC_BSG_CGN_RESET_STAT 1
};
/* driver only */
#define SLI_CONFIG_NOT_HANDLED 0
#define SLI_CONFIG_HANDLED 1
@@ -0,0 +1,98 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2011 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* 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 *
* 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. *
*******************************************************************/
/*
* This file provides macros to aid compilation in the Linux 2.4 kernel
* over various platform architectures.
*/
/*******************************************************************
Note: HBA's SLI memory contains little-endian LW.
Thus to access it from a little-endian host,
memcpy_toio() and memcpy_fromio() can be used.
However on a big-endian host, copy 4 bytes at a time,
using writel() and readl().
*******************************************************************/
#include <asm/byteorder.h>
#ifdef __BIG_ENDIAN
static inline void
lpfc_memcpy_to_slim(void __iomem *dest, void *src, unsigned int bytes)
{
uint32_t __iomem *dest32;
uint32_t *src32;
unsigned int four_bytes;
dest32 = (uint32_t __iomem *) dest;
src32 = (uint32_t *) src;
/* write input bytes, 4 bytes at a time */
for (four_bytes = bytes /4; four_bytes > 0; four_bytes--) {
writel( *src32, dest32);
readl(dest32); /* flush */
dest32++;
src32++;
}
return;
}
static inline void
lpfc_memcpy_from_slim( void *dest, void __iomem *src, unsigned int bytes)
{
uint32_t *dest32;
uint32_t __iomem *src32;
unsigned int four_bytes;
dest32 = (uint32_t *) dest;
src32 = (uint32_t __iomem *) src;
/* read input bytes, 4 bytes at a time */
for (four_bytes = bytes /4; four_bytes > 0; four_bytes--) {
*dest32 = readl( src32);
dest32++;
src32++;
}
return;
}
#else
static inline void
lpfc_memcpy_to_slim( void __iomem *dest, void *src, unsigned int bytes)
{
/* convert bytes in argument list to word count for copy function */
__iowrite32_copy(dest, src, bytes / sizeof(uint32_t));
}
static inline void
lpfc_memcpy_from_slim( void *dest, void __iomem *src, unsigned int bytes)
{
/* actually returns 1 byte past dest */
memcpy_fromio( dest, src, bytes);
}
#endif /* __BIG_ENDIAN */
+696
View File
@@ -0,0 +1,696 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017-2026 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* 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 *
* 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. *
*******************************************************************/
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);
void lpfc_dump_wakeup_param(struct lpfc_hba *, LPFC_MBOXQ_t *);
int lpfc_dump_static_vport(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t);
int lpfc_sli4_dump_cfg_rg23(struct lpfc_hba *, struct lpfcMboxq *);
void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_config_async(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t);
int lpfc_mbox_rsrc_prep(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox);
void lpfc_mbox_rsrc_cleanup(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox,
enum lpfc_mbox_ctx locked);
void lpfc_heart_beat(struct lpfc_hba *, LPFC_MBOXQ_t *);
int lpfc_read_topology(struct lpfc_hba *, LPFC_MBOXQ_t *, struct lpfc_dmabuf *);
void lpfc_clear_la(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_issue_clear_la(struct lpfc_hba *, struct lpfc_vport *);
void lpfc_config_link(struct lpfc_hba *, LPFC_MBOXQ_t *);
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_rpi(struct lpfc_hba *, uint16_t, uint32_t, uint8_t *,
LPFC_MBOXQ_t *, uint16_t);
void lpfc_set_var(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_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_sli4_unreg_all_rpis(struct lpfc_vport *);
void lpfc_reg_vpi(struct lpfc_vport *, LPFC_MBOXQ_t *);
void lpfc_register_new_vport(struct lpfc_hba *, struct lpfc_vport *,
struct lpfc_nodelist *);
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 *);
int lpfc_sli4_mbox_rsrc_extent(struct lpfc_hba *, struct lpfcMboxq *,
uint16_t, uint16_t, bool);
int lpfc_get_sli4_parameters(struct lpfc_hba *, LPFC_MBOXQ_t *);
int lpfc_reg_congestion_buf(struct lpfc_hba *phba);
int lpfc_unreg_congestion_buf(struct lpfc_hba *phba);
struct lpfc_vport *lpfc_find_vport_by_did(struct lpfc_hba *, uint32_t);
void lpfc_cleanup_rcv_buffers(struct lpfc_vport *);
void lpfc_rcv_seq_check_edtov(struct lpfc_vport *);
void lpfc_cleanup_rpis(struct lpfc_vport *, int);
void lpfc_cleanup_pending_mbox(struct lpfc_vport *);
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_topology(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_init_vpi_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_cancel_all_vport_retry_delay_timer(struct lpfc_hba *);
void lpfc_retry_pport_discovery(struct lpfc_hba *);
int lpfc_init_iocb_list(struct lpfc_hba *phba, int cnt);
void lpfc_free_iocb_list(struct lpfc_hba *phba);
int lpfc_post_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *hrq,
struct lpfc_queue *drq, int count, int idx);
int lpfc_read_lds_params(struct lpfc_hba *phba);
uint32_t lpfc_calc_cmf_latency(struct lpfc_hba *phba);
void lpfc_cmf_signal_init(struct lpfc_hba *phba);
void lpfc_cmf_start(struct lpfc_hba *phba);
void lpfc_cmf_stop(struct lpfc_hba *phba);
void lpfc_init_congestion_stat(struct lpfc_hba *phba);
void lpfc_init_congestion_buf(struct lpfc_hba *phba);
int lpfc_sli4_cgn_params_read(struct lpfc_hba *phba);
uint32_t lpfc_cgn_calc_crc32(const void *data, size_t size);
int lpfc_config_cgn_signal(struct lpfc_hba *phba);
int lpfc_issue_cmf_sync_wqe(struct lpfc_hba *phba, u32 ms, u64 total);
void lpfc_cgn_dump_rxmonitor(struct lpfc_hba *phba);
void lpfc_cgn_update_stat(struct lpfc_hba *phba, uint32_t dtag);
void lpfc_unblock_requests(struct lpfc_hba *phba);
void lpfc_block_requests(struct lpfc_hba *phba);
int lpfc_rx_monitor_create_ring(struct lpfc_rx_info_monitor *rx_monitor,
u32 entries);
void lpfc_rx_monitor_destroy_ring(struct lpfc_rx_info_monitor *rx_monitor);
void lpfc_rx_monitor_record(struct lpfc_rx_info_monitor *rx_monitor,
struct rx_info_entry *entry);
u32 lpfc_rx_monitor_report(struct lpfc_hba *phba,
struct lpfc_rx_info_monitor *rx_monitor, char *buf,
u32 buf_len, u32 max_read_entries);
void lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_mbx_cmpl_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_mbx_cmpl_fc_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb);
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_unregister_vfi_cmpl(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 *);
void lpfc_nlp_set_state(struct lpfc_vport *, struct lpfc_nodelist *, int);
void lpfc_nlp_reg_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp);
void lpfc_nlp_unreg_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp);
void lpfc_drop_node(struct lpfc_vport *, struct lpfc_nodelist *);
void lpfc_set_disctmo(struct lpfc_vport *);
int lpfc_can_disctmo(struct lpfc_vport *);
int lpfc_unreg_rpi(struct lpfc_vport *, struct lpfc_nodelist *);
void lpfc_unreg_all_rpis(struct lpfc_vport *);
void lpfc_unreg_hba_rpis(struct lpfc_hba *);
void lpfc_unreg_default_rpis(struct lpfc_vport *);
void lpfc_issue_reg_vpi(struct lpfc_hba *, struct lpfc_vport *);
int lpfc_check_sli_ndlp(struct lpfc_hba *, struct lpfc_sli_ring *,
struct lpfc_iocbq *, struct lpfc_nodelist *);
struct lpfc_nodelist *lpfc_nlp_init(struct lpfc_vport *vport, uint32_t did);
struct lpfc_nodelist *lpfc_nlp_get(struct lpfc_nodelist *);
int lpfc_nlp_put(struct lpfc_nodelist *);
void lpfc_check_nlp_post_devloss(struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp);
void lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb);
struct lpfc_nodelist *lpfc_setup_disc_node(struct lpfc_vport *, uint32_t);
void lpfc_disc_list_loopmap(struct lpfc_vport *);
void lpfc_disc_start(struct lpfc_vport *);
void lpfc_cleanup_discovery_resources(struct lpfc_vport *);
void lpfc_cleanup(struct lpfc_vport *);
void lpfc_prep_embed_io(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_ncmd);
void lpfc_disc_timeout(struct timer_list *);
int lpfc_unregister_fcf_prep(struct lpfc_hba *);
struct lpfc_nodelist *__lpfc_findnode_rpi(struct lpfc_vport *, uint16_t);
struct lpfc_nodelist *lpfc_findnode_rpi(struct lpfc_vport *, uint16_t);
void lpfc_worker_wake_up(struct lpfc_hba *);
int lpfc_workq_post_event(struct lpfc_hba *, void *, void *, uint32_t);
int lpfc_do_work(void *);
int lpfc_disc_state_machine(struct lpfc_vport *, struct lpfc_nodelist *, void *,
uint32_t);
void lpfc_do_scr_ns_plogi(struct lpfc_hba *, struct lpfc_vport *);
int lpfc_check_sparm(struct lpfc_vport *, struct lpfc_nodelist *,
struct serv_parm *, uint32_t, int);
void lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist *);
void lpfc_more_plogi(struct lpfc_vport *);
void lpfc_more_adisc(struct lpfc_vport *);
void lpfc_end_rscn(struct lpfc_vport *);
int lpfc_els_chk_latt(struct lpfc_vport *);
int lpfc_els_abort_flogi(struct lpfc_hba *);
int lpfc_initial_flogi(struct lpfc_vport *);
void lpfc_issue_init_vfi(struct lpfc_vport *);
int lpfc_initial_fdisc(struct lpfc_vport *);
int lpfc_issue_els_plogi(struct lpfc_vport *, uint32_t, uint8_t);
int lpfc_issue_els_prli(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t);
int lpfc_issue_els_adisc(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t);
int lpfc_issue_els_logo(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t);
int lpfc_issue_els_npiv_logo(struct lpfc_vport *, struct lpfc_nodelist *);
int lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry);
int lpfc_issue_els_rscn(struct lpfc_vport *vport, uint8_t retry);
int lpfc_issue_fabric_reglogin(struct lpfc_vport *);
int lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry);
int lpfc_issue_els_edc(struct lpfc_vport *vport, uint8_t retry);
void lpfc_els_rcv_fpin(struct lpfc_vport *vport, void *p, u32 fpin_length);
int lpfc_els_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *);
int lpfc_ct_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *);
int lpfc_els_rsp_acc(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *,
struct lpfc_nodelist *, LPFC_MBOXQ_t *);
int lpfc_els_rsp_reject(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *,
struct lpfc_nodelist *, LPFC_MBOXQ_t *);
int lpfc_els_rsp_adisc_acc(struct lpfc_vport *, struct lpfc_iocbq *,
struct lpfc_nodelist *);
int lpfc_els_rsp_prli_acc(struct lpfc_vport *, struct lpfc_iocbq *,
struct lpfc_nodelist *);
void lpfc_cancel_retry_delay_tmo(struct lpfc_vport *, struct lpfc_nodelist *);
void lpfc_els_retry_delay(struct timer_list *);
void lpfc_els_retry_delay_handler(struct lpfc_nodelist *);
void lpfc_els_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *,
struct lpfc_iocbq *);
int lpfc_els_handle_rscn(struct lpfc_vport *);
void lpfc_els_flush_rscn(struct lpfc_vport *);
int lpfc_rscn_payload_check(struct lpfc_vport *, uint32_t);
void lpfc_els_flush_all_cmd(struct lpfc_hba *);
void lpfc_els_flush_cmd(struct lpfc_vport *);
int lpfc_els_disc_adisc(struct lpfc_vport *);
int lpfc_els_disc_plogi(struct lpfc_vport *);
void lpfc_els_timeout(struct timer_list *);
void lpfc_els_timeout_handler(struct lpfc_vport *);
struct lpfc_iocbq *lpfc_prep_els_iocb(struct lpfc_vport *, uint8_t, uint16_t,
uint8_t, struct lpfc_nodelist *,
uint32_t, uint32_t);
void lpfc_sli_prep_wqe(struct lpfc_hba *phba, struct lpfc_iocbq *job);
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_gidpt(struct lpfc_vport *vport);
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_change_check(struct lpfc_vport *vport);
void lpfc_delayed_disc_tmo(struct timer_list *);
void lpfc_delayed_disc_timeout_handler(struct lpfc_vport *);
int lpfc_config_port_prep(struct lpfc_hba *);
void lpfc_update_vport_wwn(struct lpfc_vport *vport);
int lpfc_config_port_post(struct lpfc_hba *);
int lpfc_sli4_refresh_params(struct lpfc_hba *phba);
int lpfc_hba_down_prep(struct lpfc_hba *);
int lpfc_hba_down_post(struct lpfc_hba *);
void lpfc_hba_init(struct lpfc_hba *, uint32_t *);
int lpfc_sli3_post_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, int cnt);
void lpfc_decode_firmware_rev(struct lpfc_hba *, char *, int);
int lpfc_online(struct lpfc_hba *);
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_sli_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 *);
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_hba_intr_handler(int, void *);
irqreturn_t lpfc_sli4_hba_intr_handler_th(int irq, void *dev_id);
int lpfc_read_object(struct lpfc_hba *phba, char *s, uint32_t *datap,
uint32_t len);
void lpfc_sli4_cleanup_poll_list(struct lpfc_hba *phba);
void lpfc_sli4_poll_hbtimer(struct timer_list *t);
void lpfc_sli4_start_polling(struct lpfc_queue *q);
void lpfc_sli4_stop_polling(struct lpfc_queue *q);
void lpfc_read_rev(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_sli4_swap_str(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_config_ring(struct lpfc_hba *, int, LPFC_MBOXQ_t *);
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 *, LPFC_MBOXQ_t *);
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 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);
void lpfc_issue_init_vpi(struct lpfc_vport *);
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 *);
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_nvmet_ctxbuf_post(struct lpfc_hba *phba,
struct lpfc_nvmet_ctxbuf *ctxp);
int lpfc_nvmet_rcv_unsol_abort(struct lpfc_vport *vport,
struct fc_frame_header *fc_hdr);
void lpfc_nvmet_wqfull_process(struct lpfc_hba *phba, struct lpfc_queue *wq);
void lpfc_nvme_wait_for_io_drain(struct lpfc_hba *phba);
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_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 *);
int lpfc_sli4_redisc_fcf_table(struct lpfc_hba *);
void lpfc_fcf_redisc_wait_start_timer(struct lpfc_hba *);
void lpfc_sli4_fcf_dead_failthrough(struct lpfc_hba *);
uint16_t lpfc_sli4_fcf_rr_next_index_get(struct lpfc_hba *);
void lpfc_sli4_set_fcf_flogi_fail(struct lpfc_hba *, uint16_t);
int lpfc_sli4_fcf_rr_index_set(struct lpfc_hba *, uint16_t);
void lpfc_sli4_fcf_rr_index_clear(struct lpfc_hba *, uint16_t);
int lpfc_sli4_fcf_rr_next_proc(struct lpfc_vport *, uint16_t);
void lpfc_sli4_clear_fcf_rr_bmask(struct lpfc_hba *);
int lpfc_mem_alloc(struct lpfc_hba *, int align);
int lpfc_nvmet_mem_alloc(struct lpfc_hba *phba);
int lpfc_mem_alloc_active_rrq_pool_s4(struct lpfc_hba *);
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(struct timer_list *t);
void lpfc_poll_start_timer(struct lpfc_hba *);
void lpfc_poll_eratt(struct timer_list *);
int
lpfc_sli_handle_fast_ring_event(struct lpfc_hba *,
struct lpfc_sli_ring *, uint32_t);
struct lpfc_iocbq *__lpfc_sli_get_iocbq(struct lpfc_hba *);
struct lpfc_iocbq * lpfc_sli_get_iocbq(struct lpfc_hba *);
void lpfc_sli_release_iocbq(struct lpfc_hba *, struct lpfc_iocbq *);
uint16_t lpfc_sli_next_iotag(struct lpfc_hba *, struct lpfc_iocbq *);
void lpfc_sli_cancel_iocbs(struct lpfc_hba *, struct list_head *, uint32_t,
uint32_t);
void lpfc_sli_wake_mbox_wait(struct lpfc_hba *, LPFC_MBOXQ_t *);
int lpfc_selective_reset(struct lpfc_hba *);
void lpfc_reset_barrier(struct lpfc_hba *);
int lpfc_sli_brdready(struct lpfc_hba *, uint32_t);
int lpfc_sli_brdkill(struct lpfc_hba *);
int lpfc_sli_chipset_init(struct lpfc_hba *phba);
int lpfc_sli_brdreset(struct lpfc_hba *);
int lpfc_sli_brdrestart(struct lpfc_hba *);
int lpfc_sli_hba_setup(struct lpfc_hba *);
int lpfc_sli_config_port(struct lpfc_hba *, int);
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 *);
void lpfc_sli_mbox_sys_shutdown(struct lpfc_hba *, int);
int lpfc_sli_check_eratt(struct lpfc_hba *);
void lpfc_sli_handle_slow_ring_event(struct lpfc_hba *,
struct lpfc_sli_ring *, uint32_t);
void lpfc_sli4_handle_received_buffer(struct lpfc_hba *, struct hbq_dmabuf *);
void lpfc_sli4_seq_abort_rsp(struct lpfc_vport *vport,
struct fc_frame_header *fc_hdr, bool aborted);
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_sli_issue_fcp_io(struct lpfc_hba *phba, uint32_t ring_number,
struct lpfc_iocbq *piocb, uint32_t flag);
int lpfc_sli4_issue_wqe(struct lpfc_hba *phba, struct lpfc_sli4_hdw_queue *qp,
struct lpfc_iocbq *pwqe);
int lpfc_sli4_issue_abort_iotag(struct lpfc_hba *phba,
struct lpfc_iocbq *cmdiocb, void *cmpl);
void lpfc_sli_prep_els_req_rsp(struct lpfc_hba *phba,
struct lpfc_iocbq *cmdiocbq,
struct lpfc_vport *vport,
struct lpfc_dmabuf *bmp, u16 cmd_size, u32 did,
u32 elscmd, u8 tmo, u8 expect_rsp);
void lpfc_sli_prep_gen_req(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocbq,
struct lpfc_dmabuf *bmp, u16 rpi, u32 num_entry,
u8 tmo);
void lpfc_sli_prep_xmit_seq64(struct lpfc_hba *phba,
struct lpfc_iocbq *cmdiocbq,
struct lpfc_dmabuf *bmp, u16 rpi, u16 ox_id,
u32 num_entry, u8 rctl, u8 last_seq,
u8 cr_cx_cmd);
void lpfc_sli_prep_abort_xri(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocbq,
u16 ulp_context, u16 iotag, u8 ulp_class, u16 cqid,
bool ia, bool wqec);
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 *);
void lpfc_sli_abort_fcp_rings(struct lpfc_hba *phba);
void lpfc_sli_hba_iocb_abort(struct lpfc_hba *);
void lpfc_sli_flush_io_rings(struct lpfc_hba *phba);
int lpfc_sli_ringpostbuf_put(struct lpfc_hba *, struct lpfc_sli_ring *,
struct lpfc_dmabuf *);
struct lpfc_dmabuf *lpfc_sli_ringpostbuf_get(struct lpfc_hba *,
struct lpfc_sli_ring *,
dma_addr_t);
uint32_t lpfc_sli_get_buffer_tag(struct lpfc_hba *);
struct lpfc_dmabuf * lpfc_sli_ring_taggedbuf_get(struct lpfc_hba *,
struct lpfc_sli_ring *, uint32_t );
int lpfc_sli_hbq_count(void);
int lpfc_sli_hbqbuf_add_hbqs(struct lpfc_hba *, uint32_t);
void lpfc_sli_hbqbuf_free_all(struct lpfc_hba *);
int lpfc_sli_hbq_size(void);
int lpfc_sli_issue_abort_iotag(struct lpfc_hba *, struct lpfc_sli_ring *,
struct lpfc_iocbq *, void *);
int lpfc_sli_sum_iocb(struct lpfc_vport *, uint16_t, uint64_t, lpfc_ctx_cmd);
int lpfc_sli_abort_iocb(struct lpfc_vport *vport, u16 tgt_id, u64 lun_id,
lpfc_ctx_cmd abort_cmd);
int
lpfc_sli_abort_taskmgmt(struct lpfc_vport *, struct lpfc_sli_ring *,
uint16_t, uint64_t, lpfc_ctx_cmd);
void lpfc_mbox_timeout(struct timer_list *t);
void lpfc_mbox_timeout_handler(struct lpfc_hba *);
int lpfc_issue_hb_mbox(struct lpfc_hba *phba);
void lpfc_issue_hb_tmo(struct lpfc_hba *phba);
struct lpfc_nodelist *lpfc_findnode_did(struct lpfc_vport *, uint32_t);
struct lpfc_nodelist *lpfc_findnode_wwpn(struct lpfc_vport *,
struct lpfc_name *);
struct lpfc_nodelist *lpfc_findnode_mapped(struct lpfc_vport *vport);
int lpfc_sli_issue_mbox_wait(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t);
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 *,
struct lpfc_iocbq *);
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);
void lpfc_setup_fdmi_mask(struct lpfc_vport *vport);
int lpfc_link_reset(struct lpfc_vport *vport);
/* Function prototypes. */
int lpfc_check_pci_resettable(struct lpfc_hba *phba);
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 *);
void lpfc_free_sysfs_attr(struct lpfc_vport *);
bool lpfc_error_lost_link(struct lpfc_vport *vport, u32 ulp_status,
u32 ulp_word4);
extern const struct attribute_group *lpfc_hba_groups[];
extern const struct attribute_group *lpfc_vport_groups[];
extern struct scsi_host_template lpfc_template;
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;
int lpfc_vport_symbolic_node_name(struct lpfc_vport *, char *, size_t);
int lpfc_vport_symbolic_port_name(struct lpfc_vport *, char *, size_t);
void lpfc_terminate_rport_io(struct fc_rport *);
void lpfc_dev_loss_tmo_callbk(struct fc_rport *rport);
struct lpfc_vport *lpfc_create_port(struct lpfc_hba *, int, struct device *);
int lpfc_vport_disable(struct fc_vport *fc_vport, bool disable);
int lpfc_mbx_unreg_vpi(struct lpfc_vport *);
void destroy_port(struct lpfc_vport *);
int lpfc_get_instance(void);
void lpfc_host_attrib_init(struct Scsi_Host *);
extern void lpfc_debugfs_initialize(struct lpfc_vport *);
extern void lpfc_debugfs_terminate(struct lpfc_vport *);
extern void lpfc_debugfs_disc_trc(struct lpfc_vport *, int, char *, uint32_t,
uint32_t, uint32_t);
extern void lpfc_debugfs_slow_ring_trc(struct lpfc_hba *, char *, 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. */
int lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *);
int lpfc_sli4_dealloc_resource_identifiers(struct lpfc_hba *);
int lpfc_sli4_get_allocated_extnts(struct lpfc_hba *, uint16_t,
uint16_t *, uint16_t *);
int lpfc_sli4_get_avail_extnt_rsrc(struct lpfc_hba *, uint16_t,
uint16_t *, uint16_t *);
/* Interface exported by fabric iocb scheduler */
void lpfc_fabric_abort_nport(struct lpfc_nodelist *);
void lpfc_fabric_abort_hba(struct lpfc_hba *);
void lpfc_fabric_block_timeout(struct timer_list *);
void lpfc_unblock_fabric_iocbs(struct lpfc_hba *);
void lpfc_rampdown_queue_depth(struct lpfc_hba *);
void lpfc_ramp_down_queue_handler(struct lpfc_hba *);
void lpfc_scsi_dev_block(struct lpfc_hba *);
void
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 *);
int lpfc_update_cmf_cmd(struct lpfc_hba *phba, uint32_t sz);
int lpfc_update_cmf_cmpl(struct lpfc_hba *phba, uint64_t val, uint32_t sz,
struct Scsi_Host *shost);
void __lpfc_sli4_stop_fcf_redisc_wait_timer(struct lpfc_hba *);
void lpfc_sli4_stop_fcf_redisc_wait_timer(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);
struct lpfc_vport *lpfc_find_vport_by_vpid(struct lpfc_hba *, uint16_t);
struct lpfc_sglq *__lpfc_get_active_sglq(struct lpfc_hba *, uint16_t);
#define HBA_EVENT_RSCN 5
#define HBA_EVENT_LINK_UP 2
#define HBA_EVENT_LINK_DOWN 3
/* functions to support SGIOv4/bsg interface */
int lpfc_bsg_request(struct bsg_job *);
int lpfc_bsg_timeout(struct bsg_job *);
int lpfc_bsg_ct_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *,
struct lpfc_iocbq *);
int lpfc_bsg_ct_unsol_abort(struct lpfc_hba *, struct hbq_dmabuf *);
void __lpfc_sli_ringtx_put(struct lpfc_hba *, struct lpfc_sli_ring *,
struct lpfc_iocbq *);
struct lpfc_iocbq *lpfc_sli_ringtx_get(struct lpfc_hba *,
struct lpfc_sli_ring *);
int __lpfc_sli_issue_iocb(struct lpfc_hba *, uint32_t,
struct lpfc_iocbq *, uint32_t);
uint32_t lpfc_drain_txq(struct lpfc_hba *);
void lpfc_clr_rrq_active(struct lpfc_hba *, uint16_t, struct lpfc_node_rrq *);
int lpfc_test_rrq_active(struct lpfc_hba *, struct lpfc_nodelist *, uint16_t);
void lpfc_handle_rrq_active(struct lpfc_hba *);
int lpfc_send_rrq(struct lpfc_hba *, struct lpfc_node_rrq *);
int lpfc_set_rrq_active(struct lpfc_hba *, struct lpfc_nodelist *,
uint16_t, uint16_t, uint16_t);
uint16_t lpfc_sli4_xri_inrange(struct lpfc_hba *, uint16_t);
void lpfc_cleanup_vports_rrqs(struct lpfc_vport *, struct lpfc_nodelist *);
struct lpfc_node_rrq *lpfc_get_active_rrq(struct lpfc_vport *, uint16_t,
uint32_t);
void lpfc_idiag_mbxacc_dump_bsg_mbox(struct lpfc_hba *, enum nemb_type,
enum mbox_type, enum dma_type, enum sta_type,
struct lpfc_dmabuf *, uint32_t);
void lpfc_idiag_mbxacc_dump_issue_mbox(struct lpfc_hba *, MAILBOX_t *);
int lpfc_wr_object(struct lpfc_hba *, struct list_head *, uint32_t, uint32_t *);
/* functions to support SR-IOV */
int lpfc_sli_probe_sriov_nr_virtfn(struct lpfc_hba *, int);
uint16_t lpfc_sli_sriov_nr_virtfn_get(struct lpfc_hba *);
int lpfc_sli4_queue_create(struct lpfc_hba *);
void lpfc_sli4_queue_destroy(struct lpfc_hba *);
void lpfc_sli4_abts_err_handler(struct lpfc_hba *, struct lpfc_nodelist *,
struct sli4_wcqe_xri_aborted *);
void lpfc_sli_abts_recover_port(struct lpfc_vport *,
struct lpfc_nodelist *);
int lpfc_hba_init_link_fc_topology(struct lpfc_hba *, uint32_t, uint32_t);
int lpfc_issue_reg_vfi(struct lpfc_vport *);
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_rpi_restore(struct lpfc_hba *phba);
int lpfc_sli4_els_sgl_update(struct lpfc_hba *phba);
int lpfc_sli4_nvmet_sgl_update(struct lpfc_hba *phba);
int lpfc_io_buf_flush(struct lpfc_hba *phba, struct list_head *sglist);
int lpfc_io_buf_replenish(struct lpfc_hba *phba, struct list_head *cbuf);
int lpfc_sli4_io_sgl_update(struct lpfc_hba *phba);
int lpfc_sli4_post_io_sgl_list(struct lpfc_hba *phba,
struct list_head *blist, int xricnt);
int lpfc_new_io_buf(struct lpfc_hba *phba, int num_to_alloc);
void lpfc_io_free(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);
void lpfc_sli4_offline_eratt(struct lpfc_hba *);
struct lpfc_device_data *lpfc_create_device_data(struct lpfc_hba *,
struct lpfc_name *,
struct lpfc_name *,
uint64_t, uint32_t, bool);
void lpfc_delete_device_data(struct lpfc_hba *, struct lpfc_device_data*);
struct lpfc_device_data *__lpfc_get_device_data(struct lpfc_hba *,
struct list_head *list,
struct lpfc_name *,
struct lpfc_name *, uint64_t);
bool lpfc_enable_oas_lun(struct lpfc_hba *, struct lpfc_name *,
struct lpfc_name *, uint64_t, uint8_t);
bool lpfc_disable_oas_lun(struct lpfc_hba *, struct lpfc_name *,
struct lpfc_name *, uint64_t, uint8_t);
bool lpfc_find_next_oas_lun(struct lpfc_hba *, struct lpfc_name *,
struct lpfc_name *, uint64_t *, struct lpfc_name *,
struct lpfc_name *, uint64_t *,
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);
/* RAS Interface */
void lpfc_sli4_ras_init(struct lpfc_hba *phba);
void lpfc_sli4_ras_setup(struct lpfc_hba *phba);
int lpfc_sli4_ras_fwlog_init(struct lpfc_hba *phba, uint32_t fwlog_level,
uint32_t fwlog_enable);
void lpfc_ras_stop_fwlog(struct lpfc_hba *phba);
int lpfc_check_fwlog_support(struct lpfc_hba *phba);
/* NVME interfaces. */
void lpfc_nvme_rescan_port(struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp);
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);
int lpfc_nvme_handle_lsreq(struct lpfc_hba *phba,
struct lpfc_async_xchg_ctx *axchg);
int lpfc_nvmet_handle_lsreq(struct lpfc_hba *phba,
struct lpfc_async_xchg_ctx *axchg);
void lpfc_nvmet_unsol_fcp_event(struct lpfc_hba *phba, uint32_t idx,
struct rqb_dmabuf *nvmebuf, uint64_t isr_ts,
uint8_t cqflag);
void lpfc_nvme_mod_param_dep(struct lpfc_hba *phba);
void lpfc_nvmet_invalidate_host(struct lpfc_hba *phba,
struct lpfc_nodelist *ndlp);
void lpfc_nvme_abort_fcreq_cmpl(struct lpfc_hba *phba,
struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb);
void lpfc_create_multixri_pools(struct lpfc_hba *phba);
void lpfc_create_destroy_pools(struct lpfc_hba *phba);
void lpfc_move_xri_pvt_to_pbl(struct lpfc_hba *phba, u32 hwqid);
void lpfc_move_xri_pbl_to_pvt(struct lpfc_hba *phba, u32 hwqid, u32 cnt);
void lpfc_adjust_high_watermark(struct lpfc_hba *phba, u32 hwqid);
void lpfc_keep_pvt_pool_above_lowwm(struct lpfc_hba *phba, u32 hwqid);
void lpfc_adjust_pvt_pool_count(struct lpfc_hba *phba, u32 hwqid);
#ifdef LPFC_MXP_STAT
void lpfc_snapshot_mxp(struct lpfc_hba *, u32);
#endif
struct lpfc_io_buf *lpfc_get_io_buf(struct lpfc_hba *phba,
struct lpfc_nodelist *ndlp, u32 hwqid,
int);
void lpfc_release_io_buf(struct lpfc_hba *phba, struct lpfc_io_buf *ncmd,
struct lpfc_sli4_hdw_queue *qp);
void lpfc_io_ktime(struct lpfc_hba *phba, struct lpfc_io_buf *ncmd);
void lpfc_wqe_cmd_template(void);
void lpfc_nvmet_cmd_template(void);
void lpfc_nvme_cancel_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
uint32_t stat, uint32_t param);
void lpfc_nvme_flush_abts_list(struct lpfc_hba *phba);
void lpfc_nvmels_flush_cmd(struct lpfc_hba *phba);
extern int lpfc_enable_nvmet_cnt;
extern unsigned long long lpfc_enable_nvmet[];
extern int lpfc_no_hba_reset_cnt;
extern unsigned long lpfc_no_hba_reset[];
extern unsigned char lpfc_acqe_cgn_frequency;
extern int lpfc_fabric_cgn_frequency;
extern int lpfc_use_cgn_signal;
extern union lpfc_wqe128 lpfc_iread_cmd_template;
extern union lpfc_wqe128 lpfc_iwrite_cmd_template;
extern union lpfc_wqe128 lpfc_icmnd_cmd_template;
/* vmid interface */
int lpfc_vmid_uvem(struct lpfc_vport *vport, struct lpfc_vmid *vmid, bool ins);
uint32_t lpfc_vmid_get_cs_ctl(struct lpfc_vport *vport);
int lpfc_vmid_cmd(struct lpfc_vport *vport,
int cmdcode, struct lpfc_vmid *vmid);
int lpfc_vmid_hash_fn(const char *vmid, int len);
struct lpfc_vmid *lpfc_get_vmid_from_hashtable(struct lpfc_vport *vport,
uint32_t hash, uint8_t *buf);
int lpfc_vmid_get_appid(struct lpfc_vport *vport, char *uuid,
enum dma_data_direction iodir,
union lpfc_vmid_io_tag *tag);
void lpfc_vmid_vport_cleanup(struct lpfc_vport *vport);
int lpfc_issue_els_qfpa(struct lpfc_vport *vport);
void lpfc_reinit_vmid(struct lpfc_vport *vport);
void lpfc_sli_rpi_release(struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp);
int lpfc_get_sfp_info_wait(struct lpfc_hba *phba,
struct lpfc_rdp_context *rdp_context);
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,713 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017-2025 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2007-2011 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* 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 *
* Public License as published by the Free Software Foundation. *
* This program is distributed in the hope that it will be useful. *
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
* DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
* TO BE LEGALLY INVALID. See the GNU General Public License for *
* more details, a copy of which can be found in the file COPYING *
* included with this package. *
*******************************************************************/
#ifndef _H_LPFC_DEBUG_FS
#define _H_LPFC_DEBUG_FS
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
/* size of output line, for discovery_trace and slow_ring_trace */
#define LPFC_DEBUG_TRC_ENTRY_SIZE 100
/* nodelist output buffer size */
#define LPFC_NODELIST_SIZE 8192
#define LPFC_NODELIST_ENTRY_SIZE 120
/* dumpHBASlim output buffer size */
#define LPFC_DUMPHBASLIM_SIZE 4096
/* dumpHostSlim output buffer size */
#define LPFC_DUMPHOSTSLIM_SIZE 4096
/* dumpSLIqinfo output buffer size */
#define LPFC_DUMPSLIQINFO_SIZE 4096
/* hbqinfo output buffer size */
#define LPFC_HBQINFO_SIZE 8192
/* hdwqinfo output buffer size */
#define LPFC_HDWQINFO_SIZE 8192
/* nvmestat output buffer size */
#define LPFC_NVMESTAT_SIZE 8192
#define LPFC_IOKTIME_SIZE 8192
#define LPFC_NVMEIO_TRC_SIZE 8192
/* scsistat output buffer size */
#define LPFC_SCSISTAT_SIZE 8192
/* Congestion Info Buffer size */
#define LPFC_CGN_BUF_SIZE 8192
#define LPFC_DEBUG_OUT_LINE_SZ 80
/*
* For SLI4 iDiag debugfs diagnostics tool
*/
/* pciConf */
#define LPFC_PCI_CFG_BROWSE 0xffff
#define LPFC_PCI_CFG_RD_CMD_ARG 2
#define LPFC_PCI_CFG_WR_CMD_ARG 3
#define LPFC_PCI_CFG_SIZE 4096
#define LPFC_PCI_CFG_RD_SIZE (LPFC_PCI_CFG_SIZE/4)
#define IDIAG_PCICFG_WHERE_INDX 0
#define IDIAG_PCICFG_COUNT_INDX 1
#define IDIAG_PCICFG_VALUE_INDX 2
/* barAcc */
#define LPFC_PCI_BAR_BROWSE 0xffff
#define LPFC_PCI_BAR_RD_CMD_ARG 3
#define LPFC_PCI_BAR_WR_CMD_ARG 3
#define LPFC_PCI_IF0_BAR0_SIZE (1024 * 16)
#define LPFC_PCI_IF0_BAR1_SIZE (1024 * 128)
#define LPFC_PCI_IF0_BAR2_SIZE (1024 * 128)
#define LPFC_PCI_IF2_BAR0_SIZE (1024 * 32)
#define LPFC_PCI_BAR_RD_BUF_SIZE 4096
#define LPFC_PCI_BAR_RD_SIZE (LPFC_PCI_BAR_RD_BUF_SIZE/4)
#define LPFC_PCI_IF0_BAR0_RD_SIZE (LPFC_PCI_IF0_BAR0_SIZE/4)
#define LPFC_PCI_IF0_BAR1_RD_SIZE (LPFC_PCI_IF0_BAR1_SIZE/4)
#define LPFC_PCI_IF0_BAR2_RD_SIZE (LPFC_PCI_IF0_BAR2_SIZE/4)
#define LPFC_PCI_IF2_BAR0_RD_SIZE (LPFC_PCI_IF2_BAR0_SIZE/4)
#define IDIAG_BARACC_BAR_NUM_INDX 0
#define IDIAG_BARACC_OFF_SET_INDX 1
#define IDIAG_BARACC_ACC_MOD_INDX 2
#define IDIAG_BARACC_REG_VAL_INDX 2
#define IDIAG_BARACC_BAR_SZE_INDX 3
#define IDIAG_BARACC_BAR_0 0
#define IDIAG_BARACC_BAR_1 1
#define IDIAG_BARACC_BAR_2 2
#define SINGLE_WORD 1
/* queue info */
#define LPFC_QUE_INFO_GET_BUF_SIZE 4096
/* queue acc */
#define LPFC_QUE_ACC_BROWSE 0xffff
#define LPFC_QUE_ACC_RD_CMD_ARG 4
#define LPFC_QUE_ACC_WR_CMD_ARG 6
#define LPFC_QUE_ACC_BUF_SIZE 4096
#define LPFC_QUE_ACC_SIZE (LPFC_QUE_ACC_BUF_SIZE/2)
#define LPFC_IDIAG_EQ 1
#define LPFC_IDIAG_CQ 2
#define LPFC_IDIAG_MQ 3
#define LPFC_IDIAG_WQ 4
#define LPFC_IDIAG_RQ 5
#define IDIAG_QUEACC_QUETP_INDX 0
#define IDIAG_QUEACC_QUEID_INDX 1
#define IDIAG_QUEACC_INDEX_INDX 2
#define IDIAG_QUEACC_COUNT_INDX 3
#define IDIAG_QUEACC_OFFST_INDX 4
#define IDIAG_QUEACC_VALUE_INDX 5
/* doorbell register acc */
#define LPFC_DRB_ACC_ALL 0xffff
#define LPFC_DRB_ACC_RD_CMD_ARG 1
#define LPFC_DRB_ACC_WR_CMD_ARG 2
#define LPFC_DRB_ACC_BUF_SIZE 256
#define LPFC_DRB_EQ 1
#define LPFC_DRB_CQ 2
#define LPFC_DRB_MQ 3
#define LPFC_DRB_WQ 4
#define LPFC_DRB_RQ 5
#define LPFC_DRB_MAX 5
#define IDIAG_DRBACC_REGID_INDX 0
#define IDIAG_DRBACC_VALUE_INDX 1
/* control register acc */
#define LPFC_CTL_ACC_ALL 0xffff
#define LPFC_CTL_ACC_RD_CMD_ARG 1
#define LPFC_CTL_ACC_WR_CMD_ARG 2
#define LPFC_CTL_ACC_BUF_SIZE 256
#define LPFC_CTL_PORT_SEM 1
#define LPFC_CTL_PORT_STA 2
#define LPFC_CTL_PORT_CTL 3
#define LPFC_CTL_PORT_ER1 4
#define LPFC_CTL_PORT_ER2 5
#define LPFC_CTL_PDEV_CTL 6
#define LPFC_CTL_MAX 6
#define IDIAG_CTLACC_REGID_INDX 0
#define IDIAG_CTLACC_VALUE_INDX 1
/* mailbox access */
#define LPFC_MBX_DMP_ARG 4
#define LPFC_MBX_ACC_BUF_SIZE 512
#define LPFC_MBX_ACC_LBUF_SZ 128
#define LPFC_MBX_DMP_MBX_WORD 0x00000001
#define LPFC_MBX_DMP_MBX_BYTE 0x00000002
#define LPFC_MBX_DMP_MBX_ALL (LPFC_MBX_DMP_MBX_WORD | LPFC_MBX_DMP_MBX_BYTE)
#define LPFC_BSG_DMP_MBX_RD_MBX 0x00000001
#define LPFC_BSG_DMP_MBX_RD_BUF 0x00000002
#define LPFC_BSG_DMP_MBX_WR_MBX 0x00000004
#define LPFC_BSG_DMP_MBX_WR_BUF 0x00000008
#define LPFC_BSG_DMP_MBX_ALL (LPFC_BSG_DMP_MBX_RD_MBX | \
LPFC_BSG_DMP_MBX_RD_BUF | \
LPFC_BSG_DMP_MBX_WR_MBX | \
LPFC_BSG_DMP_MBX_WR_BUF)
#define LPFC_MBX_DMP_ALL 0xffff
#define LPFC_MBX_ALL_CMD 0xff
#define IDIAG_MBXACC_MBCMD_INDX 0
#define IDIAG_MBXACC_DPMAP_INDX 1
#define IDIAG_MBXACC_DPCNT_INDX 2
#define IDIAG_MBXACC_WDCNT_INDX 3
/* extents access */
#define LPFC_EXT_ACC_CMD_ARG 1
#define LPFC_EXT_ACC_BUF_SIZE 4096
#define LPFC_EXT_ACC_AVAIL 0x1
#define LPFC_EXT_ACC_ALLOC 0x2
#define LPFC_EXT_ACC_DRIVR 0x4
#define LPFC_EXT_ACC_ALL (LPFC_EXT_ACC_DRIVR | \
LPFC_EXT_ACC_AVAIL | \
LPFC_EXT_ACC_ALLOC)
#define IDIAG_EXTACC_EXMAP_INDX 0
#define SIZE_U8 sizeof(uint8_t)
#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;
#define LPFC_IDIAG_OP_RD 1
#define LPFC_IDIAG_OP_WR 2
char *buffer;
int len;
};
struct lpfc_debugfs_trc {
char *fmt;
uint32_t data1;
uint32_t data2;
uint32_t data3;
uint32_t seq_cnt;
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;
};
#define LPFC_IDIAG_CMD_DATA_SIZE 8
struct lpfc_idiag_cmd {
uint32_t opcode;
#define LPFC_IDIAG_CMD_PCICFG_RD 0x00000001
#define LPFC_IDIAG_CMD_PCICFG_WR 0x00000002
#define LPFC_IDIAG_CMD_PCICFG_ST 0x00000003
#define LPFC_IDIAG_CMD_PCICFG_CL 0x00000004
#define LPFC_IDIAG_CMD_BARACC_RD 0x00000008
#define LPFC_IDIAG_CMD_BARACC_WR 0x00000009
#define LPFC_IDIAG_CMD_BARACC_ST 0x0000000a
#define LPFC_IDIAG_CMD_BARACC_CL 0x0000000b
#define LPFC_IDIAG_CMD_QUEACC_RD 0x00000011
#define LPFC_IDIAG_CMD_QUEACC_WR 0x00000012
#define LPFC_IDIAG_CMD_QUEACC_ST 0x00000013
#define LPFC_IDIAG_CMD_QUEACC_CL 0x00000014
#define LPFC_IDIAG_CMD_DRBACC_RD 0x00000021
#define LPFC_IDIAG_CMD_DRBACC_WR 0x00000022
#define LPFC_IDIAG_CMD_DRBACC_ST 0x00000023
#define LPFC_IDIAG_CMD_DRBACC_CL 0x00000024
#define LPFC_IDIAG_CMD_CTLACC_RD 0x00000031
#define LPFC_IDIAG_CMD_CTLACC_WR 0x00000032
#define LPFC_IDIAG_CMD_CTLACC_ST 0x00000033
#define LPFC_IDIAG_CMD_CTLACC_CL 0x00000034
#define LPFC_IDIAG_CMD_MBXACC_DP 0x00000041
#define LPFC_IDIAG_BSG_MBXACC_DP 0x00000042
#define LPFC_IDIAG_CMD_EXTACC_RD 0x00000051
uint32_t data[LPFC_IDIAG_CMD_DATA_SIZE];
};
struct lpfc_idiag {
uint32_t active;
struct lpfc_idiag_cmd cmd;
struct lpfc_idiag_offset offset;
void *ptr_private;
};
#define MAX_DEBUGFS_RX_INFO_SIZE (128 * LPFC_MAX_RXMONITOR_ENTRY)
struct lpfc_rx_monitor_debug {
char *i_private;
char *buffer;
};
#else
#define lpfc_nvmeio_data(phba, fmt, arg...) \
no_printk(fmt, ##arg)
#endif
/* multixripool output buffer size */
#define LPFC_DUMP_MULTIXRIPOOL_SIZE 8192
enum {
DUMP_IO,
DUMP_MBX,
DUMP_ELS,
DUMP_NVMELS,
};
/* Mask for discovery_trace */
#define LPFC_DISC_TRC_ELS_CMD 0x1 /* Trace ELS commands */
#define LPFC_DISC_TRC_ELS_RSP 0x2 /* Trace ELS response */
#define LPFC_DISC_TRC_ELS_UNSOL 0x4 /* Trace ELS rcv'ed */
#define LPFC_DISC_TRC_ELS_ALL 0x7 /* Trace ELS */
#define LPFC_DISC_TRC_MBOX_VPORT 0x8 /* Trace vport MBOXs */
#define LPFC_DISC_TRC_MBOX 0x10 /* Trace other MBOXs */
#define LPFC_DISC_TRC_MBOX_ALL 0x18 /* Trace all MBOXs */
#define LPFC_DISC_TRC_CT 0x20 /* Trace disc CT requests */
#define LPFC_DISC_TRC_DSM 0x40 /* Trace DSM events */
#define LPFC_DISC_TRC_RPORT 0x80 /* Trace rport events */
#define LPFC_DISC_TRC_NODE 0x100 /* Trace ndlp state changes */
#define LPFC_DISC_TRC_DISCOVERY 0xef /* common mask for general
* discovery */
#endif /* H_LPFC_DEBUG_FS */
enum {
writeGuard = 1,
writeApp,
writeRef,
readGuard,
readApp,
readRef,
InjErrLBA,
InjErrNPortID,
InjErrWWPN,
};
/*
* Driver debug utility routines outside of debugfs. The debug utility
* routines implemented here is intended to be used in the instrumented
* debug driver for debugging host or port issues.
*/
/**
* lpfc_debug_dump_qe - dump an specific entry from a queue
* @q: Pointer to the queue descriptor.
* @idx: Index to the entry on the queue.
*
* This function dumps an entry indexed by @idx from a queue specified by the
* queue descriptor @q.
**/
static void
lpfc_debug_dump_qe(struct lpfc_queue *q, uint32_t idx)
{
char line_buf[LPFC_LBUF_SZ];
int i, esize, qe_word_cnt, len;
uint32_t *pword;
/* sanity checks */
if (!q)
return;
if (idx >= q->entry_count)
return;
esize = q->entry_size;
qe_word_cnt = esize / sizeof(uint32_t);
pword = lpfc_sli4_qe(q, idx);
len = 0;
len += scnprintf(line_buf+len, LPFC_LBUF_SZ-len, "QE[%04d]: ", idx);
if (qe_word_cnt > 8)
printk(KERN_ERR "%s\n", line_buf);
for (i = 0; i < qe_word_cnt; i++) {
if (!(i % 8)) {
if (i != 0)
printk(KERN_ERR "%s\n", line_buf);
if (qe_word_cnt > 8) {
len = 0;
memset(line_buf, 0, LPFC_LBUF_SZ);
len += scnprintf(line_buf+len, LPFC_LBUF_SZ-len,
"%03d: ", i);
}
}
len += scnprintf(line_buf+len, LPFC_LBUF_SZ-len, "%08x ",
((uint32_t)*pword) & 0xffffffff);
pword++;
}
if (qe_word_cnt <= 8 || (i - 1) % 8)
printk(KERN_ERR "%s\n", line_buf);
}
/**
* lpfc_debug_dump_q - dump all entries from an specific queue
* @q: Pointer to the queue descriptor.
*
* This function dumps all entries from a queue specified by the queue
* descriptor @q.
**/
static inline void
lpfc_debug_dump_q(struct lpfc_queue *q)
{
int idx, entry_count;
/* sanity check */
if (!q)
return;
dev_printk(KERN_ERR, &(((q->phba))->pcidev)->dev,
"%d: [qid:%d, type:%d, subtype:%d, "
"qe_size:%d, qe_count:%d, "
"host_index:%d, port_index:%d]\n",
(q->phba)->brd_no,
q->queue_id, q->type, q->subtype,
q->entry_size, q->entry_count,
q->host_index, q->hba_index);
entry_count = q->entry_count;
for (idx = 0; idx < entry_count; idx++)
lpfc_debug_dump_qe(q, idx);
printk(KERN_ERR "\n");
}
/**
* lpfc_debug_dump_wq - dump all entries from the fcp or nvme work queue
* @phba: Pointer to HBA context object.
* @wqidx: Index to a FCP or NVME work queue.
*
* This function dumps all entries from a FCP or NVME work queue specified
* by the wqidx.
**/
static inline void
lpfc_debug_dump_wq(struct lpfc_hba *phba, int qtype, int wqidx)
{
struct lpfc_queue *wq;
char *qtypestr;
if (qtype == DUMP_IO) {
wq = phba->sli4_hba.hdwq[wqidx].io_wq;
qtypestr = "IO";
} 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;
if (qtype == DUMP_IO)
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_cq - dump all entries from a fcp or nvme work queue's
* cmpl queue
* @phba: Pointer to HBA context object.
* @wqidx: Index to a FCP work queue.
*
* 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_cq(struct lpfc_hba *phba, int qtype, int wqidx)
{
struct lpfc_queue *wq, *cq, *eq;
char *qtypestr;
int eqidx;
/* io wq and cq are 1:1, thus same indexes */
eq = NULL;
if (qtype == DUMP_IO) {
wq = phba->sli4_hba.hdwq[wqidx].io_wq;
cq = phba->sli4_hba.hdwq[wqidx].io_cq;
qtypestr = "IO";
} 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;
for (eqidx = 0; eqidx < phba->cfg_hdw_queue; eqidx++) {
eq = phba->sli4_hba.hdwq[eqidx].hba_eq;
if (cq->assoc_qid == eq->queue_id)
break;
}
if (eqidx == phba->cfg_hdw_queue) {
pr_err("Couldn't find EQ for CQ. Using EQ[0]\n");
eqidx = 0;
eq = phba->sli4_hba.hdwq[0].hba_eq;
}
if (qtype == DUMP_IO)
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);
}
/**
* lpfc_debug_dump_hba_eq - dump all entries from a fcp work queue's evt queue
* @phba: Pointer to HBA context object.
* @fcp_wqidx: Index to a FCP work queue.
*
* This function dumps all entries from a FCP event queue which is
* associated to the FCP work queue specified by the @fcp_wqidx.
**/
static inline void
lpfc_debug_dump_hba_eq(struct lpfc_hba *phba, int qidx)
{
struct lpfc_queue *qp;
qp = phba->sli4_hba.hdwq[qidx].hba_eq;
pr_err("EQ[Idx:%d|Qid:%d]\n", qidx, qp->queue_id);
lpfc_debug_dump_q(qp);
}
/**
* lpfc_debug_dump_dat_rq - dump all entries from the receive data queue
* @phba: Pointer to HBA context object.
*
* This function dumps all entries from the receive data queue.
**/
static inline void
lpfc_debug_dump_dat_rq(struct lpfc_hba *phba)
{
printk(KERN_ERR "DAT RQ: RQ[Qid:%d]\n",
phba->sli4_hba.dat_rq->queue_id);
lpfc_debug_dump_q(phba->sli4_hba.dat_rq);
}
/**
* lpfc_debug_dump_hdr_rq - dump all entries from the receive header queue
* @phba: Pointer to HBA context object.
*
* This function dumps all entries from the receive header queue.
**/
static inline void
lpfc_debug_dump_hdr_rq(struct lpfc_hba *phba)
{
printk(KERN_ERR "HDR RQ: RQ[Qid:%d]\n",
phba->sli4_hba.hdr_rq->queue_id);
lpfc_debug_dump_q(phba->sli4_hba.hdr_rq);
}
/**
* lpfc_debug_dump_wq_by_id - dump all entries from a work queue by queue id
* @phba: Pointer to HBA context object.
* @qid: Work queue identifier.
*
* This function dumps all entries from a work queue identified by the queue
* identifier.
**/
static inline void
lpfc_debug_dump_wq_by_id(struct lpfc_hba *phba, int qid)
{
int wq_idx;
for (wq_idx = 0; wq_idx < phba->cfg_hdw_queue; wq_idx++)
if (phba->sli4_hba.hdwq[wq_idx].io_wq->queue_id == qid)
break;
if (wq_idx < phba->cfg_hdw_queue) {
pr_err("IO WQ[Idx:%d|Qid:%d]\n", wq_idx, qid);
lpfc_debug_dump_q(phba->sli4_hba.hdwq[wq_idx].io_wq);
return;
}
if (phba->sli4_hba.els_wq->queue_id == 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);
}
}
/**
* lpfc_debug_dump_mq_by_id - dump all entries from a mbox queue by queue id
* @phba: Pointer to HBA context object.
* @qid: Mbox work queue identifier.
*
* This function dumps all entries from a mbox work queue identified by the
* queue identifier.
**/
static inline void
lpfc_debug_dump_mq_by_id(struct lpfc_hba *phba, int qid)
{
if (phba->sli4_hba.mbx_wq->queue_id == qid) {
printk(KERN_ERR "MBX WQ[Qid:%d]\n", qid);
lpfc_debug_dump_q(phba->sli4_hba.mbx_wq);
}
}
/**
* lpfc_debug_dump_rq_by_id - dump all entries from a receive queue by queue id
* @phba: Pointer to HBA context object.
* @qid: Receive queue identifier.
*
* This function dumps all entries from a receive queue identified by the
* queue identifier.
**/
static inline void
lpfc_debug_dump_rq_by_id(struct lpfc_hba *phba, int qid)
{
if (phba->sli4_hba.hdr_rq->queue_id == qid) {
printk(KERN_ERR "HDR RQ[Qid:%d]\n", qid);
lpfc_debug_dump_q(phba->sli4_hba.hdr_rq);
return;
}
if (phba->sli4_hba.dat_rq->queue_id == qid) {
printk(KERN_ERR "DAT RQ[Qid:%d]\n", qid);
lpfc_debug_dump_q(phba->sli4_hba.dat_rq);
}
}
/**
* lpfc_debug_dump_cq_by_id - dump all entries from a cmpl queue by queue id
* @phba: Pointer to HBA context object.
* @qid: Complete queue identifier.
*
* This function dumps all entries from a complete queue identified by the
* queue identifier.
**/
static inline void
lpfc_debug_dump_cq_by_id(struct lpfc_hba *phba, int qid)
{
int cq_idx;
for (cq_idx = 0; cq_idx < phba->cfg_hdw_queue; cq_idx++)
if (phba->sli4_hba.hdwq[cq_idx].io_cq->queue_id == qid)
break;
if (cq_idx < phba->cfg_hdw_queue) {
pr_err("IO CQ[Idx:%d|Qid:%d]\n", cq_idx, qid);
lpfc_debug_dump_q(phba->sli4_hba.hdwq[cq_idx].io_cq);
return;
}
if (phba->sli4_hba.els_cq->queue_id == 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) {
pr_err("MBX CQ[Qid:%d]\n", qid);
lpfc_debug_dump_q(phba->sli4_hba.mbx_cq);
}
}
/**
* lpfc_debug_dump_eq_by_id - dump all entries from an event queue by queue id
* @phba: Pointer to HBA context object.
* @qid: Complete queue identifier.
*
* This function dumps all entries from an event queue identified by the
* queue identifier.
**/
static inline void
lpfc_debug_dump_eq_by_id(struct lpfc_hba *phba, int qid)
{
int eq_idx;
for (eq_idx = 0; eq_idx < phba->cfg_hdw_queue; eq_idx++)
if (phba->sli4_hba.hdwq[eq_idx].hba_eq->queue_id == qid)
break;
if (eq_idx < phba->cfg_hdw_queue) {
printk(KERN_ERR "FCP EQ[Idx:%d|Qid:%d]\n", eq_idx, qid);
lpfc_debug_dump_q(phba->sli4_hba.hdwq[eq_idx].hba_eq);
return;
}
}
void lpfc_debug_dump_all_queues(struct lpfc_hba *);
+308
View File
@@ -0,0 +1,308 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017-2026 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2013 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* 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 *
* 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 FC_MAX_HOLD_RSCN 32 /* max number of deferred RSCNs */
#define FC_MAX_NS_RSP 64512 /* max size NameServer rsp */
#define FC_MAXLOOP 126 /* max devices supported on a fc loop */
#define LPFC_DISC_FLOGI_TMO 10 /* Discovery FLOGI ratov */
/* This is the protocol dependent definition for a Node List Entry.
* This is used by Fibre Channel protocol to support FCP.
*/
/* worker thread events */
enum lpfc_work_type {
LPFC_EVT_ONLINE,
LPFC_EVT_OFFLINE_PREP,
LPFC_EVT_OFFLINE,
LPFC_EVT_WARM_START,
LPFC_EVT_KILL,
LPFC_EVT_ELS_RETRY,
LPFC_EVT_DEV_LOSS,
LPFC_EVT_FASTPATH_MGMT_EVT,
LPFC_EVT_RESET_HBA,
LPFC_EVT_RECOVER_PORT
};
/* structure used to queue event to the discovery tasklet */
struct lpfc_work_evt {
struct list_head evt_listp;
void *evt_arg1;
void *evt_arg2;
enum lpfc_work_type evt;
};
struct lpfc_scsi_check_condition_event;
struct lpfc_scsi_varqueuedepth_event;
struct lpfc_scsi_event_header;
struct lpfc_fabric_event_header;
struct lpfc_fcprdchkerr_event;
/* structure used for sending events from fast path */
struct lpfc_fast_path_event {
struct lpfc_work_evt work_evt;
struct lpfc_vport *vport;
union {
struct lpfc_scsi_check_condition_event check_cond_evt;
struct lpfc_scsi_varqueuedepth_event queue_depth_evt;
struct lpfc_scsi_event_header scsi_evt;
struct lpfc_fabric_event_header fabric_evt;
struct lpfc_fcprdchkerr_event read_check_error;
} un;
};
#define LPFC_SLI4_MAX_XRI 1024 /* Used to make the ndlp's xri_bitmap */
#define XRI_BITMAP_ULONGS (LPFC_SLI4_MAX_XRI / BITS_PER_LONG)
struct lpfc_node_rrqs {
unsigned long xri_bitmap[XRI_BITMAP_ULONGS];
};
struct lpfc_enc_info {
u8 status; /* encryption status for session */
u8 level; /* CNSA encryption level */
};
enum lpfc_fc4_xpt_flags {
NLP_XPT_REGD = 0x1,
SCSI_XPT_REGD = 0x2,
NVME_XPT_REGD = 0x4,
NVME_XPT_UNREG_WAIT = 0x8,
NLP_XPT_HAS_HH = 0x10
};
enum lpfc_nlp_save_flags { /* mask bits */
/* devloss occurred during recovery */
NLP_IN_RECOV_POST_DEV_LOSS,
/* wait for outstanding LOGO to cmpl */
NLP_WAIT_FOR_LOGO,
/* wait for outstanding DA_ID to finish */
NLP_WAIT_FOR_DA_ID
};
struct lpfc_nodelist {
struct list_head nlp_listp;
struct serv_parm fc_sparam; /* buffer for service params */
struct lpfc_name nlp_portname;
struct lpfc_name nlp_nodename;
spinlock_t lock; /* Node management lock */
unsigned long nlp_flag; /* entry flags */
uint32_t nlp_DID; /* FC D_ID of entry */
uint32_t nlp_last_elscmd; /* Last ELS cmd sent */
uint16_t nlp_type;
#define NLP_FC_NODE 0x1 /* entry is an FC node */
#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 */
#define NLP_NVME_DISCOVERY 0x80 /* entry has NVME disc srvc */
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 */
uint16_t nlp_prev_state; /* state transition indicator */
uint16_t nlp_xri; /* output exchange id for RPI */
uint16_t nlp_sid; /* scsi id */
#define NLP_NO_SID 0xffff
uint16_t nlp_maxframe; /* Max RCV frame size */
uint8_t nlp_class_sup; /* Supported Classes */
uint8_t nlp_retry; /* used for ELS retries */
uint8_t nlp_fcp_info; /* class info, bits 0-2 */
#define NLP_FCP_CLASS_MASK 0x07 /* class info bitmask */
#define NLP_FCP_2_DEVICE 0x10 /* FCP-2 device */
u8 nlp_nvme_info; /* NVME NSLER Support */
uint8_t vmid_support; /* destination VMID support */
#define NLP_NVME_NSLER 0x1 /* NVME NSLER device */
struct lpfc_enc_info nlp_enc_info; /* Encryption information struct */
struct timer_list nlp_delayfunc; /* Used for delayed ELS cmds */
struct lpfc_hba *phba;
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;
struct lpfc_work_evt recovery_evt;
struct kref kref;
atomic_t cmd_pending;
uint32_t cmd_qdepth;
unsigned long last_change_time;
unsigned long *active_rrqs_xri_bitmap;
uint32_t fc4_prli_sent;
/* flags to keep ndlp alive until special conditions are met */
unsigned long save_flags;
enum lpfc_fc4_xpt_flags fc4_xpt_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. */
uint32_t nlp_defer_did;
/* These wait objects are NPIV specific. These IOs must complete
* synchronously.
*/
wait_queue_head_t *logo_waitq;
wait_queue_head_t *da_id_waitq;
};
struct lpfc_node_rrq {
struct list_head list;
uint16_t xritag;
uint16_t send_rrq;
uint16_t rxid;
uint32_t nlp_DID; /* FC D_ID of entry */
struct lpfc_vport *vport;
unsigned long rrq_stop_time;
};
#define lpfc_ndlp_check_qdepth(phba, ndlp) \
(ndlp->cmd_qdepth < phba->sli4_hba.max_cfg_param.max_xri)
/* nlp_flag mask bits */
enum lpfc_nlp_flag {
NLP_IGNR_REG_CMPL = 0, /* Rcvd rscn before we cmpl reg login */
NLP_REG_LOGIN_SEND = 1, /* sent reglogin to adapter */
NLP_SUPPRESS_RSP = 4, /* Remote NPort supports suppress rsp */
NLP_PLOGI_SND = 5, /* sent PLOGI request for this entry */
NLP_PRLI_SND = 6, /* sent PRLI request for this entry */
NLP_ADISC_SND = 7, /* sent ADISC request for this entry */
NLP_LOGO_SND = 8, /* sent LOGO request for this entry */
NLP_RNID_SND = 10, /* sent RNID request for this entry */
NLP_NVMET_RECOV = 12, /* NVMET auditing node for recovery. */
NLP_UNREG_INP = 15, /* UNREG_RPI cmd is in progress */
NLP_DROPPED = 16, /* Init ref count has been dropped */
NLP_DELAY_TMO = 17, /* delay timeout is running for node */
NLP_NPR_2B_DISC = 18, /* node is included in num_disc_nodes */
NLP_RCV_PLOGI = 19, /* Rcv'ed PLOGI from remote system */
NLP_LOGO_ACC = 20, /* Process LOGO after ACC completes */
NLP_TGT_NO_SCSIID = 21, /* good PRLI but no binding for scsid */
NLP_ISSUE_LOGO = 22, /* waiting to issue a LOGO */
NLP_IN_DEV_LOSS = 23, /* devloss in progress */
NLP_ACC_REGLOGIN = 24, /* Issue Reg Login after successful
ACC */
NLP_NPR_ADISC = 25, /* Issue ADISC when dq'ed from
NPR list */
NLP_RM_DFLT_RPI = 26, /* need to remove leftover dflt RPI */
NLP_NODEV_REMOVE = 27, /* Defer removal till discovery ends */
NLP_FLOGI_DFR_ACC = 28, /* FLOGI LS_ACC was Deferred */
NLP_SC_REQ = 29, /* Target requires authentication */
NLP_FIRSTBURST = 30, /* Target supports FirstBurst */
NLP_RPI_REGISTERED = 31 /* nlp_rpi is valid */
};
/* There are 4 different double linked lists nodelist entries can reside on.
* The Port Login (PLOGI) list and Address Discovery (ADISC) list are used
* when Link Up discovery or Registered State Change Notification (RSCN)
* processing is needed. Each list holds the nodes that require a PLOGI or
* ADISC Extended Link Service (ELS) request. These lists keep track of the
* nodes affected by an RSCN, or a Link Up (Typically, all nodes are effected
* by Link Up) event. The unmapped_list contains all nodes that have
* successfully logged into at the Fibre Channel level. The
* mapped_list will contain all nodes that are mapped FCP targets.
*
* The bind list is a list of undiscovered (potentially non-existent) nodes
* that we have saved binding information on. This information is used when
* nodes transition from the unmapped to the mapped list.
*/
/* Defines for nlp_state */
#define NLP_STE_UNUSED_NODE 0x0 /* node is just allocated */
#define NLP_STE_PLOGI_ISSUE 0x1 /* PLOGI was sent to NL_PORT */
#define NLP_STE_ADISC_ISSUE 0x2 /* ADISC was sent to NL_PORT */
#define NLP_STE_REG_LOGIN_ISSUE 0x3 /* REG_LOGIN was issued for NL_PORT */
#define NLP_STE_PRLI_ISSUE 0x4 /* PRLI was sent to NL_PORT */
#define NLP_STE_LOGO_ISSUE 0x5 /* LOGO was sent to NL_PORT */
#define NLP_STE_UNMAPPED_NODE 0x6 /* PRLI completed from NL_PORT */
#define NLP_STE_MAPPED_NODE 0x7 /* Identified as a FCP Target */
#define NLP_STE_NPR_NODE 0x8 /* NPort disappeared */
#define NLP_STE_MAX_STATE 0x9
#define NLP_STE_FREED_NODE 0xff /* node entry was freed to MEM_NLP */
/* For UNUSED_NODE state, the node has just been allocated.
* For PLOGI_ISSUE and REG_LOGIN_ISSUE, the node is on
* the PLOGI list. For REG_LOGIN_COMPL, the node is taken off the PLOGI list
* and put on the unmapped list. For ADISC processing, the node is taken off
* the ADISC list and placed on either the mapped or unmapped list (depending
* on its previous state). Once on the unmapped list, a PRLI is issued and the
* state changed to PRLI_ISSUE. When the PRLI completion occurs, the state is
* changed to PRLI_COMPL. If the completion indicates a mapped
* node, the node is taken off the unmapped list. The binding list is checked
* for a valid binding, or a binding is automatically assigned. If binding
* assignment is unsuccessful, the node is left on the unmapped list. If
* binding assignment is successful, the associated binding list entry (if
* any) is removed, and the node is placed on the mapped list.
*/
/*
* For a Link Down, all nodes on the ADISC, PLOGI, unmapped or mapped
* lists will receive a DEVICE_RECOVERY event. If the linkdown or devloss timers
* expire, all effected nodes will receive a DEVICE_RM event.
*/
/*
* For a Link Up or RSCN, all nodes will move from the mapped / unmapped lists
* to either the ADISC or PLOGI list. After a Nameserver query or ALPA loopmap
* check, additional nodes may be added (DEVICE_ADD) or removed (DEVICE_RM) to /
* from the PLOGI or ADISC lists. Once the PLOGI and ADISC lists are populated,
* we will first process the ADISC list. 32 entries are processed initially and
* ADISC is initited for each one. Completions / Events for each node are
* funnelled thru the state machine. As each node finishes ADISC processing, it
* starts ADISC for any nodes waiting for ADISC processing. If no nodes are
* waiting, and the ADISC list count is identically 0, then we are done. For
* Link Up discovery, since all nodes on the PLOGI list are UNREG_LOGIN'ed, we
* can issue a CLEAR_LA and reenable Link Events. Next we will process the PLOGI
* list. 32 entries are processed initially and PLOGI is initited for each one.
* Completions / Events for each node are funnelled thru the state machine. As
* each node finishes PLOGI processing, it starts PLOGI for any nodes waiting
* for PLOGI processing. If no nodes are waiting, and the PLOGI list count is
* identically 0, then we are done. We have now completed discovery / RSCN
* handling. Upon completion, ALL nodes should be on either the mapped or
* unmapped lists.
*/
/* Defines for Node List Entry Events that could happen */
#define NLP_EVT_RCV_PLOGI 0x0 /* Rcv'd an ELS PLOGI command */
#define NLP_EVT_RCV_PRLI 0x1 /* Rcv'd an ELS PRLI command */
#define NLP_EVT_RCV_LOGO 0x2 /* Rcv'd an ELS LOGO command */
#define NLP_EVT_RCV_ADISC 0x3 /* Rcv'd an ELS ADISC command */
#define NLP_EVT_RCV_PDISC 0x4 /* Rcv'd an ELS PDISC command */
#define NLP_EVT_RCV_PRLO 0x5 /* Rcv'd an ELS PRLO command */
#define NLP_EVT_CMPL_PLOGI 0x6 /* Sent an ELS PLOGI command */
#define NLP_EVT_CMPL_PRLI 0x7 /* Sent an ELS PRLI command */
#define NLP_EVT_CMPL_LOGO 0x8 /* Sent an ELS LOGO command */
#define NLP_EVT_CMPL_ADISC 0x9 /* Sent an ELS ADISC command */
#define NLP_EVT_CMPL_REG_LOGIN 0xa /* REG_LOGIN mbox cmd completed */
#define NLP_EVT_DEVICE_RM 0xb /* Device not found in NS / ALPAmap */
#define NLP_EVT_DEVICE_RECOVERY 0xc /* Device existence unknown */
#define NLP_EVT_MAX_EVENT 0xd
#define NLP_EVT_NOTHING_PENDING 0xff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+158
View File
@@ -0,0 +1,158 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017-2026 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.broadcom.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of version 2 of the GNU General *
* Public License as published by the Free Software Foundation. *
* This program is distributed in the hope that it will be useful. *
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
* DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
* TO BE LEGALLY INVALID. See the GNU General Public License for *
* more details, a copy of which can be found in the file COPYING *
* included with this package. *
*******************************************************************/
#include <linux/pci.h>
const struct pci_device_id lpfc_id_table[] = {
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_VIPER,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_FIREFLY,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_THOR,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_PEGASUS,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_CENTAUR,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_DRAGONFLY,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SUPERFLY,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_RFLY,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_PFLY,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_NEPTUNE,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_NEPTUNE_SCSP,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_NEPTUNE_DCSP,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_HELIOS,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_HELIOS_SCSP,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_HELIOS_DCSP,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_BMID,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_BSMB,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZEPHYR,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZEPHYR_SCSP,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZEPHYR_DCSP,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZMID,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZSMB,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_TFLY,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LP101,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LP10000S,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LP11000S,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LPE11000S,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_MID,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_SMB,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_DCSP,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_SCSP,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_S,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_PROTEUS_VF,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_PROTEUS_PF,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_PROTEUS_S,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_SERVERENGINE, PCI_DEVICE_ID_TIGERSHARK,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_SERVERENGINE, PCI_DEVICE_ID_TOMCAT,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_FALCON,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_BALIUS,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_FC,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_FCOE,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_FC_VF,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_FCOE_VF,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_G6_FC,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_G7_FC,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_G7P_FC,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_G8_FC,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SKYHAWK,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SKYHAWK_VF,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_ATTO, PCI_DEVICE_ID_CLRY_16XE,
PCI_VENDOR_ID_ATTO, PCI_DEVICE_ID_CLRY_161E, },
{PCI_VENDOR_ID_ATTO, PCI_DEVICE_ID_CLRY_16XE,
PCI_VENDOR_ID_ATTO, PCI_DEVICE_ID_CLRY_162E, },
{PCI_VENDOR_ID_ATTO, PCI_DEVICE_ID_CLRY_16XE,
PCI_VENDOR_ID_ATTO, PCI_DEVICE_ID_CLRY_164E, },
{PCI_VENDOR_ID_ATTO, PCI_DEVICE_ID_CLRY_16XP,
PCI_VENDOR_ID_ATTO, PCI_DEVICE_ID_CLRY_161P, },
{PCI_VENDOR_ID_ATTO, PCI_DEVICE_ID_CLRY_16XP,
PCI_VENDOR_ID_ATTO, PCI_DEVICE_ID_CLRY_162P, },
{PCI_VENDOR_ID_ATTO, PCI_DEVICE_ID_CLRY_16XP,
PCI_VENDOR_ID_ATTO, PCI_DEVICE_ID_CLRY_164P, },
{PCI_VENDOR_ID_ATTO, PCI_DEVICE_ID_CLRY_32XE,
PCI_VENDOR_ID_ATTO, PCI_DEVICE_ID_CLRY_321E, },
{PCI_VENDOR_ID_ATTO, PCI_DEVICE_ID_CLRY_32XE,
PCI_VENDOR_ID_ATTO, PCI_DEVICE_ID_CLRY_322E, },
{PCI_VENDOR_ID_ATTO, PCI_DEVICE_ID_CLRY_32XE,
PCI_VENDOR_ID_ATTO, PCI_DEVICE_ID_CLRY_324E, },
{PCI_VENDOR_ID_ATTO, PCI_DEVICE_ID_CLRY_32XP,
PCI_VENDOR_ID_ATTO, PCI_DEVICE_ID_CLRY_321P, },
{PCI_VENDOR_ID_ATTO, PCI_DEVICE_ID_CLRY_32XP,
PCI_VENDOR_ID_ATTO, PCI_DEVICE_ID_CLRY_322P, },
{PCI_VENDOR_ID_ATTO, PCI_DEVICE_ID_CLRY_32XP,
PCI_VENDOR_ID_ATTO, PCI_DEVICE_ID_CLRY_324P, },
{PCI_VENDOR_ID_ATTO, PCI_DEVICE_ID_TLFC_2,
PCI_VENDOR_ID_ATTO, PCI_DEVICE_ID_TLFC_2XX2, },
{PCI_VENDOR_ID_ATTO, PCI_DEVICE_ID_TLFC_3,
PCI_VENDOR_ID_ATTO, PCI_DEVICE_ID_TLFC_3162, },
{PCI_VENDOR_ID_ATTO, PCI_DEVICE_ID_TLFC_3,
PCI_VENDOR_ID_ATTO, PCI_DEVICE_ID_TLFC_3322, },
{ 0 }
};
File diff suppressed because it is too large Load Diff
+100
View File
@@ -0,0 +1,100 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017-2025 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2009 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* 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 *
* 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 LOG_ELS 0x00000001 /* ELS events */
#define LOG_DISCOVERY 0x00000002 /* Link discovery events */
#define LOG_MBOX 0x00000004 /* Mailbox events */
#define LOG_INIT 0x00000008 /* Initialization events */
#define LOG_LINK_EVENT 0x00000010 /* Link events */
#define LOG_NODE_VERBOSE 0x00000020 /* Node verbose events */
#define LOG_FCP 0x00000040 /* FCP traffic history */
#define LOG_NODE 0x00000080 /* Node table events */
#define LOG_TEMP 0x00000100 /* Temperature sensor events */
#define LOG_BG 0x00000200 /* BlockGuard events */
#define LOG_MISC 0x00000400 /* Miscellaneous events */
#define LOG_SLI 0x00000800 /* SLI events */
#define LOG_FCP_ERROR 0x00001000 /* log errors, not underruns */
#define LOG_LIBDFC 0x00002000 /* Libdfc events */
#define LOG_VPORT 0x00004000 /* NPIV events */
#define LOG_LDS_EVENT 0x00008000 /* Link Degrade Signaling events */
#define LOG_EVENT 0x00010000 /* CT,TEMP,DUMP, logging */
#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_RSVD1 0x01000000 /* Reserved */
#define LOG_RSVD2 0x02000000 /* Reserved */
#define LOG_CGN_MGMT 0x04000000 /* Congestion Mgmt events */
#define LOG_ENCRYPTION 0x40000000 /* EDIF Encryption events. */
#define LOG_TRACE_EVENT 0x80000000 /* Dmp the DBG log on this err */
#define LOG_ALL_MSG 0x7fffffff /* LOG all messages */
void lpfc_dmp_dbg(struct lpfc_hba *phba);
void lpfc_dbg_print(struct lpfc_hba *phba, const char *fmt, ...);
/* generate message by verbose log setting or severity */
#define lpfc_vlog_msg(vport, level, mask, fmt, arg...) \
{ if (((mask) & (vport)->cfg_log_verbose) || (level[1] <= '5')) \
dev_printk(level, &((vport)->phba->pcidev)->dev, "%d:(%d):" \
fmt, (vport)->phba->brd_no, vport->vpi, ##arg); }
#define lpfc_log_msg(phba, level, mask, fmt, arg...) \
do { \
{ uint32_t log_verbose = (phba)->pport ? \
(phba)->pport->cfg_log_verbose : \
(phba)->cfg_log_verbose; \
if (((mask) & log_verbose) || (level[1] <= '5')) \
dev_printk(level, &((phba)->pcidev)->dev, "%d:" \
fmt, phba->brd_no, ##arg); \
} \
} while (0)
#define lpfc_printf_vlog(vport, level, mask, fmt, arg...) \
do { \
{ if (((mask) & (vport)->cfg_log_verbose) || (level[1] <= '3')) { \
if ((mask) & LOG_TRACE_EVENT && !(vport)->cfg_log_verbose) \
lpfc_dmp_dbg((vport)->phba); \
dev_printk(level, &((vport)->phba->pcidev)->dev, "%d:(%d):" \
fmt, (vport)->phba->brd_no, vport->vpi, ##arg); \
} else if (!(vport)->cfg_log_verbose) \
lpfc_dbg_print((vport)->phba, "%d:(%d):" fmt, \
(vport)->phba->brd_no, (vport)->vpi, ##arg); \
} \
} while (0)
#define lpfc_printf_log(phba, level, mask, fmt, arg...) \
do { \
{ uint32_t log_verbose = (phba)->pport ? \
(phba)->pport->cfg_log_verbose : \
(phba)->cfg_log_verbose; \
if (((mask) & log_verbose) || (level[1] <= '3')) { \
if ((mask) & LOG_TRACE_EVENT && !log_verbose) \
lpfc_dmp_dbg(phba); \
dev_printk(level, &((phba)->pcidev)->dev, "%d:" \
fmt, phba->brd_no, ##arg); \
} else if (!log_verbose)\
lpfc_dbg_print(phba, "%d:" fmt, phba->brd_no, ##arg); \
} \
} while (0)
File diff suppressed because it is too large Load Diff
+761
View File
@@ -0,0 +1,761 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017-2023 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2014 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.broadcom.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of version 2 of the GNU General *
* Public License as published by the Free Software Foundation. *
* This program is distributed in the hope that it will be useful. *
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
* DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
* TO BE LEGALLY INVALID. See the GNU General Public License for *
* more details, a copy of which can be found in the file COPYING *
* included with this package. *
*******************************************************************/
#include <linux/mempool.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_transport_fc.h>
#include <scsi/fc/fc_fs.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.h"
#include "lpfc_scsi.h"
#include "lpfc_crtn.h"
#include "lpfc_logmsg.h"
#define LPFC_MBUF_POOL_SIZE 64 /* max elements in MBUF safety pool */
#define LPFC_MEM_POOL_SIZE 64 /* max elem in non-DMA safety pool */
#define LPFC_DEVICE_DATA_POOL_SIZE 64 /* max elements in device data pool */
#define LPFC_RRQ_POOL_SIZE 256 /* max elements in non-DMA pool */
#define LPFC_MBX_POOL_SIZE 256 /* max elements in MBX non-DMA pool */
/* lpfc_mbox_free_sli_mbox
*
* @phba: HBA to free memory for
* @mbox: mailbox command to free
*
* This routine detects the mbox type and calls the correct
* free routine to fully release all associated memory.
*/
static void
lpfc_mem_free_sli_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox)
{
/* Detect if the caller's mbox is an SLI4_CONFIG type. If so, this
* mailbox type requires a different cleanup routine. Otherwise, the
* mailbox is just an mbuf and mem_pool release.
*/
if (phba->sli_rev == LPFC_SLI_REV4 &&
bf_get(lpfc_mqe_command, &mbox->u.mqe) == MBX_SLI4_CONFIG) {
lpfc_sli4_mbox_cmd_free(phba, mbox);
} else {
lpfc_mbox_rsrc_cleanup(phba, mbox, MBOX_THD_UNLOCKED);
}
}
int
lpfc_mem_alloc_active_rrq_pool_s4(struct lpfc_hba *phba) {
size_t bytes;
int max_xri = phba->sli4_hba.max_cfg_param.max_xri;
if (max_xri <= 0)
return -ENOMEM;
bytes = ((BITS_PER_LONG - 1 + max_xri) / BITS_PER_LONG) *
sizeof(unsigned long);
phba->cfg_rrq_xri_bitmap_sz = bytes;
phba->active_rrq_pool = mempool_create_kmalloc_pool(LPFC_MEM_POOL_SIZE,
bytes);
if (!phba->active_rrq_pool)
return -ENOMEM;
else
return 0;
}
/**
* lpfc_mem_alloc - create and allocate all PCI and memory pools
* @phba: HBA to allocate pools for
* @align: alignment requirement for blocks; must be a power of two
*
* Description: Creates and allocates PCI pools 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
* allocation fails, frees all successfully allocated memory before returning.
*
* Returns:
* 0 on success
* -ENOMEM on failure (if any memory allocations fail)
**/
int
lpfc_mem_alloc(struct lpfc_hba *phba, int align)
{
struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool;
int i;
phba->lpfc_mbuf_pool = dma_pool_create("lpfc_mbuf_pool", &phba->pcidev->dev,
LPFC_BPL_SIZE,
align, 0);
if (!phba->lpfc_mbuf_pool)
goto fail;
pool->elements = kmalloc_objs(struct lpfc_dmabuf, LPFC_MBUF_POOL_SIZE);
if (!pool->elements)
goto fail_free_lpfc_mbuf_pool;
pool->max_count = 0;
pool->current_count = 0;
for ( i = 0; i < LPFC_MBUF_POOL_SIZE; i++) {
pool->elements[i].virt = dma_pool_alloc(phba->lpfc_mbuf_pool,
GFP_KERNEL, &pool->elements[i].phys);
if (!pool->elements[i].virt)
goto fail_free_mbuf_pool;
pool->max_count++;
pool->current_count++;
}
phba->mbox_mem_pool = mempool_create_kmalloc_pool(LPFC_MBX_POOL_SIZE,
sizeof(LPFC_MBOXQ_t));
if (!phba->mbox_mem_pool)
goto fail_free_mbuf_pool;
phba->nlp_mem_pool = mempool_create_kmalloc_pool(LPFC_MEM_POOL_SIZE,
sizeof(struct lpfc_nodelist));
if (!phba->nlp_mem_pool)
goto fail_free_mbox_pool;
if (phba->sli_rev == LPFC_SLI_REV4) {
phba->rrq_pool =
mempool_create_kmalloc_pool(LPFC_RRQ_POOL_SIZE,
sizeof(struct lpfc_node_rrq));
if (!phba->rrq_pool)
goto fail_free_nlp_mem_pool;
phba->lpfc_hrb_pool = dma_pool_create("lpfc_hrb_pool",
&phba->pcidev->dev,
LPFC_HDR_BUF_SIZE, align, 0);
if (!phba->lpfc_hrb_pool)
goto fail_free_rrq_mem_pool;
phba->lpfc_drb_pool = dma_pool_create("lpfc_drb_pool",
&phba->pcidev->dev,
LPFC_DATA_BUF_SIZE, align, 0);
if (!phba->lpfc_drb_pool)
goto fail_free_hrb_pool;
phba->lpfc_hbq_pool = NULL;
} else {
phba->lpfc_hbq_pool = dma_pool_create("lpfc_hbq_pool",
&phba->pcidev->dev, LPFC_BPL_SIZE, align, 0);
if (!phba->lpfc_hbq_pool)
goto fail_free_nlp_mem_pool;
phba->lpfc_hrb_pool = NULL;
phba->lpfc_drb_pool = NULL;
}
if (phba->cfg_EnableXLane) {
phba->device_data_mem_pool = mempool_create_kmalloc_pool(
LPFC_DEVICE_DATA_POOL_SIZE,
sizeof(struct lpfc_device_data));
if (!phba->device_data_mem_pool)
goto fail_free_drb_pool;
} else {
phba->device_data_mem_pool = NULL;
}
return 0;
fail_free_drb_pool:
dma_pool_destroy(phba->lpfc_drb_pool);
phba->lpfc_drb_pool = NULL;
fail_free_hrb_pool:
dma_pool_destroy(phba->lpfc_hrb_pool);
phba->lpfc_hrb_pool = NULL;
fail_free_rrq_mem_pool:
mempool_destroy(phba->rrq_pool);
phba->rrq_pool = NULL;
fail_free_nlp_mem_pool:
mempool_destroy(phba->nlp_mem_pool);
phba->nlp_mem_pool = NULL;
fail_free_mbox_pool:
mempool_destroy(phba->mbox_mem_pool);
phba->mbox_mem_pool = NULL;
fail_free_mbuf_pool:
while (i--)
dma_pool_free(phba->lpfc_mbuf_pool, pool->elements[i].virt,
pool->elements[i].phys);
kfree(pool->elements);
fail_free_lpfc_mbuf_pool:
dma_pool_destroy(phba->lpfc_mbuf_pool);
phba->lpfc_mbuf_pool = NULL;
fail:
return -ENOMEM;
}
int
lpfc_nvmet_mem_alloc(struct lpfc_hba *phba)
{
phba->lpfc_nvmet_drb_pool =
dma_pool_create("lpfc_nvmet_drb_pool",
&phba->pcidev->dev, LPFC_NVMET_DATA_BUF_SIZE,
SGL_ALIGN_SZ, 0);
if (!phba->lpfc_nvmet_drb_pool) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"6024 Can't enable NVME Target - no memory\n");
return -ENOMEM;
}
return 0;
}
/**
* lpfc_mem_free - Frees memory allocated by lpfc_mem_alloc
* @phba: HBA to free memory for
*
* 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)
{
int i;
struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool;
struct lpfc_device_data *device_data;
/* Free HBQ pools */
lpfc_sli_hbqbuf_free_all(phba);
dma_pool_destroy(phba->lpfc_nvmet_drb_pool);
phba->lpfc_nvmet_drb_pool = NULL;
dma_pool_destroy(phba->lpfc_drb_pool);
phba->lpfc_drb_pool = NULL;
dma_pool_destroy(phba->lpfc_hrb_pool);
phba->lpfc_hrb_pool = NULL;
dma_pool_destroy(phba->lpfc_hbq_pool);
phba->lpfc_hbq_pool = NULL;
mempool_destroy(phba->rrq_pool);
phba->rrq_pool = NULL;
/* Free NLP memory pool */
mempool_destroy(phba->nlp_mem_pool);
phba->nlp_mem_pool = NULL;
if (phba->sli_rev == LPFC_SLI_REV4 && phba->active_rrq_pool) {
mempool_destroy(phba->active_rrq_pool);
phba->active_rrq_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++)
dma_pool_free(phba->lpfc_mbuf_pool, pool->elements[i].virt,
pool->elements[i].phys);
kfree(pool->elements);
dma_pool_destroy(phba->lpfc_mbuf_pool);
phba->lpfc_mbuf_pool = NULL;
/* Free Device Data memory pool */
if (phba->device_data_mem_pool) {
/* Ensure all objects have been returned to the pool */
while (!list_empty(&phba->luns)) {
device_data = list_first_entry(&phba->luns,
struct lpfc_device_data,
listentry);
list_del(&device_data->listentry);
mempool_free(device_data, phba->device_data_mem_pool);
}
mempool_destroy(phba->device_data_mem_pool);
}
phba->device_data_mem_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_sg_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;
LPFC_MBOXQ_t *mbox, *next_mbox;
/* Free memory used in mailbox queue back to mailbox memory pool */
list_for_each_entry_safe(mbox, next_mbox, &psli->mboxq, list) {
list_del(&mbox->list);
lpfc_mem_free_sli_mbox(phba, mbox);
}
/* Free memory used in mailbox cmpl list back to mailbox memory pool */
list_for_each_entry_safe(mbox, next_mbox, &psli->mboxq_cmpl, list) {
list_del(&mbox->list);
lpfc_mem_free_sli_mbox(phba, mbox);
}
/* 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;
lpfc_mem_free_sli_mbox(phba, mbox);
psli->mbox_active = NULL;
}
/* Free and destroy all the allocated memory pools */
lpfc_mem_free(phba);
/* Free DMA buffer memory pool */
dma_pool_destroy(phba->lpfc_sg_dma_buf_pool);
phba->lpfc_sg_dma_buf_pool = NULL;
dma_pool_destroy(phba->lpfc_cmd_rsp_buf_pool);
phba->lpfc_cmd_rsp_buf_pool = NULL;
/* Free Congestion Data buffer */
if (phba->cgn_i) {
dma_free_coherent(&phba->pcidev->dev,
sizeof(struct lpfc_cgn_info),
phba->cgn_i->virt, phba->cgn_i->phys);
kfree(phba->cgn_i);
phba->cgn_i = NULL;
}
/* Free RX Monitor */
if (phba->rx_monitor) {
lpfc_rx_monitor_destroy_ring(phba->rx_monitor);
kfree(phba->rx_monitor);
phba->rx_monitor = NULL;
}
/* Free the iocb lookup array */
kfree(psli->iocbq_lookup);
psli->iocbq_lookup = NULL;
return;
}
/**
* lpfc_mbuf_alloc - Allocate an mbuf from the lpfc_mbuf_pool PCI pool
* @phba: HBA which owns the pool to allocate from
* @mem_flags: indicates if this is a priority (MEM_PRI) allocation
* @handle: used to return the DMA-mapped address of the mbuf
*
* Description: Allocates a DMA-mapped buffer from the lpfc_mbuf_pool PCI pool.
* Allocates from generic dma_pool_alloc function first and if that fails and
* mem_flags has MEM_PRI set (the only defined flag), returns an mbuf from the
* HBA's pool.
*
* Notes: Not interrupt-safe. Must be called with no locks held. Takes
* phba->hbalock.
*
* Returns:
* pointer to the allocated mbuf on success
* NULL on failure
**/
void *
lpfc_mbuf_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle)
{
struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool;
unsigned long iflags;
void *ret;
ret = dma_pool_alloc(phba->lpfc_mbuf_pool, GFP_KERNEL, handle);
spin_lock_irqsave(&phba->hbalock, iflags);
if (!ret && (mem_flags & MEM_PRI) && pool->current_count) {
pool->current_count--;
ret = pool->elements[pool->current_count].virt;
*handle = pool->elements[pool->current_count].phys;
}
spin_unlock_irqrestore(&phba->hbalock, iflags);
return ret;
}
/**
* __lpfc_mbuf_free - Free an mbuf from the lpfc_mbuf_pool PCI pool (locked)
* @phba: HBA which owns the pool to return to
* @virt: mbuf to free
* @dma: the DMA-mapped address of the lpfc_mbuf_pool to be freed
*
* Description: Returns an mbuf lpfc_mbuf_pool to the lpfc_mbuf_safety_pool if
* it is below its max_count, frees the mbuf otherwise.
*
* Notes: Must be called with phba->hbalock held to synchronize access to
* lpfc_mbuf_safety_pool.
*
* Returns: None
**/
void
__lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
{
struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool;
if (pool->current_count < pool->max_count) {
pool->elements[pool->current_count].virt = virt;
pool->elements[pool->current_count].phys = dma;
pool->current_count++;
} else {
dma_pool_free(phba->lpfc_mbuf_pool, virt, dma);
}
return;
}
/**
* lpfc_mbuf_free - Free an mbuf from the lpfc_mbuf_pool PCI pool (unlocked)
* @phba: HBA which owns the pool to return to
* @virt: mbuf to free
* @dma: the DMA-mapped address of the lpfc_mbuf_pool to be freed
*
* Description: Returns an mbuf lpfc_mbuf_pool to the lpfc_mbuf_safety_pool if
* it is below its max_count, frees the mbuf otherwise.
*
* Notes: Takes phba->hbalock. Can be called with or without other locks held.
*
* Returns: None
**/
void
lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
{
unsigned long iflags;
spin_lock_irqsave(&phba->hbalock, iflags);
__lpfc_mbuf_free(phba, virt, dma);
spin_unlock_irqrestore(&phba->hbalock, iflags);
return;
}
/**
* lpfc_nvmet_buf_alloc - Allocate an nvmet_buf from the
* lpfc_sg_dma_buf_pool PCI pool
* @phba: HBA which owns the pool to allocate from
* @mem_flags: indicates if this is a priority (MEM_PRI) allocation
* @handle: used to return the DMA-mapped address of the nvmet_buf
*
* Description: Allocates a DMA-mapped buffer from the lpfc_sg_dma_buf_pool
* PCI pool. Allocates from generic dma_pool_alloc function.
*
* Returns:
* pointer to the allocated nvmet_buf on success
* NULL on failure
**/
void *
lpfc_nvmet_buf_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle)
{
void *ret;
ret = dma_pool_alloc(phba->lpfc_sg_dma_buf_pool, GFP_KERNEL, handle);
return ret;
}
/**
* lpfc_nvmet_buf_free - Free an nvmet_buf from the lpfc_sg_dma_buf_pool
* PCI pool
* @phba: HBA which owns the pool to return to
* @virt: nvmet_buf to free
* @dma: the DMA-mapped address of the lpfc_sg_dma_buf_pool to be freed
*
* Returns: None
**/
void
lpfc_nvmet_buf_free(struct lpfc_hba *phba, void *virt, dma_addr_t dma)
{
dma_pool_free(phba->lpfc_sg_dma_buf_pool, virt, 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_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_els_hbq_alloc(struct lpfc_hba *phba)
{
struct hbq_dmabuf *hbqbp;
hbqbp = kzalloc_obj(struct hbq_dmabuf);
if (!hbqbp)
return NULL;
hbqbp->dbuf.virt = dma_pool_alloc(phba->lpfc_hbq_pool, GFP_KERNEL,
&hbqbp->dbuf.phys);
if (!hbqbp->dbuf.virt) {
kfree(hbqbp);
return NULL;
}
hbqbp->total_size = LPFC_BPL_SIZE;
return hbqbp;
}
/**
* 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
*
* Description: Frees both the container and the DMA-mapped buffer returned by
* lpfc_els_hbq_alloc.
*
* Notes: Can be called with or without locks held.
*
* Returns: None
**/
void
lpfc_els_hbq_free(struct lpfc_hba *phba, struct hbq_dmabuf *hbqbp)
{
dma_pool_free(phba->lpfc_hbq_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 = kzalloc_obj(struct hbq_dmabuf);
if (!dma_buf)
return NULL;
dma_buf->hbuf.virt = dma_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 = dma_pool_alloc(phba->lpfc_drb_pool, GFP_KERNEL,
&dma_buf->dbuf.phys);
if (!dma_buf->dbuf.virt) {
dma_pool_free(phba->lpfc_hrb_pool, dma_buf->hbuf.virt,
dma_buf->hbuf.phys);
kfree(dma_buf);
return NULL;
}
dma_buf->total_size = LPFC_DATA_BUF_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)
{
dma_pool_free(phba->lpfc_hrb_pool, dmab->hbuf.virt, dmab->hbuf.phys);
dma_pool_free(phba->lpfc_drb_pool, dmab->dbuf.virt, dmab->dbuf.phys);
kfree(dmab);
}
/**
* lpfc_sli4_nvmet_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.
*
* Returns:
* pointer to HBQ on success
* NULL on failure
**/
struct rqb_dmabuf *
lpfc_sli4_nvmet_alloc(struct lpfc_hba *phba)
{
struct rqb_dmabuf *dma_buf;
dma_buf = kzalloc_obj(*dma_buf);
if (!dma_buf)
return NULL;
dma_buf->hbuf.virt = dma_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 = dma_pool_alloc(phba->lpfc_nvmet_drb_pool,
GFP_KERNEL, &dma_buf->dbuf.phys);
if (!dma_buf->dbuf.virt) {
dma_pool_free(phba->lpfc_hrb_pool, dma_buf->hbuf.virt,
dma_buf->hbuf.phys);
kfree(dma_buf);
return NULL;
}
dma_buf->total_size = LPFC_NVMET_DATA_BUF_SIZE;
return dma_buf;
}
/**
* lpfc_sli4_nvmet_free - Frees a receive buffer
* @phba: HBA buffer was allocated for
* @dmab: DMA Buffer container returned by lpfc_sli4_rbq_alloc
*
* Description: Frees both the container and the DMA-mapped buffers returned by
* lpfc_sli4_nvmet_alloc.
*
* Notes: Can be called with or without locks held.
*
* Returns: None
**/
void
lpfc_sli4_nvmet_free(struct lpfc_hba *phba, struct rqb_dmabuf *dmab)
{
dma_pool_free(phba->lpfc_hrb_pool, dmab->hbuf.virt, dmab->hbuf.phys);
dma_pool_free(phba->lpfc_nvmet_drb_pool,
dmab->dbuf.virt, dmab->dbuf.phys);
kfree(dmab);
}
/**
* lpfc_in_buf_free - Free a DMA buffer
* @phba: HBA buffer is associated with
* @mp: Buffer to free
*
* Description: Frees the given DMA buffer in the appropriate way given if the
* HBA is running in SLI3 mode with HBQs enabled.
*
* Notes: Takes phba->hbalock. Can be called with or without other locks held.
*
* Returns: None
**/
void
lpfc_in_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp)
{
struct hbq_dmabuf *hbq_entry;
unsigned long flags;
if (!mp)
return;
if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
hbq_entry = container_of(mp, struct hbq_dmabuf, dbuf);
/* Check whether HBQ is still in use */
spin_lock_irqsave(&phba->hbalock, flags);
if (!phba->hbq_in_use) {
spin_unlock_irqrestore(&phba->hbalock, flags);
return;
}
list_del(&hbq_entry->dbuf.list);
if (hbq_entry->tag == -1) {
(phba->hbqs[LPFC_ELS_HBQ].hbq_free_buffer)
(phba, hbq_entry);
} else {
lpfc_sli_free_hbq(phba, hbq_entry);
}
spin_unlock_irqrestore(&phba->hbalock, flags);
} else {
lpfc_mbuf_free(phba, mp->virt, mp->phys);
kfree(mp);
}
return;
}
/**
* lpfc_rq_buf_free - Free a RQ DMA buffer
* @phba: HBA buffer is associated with
* @mp: Buffer to free
*
* Description: Frees the given DMA buffer in the appropriate way given by
* reposting it to its associated RQ so it can be reused.
*
* Notes: Takes phba->hbalock. Can be called with or without other locks held.
*
* Returns: None
**/
void
lpfc_rq_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp)
{
struct lpfc_rqb *rqbp;
struct lpfc_rqe hrqe;
struct lpfc_rqe drqe;
struct rqb_dmabuf *rqb_entry;
unsigned long flags;
int rc;
if (!mp)
return;
rqb_entry = container_of(mp, struct rqb_dmabuf, hbuf);
rqbp = rqb_entry->hrq->rqbp;
spin_lock_irqsave(&phba->hbalock, flags);
list_del(&rqb_entry->hbuf.list);
hrqe.address_lo = putPaddrLow(rqb_entry->hbuf.phys);
hrqe.address_hi = putPaddrHigh(rqb_entry->hbuf.phys);
drqe.address_lo = putPaddrLow(rqb_entry->dbuf.phys);
drqe.address_hi = putPaddrHigh(rqb_entry->dbuf.phys);
rc = lpfc_sli4_rq_put(rqb_entry->hrq, rqb_entry->drq, &hrqe, &drqe);
if (rc < 0) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"6409 Cannot post to HRQ %d: %x %x %x "
"DRQ %x %x\n",
rqb_entry->hrq->queue_id,
rqb_entry->hrq->host_index,
rqb_entry->hrq->hba_index,
rqb_entry->hrq->entry_count,
rqb_entry->drq->host_index,
rqb_entry->drq->hba_index);
(rqbp->rqb_free_buffer)(phba, rqb_entry);
} else {
list_add_tail(&rqb_entry->hbuf.list, &rqbp->rqb_buffer_list);
rqbp->buffer_count++;
}
spin_unlock_irqrestore(&phba->hbalock, flags);
}
+181
View File
@@ -0,0 +1,181 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2010 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* 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 *
* 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. *
*******************************************************************/
/* Event definitions for RegisterForEvent */
#define FC_REG_LINK_EVENT 0x0001 /* link up / down events */
#define FC_REG_RSCN_EVENT 0x0002 /* RSCN events */
#define FC_REG_CT_EVENT 0x0004 /* CT request events */
#define FC_REG_DUMP_EVENT 0x0010 /* Dump events */
#define FC_REG_TEMPERATURE_EVENT 0x0020 /* temperature events */
#define FC_REG_VPORTRSCN_EVENT 0x0040 /* Vport RSCN events */
#define FC_REG_ELS_EVENT 0x0080 /* lpfc els events */
#define FC_REG_FABRIC_EVENT 0x0100 /* lpfc fabric events */
#define FC_REG_SCSI_EVENT 0x0200 /* lpfc scsi events */
#define FC_REG_BOARD_EVENT 0x0400 /* lpfc board events */
#define FC_REG_ADAPTER_EVENT 0x0800 /* lpfc adapter events */
#define FC_REG_EVENT_MASK (FC_REG_LINK_EVENT | \
FC_REG_RSCN_EVENT | \
FC_REG_CT_EVENT | \
FC_REG_DUMP_EVENT | \
FC_REG_TEMPERATURE_EVENT | \
FC_REG_VPORTRSCN_EVENT | \
FC_REG_ELS_EVENT | \
FC_REG_FABRIC_EVENT | \
FC_REG_SCSI_EVENT | \
FC_REG_BOARD_EVENT | \
FC_REG_ADAPTER_EVENT)
/* Temperature events */
#define LPFC_CRIT_TEMP 0x1
#define LPFC_THRESHOLD_TEMP 0x2
#define LPFC_NORMAL_TEMP 0x3
/*
* All net link event payloads will begin with and event type
* and subcategory. The event type must come first.
* The subcategory further defines the data that follows in the rest
* of the payload. Each category will have its own unique header plus
* any additional data unique to the subcategory.
* The payload sent via the fc transport is one-way driver->application.
*/
/* RSCN event header */
struct lpfc_rscn_event_header {
uint32_t event_type;
uint32_t payload_length; /* RSCN data length in bytes */
uint32_t rscn_payload[];
};
/* els event header */
struct lpfc_els_event_header {
uint32_t event_type;
uint32_t subcategory;
uint8_t wwpn[8];
uint8_t wwnn[8];
};
/* subcategory codes for FC_REG_ELS_EVENT */
#define LPFC_EVENT_PLOGI_RCV 0x01
#define LPFC_EVENT_PRLO_RCV 0x02
#define LPFC_EVENT_ADISC_RCV 0x04
#define LPFC_EVENT_LSRJT_RCV 0x08
#define LPFC_EVENT_LOGO_RCV 0x10
/* special els lsrjt event */
struct lpfc_lsrjt_event {
struct lpfc_els_event_header header;
uint32_t command;
uint32_t reason_code;
uint32_t explanation;
};
/* special els logo event */
struct lpfc_logo_event {
struct lpfc_els_event_header header;
uint8_t logo_wwpn[8];
};
/* fabric event header */
struct lpfc_fabric_event_header {
uint32_t event_type;
uint32_t subcategory;
uint8_t wwpn[8];
uint8_t wwnn[8];
};
/* subcategory codes for FC_REG_FABRIC_EVENT */
#define LPFC_EVENT_FABRIC_BUSY 0x01
#define LPFC_EVENT_PORT_BUSY 0x02
#define LPFC_EVENT_FCPRDCHKERR 0x04
/* special case fabric fcprdchkerr event */
struct lpfc_fcprdchkerr_event {
struct lpfc_fabric_event_header header;
uint32_t lun;
uint32_t opcode;
uint32_t fcpiparam;
};
/* scsi event header */
struct lpfc_scsi_event_header {
uint32_t event_type;
uint32_t subcategory;
uint32_t lun;
uint8_t wwpn[8];
uint8_t wwnn[8];
};
/* subcategory codes for FC_REG_SCSI_EVENT */
#define LPFC_EVENT_QFULL 0x0001
#define LPFC_EVENT_DEVBSY 0x0002
#define LPFC_EVENT_CHECK_COND 0x0004
#define LPFC_EVENT_LUNRESET 0x0008
#define LPFC_EVENT_TGTRESET 0x0010
#define LPFC_EVENT_BUSRESET 0x0020
#define LPFC_EVENT_VARQUEDEPTH 0x0040
/* special case scsi varqueuedepth event */
struct lpfc_scsi_varqueuedepth_event {
struct lpfc_scsi_event_header scsi_event;
uint32_t oldval;
uint32_t newval;
};
/* special case scsi check condition event */
struct lpfc_scsi_check_condition_event {
struct lpfc_scsi_event_header scsi_event;
uint8_t opcode;
uint8_t sense_key;
uint8_t asc;
uint8_t ascq;
};
/* event codes for FC_REG_BOARD_EVENT */
#define LPFC_EVENT_PORTINTERR 0x01
/* board event header */
struct lpfc_board_event_header {
uint32_t event_type;
uint32_t subcategory;
};
/* event codes for FC_REG_ADAPTER_EVENT */
#define LPFC_EVENT_ARRIVAL 0x01
/* adapter event header */
struct lpfc_adapter_event_header {
uint32_t event_type;
uint32_t subcategory;
};
/* event codes for temp_event */
#define LPFC_CRIT_TEMP 0x1
#define LPFC_THRESHOLD_TEMP 0x2
#define LPFC_NORMAL_TEMP 0x3
struct temp_event {
uint32_t event_type;
uint32_t event_code;
uint32_t data;
};
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+253
View File
@@ -0,0 +1,253 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.broadcom.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of version 2 of the GNU General *
* Public License as published by the Free Software Foundation. *
* This program is distributed in the hope that it will be useful. *
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
* DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
* TO BE LEGALLY INVALID. See the GNU General Public License for *
* more details, a copy of which can be found in the file COPYING *
* included with this package. *
********************************************************************/
#include <linux/nvme.h>
#include <linux/nvme-fc-driver.h>
#include <linux/nvme-fc.h>
#define LPFC_NVME_DEFAULT_SEGS (64 + 1) /* 256K IOs */
#define LPFC_NVME_ERSP_LEN 0x20
#define LPFC_NVME_WAIT_TMO 10
#define LPFC_NVME_EXPEDITE_XRICNT 8
#define LPFC_NVME_FB_SHIFT 9
#define LPFC_NVME_MAX_FB (1 << 20) /* 1M */
#define lpfc_ndlp_get_nrport(ndlp) \
((!ndlp->nrport || (ndlp->fc4_xpt_flags & NVME_XPT_UNREG_WAIT))\
? NULL : ndlp->nrport)
struct lpfc_nvme_qhandle {
uint32_t index; /* WQ index to use */
uint32_t qidx; /* queue index passed to create */
uint32_t cpu_id; /* current cpu id at time of create */
};
/* Declare nvme-based local and remote port definitions. */
struct lpfc_nvme_lport {
struct lpfc_vport *vport;
struct completion *lport_unreg_cmp;
/* Add stats counters here */
atomic_t fc4NvmeLsRequests;
atomic_t fc4NvmeLsCmpls;
atomic_t xmt_fcp_noxri;
atomic_t xmt_fcp_bad_ndlp;
atomic_t xmt_fcp_qdepth;
atomic_t xmt_fcp_wqerr;
atomic_t xmt_fcp_err;
atomic_t xmt_fcp_abort;
atomic_t xmt_ls_abort;
atomic_t xmt_ls_err;
atomic_t cmpl_fcp_xb;
atomic_t cmpl_fcp_err;
atomic_t cmpl_ls_xb;
atomic_t cmpl_ls_err;
};
struct lpfc_nvme_rport {
struct lpfc_nvme_lport *lport;
struct nvme_fc_remote_port *remoteport;
struct lpfc_nodelist *ndlp;
struct completion rport_unreg_done;
};
struct lpfc_nvme_fcpreq_priv {
struct lpfc_io_buf *nvme_buf;
};
/*
* set NVME LS request timeouts to 30s. It is larger than the 2*R_A_TOV
* set by the spec, which appears to have issues with some devices.
*/
#define LPFC_NVME_LS_TIMEOUT 30
#define LPFC_NVMET_DEFAULT_SEGS (64 + 1) /* 256K IOs */
#define LPFC_NVMET_RQE_MIN_POST 128
#define LPFC_NVMET_RQE_DEF_POST 512
#define LPFC_NVMET_RQE_DEF_COUNT 2048
#define LPFC_NVMET_SUCCESS_LEN 12
#define LPFC_NVMET_MRQ_AUTO 0
#define LPFC_NVMET_MRQ_MAX 16
#define LPFC_NVMET_WAIT_TMO (5 * MSEC_PER_SEC)
/* Used for NVME Target */
#define LPFC_NVMET_INV_HOST_ACTIVE 1
struct lpfc_nvmet_tgtport {
struct lpfc_hba *phba;
struct completion *tport_unreg_cmp;
atomic_t state; /* tracks nvmet hosthandle invalidation */
/* Stats counters - lpfc_nvmet_unsol_ls_buffer */
atomic_t rcv_ls_req_in;
atomic_t rcv_ls_req_out;
atomic_t rcv_ls_req_drop;
atomic_t xmt_ls_abort;
atomic_t xmt_ls_abort_cmpl;
/* Stats counters - lpfc_nvmet_xmt_ls_rsp */
atomic_t xmt_ls_rsp;
atomic_t xmt_ls_drop;
/* Stats counters - lpfc_nvmet_xmt_ls_rsp_cmp */
atomic_t xmt_ls_rsp_error;
atomic_t xmt_ls_rsp_aborted;
atomic_t xmt_ls_rsp_xb_set;
atomic_t xmt_ls_rsp_cmpl;
/* Stats counters - lpfc_nvmet_unsol_fcp_buffer */
atomic_t rcv_fcp_cmd_in;
atomic_t rcv_fcp_cmd_out;
atomic_t rcv_fcp_cmd_drop;
atomic_t rcv_fcp_cmd_defer;
atomic_t xmt_fcp_release;
/* Stats counters - lpfc_nvmet_xmt_fcp_op */
atomic_t xmt_fcp_drop;
atomic_t xmt_fcp_read_rsp;
atomic_t xmt_fcp_read;
atomic_t xmt_fcp_write;
atomic_t xmt_fcp_rsp;
/* Stats counters - lpfc_nvmet_xmt_fcp_op_cmp */
atomic_t xmt_fcp_rsp_xb_set;
atomic_t xmt_fcp_rsp_cmpl;
atomic_t xmt_fcp_rsp_error;
atomic_t xmt_fcp_rsp_aborted;
atomic_t xmt_fcp_rsp_drop;
/* Stats counters - lpfc_nvmet_xmt_fcp_abort */
atomic_t xmt_fcp_xri_abort_cqe;
atomic_t xmt_fcp_abort;
atomic_t xmt_fcp_abort_cmpl;
atomic_t xmt_abort_sol;
atomic_t xmt_abort_unsol;
atomic_t xmt_abort_rsp;
atomic_t xmt_abort_rsp_error;
/* Stats counters - defer IO */
atomic_t defer_ctx;
atomic_t defer_fod;
atomic_t defer_wqfull;
};
struct lpfc_nvmet_ctx_info {
struct list_head nvmet_ctx_list;
spinlock_t nvmet_ctx_list_lock; /* lock per CPU */
struct lpfc_nvmet_ctx_info *nvmet_ctx_next_cpu;
struct lpfc_nvmet_ctx_info *nvmet_ctx_start_cpu;
uint16_t nvmet_ctx_list_cnt;
char pad[16]; /* pad to a cache-line */
};
/* This retrieves the context info associated with the specified cpu / mrq */
#define lpfc_get_ctx_list(phba, cpu, mrq) \
(phba->sli4_hba.nvmet_ctx_info + ((cpu * phba->cfg_nvmet_mrq) + mrq))
/* Values for state field of struct lpfc_async_xchg_ctx */
#define LPFC_NVME_STE_LS_RCV 1
#define LPFC_NVME_STE_LS_ABORT 2
#define LPFC_NVME_STE_LS_RSP 3
#define LPFC_NVME_STE_RCV 4
#define LPFC_NVME_STE_DATA 5
#define LPFC_NVME_STE_ABORT 6
#define LPFC_NVME_STE_DONE 7
#define LPFC_NVME_STE_FREE 0xff
/* Values for flag field of struct lpfc_async_xchg_ctx */
#define LPFC_NVME_IO_INP 0x1 /* IO is in progress on exchange */
#define LPFC_NVME_ABORT_OP 0x2 /* Abort WQE issued on exchange */
#define LPFC_NVME_XBUSY 0x4 /* XB bit set on IO cmpl */
#define LPFC_NVME_CTX_RLS 0x8 /* ctx free requested */
#define LPFC_NVME_ABTS_RCV 0x10 /* ABTS received on exchange */
#define LPFC_NVME_CTX_REUSE_WQ 0x20 /* ctx reused via WQ */
#define LPFC_NVME_DEFER_WQFULL 0x40 /* Waiting on a free WQE */
#define LPFC_NVME_TNOTIFY 0x80 /* notify transport of abts */
struct lpfc_async_xchg_ctx {
union {
struct nvmefc_tgt_fcp_req fcp_req;
} hdlrctx;
struct list_head list;
struct lpfc_hba *phba;
struct lpfc_nodelist *ndlp;
struct nvmefc_ls_req *ls_req;
struct nvmefc_ls_rsp ls_rsp;
struct lpfc_iocbq *wqeq;
struct lpfc_iocbq *abort_wqeq;
spinlock_t ctxlock; /* protect flag access */
uint32_t sid;
uint32_t offset;
uint16_t oxid;
uint16_t size;
uint16_t entry_cnt;
uint16_t cpu;
uint16_t idx;
uint16_t state;
uint16_t flag;
void *payload;
struct rqb_dmabuf *rqb_buffer;
struct lpfc_nvmet_ctxbuf *ctxbuf;
struct lpfc_sli4_hdw_queue *hdwq;
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
uint64_t ts_isr_cmd;
uint64_t ts_cmd_nvme;
uint64_t ts_nvme_data;
uint64_t ts_data_wqput;
uint64_t ts_isr_data;
uint64_t ts_data_nvme;
uint64_t ts_nvme_status;
uint64_t ts_status_wqput;
uint64_t ts_isr_status;
uint64_t ts_status_nvme;
#endif
};
/* routines found in lpfc_nvme.c */
int __lpfc_nvme_ls_req(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
struct nvmefc_ls_req *pnvme_lsreq,
void (*gen_req_cmp)(struct lpfc_hba *phba,
struct lpfc_iocbq *cmdwqe,
struct lpfc_iocbq *rspwqe));
void __lpfc_nvme_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_vport *vport,
struct lpfc_iocbq *cmdwqe, struct lpfc_wcqe_complete *wcqe);
int __lpfc_nvme_ls_abort(struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp, struct nvmefc_ls_req *pnvme_lsreq);
/* routines found in lpfc_nvmet.c */
int lpfc_nvme_unsol_ls_issue_abort(struct lpfc_hba *phba,
struct lpfc_async_xchg_ctx *ctxp, uint32_t sid,
uint16_t xri);
int __lpfc_nvme_xmt_ls_rsp(struct lpfc_async_xchg_ctx *axchg,
struct nvmefc_ls_rsp *ls_rsp,
void (*xmt_ls_rsp_cmp)(struct lpfc_hba *phba,
struct lpfc_iocbq *cmdwqe,
struct lpfc_iocbq *rspwqe));
void __lpfc_nvme_xmt_ls_rsp_cmp(struct lpfc_hba *phba,
struct lpfc_iocbq *cmdwqe, struct lpfc_iocbq *rspwqe);
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+163
View File
@@ -0,0 +1,163 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017-2024 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* 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 *
* Public License as published by the Free Software Foundation. *
* This program is distributed in the hope that it will be useful. *
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
* DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
* TO BE LEGALLY INVALID. See the GNU General Public License for *
* more details, a copy of which can be found in the file COPYING *
* included with this package. *
*******************************************************************/
#include <asm/byteorder.h>
struct lpfc_hba;
#define LPFC_FCP_CDB_LEN 16
#define LPFC_FCP_CDB_LEN_32 32
#define list_remove_head(list, entry, type, member) \
do { \
entry = NULL; \
if (!list_empty(list)) { \
entry = list_entry((list)->next, type, member); \
list_del_init(&entry->member); \
} \
} while(0)
#define list_get_first(list, type, member) \
(list_empty(list)) ? NULL : \
list_entry((list)->next, type, member)
/* per-port data that is allocated in the FC transport for us */
struct lpfc_rport_data {
struct lpfc_nodelist *pnode; /* Pointer to the node structure. */
};
struct lpfc_device_id {
struct lpfc_name vport_wwpn;
struct lpfc_name target_wwpn;
uint64_t lun;
};
struct lpfc_device_data {
struct list_head listentry;
struct lpfc_rport_data *rport_data;
struct lpfc_device_id device_id;
uint8_t priority;
bool oas_enabled;
bool available;
};
struct fcp_rsp {
uint32_t rspRsvd1; /* FC Word 0, byte 0:3 */
uint32_t rspRsvd2; /* FC Word 1, byte 0:3 */
uint8_t rspStatus0; /* FCP_STATUS byte 0 (reserved) */
uint8_t rspStatus1; /* FCP_STATUS byte 1 (reserved) */
uint8_t rspStatus2; /* FCP_STATUS byte 2 field validity */
#define RSP_LEN_VALID 0x01 /* bit 0 */
#define SNS_LEN_VALID 0x02 /* bit 1 */
#define RESID_OVER 0x04 /* bit 2 */
#define RESID_UNDER 0x08 /* bit 3 */
uint8_t rspStatus3; /* FCP_STATUS byte 3 SCSI status byte */
uint32_t rspResId; /* Residual xfer if residual count field set in
fcpStatus2 */
/* Received in Big Endian format */
uint32_t rspSnsLen; /* Length of sense data in fcpSnsInfo */
/* Received in Big Endian format */
uint32_t rspRspLen; /* Length of FCP response data in fcpRspInfo */
/* Received in Big Endian format */
uint8_t rspInfo0; /* FCP_RSP_INFO byte 0 (reserved) */
uint8_t rspInfo1; /* FCP_RSP_INFO byte 1 (reserved) */
uint8_t rspInfo2; /* FCP_RSP_INFO byte 2 (reserved) */
uint8_t rspInfo3; /* FCP_RSP_INFO RSP_CODE byte 3 */
#define RSP_NO_FAILURE 0x00
#define RSP_DATA_BURST_ERR 0x01
#define RSP_CMD_FIELD_ERR 0x02
#define RSP_RO_MISMATCH_ERR 0x03
#define RSP_TM_NOT_SUPPORTED 0x04 /* Task mgmt function not supported */
#define RSP_TM_NOT_COMPLETED 0x05 /* Task mgmt function not performed */
#define RSP_TM_INVALID_LU 0x09 /* Task mgmt function to invalid LU */
uint32_t rspInfoRsvd; /* FCP_RSP_INFO bytes 4-7 (reserved) */
uint8_t rspSnsInfo[128];
#define SNS_ILLEGAL_REQ 0x05 /* sense key is byte 3 ([2]) */
#define SNSCOD_BADCMD 0x20 /* sense code is byte 13 ([12]) */
};
#define SIMPLE_Q 0x00
#define HEAD_OF_Q 0x01
#define ORDERED_Q 0x02
#define ACA_Q 0x04
#define UNTAGGED 0x05
#define FCP_ABORT_TASK_SET 0x02 /* Bit 1 */
#define FCP_CLEAR_TASK_SET 0x04 /* bit 2 */
#define FCP_BUS_RESET 0x08 /* bit 3 */
#define FCP_LUN_RESET 0x10 /* bit 4 */
#define FCP_TARGET_RESET 0x20 /* bit 5 */
#define FCP_CLEAR_ACA 0x40 /* bit 6 */
#define FCP_TERMINATE_TASK 0x80 /* bit 7 */
#define WRITE_DATA 0x01 /* Bit 0 */
#define READ_DATA 0x02 /* Bit 1 */
struct fcp_cmnd {
struct scsi_lun fcp_lun;
uint8_t fcpCntl0; /* FCP_CNTL byte 0 (reserved) */
uint8_t fcpCntl1; /* FCP_CNTL byte 1 task codes */
uint8_t fcpCntl2; /* FCP_CTL byte 2 task management codes */
uint8_t fcpCntl3;
uint8_t fcpCdb[LPFC_FCP_CDB_LEN]; /* SRB cdb field is copied here */
__be32 fcpDl; /* Total transfer length */
};
struct fcp_cmnd32 {
struct scsi_lun fcp_lun;
uint8_t fcpCntl0; /* FCP_CNTL byte 0 (reserved) */
uint8_t fcpCntl1; /* FCP_CNTL byte 1 task codes */
uint8_t fcpCntl2; /* FCP_CTL byte 2 task management codes */
uint8_t fcpCntl3;
uint8_t fcpCdb[LPFC_FCP_CDB_LEN_32]; /* SRB cdb field is copied here */
__be32 fcpDl; /* Total transfer length */
};
#define LPFC_SCSI_DMA_EXT_SIZE 264
#define LPFC_BPL_SIZE 1024
#define MDAC_DIRECT_CMD 0x22
#define FIND_FIRST_OAS_LUN 0
#define NO_MORE_OAS_LUN -1
#define NOT_OAS_ENABLED_LUN NO_MORE_OAS_LUN
#ifndef FC_PORTSPEED_128GBIT
#define FC_PORTSPEED_128GBIT 0x2000
#endif
#ifndef FC_PORTSPEED_256GBIT
#define FC_PORTSPEED_256GBIT 0x4000
#endif
#define TXRDY_PAYLOAD_LEN 12
/* For sysfs/debugfs tmp string max len */
#define LPFC_MAX_SCSI_INFO_TMP_LEN 79
File diff suppressed because it is too large Load Diff
+503
View File
@@ -0,0 +1,503 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017-2024 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* 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 *
* 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. *
*******************************************************************/
#if defined(CONFIG_DEBUG_FS) && !defined(CONFIG_SCSI_LPFC_DEBUG_FS)
#define CONFIG_SCSI_LPFC_DEBUG_FS
#endif
/* forward declaration for LPFC_IOCB_t's use */
struct lpfc_hba;
struct lpfc_vport;
/* Define the context types that SLI handles for abort and sums. */
typedef enum _lpfc_ctx_cmd {
LPFC_CTX_LUN,
LPFC_CTX_TGT,
LPFC_CTX_HOST
} lpfc_ctx_cmd;
/* Enumeration to describe the thread lock context. */
enum lpfc_mbox_ctx {
MBOX_THD_UNLOCKED,
MBOX_THD_LOCKED
};
union lpfc_vmid_tag {
uint32_t app_id;
uint8_t cs_ctl_vmid;
struct lpfc_vmid_context *vmid_context; /* UVEM context information */
};
struct lpfc_cq_event {
struct list_head list;
uint16_t hdwq;
union {
struct lpfc_mcqe mcqe_cmpl;
struct lpfc_acqe_link acqe_link;
struct lpfc_acqe_fip acqe_fip;
struct lpfc_acqe_dcbx acqe_dcbx;
struct lpfc_acqe_grp5 acqe_grp5;
struct lpfc_acqe_fc_la acqe_fc;
struct lpfc_acqe_sli acqe_sli;
struct lpfc_rcqe rcqe_cmpl;
struct sli4_wcqe_xri_aborted wcqe_axri;
struct lpfc_wcqe_complete wcqe_cmpl;
} cqe;
};
/* 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;
struct list_head dlist;
uint16_t iotag; /* pre-assigned IO tag */
uint16_t sli4_lxritag; /* logical pre-assigned XRI. */
uint16_t sli4_xritag; /* pre-assigned XRI, (OXID) tag. */
uint16_t hba_wqidx; /* index to HBA work queue */
struct lpfc_cq_event cq_event;
uint64_t isr_timestamp;
union lpfc_wqe128 wqe; /* SLI-4 */
IOCB_t iocb; /* SLI-3 */
struct lpfc_wcqe_complete wcqe_cmpl; /* WQE cmpl */
u32 unsol_rcv_len; /* Receive len in usol path */
/* Pack the u8's together and make them module-4. */
u8 num_bdes; /* Number of BDEs */
u8 abort_bls; /* ABTS by initiator or responder */
u8 abort_rctl; /* ACC or RJT flag */
u8 priority; /* OAS priority */
u8 retry; /* retry counter for IOCB cmd - if needed */
u8 rsvd1; /* Pad for u32 */
u8 rsvd2; /* Pad for u32 */
u8 rsvd3; /* Pad for u32 */
u32 cmd_flag;
#define LPFC_IO_LIBDFC 1 /* libdfc iocb */
#define LPFC_IO_WAKE 2 /* Synchronous I/O completed */
#define LPFC_IO_WAKE_TMO LPFC_IO_WAKE /* Synchronous I/O timed out */
#define LPFC_IO_FCP 4 /* FCP command -- iocbq in scsi_buf */
#define LPFC_DRIVER_ABORTED 8 /* driver aborted this request */
#define LPFC_IO_FABRIC 0x10 /* Iocb send using fabric scheduler */
#define LPFC_DELAY_MEM_FREE 0x20 /* Defer free'ing of FC data */
#define LPFC_EXCHANGE_BUSY 0x40 /* SLI4 hba reported XB in response */
#define LPFC_USE_FCPWQIDX 0x80 /* Submit to specified FCPWQ index */
#define DSS_SECURITY_OP 0x100 /* security IO */
#define LPFC_IO_ON_TXCMPLQ 0x200 /* The IO is still on the TXCMPLQ */
#define LPFC_IO_DIF_PASS 0x400 /* T10 DIF IO pass-thru prot */
#define LPFC_IO_DIF_STRIP 0x800 /* T10 DIF IO strip prot */
#define LPFC_IO_DIF_INSERT 0x1000 /* T10 DIF IO insert prot */
#define LPFC_IO_CMD_OUTSTANDING 0x2000 /* timeout handler abort window */
#define LPFC_FIP_ELS_ID_MASK 0xc000 /* ELS_ID range 0-3, non-shifted mask */
#define LPFC_FIP_ELS_ID_SHIFT 14
#define LPFC_IO_OAS 0x10000 /* OAS FCP IO */
#define LPFC_IO_FOF 0x20000 /* FOF FCP IO */
#define LPFC_IO_LOOPBACK 0x40000 /* Loopback IO */
#define LPFC_PRLI_NVME_REQ 0x80000 /* This is an NVME PRLI. */
#define LPFC_PRLI_FCP_REQ 0x100000 /* This is an NVME PRLI. */
#define LPFC_IO_NVME 0x200000 /* NVME FCP command */
#define LPFC_IO_NVME_LS 0x400000 /* NVME LS command */
#define LPFC_IO_NVMET 0x800000 /* NVMET command */
#define LPFC_IO_VMID 0x1000000 /* VMID tagged IO */
#define LPFC_IO_CMF 0x4000000 /* CMF command */
uint32_t drvrTimeout; /* driver timeout in seconds */
struct lpfc_vport *vport;/* virtual port pointer */
struct lpfc_dmabuf *cmd_dmabuf;
struct lpfc_dmabuf *rsp_dmabuf;
struct lpfc_dmabuf *bpl_dmabuf;
uint32_t event_tag; /* LA Event tag */
union {
wait_queue_head_t *wait_queue;
struct lpfcMboxq *mbox;
struct lpfc_node_rrq *rrq;
struct nvmefc_ls_req *nvme_lsreq;
struct lpfc_async_xchg_ctx *axchg;
struct bsg_job_data *dd_data;
} context_un;
struct lpfc_io_buf *io_buf;
struct lpfc_iocbq *rsp_iocb;
struct lpfc_nodelist *ndlp;
union lpfc_vmid_tag vmid_tag;
void (*fabric_cmd_cmpl)(struct lpfc_hba *phba, struct lpfc_iocbq *cmd,
struct lpfc_iocbq *rsp);
void (*wait_cmd_cmpl)(struct lpfc_hba *phba, struct lpfc_iocbq *cmd,
struct lpfc_iocbq *rsp);
void (*cmd_cmpl)(struct lpfc_hba *phba, struct lpfc_iocbq *cmd,
struct lpfc_iocbq *rsp);
};
#define SLI_IOCB_RET_IOCB 1 /* Return IOCB if cmd ring full */
#define IOCB_SUCCESS 0
#define IOCB_BUSY 1
#define IOCB_ERROR 2
#define IOCB_TIMEDOUT 3
#define IOCB_ABORTED 4
#define IOCB_ABORTING 5
#define IOCB_NORESOURCE 6
#define SLI_WQE_RET_WQE 1 /* Return WQE if cmd ring full */
#define WQE_SUCCESS 0
#define WQE_BUSY 1
#define WQE_ERROR 2
#define WQE_TIMEDOUT 3
#define WQE_ABORTED 4
#define WQE_ABORTING 5
#define WQE_NORESOURCE 6
#define LPFC_MBX_WAKE 1
#define LPFC_MBX_IMED_UNREG 2
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_mqe mqe;
} u;
struct lpfc_vport *vport; /* virtual port pointer */
struct lpfc_nodelist *ctx_ndlp; /* caller ndlp pointer */
struct lpfc_dmabuf *ctx_buf; /* caller buffer information */
void *ext_buf; /* extended buffer for extended mbox
* cmds. Not a generic pointer.
* Use for storing virtual address.
*/
/* Pointers that are seldom used during mbox execution, but require
* a saved context.
*/
union {
unsigned long ox_rx_id; /* Used in els_rsp_rls_acc */
struct lpfc_rdp_context *rdp; /* Used in get_rdp_info */
struct lpfc_lcb_context *lcb; /* Used in set_beacon */
struct completion *mbox_wait; /* Used in issue_mbox_wait */
struct bsg_job_data *dd_data; /* Used in bsg_issue_mbox_cmpl
* and
* bsg_issue_mbox_ext_handle_job
*/
struct lpfc_iocbq *save_iocb; /* Used in defer_plogi_acc and
* lpfc_mbx_cmpl_resume_rpi
*/
} ctx_u;
void (*mbox_cmpl) (struct lpfc_hba *, struct lpfcMboxq *);
uint8_t mbox_flag;
uint16_t in_ext_byte_len;
uint16_t out_ext_byte_len;
uint8_t mbox_offset_word;
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
return */
#define MBX_NOWAIT 2 /* issue command then return immediately */
#define LPFC_MAX_RING_MASK 5 /* max num of rctl/type masks allowed per
ring */
#define LPFC_SLI3_MAX_RING 4 /* Max num of SLI3 rings used by driver.
For SLI4, an additional ring for each
FCP WQ will be allocated. */
struct lpfc_sli_ring;
struct lpfc_sli_ring_mask {
uint8_t profile; /* profile associated with ring */
uint8_t rctl; /* rctl / type pair configured for ring */
uint8_t type; /* rctl / type pair configured for ring */
uint8_t rsvd;
/* rcv'd unsol event */
void (*lpfc_sli_rcv_unsol_event) (struct lpfc_hba *,
struct lpfc_sli_ring *,
struct lpfc_iocbq *);
};
/* Structure used to hold SLI statistical counters and info */
struct lpfc_sli_ring_stat {
uint64_t iocb_event; /* IOCB event counters */
uint64_t iocb_cmd; /* IOCB cmd issued */
uint64_t iocb_rsp; /* IOCB rsp received */
uint64_t iocb_cmd_delay; /* IOCB cmd ring delay */
uint64_t iocb_cmd_full; /* IOCB cmd ring full */
uint64_t iocb_cmd_empty; /* IOCB cmd ring is now empty */
uint64_t iocb_rsp_full; /* IOCB rsp ring full */
};
struct lpfc_sli3_ring {
uint32_t local_getidx; /* last available cmd index (from cmdGetInx) */
uint32_t next_cmdidx; /* next_cmd index */
uint32_t rspidx; /* current index in response ring */
uint32_t cmdidx; /* current index in command ring */
uint16_t numCiocb; /* number of command iocb's per ring */
uint16_t numRiocb; /* number of rsp iocb's per ring */
uint16_t sizeCiocb; /* Size of command iocb's in this ring */
uint16_t sizeRiocb; /* Size of response iocb's in this ring */
uint32_t *cmdringaddr; /* virtual address for cmd rings */
uint32_t *rspringaddr; /* virtual address for rsp rings */
};
struct lpfc_sli4_ring {
struct lpfc_queue *wqp; /* Pointer to associated WQ */
};
/* Structure used to hold SLI ring information */
struct lpfc_sli_ring {
uint16_t flag; /* ring flags */
#define LPFC_DEFERRED_RING_EVENT 0x001 /* Deferred processing a ring event */
#define LPFC_CALL_RING_AVAILABLE 0x002 /* indicates cmd was full */
#define LPFC_STOP_IOCB_EVENT 0x020 /* Stop processing IOCB cmds event */
uint16_t abtsiotag; /* tracks next iotag to use for ABTS */
uint8_t rsvd;
uint8_t ringno; /* ring number */
spinlock_t ring_lock; /* lock for issuing commands */
uint32_t fast_iotag; /* max fastlookup based iotag */
uint32_t iotag_ctr; /* keeps track of the next iotag to use */
uint32_t iotag_max; /* max iotag value to use */
struct list_head txq;
uint16_t txq_cnt; /* current length of queue */
uint16_t txq_max; /* max length */
struct list_head txcmplq;
uint16_t txcmplq_cnt; /* current length of queue */
uint16_t txcmplq_max; /* max length */
uint32_t missbufcnt; /* keep track of buffers to post */
struct list_head postbufq;
uint16_t postbufq_cnt; /* current length of queue */
uint16_t postbufq_max; /* max length */
struct list_head iocb_continueq;
uint16_t iocb_continueq_cnt; /* current length of queue */
uint16_t iocb_continueq_max; /* max length */
struct list_head iocb_continue_saveq;
struct lpfc_sli_ring_mask prt[LPFC_MAX_RING_MASK];
uint32_t num_mask; /* number of mask entries in prt array */
void (*lpfc_sli_rcv_async_status) (struct lpfc_hba *,
struct lpfc_sli_ring *, struct lpfc_iocbq *);
struct lpfc_sli_ring_stat stats; /* SLI statistical info */
/* cmd ring available */
void (*lpfc_sli_cmd_available) (struct lpfc_hba *,
struct lpfc_sli_ring *);
union {
struct lpfc_sli3_ring sli3;
struct lpfc_sli4_ring sli4;
} sli;
};
/* Structure used for configuring rings to a specific profile or rctl / type */
struct lpfc_hbq_init {
uint32_t rn; /* Receive buffer notification */
uint32_t entry_count; /* max # of entries in HBQ */
uint32_t headerLen; /* 0 if not profile 4 or 5 */
uint32_t logEntry; /* Set to 1 if this HBQ used for LogEntry */
uint32_t profile; /* Selection profile 0=all, 7=logentry */
uint32_t ring_mask; /* Binds HBQ to a ring e.g. Ring0=b0001,
* ring2=b0100 */
uint32_t hbq_index; /* index of this hbq in ring .HBQs[] */
uint32_t seqlenoff;
uint32_t maxlen;
uint32_t seqlenbcnt;
uint32_t cmdcodeoff;
uint32_t cmdmatch[8];
uint32_t mask_count; /* number of mask entries in prt array */
struct hbq_mask hbqMasks[6];
/* Non-config rings fields to keep track of buffer allocations */
uint32_t buffer_count; /* number of buffers allocated */
uint32_t init_count; /* number to allocate when initialized */
uint32_t add_count; /* number to allocate when starved */
} ;
/* Structure used to hold SLI statistical counters and info */
struct lpfc_sli_stat {
uint64_t mbox_stat_err; /* Mbox cmds completed status error */
uint64_t mbox_cmd; /* Mailbox commands issued */
uint64_t sli_intr; /* Count of Host Attention interrupts */
uint64_t sli_prev_intr; /* Previous cnt of Host Attention interrupts */
uint64_t sli_ips; /* Host Attention interrupts per sec */
uint32_t err_attn_event; /* Error Attn event counters */
uint32_t link_event; /* Link event counters */
uint32_t mbox_event; /* Mailbox event counters */
uint32_t mbox_busy; /* Mailbox cmd busy */
};
/* Structure to store link status values when port stats are reset */
struct lpfc_lnk_stat {
uint32_t link_failure_count;
uint32_t loss_of_sync_count;
uint32_t loss_of_signal_count;
uint32_t prim_seq_protocol_err_count;
uint32_t invalid_tx_word_count;
uint32_t invalid_crc_count;
uint32_t error_frames;
uint32_t link_events;
};
/* Structure used to hold SLI information */
struct lpfc_sli {
uint32_t num_rings;
uint32_t sli_flag;
/* Additional sli_flags */
#define LPFC_SLI_MBOX_ACTIVE 0x100 /* HBA mailbox is currently active */
#define LPFC_SLI_ACTIVE 0x200 /* SLI in firmware is active */
#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_SLI_ASYNC_MBX_BLK 0x2000 /* Async mailbox is blocked */
#define LPFC_SLI_SUPPRESS_RSP 0x4000 /* Suppress RSP feature is supported */
#define LPFC_SLI_USE_EQDR 0x8000 /* EQ Delay Register is supported */
#define LPFC_QUEUE_FREE_INIT 0x10000 /* Queue freeing is in progress */
#define LPFC_QUEUE_FREE_WAIT 0x20000 /* Hold Queue free as it is being
* used outside worker thread
*/
struct lpfc_sli_ring *sli3_ring;
struct lpfc_sli_stat slistat; /* SLI statistical info */
struct list_head mboxq;
uint16_t mboxq_cnt; /* current length of queue */
uint16_t mboxq_max; /* max length */
LPFC_MBOXQ_t *mbox_active; /* active mboxq information */
struct list_head mboxq_cmpl;
struct timer_list mbox_tmo; /* Hold clk to timeout active mbox
cmd */
#define LPFC_IOCBQ_LOOKUP_INCREMENT 1024
struct lpfc_iocbq ** iocbq_lookup; /* array to lookup IOCB by IOTAG */
size_t iocbq_lookup_len; /* current lengs of the array */
uint16_t last_iotag; /* last allocated IOTAG */
time64_t stats_start; /* in seconds */
struct lpfc_lnk_stat lnk_stat_offsets;
};
/* Timeout for normal outstanding mbox command (Seconds) */
#define LPFC_MBOX_TMO 30
/* Timeout for non-flash-based outstanding sli_config mbox command (Seconds) */
#define LPFC_MBOX_SLI4_CONFIG_TMO 60
/* Timeout for flash-based outstanding sli_config mbox command (Seconds) */
#define LPFC_MBOX_SLI4_CONFIG_EXTENDED_TMO 300
/* Timeout for other flash-based outstanding mbox command (Seconds) */
#define LPFC_MBOX_TMO_FLASH_CMD 300
struct lpfc_io_buf {
/* Common fields */
struct list_head list;
void *data;
dma_addr_t dma_handle;
dma_addr_t dma_phys_sgl;
struct sli4_sge *dma_sgl; /* initial segment chunk */
/* linked list of extra sli4_hybrid_sge */
struct list_head dma_sgl_xtra_list;
/* list head for fcp_cmd_rsp buf */
struct list_head dma_cmd_rsp_list;
struct lpfc_iocbq cur_iocbq;
struct lpfc_sli4_hdw_queue *hdwq;
uint16_t hdwq_no;
uint16_t cpu;
struct lpfc_nodelist *ndlp;
uint32_t timeout;
uint16_t flags;
#define LPFC_SBUF_XBUSY 0x1 /* SLI4 hba reported XB on WCQE cmpl */
#define LPFC_SBUF_BUMP_QDEPTH 0x2 /* bumped queue depth counter */
/* External DIF device IO conversions */
#define LPFC_SBUF_NORMAL_DIF 0x4 /* normal mode to insert/strip */
#define LPFC_SBUF_PASS_DIF 0x8 /* insert/strip mode to passthru */
#define LPFC_SBUF_NOT_POSTED 0x10 /* SGL failed post to FW. */
uint16_t status; /* From IOCB Word 7- ulpStatus */
uint32_t result; /* From IOCB Word 4. */
uint32_t seg_cnt; /* Number of scatter-gather segments returned by
* dma_map_sg. The driver needs this for calls
* to dma_unmap_sg.
*/
unsigned long start_time;
spinlock_t buf_lock; /* lock used in case of simultaneous abort */
bool expedite; /* this is an expedite io_buf */
union {
/* SCSI specific fields */
struct {
struct scsi_cmnd *pCmd;
struct lpfc_rport_data *rdata;
uint32_t prot_seg_cnt; /* seg_cnt's counterpart for
* protection data
*/
/*
* data and dma_handle are the kernel virtual and bus
* address of the dma-able buffer containing the
* fcp_cmd, fcp_rsp and a scatter gather bde list that
* supports the sg_tablesize value.
*/
struct fcp_cmnd *fcp_cmnd;
struct fcp_rsp *fcp_rsp;
wait_queue_head_t *waitq;
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
/* Used to restore any changes to protection data for
* error injection
*/
void *prot_data_segment;
uint32_t prot_data;
uint32_t prot_data_type;
#define LPFC_INJERR_REFTAG 1
#define LPFC_INJERR_APPTAG 2
#define LPFC_INJERR_GUARD 3
#endif
};
/* NVME specific fields */
struct {
struct nvmefc_fcp_req *nvmeCmd;
uint16_t qidx;
};
};
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
uint64_t ts_cmd_start;
uint64_t ts_last_cmd;
uint64_t ts_cmd_wqput;
uint64_t ts_isr_cmpl;
uint64_t ts_data_io;
#endif
uint64_t rx_cmd_start;
};
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,37 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017-2026 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* 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 *
* 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_DRIVER_VERSION "15.0.0.0"
#define LPFC_DRIVER_NAME "lpfc"
/* Used for SLI 2/3 */
#define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp"
#define LPFC_FP_DRIVER_HANDLER_NAME "lpfc:fp"
/* Used for SLI4 */
#define LPFC_DRIVER_HANDLER_NAME "lpfc:"
#define LPFC_MODULE_DESC "Emulex LightPulse Fibre Channel SCSI driver " \
LPFC_DRIVER_VERSION
#define LPFC_COPYRIGHT "Copyright (C) 2017-2026 Broadcom. All Rights " \
"Reserved. The term \"Broadcom\" refers to Broadcom Inc. " \
"and/or its subsidiaries."
+325
View File
@@ -0,0 +1,325 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017-2024 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.broadcom.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of version 2 of the GNU General *
* Public License as published by the Free Software Foundation. *
* This program is distributed in the hope that it will be useful. *
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
* DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
* TO BE LEGALLY INVALID. See the GNU General Public License for *
* more details, a copy of which can be found in the file COPYING *
* included with this package. *
*******************************************************************/
#include <linux/interrupt.h>
#include <linux/dma-direction.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.h"
#include "lpfc_crtn.h"
/*
* lpfc_get_vmid_from_hashtable - search the UUID in the hash table
* @vport: The virtual port for which this call is being executed.
* @hash: calculated hash value
* @buf: uuid associated with the VE
* Return the VMID entry associated with the UUID
* Make sure to acquire the appropriate lock before invoking this routine.
*/
struct lpfc_vmid *lpfc_get_vmid_from_hashtable(struct lpfc_vport *vport,
u32 hash, u8 *buf)
{
struct lpfc_vmid *vmp;
hash_for_each_possible(vport->hash_table, vmp, hnode, hash) {
if (memcmp(&vmp->host_vmid[0], buf, 16) == 0)
return vmp;
}
return NULL;
}
/*
* lpfc_put_vmid_in_hashtable - put the VMID in the hash table
* @vport: The virtual port for which this call is being executed.
* @hash - calculated hash value
* @vmp: Pointer to a VMID entry representing a VM sending I/O
*
* This routine will insert the newly acquired VMID entity in the hash table.
* Make sure to acquire the appropriate lock before invoking this routine.
*/
static void
lpfc_put_vmid_in_hashtable(struct lpfc_vport *vport, u32 hash,
struct lpfc_vmid *vmp)
{
hash_add(vport->hash_table, &vmp->hnode, hash);
}
/*
* lpfc_vmid_hash_fn - create a hash value of the UUID
* @vmid: uuid associated with the VE
* @len: length of the VMID string
* Returns the calculated hash value
*/
int lpfc_vmid_hash_fn(const char *vmid, int len)
{
int c;
int hash = 0;
if (len == 0)
return 0;
while (len--) {
c = *vmid++;
if (c >= 'A' && c <= 'Z')
c += 'a' - 'A';
hash = (hash + (c << LPFC_VMID_HASH_SHIFT) +
(c >> LPFC_VMID_HASH_SHIFT)) * 19;
}
return hash & LPFC_VMID_HASH_MASK;
}
/*
* lpfc_vmid_update_entry - update the vmid entry in the hash table
* @vport: The virtual port for which this call is being executed.
* @iodir: io direction
* @vmp: Pointer to a VMID entry representing a VM sending I/O
* @tag: VMID tag
*/
static void lpfc_vmid_update_entry(struct lpfc_vport *vport,
enum dma_data_direction iodir,
struct lpfc_vmid *vmp,
union lpfc_vmid_io_tag *tag)
{
u64 *lta;
if (vport->phba->pport->vmid_flag & LPFC_VMID_TYPE_PRIO)
tag->cs_ctl_vmid = vmp->un.cs_ctl_vmid;
else if (vport->phba->cfg_vmid_app_header)
tag->app_id = vmp->un.app_id;
if (iodir == DMA_TO_DEVICE)
vmp->io_wr_cnt++;
else if (iodir == DMA_FROM_DEVICE)
vmp->io_rd_cnt++;
/* update the last access timestamp in the table */
lta = per_cpu_ptr(vmp->last_io_time, raw_smp_processor_id());
*lta = jiffies;
}
static void lpfc_vmid_assign_cs_ctl(struct lpfc_vport *vport,
struct lpfc_vmid *vmid)
{
u32 hash;
struct lpfc_vmid *pvmid;
if (vport->port_type == LPFC_PHYSICAL_PORT) {
vmid->un.cs_ctl_vmid = lpfc_vmid_get_cs_ctl(vport);
} else {
hash = lpfc_vmid_hash_fn(vmid->host_vmid, vmid->vmid_len);
pvmid =
lpfc_get_vmid_from_hashtable(vport->phba->pport, hash,
vmid->host_vmid);
if (pvmid)
vmid->un.cs_ctl_vmid = pvmid->un.cs_ctl_vmid;
else
vmid->un.cs_ctl_vmid = lpfc_vmid_get_cs_ctl(vport);
}
}
/*
* lpfc_vmid_get_appid - get the VMID associated with the UUID
* @vport: The virtual port for which this call is being executed.
* @uuid: UUID associated with the VE
* @cmd: address of scsi_cmd descriptor
* @iodir: io direction
* @tag: VMID tag
* Returns status of the function
*/
int lpfc_vmid_get_appid(struct lpfc_vport *vport, char *uuid,
enum dma_data_direction iodir,
union lpfc_vmid_io_tag *tag)
{
struct lpfc_vmid *vmp = NULL;
int hash, len, rc = -EPERM, i;
/* check if QFPA is complete */
if (lpfc_vmid_is_type_priority_tag(vport) &&
!(vport->vmid_flag & LPFC_VMID_QFPA_CMPL) &&
(vport->vmid_flag & LPFC_VMID_ISSUE_QFPA)) {
vport->work_port_events |= WORKER_CHECK_VMID_ISSUE_QFPA;
return -EAGAIN;
}
/* search if the UUID has already been mapped to the VMID */
len = strlen(uuid);
hash = lpfc_vmid_hash_fn(uuid, len);
/* search for the VMID in the table */
read_lock(&vport->vmid_lock);
vmp = lpfc_get_vmid_from_hashtable(vport, hash, uuid);
/* if found, check if its already registered */
if (vmp && vmp->flag & LPFC_VMID_REGISTERED) {
read_unlock(&vport->vmid_lock);
lpfc_vmid_update_entry(vport, iodir, vmp, tag);
rc = 0;
} else if (vmp && (vmp->flag & LPFC_VMID_REQ_REGISTER ||
vmp->flag & LPFC_VMID_DE_REGISTER)) {
/* else if register or dereg request has already been sent */
/* Hence VMID tag will not be added for this I/O */
read_unlock(&vport->vmid_lock);
rc = -EBUSY;
} else {
/* The VMID was not found in the hashtable. At this point, */
/* drop the read lock first before proceeding further */
read_unlock(&vport->vmid_lock);
/* start the process to obtain one as per the */
/* type of the VMID indicated */
write_lock(&vport->vmid_lock);
vmp = lpfc_get_vmid_from_hashtable(vport, hash, uuid);
/* while the read lock was released, in case the entry was */
/* added by other context or is in process of being added */
if (vmp && vmp->flag & LPFC_VMID_REGISTERED) {
lpfc_vmid_update_entry(vport, iodir, vmp, tag);
write_unlock(&vport->vmid_lock);
return 0;
} else if (vmp && vmp->flag & LPFC_VMID_REQ_REGISTER) {
write_unlock(&vport->vmid_lock);
return -EBUSY;
}
/* else search and allocate a free slot in the hash table */
if (vport->cur_vmid_cnt < vport->max_vmid) {
for (i = 0; i < vport->max_vmid; i++) {
vmp = vport->vmid + i;
if (vmp->flag == LPFC_VMID_SLOT_FREE)
break;
}
if (i == vport->max_vmid)
vmp = NULL;
} else {
vmp = NULL;
}
if (!vmp) {
write_unlock(&vport->vmid_lock);
return -ENOMEM;
}
/* Add the vmid and register */
lpfc_put_vmid_in_hashtable(vport, hash, vmp);
vmp->vmid_len = len;
memcpy(vmp->host_vmid, uuid, vmp->vmid_len);
vmp->io_rd_cnt = 0;
vmp->io_wr_cnt = 0;
vmp->flag = LPFC_VMID_SLOT_USED;
vmp->delete_inactive =
vport->vmid_inactivity_timeout ? 1 : 0;
/* if type priority tag, get next available VMID */
if (vport->phba->pport->vmid_flag & LPFC_VMID_TYPE_PRIO)
lpfc_vmid_assign_cs_ctl(vport, vmp);
/* allocate the per cpu variable for holding */
/* the last access time stamp only if VMID is enabled */
if (!vmp->last_io_time)
vmp->last_io_time = alloc_percpu_gfp(u64, GFP_ATOMIC);
if (!vmp->last_io_time) {
hash_del(&vmp->hnode);
vmp->flag = LPFC_VMID_SLOT_FREE;
write_unlock(&vport->vmid_lock);
return -EIO;
}
write_unlock(&vport->vmid_lock);
/* complete transaction with switch */
if (vport->phba->pport->vmid_flag & LPFC_VMID_TYPE_PRIO)
rc = lpfc_vmid_uvem(vport, vmp, true);
else if (vport->phba->cfg_vmid_app_header)
rc = lpfc_vmid_cmd(vport, SLI_CTAS_RAPP_IDENT, vmp);
if (!rc) {
write_lock(&vport->vmid_lock);
vport->cur_vmid_cnt++;
vmp->flag |= LPFC_VMID_REQ_REGISTER;
write_unlock(&vport->vmid_lock);
} else {
write_lock(&vport->vmid_lock);
hash_del(&vmp->hnode);
vmp->flag = LPFC_VMID_SLOT_FREE;
free_percpu(vmp->last_io_time);
write_unlock(&vport->vmid_lock);
return -EIO;
}
/* finally, enable the idle timer once */
if (!(vport->phba->pport->vmid_flag & LPFC_VMID_TIMER_ENBLD)) {
mod_timer(&vport->phba->inactive_vmid_poll,
jiffies +
secs_to_jiffies(LPFC_VMID_TIMER));
vport->phba->pport->vmid_flag |= LPFC_VMID_TIMER_ENBLD;
}
}
return rc;
}
/*
* lpfc_reinit_vmid - reinitializes the vmid data structure
* @vport: pointer to vport data structure
*
* This routine reinitializes the vmid post flogi completion
*
* Return codes
* None
*/
void
lpfc_reinit_vmid(struct lpfc_vport *vport)
{
u32 bucket, i, cpu;
struct lpfc_vmid *cur;
struct lpfc_vmid *vmp = NULL;
struct hlist_node *tmp;
write_lock(&vport->vmid_lock);
vport->cur_vmid_cnt = 0;
for (i = 0; i < vport->max_vmid; i++) {
vmp = &vport->vmid[i];
vmp->flag = LPFC_VMID_SLOT_FREE;
memset(vmp->host_vmid, 0, sizeof(vmp->host_vmid));
vmp->io_rd_cnt = 0;
vmp->io_wr_cnt = 0;
if (vmp->last_io_time)
for_each_possible_cpu(cpu)
*per_cpu_ptr(vmp->last_io_time, cpu) = 0;
}
/* for all elements in the hash table */
if (!hash_empty(vport->hash_table))
hash_for_each_safe(vport->hash_table, bucket, tmp, cur, hnode)
hash_del(&cur->hnode);
write_unlock(&vport->vmid_lock);
}
+820
View File
@@ -0,0 +1,820 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017-2024 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.broadcom.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of version 2 of the GNU General *
* Public License as published by the Free Software Foundation. *
* This program is distributed in the hope that it will be useful. *
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
* DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
* TO BE LEGALLY INVALID. See the GNU General Public License for *
* more details, a copy of which can be found in the file COPYING *
* included with this package. *
*******************************************************************/
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/idr.h>
#include <linux/interrupt.h>
#include <linux/kthread.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/sched/signal.h>
#include <scsi/scsi.h>
#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"
#include "lpfc.h"
#include "lpfc_logmsg.h"
#include "lpfc_crtn.h"
#include "lpfc_version.h"
#include "lpfc_vport.h"
inline void lpfc_vport_set_state(struct lpfc_vport *vport,
enum fc_vport_state new_state)
{
struct fc_vport *fc_vport = vport->fc_vport;
if (fc_vport) {
/*
* When the transport defines fc_vport_set state we will replace
* this code with the following line
*/
/* fc_vport_set_state(fc_vport, new_state); */
if (new_state != FC_VPORT_INITIALIZING)
fc_vport->vport_last_state = fc_vport->vport_state;
fc_vport->vport_state = new_state;
}
/* for all the error states we will set the invternal state to FAILED */
switch (new_state) {
case FC_VPORT_NO_FABRIC_SUPP:
case FC_VPORT_NO_FABRIC_RSCS:
case FC_VPORT_FABRIC_LOGOUT:
case FC_VPORT_FABRIC_REJ_WWN:
case FC_VPORT_FAILED:
vport->port_state = LPFC_VPORT_FAILED;
break;
case FC_VPORT_LINKDOWN:
vport->port_state = LPFC_VPORT_UNKNOWN;
break;
default:
/* do nothing */
break;
}
}
int
lpfc_alloc_vpi(struct lpfc_hba *phba)
{
unsigned long vpi;
spin_lock_irq(&phba->hbalock);
/* Start at bit 1 because vpi zero is reserved for the physical port */
vpi = find_next_zero_bit(phba->vpi_bmask, (phba->max_vpi + 1), 1);
if (vpi > phba->max_vpi)
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;
}
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);
}
static int
lpfc_vport_sparm(struct lpfc_hba *phba, struct lpfc_vport *vport)
{
LPFC_MBOXQ_t *pmb;
MAILBOX_t *mb;
struct lpfc_dmabuf *mp;
int rc;
pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!pmb) {
return -ENOMEM;
}
mb = &pmb->u.mb;
rc = lpfc_read_sparam(phba, pmb, vport->vpi);
if (rc) {
mempool_free(pmb, phba->mbox_mem_pool);
return -ENOMEM;
}
/*
* Wait for the read_sparams mailbox to complete. Driver needs
* this per vport to start the FDISC. If the mailbox fails,
* just cleanup and return an error unless the failure is a
* mailbox timeout. For MBX_TIMEOUT, allow the default
* mbox completion handler to take care of the cleanup. This
* is safe as the mailbox command isn't one that triggers
* another mailbox.
*/
pmb->vport = vport;
rc = lpfc_sli_issue_mbox_wait(phba, pmb, phba->fc_ratov * 2);
if (rc != MBX_SUCCESS) {
if (signal_pending(current)) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"1830 Signal aborted mbxCmd x%x\n",
mb->mbxCommand);
if (rc != MBX_TIMEOUT)
lpfc_mbox_rsrc_cleanup(phba, pmb,
MBOX_THD_UNLOCKED);
return -EINTR;
} else {
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"1818 VPort failed init, mbxCmd x%x "
"READ_SPARM mbxStatus x%x, rc = x%x\n",
mb->mbxCommand, mb->mbxStatus, rc);
if (rc != MBX_TIMEOUT)
lpfc_mbox_rsrc_cleanup(phba, pmb,
MBOX_THD_UNLOCKED);
return -EIO;
}
}
mp = pmb->ctx_buf;
memcpy(&vport->fc_sparam, mp->virt, sizeof (struct serv_parm));
memcpy(&vport->fc_nodename, &vport->fc_sparam.nodeName,
sizeof (struct lpfc_name));
memcpy(&vport->fc_portname, &vport->fc_sparam.portName,
sizeof (struct lpfc_name));
lpfc_mbox_rsrc_cleanup(phba, pmb, MBOX_THD_UNLOCKED);
return 0;
}
static int
lpfc_valid_wwn_format(struct lpfc_hba *phba, struct lpfc_name *wwn,
const char *name_type)
{
/* ensure that IEEE format 1 addresses
* contain zeros in bits 59-48
*/
if (!((wwn->u.wwn[0] >> 4) == 1 &&
((wwn->u.wwn[0] & 0xf) != 0 || (wwn->u.wwn[1] & 0xf) != 0)))
return 1;
lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
"1822 Invalid %s: %02x:%02x:%02x:%02x:"
"%02x:%02x:%02x:%02x\n",
name_type,
wwn->u.wwn[0], wwn->u.wwn[1],
wwn->u.wwn[2], wwn->u.wwn[3],
wwn->u.wwn[4], wwn->u.wwn[5],
wwn->u.wwn[6], wwn->u.wwn[7]);
return 0;
}
static int
lpfc_unique_wwpn(struct lpfc_hba *phba, struct lpfc_vport *new_vport)
{
struct lpfc_vport *vport;
unsigned long flags;
spin_lock_irqsave(&phba->port_list_lock, flags);
list_for_each_entry(vport, &phba->port_list, listentry) {
if (vport == new_vport)
continue;
/* If they match, return not unique */
if (memcmp(&vport->fc_sparam.portName,
&new_vport->fc_sparam.portName,
sizeof(struct lpfc_name)) == 0) {
spin_unlock_irqrestore(&phba->port_list_lock, flags);
return 0;
}
}
spin_unlock_irqrestore(&phba->port_list_lock, flags);
return 1;
}
/**
* lpfc_discovery_wait - Wait for driver discovery to quiesce
* @vport: The virtual port for which this call is being executed.
*
* This driver calls this routine specifically from lpfc_vport_delete
* to enforce a synchronous execution of vport
* delete relative to discovery activities. The
* lpfc_vport_delete routine should not return until it
* can reasonably guarantee that discovery has quiesced.
* Post FDISC LOGO, the driver must wait until its SAN teardown is
* complete and all resources recovered before allowing
* cleanup.
*
* This routine does not require any locks held.
**/
static void lpfc_discovery_wait(struct lpfc_vport *vport)
{
struct lpfc_hba *phba = vport->phba;
unsigned long wait_time_max;
unsigned long start_time;
/*
* The time constraint on this loop is a balance between the
* fabric RA_TOV value and dev_loss tmo. The driver's
* devloss_tmo is 10 giving this loop a 3x multiplier minimally.
*/
wait_time_max = secs_to_jiffies((phba->fc_ratov * 3) + 3);
wait_time_max += jiffies;
start_time = jiffies;
while (time_before(jiffies, wait_time_max)) {
if ((vport->num_disc_nodes > 0) ||
test_bit(FC_RSCN_MODE, &vport->fc_flag) ||
test_bit(FC_RSCN_DISCOVERY, &vport->fc_flag) ||
test_bit(FC_NLP_MORE, &vport->fc_flag) ||
test_bit(FC_RSCN_DEFERRED, &vport->fc_flag) ||
test_bit(FC_NDISC_ACTIVE, &vport->fc_flag) ||
test_bit(FC_DISC_TMO, &vport->fc_flag) ||
((vport->port_state > LPFC_VPORT_FAILED) &&
(vport->port_state < LPFC_VPORT_READY))) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_VPORT,
"1833 Vport discovery quiesce Wait: "
"state x%x fc_flags x%lx "
"num_nodes x%x, waiting 1000 msecs "
"total wait msecs x%x\n",
vport->port_state, vport->fc_flag,
vport->num_disc_nodes,
jiffies_to_msecs(jiffies - start_time));
msleep(1000);
} else {
/* Base case. Wait variants satisfied. Break out */
lpfc_printf_vlog(vport, KERN_INFO, LOG_VPORT,
"1834 Vport discovery quiesced: "
"state x%x fc_flags x%lx "
"wait msecs x%x\n",
vport->port_state, vport->fc_flag,
jiffies_to_msecs(jiffies
- start_time));
break;
}
}
if (time_after(jiffies, wait_time_max))
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"1835 Vport discovery quiesce failed:"
" state x%x fc_flags x%lx wait msecs x%x\n",
vport->port_state, vport->fc_flag,
jiffies_to_msecs(jiffies - start_time));
}
int
lpfc_vport_create(struct fc_vport *fc_vport, bool disable)
{
struct lpfc_nodelist *ndlp;
struct Scsi_Host *shost = fc_vport->shost;
struct lpfc_vport *pport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = pport->phba;
struct lpfc_vport *vport = NULL;
int instance;
int vpi;
int rc = VPORT_ERROR;
int status;
if ((phba->sli_rev < 3) || !(phba->cfg_enable_npiv)) {
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1808 Create VPORT failed: "
"NPIV is not enabled: SLImode:%d\n",
phba->sli_rev);
rc = VPORT_INVAL;
goto error_out;
}
/* NPIV is not supported if HBA has NVME Target enabled */
if (phba->nvmet_support) {
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3189 Create VPORT failed: "
"NPIV is not supported on NVME Target\n");
rc = VPORT_INVAL;
goto error_out;
}
vpi = lpfc_alloc_vpi(phba);
if (vpi == 0) {
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1809 Create VPORT failed: "
"Max VPORTs (%d) exceeded\n",
phba->max_vpi);
rc = VPORT_NORESOURCES;
goto error_out;
}
/* Assign an unused board number */
if ((instance = lpfc_get_instance()) < 0) {
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1810 Create VPORT failed: Cannot get "
"instance number\n");
lpfc_free_vpi(phba, vpi);
rc = VPORT_NORESOURCES;
goto error_out;
}
vport = lpfc_create_port(phba, instance, &fc_vport->dev);
if (!vport) {
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1811 Create VPORT failed: vpi x%x\n", vpi);
lpfc_free_vpi(phba, vpi);
rc = VPORT_NORESOURCES;
goto error_out;
}
vport->vpi = vpi;
lpfc_debugfs_initialize(vport);
if ((status = lpfc_vport_sparm(phba, vport))) {
if (status == -EINTR) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"1831 Create VPORT Interrupted.\n");
rc = VPORT_ERROR;
} else {
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"1813 Create VPORT failed. "
"Cannot get sparam\n");
rc = VPORT_NORESOURCES;
}
lpfc_free_vpi(phba, vpi);
destroy_port(vport);
goto error_out;
}
u64_to_wwn(fc_vport->node_name, vport->fc_nodename.u.wwn);
u64_to_wwn(fc_vport->port_name, vport->fc_portname.u.wwn);
memcpy(&vport->fc_sparam.portName, vport->fc_portname.u.wwn, 8);
memcpy(&vport->fc_sparam.nodeName, vport->fc_nodename.u.wwn, 8);
if (!lpfc_valid_wwn_format(phba, &vport->fc_sparam.nodeName, "WWNN") ||
!lpfc_valid_wwn_format(phba, &vport->fc_sparam.portName, "WWPN")) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"1821 Create VPORT failed. "
"Invalid WWN format\n");
lpfc_free_vpi(phba, vpi);
destroy_port(vport);
rc = VPORT_INVAL;
goto error_out;
}
if (!lpfc_unique_wwpn(phba, vport)) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"1823 Create VPORT failed. "
"Duplicate WWN on HBA\n");
lpfc_free_vpi(phba, vpi);
destroy_port(vport);
rc = VPORT_INVAL;
goto error_out;
}
/* Create binary sysfs attribute for vport */
lpfc_alloc_sysfs_attr(vport);
/* Set the DFT_LUN_Q_DEPTH accordingly */
vport->cfg_lun_queue_depth = phba->pport->cfg_lun_queue_depth;
/* Only the physical port can support NVME for now */
vport->cfg_enable_fc4_type = LPFC_ENABLE_FCP;
*(struct lpfc_vport **)fc_vport->dd_data = vport;
vport->fc_vport = fc_vport;
/* At this point we are fully registered with SCSI Layer. */
set_bit(FC_ALLOW_FDMI, &vport->load_flag);
if (phba->cfg_enable_SmartSAN ||
(phba->cfg_fdmi_on == LPFC_FDMI_SUPPORT)) {
/* Setup appropriate attribute masks */
vport->fdmi_hba_mask = phba->pport->fdmi_hba_mask;
vport->fdmi_port_mask = phba->pport->fdmi_port_mask;
}
/*
* In SLI4, the vpi must be activated before it can be used
* by the port.
*/
if ((phba->sli_rev == LPFC_SLI_REV4) &&
test_bit(FC_VFI_REGISTERED, &pport->fc_flag)) {
rc = lpfc_sli4_init_vpi(vport);
if (rc) {
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1838 Failed to INIT_VPI on vpi %d "
"status %d\n", vpi, rc);
rc = VPORT_NORESOURCES;
lpfc_free_vpi(phba, vpi);
goto error_out;
}
} else if (phba->sli_rev == LPFC_SLI_REV4) {
/*
* Driver cannot INIT_VPI now. Set the flags to
* init_vpi when reg_vfi complete.
*/
set_bit(FC_VPORT_NEEDS_INIT_VPI, &vport->fc_flag);
lpfc_vport_set_state(vport, FC_VPORT_LINKDOWN);
rc = VPORT_OK;
goto out;
}
if ((phba->link_state < LPFC_LINK_UP) ||
(pport->port_state < LPFC_FABRIC_CFG_LINK) ||
(phba->fc_topology == LPFC_TOPOLOGY_LOOP)) {
lpfc_vport_set_state(vport, FC_VPORT_LINKDOWN);
rc = VPORT_OK;
goto out;
}
if (disable) {
lpfc_vport_set_state(vport, FC_VPORT_DISABLED);
rc = VPORT_OK;
goto out;
}
/* Use the Physical nodes Fabric NDLP to determine if the link is
* up and ready to FDISC.
*/
ndlp = lpfc_findnode_did(phba->pport, Fabric_DID);
if (ndlp &&
ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) {
lpfc_set_disctmo(vport);
lpfc_initial_fdisc(vport);
} else {
lpfc_vport_set_state(vport, FC_VPORT_NO_FABRIC_SUPP);
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0262 No NPIV Fabric support\n");
}
} else {
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
}
rc = VPORT_OK;
out:
lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
"1825 Vport Created.\n");
lpfc_host_attrib_init(lpfc_shost_from_vport(vport));
error_out:
return rc;
}
static int
lpfc_send_npiv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
{
int rc;
struct lpfc_hba *phba = vport->phba;
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waitq);
spin_lock_irq(&ndlp->lock);
if (!test_bit(NLP_WAIT_FOR_LOGO, &ndlp->save_flags) &&
!ndlp->logo_waitq) {
ndlp->logo_waitq = &waitq;
ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
set_bit(NLP_ISSUE_LOGO, &ndlp->nlp_flag);
set_bit(NLP_WAIT_FOR_LOGO, &ndlp->save_flags);
}
spin_unlock_irq(&ndlp->lock);
rc = lpfc_issue_els_npiv_logo(vport, ndlp);
if (!rc) {
wait_event_timeout(waitq,
!test_bit(NLP_WAIT_FOR_LOGO,
&ndlp->save_flags),
secs_to_jiffies(phba->fc_ratov * 2));
if (!test_bit(NLP_WAIT_FOR_LOGO, &ndlp->save_flags))
goto logo_cmpl;
/* LOGO wait failed. Correct status. */
rc = -EINTR;
} else {
rc = -EIO;
}
/* Error - clean up node flags. */
clear_bit(NLP_ISSUE_LOGO, &ndlp->nlp_flag);
clear_bit(NLP_WAIT_FOR_LOGO, &ndlp->save_flags);
logo_cmpl:
lpfc_printf_vlog(vport, KERN_INFO, LOG_VPORT,
"1824 Issue LOGO completes with status %d\n",
rc);
spin_lock_irq(&ndlp->lock);
ndlp->logo_waitq = NULL;
spin_unlock_irq(&ndlp->lock);
return rc;
}
static int
disable_vport(struct fc_vport *fc_vport)
{
struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data;
struct lpfc_hba *phba = vport->phba;
struct lpfc_nodelist *ndlp = NULL;
/* Can't disable during an outstanding delete. */
if (test_bit(FC_UNLOADING, &vport->load_flag))
return 0;
ndlp = lpfc_findnode_did(vport, Fabric_DID);
if (ndlp && phba->link_state >= LPFC_LINK_UP)
(void)lpfc_send_npiv_logo(vport, ndlp);
lpfc_sli_host_down(vport);
lpfc_cleanup_rpis(vport, 0);
lpfc_stop_vport_timers(vport);
lpfc_unreg_all_rpis(vport);
lpfc_unreg_default_rpis(vport);
/*
* Completion of unreg_vpi (lpfc_mbx_cmpl_unreg_vpi) does the
* scsi_host_put() to release the vport.
*/
lpfc_mbx_unreg_vpi(vport);
if (phba->sli_rev == LPFC_SLI_REV4)
set_bit(FC_VPORT_NEEDS_INIT_VPI, &vport->fc_flag);
lpfc_vport_set_state(vport, FC_VPORT_DISABLED);
lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
"1826 Vport Disabled.\n");
return VPORT_OK;
}
static int
enable_vport(struct fc_vport *fc_vport)
{
struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data;
struct lpfc_hba *phba = vport->phba;
struct lpfc_nodelist *ndlp = NULL;
if ((phba->link_state < LPFC_LINK_UP) ||
(phba->fc_topology == LPFC_TOPOLOGY_LOOP)) {
lpfc_vport_set_state(vport, FC_VPORT_LINKDOWN);
return VPORT_OK;
}
set_bit(FC_LOADING, &vport->load_flag);
if (test_bit(FC_VPORT_NEEDS_INIT_VPI, &vport->fc_flag)) {
lpfc_issue_init_vpi(vport);
goto out;
}
set_bit(FC_VPORT_NEEDS_REG_VPI, &vport->fc_flag);
/* Use the Physical nodes Fabric NDLP to determine if the link is
* up and ready to FDISC.
*/
ndlp = lpfc_findnode_did(phba->pport, Fabric_DID);
if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) {
lpfc_set_disctmo(vport);
lpfc_initial_fdisc(vport);
} else {
lpfc_vport_set_state(vport, FC_VPORT_NO_FABRIC_SUPP);
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0264 No NPIV Fabric support\n");
}
} else {
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
}
out:
lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
"1827 Vport Enabled.\n");
return VPORT_OK;
}
int
lpfc_vport_disable(struct fc_vport *fc_vport, bool disable)
{
if (disable)
return disable_vport(fc_vport);
else
return enable_vport(fc_vport);
}
int
lpfc_vport_delete(struct fc_vport *fc_vport)
{
struct lpfc_nodelist *ndlp = NULL;
struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba;
int rc;
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waitq);
if (vport->port_type == LPFC_PHYSICAL_PORT) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"1812 vport_delete failed: Cannot delete "
"physical host\n");
return VPORT_ERROR;
}
/* If the vport is a static vport fail the deletion. */
if ((vport->vport_flag & STATIC_VPORT) &&
!test_bit(FC_UNLOADING, &phba->pport->load_flag)) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"1837 vport_delete failed: Cannot delete "
"static vport.\n");
return VPORT_ERROR;
}
set_bit(FC_UNLOADING, &vport->load_flag);
/*
* If we are not unloading the driver then prevent the vport_delete
* from happening until after this vport's discovery is finished.
*/
if (!test_bit(FC_UNLOADING, &phba->pport->load_flag)) {
int check_count = 0;
while (check_count < ((phba->fc_ratov * 3) + 3) &&
vport->port_state > LPFC_VPORT_FAILED &&
vport->port_state < LPFC_VPORT_READY) {
check_count++;
msleep(1000);
}
if (vport->port_state > LPFC_VPORT_FAILED &&
vport->port_state < LPFC_VPORT_READY)
return -EAGAIN;
}
/*
* Take early refcount for outstanding I/O requests we schedule during
* delete processing for unreg_vpi. Always keep this before
* scsi_remove_host() as we can no longer obtain a reference through
* scsi_host_get() after scsi_remove_host as shost is set to SHOST_DEL.
*/
if (!scsi_host_get(shost))
return VPORT_INVAL;
lpfc_free_sysfs_attr(vport);
lpfc_debugfs_terminate(vport);
/* Send the DA_ID and Fabric LOGO to cleanup Nameserver entries. */
ndlp = lpfc_findnode_did(vport, Fabric_DID);
if (!ndlp)
goto skip_logo;
/* Send the DA_ID and Fabric LOGO to cleanup the NPIV fabric entries. */
if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE &&
phba->link_state >= LPFC_LINK_UP &&
phba->fc_topology != LPFC_TOPOLOGY_LOOP) {
if (vport->cfg_enable_da_id) {
/* Send DA_ID and wait for a completion. This is best
* effort. If the DA_ID fails, likely the fabric will
* "leak" NportIDs but at least the driver issued the
* command.
*/
ndlp = lpfc_findnode_did(vport, NameServer_DID);
if (!ndlp)
goto issue_logo;
spin_lock_irq(&ndlp->lock);
ndlp->da_id_waitq = &waitq;
spin_unlock_irq(&ndlp->lock);
set_bit(NLP_WAIT_FOR_DA_ID, &ndlp->save_flags);
rc = lpfc_ns_cmd(vport, SLI_CTNS_DA_ID, 0, 0);
if (!rc) {
wait_event_timeout(waitq,
!test_bit(NLP_WAIT_FOR_DA_ID,
&ndlp->save_flags),
secs_to_jiffies(phba->fc_ratov * 2));
}
lpfc_printf_vlog(vport, KERN_INFO, LOG_VPORT | LOG_ELS,
"1829 DA_ID issue status %d. "
"SFlag x%lx NState x%x, NFlag x%lx "
"Rpi x%x\n",
rc, ndlp->save_flags, ndlp->nlp_state,
ndlp->nlp_flag, ndlp->nlp_rpi);
/* Remove the waitq and save_flags. It no
* longer matters if the wake happened.
*/
spin_lock_irq(&ndlp->lock);
ndlp->da_id_waitq = NULL;
spin_unlock_irq(&ndlp->lock);
clear_bit(NLP_WAIT_FOR_DA_ID, &ndlp->save_flags);
}
issue_logo:
/*
* If the vpi is not registered, then a valid FDISC doesn't
* exist and there is no need for a ELS LOGO. Just cleanup
* the ndlp.
*/
if (!(vport->vpi_state & LPFC_VPI_REGISTERED))
goto skip_logo;
/* Issue a Fabric LOGO to cleanup fabric resources. */
ndlp = lpfc_findnode_did(vport, Fabric_DID);
if (!ndlp)
goto skip_logo;
rc = lpfc_send_npiv_logo(vport, ndlp);
if (rc)
goto skip_logo;
}
if (!test_bit(FC_UNLOADING, &phba->pport->load_flag))
lpfc_discovery_wait(vport);
skip_logo:
/* Remove FC host to break driver binding. */
fc_remove_host(shost);
scsi_remove_host(shost);
lpfc_cleanup(vport);
/* Remove scsi host now. The nodes are cleaned up. */
lpfc_sli_host_down(vport);
lpfc_stop_vport_timers(vport);
if (!test_bit(FC_UNLOADING, &phba->pport->load_flag)) {
lpfc_unreg_all_rpis(vport);
lpfc_unreg_default_rpis(vport);
/*
* Completion of unreg_vpi (lpfc_mbx_cmpl_unreg_vpi)
* does the scsi_host_put() to release the vport.
*/
if (!(vport->vpi_state & LPFC_VPI_REGISTERED) ||
lpfc_mbx_unreg_vpi(vport))
scsi_host_put(shost);
} else {
scsi_host_put(shost);
}
lpfc_free_vpi(phba, vport->vpi);
vport->work_port_events = 0;
spin_lock_irq(&phba->port_list_lock);
list_del_init(&vport->listentry);
spin_unlock_irq(&phba->port_list_lock);
lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
"1828 Vport Deleted.\n");
scsi_host_put(shost);
return VPORT_OK;
}
struct lpfc_vport **
lpfc_create_vport_work_array(struct lpfc_hba *phba)
{
struct lpfc_vport *port_iterator;
struct lpfc_vport **vports;
int index = 0;
vports = kzalloc_objs(struct lpfc_vport *, phba->max_vports + 1);
if (vports == NULL)
return NULL;
spin_lock_irq(&phba->port_list_lock);
list_for_each_entry(port_iterator, &phba->port_list, listentry) {
if (test_bit(FC_UNLOADING, &port_iterator->load_flag))
continue;
if (!scsi_host_get(lpfc_shost_from_vport(port_iterator))) {
lpfc_printf_vlog(port_iterator, KERN_ERR,
LOG_TRACE_EVENT,
"1801 Create vport work array FAILED: "
"cannot do scsi_host_get\n");
continue;
}
vports[index++] = port_iterator;
}
spin_unlock_irq(&phba->port_list_lock);
return vports;
}
void
lpfc_destroy_vport_work_array(struct lpfc_hba *phba, struct lpfc_vport **vports)
{
int i;
if (vports == NULL)
return;
for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++)
scsi_host_put(lpfc_shost_from_vport(vports[i]));
kfree(vports);
}
+118
View File
@@ -0,0 +1,118 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2006 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.broadcom.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of version 2 of the GNU General *
* Public License as published by the Free Software Foundation. *
* This program is distributed in the hope that it will be useful. *
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
* WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
* DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
* TO BE LEGALLY INVALID. See the GNU General Public License for *
* more details, a copy of which can be found in the file COPYING *
* included with this package. *
*******************************************************************/
#ifndef _H_LPFC_VPORT
#define _H_LPFC_VPORT
/* API version values (each will be an individual bit) */
#define VPORT_API_VERSION_1 0x01
/* Values returned via lpfc_vport_getinfo() */
struct vport_info {
uint32_t api_versions;
uint8_t linktype;
#define VPORT_TYPE_PHYSICAL 0
#define VPORT_TYPE_VIRTUAL 1
uint8_t state;
#define VPORT_STATE_OFFLINE 0
#define VPORT_STATE_ACTIVE 1
#define VPORT_STATE_FAILED 2
uint8_t fail_reason;
uint8_t prev_fail_reason;
#define VPORT_FAIL_UNKNOWN 0
#define VPORT_FAIL_LINKDOWN 1
#define VPORT_FAIL_FAB_UNSUPPORTED 2
#define VPORT_FAIL_FAB_NORESOURCES 3
#define VPORT_FAIL_FAB_LOGOUT 4
#define VPORT_FAIL_ADAP_NORESOURCES 5
uint8_t node_name[8]; /* WWNN */
uint8_t port_name[8]; /* WWPN */
struct Scsi_Host *shost;
/* Following values are valid only on physical links */
uint32_t vports_max;
uint32_t vports_inuse;
uint32_t rpi_max;
uint32_t rpi_inuse;
#define VPORT_CNT_INVALID 0xFFFFFFFF
};
/* data used in link creation */
struct vport_data {
uint32_t api_version;
uint32_t options;
#define VPORT_OPT_AUTORETRY 0x01
uint8_t node_name[8]; /* WWNN */
uint8_t port_name[8]; /* WWPN */
/*
* Upon successful creation, vport_shost will point to the new Scsi_Host
* structure for the new virtual link.
*/
struct Scsi_Host *vport_shost;
};
/* API function return codes */
#define VPORT_OK 0
#define VPORT_ERROR -1
#define VPORT_INVAL -2
#define VPORT_NOMEM -3
#define VPORT_NORESOURCES -4
int lpfc_vport_create(struct fc_vport *, bool);
int lpfc_vport_delete(struct fc_vport *);
int lpfc_vport_getinfo(struct Scsi_Host *, struct vport_info *);
int lpfc_vport_tgt_remove(struct Scsi_Host *, uint, uint);
struct lpfc_vport **lpfc_create_vport_work_array(struct lpfc_hba *);
void lpfc_destroy_vport_work_array(struct lpfc_hba *, struct lpfc_vport **);
int lpfc_alloc_vpi(struct lpfc_hba *phba);
/*
* queuecommand VPORT-specific return codes. Specified in the host byte code.
* Returned when the virtual link has failed or is not active.
*/
#define DID_VPORT_ERROR 0x0f
#define VPORT_INFO 0x1
#define VPORT_CREATE 0x2
#define VPORT_DELETE 0x4
struct vport_cmd_tag {
uint32_t cmd;
struct vport_data cdata;
struct vport_info cinfo;
void *vport;
int vport_num;
};
void lpfc_vport_set_state(struct lpfc_vport *vport,
enum fc_vport_state new_state);
#endif /* H_LPFC_VPORT */