aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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