Skip to content

Commit faf8dcc

Browse files
jco-xilinxdavem330
authored andcommitted
sfc: Track RPS flow IDs per channel instead of per function
Otherwise we get confused when two flows on different channels get the same flow ID. Signed-off-by: Edward Cree <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent d69d169 commit faf8dcc

File tree

3 files changed

+56
-17
lines changed

3 files changed

+56
-17
lines changed

drivers/net/ethernet/sfc/efx.c

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1726,14 +1726,33 @@ static int efx_probe_filters(struct efx_nic *efx)
17261726

17271727
#ifdef CONFIG_RFS_ACCEL
17281728
if (efx->type->offload_features & NETIF_F_NTUPLE) {
1729-
efx->rps_flow_id = kcalloc(efx->type->max_rx_ip_filters,
1730-
sizeof(*efx->rps_flow_id),
1731-
GFP_KERNEL);
1732-
if (!efx->rps_flow_id) {
1729+
struct efx_channel *channel;
1730+
int i, success = 1;
1731+
1732+
efx_for_each_channel(channel, efx) {
1733+
channel->rps_flow_id =
1734+
kcalloc(efx->type->max_rx_ip_filters,
1735+
sizeof(*channel->rps_flow_id),
1736+
GFP_KERNEL);
1737+
if (!channel->rps_flow_id)
1738+
success = 0;
1739+
else
1740+
for (i = 0;
1741+
i < efx->type->max_rx_ip_filters;
1742+
++i)
1743+
channel->rps_flow_id[i] =
1744+
RPS_FLOW_ID_INVALID;
1745+
}
1746+
1747+
if (!success) {
1748+
efx_for_each_channel(channel, efx)
1749+
kfree(channel->rps_flow_id);
17331750
efx->type->filter_table_remove(efx);
17341751
rc = -ENOMEM;
17351752
goto out_unlock;
17361753
}
1754+
1755+
efx->rps_expire_index = efx->rps_expire_channel = 0;
17371756
}
17381757
#endif
17391758
out_unlock:
@@ -1744,7 +1763,10 @@ static int efx_probe_filters(struct efx_nic *efx)
17441763
static void efx_remove_filters(struct efx_nic *efx)
17451764
{
17461765
#ifdef CONFIG_RFS_ACCEL
1747-
kfree(efx->rps_flow_id);
1766+
struct efx_channel *channel;
1767+
1768+
efx_for_each_channel(channel, efx)
1769+
kfree(channel->rps_flow_id);
17481770
#endif
17491771
down_write(&efx->filter_sem);
17501772
efx->type->filter_table_remove(efx);

drivers/net/ethernet/sfc/net_driver.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,8 @@ enum efx_sync_events_state {
403403
* @event_test_cpu: Last CPU to handle interrupt or test event for this channel
404404
* @irq_count: Number of IRQs since last adaptive moderation decision
405405
* @irq_mod_score: IRQ moderation score
406+
* @rps_flow_id: Flow IDs of filters allocated for accelerated RFS,
407+
* indexed by filter ID
406408
* @n_rx_tobe_disc: Count of RX_TOBE_DISC errors
407409
* @n_rx_ip_hdr_chksum_err: Count of RX IP header checksum errors
408410
* @n_rx_tcp_udp_chksum_err: Count of RX TCP and UDP checksum errors
@@ -446,6 +448,8 @@ struct efx_channel {
446448
unsigned int irq_mod_score;
447449
#ifdef CONFIG_RFS_ACCEL
448450
unsigned int rfs_filters_added;
451+
#define RPS_FLOW_ID_INVALID 0xFFFFFFFF
452+
u32 *rps_flow_id;
449453
#endif
450454

451455
unsigned n_rx_tobe_disc;
@@ -889,9 +893,9 @@ struct vfdi_status;
889893
* @filter_sem: Filter table rw_semaphore, for freeing the table
890894
* @filter_lock: Filter table lock, for mere content changes
891895
* @filter_state: Architecture-dependent filter table state
892-
* @rps_flow_id: Flow IDs of filters allocated for accelerated RFS,
893-
* indexed by filter ID
894-
* @rps_expire_index: Next index to check for expiry in @rps_flow_id
896+
* @rps_expire_channel: Next channel to check for expiry
897+
* @rps_expire_index: Next index to check for expiry in
898+
* @rps_expire_channel's @rps_flow_id
895899
* @active_queues: Count of RX and TX queues that haven't been flushed and drained.
896900
* @rxq_flush_pending: Count of number of receive queues that need to be flushed.
897901
* Decremented when the efx_flush_rx_queue() is called.
@@ -1035,7 +1039,7 @@ struct efx_nic {
10351039
spinlock_t filter_lock;
10361040
void *filter_state;
10371041
#ifdef CONFIG_RFS_ACCEL
1038-
u32 *rps_flow_id;
1042+
unsigned int rps_expire_channel;
10391043
unsigned int rps_expire_index;
10401044
#endif
10411045

drivers/net/ethernet/sfc/rx.c

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -845,6 +845,9 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
845845
struct flow_keys fk;
846846
int rc;
847847

848+
if (flow_id == RPS_FLOW_ID_INVALID)
849+
return -EINVAL;
850+
848851
if (!skb_flow_dissect_flow_keys(skb, &fk, 0))
849852
return -EPROTONOSUPPORT;
850853

@@ -879,8 +882,8 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
879882
return rc;
880883

881884
/* Remember this so we can check whether to expire the filter later */
882-
efx->rps_flow_id[rc] = flow_id;
883-
channel = efx_get_channel(efx, skb_get_rx_queue(skb));
885+
channel = efx_get_channel(efx, rxq_index);
886+
channel->rps_flow_id[rc] = flow_id;
884887
++channel->rfs_filters_added;
885888

886889
if (spec.ether_type == htons(ETH_P_IP))
@@ -902,24 +905,34 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
902905
bool __efx_filter_rfs_expire(struct efx_nic *efx, unsigned int quota)
903906
{
904907
bool (*expire_one)(struct efx_nic *efx, u32 flow_id, unsigned int index);
905-
unsigned int index, size;
908+
unsigned int channel_idx, index, size;
906909
u32 flow_id;
907910

908911
if (!spin_trylock_bh(&efx->filter_lock))
909912
return false;
910913

911914
expire_one = efx->type->filter_rfs_expire_one;
915+
channel_idx = efx->rps_expire_channel;
912916
index = efx->rps_expire_index;
913917
size = efx->type->max_rx_ip_filters;
914918
while (quota--) {
915-
flow_id = efx->rps_flow_id[index];
916-
if (expire_one(efx, flow_id, index))
919+
struct efx_channel *channel = efx_get_channel(efx, channel_idx);
920+
flow_id = channel->rps_flow_id[index];
921+
922+
if (flow_id != RPS_FLOW_ID_INVALID &&
923+
expire_one(efx, flow_id, index)) {
917924
netif_info(efx, rx_status, efx->net_dev,
918-
"expired filter %d [flow %u]\n",
919-
index, flow_id);
920-
if (++index == size)
925+
"expired filter %d [queue %u flow %u]\n",
926+
index, channel_idx, flow_id);
927+
channel->rps_flow_id[index] = RPS_FLOW_ID_INVALID;
928+
}
929+
if (++index == size) {
930+
if (++channel_idx == efx->n_channels)
931+
channel_idx = 0;
921932
index = 0;
933+
}
922934
}
935+
efx->rps_expire_channel = channel_idx;
923936
efx->rps_expire_index = index;
924937

925938
spin_unlock_bh(&efx->filter_lock);

0 commit comments

Comments
 (0)