Commit 1e128c81 authored by Arun Easi's avatar Arun Easi Committed by David S. Miller

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: default avatarArun Easi <arun.easi@cavium.com>
Signed-off-by: default avatarYuval Mintz <yuval.mintz@cavium.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f787d1de
...@@ -114,4 +114,7 @@ config QED_RDMA ...@@ -114,4 +114,7 @@ config QED_RDMA
config QED_ISCSI config QED_ISCSI
bool bool
config QED_FCOE
bool
endif # NET_VENDOR_QLOGIC endif # NET_VENDOR_QLOGIC
...@@ -7,3 +7,4 @@ qed-$(CONFIG_QED_SRIOV) += qed_sriov.o qed_vf.o ...@@ -7,3 +7,4 @@ qed-$(CONFIG_QED_SRIOV) += qed_sriov.o qed_vf.o
qed-$(CONFIG_QED_LL2) += qed_ll2.o qed-$(CONFIG_QED_LL2) += qed_ll2.o
qed-$(CONFIG_QED_RDMA) += qed_roce.o qed-$(CONFIG_QED_RDMA) += qed_roce.o
qed-$(CONFIG_QED_ISCSI) += qed_iscsi.o qed_ooo.o qed-$(CONFIG_QED_ISCSI) += qed_iscsi.o qed_ooo.o
qed-$(CONFIG_QED_FCOE) += qed_fcoe.o
...@@ -60,6 +60,7 @@ extern const struct qed_common_ops qed_common_ops_pass; ...@@ -60,6 +60,7 @@ extern const struct qed_common_ops qed_common_ops_pass;
#define QED_WFQ_UNIT 100 #define QED_WFQ_UNIT 100
#define ISCSI_BDQ_ID(_port_id) (_port_id) #define ISCSI_BDQ_ID(_port_id) (_port_id)
#define FCOE_BDQ_ID(_port_id) ((_port_id) + 2)
#define QED_WID_SIZE (1024) #define QED_WID_SIZE (1024)
#define QED_PF_DEMS_SIZE (4) #define QED_PF_DEMS_SIZE (4)
...@@ -167,6 +168,7 @@ struct qed_tunn_update_params { ...@@ -167,6 +168,7 @@ struct qed_tunn_update_params {
*/ */
enum qed_pci_personality { enum qed_pci_personality {
QED_PCI_ETH, QED_PCI_ETH,
QED_PCI_FCOE,
QED_PCI_ISCSI, QED_PCI_ISCSI,
QED_PCI_ETH_ROCE, QED_PCI_ETH_ROCE,
QED_PCI_DEFAULT /* default in shmem */ QED_PCI_DEFAULT /* default in shmem */
...@@ -204,6 +206,7 @@ enum QED_FEATURE { ...@@ -204,6 +206,7 @@ enum QED_FEATURE {
QED_VF, QED_VF,
QED_RDMA_CNQ, QED_RDMA_CNQ,
QED_VF_L2_QUE, QED_VF_L2_QUE,
QED_FCOE_CQ,
QED_MAX_FEATURES, QED_MAX_FEATURES,
}; };
...@@ -221,6 +224,7 @@ enum QED_PORT_MODE { ...@@ -221,6 +224,7 @@ enum QED_PORT_MODE {
enum qed_dev_cap { enum qed_dev_cap {
QED_DEV_CAP_ETH, QED_DEV_CAP_ETH,
QED_DEV_CAP_FCOE,
QED_DEV_CAP_ISCSI, QED_DEV_CAP_ISCSI,
QED_DEV_CAP_ROCE, QED_DEV_CAP_ROCE,
}; };
...@@ -255,6 +259,10 @@ struct qed_hw_info { ...@@ -255,6 +259,10 @@ struct qed_hw_info {
u32 part_num[4]; u32 part_num[4];
unsigned char hw_mac_addr[ETH_ALEN]; unsigned char hw_mac_addr[ETH_ALEN];
u64 node_wwn;
u64 port_wwn;
u16 num_fcoe_conns;
struct qed_igu_info *p_igu_info; struct qed_igu_info *p_igu_info;
...@@ -410,6 +418,7 @@ struct qed_hwfn { ...@@ -410,6 +418,7 @@ struct qed_hwfn {
struct qed_ooo_info *p_ooo_info; struct qed_ooo_info *p_ooo_info;
struct qed_rdma_info *p_rdma_info; struct qed_rdma_info *p_rdma_info;
struct qed_iscsi_info *p_iscsi_info; struct qed_iscsi_info *p_iscsi_info;
struct qed_fcoe_info *p_fcoe_info;
struct qed_pf_params pf_params; struct qed_pf_params pf_params;
bool b_rdma_enabled_in_prs; bool b_rdma_enabled_in_prs;
...@@ -620,11 +629,13 @@ struct qed_dev { ...@@ -620,11 +629,13 @@ struct qed_dev {
u8 protocol; u8 protocol;
#define IS_QED_ETH_IF(cdev) ((cdev)->protocol == QED_PROTOCOL_ETH) #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 */ /* Callbacks to protocol driver */
union { union {
struct qed_common_cb_ops *common; struct qed_common_cb_ops *common;
struct qed_eth_cb_ops *eth; struct qed_eth_cb_ops *eth;
struct qed_fcoe_cb_ops *fcoe;
struct qed_iscsi_cb_ops *iscsi; struct qed_iscsi_cb_ops *iscsi;
} protocol_ops; } protocol_ops;
void *ops_cookie; void *ops_cookie;
......
...@@ -90,12 +90,14 @@ union conn_context { ...@@ -90,12 +90,14 @@ union conn_context {
struct core_conn_context core_ctx; struct core_conn_context core_ctx;
struct eth_conn_context eth_ctx; struct eth_conn_context eth_ctx;
struct iscsi_conn_context iscsi_ctx; struct iscsi_conn_context iscsi_ctx;
struct fcoe_conn_context fcoe_ctx;
struct roce_conn_context roce_ctx; struct roce_conn_context roce_ctx;
}; };
/* TYPE-0 task context - iSCSI */ /* TYPE-0 task context - iSCSI, FCOE */
union type0_task_context { union type0_task_context {
struct iscsi_task_context iscsi_ctx; struct iscsi_task_context iscsi_ctx;
struct fcoe_task_context fcoe_ctx;
}; };
/* TYPE-1 task context - ROCE */ /* TYPE-1 task context - ROCE */
...@@ -240,15 +242,22 @@ struct qed_cxt_mngr { ...@@ -240,15 +242,22 @@ struct qed_cxt_mngr {
static bool src_proto(enum protocol_type type) static bool src_proto(enum protocol_type type)
{ {
return type == PROTOCOLID_ISCSI || return type == PROTOCOLID_ISCSI ||
type == PROTOCOLID_FCOE ||
type == PROTOCOLID_ROCE; type == PROTOCOLID_ROCE;
} }
static bool tm_cid_proto(enum protocol_type type) static bool tm_cid_proto(enum protocol_type type)
{ {
return type == PROTOCOLID_ISCSI || return type == PROTOCOLID_ISCSI ||
type == PROTOCOLID_FCOE ||
type == PROTOCOLID_ROCE; 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 */ /* counts the iids for the CDU/CDUC ILT client configuration */
struct qed_cdu_iids { struct qed_cdu_iids {
u32 pf_cids; u32 pf_cids;
...@@ -307,6 +316,22 @@ static void qed_cxt_tm_iids(struct qed_cxt_mngr *p_mngr, ...@@ -307,6 +316,22 @@ static void qed_cxt_tm_iids(struct qed_cxt_mngr *p_mngr,
iids->pf_cids += p_cfg->cid_count; iids->pf_cids += p_cfg->cid_count;
iids->per_vf_cids += p_cfg->cids_per_vf; 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); iids->pf_cids = roundup(iids->pf_cids, TM_ALIGN);
...@@ -1694,9 +1719,42 @@ static void qed_tm_init_pf(struct qed_hwfn *p_hwfn) ...@@ -1694,9 +1719,42 @@ static void qed_tm_init_pf(struct qed_hwfn *p_hwfn)
/* @@@TBD how to enable the scan for the VFs */ /* @@@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) void qed_cxt_hw_init_common(struct qed_hwfn *p_hwfn)
{ {
qed_cdu_init_common(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) 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) ...@@ -1708,6 +1766,7 @@ void qed_cxt_hw_init_pf(struct qed_hwfn *p_hwfn)
qed_ilt_init_pf(p_hwfn); qed_ilt_init_pf(p_hwfn);
qed_src_init_pf(p_hwfn); qed_src_init_pf(p_hwfn);
qed_tm_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, 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) ...@@ -1885,6 +1944,27 @@ int qed_cxt_set_pf_params(struct qed_hwfn *p_hwfn)
p_params->num_cons, 1); p_params->num_cons, 1);
break; 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: case QED_PCI_ISCSI:
{ {
struct qed_iscsi_pf_params *p_params; struct qed_iscsi_pf_params *p_params;
...@@ -1927,6 +2007,10 @@ int qed_cxt_get_tid_mem_info(struct qed_hwfn *p_hwfn, ...@@ -1927,6 +2007,10 @@ int qed_cxt_get_tid_mem_info(struct qed_hwfn *p_hwfn,
/* Verify the personality */ /* Verify the personality */
switch (p_hwfn->hw_info.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: case QED_PCI_ISCSI:
proto = PROTOCOLID_ISCSI; proto = PROTOCOLID_ISCSI;
seg = QED_CXT_ISCSI_TID_SEG; seg = QED_CXT_ISCSI_TID_SEG;
...@@ -2215,15 +2299,19 @@ int qed_cxt_get_task_ctx(struct qed_hwfn *p_hwfn, ...@@ -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_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr;
struct qed_ilt_client_cfg *p_cli; struct qed_ilt_client_cfg *p_cli;
struct qed_ilt_cli_blk *p_seg;
struct qed_tid_seg *p_seg_info; struct qed_tid_seg *p_seg_info;
u32 proto, seg; struct qed_ilt_cli_blk *p_seg;
u32 total_lines;
u32 tid_size, ilt_idx;
u32 num_tids_per_block; u32 num_tids_per_block;
u32 tid_size, ilt_idx;
u32 total_lines;
u32 proto, seg;
/* Verify the personality */ /* Verify the personality */
switch (p_hwfn->hw_info.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: case QED_PCI_ISCSI:
proto = PROTOCOLID_ISCSI; proto = PROTOCOLID_ISCSI;
seg = QED_CXT_ISCSI_TID_SEG; seg = QED_CXT_ISCSI_TID_SEG;
......
...@@ -91,6 +91,7 @@ int qed_cxt_get_tid_mem_info(struct qed_hwfn *p_hwfn, ...@@ -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_ISCSI_TID_SEG PROTOCOLID_ISCSI
#define QED_CXT_ROCE_TID_SEG PROTOCOLID_ROCE #define QED_CXT_ROCE_TID_SEG PROTOCOLID_ROCE
#define QED_CXT_FCOE_TID_SEG PROTOCOLID_FCOE
enum qed_cxt_elem_type { enum qed_cxt_elem_type {
QED_ELEM_CXT, QED_ELEM_CXT,
QED_ELEM_SRQ, QED_ELEM_SRQ,
...@@ -204,4 +205,6 @@ int qed_cxt_free_proto_ilt(struct qed_hwfn *p_hwfn, enum protocol_type proto); ...@@ -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_WORKING_MEM 0
#define QED_CTX_FL_MEM 1 #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 #endif
...@@ -432,7 +432,6 @@ qed_dcbx_copy_mib(struct qed_hwfn *p_hwfn, ...@@ -432,7 +432,6 @@ qed_dcbx_copy_mib(struct qed_hwfn *p_hwfn,
return rc; return rc;
} }
#ifdef CONFIG_DCB
static void static void
qed_dcbx_get_priority_info(struct qed_hwfn *p_hwfn, qed_dcbx_get_priority_info(struct qed_hwfn *p_hwfn,
struct qed_dcbx_app_prio *p_prio, 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, ...@@ -749,7 +748,6 @@ qed_dcbx_get_params(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
return 0; return 0;
} }
#endif
static int static int
qed_dcbx_read_local_lldp_mib(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) 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, ...@@ -864,6 +862,15 @@ static int qed_dcbx_read_mib(struct qed_hwfn *p_hwfn,
return rc; 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. /* Read updated MIB.
* Reconfigure QM and invoke PF update ramrod command if operational MIB * Reconfigure QM and invoke PF update ramrod command if operational MIB
* change is detected. * change is detected.
...@@ -890,6 +897,8 @@ qed_dcbx_mib_update_event(struct qed_hwfn *p_hwfn, ...@@ -890,6 +897,8 @@ qed_dcbx_mib_update_event(struct qed_hwfn *p_hwfn,
qed_sp_pf_update(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; return rc;
} }
......
...@@ -57,7 +57,6 @@ struct qed_dcbx_app_data { ...@@ -57,7 +57,6 @@ struct qed_dcbx_app_data {
u8 tc; /* Traffic Class */ u8 tc; /* Traffic Class */
}; };
#ifdef CONFIG_DCB
#define QED_DCBX_VERSION_DISABLED 0 #define QED_DCBX_VERSION_DISABLED 0
#define QED_DCBX_VERSION_IEEE 1 #define QED_DCBX_VERSION_IEEE 1
#define QED_DCBX_VERSION_CEE 2 #define QED_DCBX_VERSION_CEE 2
...@@ -73,7 +72,6 @@ struct qed_dcbx_set { ...@@ -73,7 +72,6 @@ struct qed_dcbx_set {
struct qed_dcbx_admin_params config; struct qed_dcbx_admin_params config;
u32 ver_num; u32 ver_num;
}; };
#endif
struct qed_dcbx_results { struct qed_dcbx_results {
bool dcbx_enabled; bool dcbx_enabled;
...@@ -97,9 +95,8 @@ struct qed_dcbx_info { ...@@ -97,9 +95,8 @@ struct qed_dcbx_info {
struct qed_dcbx_results results; struct qed_dcbx_results results;
struct dcbx_mib operational; struct dcbx_mib operational;
struct dcbx_mib remote; struct dcbx_mib remote;
#ifdef CONFIG_DCB
struct qed_dcbx_set set; struct qed_dcbx_set set;
#endif struct qed_dcbx_get get;
u8 dcbx_cap; u8 dcbx_cap;
}; };
......
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
#include "qed_cxt.h" #include "qed_cxt.h"
#include "qed_dcbx.h" #include "qed_dcbx.h"
#include "qed_dev_api.h" #include "qed_dev_api.h"
#include "qed_fcoe.h"
#include "qed_hsi.h" #include "qed_hsi.h"
#include "qed_hw.h" #include "qed_hw.h"
#include "qed_init_ops.h" #include "qed_init_ops.h"
...@@ -172,6 +173,9 @@ void qed_resc_free(struct qed_dev *cdev) ...@@ -172,6 +173,9 @@ void qed_resc_free(struct qed_dev *cdev)
#ifdef CONFIG_QED_LL2 #ifdef CONFIG_QED_LL2
qed_ll2_free(p_hwfn, p_hwfn->p_ll2_info); qed_ll2_free(p_hwfn, p_hwfn->p_ll2_info);
#endif #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) { if (p_hwfn->hw_info.personality == QED_PCI_ISCSI) {
qed_iscsi_free(p_hwfn, p_hwfn->p_iscsi_info); qed_iscsi_free(p_hwfn, p_hwfn->p_iscsi_info);
qed_ooo_free(p_hwfn, p_hwfn->p_ooo_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) ...@@ -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) int qed_resc_alloc(struct qed_dev *cdev)
{ {
struct qed_iscsi_info *p_iscsi_info; struct qed_iscsi_info *p_iscsi_info;
struct qed_fcoe_info *p_fcoe_info;
struct qed_ooo_info *p_ooo_info; struct qed_ooo_info *p_ooo_info;
#ifdef CONFIG_QED_LL2 #ifdef CONFIG_QED_LL2
struct qed_ll2_info *p_ll2_info; struct qed_ll2_info *p_ll2_info;
...@@ -539,6 +544,14 @@ int qed_resc_alloc(struct qed_dev *cdev) ...@@ -539,6 +544,14 @@ int qed_resc_alloc(struct qed_dev *cdev)
p_hwfn->p_ll2_info = p_ll2_info; p_hwfn->p_ll2_info = p_ll2_info;
} }
#endif #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) { if (p_hwfn->hw_info.personality == QED_PCI_ISCSI) {
p_iscsi_info = qed_iscsi_alloc(p_hwfn); p_iscsi_info = qed_iscsi_alloc(p_hwfn);
if (!p_iscsi_info) if (!p_iscsi_info)
...@@ -602,6 +615,9 @@ void qed_resc_setup(struct qed_dev *cdev) ...@@ -602,6 +615,9 @@ void qed_resc_setup(struct qed_dev *cdev)
if (p_hwfn->using_ll2) if (p_hwfn->using_ll2)
qed_ll2_setup(p_hwfn, p_hwfn->p_ll2_info); qed_ll2_setup(p_hwfn, p_hwfn->p_ll2_info);
#endif #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) { if (p_hwfn->hw_info.personality == QED_PCI_ISCSI) {
qed_iscsi_setup(p_hwfn, p_hwfn->p_iscsi_info); qed_iscsi_setup(p_hwfn, p_hwfn->p_iscsi_info);
qed_ooo_setup(p_hwfn, p_hwfn->p_ooo_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, ...@@ -994,7 +1010,8 @@ static int qed_hw_init_pf(struct qed_hwfn *p_hwfn,
/* Protocl Configuration */ /* Protocl Configuration */
STORE_RT_REG(p_hwfn, PRS_REG_SEARCH_TCP_RT_OFFSET, STORE_RT_REG(p_hwfn, PRS_REG_SEARCH_TCP_RT_OFFSET,
(p_hwfn->hw_info.personality == QED_PCI_ISCSI) ? 1 : 0); (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); STORE_RT_REG(p_hwfn, PRS_REG_SEARCH_ROCE_RT_OFFSET, 0);
/* Cleanup chip from previous driver if such remains exist */ /* Cleanup chip from previous driver if such remains exist */
...@@ -1026,8 +1043,16 @@ static int qed_hw_init_pf(struct qed_hwfn *p_hwfn, ...@@ -1026,8 +1043,16 @@ static int qed_hw_init_pf(struct qed_hwfn *p_hwfn,
/* send function start command */ /* send function start command */
rc = qed_sp_pf_start(p_hwfn, p_tunn, p_hwfn->cdev->mf_mode, rc = qed_sp_pf_start(p_hwfn, p_tunn, p_hwfn->cdev->mf_mode,
allow_npar_tx_switch); allow_npar_tx_switch);
if (rc) if (rc) {
DP_NOTICE(p_hwfn, "Function start ramrod failed\n"); 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; return rc;
} }
...@@ -1787,8 +1812,8 @@ static int qed_hw_get_resc(struct qed_hwfn *p_hwfn) ...@@ -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) 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 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; struct qed_mcp_link_params *link;
/* Read global nvm_cfg address */ /* 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) ...@@ -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) if (device_capabilities & NVM_CFG1_GLOB_DEVICE_CAPABILITIES_ETHERNET)
__set_bit(QED_DEV_CAP_ETH, __set_bit(QED_DEV_CAP_ETH,
&p_hwfn->hw_info.device_capabilities); &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) if (device_capabilities & NVM_CFG1_GLOB_DEVICE_CAPABILITIES_ISCSI)
__set_bit(QED_DEV_CAP_ISCSI, __set_bit(QED_DEV_CAP_ISCSI,
&p_hwfn->hw_info.device_capabilities); &p_hwfn->hw_info.device_capabilities);
...@@ -2671,6 +2699,177 @@ void qed_llh_remove_mac_filter(struct qed_hwfn *p_hwfn, ...@@ -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"); 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, static int qed_set_coalesce(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
u32 hw_addr, void *p_eth_qzone, u32 hw_addr, void *p_eth_qzone,
size_t eth_qzone_size, u8 timeset) size_t eth_qzone_size, u8 timeset)
......
...@@ -353,6 +353,48 @@ int qed_llh_add_mac_filter(struct qed_hwfn *p_hwfn, ...@@ -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, void qed_llh_remove_mac_filter(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt, u8 *p_filter); 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 * *@brief Cleanup of previous driver remains prior to load
* *
......
This diff is collapsed.
/* 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 */
This diff is collapsed.
...@@ -841,6 +841,9 @@ u16 qed_get_qm_pq(struct qed_hwfn *p_hwfn, ...@@ -841,6 +841,9 @@ u16 qed_get_qm_pq(struct qed_hwfn *p_hwfn,
if (pq_id > p_hwfn->qm_info.num_pf_rls) if (pq_id > p_hwfn->qm_info.num_pf_rls)
pq_id = p_hwfn->qm_info.offload_pq; pq_id = p_hwfn->qm_info.offload_pq;
break; break;
case PROTOCOLID_FCOE:
pq_id = p_hwfn->qm_info.offload_pq;
break;
default: default:
pq_id = 0; pq_id = 0;
} }
......
...@@ -1130,6 +1130,9 @@ static int qed_sp_ll2_tx_queue_start(struct qed_hwfn *p_hwfn, ...@@ -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); p_ramrod->qm_pq_id = cpu_to_le16(pq_id);
switch (conn_type) { 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:
case QED_LL2_TYPE_ISCSI_OOO: case QED_LL2_TYPE_ISCSI_OOO:
p_ramrod->conn_type = PROTOCOLID_ISCSI; p_ramrod->conn_type = PROTOCOLID_ISCSI;
...@@ -1458,6 +1461,15 @@ int qed_ll2_establish_connection(struct qed_hwfn *p_hwfn, u8 connection_handle) ...@@ -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); 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; return rc;
} }
...@@ -1831,6 +1843,15 @@ int qed_ll2_terminate_connection(struct qed_hwfn *p_hwfn, u8 connection_handle) ...@@ -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) if (p_ll2_conn->conn.conn_type == QED_LL2_TYPE_ISCSI_OOO)
qed_ooo_release_all_isles(p_hwfn, p_hwfn->p_ooo_info); 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; return rc;
} }
...@@ -2039,6 +2060,10 @@ static int qed_ll2_start(struct qed_dev *cdev, struct qed_ll2_params *params) ...@@ -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) { 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: case QED_PCI_ISCSI:
conn_type = QED_LL2_TYPE_ISCSI; conn_type = QED_LL2_TYPE_ISCSI;
gsi_enable = 0; gsi_enable = 0;
......
...@@ -54,7 +54,7 @@ enum qed_ll2_roce_flavor_type { ...@@ -54,7 +54,7 @@ enum qed_ll2_roce_flavor_type {
}; };
enum qed_ll2_conn_type { enum qed_ll2_conn_type {
QED_LL2_TYPE_RESERVED, QED_LL2_TYPE_FCOE,
QED_LL2_TYPE_ISCSI, QED_LL2_TYPE_ISCSI,
QED_LL2_TYPE_TEST, QED_LL2_TYPE_TEST,
QED_LL2_TYPE_ISCSI_OOO, QED_LL2_TYPE_ISCSI_OOO,
......
...@@ -53,9 +53,11 @@ ...@@ -53,9 +53,11 @@
#include "qed_sp.h" #include "qed_sp.h"
#include "qed_dev_api.h" #include "qed_dev_api.h"
#include "qed_ll2.h" #include "qed_ll2.h"
#include "qed_fcoe.h"
#include "qed_mcp.h" #include "qed_mcp.h"
#include "qed_hw.h" #include "qed_hw.h"
#include "qed_selftest.h" #include "qed_selftest.h"
#include "qed_debug.h"
#define QED_ROCE_QPS (8192) #define QED_ROCE_QPS (8192)
#define QED_ROCE_DPIS (8) #define QED_ROCE_DPIS (8)
...@@ -1603,6 +1605,8 @@ const struct qed_common_ops qed_common_ops_pass = { ...@@ -1603,6 +1605,8 @@ const struct qed_common_ops qed_common_ops_pass = {
.sb_release = &qed_sb_release, .sb_release = &qed_sb_release,
.simd_handler_config = &qed_simd_handler_config, .simd_handler_config = &qed_simd_handler_config,
.simd_handler_clean = &qed_simd_handler_clean, .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, .can_link_change = &qed_can_link_change,
.set_link = &qed_set_link, .set_link = &qed_set_link,
.get_link = &qed_get_current_link, .get_link = &qed_get_current_link,
...@@ -1636,6 +1640,9 @@ void qed_get_protocol_stats(struct qed_dev *cdev, ...@@ -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.ucast_tx_pkts = eth_stats.tx_ucast_pkts;
stats->lan_stats.fcs_err = -1; stats->lan_stats.fcs_err = -1;
break; break;
case QED_MCP_FCOE_STATS:
qed_get_protocol_stats_fcoe(cdev, &stats->fcoe_stats);
break;
default: default:
DP_ERR(cdev, "Invalid protocol type = %d\n", type); DP_ERR(cdev, "Invalid protocol type = %d\n", type);
return; return;
......
...@@ -1130,6 +1130,9 @@ qed_mcp_get_shmem_proto(struct qed_hwfn *p_hwfn, ...@@ -1130,6 +1130,9 @@ qed_mcp_get_shmem_proto(struct qed_hwfn *p_hwfn,
case FUNC_MF_CFG_PROTOCOL_ISCSI: case FUNC_MF_CFG_PROTOCOL_ISCSI:
*p_proto = QED_PCI_ISCSI; *p_proto = QED_PCI_ISCSI;
break; break;
case FUNC_MF_CFG_PROTOCOL_FCOE:
*p_proto = QED_PCI_FCOE;
break;
case FUNC_MF_CFG_PROTOCOL_ROCE: case FUNC_MF_CFG_PROTOCOL_ROCE:
DP_NOTICE(p_hwfn, "RoCE personality is not a valid value!\n"); DP_NOTICE(p_hwfn, "RoCE personality is not a valid value!\n");
/* Fallthrough */ /* Fallthrough */
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/qed/qed_fcoe_if.h>
#include "qed_hsi.h" #include "qed_hsi.h"
struct qed_mcp_link_speed_params { struct qed_mcp_link_speed_params {
......
...@@ -110,6 +110,8 @@ ...@@ -110,6 +110,8 @@
0x1e80000UL 0x1e80000UL
#define NIG_REG_RX_LLH_BRB_GATE_DNTFWD_PERPF \ #define NIG_REG_RX_LLH_BRB_GATE_DNTFWD_PERPF \
0x5011f4UL 0x5011f4UL
#define PRS_REG_SEARCH_RESP_INITIATOR_TYPE \
0x1f0164UL
#define PRS_REG_SEARCH_TCP \ #define PRS_REG_SEARCH_TCP \
0x1f0400UL 0x1f0400UL
#define PRS_REG_SEARCH_UDP \ #define PRS_REG_SEARCH_UDP \
...@@ -120,6 +122,12 @@ ...@@ -120,6 +122,12 @@
0x1f040cUL 0x1f040cUL
#define PRS_REG_SEARCH_OPENFLOW \ #define PRS_REG_SEARCH_OPENFLOW \
0x1f0434UL 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 \ #define TM_REG_PF_ENABLE_CONN \
0x2c043cUL 0x2c043cUL
#define TM_REG_PF_ENABLE_TASK \ #define TM_REG_PF_ENABLE_TASK \
......
...@@ -109,6 +109,10 @@ union ramrod_data { ...@@ -109,6 +109,10 @@ union ramrod_data {
struct rdma_srq_destroy_ramrod_data rdma_destroy_srq; struct rdma_srq_destroy_ramrod_data rdma_destroy_srq;
struct rdma_srq_modify_ramrod_data rdma_modify_srq; struct rdma_srq_modify_ramrod_data rdma_modify_srq;
struct roce_init_func_ramrod_data roce_init_func; 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_slow_path_hdr iscsi_empty;
struct iscsi_init_ramrod_params iscsi_init; struct iscsi_init_ramrod_params iscsi_init;
......
...@@ -386,6 +386,9 @@ int qed_sp_pf_start(struct qed_hwfn *p_hwfn, ...@@ -386,6 +386,9 @@ int qed_sp_pf_start(struct qed_hwfn *p_hwfn,
case QED_PCI_ETH: case QED_PCI_ETH:
p_ramrod->personality = PERSONALITY_ETH; p_ramrod->personality = PERSONALITY_ETH;
break; break;
case QED_PCI_FCOE:
p_ramrod->personality = PERSONALITY_FCOE;
break;
case QED_PCI_ISCSI: case QED_PCI_ISCSI:
p_ramrod->personality = PERSONALITY_ISCSI; p_ramrod->personality = PERSONALITY_ISCSI;
break; break;
......
...@@ -62,6 +62,7 @@ ...@@ -62,6 +62,7 @@
#define COMMON_QUEUE_ENTRY_MAX_BYTE_SIZE 64 #define COMMON_QUEUE_ENTRY_MAX_BYTE_SIZE 64
#define ISCSI_CDU_TASK_SEG_TYPE 0 #define ISCSI_CDU_TASK_SEG_TYPE 0
#define FCOE_CDU_TASK_SEG_TYPE 0
#define RDMA_CDU_TASK_SEG_TYPE 1 #define RDMA_CDU_TASK_SEG_TYPE 1
#define FW_ASSERT_GENERAL_ATTN_IDX 32 #define FW_ASSERT_GENERAL_ATTN_IDX 32
...@@ -205,6 +206,9 @@ ...@@ -205,6 +206,9 @@
#define DQ_XCM_ETH_TX_BD_CONS_CMD DQ_XCM_AGG_VAL_SEL_WORD3 #define DQ_XCM_ETH_TX_BD_CONS_CMD DQ_XCM_AGG_VAL_SEL_WORD3
#define DQ_XCM_ETH_TX_BD_PROD_CMD DQ_XCM_AGG_VAL_SEL_WORD4 #define DQ_XCM_ETH_TX_BD_PROD_CMD DQ_XCM_AGG_VAL_SEL_WORD4
#define DQ_XCM_ETH_GO_TO_BD_CONS_CMD DQ_XCM_AGG_VAL_SEL_WORD5 #define DQ_XCM_ETH_GO_TO_BD_CONS_CMD DQ_XCM_AGG_VAL_SEL_WORD5
#define DQ_XCM_FCOE_SQ_CONS_CMD DQ_XCM_AGG_VAL_SEL_WORD3
#define DQ_XCM_FCOE_SQ_PROD_CMD DQ_XCM_AGG_VAL_SEL_WORD4
#define DQ_XCM_FCOE_X_FERQ_PROD_CMD DQ_XCM_AGG_VAL_SEL_WORD5
#define DQ_XCM_ISCSI_SQ_CONS_CMD DQ_XCM_AGG_VAL_SEL_WORD3 #define DQ_XCM_ISCSI_SQ_CONS_CMD DQ_XCM_AGG_VAL_SEL_WORD3
#define DQ_XCM_ISCSI_SQ_PROD_CMD DQ_XCM_AGG_VAL_SEL_WORD4 #define DQ_XCM_ISCSI_SQ_PROD_CMD DQ_XCM_AGG_VAL_SEL_WORD4
#define DQ_XCM_ISCSI_MORE_TO_SEND_SEQ_CMD DQ_XCM_AGG_VAL_SEL_REG3 #define DQ_XCM_ISCSI_MORE_TO_SEND_SEQ_CMD DQ_XCM_AGG_VAL_SEL_REG3
...@@ -261,6 +265,7 @@ ...@@ -261,6 +265,7 @@
#define DQ_XCM_ETH_TERMINATE_CMD BIT(DQ_XCM_AGG_FLG_SHIFT_CF19) #define DQ_XCM_ETH_TERMINATE_CMD BIT(DQ_XCM_AGG_FLG_SHIFT_CF19)
#define DQ_XCM_ETH_SLOW_PATH_CMD BIT(DQ_XCM_AGG_FLG_SHIFT_CF22) #define DQ_XCM_ETH_SLOW_PATH_CMD BIT(DQ_XCM_AGG_FLG_SHIFT_CF22)
#define DQ_XCM_ETH_TPH_EN_CMD BIT(DQ_XCM_AGG_FLG_SHIFT_CF23) #define DQ_XCM_ETH_TPH_EN_CMD BIT(DQ_XCM_AGG_FLG_SHIFT_CF23)
#define DQ_XCM_FCOE_SLOW_PATH_CMD BIT(DQ_XCM_AGG_FLG_SHIFT_CF22)
#define DQ_XCM_ISCSI_DQ_FLUSH_CMD BIT(DQ_XCM_AGG_FLG_SHIFT_CF19) #define DQ_XCM_ISCSI_DQ_FLUSH_CMD BIT(DQ_XCM_AGG_FLG_SHIFT_CF19)
#define DQ_XCM_ISCSI_SLOW_PATH_CMD BIT(DQ_XCM_AGG_FLG_SHIFT_CF22) #define DQ_XCM_ISCSI_SLOW_PATH_CMD BIT(DQ_XCM_AGG_FLG_SHIFT_CF22)
#define DQ_XCM_ISCSI_PROC_ONLY_CLEANUP_CMD BIT(DQ_XCM_AGG_FLG_SHIFT_CF23) #define DQ_XCM_ISCSI_PROC_ONLY_CLEANUP_CMD BIT(DQ_XCM_AGG_FLG_SHIFT_CF23)
...@@ -291,6 +296,9 @@ ...@@ -291,6 +296,9 @@
#define DQ_TCM_AGG_FLG_SHIFT_CF6 6 #define DQ_TCM_AGG_FLG_SHIFT_CF6 6
#define DQ_TCM_AGG_FLG_SHIFT_CF7 7 #define DQ_TCM_AGG_FLG_SHIFT_CF7 7
/* TCM agg counter flag selection (FW) */ /* TCM agg counter flag selection (FW) */
#define DQ_TCM_FCOE_FLUSH_Q0_CMD BIT(DQ_TCM_AGG_FLG_SHIFT_CF1)
#define DQ_TCM_FCOE_DUMMY_TIMER_CMD BIT(DQ_TCM_AGG_FLG_SHIFT_CF2)
#define DQ_TCM_FCOE_TIMER_STOP_ALL_CMD BIT(DQ_TCM_AGG_FLG_SHIFT_CF3)
#define DQ_TCM_ISCSI_FLUSH_Q0_CMD BIT(DQ_TCM_AGG_FLG_SHIFT_CF1) #define DQ_TCM_ISCSI_FLUSH_Q0_CMD BIT(DQ_TCM_AGG_FLG_SHIFT_CF1)
#define DQ_TCM_ISCSI_TIMER_STOP_ALL_CMD BIT(DQ_TCM_AGG_FLG_SHIFT_CF3) #define DQ_TCM_ISCSI_TIMER_STOP_ALL_CMD BIT(DQ_TCM_AGG_FLG_SHIFT_CF3)
...@@ -728,7 +736,7 @@ enum mf_mode { ...@@ -728,7 +736,7 @@ enum mf_mode {
/* Per-protocol connection types */ /* Per-protocol connection types */
enum protocol_type { enum protocol_type {
PROTOCOLID_ISCSI, PROTOCOLID_ISCSI,
PROTOCOLID_RESERVED2, PROTOCOLID_FCOE,
PROTOCOLID_ROCE, PROTOCOLID_ROCE,
PROTOCOLID_CORE, PROTOCOLID_CORE,
PROTOCOLID_ETH, PROTOCOLID_ETH,
......
This diff is collapsed.
#ifndef _QED_FCOE_IF_H
#define _QED_FCOE_IF_H
#include <linux/types.h>
#include <linux/qed/qed_if.h>
struct qed_fcoe_stats {
u64 fcoe_rx_byte_cnt;
u64 fcoe_rx_data_pkt_cnt;
u64 fcoe_rx_xfer_pkt_cnt;
u64 fcoe_rx_other_pkt_cnt;
u32 fcoe_silent_drop_pkt_cmdq_full_cnt;
u32 fcoe_silent_drop_pkt_rq_full_cnt;
u32 fcoe_silent_drop_pkt_crc_error_cnt;
u32 fcoe_silent_drop_pkt_task_invalid_cnt;
u32 fcoe_silent_drop_total_pkt_cnt;
u64 fcoe_tx_byte_cnt;
u64 fcoe_tx_data_pkt_cnt;
u64 fcoe_tx_xfer_pkt_cnt;
u64 fcoe_tx_other_pkt_cnt;
};
struct qed_dev_fcoe_info {
struct qed_dev_info common;
void __iomem *primary_dbq_rq_addr;
void __iomem *secondary_bdq_rq_addr;
};
struct qed_fcoe_params_offload {
dma_addr_t sq_pbl_addr;
dma_addr_t sq_curr_page_addr;
dma_addr_t sq_next_page_addr;
u8 src_mac[ETH_ALEN];
u8 dst_mac[ETH_ALEN];
u16 tx_max_fc_pay_len;
u16 e_d_tov_timer_val;
u16 rec_tov_timer_val;
u16 rx_max_fc_pay_len;
u16 vlan_tag;
struct fc_addr_nw s_id;
u8 max_conc_seqs_c3;
struct fc_addr_nw d_id;
u8 flags;
u8 def_q_idx;
};
#define MAX_TID_BLOCKS_FCOE (512)
struct qed_fcoe_tid {
u32 size; /* In bytes per task */
u32 num_tids_per_block;
u8 *blocks[MAX_TID_BLOCKS_FCOE];
};
struct qed_fcoe_cb_ops {
struct qed_common_cb_ops common;
u32 (*get_login_failures)(void *cookie);
};
void qed_fcoe_set_pf_params(struct qed_dev *cdev,
struct qed_fcoe_pf_params *params);
/**
* struct qed_fcoe_ops - qed FCoE operations.
* @common: common operations pointer
* @fill_dev_info: fills FCoE specific information
* @param cdev
* @param info
* @return 0 on sucesss, otherwise error value.
* @register_ops: register FCoE operations
* @param cdev
* @param ops - specified using qed_iscsi_cb_ops
* @param cookie - driver private
* @ll2: light L2 operations pointer
* @start: fcoe in FW
* @param cdev
* @param tasks - qed will fill information about tasks
* return 0 on success, otherwise error value.
* @stop: stops fcoe in FW
* @param cdev
* return 0 on success, otherwise error value.
* @acquire_conn: acquire a new fcoe connection
* @param cdev
* @param handle - qed will fill handle that should be
* used henceforth as identifier of the
* connection.
* @param p_doorbell - qed will fill the address of the
* doorbell.
* return 0 on sucesss, otherwise error value.
* @release_conn: release a previously acquired fcoe connection
* @param cdev
* @param handle - the connection handle.
* return 0 on success, otherwise error value.
* @offload_conn: configures an offloaded connection
* @param cdev
* @param handle - the connection handle.
* @param conn_info - the configuration to use for the
* offload.
* return 0 on success, otherwise error value.
* @destroy_conn: stops an offloaded connection
* @param cdev
* @param handle - the connection handle.
* @param terminate_params
* return 0 on success, otherwise error value.
* @get_stats: gets FCoE related statistics
* @param cdev
* @param stats - pointer to struck that would be filled
* we stats
* return 0 on success, error otherwise.
*/
struct qed_fcoe_ops {
const struct qed_common_ops *common;
int (*fill_dev_info)(struct qed_dev *cdev,
struct qed_dev_fcoe_info *info);
void (*register_ops)(struct qed_dev *cdev,
struct qed_fcoe_cb_ops *ops, void *cookie);
const struct qed_ll2_ops *ll2;
int (*start)(struct qed_dev *cdev, struct qed_fcoe_tid *tasks);
int (*stop)(struct qed_dev *cdev);
int (*acquire_conn)(struct qed_dev *cdev,
u32 *handle,
u32 *fw_cid, void __iomem **p_doorbell);
int (*release_conn)(struct qed_dev *cdev, u32 handle);
int (*offload_conn)(struct qed_dev *cdev,
u32 handle,
struct qed_fcoe_params_offload *conn_info);
int (*destroy_conn)(struct qed_dev *cdev,
u32 handle, dma_addr_t terminate_params);
int (*get_stats)(struct qed_dev *cdev, struct qed_fcoe_stats *stats);
};
const struct qed_fcoe_ops *qed_get_fcoe_ops(void);
void qed_put_fcoe_ops(void);
#endif
...@@ -59,7 +59,6 @@ enum dcbx_protocol_type { ...@@ -59,7 +59,6 @@ enum dcbx_protocol_type {
#define QED_ROCE_PROTOCOL_INDEX (3) #define QED_ROCE_PROTOCOL_INDEX (3)
#ifdef CONFIG_DCB
#define QED_LLDP_CHASSIS_ID_STAT_LEN 4 #define QED_LLDP_CHASSIS_ID_STAT_LEN 4
#define QED_LLDP_PORT_ID_STAT_LEN 4 #define QED_LLDP_PORT_ID_STAT_LEN 4
#define QED_DCBX_MAX_APP_PROTOCOL 32 #define QED_DCBX_MAX_APP_PROTOCOL 32
...@@ -155,7 +154,6 @@ struct qed_dcbx_get { ...@@ -155,7 +154,6 @@ struct qed_dcbx_get {
struct qed_dcbx_remote_params remote; struct qed_dcbx_remote_params remote;
struct qed_dcbx_admin_params local; struct qed_dcbx_admin_params local;
}; };
#endif
enum qed_led_mode { enum qed_led_mode {
QED_LED_MODE_OFF, QED_LED_MODE_OFF,
...@@ -182,6 +180,38 @@ struct qed_eth_pf_params { ...@@ -182,6 +180,38 @@ struct qed_eth_pf_params {
u16 num_cons; u16 num_cons;
}; };
struct qed_fcoe_pf_params {
/* The following parameters are used during protocol-init */
u64 glbl_q_params_addr;
u64 bdq_pbl_base_addr[2];
/* The following parameters are used during HW-init
* and these parameters need to be passed as arguments
* to update_pf_params routine invoked before slowpath start
*/
u16 num_cons;
u16 num_tasks;
/* The following parameters are used during protocol-init */
u16 sq_num_pbl_pages;
u16 cq_num_entries;
u16 cmdq_num_entries;
u16 rq_buffer_log_size;
u16 mtu;
u16 dummy_icid;
u16 bdq_xoff_threshold[2];
u16 bdq_xon_threshold[2];
u16 rq_buffer_size;
u8 num_cqs; /* num of global CQs */
u8 log_page_size;
u8 gl_rq_pi;
u8 gl_cmd_pi;
u8 debug_mode;
u8 is_target;
u8 bdq_pbl_num_entries[2];
};
/* Most of the the parameters below are described in the FW iSCSI / TCP HSI */ /* Most of the the parameters below are described in the FW iSCSI / TCP HSI */
struct qed_iscsi_pf_params { struct qed_iscsi_pf_params {
u64 glbl_q_params_addr; u64 glbl_q_params_addr;
...@@ -245,6 +275,7 @@ struct qed_rdma_pf_params { ...@@ -245,6 +275,7 @@ struct qed_rdma_pf_params {
struct qed_pf_params { struct qed_pf_params {
struct qed_eth_pf_params eth_pf_params; struct qed_eth_pf_params eth_pf_params;
struct qed_fcoe_pf_params fcoe_pf_params;
struct qed_iscsi_pf_params iscsi_pf_params; struct qed_iscsi_pf_params iscsi_pf_params;
struct qed_rdma_pf_params rdma_pf_params; struct qed_rdma_pf_params rdma_pf_params;
}; };
...@@ -305,6 +336,7 @@ enum qed_sb_type { ...@@ -305,6 +336,7 @@ enum qed_sb_type {
enum qed_protocol { enum qed_protocol {
QED_PROTOCOL_ETH, QED_PROTOCOL_ETH,
QED_PROTOCOL_ISCSI, QED_PROTOCOL_ISCSI,
QED_PROTOCOL_FCOE,
}; };
enum qed_link_mode_bits { enum qed_link_mode_bits {
...@@ -391,6 +423,7 @@ struct qed_int_info { ...@@ -391,6 +423,7 @@ struct qed_int_info {
struct qed_common_cb_ops { struct qed_common_cb_ops {
void (*link_update)(void *dev, void (*link_update)(void *dev,
struct qed_link_output *link); struct qed_link_output *link);
void (*dcbx_aen)(void *dev, struct qed_dcbx_get *get, u32 mib_type);
}; };
struct qed_selftest_ops { struct qed_selftest_ops {
...@@ -494,6 +527,10 @@ struct qed_common_ops { ...@@ -494,6 +527,10 @@ struct qed_common_ops {
void (*simd_handler_clean)(struct qed_dev *cdev, void (*simd_handler_clean)(struct qed_dev *cdev,
int index); int index);
int (*dbg_grc)(struct qed_dev *cdev,
void *buffer, u32 *num_dumped_bytes);
int (*dbg_grc_size)(struct qed_dev *cdev);
int (*dbg_all_data) (struct qed_dev *cdev, void *buffer); int (*dbg_all_data) (struct qed_dev *cdev, void *buffer);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment