virtio_log_debug (vif, "max queue pair is %x", max_queue_pairs);
if (max_queue_pairs < 1 || max_queue_pairs > 0x8000)
- return clib_error_return (error, "max queue pair is %x", max_queue_pairs);
+ return clib_error_return (error, "max queue pair is %x,"
+ " should be in range [1, 0x8000]",
+ max_queue_pairs);
vif->max_queue_pairs = max_queue_pairs;
return error;
}
static void
-virtio_pci_irq_0_handler (vlib_main_t * vm, vlib_pci_dev_handle_t h, u16 line)
+virtio_pci_irq_queue_handler (vlib_main_t * vm, vlib_pci_dev_handle_t h,
+ u16 line)
{
vnet_main_t *vnm = vnet_get_main ();
virtio_main_t *vim = &virtio_main;
uword pd = vlib_pci_get_private_data (vm, h);
virtio_if_t *vif = pool_elt_at_index (vim->interfaces, pd);
+ line--;
u16 qid = line;
vnet_device_input_set_interrupt_pending (vnm, vif->hw_if_index, qid);
}
static void
-virtio_pci_irq_1_handler (vlib_main_t * vm, vlib_pci_dev_handle_t h, u16 line)
+virtio_pci_irq_config_handler (vlib_main_t * vm, vlib_pci_dev_handle_t h,
+ u16 line)
{
vnet_main_t *vnm = vnet_get_main ();
virtio_main_t *vim = &virtio_main;
* been made by the device which requires servicing.
*/
if (isr & VIRTIO_PCI_ISR_INTR)
- virtio_pci_irq_0_handler (vm, h, line);
+ {
+ for (; line < vif->num_rxqs; line++)
+ virtio_pci_irq_queue_handler (vm, h, (line + 1));
+ }
if (isr & VIRTIO_PCI_ISR_CONFIG)
- virtio_pci_irq_1_handler (vm, h, line);
+ virtio_pci_irq_config_handler (vm, h, line);
}
inline void
vring->used = vr.used;
vring->queue_id = queue_num;
vring->avail->flags = VIRTIO_RING_FLAG_MASK_INT;
+ vring->flow_table = 0;
ASSERT (vring->buffers == 0);
vec_validate_aligned (vring->buffers, queue_size, CLIB_CACHE_LINE_BYTES);
{
virtio_log_debug (vif, "msix interrupt enabled");
vif->msix_enabled = VIRTIO_MSIX_ENABLED;
+ vif->msix_table_size = table_size;
}
else
{
virtio_log_debug (vif, "msix interrupt disabled");
vif->msix_enabled = VIRTIO_MSIX_DISABLED;
+ vif->msix_table_size = 0;
}
}
u8 status = 0;
if ((error = virtio_pci_read_caps (vm, vif)))
- clib_error_return (error, "Device is not supported");
+ {
+ args->rv = VNET_API_ERROR_UNSUPPORTED;
+ virtio_log_error (vif, "Device is not supported");
+ clib_error_return (error, "Device is not supported");
+ }
if (virtio_pci_reset_device (vm, vif) < 0)
{
+ args->rv = VNET_API_ERROR_INIT_FAILED;
virtio_log_error (vif, "Failed to reset the device");
clib_error_return (error, "Failed to reset the device");
}
* read device features and negotiate (user) requested features
*/
virtio_pci_read_device_feature (vm, vif);
+ if ((vif->remote_features & VIRTIO_FEATURE (VIRTIO_RING_F_INDIRECT_DESC)) ==
+ 0)
+ {
+ virtio_log_warning (vif, "error encountered: vhost-net backend doesn't "
+ "support VIRTIO_RING_F_INDIRECT_DESC features");
+ }
+ if ((vif->remote_features & VIRTIO_FEATURE (VIRTIO_NET_F_MRG_RXBUF)) == 0)
+ {
+ virtio_log_warning (vif, "error encountered: vhost-net backend doesn't "
+ "support VIRTIO_NET_F_MRG_RXBUF features");
+ }
virtio_negotiate_features (vm, vif, args->features);
/*
status = virtio_pci_legacy_get_status (vm, vif);
if (!(status & VIRTIO_CONFIG_STATUS_FEATURES_OK))
{
+ args->rv = VNET_API_ERROR_UNSUPPORTED;
virtio_log_error (vif,
"error encountered: Device doesn't support requested features");
clib_error_return (error, "Device doesn't support requested features");
* Initialize the virtqueues
*/
if ((error = virtio_pci_get_max_virtqueue_pairs (vm, vif)))
- goto err;
+ {
+ args->rv = VNET_API_ERROR_EXCEEDED_NUMBER_OF_RANGES_CAPACITY;
+ goto err;
+ }
+
+ if (vif->msix_enabled == VIRTIO_MSIX_ENABLED)
+ {
+ if (vif->msix_table_size <= vif->max_queue_pairs)
+ {
+ virtio_log_error (vif,
+ "error MSIX lines (%u) <= Number of RXQs (%u)",
+ vif->msix_table_size, vif->max_queue_pairs);
+ return clib_error_return (error,
+ "error MSIX lines (%u) <= Number of RXQs (%u)",
+ vif->msix_table_size,
+ vif->max_queue_pairs);
+ }
+ }
for (int i = 0; i < vif->max_queue_pairs; i++)
{
if ((error = virtio_pci_vring_init (vm, vif, RX_QUEUE (i))))
{
- virtio_log_warning (vif, "%s (%u) %s", "error in rxq-queue",
- RX_QUEUE (i), "initialization");
+ args->rv = VNET_API_ERROR_INIT_FAILED;
+ virtio_log_error (vif, "%s (%u) %s", "error in rxq-queue",
+ RX_QUEUE (i), "initialization");
+ clib_error_return (error, "%s (%u) %s", "error in rxq-queue",
+ RX_QUEUE (i), "initialization");
}
else
{
if ((error = virtio_pci_vring_init (vm, vif, TX_QUEUE (i))))
{
- virtio_log_warning (vif, "%s (%u) %s", "error in txq-queue",
- TX_QUEUE (i), "initialization");
+ args->rv = VNET_API_ERROR_INIT_FAILED;
+ virtio_log_error (vif, "%s (%u) %s", "error in txq-queue",
+ TX_QUEUE (i), "initialization");
+ clib_error_return (error, "%s (%u) %s", "error in txq-queue",
+ TX_QUEUE (i), "initialization");
}
else
{
*/
if (vif->msix_enabled == VIRTIO_MSIX_ENABLED)
{
- if (virtio_pci_legacy_set_config_irq (vm, vif, 1) ==
- VIRTIO_MSI_NO_VECTOR)
- virtio_log_warning (vif, "config vector 1 is not set");
- if (virtio_pci_legacy_set_queue_irq (vm, vif, 0, 0) ==
+ int i, j;
+ if (virtio_pci_legacy_set_config_irq (vm, vif, 0) ==
VIRTIO_MSI_NO_VECTOR)
- virtio_log_warning (vif, "queue vector 0 is not set");
+ {
+ virtio_log_warning (vif, "config vector 0 is not set");
+ }
+ else
+ {
+ virtio_log_debug (vif, "config msix vector is set at 0");
+ }
+ for (i = 0, j = 1; i < vif->max_queue_pairs; i++, j++)
+ {
+ if (virtio_pci_legacy_set_queue_irq (vm, vif, j, RX_QUEUE (i)) ==
+ VIRTIO_MSI_NO_VECTOR)
+ {
+ virtio_log_warning (vif, "queue (%u) vector is not set at %u",
+ RX_QUEUE (i), j);
+ }
+ else
+ {
+ virtio_log_debug (vif, "%s (%u) %s %u", "queue",
+ RX_QUEUE (i), "msix vector is set at", j);
+ }
+ }
}
/*
virtio_if_t *vif;
vlib_pci_dev_handle_t h;
clib_error_t *error = 0;
+ u32 interrupt_count = 0;
/* *INDENT-OFF* */
pool_foreach (vif, vim->interfaces, ({
if (vif->pci_addr.as_u32 == args->addr)
{
- args->rv = VNET_API_ERROR_INVALID_VALUE;
+ args->rv = VNET_API_ERROR_ADDRESS_IN_USE;
args->error =
clib_error_return (error, "PCI address in use");
vlib_log (VLIB_LOG_LEVEL_ERR, vim->log_default, "%U: %s",
goto error;
}
- if (vlib_pci_get_num_msix_interrupts (vm, h) > 1)
+ interrupt_count = vlib_pci_get_num_msix_interrupts (vm, h);
+ if (interrupt_count > 1)
{
if ((error = vlib_pci_register_msix_handler (vm, h, 0, 1,
- &virtio_pci_irq_0_handler)))
+ &virtio_pci_irq_config_handler)))
{
+ args->rv = VNET_API_ERROR_INVALID_REGISTRATION;
virtio_log_error (vif,
"error encountered on pci register msix handler 0");
goto error;
}
- if ((error = vlib_pci_register_msix_handler (vm, h, 1, 1,
- &virtio_pci_irq_1_handler)))
+
+ if ((error =
+ vlib_pci_register_msix_handler (vm, h, 1, (interrupt_count - 1),
+ &virtio_pci_irq_queue_handler)))
{
+ args->rv = VNET_API_ERROR_INVALID_REGISTRATION;
virtio_log_error (vif,
"error encountered on pci register msix handler 1");
goto error;
}
- if ((error = vlib_pci_enable_msix_irq (vm, h, 0, 2)))
+ if ((error = vlib_pci_enable_msix_irq (vm, h, 0, interrupt_count)))
{
virtio_log_error (vif, "error encountered on pci enable msix irq");
goto error;
vif->support_int_mode = 1;
virtio_log_debug (vif, "device supports msix interrupts");
}
- else if (vlib_pci_get_num_msix_interrupts (vm, h) == 1)
+ else if (interrupt_count == 1)
{
/*
* if msix table-size is 1, fall back to intX.
if (error)
{
+ args->rv = VNET_API_ERROR_INVALID_REGISTRATION;
virtio_log_error (vif,
"error encountered on ethernet register interface");
goto error;
error:
virtio_pci_delete_if (vm, vif);
- args->rv = VNET_API_ERROR_INVALID_INTERFACE;
+ if (args->rv == 0)
+ args->rv = VNET_API_ERROR_INVALID_INTERFACE;
args->error = error;
}