sfc: only schedule asynchronous filter work if needed
authorEdward Cree <ecree@solarflare.com>
Mon, 17 Feb 2020 13:43:10 +0000 (13:43 +0000)
committerDavid S. Miller <davem@davemloft.net>
Mon, 17 Feb 2020 22:35:23 +0000 (14:35 -0800)
Prevent excessive CPU time spent running a workitem with nothing to do.

We avoid any races by keeping the same check in efx_filter_rfs_expire().

Suggested-by: Martin Habets <mhabets@solarflare.com>
Signed-off-by: Edward Cree <ecree@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/sfc/efx.h
drivers/net/ethernet/sfc/efx_channels.c

index f1bdb04efbe4d326ebc12f7f1fd544467249825f..78babbe6d2d8ba5c623ad693d0e9c100c0ff928c 100644 (file)
@@ -159,7 +159,7 @@ static inline void efx_filter_rfs_expire(struct work_struct *data)
        channel = container_of(dwork, struct efx_channel, filter_work);
        time = jiffies - channel->rfs_last_expiry;
        quota = channel->rfs_filter_count * time / (30 * HZ);
-       if (quota > 20 && __efx_filter_rfs_expire(channel, min(channel->rfs_filter_count, quota)))
+       if (quota >= 20 && __efx_filter_rfs_expire(channel, min(channel->rfs_filter_count, quota)))
                channel->rfs_last_expiry += time;
        /* Ensure we do more work eventually even if NAPI poll is not happening */
        schedule_delayed_work(dwork, 30 * HZ);
index aeb5e8aa2f2a2ba76c679ffa41dc929aff2c0bd1..1b1265d94fc9a3527ee316797ca6d3d1a4dc0601 100644 (file)
@@ -1166,6 +1166,9 @@ static int efx_poll(struct napi_struct *napi, int budget)
        struct efx_channel *channel =
                container_of(napi, struct efx_channel, napi_str);
        struct efx_nic *efx = channel->efx;
+#ifdef CONFIG_RFS_ACCEL
+       unsigned int time;
+#endif
        int spent;
 
        netif_vdbg(efx, intr, efx->net_dev,
@@ -1185,7 +1188,10 @@ static int efx_poll(struct napi_struct *napi, int budget)
 
 #ifdef CONFIG_RFS_ACCEL
                /* Perhaps expire some ARFS filters */
-               mod_delayed_work(system_wq, &channel->filter_work, 0);
+               time = jiffies - channel->rfs_last_expiry;
+               /* Would our quota be >= 20? */
+               if (channel->rfs_filter_count * time >= 600 * HZ)
+                       mod_delayed_work(system_wq, &channel->filter_work, 0);
 #endif
 
                /* There is no race here; although napi_disable() will