/* lock for RX network flow classification filter */
        spinlock_t nfc_lock;
-       bool etype_bitmap[MAX_ETYPE_FILTER];
 
        struct igc_mac_addr *mac_table;
 
 int igc_add_vlan_prio_filter(struct igc_adapter *adapter, int prio,
                             int queue);
 void igc_del_vlan_prio_filter(struct igc_adapter *adapter, int prio);
+int igc_add_etype_filter(struct igc_adapter *adapter, u16 etype, int queue);
+int igc_del_etype_filter(struct igc_adapter *adapter, u16 etype);
 void igc_update_stats(struct igc_adapter *adapter);
 
 /* igc_dump declarations */
        struct hlist_node nfc_node;
        struct igc_nfc_input filter;
        unsigned long cookie;
-       u16 etype_reg_index;
        u16 sw_idx;
        u16 action;
 };
 
        return 0;
 }
 
-static int igc_rxnfc_write_etype_filter(struct igc_adapter *adapter,
-                                       struct igc_nfc_filter *input)
-{
-       struct igc_hw *hw = &adapter->hw;
-       u8 i;
-       u32 etqf;
-       u16 etype;
-
-       /* find an empty etype filter register */
-       for (i = 0; i < MAX_ETYPE_FILTER; ++i) {
-               if (!adapter->etype_bitmap[i])
-                       break;
-       }
-       if (i == MAX_ETYPE_FILTER) {
-               netdev_err(adapter->netdev,
-                          "ethtool -N: etype filters are all used\n");
-               return -EINVAL;
-       }
-
-       adapter->etype_bitmap[i] = true;
-
-       etqf = rd32(IGC_ETQF(i));
-       etype = ntohs(input->filter.etype & ETHER_TYPE_FULL_MASK);
-
-       etqf |= IGC_ETQF_FILTER_ENABLE;
-       etqf &= ~IGC_ETQF_ETYPE_MASK;
-       etqf |= (etype & IGC_ETQF_ETYPE_MASK);
-
-       etqf &= ~IGC_ETQF_QUEUE_MASK;
-       etqf |= ((input->action << IGC_ETQF_QUEUE_SHIFT)
-               & IGC_ETQF_QUEUE_MASK);
-       etqf |= IGC_ETQF_QUEUE_ENABLE;
-
-       wr32(IGC_ETQF(i), etqf);
-
-       input->etype_reg_index = i;
-
-       return 0;
-}
-
 int igc_add_filter(struct igc_adapter *adapter, struct igc_nfc_filter *input)
 {
        struct igc_hw *hw = &adapter->hw;
        }
 
        if (input->filter.match_flags & IGC_FILTER_FLAG_ETHER_TYPE) {
-               err = igc_rxnfc_write_etype_filter(adapter, input);
+               u16 etype = ntohs(input->filter.etype);
+
+               err = igc_add_etype_filter(adapter, etype, input->action);
                if (err)
                        return err;
        }
        return 0;
 }
 
-static void igc_clear_etype_filter_regs(struct igc_adapter *adapter,
-                                       u16 reg_index)
-{
-       struct igc_hw *hw = &adapter->hw;
-       u32 etqf = rd32(IGC_ETQF(reg_index));
-
-       etqf &= ~IGC_ETQF_QUEUE_ENABLE;
-       etqf &= ~IGC_ETQF_QUEUE_MASK;
-       etqf &= ~IGC_ETQF_FILTER_ENABLE;
-
-       wr32(IGC_ETQF(reg_index), etqf);
-
-       adapter->etype_bitmap[reg_index] = false;
-}
-
 int igc_erase_filter(struct igc_adapter *adapter, struct igc_nfc_filter *input)
 {
-       if (input->filter.match_flags & IGC_FILTER_FLAG_ETHER_TYPE)
-               igc_clear_etype_filter_regs(adapter,
-                                           input->etype_reg_index);
+       if (input->filter.match_flags & IGC_FILTER_FLAG_ETHER_TYPE) {
+               u16 etype = ntohs(input->filter.etype);
+
+               igc_del_etype_filter(adapter, etype);
+       }
 
        if (input->filter.match_flags & IGC_FILTER_FLAG_VLAN_TCI) {
                int prio = (ntohs(input->filter.vlan_tci) & VLAN_PRIO_MASK) >>
 
                   prio);
 }
 
+static int igc_get_avail_etype_filter_slot(struct igc_adapter *adapter)
+{
+       struct igc_hw *hw = &adapter->hw;
+       int i;
+
+       for (i = 0; i < MAX_ETYPE_FILTER; i++) {
+               u32 etqf = rd32(IGC_ETQF(i));
+
+               if (!(etqf & IGC_ETQF_FILTER_ENABLE))
+                       return i;
+       }
+
+       return -1;
+}
+
+/**
+ * igc_add_etype_filter() - Add ethertype filter
+ * @adapter: Pointer to adapter where the filter should be added
+ * @etype: Ethertype value
+ * @queue: If non-negative, queue assignment feature is enabled and frames
+ *         matching the filter are enqueued onto 'queue'. Otherwise, queue
+ *         assignment is disabled.
+ *
+ * Return: 0 in case of success, negative errno code otherwise.
+ */
+int igc_add_etype_filter(struct igc_adapter *adapter, u16 etype, int queue)
+{
+       struct igc_hw *hw = &adapter->hw;
+       int index;
+       u32 etqf;
+
+       index = igc_get_avail_etype_filter_slot(adapter);
+       if (index < 0)
+               return -ENOSPC;
+
+       etqf = rd32(IGC_ETQF(index));
+
+       etqf &= ~IGC_ETQF_ETYPE_MASK;
+       etqf |= etype;
+
+       if (queue >= 0) {
+               etqf &= ~IGC_ETQF_QUEUE_MASK;
+               etqf |= (queue << IGC_ETQF_QUEUE_SHIFT);
+               etqf |= IGC_ETQF_QUEUE_ENABLE;
+       }
+
+       etqf |= IGC_ETQF_FILTER_ENABLE;
+
+       wr32(IGC_ETQF(index), etqf);
+
+       netdev_dbg(adapter->netdev, "Add ethertype filter: etype %04x queue %d\n",
+                  etype, queue);
+       return 0;
+}
+
+static int igc_find_etype_filter(struct igc_adapter *adapter, u16 etype)
+{
+       struct igc_hw *hw = &adapter->hw;
+       int i;
+
+       for (i = 0; i < MAX_ETYPE_FILTER; i++) {
+               u32 etqf = rd32(IGC_ETQF(i));
+
+               if ((etqf & IGC_ETQF_ETYPE_MASK) == etype)
+                       return i;
+       }
+
+       return -1;
+}
+
+/**
+ * igc_del_etype_filter() - Delete ethertype filter
+ * @adapter: Pointer to adapter where the filter should be deleted from
+ * @etype: Ethertype value
+ *
+ * Return: 0 in case of success, negative errno code otherwise.
+ */
+int igc_del_etype_filter(struct igc_adapter *adapter, u16 etype)
+{
+       struct igc_hw *hw = &adapter->hw;
+       int index;
+
+       index = igc_find_etype_filter(adapter, etype);
+       if (index < 0)
+               return -ENOENT;
+
+       wr32(IGC_ETQF(index), 0);
+
+       netdev_dbg(adapter->netdev, "Delete ethertype filter: etype %04x\n",
+                  etype);
+       return 0;
+}
+
 static int igc_uc_sync(struct net_device *netdev, const unsigned char *addr)
 {
        struct igc_adapter *adapter = netdev_priv(netdev);