qed: Add support for hardware offloaded FCoE.

This adds the backbone required for the various HW initalizations
which are necessary for the FCoE driver (qedf) for QLogic FastLinQ
4xxxx line of adapters - FW notification, resource initializations, etc.

Signed-off-by: Arun Easi <arun.easi@cavium.com>
Signed-off-by: Yuval Mintz <yuval.mintz@cavium.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Arun Easi
2017-02-15 06:28:22 -08:00
committed by David S. Miller
parent f787d1debf
commit 1e128c8129
25 changed files with 3211 additions and 19 deletions

View File

@@ -114,4 +114,7 @@ config QED_RDMA
config QED_ISCSI
bool
config QED_FCOE
bool
endif # NET_VENDOR_QLOGIC

View File

@@ -7,3 +7,4 @@ qed-$(CONFIG_QED_SRIOV) += qed_sriov.o qed_vf.o
qed-$(CONFIG_QED_LL2) += qed_ll2.o
qed-$(CONFIG_QED_RDMA) += qed_roce.o
qed-$(CONFIG_QED_ISCSI) += qed_iscsi.o qed_ooo.o
qed-$(CONFIG_QED_FCOE) += qed_fcoe.o

View File

@@ -60,6 +60,7 @@ extern const struct qed_common_ops qed_common_ops_pass;
#define QED_WFQ_UNIT 100
#define ISCSI_BDQ_ID(_port_id) (_port_id)
#define FCOE_BDQ_ID(_port_id) ((_port_id) + 2)
#define QED_WID_SIZE (1024)
#define QED_PF_DEMS_SIZE (4)
@@ -167,6 +168,7 @@ struct qed_tunn_update_params {
*/
enum qed_pci_personality {
QED_PCI_ETH,
QED_PCI_FCOE,
QED_PCI_ISCSI,
QED_PCI_ETH_ROCE,
QED_PCI_DEFAULT /* default in shmem */
@@ -204,6 +206,7 @@ enum QED_FEATURE {
QED_VF,
QED_RDMA_CNQ,
QED_VF_L2_QUE,
QED_FCOE_CQ,
QED_MAX_FEATURES,
};
@@ -221,6 +224,7 @@ enum QED_PORT_MODE {
enum qed_dev_cap {
QED_DEV_CAP_ETH,
QED_DEV_CAP_FCOE,
QED_DEV_CAP_ISCSI,
QED_DEV_CAP_ROCE,
};
@@ -255,6 +259,10 @@ struct qed_hw_info {
u32 part_num[4];
unsigned char hw_mac_addr[ETH_ALEN];
u64 node_wwn;
u64 port_wwn;
u16 num_fcoe_conns;
struct qed_igu_info *p_igu_info;
@@ -410,6 +418,7 @@ struct qed_hwfn {
struct qed_ooo_info *p_ooo_info;
struct qed_rdma_info *p_rdma_info;
struct qed_iscsi_info *p_iscsi_info;
struct qed_fcoe_info *p_fcoe_info;
struct qed_pf_params pf_params;
bool b_rdma_enabled_in_prs;
@@ -620,11 +629,13 @@ struct qed_dev {
u8 protocol;
#define IS_QED_ETH_IF(cdev) ((cdev)->protocol == QED_PROTOCOL_ETH)
#define IS_QED_FCOE_IF(cdev) ((cdev)->protocol == QED_PROTOCOL_FCOE)
/* Callbacks to protocol driver */
union {
struct qed_common_cb_ops *common;
struct qed_eth_cb_ops *eth;
struct qed_fcoe_cb_ops *fcoe;
struct qed_iscsi_cb_ops *iscsi;
} protocol_ops;
void *ops_cookie;

View File

@@ -90,12 +90,14 @@ union conn_context {
struct core_conn_context core_ctx;
struct eth_conn_context eth_ctx;
struct iscsi_conn_context iscsi_ctx;
struct fcoe_conn_context fcoe_ctx;
struct roce_conn_context roce_ctx;
};
/* TYPE-0 task context - iSCSI */
/* TYPE-0 task context - iSCSI, FCOE */
union type0_task_context {
struct iscsi_task_context iscsi_ctx;
struct fcoe_task_context fcoe_ctx;
};
/* TYPE-1 task context - ROCE */
@@ -240,15 +242,22 @@ struct qed_cxt_mngr {
static bool src_proto(enum protocol_type type)
{
return type == PROTOCOLID_ISCSI ||
type == PROTOCOLID_FCOE ||
type == PROTOCOLID_ROCE;
}
static bool tm_cid_proto(enum protocol_type type)
{
return type == PROTOCOLID_ISCSI ||
type == PROTOCOLID_FCOE ||
type == PROTOCOLID_ROCE;
}
static bool tm_tid_proto(enum protocol_type type)
{
return type == PROTOCOLID_FCOE;
}
/* counts the iids for the CDU/CDUC ILT client configuration */
struct qed_cdu_iids {
u32 pf_cids;
@@ -307,6 +316,22 @@ static void qed_cxt_tm_iids(struct qed_cxt_mngr *p_mngr,
iids->pf_cids += p_cfg->cid_count;
iids->per_vf_cids += p_cfg->cids_per_vf;
}
if (tm_tid_proto(i)) {
struct qed_tid_seg *segs = p_cfg->tid_seg;
/* for each segment there is at most one
* protocol for which count is not 0.
*/
for (j = 0; j < NUM_TASK_PF_SEGMENTS; j++)
iids->pf_tids[j] += segs[j].count;
/* The last array elelment is for the VFs. As for PF
* segments there can be only one protocol for
* which this value is not 0.
*/
iids->per_vf_tids += segs[NUM_TASK_PF_SEGMENTS].count;
}
}
iids->pf_cids = roundup(iids->pf_cids, TM_ALIGN);
@@ -1694,9 +1719,42 @@ static void qed_tm_init_pf(struct qed_hwfn *p_hwfn)
/* @@@TBD how to enable the scan for the VFs */
}
static void qed_prs_init_common(struct qed_hwfn *p_hwfn)
{
if ((p_hwfn->hw_info.personality == QED_PCI_FCOE) &&
p_hwfn->pf_params.fcoe_pf_params.is_target)
STORE_RT_REG(p_hwfn,
PRS_REG_SEARCH_RESP_INITIATOR_TYPE_RT_OFFSET, 0);
}
static void qed_prs_init_pf(struct qed_hwfn *p_hwfn)
{
struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr;
struct qed_conn_type_cfg *p_fcoe;
struct qed_tid_seg *p_tid;
p_fcoe = &p_mngr->conn_cfg[PROTOCOLID_FCOE];
/* If FCoE is active set the MAX OX_ID (tid) in the Parser */
if (!p_fcoe->cid_count)
return;
p_tid = &p_fcoe->tid_seg[QED_CXT_FCOE_TID_SEG];
if (p_hwfn->pf_params.fcoe_pf_params.is_target) {
STORE_RT_REG_AGG(p_hwfn,
PRS_REG_TASK_ID_MAX_TARGET_PF_RT_OFFSET,
p_tid->count);
} else {
STORE_RT_REG_AGG(p_hwfn,
PRS_REG_TASK_ID_MAX_INITIATOR_PF_RT_OFFSET,
p_tid->count);
}
}
void qed_cxt_hw_init_common(struct qed_hwfn *p_hwfn)
{
qed_cdu_init_common(p_hwfn);
qed_prs_init_common(p_hwfn);
}
void qed_cxt_hw_init_pf(struct qed_hwfn *p_hwfn)
@@ -1708,6 +1766,7 @@ void qed_cxt_hw_init_pf(struct qed_hwfn *p_hwfn)
qed_ilt_init_pf(p_hwfn);
qed_src_init_pf(p_hwfn);
qed_tm_init_pf(p_hwfn);
qed_prs_init_pf(p_hwfn);
}
int qed_cxt_acquire_cid(struct qed_hwfn *p_hwfn,
@@ -1885,6 +1944,27 @@ int qed_cxt_set_pf_params(struct qed_hwfn *p_hwfn)
p_params->num_cons, 1);
break;
}
case QED_PCI_FCOE:
{
struct qed_fcoe_pf_params *p_params;
p_params = &p_hwfn->pf_params.fcoe_pf_params;
if (p_params->num_cons && p_params->num_tasks) {
qed_cxt_set_proto_cid_count(p_hwfn,
PROTOCOLID_FCOE,
p_params->num_cons,
0);
qed_cxt_set_proto_tid_count(p_hwfn, PROTOCOLID_FCOE,
QED_CXT_FCOE_TID_SEG, 0,
p_params->num_tasks, true);
} else {
DP_INFO(p_hwfn->cdev,
"Fcoe personality used without setting params!\n");
}
break;
}
case QED_PCI_ISCSI:
{
struct qed_iscsi_pf_params *p_params;
@@ -1927,6 +2007,10 @@ int qed_cxt_get_tid_mem_info(struct qed_hwfn *p_hwfn,
/* Verify the personality */
switch (p_hwfn->hw_info.personality) {
case QED_PCI_FCOE:
proto = PROTOCOLID_FCOE;
seg = QED_CXT_FCOE_TID_SEG;
break;
case QED_PCI_ISCSI:
proto = PROTOCOLID_ISCSI;
seg = QED_CXT_ISCSI_TID_SEG;
@@ -2215,15 +2299,19 @@ int qed_cxt_get_task_ctx(struct qed_hwfn *p_hwfn,
{
struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr;
struct qed_ilt_client_cfg *p_cli;
struct qed_ilt_cli_blk *p_seg;
struct qed_tid_seg *p_seg_info;
u32 proto, seg;
u32 total_lines;
u32 tid_size, ilt_idx;
struct qed_ilt_cli_blk *p_seg;
u32 num_tids_per_block;
u32 tid_size, ilt_idx;
u32 total_lines;
u32 proto, seg;
/* Verify the personality */
switch (p_hwfn->hw_info.personality) {
case QED_PCI_FCOE:
proto = PROTOCOLID_FCOE;
seg = QED_CXT_FCOE_TID_SEG;
break;
case QED_PCI_ISCSI:
proto = PROTOCOLID_ISCSI;
seg = QED_CXT_ISCSI_TID_SEG;

View File

@@ -91,6 +91,7 @@ int qed_cxt_get_tid_mem_info(struct qed_hwfn *p_hwfn,
#define QED_CXT_ISCSI_TID_SEG PROTOCOLID_ISCSI
#define QED_CXT_ROCE_TID_SEG PROTOCOLID_ROCE
#define QED_CXT_FCOE_TID_SEG PROTOCOLID_FCOE
enum qed_cxt_elem_type {
QED_ELEM_CXT,
QED_ELEM_SRQ,
@@ -204,4 +205,6 @@ int qed_cxt_free_proto_ilt(struct qed_hwfn *p_hwfn, enum protocol_type proto);
#define QED_CTX_WORKING_MEM 0
#define QED_CTX_FL_MEM 1
int qed_cxt_get_task_ctx(struct qed_hwfn *p_hwfn,
u32 tid, u8 ctx_type, void **task_ctx);
#endif

View File

@@ -432,7 +432,6 @@ qed_dcbx_copy_mib(struct qed_hwfn *p_hwfn,
return rc;
}
#ifdef CONFIG_DCB
static void
qed_dcbx_get_priority_info(struct qed_hwfn *p_hwfn,
struct qed_dcbx_app_prio *p_prio,
@@ -749,7 +748,6 @@ qed_dcbx_get_params(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
return 0;
}
#endif
static int
qed_dcbx_read_local_lldp_mib(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
@@ -864,6 +862,15 @@ static int qed_dcbx_read_mib(struct qed_hwfn *p_hwfn,
return rc;
}
void qed_dcbx_aen(struct qed_hwfn *hwfn, u32 mib_type)
{
struct qed_common_cb_ops *op = hwfn->cdev->protocol_ops.common;
void *cookie = hwfn->cdev->ops_cookie;
if (cookie && op->dcbx_aen)
op->dcbx_aen(cookie, &hwfn->p_dcbx_info->get, mib_type);
}
/* Read updated MIB.
* Reconfigure QM and invoke PF update ramrod command if operational MIB
* change is detected.
@@ -890,6 +897,8 @@ qed_dcbx_mib_update_event(struct qed_hwfn *p_hwfn,
qed_sp_pf_update(p_hwfn);
}
}
qed_dcbx_get_params(p_hwfn, p_ptt, &p_hwfn->p_dcbx_info->get, type);
qed_dcbx_aen(p_hwfn, type);
return rc;
}

View File

@@ -57,7 +57,6 @@ struct qed_dcbx_app_data {
u8 tc; /* Traffic Class */
};
#ifdef CONFIG_DCB
#define QED_DCBX_VERSION_DISABLED 0
#define QED_DCBX_VERSION_IEEE 1
#define QED_DCBX_VERSION_CEE 2
@@ -73,7 +72,6 @@ struct qed_dcbx_set {
struct qed_dcbx_admin_params config;
u32 ver_num;
};
#endif
struct qed_dcbx_results {
bool dcbx_enabled;
@@ -97,9 +95,8 @@ struct qed_dcbx_info {
struct qed_dcbx_results results;
struct dcbx_mib operational;
struct dcbx_mib remote;
#ifdef CONFIG_DCB
struct qed_dcbx_set set;
#endif
struct qed_dcbx_get get;
u8 dcbx_cap;
};

View File

@@ -49,6 +49,7 @@
#include "qed_cxt.h"
#include "qed_dcbx.h"
#include "qed_dev_api.h"
#include "qed_fcoe.h"
#include "qed_hsi.h"
#include "qed_hw.h"
#include "qed_init_ops.h"
@@ -172,6 +173,9 @@ void qed_resc_free(struct qed_dev *cdev)
#ifdef CONFIG_QED_LL2
qed_ll2_free(p_hwfn, p_hwfn->p_ll2_info);
#endif
if (p_hwfn->hw_info.personality == QED_PCI_FCOE)
qed_fcoe_free(p_hwfn, p_hwfn->p_fcoe_info);
if (p_hwfn->hw_info.personality == QED_PCI_ISCSI) {
qed_iscsi_free(p_hwfn, p_hwfn->p_iscsi_info);
qed_ooo_free(p_hwfn, p_hwfn->p_ooo_info);
@@ -433,6 +437,7 @@ int qed_qm_reconf(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
int qed_resc_alloc(struct qed_dev *cdev)
{
struct qed_iscsi_info *p_iscsi_info;
struct qed_fcoe_info *p_fcoe_info;
struct qed_ooo_info *p_ooo_info;
#ifdef CONFIG_QED_LL2
struct qed_ll2_info *p_ll2_info;
@@ -539,6 +544,14 @@ int qed_resc_alloc(struct qed_dev *cdev)
p_hwfn->p_ll2_info = p_ll2_info;
}
#endif
if (p_hwfn->hw_info.personality == QED_PCI_FCOE) {
p_fcoe_info = qed_fcoe_alloc(p_hwfn);
if (!p_fcoe_info)
goto alloc_no_mem;
p_hwfn->p_fcoe_info = p_fcoe_info;
}
if (p_hwfn->hw_info.personality == QED_PCI_ISCSI) {
p_iscsi_info = qed_iscsi_alloc(p_hwfn);
if (!p_iscsi_info)
@@ -602,6 +615,9 @@ void qed_resc_setup(struct qed_dev *cdev)
if (p_hwfn->using_ll2)
qed_ll2_setup(p_hwfn, p_hwfn->p_ll2_info);
#endif
if (p_hwfn->hw_info.personality == QED_PCI_FCOE)
qed_fcoe_setup(p_hwfn, p_hwfn->p_fcoe_info);
if (p_hwfn->hw_info.personality == QED_PCI_ISCSI) {
qed_iscsi_setup(p_hwfn, p_hwfn->p_iscsi_info);
qed_ooo_setup(p_hwfn, p_hwfn->p_ooo_info);
@@ -994,7 +1010,8 @@ static int qed_hw_init_pf(struct qed_hwfn *p_hwfn,
/* Protocl Configuration */
STORE_RT_REG(p_hwfn, PRS_REG_SEARCH_TCP_RT_OFFSET,
(p_hwfn->hw_info.personality == QED_PCI_ISCSI) ? 1 : 0);
STORE_RT_REG(p_hwfn, PRS_REG_SEARCH_FCOE_RT_OFFSET, 0);
STORE_RT_REG(p_hwfn, PRS_REG_SEARCH_FCOE_RT_OFFSET,
(p_hwfn->hw_info.personality == QED_PCI_FCOE) ? 1 : 0);
STORE_RT_REG(p_hwfn, PRS_REG_SEARCH_ROCE_RT_OFFSET, 0);
/* Cleanup chip from previous driver if such remains exist */
@@ -1026,8 +1043,16 @@ static int qed_hw_init_pf(struct qed_hwfn *p_hwfn,
/* send function start command */
rc = qed_sp_pf_start(p_hwfn, p_tunn, p_hwfn->cdev->mf_mode,
allow_npar_tx_switch);
if (rc)
if (rc) {
DP_NOTICE(p_hwfn, "Function start ramrod failed\n");
return rc;
}
if (p_hwfn->hw_info.personality == QED_PCI_FCOE) {
qed_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_TAG1, BIT(2));
qed_wr(p_hwfn, p_ptt,
PRS_REG_PKT_LEN_STAT_TAGS_NOT_COUNTED_FIRST,
0x100);
}
}
return rc;
}
@@ -1787,8 +1812,8 @@ static int qed_hw_get_resc(struct qed_hwfn *p_hwfn)
static int qed_hw_get_nvm_info(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
{
u32 nvm_cfg1_offset, mf_mode, addr, generic_cont0, core_cfg;
u32 port_cfg_addr, link_temp, nvm_cfg_addr, device_capabilities;
u32 nvm_cfg1_offset, mf_mode, addr, generic_cont0, core_cfg;
struct qed_mcp_link_params *link;
/* Read global nvm_cfg address */
@@ -1934,6 +1959,9 @@ static int qed_hw_get_nvm_info(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
if (device_capabilities & NVM_CFG1_GLOB_DEVICE_CAPABILITIES_ETHERNET)
__set_bit(QED_DEV_CAP_ETH,
&p_hwfn->hw_info.device_capabilities);
if (device_capabilities & NVM_CFG1_GLOB_DEVICE_CAPABILITIES_FCOE)
__set_bit(QED_DEV_CAP_FCOE,
&p_hwfn->hw_info.device_capabilities);
if (device_capabilities & NVM_CFG1_GLOB_DEVICE_CAPABILITIES_ISCSI)
__set_bit(QED_DEV_CAP_ISCSI,
&p_hwfn->hw_info.device_capabilities);
@@ -2671,6 +2699,177 @@ void qed_llh_remove_mac_filter(struct qed_hwfn *p_hwfn,
DP_NOTICE(p_hwfn, "Tried to remove a non-configured filter\n");
}
int
qed_llh_add_protocol_filter(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt,
u16 source_port_or_eth_type,
u16 dest_port, enum qed_llh_port_filter_type_t type)
{
u32 high = 0, low = 0, en;
int i;
if (!(IS_MF_SI(p_hwfn) || IS_MF_DEFAULT(p_hwfn)))
return 0;
switch (type) {
case QED_LLH_FILTER_ETHERTYPE:
high = source_port_or_eth_type;
break;
case QED_LLH_FILTER_TCP_SRC_PORT:
case QED_LLH_FILTER_UDP_SRC_PORT:
low = source_port_or_eth_type << 16;
break;
case QED_LLH_FILTER_TCP_DEST_PORT:
case QED_LLH_FILTER_UDP_DEST_PORT:
low = dest_port;
break;
case QED_LLH_FILTER_TCP_SRC_AND_DEST_PORT:
case QED_LLH_FILTER_UDP_SRC_AND_DEST_PORT:
low = (source_port_or_eth_type << 16) | dest_port;
break;
default:
DP_NOTICE(p_hwfn,
"Non valid LLH protocol filter type %d\n", type);
return -EINVAL;
}
/* Find a free entry and utilize it */
for (i = 0; i < NIG_REG_LLH_FUNC_FILTER_EN_SIZE; i++) {
en = qed_rd(p_hwfn, p_ptt,
NIG_REG_LLH_FUNC_FILTER_EN + i * sizeof(u32));
if (en)
continue;
qed_wr(p_hwfn, p_ptt,
NIG_REG_LLH_FUNC_FILTER_VALUE +
2 * i * sizeof(u32), low);
qed_wr(p_hwfn, p_ptt,
NIG_REG_LLH_FUNC_FILTER_VALUE +
(2 * i + 1) * sizeof(u32), high);
qed_wr(p_hwfn, p_ptt,
NIG_REG_LLH_FUNC_FILTER_MODE + i * sizeof(u32), 1);
qed_wr(p_hwfn, p_ptt,
NIG_REG_LLH_FUNC_FILTER_PROTOCOL_TYPE +
i * sizeof(u32), 1 << type);
qed_wr(p_hwfn, p_ptt,
NIG_REG_LLH_FUNC_FILTER_EN + i * sizeof(u32), 1);
break;
}
if (i >= NIG_REG_LLH_FUNC_FILTER_EN_SIZE) {
DP_NOTICE(p_hwfn,
"Failed to find an empty LLH filter to utilize\n");
return -EINVAL;
}
switch (type) {
case QED_LLH_FILTER_ETHERTYPE:
DP_VERBOSE(p_hwfn, NETIF_MSG_HW,
"ETH type %x is added at %d\n",
source_port_or_eth_type, i);
break;
case QED_LLH_FILTER_TCP_SRC_PORT:
DP_VERBOSE(p_hwfn, NETIF_MSG_HW,
"TCP src port %x is added at %d\n",
source_port_or_eth_type, i);
break;
case QED_LLH_FILTER_UDP_SRC_PORT:
DP_VERBOSE(p_hwfn, NETIF_MSG_HW,
"UDP src port %x is added at %d\n",
source_port_or_eth_type, i);
break;
case QED_LLH_FILTER_TCP_DEST_PORT:
DP_VERBOSE(p_hwfn, NETIF_MSG_HW,
"TCP dst port %x is added at %d\n", dest_port, i);
break;
case QED_LLH_FILTER_UDP_DEST_PORT:
DP_VERBOSE(p_hwfn, NETIF_MSG_HW,
"UDP dst port %x is added at %d\n", dest_port, i);
break;
case QED_LLH_FILTER_TCP_SRC_AND_DEST_PORT:
DP_VERBOSE(p_hwfn, NETIF_MSG_HW,
"TCP src/dst ports %x/%x are added at %d\n",
source_port_or_eth_type, dest_port, i);
break;
case QED_LLH_FILTER_UDP_SRC_AND_DEST_PORT:
DP_VERBOSE(p_hwfn, NETIF_MSG_HW,
"UDP src/dst ports %x/%x are added at %d\n",
source_port_or_eth_type, dest_port, i);
break;
}
return 0;
}
void
qed_llh_remove_protocol_filter(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt,
u16 source_port_or_eth_type,
u16 dest_port,
enum qed_llh_port_filter_type_t type)
{
u32 high = 0, low = 0;
int i;
if (!(IS_MF_SI(p_hwfn) || IS_MF_DEFAULT(p_hwfn)))
return;
switch (type) {
case QED_LLH_FILTER_ETHERTYPE:
high = source_port_or_eth_type;
break;
case QED_LLH_FILTER_TCP_SRC_PORT:
case QED_LLH_FILTER_UDP_SRC_PORT:
low = source_port_or_eth_type << 16;
break;
case QED_LLH_FILTER_TCP_DEST_PORT:
case QED_LLH_FILTER_UDP_DEST_PORT:
low = dest_port;
break;
case QED_LLH_FILTER_TCP_SRC_AND_DEST_PORT:
case QED_LLH_FILTER_UDP_SRC_AND_DEST_PORT:
low = (source_port_or_eth_type << 16) | dest_port;
break;
default:
DP_NOTICE(p_hwfn,
"Non valid LLH protocol filter type %d\n", type);
return;
}
for (i = 0; i < NIG_REG_LLH_FUNC_FILTER_EN_SIZE; i++) {
if (!qed_rd(p_hwfn, p_ptt,
NIG_REG_LLH_FUNC_FILTER_EN + i * sizeof(u32)))
continue;
if (!qed_rd(p_hwfn, p_ptt,
NIG_REG_LLH_FUNC_FILTER_MODE + i * sizeof(u32)))
continue;
if (!(qed_rd(p_hwfn, p_ptt,
NIG_REG_LLH_FUNC_FILTER_PROTOCOL_TYPE +
i * sizeof(u32)) & BIT(type)))
continue;
if (qed_rd(p_hwfn, p_ptt,
NIG_REG_LLH_FUNC_FILTER_VALUE +
2 * i * sizeof(u32)) != low)
continue;
if (qed_rd(p_hwfn, p_ptt,
NIG_REG_LLH_FUNC_FILTER_VALUE +
(2 * i + 1) * sizeof(u32)) != high)
continue;
qed_wr(p_hwfn, p_ptt,
NIG_REG_LLH_FUNC_FILTER_EN + i * sizeof(u32), 0);
qed_wr(p_hwfn, p_ptt,
NIG_REG_LLH_FUNC_FILTER_MODE + i * sizeof(u32), 0);
qed_wr(p_hwfn, p_ptt,
NIG_REG_LLH_FUNC_FILTER_PROTOCOL_TYPE +
i * sizeof(u32), 0);
qed_wr(p_hwfn, p_ptt,
NIG_REG_LLH_FUNC_FILTER_VALUE + 2 * i * sizeof(u32), 0);
qed_wr(p_hwfn, p_ptt,
NIG_REG_LLH_FUNC_FILTER_VALUE +
(2 * i + 1) * sizeof(u32), 0);
break;
}
if (i >= NIG_REG_LLH_FUNC_FILTER_EN_SIZE)
DP_NOTICE(p_hwfn, "Tried to remove a non-configured filter\n");
}
static int qed_set_coalesce(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
u32 hw_addr, void *p_eth_qzone,
size_t eth_qzone_size, u8 timeset)

View File

@@ -353,6 +353,48 @@ int qed_llh_add_mac_filter(struct qed_hwfn *p_hwfn,
void qed_llh_remove_mac_filter(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt, u8 *p_filter);
enum qed_llh_port_filter_type_t {
QED_LLH_FILTER_ETHERTYPE,
QED_LLH_FILTER_TCP_SRC_PORT,
QED_LLH_FILTER_TCP_DEST_PORT,
QED_LLH_FILTER_TCP_SRC_AND_DEST_PORT,
QED_LLH_FILTER_UDP_SRC_PORT,
QED_LLH_FILTER_UDP_DEST_PORT,
QED_LLH_FILTER_UDP_SRC_AND_DEST_PORT
};
/**
* @brief qed_llh_add_protocol_filter - configures a protocol filter in llh
*
* @param p_hwfn
* @param p_ptt
* @param source_port_or_eth_type - source port or ethertype to add
* @param dest_port - destination port to add
* @param type - type of filters and comparing
*/
int
qed_llh_add_protocol_filter(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt,
u16 source_port_or_eth_type,
u16 dest_port,
enum qed_llh_port_filter_type_t type);
/**
* @brief qed_llh_remove_protocol_filter - remove a protocol filter in llh
*
* @param p_hwfn
* @param p_ptt
* @param source_port_or_eth_type - source port or ethertype to add
* @param dest_port - destination port to add
* @param type - type of filters and comparing
*/
void
qed_llh_remove_protocol_filter(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt,
u16 source_port_or_eth_type,
u16 dest_port,
enum qed_llh_port_filter_type_t type);
/**
* *@brief Cleanup of previous driver remains prior to load
*

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,87 @@
/* QLogic qed NIC Driver
* Copyright (c) 2015-2017 QLogic Corporation
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and /or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef _QED_FCOE_H
#define _QED_FCOE_H
#include <linux/types.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/qed/qed_fcoe_if.h>
#include <linux/qed/qed_chain.h>
#include "qed.h"
#include "qed_hsi.h"
#include "qed_mcp.h"
#include "qed_sp.h"
struct qed_fcoe_info {
spinlock_t lock; /* Connection resources. */
struct list_head free_list;
};
#if IS_ENABLED(CONFIG_QED_FCOE)
struct qed_fcoe_info *qed_fcoe_alloc(struct qed_hwfn *p_hwfn);
void qed_fcoe_setup(struct qed_hwfn *p_hwfn, struct qed_fcoe_info *p_fcoe_info);
void qed_fcoe_free(struct qed_hwfn *p_hwfn, struct qed_fcoe_info *p_fcoe_info);
void qed_get_protocol_stats_fcoe(struct qed_dev *cdev,
struct qed_mcp_fcoe_stats *stats);
#else /* CONFIG_QED_FCOE */
static inline struct qed_fcoe_info *
qed_fcoe_alloc(struct qed_hwfn *p_hwfn)
{
return NULL;
}
static inline void qed_fcoe_setup(struct qed_hwfn *p_hwfn,
struct qed_fcoe_info *p_fcoe_info)
{
}
static inline void qed_fcoe_free(struct qed_hwfn *p_hwfn,
struct qed_fcoe_info *p_fcoe_info)
{
}
static inline void qed_get_protocol_stats_fcoe(struct qed_dev *cdev,
struct qed_mcp_fcoe_stats *stats)
{
}
#endif /* CONFIG_QED_FCOE */
#ifdef CONFIG_QED_LL2
extern const struct qed_common_ops qed_common_ops_pass;
extern const struct qed_ll2_ops qed_ll2_ops_pass;
#endif
#endif /* _QED_FCOE_H */

File diff suppressed because it is too large Load Diff

View File

@@ -841,6 +841,9 @@ u16 qed_get_qm_pq(struct qed_hwfn *p_hwfn,
if (pq_id > p_hwfn->qm_info.num_pf_rls)
pq_id = p_hwfn->qm_info.offload_pq;
break;
case PROTOCOLID_FCOE:
pq_id = p_hwfn->qm_info.offload_pq;
break;
default:
pq_id = 0;
}

View File

@@ -1130,6 +1130,9 @@ static int qed_sp_ll2_tx_queue_start(struct qed_hwfn *p_hwfn,
p_ramrod->qm_pq_id = cpu_to_le16(pq_id);
switch (conn_type) {
case QED_LL2_TYPE_FCOE:
p_ramrod->conn_type = PROTOCOLID_FCOE;
break;
case QED_LL2_TYPE_ISCSI:
case QED_LL2_TYPE_ISCSI_OOO:
p_ramrod->conn_type = PROTOCOLID_ISCSI;
@@ -1458,6 +1461,15 @@ int qed_ll2_establish_connection(struct qed_hwfn *p_hwfn, u8 connection_handle)
qed_ll2_establish_connection_ooo(p_hwfn, p_ll2_conn);
if (p_ll2_conn->conn.conn_type == QED_LL2_TYPE_FCOE) {
qed_llh_add_protocol_filter(p_hwfn, p_hwfn->p_main_ptt,
0x8906, 0,
QED_LLH_FILTER_ETHERTYPE);
qed_llh_add_protocol_filter(p_hwfn, p_hwfn->p_main_ptt,
0x8914, 0,
QED_LLH_FILTER_ETHERTYPE);
}
return rc;
}
@@ -1831,6 +1843,15 @@ int qed_ll2_terminate_connection(struct qed_hwfn *p_hwfn, u8 connection_handle)
if (p_ll2_conn->conn.conn_type == QED_LL2_TYPE_ISCSI_OOO)
qed_ooo_release_all_isles(p_hwfn, p_hwfn->p_ooo_info);
if (p_ll2_conn->conn.conn_type == QED_LL2_TYPE_FCOE) {
qed_llh_remove_protocol_filter(p_hwfn, p_hwfn->p_main_ptt,
0x8906, 0,
QED_LLH_FILTER_ETHERTYPE);
qed_llh_remove_protocol_filter(p_hwfn, p_hwfn->p_main_ptt,
0x8914, 0,
QED_LLH_FILTER_ETHERTYPE);
}
return rc;
}
@@ -2039,6 +2060,10 @@ static int qed_ll2_start(struct qed_dev *cdev, struct qed_ll2_params *params)
}
switch (QED_LEADING_HWFN(cdev)->hw_info.personality) {
case QED_PCI_FCOE:
conn_type = QED_LL2_TYPE_FCOE;
gsi_enable = 0;
break;
case QED_PCI_ISCSI:
conn_type = QED_LL2_TYPE_ISCSI;
gsi_enable = 0;

View File

@@ -54,7 +54,7 @@ enum qed_ll2_roce_flavor_type {
};
enum qed_ll2_conn_type {
QED_LL2_TYPE_RESERVED,
QED_LL2_TYPE_FCOE,
QED_LL2_TYPE_ISCSI,
QED_LL2_TYPE_TEST,
QED_LL2_TYPE_ISCSI_OOO,

View File

@@ -53,9 +53,11 @@
#include "qed_sp.h"
#include "qed_dev_api.h"
#include "qed_ll2.h"
#include "qed_fcoe.h"
#include "qed_mcp.h"
#include "qed_hw.h"
#include "qed_selftest.h"
#include "qed_debug.h"
#define QED_ROCE_QPS (8192)
#define QED_ROCE_DPIS (8)
@@ -1603,6 +1605,8 @@ const struct qed_common_ops qed_common_ops_pass = {
.sb_release = &qed_sb_release,
.simd_handler_config = &qed_simd_handler_config,
.simd_handler_clean = &qed_simd_handler_clean,
.dbg_grc = &qed_dbg_grc,
.dbg_grc_size = &qed_dbg_grc_size,
.can_link_change = &qed_can_link_change,
.set_link = &qed_set_link,
.get_link = &qed_get_current_link,
@@ -1636,6 +1640,9 @@ void qed_get_protocol_stats(struct qed_dev *cdev,
stats->lan_stats.ucast_tx_pkts = eth_stats.tx_ucast_pkts;
stats->lan_stats.fcs_err = -1;
break;
case QED_MCP_FCOE_STATS:
qed_get_protocol_stats_fcoe(cdev, &stats->fcoe_stats);
break;
default:
DP_ERR(cdev, "Invalid protocol type = %d\n", type);
return;

View File

@@ -1130,6 +1130,9 @@ qed_mcp_get_shmem_proto(struct qed_hwfn *p_hwfn,
case FUNC_MF_CFG_PROTOCOL_ISCSI:
*p_proto = QED_PCI_ISCSI;
break;
case FUNC_MF_CFG_PROTOCOL_FCOE:
*p_proto = QED_PCI_FCOE;
break;
case FUNC_MF_CFG_PROTOCOL_ROCE:
DP_NOTICE(p_hwfn, "RoCE personality is not a valid value!\n");
/* Fallthrough */

View File

@@ -37,6 +37,7 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/qed/qed_fcoe_if.h>
#include "qed_hsi.h"
struct qed_mcp_link_speed_params {

View File

@@ -110,6 +110,8 @@
0x1e80000UL
#define NIG_REG_RX_LLH_BRB_GATE_DNTFWD_PERPF \
0x5011f4UL
#define PRS_REG_SEARCH_RESP_INITIATOR_TYPE \
0x1f0164UL
#define PRS_REG_SEARCH_TCP \
0x1f0400UL
#define PRS_REG_SEARCH_UDP \
@@ -120,6 +122,12 @@
0x1f040cUL
#define PRS_REG_SEARCH_OPENFLOW \
0x1f0434UL
#define PRS_REG_SEARCH_TAG1 \
0x1f0444UL
#define PRS_REG_PKT_LEN_STAT_TAGS_NOT_COUNTED_FIRST \
0x1f0a0cUL
#define PRS_REG_SEARCH_TCP_FIRST_FRAG \
0x1f0410UL
#define TM_REG_PF_ENABLE_CONN \
0x2c043cUL
#define TM_REG_PF_ENABLE_TASK \

View File

@@ -109,6 +109,10 @@ union ramrod_data {
struct rdma_srq_destroy_ramrod_data rdma_destroy_srq;
struct rdma_srq_modify_ramrod_data rdma_modify_srq;
struct roce_init_func_ramrod_data roce_init_func;
struct fcoe_init_ramrod_params fcoe_init;
struct fcoe_conn_offload_ramrod_params fcoe_conn_ofld;
struct fcoe_conn_terminate_ramrod_params fcoe_conn_terminate;
struct fcoe_stat_ramrod_params fcoe_stat;
struct iscsi_slow_path_hdr iscsi_empty;
struct iscsi_init_ramrod_params iscsi_init;

Some files were not shown because too many files have changed in this diff Show More