aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/intel/igc/igc_ethtool.c
diff options
context:
space:
mode:
authorSasha Neftin <sasha.neftin@intel.com>2019-02-14 06:31:37 -0500
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2019-03-19 17:45:23 -0400
commit6245c8483ae0110d2eb7e7cd2922dba1a5fce720 (patch)
tree0780b1b6fdfe6a01d5722bee77e039b83bf93c9a /drivers/net/ethernet/intel/igc/igc_ethtool.c
parent2121c2712f8249e4d2555a4c989e4666aba34031 (diff)
igc: Extend the ethtool supporting
Add show and configure network flow classification (NFC) methods to the ethtool. Show the specifies Rx ntuple filters. Configures receive network flow classification option or rules. Signed-off-by: Sasha Neftin <sasha.neftin@intel.com> Tested-by: Aaron Brown <aaron.f.brown@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel/igc/igc_ethtool.c')
-rw-r--r--drivers/net/ethernet/intel/igc/igc_ethtool.c602
1 files changed, 602 insertions, 0 deletions
diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c
index eff37a6c0afa..25d14fc82bf8 100644
--- a/drivers/net/ethernet/intel/igc/igc_ethtool.c
+++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c
@@ -2,6 +2,7 @@
2/* Copyright (c) 2018 Intel Corporation */ 2/* Copyright (c) 2018 Intel Corporation */
3 3
4/* ethtool support for igc */ 4/* ethtool support for igc */
5#include <linux/if_vlan.h>
5#include <linux/pm_runtime.h> 6#include <linux/pm_runtime.h>
6 7
7#include "igc.h" 8#include "igc.h"
@@ -643,6 +644,605 @@ static int igc_set_coalesce(struct net_device *netdev,
643 return 0; 644 return 0;
644} 645}
645 646
647#define ETHER_TYPE_FULL_MASK ((__force __be16)~0)
648static int igc_get_ethtool_nfc_entry(struct igc_adapter *adapter,
649 struct ethtool_rxnfc *cmd)
650{
651 struct ethtool_rx_flow_spec *fsp = &cmd->fs;
652 struct igc_nfc_filter *rule = NULL;
653
654 /* report total rule count */
655 cmd->data = IGC_MAX_RXNFC_FILTERS;
656
657 hlist_for_each_entry(rule, &adapter->nfc_filter_list, nfc_node) {
658 if (fsp->location <= rule->sw_idx)
659 break;
660 }
661
662 if (!rule || fsp->location != rule->sw_idx)
663 return -EINVAL;
664
665 if (rule->filter.match_flags) {
666 fsp->flow_type = ETHER_FLOW;
667 fsp->ring_cookie = rule->action;
668 if (rule->filter.match_flags & IGC_FILTER_FLAG_ETHER_TYPE) {
669 fsp->h_u.ether_spec.h_proto = rule->filter.etype;
670 fsp->m_u.ether_spec.h_proto = ETHER_TYPE_FULL_MASK;
671 }
672 if (rule->filter.match_flags & IGC_FILTER_FLAG_VLAN_TCI) {
673 fsp->flow_type |= FLOW_EXT;
674 fsp->h_ext.vlan_tci = rule->filter.vlan_tci;
675 fsp->m_ext.vlan_tci = htons(VLAN_PRIO_MASK);
676 }
677 if (rule->filter.match_flags & IGC_FILTER_FLAG_DST_MAC_ADDR) {
678 ether_addr_copy(fsp->h_u.ether_spec.h_dest,
679 rule->filter.dst_addr);
680 /* As we only support matching by the full
681 * mask, return the mask to userspace
682 */
683 eth_broadcast_addr(fsp->m_u.ether_spec.h_dest);
684 }
685 if (rule->filter.match_flags & IGC_FILTER_FLAG_SRC_MAC_ADDR) {
686 ether_addr_copy(fsp->h_u.ether_spec.h_source,
687 rule->filter.src_addr);
688 /* As we only support matching by the full
689 * mask, return the mask to userspace
690 */
691 eth_broadcast_addr(fsp->m_u.ether_spec.h_source);
692 }
693
694 return 0;
695 }
696 return -EINVAL;
697}
698
699static int igc_get_ethtool_nfc_all(struct igc_adapter *adapter,
700 struct ethtool_rxnfc *cmd,
701 u32 *rule_locs)
702{
703 struct igc_nfc_filter *rule;
704 int cnt = 0;
705
706 /* report total rule count */
707 cmd->data = IGC_MAX_RXNFC_FILTERS;
708
709 hlist_for_each_entry(rule, &adapter->nfc_filter_list, nfc_node) {
710 if (cnt == cmd->rule_cnt)
711 return -EMSGSIZE;
712 rule_locs[cnt] = rule->sw_idx;
713 cnt++;
714 }
715
716 cmd->rule_cnt = cnt;
717
718 return 0;
719}
720
721static int igc_get_rss_hash_opts(struct igc_adapter *adapter,
722 struct ethtool_rxnfc *cmd)
723{
724 cmd->data = 0;
725
726 /* Report default options for RSS on igc */
727 switch (cmd->flow_type) {
728 case TCP_V4_FLOW:
729 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
730 /* Fall through */
731 case UDP_V4_FLOW:
732 if (adapter->flags & IGC_FLAG_RSS_FIELD_IPV4_UDP)
733 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
734 /* Fall through */
735 case SCTP_V4_FLOW:
736 /* Fall through */
737 case AH_ESP_V4_FLOW:
738 /* Fall through */
739 case AH_V4_FLOW:
740 /* Fall through */
741 case ESP_V4_FLOW:
742 /* Fall through */
743 case IPV4_FLOW:
744 cmd->data |= RXH_IP_SRC | RXH_IP_DST;
745 break;
746 case TCP_V6_FLOW:
747 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
748 /* Fall through */
749 case UDP_V6_FLOW:
750 if (adapter->flags & IGC_FLAG_RSS_FIELD_IPV6_UDP)
751 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
752 /* Fall through */
753 case SCTP_V6_FLOW:
754 /* Fall through */
755 case AH_ESP_V6_FLOW:
756 /* Fall through */
757 case AH_V6_FLOW:
758 /* Fall through */
759 case ESP_V6_FLOW:
760 /* Fall through */
761 case IPV6_FLOW:
762 cmd->data |= RXH_IP_SRC | RXH_IP_DST;
763 break;
764 default:
765 return -EINVAL;
766 }
767
768 return 0;
769}
770
771static int igc_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
772 u32 *rule_locs)
773{
774 struct igc_adapter *adapter = netdev_priv(dev);
775 int ret = -EOPNOTSUPP;
776
777 switch (cmd->cmd) {
778 case ETHTOOL_GRXRINGS:
779 cmd->data = adapter->num_rx_queues;
780 ret = 0;
781 break;
782 case ETHTOOL_GRXCLSRLCNT:
783 cmd->rule_cnt = adapter->nfc_filter_count;
784 ret = 0;
785 break;
786 case ETHTOOL_GRXCLSRULE:
787 ret = igc_get_ethtool_nfc_entry(adapter, cmd);
788 break;
789 case ETHTOOL_GRXCLSRLALL:
790 ret = igc_get_ethtool_nfc_all(adapter, cmd, rule_locs);
791 break;
792 case ETHTOOL_GRXFH:
793 ret = igc_get_rss_hash_opts(adapter, cmd);
794 break;
795 default:
796 break;
797 }
798
799 return ret;
800}
801
802#define UDP_RSS_FLAGS (IGC_FLAG_RSS_FIELD_IPV4_UDP | \
803 IGC_FLAG_RSS_FIELD_IPV6_UDP)
804static int igc_set_rss_hash_opt(struct igc_adapter *adapter,
805 struct ethtool_rxnfc *nfc)
806{
807 u32 flags = adapter->flags;
808
809 /* RSS does not support anything other than hashing
810 * to queues on src and dst IPs and ports
811 */
812 if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST |
813 RXH_L4_B_0_1 | RXH_L4_B_2_3))
814 return -EINVAL;
815
816 switch (nfc->flow_type) {
817 case TCP_V4_FLOW:
818 case TCP_V6_FLOW:
819 if (!(nfc->data & RXH_IP_SRC) ||
820 !(nfc->data & RXH_IP_DST) ||
821 !(nfc->data & RXH_L4_B_0_1) ||
822 !(nfc->data & RXH_L4_B_2_3))
823 return -EINVAL;
824 break;
825 case UDP_V4_FLOW:
826 if (!(nfc->data & RXH_IP_SRC) ||
827 !(nfc->data & RXH_IP_DST))
828 return -EINVAL;
829 switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
830 case 0:
831 flags &= ~IGC_FLAG_RSS_FIELD_IPV4_UDP;
832 break;
833 case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
834 flags |= IGC_FLAG_RSS_FIELD_IPV4_UDP;
835 break;
836 default:
837 return -EINVAL;
838 }
839 break;
840 case UDP_V6_FLOW:
841 if (!(nfc->data & RXH_IP_SRC) ||
842 !(nfc->data & RXH_IP_DST))
843 return -EINVAL;
844 switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
845 case 0:
846 flags &= ~IGC_FLAG_RSS_FIELD_IPV6_UDP;
847 break;
848 case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
849 flags |= IGC_FLAG_RSS_FIELD_IPV6_UDP;
850 break;
851 default:
852 return -EINVAL;
853 }
854 break;
855 case AH_ESP_V4_FLOW:
856 case AH_V4_FLOW:
857 case ESP_V4_FLOW:
858 case SCTP_V4_FLOW:
859 case AH_ESP_V6_FLOW:
860 case AH_V6_FLOW:
861 case ESP_V6_FLOW:
862 case SCTP_V6_FLOW:
863 if (!(nfc->data & RXH_IP_SRC) ||
864 !(nfc->data & RXH_IP_DST) ||
865 (nfc->data & RXH_L4_B_0_1) ||
866 (nfc->data & RXH_L4_B_2_3))
867 return -EINVAL;
868 break;
869 default:
870 return -EINVAL;
871 }
872
873 /* if we changed something we need to update flags */
874 if (flags != adapter->flags) {
875 struct igc_hw *hw = &adapter->hw;
876 u32 mrqc = rd32(IGC_MRQC);
877
878 if ((flags & UDP_RSS_FLAGS) &&
879 !(adapter->flags & UDP_RSS_FLAGS))
880 dev_err(&adapter->pdev->dev,
881 "enabling UDP RSS: fragmented packets may arrive out of order to the stack above\n");
882
883 adapter->flags = flags;
884
885 /* Perform hash on these packet types */
886 mrqc |= IGC_MRQC_RSS_FIELD_IPV4 |
887 IGC_MRQC_RSS_FIELD_IPV4_TCP |
888 IGC_MRQC_RSS_FIELD_IPV6 |
889 IGC_MRQC_RSS_FIELD_IPV6_TCP;
890
891 mrqc &= ~(IGC_MRQC_RSS_FIELD_IPV4_UDP |
892 IGC_MRQC_RSS_FIELD_IPV6_UDP);
893
894 if (flags & IGC_FLAG_RSS_FIELD_IPV4_UDP)
895 mrqc |= IGC_MRQC_RSS_FIELD_IPV4_UDP;
896
897 if (flags & IGC_FLAG_RSS_FIELD_IPV6_UDP)
898 mrqc |= IGC_MRQC_RSS_FIELD_IPV6_UDP;
899
900 wr32(IGC_MRQC, mrqc);
901 }
902
903 return 0;
904}
905
906static int igc_rxnfc_write_etype_filter(struct igc_adapter *adapter,
907 struct igc_nfc_filter *input)
908{
909 struct igc_hw *hw = &adapter->hw;
910 u8 i;
911 u32 etqf;
912 u16 etype;
913
914 /* find an empty etype filter register */
915 for (i = 0; i < MAX_ETYPE_FILTER; ++i) {
916 if (!adapter->etype_bitmap[i])
917 break;
918 }
919 if (i == MAX_ETYPE_FILTER) {
920 dev_err(&adapter->pdev->dev, "ethtool -N: etype filters are all used.\n");
921 return -EINVAL;
922 }
923
924 adapter->etype_bitmap[i] = true;
925
926 etqf = rd32(IGC_ETQF(i));
927 etype = ntohs(input->filter.etype & ETHER_TYPE_FULL_MASK);
928
929 etqf |= IGC_ETQF_FILTER_ENABLE;
930 etqf &= ~IGC_ETQF_ETYPE_MASK;
931 etqf |= (etype & IGC_ETQF_ETYPE_MASK);
932
933 etqf &= ~IGC_ETQF_QUEUE_MASK;
934 etqf |= ((input->action << IGC_ETQF_QUEUE_SHIFT)
935 & IGC_ETQF_QUEUE_MASK);
936 etqf |= IGC_ETQF_QUEUE_ENABLE;
937
938 wr32(IGC_ETQF(i), etqf);
939
940 input->etype_reg_index = i;
941
942 return 0;
943}
944
945static int igc_rxnfc_write_vlan_prio_filter(struct igc_adapter *adapter,
946 struct igc_nfc_filter *input)
947{
948 struct igc_hw *hw = &adapter->hw;
949 u8 vlan_priority;
950 u16 queue_index;
951 u32 vlapqf;
952
953 vlapqf = rd32(IGC_VLAPQF);
954 vlan_priority = (ntohs(input->filter.vlan_tci) & VLAN_PRIO_MASK)
955 >> VLAN_PRIO_SHIFT;
956 queue_index = (vlapqf >> (vlan_priority * 4)) & IGC_VLAPQF_QUEUE_MASK;
957
958 /* check whether this vlan prio is already set */
959 if (vlapqf & IGC_VLAPQF_P_VALID(vlan_priority) &&
960 queue_index != input->action) {
961 dev_err(&adapter->pdev->dev, "ethtool rxnfc set vlan prio filter failed.\n");
962 return -EEXIST;
963 }
964
965 vlapqf |= IGC_VLAPQF_P_VALID(vlan_priority);
966 vlapqf |= IGC_VLAPQF_QUEUE_SEL(vlan_priority, input->action);
967
968 wr32(IGC_VLAPQF, vlapqf);
969
970 return 0;
971}
972
973int igc_add_filter(struct igc_adapter *adapter, struct igc_nfc_filter *input)
974{
975 struct igc_hw *hw = &adapter->hw;
976 int err = -EINVAL;
977
978 if (hw->mac.type == igc_i225 &&
979 !(input->filter.match_flags & ~IGC_FILTER_FLAG_SRC_MAC_ADDR)) {
980 dev_err(&adapter->pdev->dev,
981 "i225 doesn't support flow classification rules specifying only source addresses.\n");
982 return -EOPNOTSUPP;
983 }
984
985 if (input->filter.match_flags & IGC_FILTER_FLAG_ETHER_TYPE) {
986 err = igc_rxnfc_write_etype_filter(adapter, input);
987 if (err)
988 return err;
989 }
990
991 if (input->filter.match_flags & IGC_FILTER_FLAG_DST_MAC_ADDR) {
992 err = igc_add_mac_steering_filter(adapter,
993 input->filter.dst_addr,
994 input->action, 0);
995 err = min_t(int, err, 0);
996 if (err)
997 return err;
998 }
999
1000 if (input->filter.match_flags & IGC_FILTER_FLAG_SRC_MAC_ADDR) {
1001 err = igc_add_mac_steering_filter(adapter,
1002 input->filter.src_addr,
1003 input->action,
1004 IGC_MAC_STATE_SRC_ADDR);
1005 err = min_t(int, err, 0);
1006 if (err)
1007 return err;
1008 }
1009
1010 if (input->filter.match_flags & IGC_FILTER_FLAG_VLAN_TCI)
1011 err = igc_rxnfc_write_vlan_prio_filter(adapter, input);
1012
1013 return err;
1014}
1015
1016static void igc_clear_etype_filter_regs(struct igc_adapter *adapter,
1017 u16 reg_index)
1018{
1019 struct igc_hw *hw = &adapter->hw;
1020 u32 etqf = rd32(IGC_ETQF(reg_index));
1021
1022 etqf &= ~IGC_ETQF_QUEUE_ENABLE;
1023 etqf &= ~IGC_ETQF_QUEUE_MASK;
1024 etqf &= ~IGC_ETQF_FILTER_ENABLE;
1025
1026 wr32(IGC_ETQF(reg_index), etqf);
1027
1028 adapter->etype_bitmap[reg_index] = false;
1029}
1030
1031static void igc_clear_vlan_prio_filter(struct igc_adapter *adapter,
1032 u16 vlan_tci)
1033{
1034 struct igc_hw *hw = &adapter->hw;
1035 u8 vlan_priority;
1036 u32 vlapqf;
1037
1038 vlan_priority = (vlan_tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
1039
1040 vlapqf = rd32(IGC_VLAPQF);
1041 vlapqf &= ~IGC_VLAPQF_P_VALID(vlan_priority);
1042 vlapqf &= ~IGC_VLAPQF_QUEUE_SEL(vlan_priority,
1043 IGC_VLAPQF_QUEUE_MASK);
1044
1045 wr32(IGC_VLAPQF, vlapqf);
1046}
1047
1048int igc_erase_filter(struct igc_adapter *adapter, struct igc_nfc_filter *input)
1049{
1050 if (input->filter.match_flags & IGC_FILTER_FLAG_ETHER_TYPE)
1051 igc_clear_etype_filter_regs(adapter,
1052 input->etype_reg_index);
1053
1054 if (input->filter.match_flags & IGC_FILTER_FLAG_VLAN_TCI)
1055 igc_clear_vlan_prio_filter(adapter,
1056 ntohs(input->filter.vlan_tci));
1057
1058 if (input->filter.match_flags & IGC_FILTER_FLAG_SRC_MAC_ADDR)
1059 igc_del_mac_steering_filter(adapter, input->filter.src_addr,
1060 input->action,
1061 IGC_MAC_STATE_SRC_ADDR);
1062
1063 if (input->filter.match_flags & IGC_FILTER_FLAG_DST_MAC_ADDR)
1064 igc_del_mac_steering_filter(adapter, input->filter.dst_addr,
1065 input->action, 0);
1066
1067 return 0;
1068}
1069
1070static int igc_update_ethtool_nfc_entry(struct igc_adapter *adapter,
1071 struct igc_nfc_filter *input,
1072 u16 sw_idx)
1073{
1074 struct igc_nfc_filter *rule, *parent;
1075 int err = -EINVAL;
1076
1077 parent = NULL;
1078 rule = NULL;
1079
1080 hlist_for_each_entry(rule, &adapter->nfc_filter_list, nfc_node) {
1081 /* hash found, or no matching entry */
1082 if (rule->sw_idx >= sw_idx)
1083 break;
1084 parent = rule;
1085 }
1086
1087 /* if there is an old rule occupying our place remove it */
1088 if (rule && rule->sw_idx == sw_idx) {
1089 if (!input)
1090 err = igc_erase_filter(adapter, rule);
1091
1092 hlist_del(&rule->nfc_node);
1093 kfree(rule);
1094 adapter->nfc_filter_count--;
1095 }
1096
1097 /* If no input this was a delete, err should be 0 if a rule was
1098 * successfully found and removed from the list else -EINVAL
1099 */
1100 if (!input)
1101 return err;
1102
1103 /* initialize node */
1104 INIT_HLIST_NODE(&input->nfc_node);
1105
1106 /* add filter to the list */
1107 if (parent)
1108 hlist_add_behind(&input->nfc_node, &parent->nfc_node);
1109 else
1110 hlist_add_head(&input->nfc_node, &adapter->nfc_filter_list);
1111
1112 /* update counts */
1113 adapter->nfc_filter_count++;
1114
1115 return 0;
1116}
1117
1118static int igc_add_ethtool_nfc_entry(struct igc_adapter *adapter,
1119 struct ethtool_rxnfc *cmd)
1120{
1121 struct net_device *netdev = adapter->netdev;
1122 struct ethtool_rx_flow_spec *fsp =
1123 (struct ethtool_rx_flow_spec *)&cmd->fs;
1124 struct igc_nfc_filter *input, *rule;
1125 int err = 0;
1126
1127 if (!(netdev->hw_features & NETIF_F_NTUPLE))
1128 return -EOPNOTSUPP;
1129
1130 /* Don't allow programming if the action is a queue greater than
1131 * the number of online Rx queues.
1132 */
1133 if (fsp->ring_cookie == RX_CLS_FLOW_DISC ||
1134 fsp->ring_cookie >= adapter->num_rx_queues) {
1135 dev_err(&adapter->pdev->dev, "ethtool -N: The specified action is invalid\n");
1136 return -EINVAL;
1137 }
1138
1139 /* Don't allow indexes to exist outside of available space */
1140 if (fsp->location >= IGC_MAX_RXNFC_FILTERS) {
1141 dev_err(&adapter->pdev->dev, "Location out of range\n");
1142 return -EINVAL;
1143 }
1144
1145 if ((fsp->flow_type & ~FLOW_EXT) != ETHER_FLOW)
1146 return -EINVAL;
1147
1148 input = kzalloc(sizeof(*input), GFP_KERNEL);
1149 if (!input)
1150 return -ENOMEM;
1151
1152 if (fsp->m_u.ether_spec.h_proto == ETHER_TYPE_FULL_MASK) {
1153 input->filter.etype = fsp->h_u.ether_spec.h_proto;
1154 input->filter.match_flags = IGC_FILTER_FLAG_ETHER_TYPE;
1155 }
1156
1157 /* Only support matching addresses by the full mask */
1158 if (is_broadcast_ether_addr(fsp->m_u.ether_spec.h_source)) {
1159 input->filter.match_flags |= IGC_FILTER_FLAG_SRC_MAC_ADDR;
1160 ether_addr_copy(input->filter.src_addr,
1161 fsp->h_u.ether_spec.h_source);
1162 }
1163
1164 /* Only support matching addresses by the full mask */
1165 if (is_broadcast_ether_addr(fsp->m_u.ether_spec.h_dest)) {
1166 input->filter.match_flags |= IGC_FILTER_FLAG_DST_MAC_ADDR;
1167 ether_addr_copy(input->filter.dst_addr,
1168 fsp->h_u.ether_spec.h_dest);
1169 }
1170
1171 if ((fsp->flow_type & FLOW_EXT) && fsp->m_ext.vlan_tci) {
1172 if (fsp->m_ext.vlan_tci != htons(VLAN_PRIO_MASK)) {
1173 err = -EINVAL;
1174 goto err_out;
1175 }
1176 input->filter.vlan_tci = fsp->h_ext.vlan_tci;
1177 input->filter.match_flags |= IGC_FILTER_FLAG_VLAN_TCI;
1178 }
1179
1180 input->action = fsp->ring_cookie;
1181 input->sw_idx = fsp->location;
1182
1183 spin_lock(&adapter->nfc_lock);
1184
1185 hlist_for_each_entry(rule, &adapter->nfc_filter_list, nfc_node) {
1186 if (!memcmp(&input->filter, &rule->filter,
1187 sizeof(input->filter))) {
1188 err = -EEXIST;
1189 dev_err(&adapter->pdev->dev,
1190 "ethtool: this filter is already set\n");
1191 goto err_out_w_lock;
1192 }
1193 }
1194
1195 err = igc_add_filter(adapter, input);
1196 if (err)
1197 goto err_out_w_lock;
1198
1199 igc_update_ethtool_nfc_entry(adapter, input, input->sw_idx);
1200
1201 spin_unlock(&adapter->nfc_lock);
1202 return 0;
1203
1204err_out_w_lock:
1205 spin_unlock(&adapter->nfc_lock);
1206err_out:
1207 kfree(input);
1208 return err;
1209}
1210
1211static int igc_del_ethtool_nfc_entry(struct igc_adapter *adapter,
1212 struct ethtool_rxnfc *cmd)
1213{
1214 struct ethtool_rx_flow_spec *fsp =
1215 (struct ethtool_rx_flow_spec *)&cmd->fs;
1216 int err;
1217
1218 spin_lock(&adapter->nfc_lock);
1219 err = igc_update_ethtool_nfc_entry(adapter, NULL, fsp->location);
1220 spin_unlock(&adapter->nfc_lock);
1221
1222 return err;
1223}
1224
1225static int igc_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
1226{
1227 struct igc_adapter *adapter = netdev_priv(dev);
1228 int ret = -EOPNOTSUPP;
1229
1230 switch (cmd->cmd) {
1231 case ETHTOOL_SRXFH:
1232 ret = igc_set_rss_hash_opt(adapter, cmd);
1233 break;
1234 case ETHTOOL_SRXCLSRLINS:
1235 ret = igc_add_ethtool_nfc_entry(adapter, cmd);
1236 break;
1237 case ETHTOOL_SRXCLSRLDEL:
1238 ret = igc_del_ethtool_nfc_entry(adapter, cmd);
1239 default:
1240 break;
1241 }
1242
1243 return ret;
1244}
1245
646void igc_write_rss_indir_tbl(struct igc_adapter *adapter) 1246void igc_write_rss_indir_tbl(struct igc_adapter *adapter)
647{ 1247{
648 struct igc_hw *hw = &adapter->hw; 1248 struct igc_hw *hw = &adapter->hw;
@@ -1013,6 +1613,8 @@ static const struct ethtool_ops igc_ethtool_ops = {
1013 .set_pauseparam = igc_set_pauseparam, 1613 .set_pauseparam = igc_set_pauseparam,
1014 .get_coalesce = igc_get_coalesce, 1614 .get_coalesce = igc_get_coalesce,
1015 .set_coalesce = igc_set_coalesce, 1615 .set_coalesce = igc_set_coalesce,
1616 .get_rxnfc = igc_get_rxnfc,
1617 .set_rxnfc = igc_set_rxnfc,
1016 .get_rxfh_indir_size = igc_get_rxfh_indir_size, 1618 .get_rxfh_indir_size = igc_get_rxfh_indir_size,
1017 .get_rxfh = igc_get_rxfh, 1619 .get_rxfh = igc_get_rxfh,
1018 .set_rxfh = igc_set_rxfh, 1620 .set_rxfh = igc_set_rxfh,