From mboxrd@z Thu Jan 1 00:00:00 1970 From: Thomas Monjalon Subject: [PATCH v4 2/5] ethdev: allow event registration for all ports Date: Thu, 4 Jan 2018 17:01:09 +0100 Message-ID: <20180104160112.28651-3-thomas@monjalon.net> References: <20171128221302.15400-1-thomas@monjalon.net> <20180104160112.28651-1-thomas@monjalon.net> Cc: ferruh.yigit@intel.com, Matan Azrad To: dev@dpdk.org Return-path: Received: from out2-smtp.messagingengine.com (out2-smtp.messagingengine.com [66.111.4.26]) by dpdk.org (Postfix) with ESMTP id A9F9F7CFC for ; Thu, 4 Jan 2018 17:01:39 +0100 (CET) In-Reply-To: <20180104160112.28651-1-thomas@monjalon.net> List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" From: Matan Azrad Add option to register event callback for all ports by one call to rte_eth_dev_callback_register using port_id=RTE_ETH_ALL. In this case the callback is also registered to invalid ports. Signed-off-by: Matan Azrad Acked-by: Thomas Monjalon --- v2: - moved callback lists constructor - changed ports variables from 32 to 16 bits - changed doxygen comment v3: no change v4: revert next_port to uint32_t to avoid wrap-around --- lib/librte_ether/rte_ethdev.c | 121 ++++++++++++++++++++++++++++-------------- lib/librte_ether/rte_ethdev.h | 8 ++- 2 files changed, 88 insertions(+), 41 deletions(-) diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index c196c3692..7b440fc6b 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -204,7 +204,6 @@ eth_dev_get(uint16_t port_id) eth_dev->data = &rte_eth_dev_data[port_id]; eth_dev->state = RTE_ETH_DEV_ATTACHED; - TAILQ_INIT(&(eth_dev->link_intr_cbs)); eth_dev_last_created_port = port_id; @@ -2820,6 +2819,14 @@ rte_eth_mirror_rule_reset(uint16_t port_id, uint8_t rule_id) return (*dev->dev_ops->mirror_rule_reset)(dev, rule_id); } +RTE_INIT(eth_dev_init_cb_lists) +{ + int i; + + for (i = 0; i < RTE_MAX_ETHPORTS; i++) + TAILQ_INIT(&rte_eth_devices[i].link_intr_cbs); +} + int rte_eth_dev_callback_register(uint16_t port_id, enum rte_eth_event_type event, @@ -2827,37 +2834,59 @@ rte_eth_dev_callback_register(uint16_t port_id, { struct rte_eth_dev *dev; struct rte_eth_dev_callback *user_cb; + uint32_t next_port; /* size is 32-bit to prevent loop wrap-around */ + uint16_t last_port; if (!cb_fn) return -EINVAL; - RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL); + if (!rte_eth_dev_is_valid_port(port_id) && port_id != RTE_ETH_ALL) { + RTE_LOG(ERR, EAL, "Invalid port_id=%d\n", port_id); + return -EINVAL; + } + + if (port_id == RTE_ETH_ALL) { + next_port = 0; + last_port = RTE_MAX_ETHPORTS - 1; + } else { + next_port = last_port = port_id; + } - dev = &rte_eth_devices[port_id]; rte_spinlock_lock(&rte_eth_dev_cb_lock); - TAILQ_FOREACH(user_cb, &(dev->link_intr_cbs), next) { - if (user_cb->cb_fn == cb_fn && - user_cb->cb_arg == cb_arg && - user_cb->event == event) { - break; + do { + dev = &rte_eth_devices[next_port]; + + TAILQ_FOREACH(user_cb, &(dev->link_intr_cbs), next) { + if (user_cb->cb_fn == cb_fn && + user_cb->cb_arg == cb_arg && + user_cb->event == event) { + break; + } } - } - /* create a new callback. */ - if (user_cb == NULL) { - user_cb = rte_zmalloc("INTR_USER_CALLBACK", - sizeof(struct rte_eth_dev_callback), 0); - if (user_cb != NULL) { - user_cb->cb_fn = cb_fn; - user_cb->cb_arg = cb_arg; - user_cb->event = event; - TAILQ_INSERT_TAIL(&(dev->link_intr_cbs), user_cb, next); + /* create a new callback. */ + if (user_cb == NULL) { + user_cb = rte_zmalloc("INTR_USER_CALLBACK", + sizeof(struct rte_eth_dev_callback), 0); + if (user_cb != NULL) { + user_cb->cb_fn = cb_fn; + user_cb->cb_arg = cb_arg; + user_cb->event = event; + TAILQ_INSERT_TAIL(&(dev->link_intr_cbs), + user_cb, next); + } else { + rte_spinlock_unlock(&rte_eth_dev_cb_lock); + rte_eth_dev_callback_unregister(port_id, event, + cb_fn, cb_arg); + return -ENOMEM; + } + } - } + } while (++next_port <= last_port); rte_spinlock_unlock(&rte_eth_dev_cb_lock); - return (user_cb == NULL) ? -ENOMEM : 0; + return 0; } int @@ -2868,36 +2897,50 @@ rte_eth_dev_callback_unregister(uint16_t port_id, int ret; struct rte_eth_dev *dev; struct rte_eth_dev_callback *cb, *next; + uint32_t next_port; /* size is 32-bit to prevent loop wrap-around */ + uint16_t last_port; if (!cb_fn) return -EINVAL; - RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL); + if (!rte_eth_dev_is_valid_port(port_id) && port_id != RTE_ETH_ALL) { + RTE_LOG(ERR, EAL, "Invalid port_id=%d\n", port_id); + return -EINVAL; + } + + if (port_id == RTE_ETH_ALL) { + next_port = 0; + last_port = RTE_MAX_ETHPORTS - 1; + } else { + next_port = last_port = port_id; + } - dev = &rte_eth_devices[port_id]; rte_spinlock_lock(&rte_eth_dev_cb_lock); - ret = 0; - for (cb = TAILQ_FIRST(&dev->link_intr_cbs); cb != NULL; cb = next) { + do { + dev = &rte_eth_devices[next_port]; + ret = 0; + for (cb = TAILQ_FIRST(&dev->link_intr_cbs); cb != NULL; + cb = next) { - next = TAILQ_NEXT(cb, next); + next = TAILQ_NEXT(cb, next); - if (cb->cb_fn != cb_fn || cb->event != event || - (cb->cb_arg != (void *)-1 && - cb->cb_arg != cb_arg)) - continue; + if (cb->cb_fn != cb_fn || cb->event != event || + (cb->cb_arg != (void *)-1 && cb->cb_arg != cb_arg)) + continue; - /* - * if this callback is not executing right now, - * then remove it. - */ - if (cb->active == 0) { - TAILQ_REMOVE(&(dev->link_intr_cbs), cb, next); - rte_free(cb); - } else { - ret = -EAGAIN; + /* + * if this callback is not executing right now, + * then remove it. + */ + if (cb->active == 0) { + TAILQ_REMOVE(&(dev->link_intr_cbs), cb, next); + rte_free(cb); + } else { + ret = -EAGAIN; + } } - } + } while (++next_port <= last_port); rte_spinlock_unlock(&rte_eth_dev_cb_lock); return ret; diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index 15309aa7c..c92508cfd 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -1137,6 +1137,8 @@ struct rte_eth_dcb_info { struct rte_eth_dev; +#define RTE_ETH_ALL RTE_MAX_ETHPORTS + struct rte_eth_dev_callback; /** @internal Structure to keep track of registered callbacks */ TAILQ_HEAD(rte_eth_dev_cb_list, rte_eth_dev_callback); @@ -3536,10 +3538,11 @@ typedef int (*rte_eth_dev_cb_fn)(uint16_t port_id, /** - * Register a callback function for specific port id. + * Register a callback function for port event. * * @param port_id * Port id. + * RTE_ETH_ALL means register the event for all port ids. * @param event * Event interested. * @param cb_fn @@ -3556,10 +3559,11 @@ int rte_eth_dev_callback_register(uint16_t port_id, rte_eth_dev_cb_fn cb_fn, void *cb_arg); /** - * Unregister a callback function for specific port id. + * Unregister a callback function for port event. * * @param port_id * Port id. + * RTE_ETH_ALL means unregister the event for all port ids. * @param event * Event interested. * @param cb_fn -- 2.15.1