Skip to content

Commit 0a7fb11

Browse files
Yuval Mintzdavem330
authored andcommitted
qed: Add Light L2 support
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 <[email protected]> Signed-off-by: Ram Amrani <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent b9118b7 commit 0a7fb11

File tree

13 files changed

+2334
-3
lines changed

13 files changed

+2334
-3
lines changed

drivers/net/ethernet/qlogic/Kconfig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,14 @@ config QED
8888
---help---
8989
This enables the support for ...
9090

91+
config QED_LL2
92+
bool "Qlogic QED Light L2 interface"
93+
default n
94+
depends on QED
95+
---help---
96+
This enables support for Light L2 interface which is required
97+
by all qed protocol drivers other than qede.
98+
9199
config QED_SRIOV
92100
bool "QLogic QED 25/40/100Gb SR-IOV support"
93101
depends on QED && PCI_IOV

drivers/net/ethernet/qlogic/qed/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ qed-y := qed_cxt.o qed_dev.o qed_hw.o qed_init_fw_funcs.o qed_init_ops.o \
44
qed_int.o qed_main.o qed_mcp.o qed_sp_commands.o qed_spq.o qed_l2.o \
55
qed_selftest.o qed_dcbx.o qed_debug.o
66
qed-$(CONFIG_QED_SRIOV) += qed_sriov.o qed_vf.o
7+
qed-$(CONFIG_QED_LL2) += qed_ll2.o

drivers/net/ethernet/qlogic/qed/qed.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ struct qed_sb_info;
7272
struct qed_sb_attn_info;
7373
struct qed_cxt_mngr;
7474
struct qed_sb_sp_info;
75+
struct qed_ll2_info;
7576
struct qed_mcp_info;
7677

7778
struct qed_rt_data {
@@ -152,6 +153,7 @@ enum QED_RESOURCES {
152153
QED_MAC,
153154
QED_VLAN,
154155
QED_ILT,
156+
QED_LL2_QUEUE,
155157
QED_MAX_RESC,
156158
};
157159

@@ -360,6 +362,8 @@ struct qed_hwfn {
360362
struct qed_sb_attn_info *p_sb_attn;
361363

362364
/* Protocol related */
365+
bool using_ll2;
366+
struct qed_ll2_info *p_ll2_info;
363367
struct qed_pf_params pf_params;
364368

365369
bool b_rdma_enabled_in_prs;
@@ -564,6 +568,11 @@ struct qed_dev {
564568

565569
struct qed_dbg_params dbg_params;
566570

571+
#ifdef CONFIG_QED_LL2
572+
struct qed_cb_ll2_info *ll2;
573+
u8 ll2_mac_address[ETH_ALEN];
574+
#endif
575+
567576
const struct firmware *firmware;
568577
};
569578

drivers/net/ethernet/qlogic/qed/qed_cxt.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1839,6 +1839,8 @@ int qed_cxt_set_pf_params(struct qed_hwfn *p_hwfn)
18391839
/* Set the number of required CORE connections */
18401840
u32 core_cids = 1; /* SPQ */
18411841

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

18441846
switch (p_hwfn->hw_info.personality) {

drivers/net/ethernet/qlogic/qed/qed_dev.c

Lines changed: 118 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "qed_hw.h"
3030
#include "qed_init_ops.h"
3131
#include "qed_int.h"
32+
#include "qed_ll2.h"
3233
#include "qed_mcp.h"
3334
#include "qed_reg_addr.h"
3435
#include "qed_sp.h"
@@ -147,6 +148,9 @@ void qed_resc_free(struct qed_dev *cdev)
147148
qed_eq_free(p_hwfn, p_hwfn->p_eq);
148149
qed_consq_free(p_hwfn, p_hwfn->p_consq);
149150
qed_int_free(p_hwfn);
151+
#ifdef CONFIG_QED_LL2
152+
qed_ll2_free(p_hwfn, p_hwfn->p_ll2_info);
153+
#endif
150154
qed_iov_free(p_hwfn);
151155
qed_dmae_info_free(p_hwfn);
152156
qed_dcbx_info_free(p_hwfn, p_hwfn->p_dcbx_info);
@@ -403,6 +407,9 @@ int qed_qm_reconf(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
403407

404408
int qed_resc_alloc(struct qed_dev *cdev)
405409
{
410+
#ifdef CONFIG_QED_LL2
411+
struct qed_ll2_info *p_ll2_info;
412+
#endif
406413
struct qed_consq *p_consq;
407414
struct qed_eq *p_eq;
408415
int i, rc = 0;
@@ -513,6 +520,15 @@ int qed_resc_alloc(struct qed_dev *cdev)
513520
goto alloc_no_mem;
514521
p_hwfn->p_consq = p_consq;
515522

523+
#ifdef CONFIG_QED_LL2
524+
if (p_hwfn->using_ll2) {
525+
p_ll2_info = qed_ll2_alloc(p_hwfn);
526+
if (!p_ll2_info)
527+
goto alloc_no_mem;
528+
p_hwfn->p_ll2_info = p_ll2_info;
529+
}
530+
#endif
531+
516532
/* DMA info initialization */
517533
rc = qed_dmae_info_alloc(p_hwfn);
518534
if (rc)
@@ -561,6 +577,10 @@ void qed_resc_setup(struct qed_dev *cdev)
561577
qed_int_setup(p_hwfn, p_hwfn->p_main_ptt);
562578

563579
qed_iov_setup(p_hwfn, p_hwfn->p_main_ptt);
580+
#ifdef CONFIG_QED_LL2
581+
if (p_hwfn->using_ll2)
582+
qed_ll2_setup(p_hwfn, p_hwfn->p_ll2_info);
583+
#endif
564584
}
565585
}
566586

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

13081329
for (i = 0; i < QED_MAX_RESC; i++)
13091330
resc_start[i] = resc_num[i] * enabled_func_idx;
@@ -1327,7 +1348,8 @@ static int qed_hw_get_resc(struct qed_hwfn *p_hwfn)
13271348
"RL = %d start = %d\n"
13281349
"MAC = %d start = %d\n"
13291350
"VLAN = %d start = %d\n"
1330-
"ILT = %d start = %d\n",
1351+
"ILT = %d start = %d\n"
1352+
"LL2_QUEUE = %d start = %d\n",
13311353
p_hwfn->hw_info.resc_num[QED_SB],
13321354
p_hwfn->hw_info.resc_start[QED_SB],
13331355
p_hwfn->hw_info.resc_num[QED_L2_QUEUE],
@@ -1343,7 +1365,9 @@ static int qed_hw_get_resc(struct qed_hwfn *p_hwfn)
13431365
p_hwfn->hw_info.resc_num[QED_VLAN],
13441366
p_hwfn->hw_info.resc_start[QED_VLAN],
13451367
p_hwfn->hw_info.resc_num[QED_ILT],
1346-
p_hwfn->hw_info.resc_start[QED_ILT]);
1368+
p_hwfn->hw_info.resc_start[QED_ILT],
1369+
RESC_NUM(p_hwfn, QED_LL2_QUEUE),
1370+
RESC_START(p_hwfn, QED_LL2_QUEUE));
13471371

13481372
return 0;
13491373
}
@@ -2133,6 +2157,98 @@ int qed_fw_rss_eng(struct qed_hwfn *p_hwfn, u8 src_id, u8 *dst_id)
21332157
return 0;
21342158
}
21352159

2160+
static void qed_llh_mac_to_filter(u32 *p_high, u32 *p_low,
2161+
u8 *p_filter)
2162+
{
2163+
*p_high = p_filter[1] | (p_filter[0] << 8);
2164+
*p_low = p_filter[5] | (p_filter[4] << 8) |
2165+
(p_filter[3] << 16) | (p_filter[2] << 24);
2166+
}
2167+
2168+
int qed_llh_add_mac_filter(struct qed_hwfn *p_hwfn,
2169+
struct qed_ptt *p_ptt, u8 *p_filter)
2170+
{
2171+
u32 high = 0, low = 0, en;
2172+
int i;
2173+
2174+
if (!(IS_MF_SI(p_hwfn) || IS_MF_DEFAULT(p_hwfn)))
2175+
return 0;
2176+
2177+
qed_llh_mac_to_filter(&high, &low, p_filter);
2178+
2179+
/* Find a free entry and utilize it */
2180+
for (i = 0; i < NIG_REG_LLH_FUNC_FILTER_EN_SIZE; i++) {
2181+
en = qed_rd(p_hwfn, p_ptt,
2182+
NIG_REG_LLH_FUNC_FILTER_EN + i * sizeof(u32));
2183+
if (en)
2184+
continue;
2185+
qed_wr(p_hwfn, p_ptt,
2186+
NIG_REG_LLH_FUNC_FILTER_VALUE +
2187+
2 * i * sizeof(u32), low);
2188+
qed_wr(p_hwfn, p_ptt,
2189+
NIG_REG_LLH_FUNC_FILTER_VALUE +
2190+
(2 * i + 1) * sizeof(u32), high);
2191+
qed_wr(p_hwfn, p_ptt,
2192+
NIG_REG_LLH_FUNC_FILTER_MODE + i * sizeof(u32), 0);
2193+
qed_wr(p_hwfn, p_ptt,
2194+
NIG_REG_LLH_FUNC_FILTER_PROTOCOL_TYPE +
2195+
i * sizeof(u32), 0);
2196+
qed_wr(p_hwfn, p_ptt,
2197+
NIG_REG_LLH_FUNC_FILTER_EN + i * sizeof(u32), 1);
2198+
break;
2199+
}
2200+
if (i >= NIG_REG_LLH_FUNC_FILTER_EN_SIZE) {
2201+
DP_NOTICE(p_hwfn,
2202+
"Failed to find an empty LLH filter to utilize\n");
2203+
return -EINVAL;
2204+
}
2205+
2206+
DP_VERBOSE(p_hwfn, NETIF_MSG_HW,
2207+
"mac: %pM is added at %d\n",
2208+
p_filter, i);
2209+
2210+
return 0;
2211+
}
2212+
2213+
void qed_llh_remove_mac_filter(struct qed_hwfn *p_hwfn,
2214+
struct qed_ptt *p_ptt, u8 *p_filter)
2215+
{
2216+
u32 high = 0, low = 0;
2217+
int i;
2218+
2219+
if (!(IS_MF_SI(p_hwfn) || IS_MF_DEFAULT(p_hwfn)))
2220+
return;
2221+
2222+
qed_llh_mac_to_filter(&high, &low, p_filter);
2223+
2224+
/* Find the entry and clean it */
2225+
for (i = 0; i < NIG_REG_LLH_FUNC_FILTER_EN_SIZE; i++) {
2226+
if (qed_rd(p_hwfn, p_ptt,
2227+
NIG_REG_LLH_FUNC_FILTER_VALUE +
2228+
2 * i * sizeof(u32)) != low)
2229+
continue;
2230+
if (qed_rd(p_hwfn, p_ptt,
2231+
NIG_REG_LLH_FUNC_FILTER_VALUE +
2232+
(2 * i + 1) * sizeof(u32)) != high)
2233+
continue;
2234+
2235+
qed_wr(p_hwfn, p_ptt,
2236+
NIG_REG_LLH_FUNC_FILTER_EN + i * sizeof(u32), 0);
2237+
qed_wr(p_hwfn, p_ptt,
2238+
NIG_REG_LLH_FUNC_FILTER_VALUE + 2 * i * sizeof(u32), 0);
2239+
qed_wr(p_hwfn, p_ptt,
2240+
NIG_REG_LLH_FUNC_FILTER_VALUE +
2241+
(2 * i + 1) * sizeof(u32), 0);
2242+
2243+
DP_VERBOSE(p_hwfn, NETIF_MSG_HW,
2244+
"mac: %pM is removed from %d\n",
2245+
p_filter, i);
2246+
break;
2247+
}
2248+
if (i >= NIG_REG_LLH_FUNC_FILTER_EN_SIZE)
2249+
DP_NOTICE(p_hwfn, "Tried to remove a non-configured filter\n");
2250+
}
2251+
21362252
static int qed_set_coalesce(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
21372253
u32 hw_addr, void *p_eth_qzone,
21382254
size_t eth_qzone_size, u8 timeset)

drivers/net/ethernet/qlogic/qed/qed_dev_api.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,26 @@ int qed_fw_rss_eng(struct qed_hwfn *p_hwfn,
309309
u8 src_id,
310310
u8 *dst_id);
311311

312+
/**
313+
* @brief qed_llh_add_mac_filter - configures a MAC filter in llh
314+
*
315+
* @param p_hwfn
316+
* @param p_ptt
317+
* @param p_filter - MAC to add
318+
*/
319+
int qed_llh_add_mac_filter(struct qed_hwfn *p_hwfn,
320+
struct qed_ptt *p_ptt, u8 *p_filter);
321+
322+
/**
323+
* @brief qed_llh_remove_mac_filter - removes a MAC filter from llh
324+
*
325+
* @param p_hwfn
326+
* @param p_ptt
327+
* @param p_filter - MAC to remove
328+
*/
329+
void qed_llh_remove_mac_filter(struct qed_hwfn *p_hwfn,
330+
struct qed_ptt *p_ptt, u8 *p_filter);
331+
312332
/**
313333
* *@brief Cleanup of previous driver remains prior to load
314334
*

0 commit comments

Comments
 (0)