aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/cisco/enic
diff options
context:
space:
mode:
authorGovindarajulu Varadarajan <_govind@gmx.com>2014-07-21 07:52:18 -0400
committerDavid S. Miller <davem@davemloft.net>2014-07-21 23:22:46 -0400
commit3762ff8f0e95f50f78d94e3f62e839103d1303aa (patch)
tree1a67ff907fb9a2ba706d692e3bc25505a689c1cb /drivers/net/ethernet/cisco/enic
parente3e5af33e6d64a36bce1dfd9f599649f539801de (diff)
enic: Add ethtool support to show classifier filters added by the driver
This patch impliments ethtool_ops->get_rxnfc() to display the classifier filter added by the driver. Signed-off-by: Govindarajulu Varadarajan <_govind@gmx.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/cisco/enic')
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_clsf.c18
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_clsf.h1
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_ethtool.c98
3 files changed, 117 insertions, 0 deletions
diff --git a/drivers/net/ethernet/cisco/enic/enic_clsf.c b/drivers/net/ethernet/cisco/enic/enic_clsf.c
index ee6acbf02ef0..69dfd3c9e529 100644
--- a/drivers/net/ethernet/cisco/enic/enic_clsf.c
+++ b/drivers/net/ethernet/cisco/enic/enic_clsf.c
@@ -103,6 +103,24 @@ void enic_rfs_flw_tbl_free(struct enic *enic)
103 spin_unlock(&enic->rfs_h.lock); 103 spin_unlock(&enic->rfs_h.lock);
104} 104}
105 105
106struct enic_rfs_fltr_node *htbl_fltr_search(struct enic *enic, u16 fltr_id)
107{
108 int i;
109
110 for (i = 0; i < (1 << ENIC_RFS_FLW_BITSHIFT); i++) {
111 struct hlist_head *hhead;
112 struct hlist_node *tmp;
113 struct enic_rfs_fltr_node *n;
114
115 hhead = &enic->rfs_h.ht_head[i];
116 hlist_for_each_entry_safe(n, tmp, hhead, node)
117 if (n->fltr_id == fltr_id)
118 return n;
119 }
120
121 return NULL;
122}
123
106#ifdef CONFIG_RFS_ACCEL 124#ifdef CONFIG_RFS_ACCEL
107void enic_flow_may_expire(unsigned long data) 125void enic_flow_may_expire(unsigned long data)
108{ 126{
diff --git a/drivers/net/ethernet/cisco/enic/enic_clsf.h b/drivers/net/ethernet/cisco/enic/enic_clsf.h
index 221f364cd811..6aa9f89d073b 100644
--- a/drivers/net/ethernet/cisco/enic/enic_clsf.h
+++ b/drivers/net/ethernet/cisco/enic/enic_clsf.h
@@ -10,6 +10,7 @@ int enic_addfltr_5t(struct enic *enic, struct flow_keys *keys, u16 rq);
10int enic_delfltr(struct enic *enic, u16 filter_id); 10int enic_delfltr(struct enic *enic, u16 filter_id);
11void enic_rfs_flw_tbl_init(struct enic *enic); 11void enic_rfs_flw_tbl_init(struct enic *enic);
12void enic_rfs_flw_tbl_free(struct enic *enic); 12void enic_rfs_flw_tbl_free(struct enic *enic);
13struct enic_rfs_fltr_node *htbl_fltr_search(struct enic *enic, u16 fltr_id);
13 14
14#ifdef CONFIG_RFS_ACCEL 15#ifdef CONFIG_RFS_ACCEL
15int enic_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb, 16int enic_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
diff --git a/drivers/net/ethernet/cisco/enic/enic_ethtool.c b/drivers/net/ethernet/cisco/enic/enic_ethtool.c
index c75f84b42751..523c9ceb04c0 100644
--- a/drivers/net/ethernet/cisco/enic/enic_ethtool.c
+++ b/drivers/net/ethernet/cisco/enic/enic_ethtool.c
@@ -22,6 +22,7 @@
22#include "enic_res.h" 22#include "enic_res.h"
23#include "enic.h" 23#include "enic.h"
24#include "enic_dev.h" 24#include "enic_dev.h"
25#include "enic_clsf.h"
25 26
26struct enic_stat { 27struct enic_stat {
27 char name[ETH_GSTRING_LEN]; 28 char name[ETH_GSTRING_LEN];
@@ -282,6 +283,102 @@ static int enic_set_coalesce(struct net_device *netdev,
282 return 0; 283 return 0;
283} 284}
284 285
286static int enic_grxclsrlall(struct enic *enic, struct ethtool_rxnfc *cmd,
287 u32 *rule_locs)
288{
289 int j, ret = 0, cnt = 0;
290
291 cmd->data = enic->rfs_h.max - enic->rfs_h.free;
292 for (j = 0; j < (1 << ENIC_RFS_FLW_BITSHIFT); j++) {
293 struct hlist_head *hhead;
294 struct hlist_node *tmp;
295 struct enic_rfs_fltr_node *n;
296
297 hhead = &enic->rfs_h.ht_head[j];
298 hlist_for_each_entry_safe(n, tmp, hhead, node) {
299 if (cnt == cmd->rule_cnt)
300 return -EMSGSIZE;
301 rule_locs[cnt] = n->fltr_id;
302 cnt++;
303 }
304 }
305 cmd->rule_cnt = cnt;
306
307 return ret;
308}
309
310static int enic_grxclsrule(struct enic *enic, struct ethtool_rxnfc *cmd)
311{
312 struct ethtool_rx_flow_spec *fsp =
313 (struct ethtool_rx_flow_spec *)&cmd->fs;
314 struct enic_rfs_fltr_node *n;
315
316 n = htbl_fltr_search(enic, (u16)fsp->location);
317 if (!n)
318 return -EINVAL;
319 switch (n->keys.ip_proto) {
320 case IPPROTO_TCP:
321 fsp->flow_type = TCP_V4_FLOW;
322 break;
323 case IPPROTO_UDP:
324 fsp->flow_type = UDP_V4_FLOW;
325 break;
326 default:
327 return -EINVAL;
328 break;
329 }
330
331 fsp->h_u.tcp_ip4_spec.ip4src = n->keys.src;
332 fsp->m_u.tcp_ip4_spec.ip4src = (__u32)~0;
333
334 fsp->h_u.tcp_ip4_spec.ip4dst = n->keys.dst;
335 fsp->m_u.tcp_ip4_spec.ip4dst = (__u32)~0;
336
337 fsp->h_u.tcp_ip4_spec.psrc = n->keys.port16[0];
338 fsp->m_u.tcp_ip4_spec.psrc = (__u16)~0;
339
340 fsp->h_u.tcp_ip4_spec.pdst = n->keys.port16[1];
341 fsp->m_u.tcp_ip4_spec.pdst = (__u16)~0;
342
343 fsp->ring_cookie = n->rq_id;
344
345 return 0;
346}
347
348static int enic_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
349 u32 *rule_locs)
350{
351 struct enic *enic = netdev_priv(dev);
352 int ret = 0;
353
354 switch (cmd->cmd) {
355 case ETHTOOL_GRXRINGS:
356 cmd->data = enic->rq_count;
357 break;
358 case ETHTOOL_GRXCLSRLCNT:
359 spin_lock_bh(&enic->rfs_h.lock);
360 cmd->rule_cnt = enic->rfs_h.max - enic->rfs_h.free;
361 cmd->data = enic->rfs_h.max;
362 spin_unlock_bh(&enic->rfs_h.lock);
363 break;
364 case ETHTOOL_GRXCLSRLALL:
365 spin_lock_bh(&enic->rfs_h.lock);
366 ret = enic_grxclsrlall(enic, cmd, rule_locs);
367 spin_unlock_bh(&enic->rfs_h.lock);
368 break;
369 case ETHTOOL_GRXCLSRULE:
370 spin_lock_bh(&enic->rfs_h.lock);
371 ret = enic_grxclsrule(enic, cmd);
372 spin_unlock_bh(&enic->rfs_h.lock);
373 break;
374 default:
375 ret = -EOPNOTSUPP;
376 break;
377 }
378
379 return ret;
380}
381
285static const struct ethtool_ops enic_ethtool_ops = { 382static const struct ethtool_ops enic_ethtool_ops = {
286 .get_settings = enic_get_settings, 383 .get_settings = enic_get_settings,
287 .get_drvinfo = enic_get_drvinfo, 384 .get_drvinfo = enic_get_drvinfo,
@@ -293,6 +390,7 @@ static const struct ethtool_ops enic_ethtool_ops = {
293 .get_ethtool_stats = enic_get_ethtool_stats, 390 .get_ethtool_stats = enic_get_ethtool_stats,
294 .get_coalesce = enic_get_coalesce, 391 .get_coalesce = enic_get_coalesce,
295 .set_coalesce = enic_set_coalesce, 392 .set_coalesce = enic_set_coalesce,
393 .get_rxnfc = enic_get_rxnfc,
296}; 394};
297 395
298void enic_set_ethtool_ops(struct net_device *netdev) 396void enic_set_ethtool_ops(struct net_device *netdev)