From patchwork Mon Oct 5 17:56:35 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adrien Mazarguil X-Patchwork-Id: 7459 Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [IPv6:::1]) by dpdk.org (Postfix) with ESMTP id 2EA3593B4; Mon, 5 Oct 2015 19:57:01 +0200 (CEST) Received: from mail-wi0-f179.google.com (mail-wi0-f179.google.com [209.85.212.179]) by dpdk.org (Postfix) with ESMTP id 62FDD93B4 for ; Mon, 5 Oct 2015 19:57:00 +0200 (CEST) Received: by wicgb1 with SMTP id gb1so130919923wic.1 for ; Mon, 05 Oct 2015 10:56:59 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=q8HrjKrZMsLQePhNwarUuBohYLTTFxCrb6G6YRevmUo=; b=XEzyPr4Ztj0M7wvzk9iD1Dkpd7wCrzq4flnTVNUlUoYCJ79T3P0d0b4E51r62lhhfA aj3MuKkm5C2niVfvrzFVO4bTy00Q+YPNAVJv7llqbsEOY8+B6pAO3yPFy/oUEntQ/ETP lCaKBIN7ki4UgtRQYbqVN6H+eEifDO0Nooq2RYlk3AQ2txZxjCNpByuJ87I6bgc4me6x jrF1ur0eDm5yfvxgJJIo0JjhiIzsdB+tEsqtrH0pJCxK621Jbezpoug77EI9sn2iL1fq 4BjAm4smPJyCojk2vqEppN4yuDUaHpE5GYIYbdVwkHKi3HFSYM0oo+G8hc8CYFwsyb2N x1vw== X-Gm-Message-State: ALoCoQlQhG6kQNK3eQdadXLcmY1oIqMdFUs44PCmAeaIXBPm/l1Ibcm0Jrpav3Q6gpAGznX9tuj9 X-Received: by 10.194.76.67 with SMTP id i3mr36180231wjw.5.1444067819807; Mon, 05 Oct 2015 10:56:59 -0700 (PDT) Received: from 6wind.com (guy78-3-82-239-227-177.fbx.proxad.net. [82.239.227.177]) by smtp.gmail.com with ESMTPSA id m9sm15807359wib.13.2015.10.05.10.56.58 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Mon, 05 Oct 2015 10:56:59 -0700 (PDT) From: Adrien Mazarguil To: dev@dpdk.org Date: Mon, 5 Oct 2015 19:56:35 +0200 Message-Id: <1444067795-29748-4-git-send-email-adrien.mazarguil@6wind.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1444067795-29748-1-git-send-email-adrien.mazarguil@6wind.com> References: <1444067795-29748-1-git-send-email-adrien.mazarguil@6wind.com> Subject: [dpdk-dev] [PATCH 3/3] mlx5: handle interrupts X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" From: Nelio Laranjeiro Add interrupts handler for port status notification. Signed-off-by: Nelio Laranjeiro Signed-off-by: Adrien Mazarguil --- drivers/net/mlx5/mlx5.c | 3 + drivers/net/mlx5/mlx5.h | 7 ++ drivers/net/mlx5/mlx5_defs.h | 3 + drivers/net/mlx5/mlx5_ethdev.c | 150 ++++++++++++++++++++++++++++++++++++++++ drivers/net/mlx5/mlx5_trigger.c | 4 ++ 5 files changed, 167 insertions(+) diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c index fb9d594..7cf533f 100644 --- a/drivers/net/mlx5/mlx5.c +++ b/drivers/net/mlx5/mlx5.c @@ -87,6 +87,7 @@ mlx5_dev_close(struct rte_eth_dev *dev) ((priv->ctx != NULL) ? priv->ctx->device->name : "")); /* In case mlx5_dev_stop() has not been called. */ if (priv->started) { + priv_dev_interrupt_handler_uninstall(priv, dev); priv_allmulticast_disable(priv); priv_promiscuous_disable(priv); priv_mac_addrs_disable(priv); @@ -452,6 +453,7 @@ mlx5_pci_devinit(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) priv->dev = eth_dev; eth_dev->dev_ops = &mlx5_dev_ops; eth_dev->data->mac_addrs = priv->mac; + TAILQ_INIT(ð_dev->link_intr_cbs); /* Bring Ethernet device up. */ DEBUG("forcing Ethernet interface up"); @@ -525,6 +527,7 @@ static struct eth_driver mlx5_driver = { .name = MLX5_DRIVER_NAME, .id_table = mlx5_pci_id_map, .devinit = mlx5_pci_devinit, + .drv_flags = RTE_PCI_DRV_INTR_LSC, }, .dev_private_size = sizeof(struct priv) }; diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index de72f94..6e6bc3a 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -58,6 +58,7 @@ #include #include #include +#include #ifdef PEDANTIC #pragma GCC diagnostic error "-pedantic" #endif @@ -106,6 +107,7 @@ struct priv { unsigned int hw_csum:1; /* Checksum offload is supported. */ unsigned int hw_csum_l2tun:1; /* Same for L2 tunnels. */ unsigned int vf:1; /* This is a VF device. */ + unsigned int pending_alarm:1; /* An alarm is pending. */ /* RX/TX queues. */ unsigned int rxqs_n; /* RX queues array size. */ unsigned int txqs_n; /* TX queues array size. */ @@ -120,6 +122,7 @@ struct priv { unsigned int hash_rxqs_n; /* Hash RX QPs array size. */ /* RSS configuration array indexed by hash RX queue type. */ struct rte_eth_rss_conf *(*rss_conf)[]; + struct rte_intr_handle intr_handle; /* Interrupt handler. */ rte_spinlock_t lock; /* Lock for control functions. */ }; @@ -162,6 +165,10 @@ int mlx5_dev_get_flow_ctrl(struct rte_eth_dev *, struct rte_eth_fc_conf *); int mlx5_dev_set_flow_ctrl(struct rte_eth_dev *, struct rte_eth_fc_conf *); int mlx5_ibv_device_to_pci_addr(const struct ibv_device *, struct rte_pci_addr *); +void mlx5_dev_link_status_handler(void *); +void mlx5_dev_interrupt_handler(struct rte_intr_handle *, void *); +void priv_dev_interrupt_handler_uninstall(struct priv *, struct rte_eth_dev *); +void priv_dev_interrupt_handler_install(struct priv *, struct rte_eth_dev *); /* mlx5_mac.c */ diff --git a/drivers/net/mlx5/mlx5_defs.h b/drivers/net/mlx5/mlx5_defs.h index e697764..3298e94 100644 --- a/drivers/net/mlx5/mlx5_defs.h +++ b/drivers/net/mlx5/mlx5_defs.h @@ -85,4 +85,7 @@ #define MLX5_PMD_SOFT_COUNTERS 1 #endif +/* Alarm timeout. */ +#define MLX5_ALARM_TIMEOUT_US 100000 + #endif /* RTE_PMD_MLX5_DEFS_H_ */ diff --git a/drivers/net/mlx5/mlx5_ethdev.c b/drivers/net/mlx5/mlx5_ethdev.c index fac685e..84e877c 100644 --- a/drivers/net/mlx5/mlx5_ethdev.c +++ b/drivers/net/mlx5/mlx5_ethdev.c @@ -47,6 +47,7 @@ #include #include #include +#include /* DPDK headers don't like -pedantic. */ #ifdef PEDANTIC @@ -56,6 +57,8 @@ #include #include #include +#include +#include #ifdef PEDANTIC #pragma GCC diagnostic error "-pedantic" #endif @@ -790,3 +793,150 @@ mlx5_ibv_device_to_pci_addr(const struct ibv_device *device, fclose(file); return 0; } + +/** + * Link status handler. + * + * @param priv + * Pointer to private structure. + * @param dev + * Pointer to the rte_eth_dev structure. + * + * @return + * Nonzero if the callback process can be called immediately. + */ +static int +priv_dev_link_status_handler(struct priv *priv, struct rte_eth_dev *dev) +{ + struct ibv_async_event event; + int port_change = 0; + int ret = 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) + port_change = 1; + 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 ^ priv->pending_alarm) { + struct rte_eth_link *link = &dev->data->dev_link; + + priv->pending_alarm = 0; + mlx5_link_update_unlocked(dev, 0); + if (((link->link_speed == 0) && link->link_status) || + ((link->link_speed != 0) && !link->link_status)) { + /* Inconsistent status, check again later. */ + priv->pending_alarm = 1; + rte_eal_alarm_set(MLX5_ALARM_TIMEOUT_US, + mlx5_dev_link_status_handler, + dev); + } else + ret = 1; + } + return ret; +} + +/** + * Handle delayed link status event. + * + * @param arg + * Registered argument. + */ +void +mlx5_dev_link_status_handler(void *arg) +{ + struct rte_eth_dev *dev = arg; + struct priv *priv = dev->data->dev_private; + int ret; + + priv_lock(priv); + assert(priv->pending_alarm == 1); + ret = priv_dev_link_status_handler(priv, dev); + priv_unlock(priv); + if (ret) + _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC); +} + +/** + * Handle interrupts from the NIC. + * + * @param[in] intr_handle + * Interrupt handler. + * @param cb_arg + * Callback argument. + */ +void +mlx5_dev_interrupt_handler(struct rte_intr_handle *intr_handle, void *cb_arg) +{ + struct rte_eth_dev *dev = cb_arg; + struct priv *priv = dev->data->dev_private; + int ret; + + (void)intr_handle; + priv_lock(priv); + ret = priv_dev_link_status_handler(priv, dev); + priv_unlock(priv); + if (ret) + _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC); +} + +/** + * Uninstall interrupt handler. + * + * @param priv + * Pointer to private structure. + * @param dev + * Pointer to the rte_eth_dev structure. + */ +void +priv_dev_interrupt_handler_uninstall(struct priv *priv, struct rte_eth_dev *dev) +{ + if (!dev->data->dev_conf.intr_conf.lsc) + return; + rte_intr_callback_unregister(&priv->intr_handle, + mlx5_dev_interrupt_handler, + dev); + if (priv->pending_alarm) + rte_eal_alarm_cancel(mlx5_dev_link_status_handler, dev); + priv->pending_alarm = 0; + priv->intr_handle.fd = 0; + priv->intr_handle.type = 0; +} + +/** + * Install interrupt handler. + * + * @param priv + * Pointer to private structure. + * @param dev + * Pointer to the rte_eth_dev structure. + */ +void +priv_dev_interrupt_handler_install(struct priv *priv, struct rte_eth_dev *dev) +{ + int rc, flags; + + if (!dev->data->dev_conf.intr_conf.lsc) + return; + assert(priv->ctx->async_fd > 0); + flags = fcntl(priv->ctx->async_fd, F_GETFL); + rc = fcntl(priv->ctx->async_fd, F_SETFL, flags | O_NONBLOCK); + if (rc < 0) { + INFO("failed to change file descriptor async event queue"); + dev->data->dev_conf.intr_conf.lsc = 0; + } else { + priv->intr_handle.fd = priv->ctx->async_fd; + priv->intr_handle.type = RTE_INTR_HANDLE_EXT; + rte_intr_callback_register(&priv->intr_handle, + mlx5_dev_interrupt_handler, + dev); + } +} diff --git a/drivers/net/mlx5/mlx5_trigger.c b/drivers/net/mlx5/mlx5_trigger.c index 233c0d8..b0a6d24 100644 --- a/drivers/net/mlx5/mlx5_trigger.c +++ b/drivers/net/mlx5/mlx5_trigger.c @@ -37,6 +37,8 @@ #endif #include #include +#include +#include #ifdef PEDANTIC #pragma GCC diagnostic error "-pedantic" #endif @@ -87,6 +89,7 @@ mlx5_dev_start(struct rte_eth_dev *dev) priv_mac_addrs_disable(priv); priv_destroy_hash_rxqs(priv); } + priv_dev_interrupt_handler_install(priv, dev); priv_unlock(priv); return -err; } @@ -114,6 +117,7 @@ mlx5_dev_stop(struct rte_eth_dev *dev) priv_promiscuous_disable(priv); priv_mac_addrs_disable(priv); priv_destroy_hash_rxqs(priv); + priv_dev_interrupt_handler_uninstall(priv, dev); priv->started = 0; priv_unlock(priv); }