static void igbvf_dev_stop(struct rte_eth_dev *dev);
static void igbvf_dev_close(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);
+static void eth_igbvf_stats_get(struct rte_eth_dev *dev,
+ struct rte_eth_stats *rte_stats);
+static int eth_igbvf_xstats_get(struct rte_eth_dev *dev,
+ struct rte_eth_xstats *xstats, unsigned n);
static void eth_igbvf_stats_reset(struct rte_eth_dev *dev);
static int igbvf_vlan_filter_set(struct rte_eth_dev *dev,
uint16_t vlan_id, int on);
.dev_close = igbvf_dev_close,
.link_update = eth_igb_link_update,
.stats_get = eth_igbvf_stats_get,
+ .xstats_get = eth_igbvf_xstats_get,
.stats_reset = eth_igbvf_stats_reset,
+ .xstats_reset = eth_igbvf_stats_reset,
.vlan_filter_set = igbvf_vlan_filter_set,
.dev_infos_get = eth_igbvf_infos_get,
.rx_queue_setup = eth_igb_rx_queue_setup,
#define IGB_NB_XSTATS (sizeof(rte_igb_stats_strings) / \
sizeof(rte_igb_stats_strings[0]))
+static const struct rte_igb_xstats_name_off rte_igbvf_stats_strings[] = {
+ {"rx_multicast_packets", offsetof(struct e1000_vf_stats, mprc)},
+ {"rx_good_loopback_packets", offsetof(struct e1000_vf_stats, gprlbc)},
+ {"tx_good_loopback_packets", offsetof(struct e1000_vf_stats, gptlbc)},
+ {"rx_good_loopback_bytes", offsetof(struct e1000_vf_stats, gorlbc)},
+ {"tx_good_loopback_bytes", offsetof(struct e1000_vf_stats, gotlbc)},
+};
+
+#define IGBVF_NB_XSTATS (sizeof(rte_igbvf_stats_strings) / \
+ sizeof(rte_igbvf_stats_strings[0]))
+
/**
* Atomically reads the link status information from global
* structure rte_eth_dev.
uint32_t ctrl_ext;
pci_dev = eth_dev->pci_dev;
+
+ rte_eth_copy_pci_info(eth_dev, pci_dev);
+
eth_dev->dev_ops = ð_igb_ops;
eth_dev->rx_pkt_burst = ð_igb_recv_pkts;
eth_dev->tx_pkt_burst = ð_igb_xmit_pkts;
pci_dev = eth_dev->pci_dev;
+ rte_eth_copy_pci_info(eth_dev, pci_dev);
+
hw->device_id = pci_dev->id.device_id;
hw->vendor_id = pci_dev->id.vendor_id;
hw->hw_addr = (void *)pci_dev->mem_resource[0].addr;
igb_pf_host_configure(dev);
/* check and configure queue intr-vector mapping */
- if (dev->data->dev_conf.intr_conf.rxq != 0)
+ if (dev->data->dev_conf.intr_conf.rxq != 0) {
intr_vector = dev->data->nb_rx_queues;
-
- if (rte_intr_efd_enable(intr_handle, intr_vector))
- return -1;
+ if (rte_intr_efd_enable(intr_handle, intr_vector))
+ return -1;
+ }
if (rte_intr_dp_is_en(intr_handle)) {
intr_handle->intr_vec =
}
static void
-eth_igbvf_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
+igbvf_read_stats_registers(struct e1000_hw *hw, struct e1000_vf_stats *hw_stats)
{
- struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- struct e1000_vf_stats *hw_stats = (struct e1000_vf_stats*)
- E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
-
/* Good Rx packets, include VF loopback */
UPDATE_VF_STAT(E1000_VFGPRC,
hw_stats->last_gprc, hw_stats->gprc);
/* Good Tx loopback octets */
UPDATE_VF_STAT(E1000_VFGOTLBC,
hw_stats->last_gotlbc, hw_stats->gotlbc);
+}
+
+static int
+eth_igbvf_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+ unsigned n)
+{
+ struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct e1000_vf_stats *hw_stats = (struct e1000_vf_stats *)
+ E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+ unsigned i;
+
+ if (n < IGBVF_NB_XSTATS)
+ return IGBVF_NB_XSTATS;
+
+ igbvf_read_stats_registers(hw, hw_stats);
+
+ if (!xstats)
+ return 0;
+
+ for (i = 0; i < IGBVF_NB_XSTATS; i++) {
+ snprintf(xstats[i].name, sizeof(xstats[i].name), "%s",
+ rte_igbvf_stats_strings[i].name);
+ xstats[i].value = *(uint64_t *)(((char *)hw_stats) +
+ rte_igbvf_stats_strings[i].offset);
+ }
+
+ return IGBVF_NB_XSTATS;
+}
+
+static void
+eth_igbvf_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
+{
+ struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct e1000_vf_stats *hw_stats = (struct e1000_vf_stats *)
+ E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+
+ igbvf_read_stats_registers(hw, hw_stats);
if (rte_stats == NULL)
return;
/* reset HW current stats*/
memset(&hw_stats->gprc, 0, sizeof(*hw_stats) -
offsetof(struct e1000_vf_stats, gprc));
-
}
static void
uint32_t tmpval, regval, intr_mask;
struct e1000_hw *hw =
E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- uint32_t vec = 0;
+ uint32_t vec = E1000_MISC_VEC_ID;
+ uint32_t base = E1000_MISC_VEC_ID;
+ uint32_t misc_shift = 0;
+
struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle;
/* won't configure msix register if no mapping is done
if (!rte_intr_dp_is_en(intr_handle))
return;
+ if (rte_intr_allow_others(intr_handle)) {
+ vec = base = E1000_RX_VEC_START;
+ misc_shift = 1;
+ }
+
/* set interrupt vector for other causes */
if (hw->mac.type == e1000_82575) {
tmpval = E1000_READ_REG(hw, E1000_CTRL_EXT);
E1000_WRITE_REG(hw, E1000_GPIE, E1000_GPIE_MSIX_MODE |
E1000_GPIE_PBA | E1000_GPIE_EIAME |
E1000_GPIE_NSICR);
-
- intr_mask = (1 << intr_handle->max_intr) - 1;
+ intr_mask = RTE_LEN2MASK(intr_handle->nb_efd, uint32_t) <<
+ misc_shift;
regval = E1000_READ_REG(hw, E1000_EIAC);
E1000_WRITE_REG(hw, E1000_EIAC, regval | intr_mask);
/* use EIAM to auto-mask when MSI-X interrupt
* is asserted, this saves a register write for every interrupt
*/
- intr_mask = (1 << intr_handle->nb_efd) - 1;
+ intr_mask = RTE_LEN2MASK(intr_handle->nb_efd, uint32_t) <<
+ misc_shift;
regval = E1000_READ_REG(hw, E1000_EIAM);
E1000_WRITE_REG(hw, E1000_EIAM, regval | intr_mask);
for (queue_id = 0; queue_id < dev->data->nb_rx_queues; queue_id++) {
eth_igb_assign_msix_vector(hw, 0, queue_id, vec);
intr_handle->intr_vec[queue_id] = vec;
- if (vec < intr_handle->nb_efd - 1)
+ if (vec < base + intr_handle->nb_efd - 1)
vec++;
}