Commit c4bad432 authored by Edward Cree's avatar Edward Cree Committed by David S. Miller

sfc: accumulate MAE counter values from update packets

Add the packet and byte counts to the software running total, and store
 the latest jiffies every time the counter is bumped.
Signed-off-by: default avatarEdward Cree <ecree.xilinx@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0363aa29
......@@ -86,6 +86,8 @@ static struct efx_tc_counter *efx_tc_flower_allocate_counter(struct efx_nic *efx
if (!cnt)
return ERR_PTR(-ENOMEM);
spin_lock_init(&cnt->lock);
cnt->touched = jiffies;
cnt->type = type;
rc = efx_mae_allocate_counter(efx, cnt);
......@@ -131,9 +133,22 @@ static void efx_tc_flower_release_counter(struct efx_nic *efx,
* is handled by the generation count.
*/
synchronize_rcu();
EFX_WARN_ON_PARANOID(spin_is_locked(&cnt->lock));
kfree(cnt);
}
static struct efx_tc_counter *efx_tc_flower_find_counter_by_fw_id(
struct efx_nic *efx, int type, u32 fw_id)
{
struct efx_tc_counter key = {};
key.fw_id = fw_id;
key.type = type;
return rhashtable_lookup_fast(&efx->tc->counter_ht, &key,
efx_tc_counter_ht_params);
}
/* TC cookie to counter mapping */
void efx_tc_flower_put_counter_index(struct efx_nic *efx,
......@@ -241,7 +256,44 @@ static void efx_tc_counter_update(struct efx_nic *efx,
u32 counter_idx, u64 packets, u64 bytes,
u32 mark)
{
/* Software counter objects do not exist yet, for now we ignore this */
struct efx_tc_counter *cnt;
rcu_read_lock(); /* Protect against deletion of 'cnt' */
cnt = efx_tc_flower_find_counter_by_fw_id(efx, counter_type, counter_idx);
if (!cnt) {
/* This can legitimately happen when a counter is removed,
* with updates for the counter still in-flight; however this
* should be an infrequent occurrence.
*/
if (net_ratelimit())
netif_dbg(efx, drv, efx->net_dev,
"Got update for unwanted MAE counter %u type %u\n",
counter_idx, counter_type);
goto out;
}
spin_lock_bh(&cnt->lock);
if ((s32)mark - (s32)cnt->gen < 0) {
/* This counter update packet is from before the counter was
* allocated; thus it must be for a previous counter with
* the same ID that has since been freed, and it should be
* ignored.
*/
} else {
/* Update latest seen generation count. This ensures that
* even a long-lived counter won't start getting ignored if
* the generation count wraps around, unless it somehow
* manages to go 1<<31 generations without an update.
*/
cnt->gen = mark;
/* update counter values */
cnt->packets += packets;
cnt->bytes += bytes;
cnt->touched = jiffies;
}
spin_unlock_bh(&cnt->lock);
out:
rcu_read_unlock();
}
static void efx_tc_rx_version_1(struct efx_nic *efx, const u8 *data, u32 mark)
......
......@@ -26,7 +26,11 @@ struct efx_tc_counter {
u32 fw_id; /* index in firmware counter table */
enum efx_tc_counter_type type;
struct rhash_head linkage; /* efx->tc->counter_ht */
spinlock_t lock; /* Serialises updates to counter values */
u32 gen; /* Generation count at which this counter is current */
u64 packets, bytes;
/* jiffies of the last time we saw packets increase */
unsigned long touched;
};
struct efx_tc_counter_index {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment