+static int
+dpdk_eth_dev_queue_setup(struct netdev_dpdk *dev, int n_rxq, int n_txq)
+{
+ int diag = 0;
+ int i;
+
+ /* A device may report more queues than it makes available (this has
+ * been observed for Intel xl710, which reserves some of them for
+ * SRIOV): rte_eth_*_queue_setup will fail if a queue is not
+ * available. When this happens we can retry the configuration
+ * and request less queues */
+ while (n_rxq && n_txq) {
+ if (diag) {
+ VLOG_INFO("Retrying setup with (rxq:%d txq:%d)", n_rxq, n_txq);
+ }
+
+ diag = rte_eth_dev_configure(dev->port_id, n_rxq, n_txq, &port_conf);
+ if (diag) {
+ break;
+ }
+
+ for (i = 0; i < n_txq; i++) {
+ diag = rte_eth_tx_queue_setup(dev->port_id, i, NIC_PORT_TX_Q_SIZE,
+ dev->socket_id, NULL);
+ if (diag) {
+ VLOG_INFO("Interface %s txq(%d) setup error: %s",
+ dev->up.name, i, rte_strerror(-diag));
+ break;
+ }
+ }
+
+ if (i != n_txq) {
+ /* Retry with less tx queues */
+ n_txq = i;
+ continue;
+ }
+
+ for (i = 0; i < n_rxq; i++) {
+ diag = rte_eth_rx_queue_setup(dev->port_id, i, NIC_PORT_RX_Q_SIZE,
+ dev->socket_id, NULL,
+ dev->dpdk_mp->mp);
+ if (diag) {
+ VLOG_INFO("Interface %s rxq(%d) setup error: %s",
+ dev->up.name, i, rte_strerror(-diag));
+ break;
+ }
+ }
+
+ if (i != n_rxq) {
+ /* Retry with less rx queues */
+ n_rxq = i;
+ continue;
+ }
+
+ dev->up.n_rxq = n_rxq;
+ dev->real_n_txq = n_txq;
+
+ return 0;
+ }
+
+ return diag;
+}
+
+