struct rte_ether_addr *mac_addr);
static int virtio_intr_disable(struct rte_eth_dev *dev);
+static int virtio_get_monitor_addr(void *rx_queue,
+ struct rte_power_monitor_cond *pmc);
static int virtio_dev_queue_stats_mapping_set(
struct rte_eth_dev *eth_dev,
.mac_addr_add = virtio_mac_addr_add,
.mac_addr_remove = virtio_mac_addr_remove,
.mac_addr_set = virtio_mac_addr_set,
+ .get_monitor_addr = virtio_get_monitor_addr,
};
/*
return 0;
}
+#define CLB_VAL_IDX 0
+#define CLB_MSK_IDX 1
+#define CLB_MATCH_IDX 2
+static int
+virtio_monitor_callback(const uint64_t value,
+ const uint64_t opaque[RTE_POWER_MONITOR_OPAQUE_SZ])
+{
+ const uint64_t m = opaque[CLB_MSK_IDX];
+ const uint64_t v = opaque[CLB_VAL_IDX];
+ const uint64_t c = opaque[CLB_MATCH_IDX];
+
+ if (c)
+ return (value & m) == v ? -1 : 0;
+ else
+ return (value & m) == v ? 0 : -1;
+}
+
+static int
+virtio_get_monitor_addr(void *rx_queue, struct rte_power_monitor_cond *pmc)
+{
+ struct virtnet_rx *rxvq = rx_queue;
+ struct virtqueue *vq = virtnet_rxq_to_vq(rxvq);
+ struct virtio_hw *hw;
+
+ if (vq == NULL)
+ return -EINVAL;
+
+ hw = vq->hw;
+ if (virtio_with_packed_queue(hw)) {
+ struct vring_packed_desc *desc;
+ desc = vq->vq_packed.ring.desc;
+ pmc->addr = &desc[vq->vq_used_cons_idx].flags;
+ if (vq->vq_packed.used_wrap_counter)
+ pmc->opaque[CLB_VAL_IDX] =
+ VRING_PACKED_DESC_F_AVAIL_USED;
+ else
+ pmc->opaque[CLB_VAL_IDX] = 0;
+ pmc->opaque[CLB_MSK_IDX] = VRING_PACKED_DESC_F_AVAIL_USED;
+ pmc->opaque[CLB_MATCH_IDX] = 1;
+ pmc->size = sizeof(desc[vq->vq_used_cons_idx].flags);
+ } else {
+ pmc->addr = &vq->vq_split.ring.used->idx;
+ pmc->opaque[CLB_VAL_IDX] = vq->vq_used_cons_idx
+ & (vq->vq_nentries - 1);
+ pmc->opaque[CLB_MSK_IDX] = vq->vq_nentries - 1;
+ pmc->opaque[CLB_MATCH_IDX] = 0;
+ pmc->size = sizeof(vq->vq_split.ring.used->idx);
+ }
+ pmc->fn = virtio_monitor_callback;
+
+ return 0;
+}
+
static int
virtio_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
{
return 0;
}
+static void
+virtio_get_speed_duplex(struct rte_eth_dev *eth_dev,
+ struct rte_eth_link *link)
+{
+ struct virtio_hw *hw = eth_dev->data->dev_private;
+ struct virtio_net_config *config;
+ struct virtio_net_config local_config;
+
+ config = &local_config;
+ virtio_read_dev_config(hw,
+ offsetof(struct virtio_net_config, speed),
+ &config->speed, sizeof(config->speed));
+ virtio_read_dev_config(hw,
+ offsetof(struct virtio_net_config, duplex),
+ &config->duplex, sizeof(config->duplex));
+ hw->speed = config->speed;
+ hw->duplex = config->duplex;
+ if (link != NULL) {
+ link->link_duplex = hw->duplex;
+ link->link_speed = hw->speed;
+ }
+ PMD_INIT_LOG(DEBUG, "link speed = %d, duplex = %d",
+ hw->speed, hw->duplex);
+}
+
static uint64_t
ethdev_to_virtio_rss_offloads(uint64_t ethdev_hash_types)
{
return 0;
restore_key:
- memcpy(hw->rss_key, old_rss_key, VIRTIO_NET_RSS_KEY_SIZE);
+ if (rss_conf->rss_key && rss_conf->rss_key_len)
+ memcpy(hw->rss_key, old_rss_key, VIRTIO_NET_RSS_KEY_SIZE);
restore_types:
hw->rss_hash_types = old_hash_types;
hw->mac_addr[0], hw->mac_addr[1], hw->mac_addr[2],
hw->mac_addr[3], hw->mac_addr[4], hw->mac_addr[5]);
- if (hw->speed == RTE_ETH_SPEED_NUM_UNKNOWN) {
- if (virtio_with_feature(hw, VIRTIO_NET_F_SPEED_DUPLEX)) {
- config = &local_config;
- virtio_read_dev_config(hw,
- offsetof(struct virtio_net_config, speed),
- &config->speed, sizeof(config->speed));
- virtio_read_dev_config(hw,
- offsetof(struct virtio_net_config, duplex),
- &config->duplex, sizeof(config->duplex));
- hw->speed = config->speed;
- hw->duplex = config->duplex;
- }
- }
+ hw->get_speed_via_feat = hw->speed == RTE_ETH_SPEED_NUM_UNKNOWN &&
+ virtio_with_feature(hw, VIRTIO_NET_F_SPEED_DUPLEX);
+ if (hw->get_speed_via_feat)
+ virtio_get_speed_duplex(eth_dev, NULL);
if (hw->duplex == DUPLEX_UNKNOWN)
hw->duplex = RTE_ETH_LINK_FULL_DUPLEX;
PMD_INIT_LOG(DEBUG, "link speed = %d, duplex = %d",
hw->has_rx_offload = rx_offload_enabled(hw);
if (dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC)
- /* Enable vector (0) for Link State Intrerrupt */
+ /* Enable vector (0) for Link State Interrupt */
if (VIRTIO_OPS(hw)->set_config_irq(hw, 0) ==
VIRTIO_MSI_NO_VECTOR) {
PMD_DRV_LOG(ERR, "failed to set config vector");
}
}
- /* Enable uio/vfio intr/eventfd mapping: althrough we already did that
+ /* Enable uio/vfio intr/eventfd mapping: although we already did that
* in device configure, but it could be unmapped when device is
* stopped.
*/
dev->data->port_id);
} else {
link.link_status = RTE_ETH_LINK_UP;
+ if (hw->get_speed_via_feat)
+ virtio_get_speed_duplex(dev, &link);
PMD_INIT_LOG(DEBUG, "Port %d is up",
dev->data->port_id);
}
} else {
link.link_status = RTE_ETH_LINK_UP;
+ if (hw->get_speed_via_feat)
+ virtio_get_speed_duplex(dev, &link);
}
return rte_eth_linkstatus_set(dev, &link);