return queue_num;
}
-
-static void
+static int
virtio_pci_legacy_setup_queue (vlib_main_t * vm, virtio_if_t * vif,
u16 queue_id, void *p)
{
u64 addr = vlib_physmem_get_pa (vm, p) >> VIRTIO_PCI_QUEUE_ADDR_SHIFT;
+ u32 addr2 = 0;
vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_SEL,
&queue_id);
vlib_pci_write_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_PFN,
(u32 *) & addr);
+ vlib_pci_read_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_PFN,
+ &addr2);
+ if ((u32) addr == addr2)
+ return 0;
+ return 1;
}
static void
}
}
-struct virtio_ctrl_mq_status_hdr
+struct virtio_ctrl_msg
{
struct virtio_net_ctrl_hdr ctrl;
- struct virtio_net_ctrl_mq num_mqs;
virtio_net_ctrl_ack status;
+ u8 data[1024];
};
static int
-virtio_pci_enable_multiqueue (vlib_main_t * vm, virtio_if_t * vif,
- u16 num_queues)
+virtio_pci_send_ctrl_msg (vlib_main_t * vm, virtio_if_t * vif,
+ struct virtio_ctrl_msg *data, u32 len)
{
virtio_main_t *vim = &virtio_main;
virtio_vring_t *vring = vif->cxq_vring;
+ virtio_net_ctrl_ack status = VIRTIO_NET_ERR;
+ struct virtio_ctrl_msg result;
u32 buffer_index;
vlib_buffer_t *b;
u16 used, next, avail;
u16 sz = vring->size;
u16 mask = sz - 1;
- struct virtio_ctrl_mq_status_hdr mq_hdr, result;
- virtio_net_ctrl_ack status = VIRTIO_NET_ERR;
-
- mq_hdr.ctrl.class = VIRTIO_NET_CTRL_MQ;
- mq_hdr.ctrl.cmd = VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET;
- mq_hdr.status = VIRTIO_NET_ERR;
- mq_hdr.num_mqs.virtqueue_pairs = num_queues;
used = vring->desc_in_use;
next = vring->desc_next;
* previous offset.
*/
b->current_data = 0;
- clib_memcpy (vlib_buffer_get_current (b), &mq_hdr,
- sizeof (struct virtio_ctrl_mq_status_hdr));
+ clib_memcpy (vlib_buffer_get_current (b), data,
+ sizeof (struct virtio_ctrl_msg));
d->flags = VRING_DESC_F_NEXT;
d->addr = vlib_buffer_get_current_pa (vm, b);
d->len = sizeof (struct virtio_net_ctrl_hdr);
d = &vring->desc[next];
d->flags = VRING_DESC_F_NEXT;
d->addr = vlib_buffer_get_current_pa (vm, b) +
- STRUCT_OFFSET_OF (struct virtio_ctrl_mq_status_hdr, num_mqs);
- d->len = sizeof (struct virtio_net_ctrl_mq);
+ STRUCT_OFFSET_OF (struct virtio_ctrl_msg, data);
+ d->len = len;
next = (next + 1) & mask;
d->next = next;
used++;
d = &vring->desc[next];
d->flags = VRING_DESC_F_WRITE;
d->addr = vlib_buffer_get_current_pa (vm, b) +
- STRUCT_OFFSET_OF (struct virtio_ctrl_mq_status_hdr, status);
- d->len = sizeof (mq_hdr.status);
+ STRUCT_OFFSET_OF (struct virtio_ctrl_msg, status);
+ d->len = sizeof (data->status);
next = (next + 1) & mask;
used++;
virtio_kick (vm, vring, vif);
}
- clib_memset (&result, 0, sizeof (result));
u16 last = vring->last_used_idx, n_left = 0;
n_left = vring->used->idx - last;
CLIB_MEMORY_BARRIER ();
clib_memcpy (&result, vlib_buffer_get_current (b),
- sizeof (struct virtio_ctrl_mq_status_hdr));
-
- virtio_log_debug (vim, vif, "multi-queue enable status on Ctrl queue : %u",
- result.status);
+ sizeof (struct virtio_ctrl_msg));
+ virtio_log_debug (vim, vif, "ctrl-queue: status %u", result.status);
status = result.status;
vlib_buffer_free (vm, &buffer_index, 1);
return status;
}
+static int
+virtio_pci_enable_multiqueue (vlib_main_t * vm, virtio_if_t * vif,
+ u16 num_queues)
+{
+ virtio_main_t *vim = &virtio_main;
+ struct virtio_ctrl_msg mq_hdr;
+ virtio_net_ctrl_ack status = VIRTIO_NET_ERR;
+
+ mq_hdr.ctrl.class = VIRTIO_NET_CTRL_MQ;
+ mq_hdr.ctrl.cmd = VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET;
+ mq_hdr.status = VIRTIO_NET_ERR;
+ clib_memcpy (mq_hdr.data, &num_queues, sizeof (num_queues));
+
+ status = virtio_pci_send_ctrl_msg (vm, vif, &mq_hdr, sizeof (num_queues));
+ virtio_log_debug (vim, vif, "multi-queue enable %u queues", num_queues);
+ return status;
+}
+
static u8
virtio_pci_queue_size_valid (u16 qsz)
{
do
{
if (n_alloc < queue_size)
- n_alloc =
+ n_alloc +=
vlib_buffer_alloc (vm, vring->indirect_buffers + n_alloc,
queue_size - n_alloc);
}
while (n_alloc != queue_size);
- vif->num_txqs++;
virtio_log_debug (vim, vif, "tx-queue: number %u, size %u", queue_num,
queue_size);
}
else
{
- vif->num_rxqs++;
virtio_log_debug (vim, vif, "rx-queue: number %u, size %u", queue_num,
queue_size);
}
vring->size = queue_size;
- virtio_pci_legacy_setup_queue (vm, vif, queue_num, ptr);
- vring->kick_fd = -1;
+ if (virtio_pci_legacy_setup_queue (vm, vif, queue_num, ptr))
+ return clib_error_return (0, "error in queue address setup");
+ vring->kick_fd = -1;
return error;
}
for (int i = 0; i < vif->max_queue_pairs; i++)
{
if ((error = virtio_pci_vring_init (vm, vif, RX_QUEUE (i))))
- virtio_log_warning (vim, vif, "%s (%u) %s", "error in rxq-queue",
- RX_QUEUE (i), "initialization");
+ {
+ virtio_log_warning (vim, vif, "%s (%u) %s", "error in rxq-queue",
+ RX_QUEUE (i), "initialization");
+ }
+ else
+ {
+ vif->num_rxqs++;
+ }
if ((error = virtio_pci_vring_init (vm, vif, TX_QUEUE (i))))
- virtio_log_warning (vim, vif, "%s (%u) %s", "error in txq-queue",
- TX_QUEUE (i), "initialization");
+ {
+ virtio_log_warning (vim, vif, "%s (%u) %s", "error in txq-queue",
+ TX_QUEUE (i), "initialization");
+ }
+ else
+ {
+ vif->num_txqs++;
+ }
}
if (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ))
vlib_pci_dev_handle_t h;
clib_error_t *error = 0;
- if (args->rxq_size == 0)
- args->rxq_size = VIRTIO_NUM_RX_DESC;
- if (args->txq_size == 0)
- args->txq_size = VIRTIO_NUM_TX_DESC;
-
- if (!virtio_pci_queue_size_valid (args->rxq_size) ||
- !virtio_pci_queue_size_valid (args->txq_size))
- {
- args->rv = VNET_API_ERROR_INVALID_VALUE;
- args->error =
- clib_error_return (error,
- "queue size must be <= 4096, >= 64, "
- "and multiples of 64");
- vlib_log (VLIB_LOG_LEVEL_ERR, vim->log_default, "%U: %s",
- format_vlib_pci_addr, &args->addr,
- "queue size must be <= 4096, >= 64, and multiples of 64");
- return;
- }
-
/* *INDENT-OFF* */
pool_foreach (vif, vim->interfaces, ({
if (vif->pci_addr.as_u32 == args->addr)