Skip to content

Commit

Permalink
qed: Add Light L2 support
Browse files Browse the repository at this point in the history
Other protocols beside the networking driver need the ability
of passing some L2 traffic, usually [although not limited] for the
purpose of some management traffic.

Signed-off-by: Yuval Mintz <Yuval.Mintz@caviumnetworks.com>
Signed-off-by: Ram Amrani <Ram.Amrani@caviumnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Yuval Mintz authored and David S. Miller committed Oct 4, 2016
1 parent b9118b7 commit 0a7fb11
Show file tree
Hide file tree
Showing 13 changed files with 2,334 additions and 3 deletions.
8 changes: 8 additions & 0 deletions drivers/net/ethernet/qlogic/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,14 @@ config QED
---help---
This enables the support for ...

config QED_LL2
bool "Qlogic QED Light L2 interface"
default n
depends on QED
---help---
This enables support for Light L2 interface which is required
by all qed protocol drivers other than qede.

config QED_SRIOV
bool "QLogic QED 25/40/100Gb SR-IOV support"
depends on QED && PCI_IOV
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/qlogic/qed/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ qed-y := qed_cxt.o qed_dev.o qed_hw.o qed_init_fw_funcs.o qed_init_ops.o \
qed_int.o qed_main.o qed_mcp.o qed_sp_commands.o qed_spq.o qed_l2.o \
qed_selftest.o qed_dcbx.o qed_debug.o
qed-$(CONFIG_QED_SRIOV) += qed_sriov.o qed_vf.o
qed-$(CONFIG_QED_LL2) += qed_ll2.o
9 changes: 9 additions & 0 deletions drivers/net/ethernet/qlogic/qed/qed.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ struct qed_sb_info;
struct qed_sb_attn_info;
struct qed_cxt_mngr;
struct qed_sb_sp_info;
struct qed_ll2_info;
struct qed_mcp_info;

struct qed_rt_data {
Expand Down Expand Up @@ -152,6 +153,7 @@ enum QED_RESOURCES {
QED_MAC,
QED_VLAN,
QED_ILT,
QED_LL2_QUEUE,
QED_MAX_RESC,
};

Expand Down Expand Up @@ -360,6 +362,8 @@ struct qed_hwfn {
struct qed_sb_attn_info *p_sb_attn;

/* Protocol related */
bool using_ll2;
struct qed_ll2_info *p_ll2_info;
struct qed_pf_params pf_params;

bool b_rdma_enabled_in_prs;
Expand Down Expand Up @@ -564,6 +568,11 @@ struct qed_dev {

struct qed_dbg_params dbg_params;

#ifdef CONFIG_QED_LL2
struct qed_cb_ll2_info *ll2;
u8 ll2_mac_address[ETH_ALEN];
#endif

const struct firmware *firmware;
};

Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/qlogic/qed/qed_cxt.c
Original file line number Diff line number Diff line change
Expand Up @@ -1839,6 +1839,8 @@ int qed_cxt_set_pf_params(struct qed_hwfn *p_hwfn)
/* Set the number of required CORE connections */
u32 core_cids = 1; /* SPQ */

if (p_hwfn->using_ll2)
core_cids += 4;
qed_cxt_set_proto_cid_count(p_hwfn, PROTOCOLID_CORE, core_cids, 0);

switch (p_hwfn->hw_info.personality) {
Expand Down
120 changes: 118 additions & 2 deletions drivers/net/ethernet/qlogic/qed/qed_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "qed_hw.h"
#include "qed_init_ops.h"
#include "qed_int.h"
#include "qed_ll2.h"
#include "qed_mcp.h"
#include "qed_reg_addr.h"
#include "qed_sp.h"
Expand Down Expand Up @@ -147,6 +148,9 @@ void qed_resc_free(struct qed_dev *cdev)
qed_eq_free(p_hwfn, p_hwfn->p_eq);
qed_consq_free(p_hwfn, p_hwfn->p_consq);
qed_int_free(p_hwfn);
#ifdef CONFIG_QED_LL2
qed_ll2_free(p_hwfn, p_hwfn->p_ll2_info);
#endif
qed_iov_free(p_hwfn);
qed_dmae_info_free(p_hwfn);
qed_dcbx_info_free(p_hwfn, p_hwfn->p_dcbx_info);
Expand Down Expand Up @@ -403,6 +407,9 @@ int qed_qm_reconf(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)

int qed_resc_alloc(struct qed_dev *cdev)
{
#ifdef CONFIG_QED_LL2
struct qed_ll2_info *p_ll2_info;
#endif
struct qed_consq *p_consq;
struct qed_eq *p_eq;
int i, rc = 0;
Expand Down Expand Up @@ -513,6 +520,15 @@ int qed_resc_alloc(struct qed_dev *cdev)
goto alloc_no_mem;
p_hwfn->p_consq = p_consq;

#ifdef CONFIG_QED_LL2
if (p_hwfn->using_ll2) {
p_ll2_info = qed_ll2_alloc(p_hwfn);
if (!p_ll2_info)
goto alloc_no_mem;
p_hwfn->p_ll2_info = p_ll2_info;
}
#endif

/* DMA info initialization */
rc = qed_dmae_info_alloc(p_hwfn);
if (rc)
Expand Down Expand Up @@ -561,6 +577,10 @@ void qed_resc_setup(struct qed_dev *cdev)
qed_int_setup(p_hwfn, p_hwfn->p_main_ptt);

qed_iov_setup(p_hwfn, p_hwfn->p_main_ptt);
#ifdef CONFIG_QED_LL2
if (p_hwfn->using_ll2)
qed_ll2_setup(p_hwfn, p_hwfn->p_ll2_info);
#endif
}
}

Expand Down Expand Up @@ -1304,6 +1324,7 @@ static int qed_hw_get_resc(struct qed_hwfn *p_hwfn)
resc_num[QED_VLAN] = (ETH_NUM_VLAN_FILTERS - 1 /*For vlan0*/) /
num_funcs;
resc_num[QED_ILT] = PXP_NUM_ILT_RECORDS_BB / num_funcs;
resc_num[QED_LL2_QUEUE] = MAX_NUM_LL2_RX_QUEUES / num_funcs;

for (i = 0; i < QED_MAX_RESC; i++)
resc_start[i] = resc_num[i] * enabled_func_idx;
Expand All @@ -1327,7 +1348,8 @@ static int qed_hw_get_resc(struct qed_hwfn *p_hwfn)
"RL = %d start = %d\n"
"MAC = %d start = %d\n"
"VLAN = %d start = %d\n"
"ILT = %d start = %d\n",
"ILT = %d start = %d\n"
"LL2_QUEUE = %d start = %d\n",
p_hwfn->hw_info.resc_num[QED_SB],
p_hwfn->hw_info.resc_start[QED_SB],
p_hwfn->hw_info.resc_num[QED_L2_QUEUE],
Expand All @@ -1343,7 +1365,9 @@ static int qed_hw_get_resc(struct qed_hwfn *p_hwfn)
p_hwfn->hw_info.resc_num[QED_VLAN],
p_hwfn->hw_info.resc_start[QED_VLAN],
p_hwfn->hw_info.resc_num[QED_ILT],
p_hwfn->hw_info.resc_start[QED_ILT]);
p_hwfn->hw_info.resc_start[QED_ILT],
RESC_NUM(p_hwfn, QED_LL2_QUEUE),
RESC_START(p_hwfn, QED_LL2_QUEUE));

return 0;
}
Expand Down Expand Up @@ -2133,6 +2157,98 @@ int qed_fw_rss_eng(struct qed_hwfn *p_hwfn, u8 src_id, u8 *dst_id)
return 0;
}

static void qed_llh_mac_to_filter(u32 *p_high, u32 *p_low,
u8 *p_filter)
{
*p_high = p_filter[1] | (p_filter[0] << 8);
*p_low = p_filter[5] | (p_filter[4] << 8) |
(p_filter[3] << 16) | (p_filter[2] << 24);
}

int qed_llh_add_mac_filter(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt, u8 *p_filter)
{
u32 high = 0, low = 0, en;
int i;

if (!(IS_MF_SI(p_hwfn) || IS_MF_DEFAULT(p_hwfn)))
return 0;

qed_llh_mac_to_filter(&high, &low, p_filter);

/* 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), 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_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;
}

DP_VERBOSE(p_hwfn, NETIF_MSG_HW,
"mac: %pM is added at %d\n",
p_filter, i);

return 0;
}

void qed_llh_remove_mac_filter(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt, u8 *p_filter)
{
u32 high = 0, low = 0;
int i;

if (!(IS_MF_SI(p_hwfn) || IS_MF_DEFAULT(p_hwfn)))
return;

qed_llh_mac_to_filter(&high, &low, p_filter);

/* Find the entry and clean it */
for (i = 0; i < NIG_REG_LLH_FUNC_FILTER_EN_SIZE; i++) {
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_VALUE + 2 * i * sizeof(u32), 0);
qed_wr(p_hwfn, p_ptt,
NIG_REG_LLH_FUNC_FILTER_VALUE +
(2 * i + 1) * sizeof(u32), 0);

DP_VERBOSE(p_hwfn, NETIF_MSG_HW,
"mac: %pM is removed from %d\n",
p_filter, i);
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)
Expand Down
20 changes: 20 additions & 0 deletions drivers/net/ethernet/qlogic/qed/qed_dev_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,26 @@ int qed_fw_rss_eng(struct qed_hwfn *p_hwfn,
u8 src_id,
u8 *dst_id);

/**
* @brief qed_llh_add_mac_filter - configures a MAC filter in llh
*
* @param p_hwfn
* @param p_ptt
* @param p_filter - MAC to add
*/
int qed_llh_add_mac_filter(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt, u8 *p_filter);

/**
* @brief qed_llh_remove_mac_filter - removes a MAC filter from llh
*
* @param p_hwfn
* @param p_ptt
* @param p_filter - MAC to remove
*/
void qed_llh_remove_mac_filter(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt, u8 *p_filter);

/**
* *@brief Cleanup of previous driver remains prior to load
*
Expand Down
Loading

0 comments on commit 0a7fb11

Please sign in to comment.