From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from NAM05-DM3-obe.outbound.protection.outlook.com (mail-eopbgr730081.outbound.protection.outlook.com [40.107.73.81]) by dpdk.org (Postfix) with ESMTP id C456D1B176 for ; Sat, 29 Sep 2018 12:32:00 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=AQUANTIA1COM.onmicrosoft.com; s=selector1-aquantia-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=m4VtXGSDDVFdHRfkWwehVCOBfmLuCDO98m0/LNhg9kU=; b=MYVveJsbYx0XVUemeVohPPAYboaT7+dcBRCHrjtZm7RNKxIepfVUld60vkEMc5BNs+qvPfldSMmOmjT1vW7QUYsF9nREHMcqL24ItH08u7AeSwcmn8uHBrDBX8JXTVl0Efk4pzAjDcOJ/51dWTNoupUraMMgJWEXArIdiky6xGo= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=Igor.Russkikh@aquantia.com; Received: from ubuntubox.rdc.aquantia.com (95.79.108.179) by BLUPR0701MB1650.namprd07.prod.outlook.com (2a01:111:e400:58c6::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1185.22; Sat, 29 Sep 2018 10:31:52 +0000 From: Igor Russkikh To: dev@dpdk.org Cc: pavel.belous@aquantia.com, igor.russkikh@aquantia.com, Pavel Belous Date: Sat, 29 Sep 2018 13:30:25 +0300 Message-Id: <1691fabf67f002c8ad6a85fd5a23a3b854a8daf3.1538215990.git.igor.russkikh@aquantia.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [95.79.108.179] X-ClientProxiedBy: VI1P193CA0009.EURP193.PROD.OUTLOOK.COM (2603:10a6:800:bd::19) To BLUPR0701MB1650.namprd07.prod.outlook.com (2a01:111:e400:58c6::20) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 8d33b3ca-d164-4341-ad0a-08d625f6c972 X-Microsoft-Antispam: BCL:0; PCL:0; RULEID:(7020095)(4652040)(8989299)(4534165)(4627221)(201703031133081)(201702281549075)(8990200)(5600074)(711020)(2017052603328)(7153060)(7193020); SRVR:BLUPR0701MB1650; X-Microsoft-Exchange-Diagnostics: 1; BLUPR0701MB1650; 3:h/ES+3ArumZQS3CbDkulJNTWLnclDAhOuaOGobfJ13mrrSg9w8TlzT5j3tU+bT6JcPboPjfro5O66fwTcVR6KwPa/MUQ5ZCi6ypLBNA82h4aDphMRgSuG6aPfY9kQQqQkPt59nOEgG/ar8xzjovnH4udrRtZRSVtpJYuA9wmtN+nAk7XU15Nd3qmokFk0bTO0g3b4kDn+a+KrlyP92b9Yw0ZNjWjZLci7vKTJB/4nebraUKXixnr5xkouMUSAWLg; 25:t3SHEquNxF2w2USNMaWBcUfmtHvilsRuD5axyYWEBlt1XUU8XHQGq244EupwSg7HDV3J/CwRgGojLUtGiFxk6rC5buf6OsbKUtOllgKeFNHyv3C9+GkutVjyrniz4EA7NAjhjrMZ9XXbbMK1mq6JZZIZMMYB6B6sC2kDgZIpHU9W1gGg6hDK4iQd3RsfwCC0J1xfDrxvP/oL3LGEpqWj0MadDytUUrRpvTL9iM+0CYBVmtw1eQ7bGpAl31wYd2nxlYd0UY/AQWugySWxNRRPvZwyE3vu2WvH2iLYtxQjWOLFgRVbGpjHFXSWvEiePdSMiS4nqUsSW/3V0tEIbfETlTQL2WOPLSnElXa7EDBrpFE=; 31:D/8gLdVTPEA9So6VL6ZX83ruFp4RK5Jpwl5bGTnSqXgcccgNpxQnE2BAFGy2GCJIUj1zfyEnTe8izXWqMTSXOzMplQYyapHhuCir1jZ0wc3BWFuZQmtJkkgUstIstTMaRrmudOrROufuP3FYQnpFpPBOGZ/XlrzyxFc/PGb+ajHX3js391+fXD8DrAZWE9eJIAlXrUKCK+aGGLxUL3go4zte7UH9UzaPnVdgPy5lU9I= X-MS-TrafficTypeDiagnostic: BLUPR0701MB1650: X-Microsoft-Exchange-Diagnostics: 1; BLUPR0701MB1650; 20:G72f9cQ3/3mdlAmcabzIn9nfV2wUyzAeqjnBKyGEUdGYtD0oXsbIyqettfK/B6C7TYICrRCdbVHPwsYKSIYXDswk4c76KGLyCzhL8EJFLMamDWrM1XspI2KwHmKxjI58vCy4zFpPF8Omj0CPxSqTaPwYQKERGXvlQWovBBPvXRiLKqWnHdvVavupztZzeNRmqt9QC57uSP1WGi4SGc772utz7FeiFmgN8JBh755kTnlDnPMn61Mh+wnyPbZ5Jxqyl2Q4PFFNKRoxBzV2exBoCAkARjP2Jh33iOk4nXQZRlK1aIsx2LEy+Rl7jEaludBbIsC9ilZBsE6BuS+OZMSKyfoSg1d/QpUELRi6+Y0LpABuc/oGME9z706QZVABS/iTFdhBS+/vu+w+HIBrup7Gm9PYrhUFmRBl2nuk7joMuFDkpC5sZkkUUq4lb0uS0rkILBvf0lJHcQxyEgj/NzImY6TBtKXfioPfgqeQgs8p3J24X2lvRefcX6kDTYC17xZA; 4:Riy/MnERKc8KXzPtQTbbCVHg/B+wxKlpIRATASoH/agEfUazNi2YlKQrPPr1G0T3SeR0xS1+yYBc04KolWaKgNXceGSXkbJhDJLB0NFvTgHH6fba9PuSNfnwT9hUJMn7+Xar+/ZXvvRl02g0fBxLItUcNQcdb3FwnC5gXap0KKwY9ZkyxUq33UgLrXzPcxQa4josYOGhrspN1YhNvTk5GjzUOZCZyI3akLzKX1tTi24y3S4PHHpGhqx51RKXNs9I9/kCK2LGoy5+pgf9ESaQoKeF+d1AVj95Qj6FRs9Rk3QXY0iC33ta0JNKd9KGljWX X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(269456686620040); X-MS-Exchange-SenderADCheck: 1 X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6040522)(2401047)(8121501046)(5005006)(10201501046)(3002001)(93006095)(93001095)(3231355)(944501410)(52105095)(149066)(150057)(6041310)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(20161123558120)(20161123564045)(20161123562045)(20161123560045)(201708071742011)(7699051); SRVR:BLUPR0701MB1650; BCL:0; PCL:0; RULEID:; SRVR:BLUPR0701MB1650; X-Forefront-PRVS: 0810818DA0 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(346002)(136003)(396003)(376002)(39850400004)(366004)(189003)(199004)(16526019)(14444005)(446003)(76176011)(2906002)(6916009)(6666003)(97736004)(8676002)(81166006)(81156014)(36756003)(4326008)(316002)(8936002)(50226002)(34290500001)(575784001)(86362001)(5660300001)(68736007)(16586007)(118296001)(72206003)(3846002)(6116002)(53936002)(386003)(105586002)(6486002)(47776003)(66066001)(486006)(25786009)(305945005)(50466002)(44832011)(956004)(2616005)(26005)(107886003)(52116002)(51416003)(7696005)(186003)(476003)(478600001)(2361001)(7736002)(2351001)(48376002)(106356001)(11346002); DIR:OUT; SFP:1101; SCL:1; SRVR:BLUPR0701MB1650; H:ubuntubox.rdc.aquantia.com; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; MX:1; A:1; Received-SPF: None (protection.outlook.com: aquantia.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; BLUPR0701MB1650; 23:G5uG2XmNHTeKhyM25FimIK+oYl2FG91AHNP/4yn?= =?us-ascii?Q?+S6tXLnCGHBKYe8ukYxIpsQ2/nuC4lqvf3LZLKFA70oZ48el0lLw4DZlPqqn?= =?us-ascii?Q?5u+7jsBeGFoCHv8FdrrE/zPrDWxv8uUWCxLpwvLMSphTVxlkcTDytC/6lf3t?= =?us-ascii?Q?zuQ6q0XazTw3mBT1UsLeGzvLSG4I67VxuWjawNsFZuLaolmBJAtP6a13vLG2?= =?us-ascii?Q?WejunhFvY8qOKy+9MsHz6IbKZbBEOaInG7uwoOCos2KctZUt1kbJrH9wWYP9?= =?us-ascii?Q?yMRauEoqdE0jU0ha1FMXTbRR5C4wN4UsQPibWUy8DQbh6XfGt59nzhw1l/dB?= =?us-ascii?Q?2wQFBIRRxs7kSaHKOHn1BpupzD7YK6AqB1r20uoPPzmJLZFluuDJLXFkSQdP?= =?us-ascii?Q?39hTZxD9QJePv/p3QTfVwg0gXzA0DtydLSirsA0O5ozxLK0pPN8kn1sxhRju?= =?us-ascii?Q?5rdPf+TPi6PwYdx9DX0+ib2G+Im2FCsIAyqcY6b6RT7HYixlhwpiNvQ70GdN?= =?us-ascii?Q?DiBPIGzcieyz9cTikGz7c4+i5jgmeUPLPrKiANXc4t5Z367IVB4IBNt5g4yS?= =?us-ascii?Q?AICIPMPO6kFGZ/WXiXaOISSvA5GS4WYILPLpv7UbU+NHI69O2x49Ql1kTwul?= =?us-ascii?Q?0rcwcl3qjLWA/SrvzOvqzQsdkV12ne6kGuY9v+Bz/TlJyFgtmhH67rztJEZb?= =?us-ascii?Q?pH9S7J+hfG+6E+nDcCZSuIrXkfxY/lPW73pjGQ1DUiIRtDmkWovCV0VExXuw?= =?us-ascii?Q?l/3gLR5I46tWtDQdAGBrmksfpr7TkhNAHfiv8W6tvQnLIYEfLT/DV5sSMonk?= =?us-ascii?Q?CWpkSDzxw9Tgiz3/rH4TQOtQ67Goc+A7pTxJR0xQhnqBVlDY+jeu/FE8G3ju?= =?us-ascii?Q?07a11miEOPCHsot1MHn7P/IyoDHroQrEeq1jsvny1IxBN2B44tMmaKDvNto+?= =?us-ascii?Q?5mSzwrnMX3HZb1Gfe6bPFNWRN997oNBtGZOLP5J02rS3SHO6zmplurahEe+C?= =?us-ascii?Q?/W4YjHvzo6kd277DrkAAIUIrgfl62D9DhKgHEthTVIUr5gKukr5GAYys50Fs?= =?us-ascii?Q?IjgykATXsVC1+p2TaPWWMEmZ+9Q/oaMIh5A8dj2v9KGMd389YHI/mPKMwXkH?= =?us-ascii?Q?L8voNk1DLKA0eVyuhBSZtl9FUjZloJAw+9cLQuu2QvvhYYPGV5cF4gVfGh3g?= =?us-ascii?Q?NUgWLqXqnkBzXv9x7vHDvr79AcSoWZ1zolAry0Sl0frPsSJ6t1h0qn2m0aKg?= =?us-ascii?Q?TmYOD33NdJIIuf24NvbuLt6IXWDpenSby7UuFaHysnoJ8j5MkoX8FZYGLOd4?= =?us-ascii?Q?cHmxCMYTo8UwNwlJ4+k9sg9edMzN7sWPLyJ2WPlm89sDN?= X-Microsoft-Antispam-Message-Info: mSgorJ6hxoTOmYKxXoLBtFT0GSxzJei6KG/rtLxq3UWDqkRcyDEzhiLP4ysPdExNruGkKOsPlzZqgd9mHkE/LBXX1sUSrph2eXJHLaEV4FYpTB3OrIGxs+DUIPTy7gdu3xtf6EqezciY2VviFAFADfldE5WBPQ5sI0wFwca0s04GQRCeOxMPtCcHdVxql/rXc5jmKpC79z9+CzGbbeP8kmRiq+3t2Nj01qe/Dxh3aCW7sxQPIxM4KO5gIteKfra3qIbk0dsziz0zq93A9jmmSew+qnXE3hSpLoatfVr+7PSIqBYPBu3AzITMkT6bvqmYvH7i415wTrcia11z/6FQWQ+39Mr8jNwvbJcfVHjcORM= X-Microsoft-Exchange-Diagnostics: 1; BLUPR0701MB1650; 6:encTneyeTGHcbaCbwK19wqLyMAjBJ621PqO6W1+B8878tzhFMgm8UbABxUZUKHS2MKJxpNaCvFF31Q7TwmwI9xvZuS8OFVbVNfqZGNKJbhtRWaZGd5gvOLWsD+KZVUn78dQh+B9LVYX9pH0z3kDdbxmIAl/XbFIOrOhOUiwXqhdtdzk4tHTQgSsHv/tnJpupBllycsnLSKpNzuPSDrC7RTDuSz/2VhBz0ErmVY1l58MGr8Ql62u6mpDt79ofADQ7Ree9vrwON1w/IGs/CE+QrtE2Sbk5taUlFqq7MP6IQZFO6IcFPW//qB/LRJ0JhO/ty+vcCfSow25O1PMMKb0F88ygi8OmKrRpnugRiNaXnKWT77kcPkt8Lw2PV4s7GxBU9OV9CObFQxiPwtV2x/9RkjviVZI2CJp7vAyq/I97kAkpKpWiYHxQFePJA05AE3RKpkwUruXERf/IHYXWrIFptw==; 5:3hPqFcqWKxuHd113KLPkTYv7drdE7aRd1wxp8gb5ENEVfFO4hx5ZdG/DuCjyARsFR/+Spqii7LvXBIey+oSc2yscbBVys/bc48+FA2sURkZdjZeRTjYVFOUOBnWI3zk02IyxJXx8NvkCzNbe/oaVk8C0cU7miKsMSm3JMRkua98=; 7:VXwlqVHCZwttIom/aDvN1LIZcAPJttNiTwK51eGMyya+N20EKJ/eShJWl7RKsyXIcNhgPcrrdjR79j8lI7dPBcxFz5BoVHto8C/om0bkvSjfID2QdUIlFu91h4KnG/RPvYO7r/1ecyivxQRvKffjvVxjCGA4pELv8YSQgLfIlfUhQGs4BvxTZX1jQzs6WCigpLvktCXSxCCooEy7ITQRSb1l41YOc99KEpSfRLOMGSNM1hqzMRpepxuWzAwzmjzf SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: aquantia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 29 Sep 2018 10:31:52.8762 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 8d33b3ca-d164-4341-ad0a-08d625f6c972 X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 83e2e134-991c-4ede-8ced-34d47e38e6b1 X-MS-Exchange-Transport-CrossTenantHeadersStamped: BLUPR0701MB1650 Subject: [dpdk-dev] [PATCH v3 11/22] net/atlantic: link status and interrupt management X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 29 Sep 2018 10:32:01 -0000 From: Pavel Belous Implement link interrupt, link info, link polling. Signed-off-by: Igor Russkikh Signed-off-by: Pavel Belous --- drivers/net/atlantic/atl_ethdev.c | 461 +++++++++++++++++++++++++++++++++++++- drivers/net/atlantic/atl_ethdev.h | 16 ++ drivers/net/atlantic/atl_rxtx.c | 36 +++ drivers/net/atlantic/atl_types.h | 2 + 4 files changed, 514 insertions(+), 1 deletion(-) diff --git a/drivers/net/atlantic/atl_ethdev.c b/drivers/net/atlantic/atl_ethdev.c index 6a00277c3c8e..75c9fa169925 100644 --- a/drivers/net/atlantic/atl_ethdev.c +++ b/drivers/net/atlantic/atl_ethdev.c @@ -18,8 +18,11 @@ static int eth_atl_dev_uninit(struct rte_eth_dev *eth_dev); static int atl_dev_configure(struct rte_eth_dev *dev); static int atl_dev_start(struct rte_eth_dev *dev); static void atl_dev_stop(struct rte_eth_dev *dev); +static int atl_dev_set_link_up(struct rte_eth_dev *dev); +static int atl_dev_set_link_down(struct rte_eth_dev *dev); static void atl_dev_close(struct rte_eth_dev *dev); static int atl_dev_reset(struct rte_eth_dev *dev); +static int atl_dev_link_update(struct rte_eth_dev *dev, int wait); static int atl_fw_version_get(struct rte_eth_dev *dev, char *fw_version, size_t fw_size); @@ -29,6 +32,16 @@ static void atl_dev_info_get(struct rte_eth_dev *dev, static const uint32_t *atl_dev_supported_ptypes_get(struct rte_eth_dev *dev); +static void atl_dev_link_status_print(struct rte_eth_dev *dev); + +/* Interrupts */ +static int atl_dev_rxq_interrupt_setup(struct rte_eth_dev *dev); +static int atl_dev_lsc_interrupt_setup(struct rte_eth_dev *dev, uint8_t on); +static int atl_dev_interrupt_get_status(struct rte_eth_dev *dev); +static int atl_dev_interrupt_action(struct rte_eth_dev *dev, + struct rte_intr_handle *handle); +static void atl_dev_interrupt_handler(void *param); + static int eth_atl_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, struct rte_pci_device *pci_dev); static int eth_atl_pci_remove(struct rte_pci_device *pci_dev); @@ -104,9 +117,14 @@ static const struct eth_dev_ops atl_eth_dev_ops = { .dev_configure = atl_dev_configure, .dev_start = atl_dev_start, .dev_stop = atl_dev_stop, + .dev_set_link_up = atl_dev_set_link_up, + .dev_set_link_down = atl_dev_set_link_down, .dev_close = atl_dev_close, .dev_reset = atl_dev_reset, + /* Link */ + .link_update = atl_dev_link_update, + .fw_version_get = atl_fw_version_get, .dev_infos_get = atl_dev_info_get, .dev_supported_ptypes_get = atl_dev_supported_ptypes_get, @@ -121,14 +139,85 @@ static const struct eth_dev_ops atl_eth_dev_ops = { .tx_queue_stop = atl_tx_queue_stop, .tx_queue_setup = atl_tx_queue_setup, .tx_queue_release = atl_tx_queue_release, + + .rx_queue_intr_enable = atl_dev_rx_queue_intr_enable, + .rx_queue_intr_disable = atl_dev_rx_queue_intr_disable, }; + +/** + * Atomically reads the link status information from global + * structure rte_eth_dev. + * + * @param dev + * - Pointer to the structure rte_eth_dev to read from. + * - Pointer to the buffer to be saved with the link status. + * + * @return + * - On success, zero. + * - On failure, negative value. + */ +static inline int +rte_atl_dev_atomic_read_link_status(struct rte_eth_dev *dev, + struct rte_eth_link *link) +{ + struct rte_eth_link *dst = link; + struct rte_eth_link *src = &dev->data->dev_link; + + if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst, + *(uint64_t *)src) == 0) + return -1; + + return 0; +} + +/** + * Atomically writes the link status information into global + * structure rte_eth_dev. + * + * @param dev + * - Pointer to the structure rte_eth_dev to read from. + * - Pointer to the buffer to be saved with the link status. + * + * @return + * - On success, zero. + * - On failure, negative value. + */ +static inline int +rte_atl_dev_atomic_write_link_status(struct rte_eth_dev *dev, + struct rte_eth_link *link) +{ + struct rte_eth_link *dst = &dev->data->dev_link; + struct rte_eth_link *src = link; + + if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst, + *(uint64_t *)src) == 0) + return -1; + + return 0; +} + static inline int32_t atl_reset_hw(struct aq_hw_s *hw) { return hw_atl_b0_hw_reset(hw); } +static inline void +atl_enable_intr(struct rte_eth_dev *dev) +{ + struct aq_hw_s *hw = ATL_DEV_PRIVATE_TO_HW(dev->data->dev_private); + + hw_atl_itr_irq_msk_setlsw_set(hw, 0xffffffff); +} + +static void +atl_disable_intr(struct aq_hw_s *hw) +{ + PMD_INIT_FUNC_TRACE(); + hw_atl_itr_irq_msk_clearlsw_set(hw, 0xffffffff); +} + static void atl_print_adapter_info(struct aq_hw_s *hw __rte_unused) { @@ -145,6 +234,7 @@ eth_atl_dev_init(struct rte_eth_dev *eth_dev) struct atl_adapter *adapter = (struct atl_adapter *)eth_dev->data->dev_private; struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); + struct rte_intr_handle *intr_handle = &pci_dev->intr_handle; struct aq_hw_s *hw = ATL_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); int err = 0; @@ -169,9 +259,17 @@ eth_atl_dev_init(struct rte_eth_dev *eth_dev) /* Hardware configuration - hardcode */ adapter->hw_cfg.is_lro = false; adapter->hw_cfg.wol = false; + adapter->hw_cfg.link_speed_msk = AQ_NIC_RATE_10G | + AQ_NIC_RATE_5G | + AQ_NIC_RATE_2G5 | + AQ_NIC_RATE_1G | + AQ_NIC_RATE_100M; hw->aq_nic_cfg = &adapter->hw_cfg; + /* disable interrupt */ + atl_disable_intr(hw); + /* Allocate memory for storing MAC addresses */ eth_dev->data->mac_addrs = rte_zmalloc("atlantic", ETHER_ADDR_LEN, 0); if (eth_dev->data->mac_addrs == NULL) { @@ -188,12 +286,23 @@ eth_atl_dev_init(struct rte_eth_dev *eth_dev) (u8 *)ð_dev->data->mac_addrs[0]) != 0) return -EINVAL; + rte_intr_callback_register(intr_handle, + atl_dev_interrupt_handler, eth_dev); + + /* enable uio/vfio intr/eventfd mapping */ + rte_intr_enable(intr_handle); + + /* enable support intr */ + atl_enable_intr(eth_dev); + return err; } static int eth_atl_dev_uninit(struct rte_eth_dev *eth_dev) { + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); + struct rte_intr_handle *intr_handle = &pci_dev->intr_handle; struct aq_hw_s *hw; PMD_INIT_FUNC_TRACE(); @@ -210,6 +319,11 @@ eth_atl_dev_uninit(struct rte_eth_dev *eth_dev) eth_dev->rx_pkt_burst = NULL; eth_dev->tx_pkt_burst = NULL; + /* disable uio intr before callback unregister */ + rte_intr_disable(intr_handle); + rte_intr_callback_unregister(intr_handle, + atl_dev_interrupt_handler, eth_dev); + rte_free(eth_dev->data->mac_addrs); eth_dev->data->mac_addrs = NULL; @@ -238,8 +352,16 @@ eth_atl_pci_remove(struct rte_pci_device *pci_dev) } static int -atl_dev_configure(struct rte_eth_dev *dev __rte_unused) +atl_dev_configure(struct rte_eth_dev *dev) { + struct atl_interrupt *intr = + ATL_DEV_PRIVATE_TO_INTR(dev->data->dev_private); + + PMD_INIT_FUNC_TRACE(); + + /* set flag to update link status after init */ + intr->flags |= ATL_FLAG_NEED_LINK_UPDATE; + return 0; } @@ -251,11 +373,26 @@ static int atl_dev_start(struct rte_eth_dev *dev) { struct aq_hw_s *hw = ATL_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); + struct rte_intr_handle *intr_handle = &pci_dev->intr_handle; + uint32_t intr_vector = 0; + uint32_t *link_speeds; + uint32_t speed = 0; int status; int err; PMD_INIT_FUNC_TRACE(); + if (dev->data->dev_conf.link_speeds & ETH_LINK_SPEED_FIXED) { + PMD_INIT_LOG(ERR, + "Invalid link_speeds for port %u, fix speed not supported", + dev->data->port_id); + return -EINVAL; + } + + /* disable uio/vfio intr/eventfd mapping */ + rte_intr_disable(intr_handle); + /* stop adapter */ hw->adapter_stopped = 0; @@ -269,6 +406,32 @@ atl_dev_start(struct rte_eth_dev *dev) err = hw_atl_b0_hw_init(hw, (uint8_t *)dev->data->mac_addrs); hw_atl_b0_hw_start(hw); + /* check and configure queue intr-vector mapping */ + if ((rte_intr_cap_multiple(intr_handle) || + !RTE_ETH_DEV_SRIOV(dev).active) && + dev->data->dev_conf.intr_conf.rxq != 0) { + intr_vector = dev->data->nb_rx_queues; + if (intr_vector > ATL_MAX_INTR_QUEUE_NUM) { + PMD_INIT_LOG(ERR, "At most %d intr queues supported", + ATL_MAX_INTR_QUEUE_NUM); + return -ENOTSUP; + } + if (rte_intr_efd_enable(intr_handle, intr_vector)) { + PMD_INIT_LOG(ERR, "rte_intr_efd_enable failed"); + return -1; + } + } + + if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) { + intr_handle->intr_vec = rte_zmalloc("intr_vec", + dev->data->nb_rx_queues * sizeof(int), 0); + if (intr_handle->intr_vec == NULL) { + PMD_INIT_LOG(ERR, "Failed to allocate %d rx_queues" + " intr_vec", dev->data->nb_rx_queues); + return -ENOMEM; + } + } + /* initialize transmission unit */ atl_tx_init(dev); @@ -285,6 +448,61 @@ atl_dev_start(struct rte_eth_dev *dev) goto error; } + err = hw->aq_fw_ops->update_link_status(hw); + + if (err) + goto error; + + dev->data->dev_link.link_status = hw->aq_link_status.mbps != 0; + + link_speeds = &dev->data->dev_conf.link_speeds; + + speed = 0x0; + + if (*link_speeds == ETH_LINK_SPEED_AUTONEG) { + speed = hw->aq_nic_cfg->link_speed_msk; + } else { + if (*link_speeds & ETH_LINK_SPEED_10G) + speed |= AQ_NIC_RATE_10G; + if (*link_speeds & ETH_LINK_SPEED_5G) + speed |= AQ_NIC_RATE_5G; + if (*link_speeds & ETH_LINK_SPEED_1G) + speed |= AQ_NIC_RATE_1G; + if (*link_speeds & ETH_LINK_SPEED_2_5G) + speed |= AQ_NIC_RATE_2G5; + if (*link_speeds & ETH_LINK_SPEED_100M) + speed |= AQ_NIC_RATE_100M; + } + + err = hw->aq_fw_ops->set_link_speed(hw, speed); + if (err) + goto error; + + if (rte_intr_allow_others(intr_handle)) { + /* check if lsc interrupt is enabled */ + if (dev->data->dev_conf.intr_conf.lsc != 0) + atl_dev_lsc_interrupt_setup(dev, TRUE); + else + atl_dev_lsc_interrupt_setup(dev, FALSE); + } else { + rte_intr_callback_unregister(intr_handle, + atl_dev_interrupt_handler, dev); + if (dev->data->dev_conf.intr_conf.lsc != 0) + PMD_INIT_LOG(INFO, "lsc won't enable because of" + " no intr multiplex"); + } + + /* check if rxq interrupt is enabled */ + if (dev->data->dev_conf.intr_conf.rxq != 0 && + rte_intr_dp_is_en(intr_handle)) + atl_dev_rxq_interrupt_setup(dev); + + /* enable uio/vfio intr/eventfd mapping */ + rte_intr_enable(intr_handle); + + /* resume enabled intr since hw reset */ + atl_enable_intr(dev); + atl_print_adapter_info(hw); return 0; @@ -301,8 +519,16 @@ atl_dev_start(struct rte_eth_dev *dev) static void atl_dev_stop(struct rte_eth_dev *dev) { + struct rte_eth_link link; struct aq_hw_s *hw = ATL_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); + struct rte_intr_handle *intr_handle = &pci_dev->intr_handle; + + PMD_INIT_FUNC_TRACE(); + + /* disable interrupts */ + atl_disable_intr(hw); /* reset the NIC */ atl_reset_hw(hw); @@ -314,6 +540,45 @@ atl_dev_stop(struct rte_eth_dev *dev) dev->data->scattered_rx = 0; dev->data->lro = 0; + /* Clear recorded link status */ + memset(&link, 0, sizeof(link)); + rte_atl_dev_atomic_write_link_status(dev, &link); + + if (!rte_intr_allow_others(intr_handle)) + /* resume to the default handler */ + rte_intr_callback_register(intr_handle, + atl_dev_interrupt_handler, + (void *)dev); + + /* Clean datapath event and queue/vec mapping */ + rte_intr_efd_disable(intr_handle); + if (intr_handle->intr_vec != NULL) { + rte_free(intr_handle->intr_vec); + intr_handle->intr_vec = NULL; + } +} + +/* + * Set device link up: enable tx. + */ +static int +atl_dev_set_link_up(struct rte_eth_dev *dev) +{ + struct aq_hw_s *hw = ATL_DEV_PRIVATE_TO_HW(dev->data->dev_private); + + return hw->aq_fw_ops->set_link_speed(hw, + hw->aq_nic_cfg->link_speed_msk); +} + +/* + * Set device link down: disable tx. + */ +static int +atl_dev_set_link_down(struct rte_eth_dev *dev) +{ + struct aq_hw_s *hw = ATL_DEV_PRIVATE_TO_HW(dev->data->dev_private); + + return hw->aq_fw_ops->set_link_speed(hw, 0); } /* @@ -402,6 +667,11 @@ atl_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) dev_info->rx_desc_lim = rx_desc_lim; dev_info->tx_desc_lim = tx_desc_lim; + + dev_info->speed_capa = ETH_LINK_SPEED_1G | ETH_LINK_SPEED_10G; + dev_info->speed_capa |= ETH_LINK_SPEED_100M; + dev_info->speed_capa |= ETH_LINK_SPEED_2_5G; + dev_info->speed_capa |= ETH_LINK_SPEED_5G; } static const uint32_t * @@ -426,6 +696,195 @@ atl_dev_supported_ptypes_get(struct rte_eth_dev *dev) return NULL; } +/* return 0 means link status changed, -1 means not changed */ +static int +atl_dev_link_update(struct rte_eth_dev *dev, int wait __rte_unused) +{ + struct aq_hw_s *hw = ATL_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct atl_interrupt *intr = + ATL_DEV_PRIVATE_TO_INTR(dev->data->dev_private); + struct rte_eth_link link, old; + int err = 0; + + link.link_status = ETH_LINK_DOWN; + link.link_speed = 0; + link.link_duplex = ETH_LINK_FULL_DUPLEX; + link.link_autoneg = hw->is_autoneg ? ETH_LINK_AUTONEG : ETH_LINK_FIXED; + memset(&old, 0, sizeof(old)); + + /* load old link status */ + rte_atl_dev_atomic_read_link_status(dev, &old); + + /* read current link status */ + err = hw->aq_fw_ops->update_link_status(hw); + + if (err) + return 0; + + if (hw->aq_link_status.mbps == 0) { + /* write default (down) link status */ + rte_atl_dev_atomic_write_link_status(dev, &link); + if (link.link_status == old.link_status) + return -1; + return 0; + } + + intr->flags &= ~ATL_FLAG_NEED_LINK_CONFIG; + + link.link_status = ETH_LINK_UP; + link.link_duplex = ETH_LINK_FULL_DUPLEX; + link.link_speed = hw->aq_link_status.mbps; + + rte_atl_dev_atomic_write_link_status(dev, &link); + + if (link.link_status == old.link_status) + return -1; + + return 0; +} + + +/** + * It clears the interrupt causes and enables the interrupt. + * It will be called once only during nic initialized. + * + * @param dev + * Pointer to struct rte_eth_dev. + * @param on + * Enable or Disable. + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ + +static int +atl_dev_lsc_interrupt_setup(struct rte_eth_dev *dev, uint8_t on __rte_unused) +{ + atl_dev_link_status_print(dev); + return 0; +} + +static int +atl_dev_rxq_interrupt_setup(struct rte_eth_dev *dev __rte_unused) +{ + return 0; +} + + +static int +atl_dev_interrupt_get_status(struct rte_eth_dev *dev) +{ + struct atl_interrupt *intr = + ATL_DEV_PRIVATE_TO_INTR(dev->data->dev_private); + struct aq_hw_s *hw = ATL_DEV_PRIVATE_TO_HW(dev->data->dev_private); + u64 cause = 0; + + hw_atl_b0_hw_irq_read(hw, &cause); + + atl_disable_intr(hw); + intr->flags = cause & BIT(ATL_IRQ_CAUSE_LINK) ? + ATL_FLAG_NEED_LINK_UPDATE : 0; + + return 0; +} + +/** + * It gets and then prints the link status. + * + * @param dev + * Pointer to struct rte_eth_dev. + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static void +atl_dev_link_status_print(struct rte_eth_dev *dev) +{ + struct rte_eth_link link; + + memset(&link, 0, sizeof(link)); + rte_atl_dev_atomic_read_link_status(dev, &link); + if (link.link_status) { + PMD_DRV_LOG(INFO, "Port %d: Link Up - speed %u Mbps - %s", + (int)(dev->data->port_id), + (unsigned int)link.link_speed, + link.link_duplex == ETH_LINK_FULL_DUPLEX ? + "full-duplex" : "half-duplex"); + } else { + PMD_DRV_LOG(INFO, " Port %d: Link Down", + (int)(dev->data->port_id)); + } + + +#ifdef DEBUG +{ + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); + + PMD_DRV_LOG(DEBUG, "PCI Address: " PCI_PRI_FMT, + pci_dev->addr.domain, + pci_dev->addr.bus, + pci_dev->addr.devid, + pci_dev->addr.function); +} +#endif + + PMD_DRV_LOG(INFO, "Link speed:%d", link.link_speed); +} + +/* + * It executes link_update after knowing an interrupt occurred. + * + * @param dev + * Pointer to struct rte_eth_dev. + * + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +atl_dev_interrupt_action(struct rte_eth_dev *dev, + struct rte_intr_handle *intr_handle) +{ + struct atl_interrupt *intr = + ATL_DEV_PRIVATE_TO_INTR(dev->data->dev_private); + + if (intr->flags & ATL_FLAG_NEED_LINK_UPDATE) { + atl_dev_link_update(dev, 0); + intr->flags &= ~ATL_FLAG_NEED_LINK_UPDATE; + atl_dev_link_status_print(dev); + _rte_eth_dev_callback_process(dev, + RTE_ETH_EVENT_INTR_LSC, NULL); + } + + atl_enable_intr(dev); + rte_intr_enable(intr_handle); + + return 0; +} + +/** + * Interrupt handler triggered by NIC for handling + * specific interrupt. + * + * @param handle + * Pointer to interrupt handle. + * @param param + * The address of parameter (struct rte_eth_dev *) regsitered before. + * + * @return + * void + */ +static void +atl_dev_interrupt_handler(void *param) +{ + struct rte_eth_dev *dev = (struct rte_eth_dev *)param; + + atl_dev_interrupt_get_status(dev); + atl_dev_interrupt_action(dev, dev->intr_handle); +} + RTE_PMD_REGISTER_PCI(net_atlantic, rte_atl_pmd); RTE_PMD_REGISTER_PCI_TABLE(net_atlantic, pci_id_atl_map); RTE_PMD_REGISTER_KMOD_DEP(net_atlantic, "* igb_uio | uio_pci_generic"); diff --git a/drivers/net/atlantic/atl_ethdev.h b/drivers/net/atlantic/atl_ethdev.h index cafe37cdf963..f75ed0fd1127 100644 --- a/drivers/net/atlantic/atl_ethdev.h +++ b/drivers/net/atlantic/atl_ethdev.h @@ -15,6 +15,16 @@ #define ATL_DEV_TO_ADAPTER(dev) \ ((struct atl_adapter *)(dev)->data->dev_private) +#define ATL_DEV_PRIVATE_TO_INTR(adapter) \ + (&((struct atl_adapter *)adapter)->intr) + +#define ATL_FLAG_NEED_LINK_UPDATE (uint32_t)(1 << 0) +#define ATL_FLAG_NEED_LINK_CONFIG (uint32_t)(4 << 0) + +struct atl_interrupt { + uint32_t flags; + uint32_t mask; +}; /* * Structure to store private data for each driver instance (for each port). @@ -22,6 +32,7 @@ struct atl_adapter { struct aq_hw_s hw; struct aq_hw_cfg_s hw_cfg; + struct atl_interrupt intr; }; /* @@ -39,6 +50,11 @@ int atl_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id, uint16_t nb_tx_desc, unsigned int socket_id, const struct rte_eth_txconf *tx_conf); +int atl_dev_rx_queue_intr_enable(struct rte_eth_dev *eth_dev, + uint16_t queue_id); +int atl_dev_rx_queue_intr_disable(struct rte_eth_dev *eth_dev, + uint16_t queue_id); + int atl_rx_init(struct rte_eth_dev *dev); int atl_tx_init(struct rte_eth_dev *dev); diff --git a/drivers/net/atlantic/atl_rxtx.c b/drivers/net/atlantic/atl_rxtx.c index 172d5fb232f2..9d82a0d74f22 100644 --- a/drivers/net/atlantic/atl_rxtx.c +++ b/drivers/net/atlantic/atl_rxtx.c @@ -620,6 +620,42 @@ atl_stop_queues(struct rte_eth_dev *dev) return 0; } +static int +atl_rx_enable_intr(struct rte_eth_dev *dev, uint16_t queue_id, bool enable) +{ + struct aq_hw_s *hw = ATL_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct atl_rx_queue *rxq; + + PMD_INIT_FUNC_TRACE(); + + if (queue_id >= dev->data->nb_rx_queues) { + PMD_DRV_LOG(ERR, "Invalid RX queue id=%d", queue_id); + return -EINVAL; + } + + rxq = dev->data->rx_queues[queue_id]; + + if (rxq == NULL) + return 0; + + /* Mapping interrupt vector */ + hw_atl_itr_irq_map_en_rx_set(hw, enable, queue_id); + + return 0; +} + +int +atl_dev_rx_queue_intr_enable(struct rte_eth_dev *eth_dev, uint16_t queue_id) +{ + return atl_rx_enable_intr(eth_dev, queue_id, true); +} + +int +atl_dev_rx_queue_intr_disable(struct rte_eth_dev *eth_dev, uint16_t queue_id) +{ + return atl_rx_enable_intr(eth_dev, queue_id, false); +} + uint16_t atl_prep_pkts(__rte_unused void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) diff --git a/drivers/net/atlantic/atl_types.h b/drivers/net/atlantic/atl_types.h index 85f768ce7d93..5f840cc8d63d 100644 --- a/drivers/net/atlantic/atl_types.h +++ b/drivers/net/atlantic/atl_types.h @@ -93,11 +93,13 @@ struct aq_hw_s { void *mmio; struct aq_hw_link_status_s aq_link_status; + bool is_autoneg; struct hw_aq_atl_utils_mbox mbox; struct hw_atl_stats_s last_stats; struct aq_stats_s curr_stats; + u64 speed; unsigned int chip_features; u32 fw_ver_actual; u32 mbox_addr; -- 2.7.4