Re: [PATCH v2 net] sfc: Track RPS flow IDs per channel instead of per function

2016-05-31 Thread David Miller
From: Edward Cree 
Date: Tue, 31 May 2016 19:12:32 +0100

> From: Jon Cooper 
> 
> Otherwise we get confused when two flows on different channels get the
>  same flow ID.
> 
> Signed-off-by: Edward Cree 

Applied, thanks.


[PATCH v2 net] sfc: Track RPS flow IDs per channel instead of per function

2016-05-31 Thread Edward Cree
From: Jon Cooper 

Otherwise we get confused when two flows on different channels get the
 same flow ID.

Signed-off-by: Edward Cree 
---
 drivers/net/ethernet/sfc/efx.c| 32 +++-
 drivers/net/ethernet/sfc/net_driver.h | 12 
 drivers/net/ethernet/sfc/rx.c | 29 +
 3 files changed, 56 insertions(+), 17 deletions(-)

diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 0705ec86..097f363 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -1726,14 +1726,33 @@ static int efx_probe_filters(struct efx_nic *efx)
 
 #ifdef CONFIG_RFS_ACCEL
if (efx->type->offload_features & NETIF_F_NTUPLE) {
-   efx->rps_flow_id = kcalloc(efx->type->max_rx_ip_filters,
-  sizeof(*efx->rps_flow_id),
-  GFP_KERNEL);
-   if (!efx->rps_flow_id) {
+   struct efx_channel *channel;
+   int i, success = 1;
+
+   efx_for_each_channel(channel, efx) {
+   channel->rps_flow_id =
+   kcalloc(efx->type->max_rx_ip_filters,
+   sizeof(*channel->rps_flow_id),
+   GFP_KERNEL);
+   if (!channel->rps_flow_id)
+   success = 0;
+   else
+   for (i = 0;
+i < efx->type->max_rx_ip_filters;
+++i)
+   channel->rps_flow_id[i] =
+   RPS_FLOW_ID_INVALID;
+   }
+
+   if (!success) {
+   efx_for_each_channel(channel, efx)
+   kfree(channel->rps_flow_id);
efx->type->filter_table_remove(efx);
rc = -ENOMEM;
goto out_unlock;
}
+
+   efx->rps_expire_index = efx->rps_expire_channel = 0;
}
 #endif
 out_unlock:
@@ -1744,7 +1763,10 @@ out_unlock:
 static void efx_remove_filters(struct efx_nic *efx)
 {
 #ifdef CONFIG_RFS_ACCEL
-   kfree(efx->rps_flow_id);
+   struct efx_channel *channel;
+
+   efx_for_each_channel(channel, efx)
+   kfree(channel->rps_flow_id);
 #endif
down_write(>filter_sem);
efx->type->filter_table_remove(efx);
diff --git a/drivers/net/ethernet/sfc/net_driver.h 
b/drivers/net/ethernet/sfc/net_driver.h
index 38c4223..d13ddf9 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -403,6 +403,8 @@ enum efx_sync_events_state {
  * @event_test_cpu: Last CPU to handle interrupt or test event for this channel
  * @irq_count: Number of IRQs since last adaptive moderation decision
  * @irq_mod_score: IRQ moderation score
+ * @rps_flow_id: Flow IDs of filters allocated for accelerated RFS,
+ *  indexed by filter ID
  * @n_rx_tobe_disc: Count of RX_TOBE_DISC errors
  * @n_rx_ip_hdr_chksum_err: Count of RX IP header checksum errors
  * @n_rx_tcp_udp_chksum_err: Count of RX TCP and UDP checksum errors
@@ -446,6 +448,8 @@ struct efx_channel {
unsigned int irq_mod_score;
 #ifdef CONFIG_RFS_ACCEL
unsigned int rfs_filters_added;
+#define RPS_FLOW_ID_INVALID 0x
+   u32 *rps_flow_id;
 #endif
 
unsigned n_rx_tobe_disc;
@@ -889,9 +893,9 @@ struct vfdi_status;
  * @filter_sem: Filter table rw_semaphore, for freeing the table
  * @filter_lock: Filter table lock, for mere content changes
  * @filter_state: Architecture-dependent filter table state
- * @rps_flow_id: Flow IDs of filters allocated for accelerated RFS,
- * indexed by filter ID
- * @rps_expire_index: Next index to check for expiry in @rps_flow_id
+ * @rps_expire_channel: Next channel to check for expiry
+ * @rps_expire_index: Next index to check for expiry in
+ * @rps_expire_channel's @rps_flow_id
  * @active_queues: Count of RX and TX queues that haven't been flushed and 
drained.
  * @rxq_flush_pending: Count of number of receive queues that need to be 
flushed.
  * Decremented when the efx_flush_rx_queue() is called.
@@ -1035,7 +1039,7 @@ struct efx_nic {
spinlock_t filter_lock;
void *filter_state;
 #ifdef CONFIG_RFS_ACCEL
-   u32 *rps_flow_id;
+   unsigned int rps_expire_channel;
unsigned int rps_expire_index;
 #endif
 
diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c
index 9d6cc8b..02b0b527 100644
--- a/drivers/net/ethernet/sfc/rx.c
+++ b/drivers/net/ethernet/sfc/rx.c
@@ -845,6 +845,9 @@ int efx_filter_rfs(struct net_device *net_dev, const struct 
sk_buff *skb,
struct flow_keys fk;
int rc;
 
+   if (flow_id == RPS_FLOW_ID_INVALID)
+