Skip to content

Commit 8e57daf

Browse files
ecree-solarflaredavem330
authored andcommitted
sfc_ef100: RX path for EF100
Includes RSS spreading. Signed-off-by: Edward Cree <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent a9dc3d5 commit 8e57daf

File tree

3 files changed

+167
-9
lines changed

3 files changed

+167
-9
lines changed

drivers/net/ethernet/sfc/ef100_nic.c

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,10 @@ static int ef100_ev_process(struct efx_channel *channel, int quota)
260260
ev_type = EFX_QWORD_FIELD(*p_event, ESF_GZ_E_TYPE);
261261

262262
switch (ev_type) {
263+
case ESE_GZ_EF100_EV_RX_PKTS:
264+
efx_ef100_ev_rx(channel, p_event);
265+
++spent;
266+
break;
263267
case ESE_GZ_EF100_EV_MCDI:
264268
efx_mcdi_process_event(channel, p_event);
265269
break;
@@ -482,9 +486,10 @@ static unsigned int ef100_check_caps(const struct efx_nic *efx,
482486

483487
/* NIC level access functions
484488
*/
485-
#define EF100_OFFLOAD_FEATURES (NETIF_F_HW_CSUM | \
489+
#define EF100_OFFLOAD_FEATURES (NETIF_F_HW_CSUM | NETIF_F_RXCSUM | \
486490
NETIF_F_HIGHDMA | NETIF_F_SG | NETIF_F_FRAGLIST | \
487-
NETIF_F_TSO_ECN | NETIF_F_TSO_MANGLEID | NETIF_F_HW_VLAN_CTAG_TX)
491+
NETIF_F_RXHASH | NETIF_F_RXFCS | NETIF_F_TSO_ECN | NETIF_F_RXALL | \
492+
NETIF_F_TSO_MANGLEID | NETIF_F_HW_VLAN_CTAG_TX)
488493

489494
const struct efx_nic_type ef100_pf_nic_type = {
490495
.revision = EFX_REV_EF100,
@@ -540,6 +545,16 @@ const struct efx_nic_type ef100_pf_nic_type = {
540545

541546
.get_phys_port_id = efx_ef100_get_phys_port_id,
542547

548+
.rx_prefix_size = ESE_GZ_RX_PKT_PREFIX_LEN,
549+
.rx_hash_offset = ESF_GZ_RX_PREFIX_RSS_HASH_LBN / 8,
550+
.rx_ts_offset = ESF_GZ_RX_PREFIX_PARTIAL_TSTAMP_LBN / 8,
551+
.rx_hash_key_size = 40,
552+
.rx_pull_rss_config = efx_mcdi_rx_pull_rss_config,
553+
.rx_push_rss_config = efx_mcdi_pf_rx_push_rss_config,
554+
.rx_push_rss_context_config = efx_mcdi_rx_push_rss_context_config,
555+
.rx_pull_rss_context_config = efx_mcdi_rx_pull_rss_context_config,
556+
.rx_restore_rss_contexts = efx_mcdi_rx_restore_rss_contexts,
557+
543558
.reconfigure_mac = ef100_reconfigure_mac,
544559

545560
/* Per-type bar/size configuration not used on ef100. Location of
@@ -903,6 +918,12 @@ static int ef100_probe_main(struct efx_nic *efx)
903918
if (rc)
904919
goto fail;
905920

921+
netdev_rss_key_fill(efx->rss_context.rx_hash_key,
922+
sizeof(efx->rss_context.rx_hash_key));
923+
924+
/* Don't fail init if RSS setup doesn't work. */
925+
efx_mcdi_push_default_indir_table(efx, efx->n_rx_channels);
926+
906927
rc = ef100_register_netdev(efx);
907928
if (rc)
908929
goto fail;

drivers/net/ethernet/sfc/ef100_rx.c

Lines changed: 143 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,156 @@
1212
#include "ef100_rx.h"
1313
#include "rx_common.h"
1414
#include "efx.h"
15+
#include "nic_common.h"
16+
#include "mcdi_functions.h"
17+
#include "ef100_regs.h"
18+
#include "ef100_nic.h"
19+
#include "io.h"
1520

16-
/* RX stubs */
21+
/* Get the value of a field in the RX prefix */
22+
#define PREFIX_OFFSET_W(_f) (ESF_GZ_RX_PREFIX_ ## _f ## _LBN / 32)
23+
#define PREFIX_OFFSET_B(_f) (ESF_GZ_RX_PREFIX_ ## _f ## _LBN % 32)
24+
#define PREFIX_WIDTH_MASK(_f) ((1UL << ESF_GZ_RX_PREFIX_ ## _f ## _WIDTH) - 1)
25+
#define PREFIX_WORD(_p, _f) le32_to_cpu((__force __le32)(_p)[PREFIX_OFFSET_W(_f)])
26+
#define PREFIX_FIELD(_p, _f) ((PREFIX_WORD(_p, _f) >> PREFIX_OFFSET_B(_f)) & \
27+
PREFIX_WIDTH_MASK(_f))
1728

18-
void ef100_rx_write(struct efx_rx_queue *rx_queue)
29+
#define ESF_GZ_RX_PREFIX_NT_OR_INNER_L3_CLASS_LBN \
30+
(ESF_GZ_RX_PREFIX_CLASS_LBN + ESF_GZ_RX_PREFIX_HCLASS_NT_OR_INNER_L3_CLASS_LBN)
31+
#define ESF_GZ_RX_PREFIX_NT_OR_INNER_L3_CLASS_WIDTH \
32+
ESF_GZ_RX_PREFIX_HCLASS_NT_OR_INNER_L3_CLASS_WIDTH
33+
34+
static bool check_fcs(struct efx_channel *channel, u32 *prefix)
1935
{
36+
u16 rxclass;
37+
u8 l2status;
38+
39+
rxclass = le16_to_cpu((__force __le16)PREFIX_FIELD(prefix, CLASS));
40+
l2status = PREFIX_FIELD(&rxclass, HCLASS_L2_STATUS);
41+
42+
if (likely(l2status == ESE_GZ_RH_HCLASS_L2_STATUS_OK))
43+
/* Everything is ok */
44+
return 0;
45+
46+
if (l2status == ESE_GZ_RH_HCLASS_L2_STATUS_FCS_ERR)
47+
channel->n_rx_eth_crc_err++;
48+
return 1;
2049
}
2150

2251
void __ef100_rx_packet(struct efx_channel *channel)
2352
{
24-
/* Stub. No RX path yet. Discard the buffer. */
25-
struct efx_rx_buffer *rx_buf = efx_rx_buffer(&channel->rx_queue,
26-
channel->rx_pkt_index);
27-
struct efx_rx_queue *rx_queue = efx_channel_get_rx_queue(channel);
53+
struct efx_rx_buffer *rx_buf = efx_rx_buffer(&channel->rx_queue, channel->rx_pkt_index);
54+
struct efx_nic *efx = channel->efx;
55+
u8 *eh = efx_rx_buf_va(rx_buf);
56+
__wsum csum = 0;
57+
u32 *prefix;
58+
59+
prefix = (u32 *)(eh - ESE_GZ_RX_PKT_PREFIX_LEN);
60+
61+
if (check_fcs(channel, prefix) &&
62+
unlikely(!(efx->net_dev->features & NETIF_F_RXALL)))
63+
goto out;
64+
65+
rx_buf->len = le16_to_cpu((__force __le16)PREFIX_FIELD(prefix, LENGTH));
66+
if (rx_buf->len <= sizeof(struct ethhdr)) {
67+
if (net_ratelimit())
68+
netif_err(channel->efx, rx_err, channel->efx->net_dev,
69+
"RX packet too small (%d)\n", rx_buf->len);
70+
++channel->n_rx_frm_trunc;
71+
goto out;
72+
}
73+
74+
if (likely(efx->net_dev->features & NETIF_F_RXCSUM)) {
75+
if (PREFIX_FIELD(prefix, NT_OR_INNER_L3_CLASS) == 1) {
76+
++channel->n_rx_ip_hdr_chksum_err;
77+
} else {
78+
u16 sum = be16_to_cpu((__force __be16)PREFIX_FIELD(prefix, CSUM_FRAME));
2879

29-
efx_free_rx_buffers(rx_queue, rx_buf, 1);
80+
csum = (__force __wsum) sum;
81+
}
82+
}
83+
84+
if (channel->type->receive_skb) {
85+
struct efx_rx_queue *rx_queue =
86+
efx_channel_get_rx_queue(channel);
87+
88+
/* no support for special channels yet, so just discard */
89+
WARN_ON_ONCE(1);
90+
efx_free_rx_buffers(rx_queue, rx_buf, 1);
91+
goto out;
92+
}
93+
94+
efx_rx_packet_gro(channel, rx_buf, channel->rx_pkt_n_frags, eh, csum);
95+
96+
out:
3097
channel->rx_pkt_n_frags = 0;
3198
}
99+
100+
static void ef100_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index)
101+
{
102+
struct efx_rx_buffer *rx_buf = efx_rx_buffer(rx_queue, index);
103+
struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
104+
struct efx_nic *efx = rx_queue->efx;
105+
106+
++rx_queue->rx_packets;
107+
108+
netif_vdbg(efx, rx_status, efx->net_dev,
109+
"RX queue %d received id %x\n",
110+
efx_rx_queue_index(rx_queue), index);
111+
112+
efx_sync_rx_buffer(efx, rx_buf, efx->rx_dma_len);
113+
114+
prefetch(efx_rx_buf_va(rx_buf));
115+
116+
rx_buf->page_offset += efx->rx_prefix_size;
117+
118+
efx_recycle_rx_pages(channel, rx_buf, 1);
119+
120+
efx_rx_flush_packet(channel);
121+
channel->rx_pkt_n_frags = 1;
122+
channel->rx_pkt_index = index;
123+
}
124+
125+
void efx_ef100_ev_rx(struct efx_channel *channel, const efx_qword_t *p_event)
126+
{
127+
struct efx_rx_queue *rx_queue = efx_channel_get_rx_queue(channel);
128+
unsigned int n_packets =
129+
EFX_QWORD_FIELD(*p_event, ESF_GZ_EV_RXPKTS_NUM_PKT);
130+
int i;
131+
132+
WARN_ON_ONCE(!n_packets);
133+
if (n_packets > 1)
134+
++channel->n_rx_merge_events;
135+
136+
channel->irq_mod_score += 2 * n_packets;
137+
138+
for (i = 0; i < n_packets; ++i) {
139+
ef100_rx_packet(rx_queue,
140+
rx_queue->removed_count & rx_queue->ptr_mask);
141+
++rx_queue->removed_count;
142+
}
143+
}
144+
145+
void ef100_rx_write(struct efx_rx_queue *rx_queue)
146+
{
147+
struct efx_rx_buffer *rx_buf;
148+
unsigned int idx;
149+
efx_qword_t *rxd;
150+
efx_dword_t rxdb;
151+
152+
while (rx_queue->notified_count != rx_queue->added_count) {
153+
idx = rx_queue->notified_count & rx_queue->ptr_mask;
154+
rx_buf = efx_rx_buffer(rx_queue, idx);
155+
rxd = efx_rx_desc(rx_queue, idx);
156+
157+
EFX_POPULATE_QWORD_1(*rxd, ESF_GZ_RX_BUF_ADDR, rx_buf->dma_addr);
158+
159+
++rx_queue->notified_count;
160+
}
161+
162+
wmb();
163+
EFX_POPULATE_DWORD_1(rxdb, ERF_GZ_RX_RING_PIDX,
164+
rx_queue->added_count & rx_queue->ptr_mask);
165+
efx_writed_page(rx_queue->efx, &rxdb,
166+
ER_GZ_RX_RING_DOORBELL, efx_rx_queue_index(rx_queue));
167+
}

drivers/net/ethernet/sfc/ef100_rx.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include "net_driver.h"
1616

17+
void efx_ef100_ev_rx(struct efx_channel *channel, const efx_qword_t *p_event);
1718
void ef100_rx_write(struct efx_rx_queue *rx_queue);
1819
void __ef100_rx_packet(struct efx_channel *channel);
1920

0 commit comments

Comments
 (0)