X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Flibrte_ether%2Frte_ethdev.c;h=3a304437f32e3a73599f0330f9b701601a3066aa;hb=c8231c63ddcb;hp=030a87781a081bfdda6f16ef81094aed7702ce1d;hpb=c49b2bad6a028fa53b09699c6cae10143e6f3a3e;p=dpdk.git diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index 030a87781a..3a304437f3 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -1,7 +1,7 @@ /*- * BSD LICENSE * - * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. + * Copyright(c) 2010-2016 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -77,6 +77,12 @@ static uint8_t nb_ports; /* spinlock for eth device callbacks */ static rte_spinlock_t rte_eth_dev_cb_lock = RTE_SPINLOCK_INITIALIZER; +/* spinlock for add/remove rx callbacks */ +static rte_spinlock_t rte_eth_rx_cb_lock = RTE_SPINLOCK_INITIALIZER; + +/* spinlock for add/remove tx callbacks */ +static rte_spinlock_t rte_eth_tx_cb_lock = RTE_SPINLOCK_INITIALIZER; + /* store statistics names and its offset in stats structure */ struct rte_eth_xstats_name_off { char name[RTE_ETH_XSTATS_NAME_SIZE]; @@ -369,8 +375,7 @@ rte_eth_dev_is_valid_port(uint8_t port_id) int rte_eth_dev_socket_id(uint8_t port_id) { - if (!rte_eth_dev_is_valid_port(port_id)) - return -1; + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -1); return rte_eth_devices[port_id].data->numa_node; } @@ -383,8 +388,7 @@ rte_eth_dev_count(void) static enum rte_eth_dev_type rte_eth_dev_get_device_type(uint8_t port_id) { - if (!rte_eth_dev_is_valid_port(port_id)) - return RTE_ETH_DEV_UNKNOWN; + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, RTE_ETH_DEV_UNKNOWN); return rte_eth_devices[port_id].dev_type; } @@ -479,10 +483,7 @@ rte_eth_dev_is_detachable(uint8_t port_id) { uint32_t dev_flags; - if (!rte_eth_dev_is_valid_port(port_id)) { - RTE_PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id); - return -EINVAL; - } + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL); switch (rte_eth_devices[port_id].data->kdrv) { case RTE_KDRV_IGB_UIO: @@ -495,7 +496,11 @@ rte_eth_dev_is_detachable(uint8_t port_id) return -ENOTSUP; } dev_flags = rte_eth_devices[port_id].data->dev_flags; - return !(dev_flags & RTE_ETH_DEV_DETACHABLE); + if ((dev_flags & RTE_ETH_DEV_DETACHABLE) && + (!(dev_flags & RTE_ETH_DEV_BONDED_SLAVE))) + return 0; + else + return 1; } /* attach the new physical device, then store port_id of the device */ @@ -862,6 +867,39 @@ rte_eth_dev_tx_queue_config(struct rte_eth_dev *dev, uint16_t nb_queues) return 0; } +uint32_t +rte_eth_speed_bitflag(uint32_t speed, int duplex) +{ + switch (speed) { + case ETH_SPEED_NUM_10M: + return duplex ? ETH_LINK_SPEED_10M : ETH_LINK_SPEED_10M_HD; + case ETH_SPEED_NUM_100M: + return duplex ? ETH_LINK_SPEED_100M : ETH_LINK_SPEED_100M_HD; + case ETH_SPEED_NUM_1G: + return ETH_LINK_SPEED_1G; + case ETH_SPEED_NUM_2_5G: + return ETH_LINK_SPEED_2_5G; + case ETH_SPEED_NUM_5G: + return ETH_LINK_SPEED_5G; + case ETH_SPEED_NUM_10G: + return ETH_LINK_SPEED_10G; + case ETH_SPEED_NUM_20G: + return ETH_LINK_SPEED_20G; + case ETH_SPEED_NUM_25G: + return ETH_LINK_SPEED_25G; + case ETH_SPEED_NUM_40G: + return ETH_LINK_SPEED_40G; + case ETH_SPEED_NUM_50G: + return ETH_LINK_SPEED_50G; + case ETH_SPEED_NUM_56G: + return ETH_LINK_SPEED_56G; + case ETH_SPEED_NUM_100G: + return ETH_LINK_SPEED_100G; + default: + return 0; + } +} + int rte_eth_dev_configure(uint8_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q, const struct rte_eth_conf *dev_conf) @@ -897,6 +935,9 @@ rte_eth_dev_configure(uint8_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q, return -EBUSY; } + /* Copy the dev_conf parameter into the dev structure */ + memcpy(&dev->data->dev_conf, dev_conf, sizeof(dev->data->dev_conf)); + /* * Check that the numbers of RX and TX queues are not greater * than the maximum number of RX and TX queues supported by the @@ -921,9 +962,6 @@ rte_eth_dev_configure(uint8_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q, return -EINVAL; } - /* Copy the dev_conf parameter into the dev structure */ - memcpy(&dev->data->dev_conf, dev_conf, sizeof(dev->data->dev_conf)); - /* * If link state interrupt is enabled, check that the * device supports it. @@ -1305,15 +1343,18 @@ rte_eth_tx_buffer_set_err_callback(struct rte_eth_dev_tx_buffer *buffer, int rte_eth_tx_buffer_init(struct rte_eth_dev_tx_buffer *buffer, uint16_t size) { + int ret = 0; + if (buffer == NULL) return -EINVAL; buffer->size = size; - if (buffer->error_callback == NULL) - rte_eth_tx_buffer_set_err_callback(buffer, - rte_eth_tx_buffer_drop_callback, NULL); + if (buffer->error_callback == NULL) { + ret = rte_eth_tx_buffer_set_err_callback( + buffer, rte_eth_tx_buffer_drop_callback, NULL); + } - return 0; + return ret; } void @@ -1467,9 +1508,88 @@ rte_eth_stats_reset(uint8_t port_id) dev->data->rx_mbuf_alloc_failed = 0; } +static int +get_xstats_count(uint8_t port_id) +{ + struct rte_eth_dev *dev; + int count; + + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL); + dev = &rte_eth_devices[port_id]; + if (dev->dev_ops->xstats_get_names != NULL) { + count = (*dev->dev_ops->xstats_get_names)(dev, NULL, 0); + if (count < 0) + return count; + } else + count = 0; + count += RTE_NB_STATS; + count += dev->data->nb_rx_queues * RTE_NB_RXQ_STATS; + count += dev->data->nb_tx_queues * RTE_NB_TXQ_STATS; + return count; +} + +int +rte_eth_xstats_get_names(uint8_t port_id, + struct rte_eth_xstat_name *xstats_names, + unsigned size) +{ + struct rte_eth_dev *dev; + int cnt_used_entries; + int cnt_expected_entries; + uint32_t idx, id_queue; + + cnt_expected_entries = get_xstats_count(port_id); + if (xstats_names == NULL || cnt_expected_entries < 0 || + (int)size < cnt_expected_entries) + return cnt_expected_entries; + + /* port_id checked in get_xstats_count() */ + dev = &rte_eth_devices[port_id]; + if (dev->dev_ops->xstats_get_names != NULL) { + cnt_used_entries = (*dev->dev_ops->xstats_get_names)( + dev, xstats_names, size); + if (cnt_used_entries < 0) + return cnt_used_entries; + } else + /* Driver itself does not support extended stats, but + * still have basic stats. + */ + cnt_used_entries = 0; + + for (idx = 0; idx < RTE_NB_STATS; idx++) { + xstats_names[cnt_used_entries].id = cnt_used_entries; + snprintf(xstats_names[cnt_used_entries].name, + sizeof(xstats_names[0].name), + "%s", rte_stats_strings[idx].name); + cnt_used_entries++; + } + for (id_queue = 0; id_queue < dev->data->nb_rx_queues; id_queue++) { + for (idx = 0; idx < RTE_NB_RXQ_STATS; idx++) { + xstats_names[cnt_used_entries].id = cnt_used_entries; + snprintf(xstats_names[cnt_used_entries].name, + sizeof(xstats_names[0].name), + "rx_q%u%s", + id_queue, rte_rxq_stats_strings[idx].name); + cnt_used_entries++; + } + + } + for (id_queue = 0; id_queue < dev->data->nb_tx_queues; id_queue++) { + for (idx = 0; idx < RTE_NB_TXQ_STATS; idx++) { + xstats_names[cnt_used_entries].id = cnt_used_entries; + snprintf(xstats_names[cnt_used_entries].name, + sizeof(xstats_names[0].name), + "tx_q%u%s", + id_queue, rte_txq_stats_strings[idx].name); + cnt_used_entries++; + } + } + return cnt_used_entries; +} + /* retrieve ethdev extended statistics */ int -rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats, +rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstat *xstats, unsigned n) { struct rte_eth_stats eth_stats; @@ -1491,14 +1611,15 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats, /* Retrieve the xstats from the driver at the end of the * xstats struct. */ - xcount = (*dev->dev_ops->xstats_get)(dev, &xstats[count], - (n > count) ? n - count : 0); + xcount = (*dev->dev_ops->xstats_get)(dev, + xstats ? xstats + count : NULL, + (n > count) ? n - count : 0); if (xcount < 0) return xcount; } - if (n < count + xcount) + if (n < count + xcount || xstats == NULL) return count + xcount; /* now fill the xstats structure */ @@ -1510,8 +1631,7 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats, stats_ptr = RTE_PTR_ADD(ð_stats, rte_stats_strings[i].offset); val = *stats_ptr; - snprintf(xstats[count].name, sizeof(xstats[count].name), - "%s", rte_stats_strings[i].name); + xstats[count].id = count + xcount; xstats[count++].value = val; } @@ -1522,9 +1642,7 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats, rte_rxq_stats_strings[i].offset + q * sizeof(uint64_t)); val = *stats_ptr; - snprintf(xstats[count].name, sizeof(xstats[count].name), - "rx_q%u_%s", q, - rte_rxq_stats_strings[i].name); + xstats[count].id = count + xcount; xstats[count++].value = val; } } @@ -1536,9 +1654,7 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats, rte_txq_stats_strings[i].offset + q * sizeof(uint64_t)); val = *stats_ptr; - snprintf(xstats[count].name, sizeof(xstats[count].name), - "tx_q%u_%s", q, - rte_txq_stats_strings[i].name); + xstats[count].id = count + xcount; xstats[count++].value = val; } } @@ -1598,7 +1714,6 @@ rte_eth_dev_set_rx_queue_stats_mapping(uint8_t port_id, uint16_t rx_queue_id, STAT_QMAP_RX); } - void rte_eth_dev_info_get(uint8_t port_id, struct rte_eth_dev_info *dev_info) { @@ -1622,6 +1737,32 @@ rte_eth_dev_info_get(uint8_t port_id, struct rte_eth_dev_info *dev_info) dev_info->driver_name = dev->data->drv_name; } +int +rte_eth_dev_get_supported_ptypes(uint8_t port_id, uint32_t ptype_mask, + uint32_t *ptypes, int num) +{ + int i, j; + struct rte_eth_dev *dev; + const uint32_t *all_ptypes; + + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); + dev = &rte_eth_devices[port_id]; + RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_supported_ptypes_get, 0); + all_ptypes = (*dev->dev_ops->dev_supported_ptypes_get)(dev); + + if (!all_ptypes) + return 0; + + for (i = 0, j = 0; all_ptypes[i] != RTE_PTYPE_UNKNOWN; ++i) + if (all_ptypes[i] & ptype_mask) { + if (j < num) + ptypes[j] = all_ptypes[i]; + j++; + } + + return j; +} + void rte_eth_macaddr_get(uint8_t port_id, struct ether_addr *mac_addr) { @@ -1927,10 +2068,7 @@ rte_eth_dev_rss_reta_query(uint8_t port_id, struct rte_eth_dev *dev; int ret; - if (port_id >= nb_ports) { - RTE_PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id); - return -ENODEV; - } + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); /* Check mask bits */ ret = rte_eth_check_reta_mask(reta_conf, reta_size); @@ -1974,8 +2112,8 @@ rte_eth_dev_rss_hash_conf_get(uint8_t port_id, } int -rte_eth_dev_udp_tunnel_add(uint8_t port_id, - struct rte_eth_udp_tunnel *udp_tunnel) +rte_eth_dev_udp_tunnel_port_add(uint8_t port_id, + struct rte_eth_udp_tunnel *udp_tunnel) { struct rte_eth_dev *dev; @@ -1991,13 +2129,13 @@ rte_eth_dev_udp_tunnel_add(uint8_t port_id, } dev = &rte_eth_devices[port_id]; - RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->udp_tunnel_add, -ENOTSUP); - return (*dev->dev_ops->udp_tunnel_add)(dev, udp_tunnel); + RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->udp_tunnel_port_add, -ENOTSUP); + return (*dev->dev_ops->udp_tunnel_port_add)(dev, udp_tunnel); } int -rte_eth_dev_udp_tunnel_delete(uint8_t port_id, - struct rte_eth_udp_tunnel *udp_tunnel) +rte_eth_dev_udp_tunnel_port_delete(uint8_t port_id, + struct rte_eth_udp_tunnel *udp_tunnel) { struct rte_eth_dev *dev; @@ -2014,8 +2152,8 @@ rte_eth_dev_udp_tunnel_delete(uint8_t port_id, return -EINVAL; } - RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->udp_tunnel_del, -ENOTSUP); - return (*dev->dev_ops->udp_tunnel_del)(dev, udp_tunnel); + RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->udp_tunnel_port_del, -ENOTSUP); + return (*dev->dev_ops->udp_tunnel_port_del)(dev, udp_tunnel); } int @@ -2574,10 +2712,7 @@ rte_eth_dev_rx_intr_ctl(uint8_t port_id, int epfd, int op, void *data) uint16_t qid; int rc; - if (!rte_eth_dev_is_valid_port(port_id)) { - RTE_PMD_DEBUG_TRACE("Invalid port_id=%u\n", port_id); - return -ENODEV; - } + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; intr_handle = &dev->pci_dev->intr_handle; @@ -2632,10 +2767,7 @@ rte_eth_dev_rx_intr_ctl_q(uint8_t port_id, uint16_t queue_id, struct rte_intr_handle *intr_handle; int rc; - if (!rte_eth_dev_is_valid_port(port_id)) { - RTE_PMD_DEBUG_TRACE("Invalid port_id=%u\n", port_id); - return -ENODEV; - } + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; if (queue_id >= dev->data->nb_rx_queues) { @@ -2667,10 +2799,7 @@ rte_eth_dev_rx_intr_enable(uint8_t port_id, { struct rte_eth_dev *dev; - if (!rte_eth_dev_is_valid_port(port_id)) { - RTE_PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id); - return -ENODEV; - } + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; @@ -2684,10 +2813,7 @@ rte_eth_dev_rx_intr_disable(uint8_t port_id, { struct rte_eth_dev *dev; - if (!rte_eth_dev_is_valid_port(port_id)) { - RTE_PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id); - return -ENODEV; - } + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; @@ -2858,7 +2984,6 @@ rte_eth_add_rx_callback(uint8_t port_id, uint16_t queue_id, rte_errno = EINVAL; return NULL; } - struct rte_eth_rxtx_callback *cb = rte_zmalloc(NULL, sizeof(*cb), 0); if (cb == NULL) { @@ -2869,6 +2994,7 @@ rte_eth_add_rx_callback(uint8_t port_id, uint16_t queue_id, cb->fn.rx = fn; cb->param = user_param; + rte_spinlock_lock(&rte_eth_rx_cb_lock); /* Add the callbacks in fifo order. */ struct rte_eth_rxtx_callback *tail = rte_eth_devices[port_id].post_rx_burst_cbs[queue_id]; @@ -2881,6 +3007,42 @@ rte_eth_add_rx_callback(uint8_t port_id, uint16_t queue_id, tail = tail->next; tail->next = cb; } + rte_spinlock_unlock(&rte_eth_rx_cb_lock); + + return cb; +} + +void * +rte_eth_add_first_rx_callback(uint8_t port_id, uint16_t queue_id, + rte_rx_callback_fn fn, void *user_param) +{ +#ifndef RTE_ETHDEV_RXTX_CALLBACKS + rte_errno = ENOTSUP; + return NULL; +#endif + /* check input parameters */ + if (!rte_eth_dev_is_valid_port(port_id) || fn == NULL || + queue_id >= rte_eth_devices[port_id].data->nb_rx_queues) { + rte_errno = EINVAL; + return NULL; + } + + struct rte_eth_rxtx_callback *cb = rte_zmalloc(NULL, sizeof(*cb), 0); + + if (cb == NULL) { + rte_errno = ENOMEM; + return NULL; + } + + cb->fn.rx = fn; + cb->param = user_param; + + rte_spinlock_lock(&rte_eth_rx_cb_lock); + /* Add the callbacks at fisrt position*/ + cb->next = rte_eth_devices[port_id].post_rx_burst_cbs[queue_id]; + rte_smp_wmb(); + rte_eth_devices[port_id].post_rx_burst_cbs[queue_id] = cb; + rte_spinlock_unlock(&rte_eth_rx_cb_lock); return cb; } @@ -2910,6 +3072,7 @@ rte_eth_add_tx_callback(uint8_t port_id, uint16_t queue_id, cb->fn.tx = fn; cb->param = user_param; + rte_spinlock_lock(&rte_eth_tx_cb_lock); /* Add the callbacks in fifo order. */ struct rte_eth_rxtx_callback *tail = rte_eth_devices[port_id].pre_tx_burst_cbs[queue_id]; @@ -2922,6 +3085,7 @@ rte_eth_add_tx_callback(uint8_t port_id, uint16_t queue_id, tail = tail->next; tail->next = cb; } + rte_spinlock_unlock(&rte_eth_tx_cb_lock); return cb; } @@ -2934,35 +3098,30 @@ rte_eth_remove_rx_callback(uint8_t port_id, uint16_t queue_id, return -ENOTSUP; #endif /* Check input parameters. */ - if (!rte_eth_dev_is_valid_port(port_id) || user_cb == NULL || - queue_id >= rte_eth_devices[port_id].data->nb_rx_queues) { + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL); + if (user_cb == NULL || + queue_id >= rte_eth_devices[port_id].data->nb_rx_queues) return -EINVAL; - } struct rte_eth_dev *dev = &rte_eth_devices[port_id]; - struct rte_eth_rxtx_callback *cb = dev->post_rx_burst_cbs[queue_id]; - struct rte_eth_rxtx_callback *prev_cb; - - /* Reset head pointer and remove user cb if first in the list. */ - if (cb == user_cb) { - dev->post_rx_burst_cbs[queue_id] = user_cb->next; - return 0; - } - - /* Remove the user cb from the callback list. */ - do { - prev_cb = cb; - cb = cb->next; - + struct rte_eth_rxtx_callback *cb; + struct rte_eth_rxtx_callback **prev_cb; + int ret = -EINVAL; + + rte_spinlock_lock(&rte_eth_rx_cb_lock); + prev_cb = &dev->post_rx_burst_cbs[queue_id]; + for (; *prev_cb != NULL; prev_cb = &cb->next) { + cb = *prev_cb; if (cb == user_cb) { - prev_cb->next = user_cb->next; - return 0; + /* Remove the user cb from the callback list. */ + *prev_cb = cb->next; + ret = 0; + break; } + } + rte_spinlock_unlock(&rte_eth_rx_cb_lock); - } while (cb != NULL); - - /* Callback wasn't found. */ - return -EINVAL; + return ret; } int @@ -2973,35 +3132,30 @@ rte_eth_remove_tx_callback(uint8_t port_id, uint16_t queue_id, return -ENOTSUP; #endif /* Check input parameters. */ - if (!rte_eth_dev_is_valid_port(port_id) || user_cb == NULL || - queue_id >= rte_eth_devices[port_id].data->nb_tx_queues) { + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL); + if (user_cb == NULL || + queue_id >= rte_eth_devices[port_id].data->nb_tx_queues) return -EINVAL; - } struct rte_eth_dev *dev = &rte_eth_devices[port_id]; - struct rte_eth_rxtx_callback *cb = dev->pre_tx_burst_cbs[queue_id]; - struct rte_eth_rxtx_callback *prev_cb; - - /* Reset head pointer and remove user cb if first in the list. */ - if (cb == user_cb) { - dev->pre_tx_burst_cbs[queue_id] = user_cb->next; - return 0; - } - - /* Remove the user cb from the callback list. */ - do { - prev_cb = cb; - cb = cb->next; - + int ret = -EINVAL; + struct rte_eth_rxtx_callback *cb; + struct rte_eth_rxtx_callback **prev_cb; + + rte_spinlock_lock(&rte_eth_tx_cb_lock); + prev_cb = &dev->pre_tx_burst_cbs[queue_id]; + for (; *prev_cb != NULL; prev_cb = &cb->next) { + cb = *prev_cb; if (cb == user_cb) { - prev_cb->next = user_cb->next; - return 0; + /* Remove the user cb from the callback list. */ + *prev_cb = cb->next; + ret = 0; + break; } + } + rte_spinlock_unlock(&rte_eth_tx_cb_lock); - } while (cb != NULL); - - /* Callback wasn't found. */ - return -EINVAL; + return ret; } int @@ -3217,10 +3371,7 @@ rte_eth_dev_get_dcb_info(uint8_t port_id, { struct rte_eth_dev *dev; - if (!rte_eth_dev_is_valid_port(port_id)) { - RTE_PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id); - return -ENODEV; - } + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); dev = &rte_eth_devices[port_id]; memset(dcb_info, 0, sizeof(struct rte_eth_dcb_info));