+/*
+ * Configure the hardware to generate MSI-X interrupts.
+ * If setting up MSIx fails, try setting up MSI (only 1 interrupt vector
+ * which will be disabled to allow lsc to work).
+ *
+ * Returns 0 on success and -1 otherwise.
+ */
+static int
+vmxnet3_configure_msix(struct rte_eth_dev *dev)
+{
+ struct vmxnet3_hw *hw = dev->data->dev_private;
+ struct rte_intr_handle *intr_handle = dev->intr_handle;
+ uint16_t intr_vector;
+ int i;
+
+ hw->intr.event_intr_idx = 0;
+
+ /* only vfio-pci driver can support interrupt mode. */
+ if (!rte_intr_cap_multiple(intr_handle) ||
+ dev->data->dev_conf.intr_conf.rxq == 0)
+ return -1;
+
+ intr_vector = dev->data->nb_rx_queues;
+ if (intr_vector > MAX_RX_QUEUES(hw)) {
+ PMD_INIT_LOG(ERR, "At most %d intr queues supported",
+ MAX_RX_QUEUES(hw));
+ return -ENOTSUP;
+ }
+
+ if (rte_intr_efd_enable(intr_handle, intr_vector)) {
+ PMD_INIT_LOG(ERR, "Failed to enable fastpath event fd");
+ return -1;
+ }
+
+ if (rte_intr_dp_is_en(intr_handle)) {
+ if (rte_intr_vec_list_alloc(intr_handle, "intr_vec",
+ dev->data->nb_rx_queues)) {
+ PMD_INIT_LOG(ERR, "Failed to allocate %d Rx queues intr_vec",
+ dev->data->nb_rx_queues);
+ rte_intr_efd_disable(intr_handle);
+ return -ENOMEM;
+ }
+ }
+
+ if (!rte_intr_allow_others(intr_handle) &&
+ dev->data->dev_conf.intr_conf.lsc != 0) {
+ PMD_INIT_LOG(ERR, "not enough intr vector to support both Rx interrupt and LSC");
+ rte_intr_vec_list_free(intr_handle);
+ rte_intr_efd_disable(intr_handle);
+ return -1;
+ }
+
+ /* if we cannot allocate one MSI-X vector per queue, don't enable
+ * interrupt mode.
+ */
+ if (hw->intr.num_intrs !=
+ (rte_intr_nb_efd_get(intr_handle) + 1)) {
+ PMD_INIT_LOG(ERR, "Device configured with %d Rx intr vectors, expecting %d",
+ hw->intr.num_intrs,
+ rte_intr_nb_efd_get(intr_handle) + 1);
+ rte_intr_vec_list_free(intr_handle);
+ rte_intr_efd_disable(intr_handle);
+ return -1;
+ }
+
+ for (i = 0; i < dev->data->nb_rx_queues; i++)
+ if (rte_intr_vec_list_index_set(intr_handle, i, i + 1))
+ return -rte_errno;
+
+ for (i = 0; i < hw->intr.num_intrs; i++)
+ hw->intr.mod_levels[i] = UPT1_IML_ADAPTIVE;
+
+ PMD_INIT_LOG(INFO, "intr type %u, mode %u, %u vectors allocated",
+ hw->intr.type, hw->intr.mask_mode, hw->intr.num_intrs);
+
+ return 0;
+}
+