X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fmlx4%2Fmlx4.c;h=667ba2bdce7b92e82514acf94a69c4625d00c5bf;hb=b62579d4ce802cb2086fafc688a99c314b462367;hp=a997a63073275280f1d49aa16ce43e388615261c;hpb=a6e8b01c3c26a87c4bbe7f9687f780642bc9ecc9;p=dpdk.git diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c index a997a63073..667ba2bdce 100644 --- a/drivers/net/mlx4/mlx4.c +++ b/drivers/net/mlx4/mlx4.c @@ -58,7 +58,6 @@ #include #include #include -#include #include #include #include @@ -88,18 +87,6 @@ const char *pmd_mlx4_init_params[] = { NULL, }; -static int -mlx4_rx_intr_enable(struct rte_eth_dev *dev, uint16_t idx); - -static int -mlx4_rx_intr_disable(struct rte_eth_dev *dev, uint16_t idx); - -static int -priv_rx_intr_vec_enable(struct priv *priv); - -static void -priv_rx_intr_vec_disable(struct priv *priv); - /* Allocate a buffer on the stack and fill it with a printf format string. */ #define MKSTR(name, ...) \ char name[snprintf(NULL, 0, __VA_ARGS__) + 1]; \ @@ -1977,9 +1964,6 @@ mlx4_rx_queue_release(void *dpdk_rxq) rte_free(rxq); } -static int priv_intr_uninstall(struct priv *priv); -static int priv_intr_install(struct priv *priv); - /** * DPDK callback to start the device. * @@ -2004,7 +1988,7 @@ mlx4_dev_start(struct rte_eth_dev *dev) ret = priv_mac_addr_add(priv); if (ret) goto err; - ret = priv_intr_install(priv); + ret = mlx4_intr_install(priv); if (ret) { ERROR("%p: interrupt handler installation failed", (void *)dev); @@ -2042,7 +2026,7 @@ mlx4_dev_stop(struct rte_eth_dev *dev) DEBUG("%p: detaching flows from all RX queues", (void *)dev); priv->started = 0; mlx4_priv_flow_stop(priv); - priv_intr_uninstall(priv); + mlx4_intr_uninstall(priv); priv_mac_addr_del(priv); } @@ -2158,7 +2142,7 @@ mlx4_dev_close(struct rte_eth_dev *dev) claim_zero(ibv_close_device(priv->ctx)); } else assert(priv->ctx == NULL); - priv_intr_uninstall(priv); + mlx4_intr_uninstall(priv); memset(priv, 0, sizeof(*priv)); } @@ -2370,7 +2354,7 @@ mlx4_stats_reset(struct rte_eth_dev *dev) * @return * 0 on success, negative errno value otherwise and rte_errno is set. */ -static int +int mlx4_link_update(struct rte_eth_dev *dev, int wait_to_complete) { const struct priv *priv = dev->data->dev_private; @@ -2645,322 +2629,6 @@ priv_get_mac(struct priv *priv, uint8_t (*mac)[ETHER_ADDR_LEN]) return 0; } -static void mlx4_link_status_alarm(struct priv *priv); - -/** - * Collect interrupt events. - * - * @param priv - * Pointer to private structure. - * @param events - * Pointer to event flags holder. - * - * @return - * Number of events. - */ -static int -priv_collect_interrupt_events(struct priv *priv, uint32_t *events) -{ - struct ibv_async_event event; - int port_change = 0; - struct rte_eth_link *link = &priv->dev->data->dev_link; - const struct rte_intr_conf *const intr_conf = - &priv->dev->data->dev_conf.intr_conf; - int ret = 0; - - *events = 0; - /* Read all message and acknowledge them. */ - for (;;) { - if (ibv_get_async_event(priv->ctx, &event)) - break; - if ((event.event_type == IBV_EVENT_PORT_ACTIVE || - event.event_type == IBV_EVENT_PORT_ERR) && - intr_conf->lsc) { - port_change = 1; - ret++; - } else if (event.event_type == IBV_EVENT_DEVICE_FATAL && - intr_conf->rmv) { - *events |= (1 << RTE_ETH_EVENT_INTR_RMV); - ret++; - } else - DEBUG("event type %d on port %d not handled", - event.event_type, event.element.port_num); - ibv_ack_async_event(&event); - } - if (!port_change) - return ret; - mlx4_link_update(priv->dev, 0); - if (((link->link_speed == 0) && link->link_status) || - ((link->link_speed != 0) && !link->link_status)) { - if (!priv->intr_alarm) { - /* Inconsistent status, check again later. */ - priv->intr_alarm = 1; - rte_eal_alarm_set(MLX4_INTR_ALARM_TIMEOUT, - (void (*)(void *)) - mlx4_link_status_alarm, - priv); - } - } else { - *events |= (1 << RTE_ETH_EVENT_INTR_LSC); - } - return ret; -} - -/** - * Process scheduled link status check. - * - * @param priv - * Pointer to private structure. - */ -static void -mlx4_link_status_alarm(struct priv *priv) -{ - uint32_t events; - int ret; - - assert(priv->intr_alarm == 1); - priv->intr_alarm = 0; - ret = priv_collect_interrupt_events(priv, &events); - if (ret > 0 && events & (1 << RTE_ETH_EVENT_INTR_LSC)) - _rte_eth_dev_callback_process(priv->dev, - RTE_ETH_EVENT_INTR_LSC, - NULL, NULL); -} - -/** - * Handle interrupts from the NIC. - * - * @param priv - * Pointer to private structure. - */ -static void -mlx4_interrupt_handler(struct priv *priv) -{ - int ret; - uint32_t ev; - int i; - - ret = priv_collect_interrupt_events(priv, &ev); - if (ret > 0) { - for (i = RTE_ETH_EVENT_UNKNOWN; - i < RTE_ETH_EVENT_MAX; - i++) { - if (ev & (1 << i)) { - ev &= ~(1 << i); - _rte_eth_dev_callback_process(priv->dev, i, - NULL, NULL); - ret--; - } - } - if (ret) - WARN("%d event%s not processed", ret, - (ret > 1 ? "s were" : " was")); - } -} - -/** - * Uninstall interrupt handler. - * - * @param priv - * Pointer to private structure. - * - * @return - * 0 on success, negative errno value otherwise and rte_errno is set. - */ -static int -priv_intr_uninstall(struct priv *priv) -{ - int err = rte_errno; /* Make sure rte_errno remains unchanged. */ - - if (priv->intr_handle.fd != -1) { - rte_intr_callback_unregister(&priv->intr_handle, - (void (*)(void *)) - mlx4_interrupt_handler, - priv); - priv->intr_handle.fd = -1; - } - rte_eal_alarm_cancel((void (*)(void *))mlx4_link_status_alarm, priv); - priv->intr_alarm = 0; - priv_rx_intr_vec_disable(priv); - rte_errno = err; - return 0; -} - -/** - * Install interrupt handler. - * - * @param priv - * Pointer to private structure. - * - * @return - * 0 on success, negative errno value otherwise and rte_errno is set. - */ -static int -priv_intr_install(struct priv *priv) -{ - const struct rte_intr_conf *const intr_conf = - &priv->dev->data->dev_conf.intr_conf; - int rc; - - priv_intr_uninstall(priv); - if (intr_conf->rxq && priv_rx_intr_vec_enable(priv) < 0) - goto error; - if (intr_conf->lsc | intr_conf->rmv) { - priv->intr_handle.fd = priv->ctx->async_fd; - rc = rte_intr_callback_register(&priv->intr_handle, - (void (*)(void *)) - mlx4_interrupt_handler, - priv); - if (rc < 0) { - rte_errno = -rc; - goto error; - } - } - return 0; -error: - priv_intr_uninstall(priv); - return -rte_errno; -} - -/** - * Allocate queue vector and fill epoll fd list for Rx interrupts. - * - * @param priv - * Pointer to private structure. - * - * @return - * 0 on success, negative errno value otherwise and rte_errno is set. - */ -static int -priv_rx_intr_vec_enable(struct priv *priv) -{ - unsigned int i; - unsigned int rxqs_n = priv->rxqs_n; - unsigned int n = RTE_MIN(rxqs_n, (uint32_t)RTE_MAX_RXTX_INTR_VEC_ID); - unsigned int count = 0; - struct rte_intr_handle *intr_handle = &priv->intr_handle; - - priv_rx_intr_vec_disable(priv); - intr_handle->intr_vec = malloc(sizeof(intr_handle->intr_vec[rxqs_n])); - if (intr_handle->intr_vec == NULL) { - rte_errno = ENOMEM; - ERROR("failed to allocate memory for interrupt vector," - " Rx interrupts will not be supported"); - return -rte_errno; - } - for (i = 0; i != n; ++i) { - struct rxq *rxq = (*priv->rxqs)[i]; - - /* Skip queues that cannot request interrupts. */ - if (!rxq || !rxq->channel) { - /* Use invalid intr_vec[] index to disable entry. */ - intr_handle->intr_vec[i] = - RTE_INTR_VEC_RXTX_OFFSET + - RTE_MAX_RXTX_INTR_VEC_ID; - continue; - } - if (count >= RTE_MAX_RXTX_INTR_VEC_ID) { - rte_errno = E2BIG; - ERROR("too many Rx queues for interrupt vector size" - " (%d), Rx interrupts cannot be enabled", - RTE_MAX_RXTX_INTR_VEC_ID); - priv_rx_intr_vec_disable(priv); - return -rte_errno; - } - intr_handle->intr_vec[i] = RTE_INTR_VEC_RXTX_OFFSET + count; - intr_handle->efds[count] = rxq->channel->fd; - count++; - } - if (!count) - priv_rx_intr_vec_disable(priv); - else - intr_handle->nb_efd = count; - return 0; -} - -/** - * Clean up Rx interrupts handler. - * - * @param priv - * Pointer to private structure. - */ -static void -priv_rx_intr_vec_disable(struct priv *priv) -{ - struct rte_intr_handle *intr_handle = &priv->intr_handle; - - rte_intr_free_epoll_fd(intr_handle); - free(intr_handle->intr_vec); - intr_handle->nb_efd = 0; - intr_handle->intr_vec = NULL; -} - -/** - * DPDK callback for Rx queue interrupt enable. - * - * @param dev - * Pointer to Ethernet device structure. - * @param idx - * Rx queue index. - * - * @return - * 0 on success, negative errno value otherwise and rte_errno is set. - */ -static int -mlx4_rx_intr_enable(struct rte_eth_dev *dev, uint16_t idx) -{ - struct priv *priv = dev->data->dev_private; - struct rxq *rxq = (*priv->rxqs)[idx]; - int ret; - - if (!rxq || !rxq->channel) - ret = EINVAL; - else - ret = ibv_req_notify_cq(rxq->cq, 0); - if (ret) { - rte_errno = ret; - WARN("unable to arm interrupt on rx queue %d", idx); - } - return -ret; -} - -/** - * DPDK callback for Rx queue interrupt disable. - * - * @param dev - * Pointer to Ethernet device structure. - * @param idx - * Rx queue index. - * - * @return - * 0 on success, negative errno value otherwise and rte_errno is set. - */ -static int -mlx4_rx_intr_disable(struct rte_eth_dev *dev, uint16_t idx) -{ - struct priv *priv = dev->data->dev_private; - struct rxq *rxq = (*priv->rxqs)[idx]; - struct ibv_cq *ev_cq; - void *ev_ctx; - int ret; - - if (!rxq || !rxq->channel) { - ret = EINVAL; - } else { - ret = ibv_get_cq_event(rxq->cq->channel, &ev_cq, &ev_ctx); - if (ret || ev_cq != rxq->cq) - ret = EINVAL; - } - if (ret) { - rte_errno = ret; - WARN("unable to disable interrupt on rx queue %d", - idx); - } else { - ibv_ack_cq_events(rxq->cq, 1); - } - return -ret; -} - /** * Verify and store value for device argument. *