static void virtio_set_hwaddr(struct virtio_hw *hw);
static void virtio_get_hwaddr(struct virtio_hw *hw);
-static void virtio_dev_rx_queue_release(__rte_unused void *rxq);
-static void virtio_dev_tx_queue_release(__rte_unused void *txq);
-
static void virtio_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats);
static void virtio_dev_stats_reset(struct rte_eth_dev *dev);
static void virtio_dev_free_mbufs(struct rte_eth_dev *dev);
return 0;
}
+void
+virtio_dev_queue_release(struct virtqueue *vq) {
+ struct virtio_hw *hw;
+
+ if (vq) {
+ hw = vq->hw;
+ /* Select and deactivate the queue */
+ VIRTIO_WRITE_REG_2(hw, VIRTIO_PCI_QUEUE_SEL, vq->queue_id);
+ VIRTIO_WRITE_REG_4(hw, VIRTIO_PCI_QUEUE_PFN, 0);
+
+ rte_free(vq);
+ vq = NULL;
+ }
+}
+
int virtio_dev_queue_setup(struct rte_eth_dev *dev,
int queue_type,
uint16_t queue_idx,
- uint16_t vtpci_queue_idx,
+ uint16_t vtpci_queue_idx,
uint16_t nb_desc,
unsigned int socket_id,
struct virtqueue **pvq)
{
char vq_name[VIRTQUEUE_MAX_NAME_SZ];
const struct rte_memzone *mz;
- uint16_t vq_size;
- int size;
+ unsigned int vq_size, size;
struct virtio_hw *hw = dev->data->dev_private;
- struct virtqueue *vq = NULL;
+ struct virtqueue *vq = NULL;
/* Write the virtqueue index to the Queue Select Field */
VIRTIO_WRITE_REG_2(hw, VIRTIO_PCI_QUEUE_SEL, vtpci_queue_idx);
- PMD_INIT_LOG(DEBUG, "selecting queue: %d", vtpci_queue_idx);
+ PMD_INIT_LOG(DEBUG, "selecting queue: %u", vtpci_queue_idx);
/*
* Read the virtqueue size from the Queue Size field
* Always power of 2 and if 0 virtqueue does not exist
*/
vq_size = VIRTIO_READ_REG_2(hw, VIRTIO_PCI_QUEUE_NUM);
- PMD_INIT_LOG(DEBUG, "vq_size: %d nb_desc:%d", vq_size, nb_desc);
- if (nb_desc == 0)
- nb_desc = vq_size;
+ PMD_INIT_LOG(DEBUG, "vq_size: %u nb_desc:%u", vq_size, nb_desc);
if (vq_size == 0) {
PMD_INIT_LOG(ERR, "%s: virtqueue does not exist", __func__);
return -EINVAL;
return -EINVAL;
}
- if (nb_desc < vq_size) {
- if (!rte_is_power_of_2(nb_desc)) {
- PMD_INIT_LOG(ERR,
- "nb_desc(%u) size is not powerof 2",
- nb_desc);
- return -EINVAL;
- }
- vq_size = nb_desc;
- }
-
if (queue_type == VTNET_RQ) {
snprintf(vq_name, sizeof(vq_name), "port%d_rvq%d",
dev->data->port_id, queue_idx);
vq->queue_id = queue_idx;
vq->vq_queue_index = vtpci_queue_idx;
vq->vq_nentries = vq_size;
- vq->vq_free_cnt = vq_size;
+
+ if (nb_desc == 0 || nb_desc > vq_size)
+ nb_desc = vq_size;
+ vq->vq_free_cnt = nb_desc;
/*
* Reserve a memzone for vring elements
uint32_t socket_id)
{
struct virtqueue *vq;
- uint16_t nb_desc = 0;
int ret;
struct virtio_hw *hw = dev->data->dev_private;
PMD_INIT_FUNC_TRACE();
ret = virtio_dev_queue_setup(dev, VTNET_CQ, VTNET_SQ_CQ_QUEUE_IDX,
- vtpci_queue_idx, nb_desc, socket_id, &vq);
+ vtpci_queue_idx, 0, socket_id, &vq);
if (ret < 0) {
PMD_INIT_LOG(ERR, "control vq initialization failed");
return ret;
return 0;
}
+static void
+virtio_free_queues(struct rte_eth_dev *dev)
+{
+ unsigned int i;
+
+ for (i = 0; i < dev->data->nb_rx_queues; i++)
+ virtio_dev_rx_queue_release(dev->data->rx_queues[i]);
+
+ dev->data->nb_rx_queues = 0;
+
+ for (i = 0; i < dev->data->nb_tx_queues; i++)
+ virtio_dev_tx_queue_release(dev->data->tx_queues[i]);
+
+ dev->data->nb_tx_queues = 0;
+}
+
static void
virtio_dev_close(struct rte_eth_dev *dev)
{
vtpci_reset(hw);
hw->started = 0;
virtio_dev_free_mbufs(dev);
+ virtio_free_queues(dev);
}
static void
.stats_reset = virtio_dev_stats_reset,
.link_update = virtio_dev_link_update,
.rx_queue_setup = virtio_dev_rx_queue_setup,
- /* meaningfull only to multiple queue */
.rx_queue_release = virtio_dev_rx_queue_release,
.tx_queue_setup = virtio_dev_tx_queue_setup,
- /* meaningfull only to multiple queue */
.tx_queue_release = virtio_dev_tx_queue_release,
/* collect stats per queue */
.queue_stats_mapping_set = virtio_dev_queue_stats_mapping_set,
struct virtio_hw *hw = eth_dev->data->dev_private;
struct virtio_net_config *config;
struct virtio_net_config local_config;
- uint32_t offset_conf = sizeof(config->mac);
struct rte_pci_device *pci_dev;
RTE_BUILD_BUG_ON(RTE_PKTMBUF_HEADROOM < sizeof(struct virtio_net_hdr));
vtpci_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER);
virtio_negotiate_features(hw);
+ /* If host does not support status then disable LSC */
+ if (!vtpci_with_feature(hw, VIRTIO_NET_F_STATUS))
+ pci_dev->driver->drv_flags &= ~RTE_PCI_DRV_INTR_LSC;
+
rx_func_get(eth_dev);
/* Setting up rx_header size for the device */
if (vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_VQ)) {
config = &local_config;
+ vtpci_read_dev_config(hw,
+ offsetof(struct virtio_net_config, mac),
+ &config->mac, sizeof(config->mac));
+
if (vtpci_with_feature(hw, VIRTIO_NET_F_STATUS)) {
- offset_conf += sizeof(config->status);
+ vtpci_read_dev_config(hw,
+ offsetof(struct virtio_net_config, status),
+ &config->status, sizeof(config->status));
} else {
PMD_INIT_LOG(DEBUG,
"VIRTIO_NET_F_STATUS is not supported");
}
if (vtpci_with_feature(hw, VIRTIO_NET_F_MQ)) {
- offset_conf += sizeof(config->max_virtqueue_pairs);
+ vtpci_read_dev_config(hw,
+ offsetof(struct virtio_net_config, max_virtqueue_pairs),
+ &config->max_virtqueue_pairs,
+ sizeof(config->max_virtqueue_pairs));
} else {
PMD_INIT_LOG(DEBUG,
"VIRTIO_NET_F_MQ is not supported");
config->max_virtqueue_pairs = 1;
}
- vtpci_read_dev_config(hw, 0, (uint8_t *)config, offset_conf);
-
hw->max_rx_queues =
(VIRTIO_MAX_RX_QUEUES < config->max_virtqueue_pairs) ?
VIRTIO_MAX_RX_QUEUES : config->max_virtqueue_pairs;
eth_dev->tx_pkt_burst = NULL;
eth_dev->rx_pkt_burst = NULL;
- rte_free(hw->cvq);
- hw->cvq = NULL;
+ virtio_dev_queue_release(hw->cvq);
rte_free(eth_dev->data->mac_addrs);
eth_dev->data->mac_addrs = NULL;
return 0;
}
-/*
- * Only 1 queue is supported, no queue release related operation
- */
-static void
-virtio_dev_rx_queue_release(__rte_unused void *rxq)
-{
-}
-
-static void
-virtio_dev_tx_queue_release(__rte_unused void *txq)
-{
-}
-
/*
* Configure virtio device
* It returns 0 on success.
struct rte_pci_device *pci_dev = dev->pci_dev;
/* check if lsc interrupt feature is enabled */
- if ((dev->data->dev_conf.intr_conf.lsc) &&
- (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC)) {
- if (!vtpci_with_feature(hw, VIRTIO_NET_F_STATUS)) {
+ if (dev->data->dev_conf.intr_conf.lsc) {
+ if (!(pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC)) {
PMD_DRV_LOG(ERR, "link status not supported by host");
return -ENOTSUP;
}