|
@@ -53,6 +53,7 @@
|
|
|
#include <net/vxlan.h>
|
|
|
#include <net/pkt_cls.h>
|
|
|
#include <net/tc_act/tc_gact.h>
|
|
|
+#include <net/tc_act/tc_mirred.h>
|
|
|
|
|
|
#include "ixgbe.h"
|
|
|
#include "ixgbe_common.h"
|
|
@@ -5558,6 +5559,58 @@ static void ixgbe_tx_timeout(struct net_device *netdev)
|
|
|
ixgbe_tx_timeout_reset(adapter);
|
|
|
}
|
|
|
|
|
|
+#ifdef CONFIG_IXGBE_DCB
|
|
|
+static void ixgbe_init_dcb(struct ixgbe_adapter *adapter)
|
|
|
+{
|
|
|
+ struct ixgbe_hw *hw = &adapter->hw;
|
|
|
+ struct tc_configuration *tc;
|
|
|
+ int j;
|
|
|
+
|
|
|
+ switch (hw->mac.type) {
|
|
|
+ case ixgbe_mac_82598EB:
|
|
|
+ case ixgbe_mac_82599EB:
|
|
|
+ adapter->dcb_cfg.num_tcs.pg_tcs = MAX_TRAFFIC_CLASS;
|
|
|
+ adapter->dcb_cfg.num_tcs.pfc_tcs = MAX_TRAFFIC_CLASS;
|
|
|
+ break;
|
|
|
+ case ixgbe_mac_X540:
|
|
|
+ case ixgbe_mac_X550:
|
|
|
+ adapter->dcb_cfg.num_tcs.pg_tcs = X540_TRAFFIC_CLASS;
|
|
|
+ adapter->dcb_cfg.num_tcs.pfc_tcs = X540_TRAFFIC_CLASS;
|
|
|
+ break;
|
|
|
+ case ixgbe_mac_X550EM_x:
|
|
|
+ case ixgbe_mac_x550em_a:
|
|
|
+ default:
|
|
|
+ adapter->dcb_cfg.num_tcs.pg_tcs = DEF_TRAFFIC_CLASS;
|
|
|
+ adapter->dcb_cfg.num_tcs.pfc_tcs = DEF_TRAFFIC_CLASS;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Configure DCB traffic classes */
|
|
|
+ for (j = 0; j < MAX_TRAFFIC_CLASS; j++) {
|
|
|
+ tc = &adapter->dcb_cfg.tc_config[j];
|
|
|
+ tc->path[DCB_TX_CONFIG].bwg_id = 0;
|
|
|
+ tc->path[DCB_TX_CONFIG].bwg_percent = 12 + (j & 1);
|
|
|
+ tc->path[DCB_RX_CONFIG].bwg_id = 0;
|
|
|
+ tc->path[DCB_RX_CONFIG].bwg_percent = 12 + (j & 1);
|
|
|
+ tc->dcb_pfc = pfc_disabled;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Initialize default user to priority mapping, UPx->TC0 */
|
|
|
+ tc = &adapter->dcb_cfg.tc_config[0];
|
|
|
+ tc->path[DCB_TX_CONFIG].up_to_tc_bitmap = 0xFF;
|
|
|
+ tc->path[DCB_RX_CONFIG].up_to_tc_bitmap = 0xFF;
|
|
|
+
|
|
|
+ adapter->dcb_cfg.bw_percentage[DCB_TX_CONFIG][0] = 100;
|
|
|
+ adapter->dcb_cfg.bw_percentage[DCB_RX_CONFIG][0] = 100;
|
|
|
+ adapter->dcb_cfg.pfc_mode_enable = false;
|
|
|
+ adapter->dcb_set_bitmap = 0x00;
|
|
|
+ if (adapter->flags & IXGBE_FLAG_DCB_CAPABLE)
|
|
|
+ adapter->dcbx_cap = DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_CEE;
|
|
|
+ memcpy(&adapter->temp_dcb_cfg, &adapter->dcb_cfg,
|
|
|
+ sizeof(adapter->temp_dcb_cfg));
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
/**
|
|
|
* ixgbe_sw_init - Initialize general software structures (struct ixgbe_adapter)
|
|
|
* @adapter: board private structure to initialize
|
|
@@ -5573,10 +5626,7 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter)
|
|
|
unsigned int rss, fdir;
|
|
|
u32 fwsm;
|
|
|
u16 device_caps;
|
|
|
-#ifdef CONFIG_IXGBE_DCB
|
|
|
- int j;
|
|
|
- struct tc_configuration *tc;
|
|
|
-#endif
|
|
|
+ int i;
|
|
|
|
|
|
/* PCI config space info */
|
|
|
|
|
@@ -5598,6 +5648,10 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter)
|
|
|
#ifdef CONFIG_IXGBE_DCA
|
|
|
adapter->flags |= IXGBE_FLAG_DCA_CAPABLE;
|
|
|
#endif
|
|
|
+#ifdef CONFIG_IXGBE_DCB
|
|
|
+ adapter->flags |= IXGBE_FLAG_DCB_CAPABLE;
|
|
|
+ adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
|
|
|
+#endif
|
|
|
#ifdef IXGBE_FCOE
|
|
|
adapter->flags |= IXGBE_FLAG_FCOE_CAPABLE;
|
|
|
adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED;
|
|
@@ -5608,7 +5662,14 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter)
|
|
|
#endif /* IXGBE_FCOE */
|
|
|
|
|
|
/* initialize static ixgbe jump table entries */
|
|
|
- adapter->jump_tables[0] = ixgbe_ipv4_fields;
|
|
|
+ adapter->jump_tables[0] = kzalloc(sizeof(*adapter->jump_tables[0]),
|
|
|
+ GFP_KERNEL);
|
|
|
+ if (!adapter->jump_tables[0])
|
|
|
+ return -ENOMEM;
|
|
|
+ adapter->jump_tables[0]->mat = ixgbe_ipv4_fields;
|
|
|
+
|
|
|
+ for (i = 1; i < IXGBE_MAX_LINK_HANDLE; i++)
|
|
|
+ adapter->jump_tables[i] = NULL;
|
|
|
|
|
|
adapter->mac_table = kzalloc(sizeof(struct ixgbe_mac_addr) *
|
|
|
hw->mac.num_rar_entries,
|
|
@@ -5647,6 +5708,16 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter)
|
|
|
break;
|
|
|
case ixgbe_mac_X550EM_x:
|
|
|
case ixgbe_mac_x550em_a:
|
|
|
+#ifdef CONFIG_IXGBE_DCB
|
|
|
+ adapter->flags &= ~IXGBE_FLAG_DCB_CAPABLE;
|
|
|
+#endif
|
|
|
+#ifdef IXGBE_FCOE
|
|
|
+ adapter->flags &= ~IXGBE_FLAG_FCOE_CAPABLE;
|
|
|
+#ifdef CONFIG_IXGBE_DCB
|
|
|
+ adapter->fcoe.up = 0;
|
|
|
+#endif /* IXGBE_DCB */
|
|
|
+#endif /* IXGBE_FCOE */
|
|
|
+ /* Fall Through */
|
|
|
case ixgbe_mac_X550:
|
|
|
#ifdef CONFIG_IXGBE_DCA
|
|
|
adapter->flags &= ~IXGBE_FLAG_DCA_CAPABLE;
|
|
@@ -5668,43 +5739,7 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter)
|
|
|
spin_lock_init(&adapter->fdir_perfect_lock);
|
|
|
|
|
|
#ifdef CONFIG_IXGBE_DCB
|
|
|
- switch (hw->mac.type) {
|
|
|
- case ixgbe_mac_X540:
|
|
|
- case ixgbe_mac_X550:
|
|
|
- case ixgbe_mac_X550EM_x:
|
|
|
- case ixgbe_mac_x550em_a:
|
|
|
- adapter->dcb_cfg.num_tcs.pg_tcs = X540_TRAFFIC_CLASS;
|
|
|
- adapter->dcb_cfg.num_tcs.pfc_tcs = X540_TRAFFIC_CLASS;
|
|
|
- break;
|
|
|
- default:
|
|
|
- adapter->dcb_cfg.num_tcs.pg_tcs = MAX_TRAFFIC_CLASS;
|
|
|
- adapter->dcb_cfg.num_tcs.pfc_tcs = MAX_TRAFFIC_CLASS;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- /* Configure DCB traffic classes */
|
|
|
- for (j = 0; j < MAX_TRAFFIC_CLASS; j++) {
|
|
|
- tc = &adapter->dcb_cfg.tc_config[j];
|
|
|
- tc->path[DCB_TX_CONFIG].bwg_id = 0;
|
|
|
- tc->path[DCB_TX_CONFIG].bwg_percent = 12 + (j & 1);
|
|
|
- tc->path[DCB_RX_CONFIG].bwg_id = 0;
|
|
|
- tc->path[DCB_RX_CONFIG].bwg_percent = 12 + (j & 1);
|
|
|
- tc->dcb_pfc = pfc_disabled;
|
|
|
- }
|
|
|
-
|
|
|
- /* Initialize default user to priority mapping, UPx->TC0 */
|
|
|
- tc = &adapter->dcb_cfg.tc_config[0];
|
|
|
- tc->path[DCB_TX_CONFIG].up_to_tc_bitmap = 0xFF;
|
|
|
- tc->path[DCB_RX_CONFIG].up_to_tc_bitmap = 0xFF;
|
|
|
-
|
|
|
- adapter->dcb_cfg.bw_percentage[DCB_TX_CONFIG][0] = 100;
|
|
|
- adapter->dcb_cfg.bw_percentage[DCB_RX_CONFIG][0] = 100;
|
|
|
- adapter->dcb_cfg.pfc_mode_enable = false;
|
|
|
- adapter->dcb_set_bitmap = 0x00;
|
|
|
- adapter->dcbx_cap = DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_CEE;
|
|
|
- memcpy(&adapter->temp_dcb_cfg, &adapter->dcb_cfg,
|
|
|
- sizeof(adapter->temp_dcb_cfg));
|
|
|
-
|
|
|
+ ixgbe_init_dcb(adapter);
|
|
|
#endif
|
|
|
|
|
|
/* default flow control settings */
|
|
@@ -8319,6 +8354,134 @@ static int ixgbe_configure_clsu32_del_hnode(struct ixgbe_adapter *adapter,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+#ifdef CONFIG_NET_CLS_ACT
|
|
|
+static int handle_redirect_action(struct ixgbe_adapter *adapter, int ifindex,
|
|
|
+ u8 *queue, u64 *action)
|
|
|
+{
|
|
|
+ unsigned int num_vfs = adapter->num_vfs, vf;
|
|
|
+ struct net_device *upper;
|
|
|
+ struct list_head *iter;
|
|
|
+
|
|
|
+ /* redirect to a SRIOV VF */
|
|
|
+ for (vf = 0; vf < num_vfs; ++vf) {
|
|
|
+ upper = pci_get_drvdata(adapter->vfinfo[vf].vfdev);
|
|
|
+ if (upper->ifindex == ifindex) {
|
|
|
+ if (adapter->num_rx_pools > 1)
|
|
|
+ *queue = vf * 2;
|
|
|
+ else
|
|
|
+ *queue = vf * adapter->num_rx_queues_per_pool;
|
|
|
+
|
|
|
+ *action = vf + 1;
|
|
|
+ *action <<= ETHTOOL_RX_FLOW_SPEC_RING_VF_OFF;
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /* redirect to a offloaded macvlan netdev */
|
|
|
+ netdev_for_each_all_upper_dev_rcu(adapter->netdev, upper, iter) {
|
|
|
+ if (netif_is_macvlan(upper)) {
|
|
|
+ struct macvlan_dev *dfwd = netdev_priv(upper);
|
|
|
+ struct ixgbe_fwd_adapter *vadapter = dfwd->fwd_priv;
|
|
|
+
|
|
|
+ if (vadapter && vadapter->netdev->ifindex == ifindex) {
|
|
|
+ *queue = adapter->rx_ring[vadapter->rx_base_queue]->reg_idx;
|
|
|
+ *action = *queue;
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return -EINVAL;
|
|
|
+}
|
|
|
+
|
|
|
+static int parse_tc_actions(struct ixgbe_adapter *adapter,
|
|
|
+ struct tcf_exts *exts, u64 *action, u8 *queue)
|
|
|
+{
|
|
|
+ const struct tc_action *a;
|
|
|
+ int err;
|
|
|
+
|
|
|
+ if (tc_no_actions(exts))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ tc_for_each_action(a, exts) {
|
|
|
+
|
|
|
+ /* Drop action */
|
|
|
+ if (is_tcf_gact_shot(a)) {
|
|
|
+ *action = IXGBE_FDIR_DROP_QUEUE;
|
|
|
+ *queue = IXGBE_FDIR_DROP_QUEUE;
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Redirect to a VF or a offloaded macvlan */
|
|
|
+ if (is_tcf_mirred_redirect(a)) {
|
|
|
+ int ifindex = tcf_mirred_ifindex(a);
|
|
|
+
|
|
|
+ err = handle_redirect_action(adapter, ifindex, queue,
|
|
|
+ action);
|
|
|
+ if (err == 0)
|
|
|
+ return err;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return -EINVAL;
|
|
|
+}
|
|
|
+#else
|
|
|
+static int parse_tc_actions(struct ixgbe_adapter *adapter,
|
|
|
+ struct tcf_exts *exts, u64 *action, u8 *queue)
|
|
|
+{
|
|
|
+ return -EINVAL;
|
|
|
+}
|
|
|
+#endif /* CONFIG_NET_CLS_ACT */
|
|
|
+
|
|
|
+static int ixgbe_clsu32_build_input(struct ixgbe_fdir_filter *input,
|
|
|
+ union ixgbe_atr_input *mask,
|
|
|
+ struct tc_cls_u32_offload *cls,
|
|
|
+ struct ixgbe_mat_field *field_ptr,
|
|
|
+ struct ixgbe_nexthdr *nexthdr)
|
|
|
+{
|
|
|
+ int i, j, off;
|
|
|
+ __be32 val, m;
|
|
|
+ bool found_entry = false, found_jump_field = false;
|
|
|
+
|
|
|
+ for (i = 0; i < cls->knode.sel->nkeys; i++) {
|
|
|
+ off = cls->knode.sel->keys[i].off;
|
|
|
+ val = cls->knode.sel->keys[i].val;
|
|
|
+ m = cls->knode.sel->keys[i].mask;
|
|
|
+
|
|
|
+ for (j = 0; field_ptr[j].val; j++) {
|
|
|
+ if (field_ptr[j].off == off) {
|
|
|
+ field_ptr[j].val(input, mask, val, m);
|
|
|
+ input->filter.formatted.flow_type |=
|
|
|
+ field_ptr[j].type;
|
|
|
+ found_entry = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (nexthdr) {
|
|
|
+ if (nexthdr->off == cls->knode.sel->keys[i].off &&
|
|
|
+ nexthdr->val == cls->knode.sel->keys[i].val &&
|
|
|
+ nexthdr->mask == cls->knode.sel->keys[i].mask)
|
|
|
+ found_jump_field = true;
|
|
|
+ else
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (nexthdr && !found_jump_field)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ if (!found_entry)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ mask->formatted.flow_type = IXGBE_ATR_L4TYPE_IPV6_MASK |
|
|
|
+ IXGBE_ATR_L4TYPE_MASK;
|
|
|
+
|
|
|
+ if (input->filter.formatted.flow_type == IXGBE_ATR_FLOW_TYPE_IPV4)
|
|
|
+ mask->formatted.flow_type &= IXGBE_ATR_L4TYPE_IPV6_MASK;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter,
|
|
|
__be16 protocol,
|
|
|
struct tc_cls_u32_offload *cls)
|
|
@@ -8326,16 +8489,13 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter,
|
|
|
u32 loc = cls->knode.handle & 0xfffff;
|
|
|
struct ixgbe_hw *hw = &adapter->hw;
|
|
|
struct ixgbe_mat_field *field_ptr;
|
|
|
- struct ixgbe_fdir_filter *input;
|
|
|
- union ixgbe_atr_input mask;
|
|
|
-#ifdef CONFIG_NET_CLS_ACT
|
|
|
- const struct tc_action *a;
|
|
|
-#endif
|
|
|
- int i, err = 0;
|
|
|
+ struct ixgbe_fdir_filter *input = NULL;
|
|
|
+ union ixgbe_atr_input *mask = NULL;
|
|
|
+ struct ixgbe_jump_table *jump = NULL;
|
|
|
+ int i, err = -EINVAL;
|
|
|
u8 queue;
|
|
|
u32 uhtid, link_uhtid;
|
|
|
|
|
|
- memset(&mask, 0, sizeof(union ixgbe_atr_input));
|
|
|
uhtid = TC_U32_USERHTID(cls->knode.handle);
|
|
|
link_uhtid = TC_U32_USERHTID(cls->knode.link_handle);
|
|
|
|
|
@@ -8347,39 +8507,11 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter,
|
|
|
* headers when needed.
|
|
|
*/
|
|
|
if (protocol != htons(ETH_P_IP))
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- if (link_uhtid) {
|
|
|
- struct ixgbe_nexthdr *nexthdr = ixgbe_ipv4_jumps;
|
|
|
-
|
|
|
- if (link_uhtid >= IXGBE_MAX_LINK_HANDLE)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- if (!test_bit(link_uhtid - 1, &adapter->tables))
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- for (i = 0; nexthdr[i].jump; i++) {
|
|
|
- if (nexthdr[i].o != cls->knode.sel->offoff ||
|
|
|
- nexthdr[i].s != cls->knode.sel->offshift ||
|
|
|
- nexthdr[i].m != cls->knode.sel->offmask ||
|
|
|
- /* do not support multiple key jumps its just mad */
|
|
|
- cls->knode.sel->nkeys > 1)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- if (nexthdr[i].off == cls->knode.sel->keys[0].off &&
|
|
|
- nexthdr[i].val == cls->knode.sel->keys[0].val &&
|
|
|
- nexthdr[i].mask == cls->knode.sel->keys[0].mask) {
|
|
|
- adapter->jump_tables[link_uhtid] =
|
|
|
- nexthdr[i].jump;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ return err;
|
|
|
|
|
|
if (loc >= ((1024 << adapter->fdir_pballoc) - 2)) {
|
|
|
e_err(drv, "Location out of range\n");
|
|
|
- return -EINVAL;
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
/* cls u32 is a graph starting at root node 0x800. The driver tracks
|
|
@@ -8390,87 +8522,123 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter,
|
|
|
* this function _should_ be generic try not to hardcode values here.
|
|
|
*/
|
|
|
if (uhtid == 0x800) {
|
|
|
- field_ptr = adapter->jump_tables[0];
|
|
|
+ field_ptr = (adapter->jump_tables[0])->mat;
|
|
|
} else {
|
|
|
if (uhtid >= IXGBE_MAX_LINK_HANDLE)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- field_ptr = adapter->jump_tables[uhtid];
|
|
|
+ return err;
|
|
|
+ if (!adapter->jump_tables[uhtid])
|
|
|
+ return err;
|
|
|
+ field_ptr = (adapter->jump_tables[uhtid])->mat;
|
|
|
}
|
|
|
|
|
|
if (!field_ptr)
|
|
|
- return -EINVAL;
|
|
|
+ return err;
|
|
|
|
|
|
- input = kzalloc(sizeof(*input), GFP_KERNEL);
|
|
|
- if (!input)
|
|
|
- return -ENOMEM;
|
|
|
+ /* At this point we know the field_ptr is valid and need to either
|
|
|
+ * build cls_u32 link or attach filter. Because adding a link to
|
|
|
+ * a handle that does not exist is invalid and the same for adding
|
|
|
+ * rules to handles that don't exist.
|
|
|
+ */
|
|
|
|
|
|
- for (i = 0; i < cls->knode.sel->nkeys; i++) {
|
|
|
- int off = cls->knode.sel->keys[i].off;
|
|
|
- __be32 val = cls->knode.sel->keys[i].val;
|
|
|
- __be32 m = cls->knode.sel->keys[i].mask;
|
|
|
- bool found_entry = false;
|
|
|
- int j;
|
|
|
+ if (link_uhtid) {
|
|
|
+ struct ixgbe_nexthdr *nexthdr = ixgbe_ipv4_jumps;
|
|
|
|
|
|
- for (j = 0; field_ptr[j].val; j++) {
|
|
|
- if (field_ptr[j].off == off) {
|
|
|
- field_ptr[j].val(input, &mask, val, m);
|
|
|
- input->filter.formatted.flow_type |=
|
|
|
- field_ptr[j].type;
|
|
|
- found_entry = true;
|
|
|
+ if (link_uhtid >= IXGBE_MAX_LINK_HANDLE)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ if (!test_bit(link_uhtid - 1, &adapter->tables))
|
|
|
+ return err;
|
|
|
+
|
|
|
+ for (i = 0; nexthdr[i].jump; i++) {
|
|
|
+ if (nexthdr[i].o != cls->knode.sel->offoff ||
|
|
|
+ nexthdr[i].s != cls->knode.sel->offshift ||
|
|
|
+ nexthdr[i].m != cls->knode.sel->offmask)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ jump = kzalloc(sizeof(*jump), GFP_KERNEL);
|
|
|
+ if (!jump)
|
|
|
+ return -ENOMEM;
|
|
|
+ input = kzalloc(sizeof(*input), GFP_KERNEL);
|
|
|
+ if (!input) {
|
|
|
+ err = -ENOMEM;
|
|
|
+ goto free_jump;
|
|
|
+ }
|
|
|
+ mask = kzalloc(sizeof(*mask), GFP_KERNEL);
|
|
|
+ if (!mask) {
|
|
|
+ err = -ENOMEM;
|
|
|
+ goto free_input;
|
|
|
+ }
|
|
|
+ jump->input = input;
|
|
|
+ jump->mask = mask;
|
|
|
+ err = ixgbe_clsu32_build_input(input, mask, cls,
|
|
|
+ field_ptr, &nexthdr[i]);
|
|
|
+ if (!err) {
|
|
|
+ jump->mat = nexthdr[i].jump;
|
|
|
+ adapter->jump_tables[link_uhtid] = jump;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- if (!found_entry)
|
|
|
- goto err_out;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
- mask.formatted.flow_type = IXGBE_ATR_L4TYPE_IPV6_MASK |
|
|
|
- IXGBE_ATR_L4TYPE_MASK;
|
|
|
-
|
|
|
- if (input->filter.formatted.flow_type == IXGBE_ATR_FLOW_TYPE_IPV4)
|
|
|
- mask.formatted.flow_type &= IXGBE_ATR_L4TYPE_IPV6_MASK;
|
|
|
+ input = kzalloc(sizeof(*input), GFP_KERNEL);
|
|
|
+ if (!input)
|
|
|
+ return -ENOMEM;
|
|
|
+ mask = kzalloc(sizeof(*mask), GFP_KERNEL);
|
|
|
+ if (!mask) {
|
|
|
+ err = -ENOMEM;
|
|
|
+ goto free_input;
|
|
|
+ }
|
|
|
|
|
|
-#ifdef CONFIG_NET_CLS_ACT
|
|
|
- if (list_empty(&cls->knode.exts->actions))
|
|
|
+ if ((uhtid != 0x800) && (adapter->jump_tables[uhtid])) {
|
|
|
+ if ((adapter->jump_tables[uhtid])->input)
|
|
|
+ memcpy(input, (adapter->jump_tables[uhtid])->input,
|
|
|
+ sizeof(*input));
|
|
|
+ if ((adapter->jump_tables[uhtid])->mask)
|
|
|
+ memcpy(mask, (adapter->jump_tables[uhtid])->mask,
|
|
|
+ sizeof(*mask));
|
|
|
+ }
|
|
|
+ err = ixgbe_clsu32_build_input(input, mask, cls, field_ptr, NULL);
|
|
|
+ if (err)
|
|
|
goto err_out;
|
|
|
|
|
|
- list_for_each_entry(a, &cls->knode.exts->actions, list) {
|
|
|
- if (!is_tcf_gact_shot(a))
|
|
|
- goto err_out;
|
|
|
- }
|
|
|
-#endif
|
|
|
+ err = parse_tc_actions(adapter, cls->knode.exts, &input->action,
|
|
|
+ &queue);
|
|
|
+ if (err < 0)
|
|
|
+ goto err_out;
|
|
|
|
|
|
- input->action = IXGBE_FDIR_DROP_QUEUE;
|
|
|
- queue = IXGBE_FDIR_DROP_QUEUE;
|
|
|
input->sw_idx = loc;
|
|
|
|
|
|
spin_lock(&adapter->fdir_perfect_lock);
|
|
|
|
|
|
if (hlist_empty(&adapter->fdir_filter_list)) {
|
|
|
- memcpy(&adapter->fdir_mask, &mask, sizeof(mask));
|
|
|
- err = ixgbe_fdir_set_input_mask_82599(hw, &mask);
|
|
|
+ memcpy(&adapter->fdir_mask, mask, sizeof(*mask));
|
|
|
+ err = ixgbe_fdir_set_input_mask_82599(hw, mask);
|
|
|
if (err)
|
|
|
goto err_out_w_lock;
|
|
|
- } else if (memcmp(&adapter->fdir_mask, &mask, sizeof(mask))) {
|
|
|
+ } else if (memcmp(&adapter->fdir_mask, mask, sizeof(*mask))) {
|
|
|
err = -EINVAL;
|
|
|
goto err_out_w_lock;
|
|
|
}
|
|
|
|
|
|
- ixgbe_atr_compute_perfect_hash_82599(&input->filter, &mask);
|
|
|
+ ixgbe_atr_compute_perfect_hash_82599(&input->filter, mask);
|
|
|
err = ixgbe_fdir_write_perfect_filter_82599(hw, &input->filter,
|
|
|
input->sw_idx, queue);
|
|
|
if (!err)
|
|
|
ixgbe_update_ethtool_fdir_entry(adapter, input, input->sw_idx);
|
|
|
spin_unlock(&adapter->fdir_perfect_lock);
|
|
|
|
|
|
+ kfree(mask);
|
|
|
return err;
|
|
|
err_out_w_lock:
|
|
|
spin_unlock(&adapter->fdir_perfect_lock);
|
|
|
err_out:
|
|
|
+ kfree(mask);
|
|
|
+free_input:
|
|
|
kfree(input);
|
|
|
- return -EINVAL;
|
|
|
+free_jump:
|
|
|
+ kfree(jump);
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
static int __ixgbe_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
|
|
@@ -9043,7 +9211,7 @@ static inline int ixgbe_enumerate_functions(struct ixgbe_adapter *adapter)
|
|
|
|
|
|
/**
|
|
|
* ixgbe_wol_supported - Check whether device supports WoL
|
|
|
- * @hw: hw specific details
|
|
|
+ * @adapter: the adapter private structure
|
|
|
* @device_id: the device ID
|
|
|
* @subdev_id: the subsystem device ID
|
|
|
*
|
|
@@ -9051,19 +9219,33 @@ static inline int ixgbe_enumerate_functions(struct ixgbe_adapter *adapter)
|
|
|
* which devices have WoL support
|
|
|
*
|
|
|
**/
|
|
|
-int ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id,
|
|
|
- u16 subdevice_id)
|
|
|
+bool ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id,
|
|
|
+ u16 subdevice_id)
|
|
|
{
|
|
|
struct ixgbe_hw *hw = &adapter->hw;
|
|
|
u16 wol_cap = adapter->eeprom_cap & IXGBE_DEVICE_CAPS_WOL_MASK;
|
|
|
- int is_wol_supported = 0;
|
|
|
|
|
|
+ /* WOL not supported on 82598 */
|
|
|
+ if (hw->mac.type == ixgbe_mac_82598EB)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ /* check eeprom to see if WOL is enabled for X540 and newer */
|
|
|
+ if (hw->mac.type >= ixgbe_mac_X540) {
|
|
|
+ if ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0_1) ||
|
|
|
+ ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0) &&
|
|
|
+ (hw->bus.func == 0)))
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* WOL is determined based on device IDs for 82599 MACs */
|
|
|
switch (device_id) {
|
|
|
case IXGBE_DEV_ID_82599_SFP:
|
|
|
/* Only these subdevices could supports WOL */
|
|
|
switch (subdevice_id) {
|
|
|
- case IXGBE_SUBDEV_ID_82599_SFP_WOL0:
|
|
|
case IXGBE_SUBDEV_ID_82599_560FLR:
|
|
|
+ case IXGBE_SUBDEV_ID_82599_LOM_SNAP6:
|
|
|
+ case IXGBE_SUBDEV_ID_82599_SFP_WOL0:
|
|
|
+ case IXGBE_SUBDEV_ID_82599_SFP_2OCP:
|
|
|
/* only support first port */
|
|
|
if (hw->bus.func != 0)
|
|
|
break;
|
|
@@ -9071,44 +9253,31 @@ int ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id,
|
|
|
case IXGBE_SUBDEV_ID_82599_SFP:
|
|
|
case IXGBE_SUBDEV_ID_82599_RNDC:
|
|
|
case IXGBE_SUBDEV_ID_82599_ECNA_DP:
|
|
|
- case IXGBE_SUBDEV_ID_82599_LOM_SFP:
|
|
|
- is_wol_supported = 1;
|
|
|
- break;
|
|
|
+ case IXGBE_SUBDEV_ID_82599_SFP_1OCP:
|
|
|
+ case IXGBE_SUBDEV_ID_82599_SFP_LOM_OEM1:
|
|
|
+ case IXGBE_SUBDEV_ID_82599_SFP_LOM_OEM2:
|
|
|
+ return true;
|
|
|
}
|
|
|
break;
|
|
|
case IXGBE_DEV_ID_82599EN_SFP:
|
|
|
- /* Only this subdevice supports WOL */
|
|
|
+ /* Only these subdevices support WOL */
|
|
|
switch (subdevice_id) {
|
|
|
case IXGBE_SUBDEV_ID_82599EN_SFP_OCP1:
|
|
|
- is_wol_supported = 1;
|
|
|
- break;
|
|
|
+ return true;
|
|
|
}
|
|
|
break;
|
|
|
case IXGBE_DEV_ID_82599_COMBO_BACKPLANE:
|
|
|
/* All except this subdevice support WOL */
|
|
|
if (subdevice_id != IXGBE_SUBDEV_ID_82599_KX4_KR_MEZZ)
|
|
|
- is_wol_supported = 1;
|
|
|
+ return true;
|
|
|
break;
|
|
|
case IXGBE_DEV_ID_82599_KX4:
|
|
|
- is_wol_supported = 1;
|
|
|
- break;
|
|
|
- case IXGBE_DEV_ID_X540T:
|
|
|
- case IXGBE_DEV_ID_X540T1:
|
|
|
- case IXGBE_DEV_ID_X550T:
|
|
|
- case IXGBE_DEV_ID_X550T1:
|
|
|
- case IXGBE_DEV_ID_X550EM_X_KX4:
|
|
|
- case IXGBE_DEV_ID_X550EM_X_KR:
|
|
|
- case IXGBE_DEV_ID_X550EM_X_10G_T:
|
|
|
- /* check eeprom to see if enabled wol */
|
|
|
- if ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0_1) ||
|
|
|
- ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0) &&
|
|
|
- (hw->bus.func == 0))) {
|
|
|
- is_wol_supported = 1;
|
|
|
- }
|
|
|
+ return true;
|
|
|
+ default:
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- return is_wol_supported;
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -9352,7 +9521,8 @@ skip_sriov:
|
|
|
netdev->priv_flags |= IFF_SUPP_NOFCS;
|
|
|
|
|
|
#ifdef CONFIG_IXGBE_DCB
|
|
|
- netdev->dcbnl_ops = &dcbnl_ops;
|
|
|
+ if (adapter->flags & IXGBE_FLAG_DCB_CAPABLE)
|
|
|
+ netdev->dcbnl_ops = &dcbnl_ops;
|
|
|
#endif
|
|
|
|
|
|
#ifdef IXGBE_FCOE
|
|
@@ -9542,6 +9712,7 @@ err_sw_init:
|
|
|
ixgbe_disable_sriov(adapter);
|
|
|
adapter->flags2 &= ~IXGBE_FLAG2_SEARCH_FOR_SFP;
|
|
|
iounmap(adapter->io_addr);
|
|
|
+ kfree(adapter->jump_tables[0]);
|
|
|
kfree(adapter->mac_table);
|
|
|
err_ioremap:
|
|
|
disable_dev = !test_and_set_bit(__IXGBE_DISABLED, &adapter->state);
|
|
@@ -9570,6 +9741,7 @@ static void ixgbe_remove(struct pci_dev *pdev)
|
|
|
struct ixgbe_adapter *adapter = pci_get_drvdata(pdev);
|
|
|
struct net_device *netdev;
|
|
|
bool disable_dev;
|
|
|
+ int i;
|
|
|
|
|
|
/* if !adapter then we already cleaned up in probe */
|
|
|
if (!adapter)
|
|
@@ -9619,6 +9791,14 @@ static void ixgbe_remove(struct pci_dev *pdev)
|
|
|
|
|
|
e_dev_info("complete\n");
|
|
|
|
|
|
+ for (i = 0; i < IXGBE_MAX_LINK_HANDLE; i++) {
|
|
|
+ if (adapter->jump_tables[i]) {
|
|
|
+ kfree(adapter->jump_tables[i]->input);
|
|
|
+ kfree(adapter->jump_tables[i]->mask);
|
|
|
+ }
|
|
|
+ kfree(adapter->jump_tables[i]);
|
|
|
+ }
|
|
|
+
|
|
|
kfree(adapter->mac_table);
|
|
|
disable_dev = !test_and_set_bit(__IXGBE_DISABLED, &adapter->state);
|
|
|
free_netdev(netdev);
|