/*-
* BSD LICENSE
*
- * Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ * Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* Default values for port configuration
*/
#define IGB_DEFAULT_RX_FREE_THRESH 32
-#define IGB_DEFAULT_RX_PTHRESH 8
+
+#define IGB_DEFAULT_RX_PTHRESH ((hw->mac.type == e1000_i354) ? 12 : 8)
#define IGB_DEFAULT_RX_HTHRESH 8
-#define IGB_DEFAULT_RX_WTHRESH 0
+#define IGB_DEFAULT_RX_WTHRESH ((hw->mac.type == e1000_82576) ? 1 : 4)
-#define IGB_DEFAULT_TX_PTHRESH 32
-#define IGB_DEFAULT_TX_HTHRESH 0
-#define IGB_DEFAULT_TX_WTHRESH 0
+#define IGB_DEFAULT_TX_PTHRESH ((hw->mac.type == e1000_i354) ? 20 : 8)
+#define IGB_DEFAULT_TX_HTHRESH 1
+#define IGB_DEFAULT_TX_WTHRESH ((hw->mac.type == e1000_82576) ? 1 : 16)
#define IGB_HKEY_MAX_INDEX 10
#define IGB_8_BIT_MASK UINT8_MAX
/* Additional timesync values. */
-#define E1000_CYCLECOUNTER_MASK 0xffffffffffffffff
+#define E1000_CYCLECOUNTER_MASK 0xffffffffffffffffULL
#define E1000_ETQF_FILTER_1588 3
#define IGB_82576_TSYNC_SHIFT 16
#define E1000_INCPERIOD_82576 (1 << E1000_TIMINCA_16NS_SHIFT)
static void eth_igb_xstats_reset(struct rte_eth_dev *dev);
static void eth_igb_infos_get(struct rte_eth_dev *dev,
struct rte_eth_dev_info *dev_info);
+static const uint32_t *eth_igb_supported_ptypes_get(struct rte_eth_dev *dev);
static void eth_igbvf_infos_get(struct rte_eth_dev *dev,
struct rte_eth_dev_info *dev_info);
static int eth_igb_flow_ctrl_get(struct rte_eth_dev *dev,
static int eth_igb_vlan_filter_set(struct rte_eth_dev *dev,
uint16_t vlan_id, int on);
-static void eth_igb_vlan_tpid_set(struct rte_eth_dev *dev, uint16_t tpid_id);
+static int eth_igb_vlan_tpid_set(struct rte_eth_dev *dev,
+ enum rte_vlan_type vlan_type,
+ uint16_t tpid_id);
static void eth_igb_vlan_offload_set(struct rte_eth_dev *dev, int mask);
static void igb_vlan_hw_filter_enable(struct rte_eth_dev *dev);
static int igbvf_dev_start(struct rte_eth_dev *dev);
static void igbvf_dev_stop(struct rte_eth_dev *dev);
static void igbvf_dev_close(struct rte_eth_dev *dev);
+static void igbvf_promiscuous_enable(struct rte_eth_dev *dev);
+static void igbvf_promiscuous_disable(struct rte_eth_dev *dev);
+static void igbvf_allmulticast_enable(struct rte_eth_dev *dev);
+static void igbvf_allmulticast_disable(struct rte_eth_dev *dev);
static int eth_igbvf_link_update(struct e1000_hw *hw);
static void eth_igbvf_stats_get(struct rte_eth_dev *dev,
struct rte_eth_stats *rte_stats);
.stats_reset = eth_igb_stats_reset,
.xstats_reset = eth_igb_xstats_reset,
.dev_infos_get = eth_igb_infos_get,
+ .dev_supported_ptypes_get = eth_igb_supported_ptypes_get,
.mtu_set = eth_igb_mtu_set,
.vlan_filter_set = eth_igb_vlan_filter_set,
.vlan_tpid_set = eth_igb_vlan_tpid_set,
.dev_start = igbvf_dev_start,
.dev_stop = igbvf_dev_stop,
.dev_close = igbvf_dev_close,
+ .promiscuous_enable = igbvf_promiscuous_enable,
+ .promiscuous_disable = igbvf_promiscuous_disable,
+ .allmulticast_enable = igbvf_allmulticast_enable,
+ .allmulticast_disable = igbvf_allmulticast_disable,
.link_update = eth_igb_link_update,
.stats_get = eth_igbvf_stats_get,
.xstats_get = eth_igbvf_xstats_get,
.xstats_reset = eth_igbvf_stats_reset,
.vlan_filter_set = igbvf_vlan_filter_set,
.dev_infos_get = eth_igbvf_infos_get,
+ .dev_supported_ptypes_get = eth_igb_supported_ptypes_get,
.rx_queue_setup = eth_igb_rx_queue_setup,
.rx_queue_release = eth_igb_rx_queue_release,
.tx_queue_setup = eth_igb_tx_queue_setup,
err_late:
igb_hw_control_release(hw);
- return (error);
+ return error;
}
static int
struct e1000_hw *hw =
E1000_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
int diag;
+ struct ether_addr *perm_addr = (struct ether_addr *)hw->mac.perm_addr;
PMD_INIT_FUNC_TRACE();
return -ENOMEM;
}
+ /* Generate a random MAC address, if none was assigned by PF. */
+ if (is_zero_ether_addr(perm_addr)) {
+ eth_random_addr(perm_addr->addr_bytes);
+ diag = e1000_rar_set(hw, perm_addr->addr_bytes, 0);
+ if (diag) {
+ rte_free(eth_dev->data->mac_addrs);
+ eth_dev->data->mac_addrs = NULL;
+ return diag;
+ }
+ PMD_INIT_LOG(INFO, "\tVF MAC address not assigned by Host PF");
+ PMD_INIT_LOG(INFO, "\tAssign randomly generated MAC address "
+ "%02x:%02x:%02x:%02x:%02x:%02x",
+ perm_addr->addr_bytes[0],
+ perm_addr->addr_bytes[1],
+ perm_addr->addr_bytes[2],
+ perm_addr->addr_bytes[3],
+ perm_addr->addr_bytes[4],
+ perm_addr->addr_bytes[5]);
+ }
+
/* Copy the permanent MAC address */
ether_addr_copy((struct ether_addr *) hw->mac.perm_addr,
ð_dev->data->mac_addrs[0]);
PMD_INIT_FUNC_TRACE();
rte_eth_driver_register(&rte_igbvf_pmd);
- return (0);
+ return 0;
}
static int
PMD_INIT_FUNC_TRACE();
+ /* disable uio/vfio intr/eventfd mapping */
+ rte_intr_disable(intr_handle);
+
/* Power up the phy. Needed to make the link go Up */
e1000_power_up_phy(hw);
/* Initialize the hardware */
if (igb_hardware_init(hw)) {
PMD_INIT_LOG(ERR, "Unable to initialize the hardware");
- return (-EIO);
+ return -EIO;
}
adapter->stopped = 0;
PMD_INIT_LOG(DEBUG, "<<");
- return (0);
+ return 0;
error_invalid_config:
PMD_INIT_LOG(ERR, "Invalid link_speed/link_duplex (%u/%u) for port %u",
dev->data->dev_conf.link_speed,
dev->data->dev_conf.link_duplex, dev->data->port_id);
igb_dev_clear_queues(dev);
- return (-EINVAL);
+ return -EINVAL;
}
/*********************************************************************
diag = e1000_init_hw(hw);
if (diag < 0)
- return (diag);
+ return diag;
E1000_WRITE_REG(hw, E1000_VET, ETHER_TYPE_VLAN << 16 | ETHER_TYPE_VLAN);
e1000_get_phy_info(hw);
e1000_check_for_link(hw);
- return (0);
+ return 0;
}
/* This function is based on igb_update_stats_counters() in igb/if_igb.c */
rte_stats->imissed = stats->mpc;
rte_stats->ierrors = stats->crcerrs +
stats->rlec + stats->ruc + stats->roc +
- rte_stats->imissed +
stats->rxerrc + stats->algnerrc + stats->cexterr;
/* Tx Errors */
dev_info->tx_desc_lim = tx_desc_lim;
}
+static const uint32_t *
+eth_igb_supported_ptypes_get(struct rte_eth_dev *dev)
+{
+ static const uint32_t ptypes[] = {
+ /* refers to igb_rxd_pkt_info_to_pkt_type() */
+ RTE_PTYPE_L2_ETHER,
+ RTE_PTYPE_L3_IPV4,
+ RTE_PTYPE_L3_IPV4_EXT,
+ RTE_PTYPE_L3_IPV6,
+ RTE_PTYPE_L3_IPV6_EXT,
+ RTE_PTYPE_L4_TCP,
+ RTE_PTYPE_L4_UDP,
+ RTE_PTYPE_L4_SCTP,
+ RTE_PTYPE_TUNNEL_IP,
+ RTE_PTYPE_INNER_L3_IPV6,
+ RTE_PTYPE_INNER_L3_IPV6_EXT,
+ RTE_PTYPE_INNER_L4_TCP,
+ RTE_PTYPE_INNER_L4_UDP,
+ RTE_PTYPE_UNKNOWN
+ };
+
+ if (dev->rx_pkt_burst == eth_igb_recv_pkts ||
+ dev->rx_pkt_burst == eth_igb_recv_scattered_pkts)
+ return ptypes;
+ return NULL;
+}
+
static void
eth_igbvf_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
{
return 0;
}
-static void
-eth_igb_vlan_tpid_set(struct rte_eth_dev *dev, uint16_t tpid)
+static int
+eth_igb_vlan_tpid_set(struct rte_eth_dev *dev,
+ enum rte_vlan_type vlan_type,
+ uint16_t tpid)
{
struct e1000_hw *hw =
E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- uint32_t reg = ETHER_TYPE_VLAN ;
+ uint32_t reg = ETHER_TYPE_VLAN;
+ int ret = 0;
+
+ switch (vlan_type) {
+ case ETH_VLAN_TYPE_INNER:
+ reg |= (tpid << 16);
+ E1000_WRITE_REG(hw, E1000_VET, reg);
+ break;
+ default:
+ ret = -EINVAL;
+ PMD_DRV_LOG(ERR, "Unsupported vlan type %d\n", vlan_type);
+ break;
+ }
- reg |= (tpid << 16);
- E1000_WRITE_REG(hw, E1000_VET, reg);
+ return ret;
}
static void
struct e1000_hw *hw;
hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- return (e1000_led_on(hw) == E1000_SUCCESS ? 0 : -ENOTSUP);
+ return e1000_led_on(hw) == E1000_SUCCESS ? 0 : -ENOTSUP;
}
static int
struct e1000_hw *hw;
hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- return (e1000_led_off(hw) == E1000_SUCCESS ? 0 : -ENOTSUP);
+ return e1000_led_off(hw) == E1000_SUCCESS ? 0 : -ENOTSUP;
}
static int
(fc_conf->high_water < fc_conf->low_water)) {
PMD_INIT_LOG(ERR, "e1000 incorrect high/low water value");
PMD_INIT_LOG(ERR, "high water must <= 0x%x", max_high_water);
- return (-EINVAL);
+ return -EINVAL;
}
hw->fc.requested_mode = rte_fcmode_2_e1000_fcmode[fc_conf->mode];
}
PMD_INIT_LOG(ERR, "e1000_setup_link_generic = 0x%x", err);
- return (-EIO);
+ return -EIO;
}
#define E1000_RAH_POOLSEL_SHIFT (18)
struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
struct e1000_adapter *adapter =
E1000_DEV_PRIVATE(dev->data->dev_private);
+ struct ether_addr addr;
PMD_INIT_FUNC_TRACE();
igbvf_dev_stop(dev);
adapter->stopped = 1;
igb_dev_free_queues(dev);
+
+ /**
+ * reprogram the RAR with a zero mac address,
+ * to ensure that the VF traffic goes to the PF
+ * after stop, close and detach of the VF.
+ **/
+
+ memset(&addr, 0, sizeof(addr));
+ igbvf_default_mac_addr_set(dev, &addr);
+}
+
+static void
+igbvf_promiscuous_enable(struct rte_eth_dev *dev)
+{
+ struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+ /* Set both unicast and multicast promisc */
+ e1000_promisc_set_vf(hw, e1000_promisc_enabled);
+}
+
+static void
+igbvf_promiscuous_disable(struct rte_eth_dev *dev)
+{
+ struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+ /* If in allmulticast mode leave multicast promisc */
+ if (dev->data->all_multicast == 1)
+ e1000_promisc_set_vf(hw, e1000_promisc_multicast);
+ else
+ e1000_promisc_set_vf(hw, e1000_promisc_disabled);
+}
+
+static void
+igbvf_allmulticast_enable(struct rte_eth_dev *dev)
+{
+ struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+ /* In promiscuous mode multicast promisc already set */
+ if (dev->data->promiscuous == 0)
+ e1000_promisc_set_vf(hw, e1000_promisc_multicast);
+}
+
+static void
+igbvf_allmulticast_disable(struct rte_eth_dev *dev)
+{
+ struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+ /* In promiscuous mode leave multicast promisc enabled */
+ if (dev->data->promiscuous == 0)
+ e1000_promisc_set_vf(hw, e1000_promisc_disabled);
}
static int igbvf_set_vfta(struct e1000_hw *hw, uint16_t vid, bool on)