Skip to content

Commit e0f911c

Browse files
Kumar Sanghvidavem330
authored andcommitted
cxgb4: fetch stats for offloaded tc flower flows
Add support to retrieve stats from hardware for offloaded tc flower flows. Also, poll for the stats of offloaded flows via timer callback. Signed-off-by: Kumar Sanghvi <kumaras@chelsio.com> Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com> Signed-off-by: Ganesh Goudar <ganeshgr@chelsio.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent cf2885a commit e0f911c

File tree

6 files changed

+161
-1
lines changed

6 files changed

+161
-1
lines changed

drivers/net/ethernet/chelsio/cxgb4/cxgb4.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,7 @@ struct adapter {
908908

909909
/* TC flower offload */
910910
DECLARE_HASHTABLE(flower_anymatch_tbl, 9);
911+
struct timer_list flower_stats_timer;
911912
};
912913

913914
/* Support for "sched-class" command to allow a TX Scheduling Class to be

drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,82 @@ static int get_filter_steerq(struct net_device *dev,
148148
return iq;
149149
}
150150

151+
static int get_filter_count(struct adapter *adapter, unsigned int fidx,
152+
u64 *pkts, u64 *bytes)
153+
{
154+
unsigned int tcb_base, tcbaddr;
155+
unsigned int word_offset;
156+
struct filter_entry *f;
157+
__be64 be64_byte_count;
158+
int ret;
159+
160+
tcb_base = t4_read_reg(adapter, TP_CMM_TCB_BASE_A);
161+
if ((fidx != (adapter->tids.nftids + adapter->tids.nsftids - 1)) &&
162+
fidx >= adapter->tids.nftids)
163+
return -E2BIG;
164+
165+
f = &adapter->tids.ftid_tab[fidx];
166+
if (!f->valid)
167+
return -EINVAL;
168+
169+
tcbaddr = tcb_base + f->tid * TCB_SIZE;
170+
171+
spin_lock(&adapter->win0_lock);
172+
if (is_t4(adapter->params.chip)) {
173+
__be64 be64_count;
174+
175+
/* T4 doesn't maintain byte counts in hw */
176+
*bytes = 0;
177+
178+
/* Get pkts */
179+
word_offset = 4;
180+
ret = t4_memory_rw(adapter, MEMWIN_NIC, MEM_EDC0,
181+
tcbaddr + (word_offset * sizeof(__be32)),
182+
sizeof(be64_count),
183+
(__be32 *)&be64_count,
184+
T4_MEMORY_READ);
185+
if (ret < 0)
186+
goto out;
187+
*pkts = be64_to_cpu(be64_count);
188+
} else {
189+
__be32 be32_count;
190+
191+
/* Get bytes */
192+
word_offset = 4;
193+
ret = t4_memory_rw(adapter, MEMWIN_NIC, MEM_EDC0,
194+
tcbaddr + (word_offset * sizeof(__be32)),
195+
sizeof(be64_byte_count),
196+
&be64_byte_count,
197+
T4_MEMORY_READ);
198+
if (ret < 0)
199+
goto out;
200+
*bytes = be64_to_cpu(be64_byte_count);
201+
202+
/* Get pkts */
203+
word_offset = 6;
204+
ret = t4_memory_rw(adapter, MEMWIN_NIC, MEM_EDC0,
205+
tcbaddr + (word_offset * sizeof(__be32)),
206+
sizeof(be32_count),
207+
&be32_count,
208+
T4_MEMORY_READ);
209+
if (ret < 0)
210+
goto out;
211+
*pkts = (u64)be32_to_cpu(be32_count);
212+
}
213+
214+
out:
215+
spin_unlock(&adapter->win0_lock);
216+
return ret;
217+
}
218+
219+
int cxgb4_get_filter_counters(struct net_device *dev, unsigned int fidx,
220+
u64 *hitcnt, u64 *bytecnt)
221+
{
222+
struct adapter *adapter = netdev2adap(dev);
223+
224+
return get_filter_count(adapter, fidx, hitcnt, bytecnt);
225+
}
226+
151227
int cxgb4_get_free_ftid(struct net_device *dev, int family)
152228
{
153229
struct adapter *adap = netdev2adap(dev);

drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4637,6 +4637,7 @@ static void free_some_resources(struct adapter *adapter)
46374637
kvfree(adapter->l2t);
46384638
t4_cleanup_sched(adapter);
46394639
kvfree(adapter->tids.tid_tab);
4640+
cxgb4_cleanup_tc_flower(adapter);
46404641
cxgb4_cleanup_tc_u32(adapter);
46414642
kfree(adapter->sge.egr_map);
46424643
kfree(adapter->sge.ingr_map);

drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,12 @@
3939
#include "cxgb4.h"
4040
#include "cxgb4_tc_flower.h"
4141

42+
#define STATS_CHECK_PERIOD (HZ / 2)
43+
4244
static struct ch_tc_flower_entry *allocate_flower_entry(void)
4345
{
4446
struct ch_tc_flower_entry *new = kzalloc(sizeof(*new), GFP_KERNEL);
47+
spin_lock_init(&new->lock);
4548
return new;
4649
}
4750

@@ -363,13 +366,87 @@ int cxgb4_tc_flower_destroy(struct net_device *dev,
363366
return ret;
364367
}
365368

369+
void ch_flower_stats_cb(unsigned long data)
370+
{
371+
struct adapter *adap = (struct adapter *)data;
372+
struct ch_tc_flower_entry *flower_entry;
373+
struct ch_tc_flower_stats *ofld_stats;
374+
unsigned int i;
375+
u64 packets;
376+
u64 bytes;
377+
int ret;
378+
379+
rcu_read_lock();
380+
hash_for_each_rcu(adap->flower_anymatch_tbl, i, flower_entry, link) {
381+
ret = cxgb4_get_filter_counters(adap->port[0],
382+
flower_entry->filter_id,
383+
&packets, &bytes);
384+
if (!ret) {
385+
spin_lock(&flower_entry->lock);
386+
ofld_stats = &flower_entry->stats;
387+
388+
if (ofld_stats->prev_packet_count != packets) {
389+
ofld_stats->prev_packet_count = packets;
390+
ofld_stats->last_used = jiffies;
391+
}
392+
spin_unlock(&flower_entry->lock);
393+
}
394+
}
395+
rcu_read_unlock();
396+
mod_timer(&adap->flower_stats_timer, jiffies + STATS_CHECK_PERIOD);
397+
}
398+
366399
int cxgb4_tc_flower_stats(struct net_device *dev,
367400
struct tc_cls_flower_offload *cls)
368401
{
369-
return -EOPNOTSUPP;
402+
struct adapter *adap = netdev2adap(dev);
403+
struct ch_tc_flower_stats *ofld_stats;
404+
struct ch_tc_flower_entry *ch_flower;
405+
u64 packets;
406+
u64 bytes;
407+
int ret;
408+
409+
ch_flower = ch_flower_lookup(adap, cls->cookie);
410+
if (!ch_flower) {
411+
ret = -ENOENT;
412+
goto err;
413+
}
414+
415+
ret = cxgb4_get_filter_counters(dev, ch_flower->filter_id,
416+
&packets, &bytes);
417+
if (ret < 0)
418+
goto err;
419+
420+
spin_lock_bh(&ch_flower->lock);
421+
ofld_stats = &ch_flower->stats;
422+
if (ofld_stats->packet_count != packets) {
423+
if (ofld_stats->prev_packet_count != packets)
424+
ofld_stats->last_used = jiffies;
425+
tcf_exts_stats_update(cls->exts, bytes - ofld_stats->byte_count,
426+
packets - ofld_stats->packet_count,
427+
ofld_stats->last_used);
428+
429+
ofld_stats->packet_count = packets;
430+
ofld_stats->byte_count = bytes;
431+
ofld_stats->prev_packet_count = packets;
432+
}
433+
spin_unlock_bh(&ch_flower->lock);
434+
return 0;
435+
436+
err:
437+
return ret;
370438
}
371439

372440
void cxgb4_init_tc_flower(struct adapter *adap)
373441
{
374442
hash_init(adap->flower_anymatch_tbl);
443+
setup_timer(&adap->flower_stats_timer, ch_flower_stats_cb,
444+
(unsigned long)adap);
445+
mod_timer(&adap->flower_stats_timer, jiffies + STATS_CHECK_PERIOD);
446+
}
447+
448+
void cxgb4_cleanup_tc_flower(struct adapter *adap)
449+
{
450+
if (adap->flower_stats_timer.function)
451+
del_timer_sync(&adap->flower_stats_timer);
375452
}

drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include <net/pkt_cls.h>
3939

4040
struct ch_tc_flower_stats {
41+
u64 prev_packet_count;
4142
u64 packet_count;
4243
u64 byte_count;
4344
u64 last_used;
@@ -49,6 +50,7 @@ struct ch_tc_flower_entry {
4950
unsigned long tc_flower_cookie;
5051
struct hlist_node link;
5152
struct rcu_head rcu;
53+
spinlock_t lock; /* lock for stats */
5254
u32 filter_id;
5355
};
5456

@@ -60,4 +62,5 @@ int cxgb4_tc_flower_stats(struct net_device *dev,
6062
struct tc_cls_flower_offload *cls);
6163

6264
void cxgb4_init_tc_flower(struct adapter *adap);
65+
void cxgb4_cleanup_tc_flower(struct adapter *adap);
6366
#endif /* __CXGB4_TC_FLOWER_H */

drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,8 @@ int __cxgb4_del_filter(struct net_device *dev, int filter_id,
221221
int cxgb4_set_filter(struct net_device *dev, int filter_id,
222222
struct ch_filter_specification *fs);
223223
int cxgb4_del_filter(struct net_device *dev, int filter_id);
224+
int cxgb4_get_filter_counters(struct net_device *dev, unsigned int fidx,
225+
u64 *hitcnt, u64 *bytecnt);
224226

225227
static inline void set_wr_txq(struct sk_buff *skb, int prio, int queue)
226228
{

0 commit comments

Comments
 (0)