aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ixgbe
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@intel.com>2011-05-11 03:18:52 -0400
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2011-06-24 01:45:24 -0400
commite4911d57a45ca30771c64b56e552891fcd105070 (patch)
treef95707c425248e8528a5b4c8c246a528b85d681e /drivers/net/ixgbe
parent3e05334f8be83e8529f1cbf4f4dea06a4d51d676 (diff)
ixgbe: add support for nfc addition and removal of filters
This change is meant to allow for nfc to insert and remove filters in order to test the ethtool interface which includes it's own rules manager. Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Tested-by: Ross Brattain <ross.b.brattain@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ixgbe')
-rw-r--r--drivers/net/ixgbe/ixgbe_ethtool.c245
-rw-r--r--drivers/net/ixgbe/ixgbe_main.c45
2 files changed, 290 insertions, 0 deletions
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index 649e5960f249..2965b6e7728b 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -2456,6 +2456,250 @@ static int ixgbe_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
2456 return ret; 2456 return ret;
2457} 2457}
2458 2458
2459static int ixgbe_update_ethtool_fdir_entry(struct ixgbe_adapter *adapter,
2460 struct ixgbe_fdir_filter *input,
2461 u16 sw_idx)
2462{
2463 struct ixgbe_hw *hw = &adapter->hw;
2464 struct hlist_node *node, *node2, *parent;
2465 struct ixgbe_fdir_filter *rule;
2466 int err = -EINVAL;
2467
2468 parent = NULL;
2469 rule = NULL;
2470
2471 hlist_for_each_entry_safe(rule, node, node2,
2472 &adapter->fdir_filter_list, fdir_node) {
2473 /* hash found, or no matching entry */
2474 if (rule->sw_idx >= sw_idx)
2475 break;
2476 parent = node;
2477 }
2478
2479 /* if there is an old rule occupying our place remove it */
2480 if (rule && (rule->sw_idx == sw_idx)) {
2481 if (!input || (rule->filter.formatted.bkt_hash !=
2482 input->filter.formatted.bkt_hash)) {
2483 err = ixgbe_fdir_erase_perfect_filter_82599(hw,
2484 &rule->filter,
2485 sw_idx);
2486 }
2487
2488 hlist_del(&rule->fdir_node);
2489 kfree(rule);
2490 adapter->fdir_filter_count--;
2491 }
2492
2493 /*
2494 * If no input this was a delete, err should be 0 if a rule was
2495 * successfully found and removed from the list else -EINVAL
2496 */
2497 if (!input)
2498 return err;
2499
2500 /* initialize node and set software index */
2501 INIT_HLIST_NODE(&input->fdir_node);
2502
2503 /* add filter to the list */
2504 if (parent)
2505 hlist_add_after(parent, &input->fdir_node);
2506 else
2507 hlist_add_head(&input->fdir_node,
2508 &adapter->fdir_filter_list);
2509
2510 /* update counts */
2511 adapter->fdir_filter_count++;
2512
2513 return 0;
2514}
2515
2516static int ixgbe_flowspec_to_flow_type(struct ethtool_rx_flow_spec *fsp,
2517 u8 *flow_type)
2518{
2519 switch (fsp->flow_type & ~FLOW_EXT) {
2520 case TCP_V4_FLOW:
2521 *flow_type = IXGBE_ATR_FLOW_TYPE_TCPV4;
2522 break;
2523 case UDP_V4_FLOW:
2524 *flow_type = IXGBE_ATR_FLOW_TYPE_UDPV4;
2525 break;
2526 case SCTP_V4_FLOW:
2527 *flow_type = IXGBE_ATR_FLOW_TYPE_SCTPV4;
2528 break;
2529 case IP_USER_FLOW:
2530 switch (fsp->h_u.usr_ip4_spec.proto) {
2531 case IPPROTO_TCP:
2532 *flow_type = IXGBE_ATR_FLOW_TYPE_TCPV4;
2533 break;
2534 case IPPROTO_UDP:
2535 *flow_type = IXGBE_ATR_FLOW_TYPE_UDPV4;
2536 break;
2537 case IPPROTO_SCTP:
2538 *flow_type = IXGBE_ATR_FLOW_TYPE_SCTPV4;
2539 break;
2540 case 0:
2541 if (!fsp->m_u.usr_ip4_spec.proto) {
2542 *flow_type = IXGBE_ATR_FLOW_TYPE_IPV4;
2543 break;
2544 }
2545 default:
2546 return 0;
2547 }
2548 break;
2549 default:
2550 return 0;
2551 }
2552
2553 return 1;
2554}
2555
2556static int ixgbe_add_ethtool_fdir_entry(struct ixgbe_adapter *adapter,
2557 struct ethtool_rxnfc *cmd)
2558{
2559 struct ethtool_rx_flow_spec *fsp =
2560 (struct ethtool_rx_flow_spec *)&cmd->fs;
2561 struct ixgbe_hw *hw = &adapter->hw;
2562 struct ixgbe_fdir_filter *input;
2563 union ixgbe_atr_input mask;
2564 int err;
2565
2566 if (!(adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))
2567 return -EOPNOTSUPP;
2568
2569 /*
2570 * Don't allow programming if the action is a queue greater than
2571 * the number of online Rx queues.
2572 */
2573 if ((fsp->ring_cookie != RX_CLS_FLOW_DISC) &&
2574 (fsp->ring_cookie >= adapter->num_rx_queues))
2575 return -EINVAL;
2576
2577 /* Don't allow indexes to exist outside of available space */
2578 if (fsp->location >= ((1024 << adapter->fdir_pballoc) - 2)) {
2579 e_err(drv, "Location out of range\n");
2580 return -EINVAL;
2581 }
2582
2583 input = kzalloc(sizeof(*input), GFP_ATOMIC);
2584 if (!input)
2585 return -ENOMEM;
2586
2587 memset(&mask, 0, sizeof(union ixgbe_atr_input));
2588
2589 /* set SW index */
2590 input->sw_idx = fsp->location;
2591
2592 /* record flow type */
2593 if (!ixgbe_flowspec_to_flow_type(fsp,
2594 &input->filter.formatted.flow_type)) {
2595 e_err(drv, "Unrecognized flow type\n");
2596 goto err_out;
2597 }
2598
2599 mask.formatted.flow_type = IXGBE_ATR_L4TYPE_IPV6_MASK |
2600 IXGBE_ATR_L4TYPE_MASK;
2601
2602 if (input->filter.formatted.flow_type == IXGBE_ATR_FLOW_TYPE_IPV4)
2603 mask.formatted.flow_type &= IXGBE_ATR_L4TYPE_IPV6_MASK;
2604
2605 /* Copy input into formatted structures */
2606 input->filter.formatted.src_ip[0] = fsp->h_u.tcp_ip4_spec.ip4src;
2607 mask.formatted.src_ip[0] = fsp->m_u.tcp_ip4_spec.ip4src;
2608 input->filter.formatted.dst_ip[0] = fsp->h_u.tcp_ip4_spec.ip4dst;
2609 mask.formatted.dst_ip[0] = fsp->m_u.tcp_ip4_spec.ip4dst;
2610 input->filter.formatted.src_port = fsp->h_u.tcp_ip4_spec.psrc;
2611 mask.formatted.src_port = fsp->m_u.tcp_ip4_spec.psrc;
2612 input->filter.formatted.dst_port = fsp->h_u.tcp_ip4_spec.pdst;
2613 mask.formatted.dst_port = fsp->m_u.tcp_ip4_spec.pdst;
2614
2615 if (fsp->flow_type & FLOW_EXT) {
2616 input->filter.formatted.vm_pool =
2617 (unsigned char)ntohl(fsp->h_ext.data[1]);
2618 mask.formatted.vm_pool =
2619 (unsigned char)ntohl(fsp->m_ext.data[1]);
2620 input->filter.formatted.vlan_id = fsp->h_ext.vlan_tci;
2621 mask.formatted.vlan_id = fsp->m_ext.vlan_tci;
2622 input->filter.formatted.flex_bytes =
2623 fsp->h_ext.vlan_etype;
2624 mask.formatted.flex_bytes = fsp->m_ext.vlan_etype;
2625 }
2626
2627 /* determine if we need to drop or route the packet */
2628 if (fsp->ring_cookie == RX_CLS_FLOW_DISC)
2629 input->action = IXGBE_FDIR_DROP_QUEUE;
2630 else
2631 input->action = fsp->ring_cookie;
2632
2633 spin_lock(&adapter->fdir_perfect_lock);
2634
2635 if (hlist_empty(&adapter->fdir_filter_list)) {
2636 /* save mask and program input mask into HW */
2637 memcpy(&adapter->fdir_mask, &mask, sizeof(mask));
2638 err = ixgbe_fdir_set_input_mask_82599(hw, &mask);
2639 if (err) {
2640 e_err(drv, "Error writing mask\n");
2641 goto err_out_w_lock;
2642 }
2643 } else if (memcmp(&adapter->fdir_mask, &mask, sizeof(mask))) {
2644 e_err(drv, "Only one mask supported per port\n");
2645 goto err_out_w_lock;
2646 }
2647
2648 /* apply mask and compute/store hash */
2649 ixgbe_atr_compute_perfect_hash_82599(&input->filter, &mask);
2650
2651 /* program filters to filter memory */
2652 err = ixgbe_fdir_write_perfect_filter_82599(hw,
2653 &input->filter, input->sw_idx,
2654 adapter->rx_ring[input->action]->reg_idx);
2655 if (err)
2656 goto err_out_w_lock;
2657
2658 ixgbe_update_ethtool_fdir_entry(adapter, input, input->sw_idx);
2659
2660 spin_unlock(&adapter->fdir_perfect_lock);
2661
2662 return err;
2663err_out_w_lock:
2664 spin_unlock(&adapter->fdir_perfect_lock);
2665err_out:
2666 kfree(input);
2667 return -EINVAL;
2668}
2669
2670static int ixgbe_del_ethtool_fdir_entry(struct ixgbe_adapter *adapter,
2671 struct ethtool_rxnfc *cmd)
2672{
2673 struct ethtool_rx_flow_spec *fsp =
2674 (struct ethtool_rx_flow_spec *)&cmd->fs;
2675 int err;
2676
2677 spin_lock(&adapter->fdir_perfect_lock);
2678 err = ixgbe_update_ethtool_fdir_entry(adapter, NULL, fsp->location);
2679 spin_unlock(&adapter->fdir_perfect_lock);
2680
2681 return err;
2682}
2683
2684static int ixgbe_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
2685{
2686 struct ixgbe_adapter *adapter = netdev_priv(dev);
2687 int ret = -EOPNOTSUPP;
2688
2689 switch (cmd->cmd) {
2690 case ETHTOOL_SRXCLSRLINS:
2691 ret = ixgbe_add_ethtool_fdir_entry(adapter, cmd);
2692 break;
2693 case ETHTOOL_SRXCLSRLDEL:
2694 ret = ixgbe_del_ethtool_fdir_entry(adapter, cmd);
2695 break;
2696 default:
2697 break;
2698 }
2699
2700 return ret;
2701}
2702
2459static const struct ethtool_ops ixgbe_ethtool_ops = { 2703static const struct ethtool_ops ixgbe_ethtool_ops = {
2460 .get_settings = ixgbe_get_settings, 2704 .get_settings = ixgbe_get_settings,
2461 .set_settings = ixgbe_set_settings, 2705 .set_settings = ixgbe_set_settings,
@@ -2492,6 +2736,7 @@ static const struct ethtool_ops ixgbe_ethtool_ops = {
2492 .get_flags = ethtool_op_get_flags, 2736 .get_flags = ethtool_op_get_flags,
2493 .set_flags = ixgbe_set_flags, 2737 .set_flags = ixgbe_set_flags,
2494 .get_rxnfc = ixgbe_get_rxnfc, 2738 .get_rxnfc = ixgbe_get_rxnfc,
2739 .set_rxnfc = ixgbe_set_rxnfc,
2495}; 2740};
2496 2741
2497void ixgbe_set_ethtool_ops(struct net_device *netdev) 2742void ixgbe_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index e177b5d061fe..2886daec70ae 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -3741,6 +3741,28 @@ static void ixgbe_configure_pb(struct ixgbe_adapter *adapter)
3741 hw->mac.ops.set_rxpba(&adapter->hw, num_tc, hdrm, PBA_STRATEGY_EQUAL); 3741 hw->mac.ops.set_rxpba(&adapter->hw, num_tc, hdrm, PBA_STRATEGY_EQUAL);
3742} 3742}
3743 3743
3744static void ixgbe_fdir_filter_restore(struct ixgbe_adapter *adapter)
3745{
3746 struct ixgbe_hw *hw = &adapter->hw;
3747 struct hlist_node *node, *node2;
3748 struct ixgbe_fdir_filter *filter;
3749
3750 spin_lock(&adapter->fdir_perfect_lock);
3751
3752 if (!hlist_empty(&adapter->fdir_filter_list))
3753 ixgbe_fdir_set_input_mask_82599(hw, &adapter->fdir_mask);
3754
3755 hlist_for_each_entry_safe(filter, node, node2,
3756 &adapter->fdir_filter_list, fdir_node) {
3757 ixgbe_fdir_write_perfect_filter_82599(hw,
3758 &filter->filter,
3759 filter->sw_idx,
3760 filter->action);
3761 }
3762
3763 spin_unlock(&adapter->fdir_perfect_lock);
3764}
3765
3744static void ixgbe_configure(struct ixgbe_adapter *adapter) 3766static void ixgbe_configure(struct ixgbe_adapter *adapter)
3745{ 3767{
3746 struct net_device *netdev = adapter->netdev; 3768 struct net_device *netdev = adapter->netdev;
@@ -3765,6 +3787,10 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter)
3765 adapter->tx_ring[i]->atr_sample_rate = 3787 adapter->tx_ring[i]->atr_sample_rate =
3766 adapter->atr_sample_rate; 3788 adapter->atr_sample_rate;
3767 ixgbe_init_fdir_signature_82599(hw, adapter->fdir_pballoc); 3789 ixgbe_init_fdir_signature_82599(hw, adapter->fdir_pballoc);
3790 } else if (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) {
3791 ixgbe_init_fdir_perfect_82599(&adapter->hw,
3792 adapter->fdir_pballoc);
3793 ixgbe_fdir_filter_restore(adapter);
3768 } 3794 }
3769 ixgbe_configure_virtualization(adapter); 3795 ixgbe_configure_virtualization(adapter);
3770 3796
@@ -4141,6 +4167,23 @@ static void ixgbe_clean_all_tx_rings(struct ixgbe_adapter *adapter)
4141 ixgbe_clean_tx_ring(adapter->tx_ring[i]); 4167 ixgbe_clean_tx_ring(adapter->tx_ring[i]);
4142} 4168}
4143 4169
4170static void ixgbe_fdir_filter_exit(struct ixgbe_adapter *adapter)
4171{
4172 struct hlist_node *node, *node2;
4173 struct ixgbe_fdir_filter *filter;
4174
4175 spin_lock(&adapter->fdir_perfect_lock);
4176
4177 hlist_for_each_entry_safe(filter, node, node2,
4178 &adapter->fdir_filter_list, fdir_node) {
4179 hlist_del(&filter->fdir_node);
4180 kfree(filter);
4181 }
4182 adapter->fdir_filter_count = 0;
4183
4184 spin_unlock(&adapter->fdir_perfect_lock);
4185}
4186
4144void ixgbe_down(struct ixgbe_adapter *adapter) 4187void ixgbe_down(struct ixgbe_adapter *adapter)
4145{ 4188{
4146 struct net_device *netdev = adapter->netdev; 4189 struct net_device *netdev = adapter->netdev;
@@ -5527,6 +5570,8 @@ static int ixgbe_close(struct net_device *netdev)
5527 ixgbe_down(adapter); 5570 ixgbe_down(adapter);
5528 ixgbe_free_irq(adapter); 5571 ixgbe_free_irq(adapter);
5529 5572
5573 ixgbe_fdir_filter_exit(adapter);
5574
5530 ixgbe_free_all_tx_resources(adapter); 5575 ixgbe_free_all_tx_resources(adapter);
5531 ixgbe_free_all_rx_resources(adapter); 5576 ixgbe_free_all_rx_resources(adapter);
5532 5577