xen: allow determining DOM0 at runtime
[dpdk.git] / lib / librte_ether / rte_ethdev.c
index c7247c3..0e41387 100644 (file)
@@ -137,27 +137,30 @@ struct rte_eth_xstats_name_off {
 };
 
 static const struct rte_eth_xstats_name_off rte_stats_strings[] = {
-       {"rx_packets", offsetof(struct rte_eth_stats, ipackets)},
-       {"tx_packets", offsetof(struct rte_eth_stats, opackets)},
-       {"rx_bytes", offsetof(struct rte_eth_stats, ibytes)},
-       {"tx_bytes", offsetof(struct rte_eth_stats, obytes)},
-       {"tx_errors", offsetof(struct rte_eth_stats, oerrors)},
+       {"rx_good_packets", offsetof(struct rte_eth_stats, ipackets)},
+       {"tx_good_packets", offsetof(struct rte_eth_stats, opackets)},
+       {"rx_good_bytes", offsetof(struct rte_eth_stats, ibytes)},
+       {"tx_good_bytes", offsetof(struct rte_eth_stats, obytes)},
        {"rx_errors", offsetof(struct rte_eth_stats, ierrors)},
-       {"alloc_rx_buff_failed", offsetof(struct rte_eth_stats, rx_nombuf)},
+       {"tx_errors", offsetof(struct rte_eth_stats, oerrors)},
+       {"rx_mbuf_allocation_errors", offsetof(struct rte_eth_stats,
+               rx_nombuf)},
 };
+
 #define RTE_NB_STATS (sizeof(rte_stats_strings) / sizeof(rte_stats_strings[0]))
 
 static const struct rte_eth_xstats_name_off rte_rxq_stats_strings[] = {
-       {"rx_packets", offsetof(struct rte_eth_stats, q_ipackets)},
-       {"rx_bytes", offsetof(struct rte_eth_stats, q_ibytes)},
+       {"packets", offsetof(struct rte_eth_stats, q_ipackets)},
+       {"bytes", offsetof(struct rte_eth_stats, q_ibytes)},
+       {"errors", offsetof(struct rte_eth_stats, q_errors)},
 };
+
 #define RTE_NB_RXQ_STATS (sizeof(rte_rxq_stats_strings) /      \
                sizeof(rte_rxq_stats_strings[0]))
 
 static const struct rte_eth_xstats_name_off rte_txq_stats_strings[] = {
-       {"tx_packets", offsetof(struct rte_eth_stats, q_opackets)},
-       {"tx_bytes", offsetof(struct rte_eth_stats, q_obytes)},
-       {"tx_errors", offsetof(struct rte_eth_stats, q_errors)},
+       {"packets", offsetof(struct rte_eth_stats, q_opackets)},
+       {"bytes", offsetof(struct rte_eth_stats, q_obytes)},
 };
 #define RTE_NB_TXQ_STATS (sizeof(rte_txq_stats_strings) /      \
                sizeof(rte_txq_stats_strings[0]))
@@ -424,7 +427,7 @@ rte_eth_dev_socket_id(uint8_t port_id)
 {
        if (!rte_eth_dev_is_valid_port(port_id))
                return -1;
-       return rte_eth_devices[port_id].pci_dev->numa_node;
+       return rte_eth_devices[port_id].data->numa_node;
 }
 
 uint8_t
@@ -441,32 +444,6 @@ rte_eth_dev_get_device_type(uint8_t port_id)
        return rte_eth_devices[port_id].dev_type;
 }
 
-static int
-rte_eth_dev_save(struct rte_eth_dev *devs, size_t size)
-{
-       if ((devs == NULL) ||
-           (size != sizeof(struct rte_eth_dev) * RTE_MAX_ETHPORTS))
-               return -EINVAL;
-
-       /* save current rte_eth_devices */
-       memcpy(devs, rte_eth_devices, size);
-       return 0;
-}
-
-static int
-rte_eth_dev_get_changed_port(struct rte_eth_dev *devs, uint8_t *port_id)
-{
-       if ((devs == NULL) || (port_id == NULL))
-               return -EINVAL;
-
-       /* check which port was attached or detached */
-       for (*port_id = 0; *port_id < RTE_MAX_ETHPORTS; (*port_id)++, devs++) {
-               if (rte_eth_devices[*port_id].attached ^ devs->attached)
-                       return 0;
-       }
-       return -ENODEV;
-}
-
 static int
 rte_eth_dev_get_addr_by_port(uint8_t port_id, struct rte_pci_addr *addr)
 {
@@ -500,60 +477,100 @@ rte_eth_dev_get_name_by_port(uint8_t port_id, char *name)
        return 0;
 }
 
+static int
+rte_eth_dev_get_port_by_name(const char *name, uint8_t *port_id)
+{
+       int i;
+
+       if (name == NULL) {
+               PMD_DEBUG_TRACE("Null pointer is specified\n");
+               return -EINVAL;
+       }
+
+       *port_id = RTE_MAX_ETHPORTS;
+
+       for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
+
+               if (!strncmp(name,
+                       rte_eth_dev_data[i].name, strlen(name))) {
+
+                       *port_id = i;
+
+                       return 0;
+               }
+       }
+       return -ENODEV;
+}
+
+static int
+rte_eth_dev_get_port_by_addr(const struct rte_pci_addr *addr, uint8_t *port_id)
+{
+       int i;
+       struct rte_pci_device *pci_dev = NULL;
+
+       if (addr == NULL) {
+               PMD_DEBUG_TRACE("Null pointer is specified\n");
+               return -EINVAL;
+       }
+
+       *port_id = RTE_MAX_ETHPORTS;
+
+       for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
+
+               pci_dev = rte_eth_devices[i].pci_dev;
+
+               if (pci_dev &&
+                       !rte_eal_compare_pci_addr(&pci_dev->addr, addr)) {
+
+                       *port_id = i;
+
+                       return 0;
+               }
+       }
+       return -ENODEV;
+}
+
 static int
 rte_eth_dev_is_detachable(uint8_t port_id)
 {
-       uint32_t drv_flags;
+       uint32_t dev_flags;
 
        if (!rte_eth_dev_is_valid_port(port_id)) {
                PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
                return -EINVAL;
        }
 
-       if (rte_eth_devices[port_id].dev_type == RTE_ETH_DEV_PCI) {
-               switch (rte_eth_devices[port_id].pci_dev->kdrv) {
-               case RTE_KDRV_IGB_UIO:
-               case RTE_KDRV_UIO_GENERIC:
-               case RTE_KDRV_NIC_UIO:
-                       break;
-               case RTE_KDRV_VFIO:
-               default:
-                       return -ENOTSUP;
-               }
+       switch (rte_eth_devices[port_id].data->kdrv) {
+       case RTE_KDRV_IGB_UIO:
+       case RTE_KDRV_UIO_GENERIC:
+       case RTE_KDRV_NIC_UIO:
+       case RTE_KDRV_NONE:
+               break;
+       case RTE_KDRV_VFIO:
+       default:
+               return -ENOTSUP;
        }
-
-       drv_flags = rte_eth_devices[port_id].driver->pci_drv.drv_flags;
-       return !(drv_flags & RTE_PCI_DRV_DETACHABLE);
+       dev_flags = rte_eth_devices[port_id].data->dev_flags;
+       return !(dev_flags & RTE_ETH_DEV_DETACHABLE);
 }
 
 /* attach the new physical device, then store port_id of the device */
 static int
 rte_eth_dev_attach_pdev(struct rte_pci_addr *addr, uint8_t *port_id)
 {
-       uint8_t new_port_id;
-       struct rte_eth_dev devs[RTE_MAX_ETHPORTS];
-
        if ((addr == NULL) || (port_id == NULL))
                goto err;
 
-       /* save current port status */
-       if (rte_eth_dev_save(devs, sizeof(devs)))
-               goto err;
        /* re-construct pci_device_list */
        if (rte_eal_pci_scan())
                goto err;
-       /* invoke probe func of the driver can handle the new device.
-        * TODO:
-        * rte_eal_pci_probe_one() should return port_id.
-        * And rte_eth_dev_save() and rte_eth_dev_get_changed_port()
-        * should be removed. */
+       /* Invoke probe func of the driver can handle the new device. */
        if (rte_eal_pci_probe_one(addr))
                goto err;
-       /* get port_id enabled by above procedures */
-       if (rte_eth_dev_get_changed_port(devs, &new_port_id))
+
+       if (rte_eth_dev_get_port_by_addr(addr, port_id))
                goto err;
 
-       *port_id = new_port_id;
        return 0;
 err:
        RTE_LOG(ERR, EAL, "Driver, cannot attach the device\n");
@@ -600,8 +617,6 @@ static int
 rte_eth_dev_attach_vdev(const char *vdevargs, uint8_t *port_id)
 {
        char *name = NULL, *args = NULL;
-       uint8_t new_port_id;
-       struct rte_eth_dev devs[RTE_MAX_ETHPORTS];
        int ret = -1;
 
        if ((vdevargs == NULL) || (port_id == NULL))
@@ -611,22 +626,18 @@ rte_eth_dev_attach_vdev(const char *vdevargs, uint8_t *port_id)
        if (rte_eal_parse_devargs_str(vdevargs, &name, &args))
                goto end;
 
-       /* save current port status */
-       if (rte_eth_dev_save(devs, sizeof(devs)))
-               goto end;
        /* walk around dev_driver_list to find the driver of the device,
-        * then invoke probe function o the driver.
-        * TODO:
-        * rte_eal_vdev_init() should return port_id,
-        * And rte_eth_dev_save() and rte_eth_dev_get_changed_port()
-        * should be removed. */
+        * then invoke probe function of the driver.
+        * rte_eal_vdev_init() updates port_id allocated after
+        * initialization.
+        */
        if (rte_eal_vdev_init(name, args))
                goto end;
-       /* get port_id enabled by above procedures */
-       if (rte_eth_dev_get_changed_port(devs, &new_port_id))
+
+       if (rte_eth_dev_get_port_by_name(name, port_id))
                goto end;
+
        ret = 0;
-       *port_id = new_port_id;
 end:
        if (name)
                free(name);
@@ -767,6 +778,13 @@ rte_eth_dev_rx_queue_start(uint8_t port_id, uint16_t rx_queue_id)
 
        FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rx_queue_start, -ENOTSUP);
 
+       if (dev->data->rx_queue_state[rx_queue_id] != RTE_ETH_QUEUE_STATE_STOPPED) {
+               PMD_DEBUG_TRACE("Queue %" PRIu16" of device with port_id=%" PRIu8
+                       " already started\n",
+                       rx_queue_id, port_id);
+               return 0;
+       }
+
        return dev->dev_ops->rx_queue_start(dev, rx_queue_id);
 
 }
@@ -790,6 +808,13 @@ rte_eth_dev_rx_queue_stop(uint8_t port_id, uint16_t rx_queue_id)
 
        FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rx_queue_stop, -ENOTSUP);
 
+       if (dev->data->rx_queue_state[rx_queue_id] == RTE_ETH_QUEUE_STATE_STOPPED) {
+               PMD_DEBUG_TRACE("Queue %" PRIu16" of device with port_id=%" PRIu8
+                       " already stopped\n",
+                       rx_queue_id, port_id);
+               return 0;
+       }
+
        return dev->dev_ops->rx_queue_stop(dev, rx_queue_id);
 
 }
@@ -813,6 +838,13 @@ rte_eth_dev_tx_queue_start(uint8_t port_id, uint16_t tx_queue_id)
 
        FUNC_PTR_OR_ERR_RET(*dev->dev_ops->tx_queue_start, -ENOTSUP);
 
+       if (dev->data->tx_queue_state[tx_queue_id] != RTE_ETH_QUEUE_STATE_STOPPED) {
+               PMD_DEBUG_TRACE("Queue %" PRIu16" of device with port_id=%" PRIu8
+                       " already started\n",
+                       tx_queue_id, port_id);
+               return 0;
+       }
+
        return dev->dev_ops->tx_queue_start(dev, tx_queue_id);
 
 }
@@ -836,6 +868,13 @@ rte_eth_dev_tx_queue_stop(uint8_t port_id, uint16_t tx_queue_id)
 
        FUNC_PTR_OR_ERR_RET(*dev->dev_ops->tx_queue_stop, -ENOTSUP);
 
+       if (dev->data->tx_queue_state[tx_queue_id] == RTE_ETH_QUEUE_STATE_STOPPED) {
+               PMD_DEBUG_TRACE("Queue %" PRIu16" of device with port_id=%" PRIu8
+                       " already stopped\n",
+                       tx_queue_id, port_id);
+               return 0;
+       }
+
        return dev->dev_ops->tx_queue_stop(dev, tx_queue_id);
 
 }
@@ -952,14 +991,11 @@ rte_eth_dev_configure(uint8_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q,
         * If link state interrupt is enabled, check that the
         * device supports it.
         */
-       if (dev_conf->intr_conf.lsc == 1) {
-               const struct rte_pci_driver *pci_drv = &dev->driver->pci_drv;
-
-               if (!(pci_drv->drv_flags & RTE_PCI_DRV_INTR_LSC)) {
+       if ((dev_conf->intr_conf.lsc == 1) &&
+               (!(dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC))) {
                        PMD_DEBUG_TRACE("driver %s does not support lsc\n",
-                                       pci_drv->name);
+                                       dev->data->drv_name);
                        return -EINVAL;
-               }
        }
 
        /*
@@ -1101,7 +1137,7 @@ rte_eth_dev_start(uint8_t port_id)
 
        rte_eth_dev_config_restore(port_id);
 
-       if (dev->data->dev_conf.intr_conf.lsc != 0) {
+       if (dev->data->dev_conf.intr_conf.lsc == 0) {
                FUNC_PTR_OR_ERR_RET(*dev->dev_ops->link_update, -ENOTSUP);
                (*dev->dev_ops->link_update)(dev, 0);
        }
@@ -1248,6 +1284,19 @@ rte_eth_rx_queue_setup(uint8_t port_id, uint16_t rx_queue_id,
                return -EINVAL;
        }
 
+       if (nb_rx_desc > dev_info.rx_desc_lim.nb_max ||
+                       nb_rx_desc < dev_info.rx_desc_lim.nb_min ||
+                       nb_rx_desc % dev_info.rx_desc_lim.nb_align != 0) {
+
+               PMD_DEBUG_TRACE("Invalid value for nb_rx_desc(=%hu), "
+                       "should be: <= %hu, = %hu, and a product of %hu\n",
+                       nb_rx_desc,
+                       dev_info.rx_desc_lim.nb_max,
+                       dev_info.rx_desc_lim.nb_min,
+                       dev_info.rx_desc_lim.nb_align);
+               return -EINVAL;
+       }
+
        if (rx_conf == NULL)
                rx_conf = &dev_info.default_rxconf;
 
@@ -1466,9 +1515,8 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
        dev = &rte_eth_devices[port_id];
 
        /* Return generic statistics */
-       count = RTE_NB_STATS;
-       count += dev->data->nb_rx_queues * RTE_NB_RXQ_STATS;
-       count += dev->data->nb_tx_queues * RTE_NB_TXQ_STATS;
+       count = RTE_NB_STATS + (dev->data->nb_rx_queues * RTE_NB_RXQ_STATS) +
+               (dev->data->nb_tx_queues * RTE_NB_TXQ_STATS);
 
        /* implemented by the driver */
        if (dev->dev_ops->xstats_get != NULL) {
@@ -1507,7 +1555,7 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
                                        q * sizeof(uint64_t));
                        val = *stats_ptr;
                        snprintf(xstats[count].name, sizeof(xstats[count].name),
-                               "rx_queue_%u_%s", q,
+                               "rx_q%u_%s", q,
                                rte_rxq_stats_strings[i].name);
                        xstats[count++].value = val;
                }
@@ -1521,7 +1569,7 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
                                        q * sizeof(uint64_t));
                        val = *stats_ptr;
                        snprintf(xstats[count].name, sizeof(xstats[count].name),
-                               "tx_queue_%u_%s", q,
+                               "tx_q%u_%s", q,
                                rte_txq_stats_strings[i].name);
                        xstats[count++].value = val;
                }
@@ -1587,17 +1635,23 @@ void
 rte_eth_dev_info_get(uint8_t port_id, struct rte_eth_dev_info *dev_info)
 {
        struct rte_eth_dev *dev;
+       const struct rte_eth_desc_lim lim = {
+               .nb_max = UINT16_MAX,
+               .nb_min = 0,
+               .nb_align = 1,
+       };
 
        VALID_PORTID_OR_RET(port_id);
        dev = &rte_eth_devices[port_id];
 
        memset(dev_info, 0, sizeof(struct rte_eth_dev_info));
+       dev_info->rx_desc_lim = lim;
+       dev_info->tx_desc_lim = lim;
 
        FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get);
        (*dev->dev_ops->dev_infos_get)(dev, dev_info);
        dev_info->pci_dev = dev->pci_dev;
-       if (dev->driver)
-               dev_info->driver_name = dev->driver->pci_drv.name;
+       dev_info->driver_name = dev->data->drv_name;
 }
 
 void
@@ -2640,6 +2694,30 @@ rte_eth_dev_rx_intr_ctl(uint8_t port_id, int epfd, int op, void *data)
        return 0;
 }
 
+const struct rte_memzone *
+rte_eth_dma_zone_reserve(const struct rte_eth_dev *dev, const char *ring_name,
+                        uint16_t queue_id, size_t size, unsigned align,
+                        int socket_id)
+{
+       char z_name[RTE_MEMZONE_NAMESIZE];
+       const struct rte_memzone *mz;
+
+       snprintf(z_name, sizeof(z_name), "%s_%s_%d_%d",
+                dev->driver->pci_drv.name, ring_name,
+                dev->data->port_id, queue_id);
+
+       mz = rte_memzone_lookup(z_name);
+       if (mz)
+               return mz;
+
+       if (is_xen_dom0_supported())
+               return rte_memzone_reserve_bounded(z_name, size, socket_id,
+                                                  0, align, RTE_PGSIZE_2M);
+       else
+               return rte_memzone_reserve_aligned(z_name, size, socket_id,
+                                                  0, align);
+}
+
 int
 rte_eth_dev_rx_intr_ctl_q(uint8_t port_id, uint16_t queue_id,
                          int epfd, int op, void *data)
@@ -3021,6 +3099,54 @@ rte_eth_remove_tx_callback(uint8_t port_id, uint16_t queue_id,
        return -EINVAL;
 }
 
+int
+rte_eth_rx_queue_info_get(uint8_t port_id, uint16_t queue_id,
+       struct rte_eth_rxq_info *qinfo)
+{
+       struct rte_eth_dev *dev;
+
+       VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+       if (qinfo == NULL)
+               return -EINVAL;
+
+       dev = &rte_eth_devices[port_id];
+       if (queue_id >= dev->data->nb_rx_queues) {
+               PMD_DEBUG_TRACE("Invalid RX queue_id=%d\n", queue_id);
+               return -EINVAL;
+       }
+
+       FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rxq_info_get, -ENOTSUP);
+
+       memset(qinfo, 0, sizeof(*qinfo));
+       dev->dev_ops->rxq_info_get(dev, queue_id, qinfo);
+       return 0;
+}
+
+int
+rte_eth_tx_queue_info_get(uint8_t port_id, uint16_t queue_id,
+       struct rte_eth_txq_info *qinfo)
+{
+       struct rte_eth_dev *dev;
+
+       VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+       if (qinfo == NULL)
+               return -EINVAL;
+
+       dev = &rte_eth_devices[port_id];
+       if (queue_id >= dev->data->nb_tx_queues) {
+               PMD_DEBUG_TRACE("Invalid TX queue_id=%d\n", queue_id);
+               return -EINVAL;
+       }
+
+       FUNC_PTR_OR_ERR_RET(*dev->dev_ops->txq_info_get, -ENOTSUP);
+
+       memset(qinfo, 0, sizeof(*qinfo));
+       dev->dev_ops->txq_info_get(dev, queue_id, qinfo);
+       return 0;
+}
+
 int
 rte_eth_dev_set_mc_addr_list(uint8_t port_id,
                             struct ether_addr *mc_addr_set,
@@ -3143,3 +3269,41 @@ rte_eth_dev_set_eeprom(uint8_t port_id, struct rte_dev_eeprom_info *info)
        FUNC_PTR_OR_ERR_RET(*dev->dev_ops->set_eeprom, -ENOTSUP);
        return (*dev->dev_ops->set_eeprom)(dev, info);
 }
+
+int
+rte_eth_dev_get_dcb_info(uint8_t port_id,
+                            struct rte_eth_dcb_info *dcb_info)
+{
+       struct rte_eth_dev *dev;
+
+       if (!rte_eth_dev_is_valid_port(port_id)) {
+               PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id);
+               return -ENODEV;
+       }
+
+       dev = &rte_eth_devices[port_id];
+       memset(dcb_info, 0, sizeof(struct rte_eth_dcb_info));
+
+       FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_dcb_info, -ENOTSUP);
+       return (*dev->dev_ops->get_dcb_info)(dev, dcb_info);
+}
+
+void
+rte_eth_copy_pci_info(struct rte_eth_dev *eth_dev, struct rte_pci_device *pci_dev)
+{
+       if ((eth_dev == NULL) || (pci_dev == NULL)) {
+               PMD_DEBUG_TRACE("NULL pointer eth_dev=%p pci_dev=%p\n",
+                               eth_dev, pci_dev);
+               return;
+       }
+
+       eth_dev->data->dev_flags = 0;
+       if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC)
+               eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC;
+       if (pci_dev->driver->drv_flags & RTE_PCI_DRV_DETACHABLE)
+               eth_dev->data->dev_flags |= RTE_ETH_DEV_DETACHABLE;
+
+       eth_dev->data->kdrv = pci_dev->kdrv;
+       eth_dev->data->numa_node = pci_dev->numa_node;
+       eth_dev->data->drv_name = pci_dev->driver->name;
+}