net/txgbe: fix queue statistics mapping
[dpdk.git] / drivers / net / virtio / virtio_ethdev.c
index 0de3406..d180162 100644 (file)
@@ -84,6 +84,8 @@ static int virtio_mac_addr_set(struct rte_eth_dev *dev,
                                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,
@@ -1051,6 +1053,7 @@ static const struct eth_dev_ops virtio_eth_dev_ops = {
        .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,
 };
 
 /*
@@ -1382,6 +1385,59 @@ virtio_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_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)
 {
@@ -1787,6 +1843,31 @@ virtio_configure_intr(struct rte_eth_dev *dev)
        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)
 {
@@ -1947,7 +2028,8 @@ virtio_dev_rss_hash_update(struct rte_eth_dev *dev,
 
        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;
 
@@ -2169,19 +2251,10 @@ virtio_init_device(struct rte_eth_dev *eth_dev, uint64_t req_features)
                     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",
@@ -2585,7 +2658,7 @@ virtio_dev_configure(struct rte_eth_dev *dev)
        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");
@@ -2703,7 +2776,7 @@ virtio_dev_start(struct rte_eth_dev *dev)
                }
        }
 
-       /* 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.
         */
@@ -2908,11 +2981,15 @@ virtio_dev_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complet
                                     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);