diff options
author | Govindarajulu Varadarajan <_govind@gmx.com> | 2014-07-21 07:52:18 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-07-21 23:22:46 -0400 |
commit | 3762ff8f0e95f50f78d94e3f62e839103d1303aa (patch) | |
tree | 1a67ff907fb9a2ba706d692e3bc25505a689c1cb /drivers/net/ethernet/cisco/enic | |
parent | e3e5af33e6d64a36bce1dfd9f599649f539801de (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.c | 18 | ||||
-rw-r--r-- | drivers/net/ethernet/cisco/enic/enic_clsf.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/cisco/enic/enic_ethtool.c | 98 |
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 | ||
106 | struct 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 |
107 | void enic_flow_may_expire(unsigned long data) | 125 | void 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); | |||
10 | int enic_delfltr(struct enic *enic, u16 filter_id); | 10 | int enic_delfltr(struct enic *enic, u16 filter_id); |
11 | void enic_rfs_flw_tbl_init(struct enic *enic); | 11 | void enic_rfs_flw_tbl_init(struct enic *enic); |
12 | void enic_rfs_flw_tbl_free(struct enic *enic); | 12 | void enic_rfs_flw_tbl_free(struct enic *enic); |
13 | struct 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 |
15 | int enic_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb, | 16 | int 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 | ||
26 | struct enic_stat { | 27 | struct 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 | ||
286 | static 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 | |||
310 | static 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 | |||
348 | static 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 | |||
285 | static const struct ethtool_ops enic_ethtool_ops = { | 382 | static 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 | ||
298 | void enic_set_ethtool_ops(struct net_device *netdev) | 396 | void enic_set_ethtool_ops(struct net_device *netdev) |