{"id":814973,"url":"http://patchwork.ozlabs.org/api/patches/814973/?format=json","web_url":"http://patchwork.ozlabs.org/project/netdev/patch/20170918153049.44185-13-mika.westerberg@linux.intel.com/","project":{"id":7,"url":"http://patchwork.ozlabs.org/api/projects/7/?format=json","name":"Linux network development","link_name":"netdev","list_id":"netdev.vger.kernel.org","list_email":"netdev@vger.kernel.org","web_url":null,"scm_url":null,"webscm_url":null,"list_archive_url":"","list_archive_url_format":"","commit_url_format":""},"msgid":"<20170918153049.44185-13-mika.westerberg@linux.intel.com>","list_archive_url":null,"date":"2017-09-18T15:30:45","name":"[12/16] thunderbolt: Use spinlock in NHI serialization","commit_ref":null,"pull_url":null,"state":"not-applicable","archived":true,"hash":"c5fe6c9a1ea7d45355ccc473c28311e45dad6cb8","submitter":{"id":14534,"url":"http://patchwork.ozlabs.org/api/people/14534/?format=json","name":"Mika Westerberg","email":"mika.westerberg@linux.intel.com"},"delegate":{"id":34,"url":"http://patchwork.ozlabs.org/api/users/34/?format=json","username":"davem","first_name":"David","last_name":"Miller","email":"davem@davemloft.net"},"mbox":"http://patchwork.ozlabs.org/project/netdev/patch/20170918153049.44185-13-mika.westerberg@linux.intel.com/mbox/","series":[{"id":3664,"url":"http://patchwork.ozlabs.org/api/series/3664/?format=json","web_url":"http://patchwork.ozlabs.org/project/netdev/list/?series=3664","date":"2017-09-18T15:30:47","name":"Thunderbolt networking","version":1,"mbox":"http://patchwork.ozlabs.org/series/3664/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/814973/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/814973/checks/","tags":{},"related":[],"headers":{"Return-Path":"<netdev-owner@vger.kernel.org>","X-Original-To":"patchwork-incoming@ozlabs.org","Delivered-To":"patchwork-incoming@ozlabs.org","Authentication-Results":"ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=vger.kernel.org\n\t(client-ip=209.132.180.67; helo=vger.kernel.org;\n\tenvelope-from=netdev-owner@vger.kernel.org;\n\treceiver=<UNKNOWN>)","Received":["from vger.kernel.org (vger.kernel.org [209.132.180.67])\n\tby ozlabs.org (Postfix) with ESMTP id 3xwqjz4pNxz9s78\n\tfor <patchwork-incoming@ozlabs.org>;\n\tTue, 19 Sep 2017 01:31:51 +1000 (AEST)","(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S932725AbdIRPbg (ORCPT <rfc822;patchwork-incoming@ozlabs.org>);\n\tMon, 18 Sep 2017 11:31:36 -0400","from mga01.intel.com ([192.55.52.88]:35539 \"EHLO mga01.intel.com\"\n\trhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP\n\tid S932594AbdIRPbb (ORCPT <rfc822;netdev@vger.kernel.org>);\n\tMon, 18 Sep 2017 11:31:31 -0400","from fmsmga004.fm.intel.com ([10.253.24.48])\n\tby fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t18 Sep 2017 08:31:31 -0700","from black.fi.intel.com ([10.237.72.28])\n\tby fmsmga004.fm.intel.com with ESMTP; 18 Sep 2017 08:31:27 -0700","by black.fi.intel.com (Postfix, from userid 1001)\n\tid E6653671; Mon, 18 Sep 2017 18:30:49 +0300 (EEST)"],"X-ExtLoop1":"1","X-IronPort-AV":"E=Sophos;i=\"5.42,413,1500966000\"; d=\"scan'208\";a=\"312962859\"","From":"Mika Westerberg <mika.westerberg@linux.intel.com>","To":"Greg Kroah-Hartman <gregkh@linuxfoundation.org>,\n\t\"David S . Miller\" <davem@davemloft.net>","Cc":"Andreas Noever <andreas.noever@gmail.com>,\n\tMichael Jamet <michael.jamet@intel.com>,\n\tYehezkel Bernat <yehezkel.bernat@intel.com>,\n\tAmir Levy <amir.jer.levy@intel.com>,\n\tMario.Limonciello@dell.com, Lukas Wunner <lukas@wunner.de>,\n\tAndy Shevchenko <andriy.shevchenko@linux.intel.com>,\n\tMika Westerberg <mika.westerberg@linux.intel.com>,\n\tlinux-kernel@vger.kernel.org, netdev@vger.kernel.org","Subject":"[PATCH 12/16] thunderbolt: Use spinlock in NHI serialization","Date":"Mon, 18 Sep 2017 18:30:45 +0300","Message-Id":"<20170918153049.44185-13-mika.westerberg@linux.intel.com>","X-Mailer":"git-send-email 2.14.1","In-Reply-To":"<20170918153049.44185-1-mika.westerberg@linux.intel.com>","References":"<20170918153049.44185-1-mika.westerberg@linux.intel.com>","Sender":"netdev-owner@vger.kernel.org","Precedence":"bulk","List-ID":"<netdev.vger.kernel.org>","X-Mailing-List":"netdev@vger.kernel.org"},"content":"This is needed because ring polling functionality can be called from\natomic contexts when networking and other high-speed traffic is\ntransferred over a Thunderbolt cable.\n\nSigned-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>\nReviewed-by: Michael Jamet <michael.jamet@intel.com>\nReviewed-by: Yehezkel Bernat <yehezkel.bernat@intel.com>\n---\n drivers/thunderbolt/nhi.c   | 75 +++++++++++++++++++++++++--------------------\n include/linux/thunderbolt.h |  2 +-\n 2 files changed, 42 insertions(+), 35 deletions(-)","diff":"diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c\nindex d1ad37c6eccf..cf1397afa72f 100644\n--- a/drivers/thunderbolt/nhi.c\n+++ b/drivers/thunderbolt/nhi.c\n@@ -327,21 +327,9 @@ static struct tb_ring *tb_ring_alloc(struct tb_nhi *nhi, u32 hop, int size,\n \tif (transmit && hop == RING_E2E_UNUSED_HOPID)\n \t\treturn NULL;\n \n-\tmutex_lock(&nhi->lock);\n-\tif (hop >= nhi->hop_count) {\n-\t\tdev_WARN(&nhi->pdev->dev, \"invalid hop: %d\\n\", hop);\n-\t\tgoto err;\n-\t}\n-\tif (transmit && nhi->tx_rings[hop]) {\n-\t\tdev_WARN(&nhi->pdev->dev, \"TX hop %d already allocated\\n\", hop);\n-\t\tgoto err;\n-\t} else if (!transmit && nhi->rx_rings[hop]) {\n-\t\tdev_WARN(&nhi->pdev->dev, \"RX hop %d already allocated\\n\", hop);\n-\t\tgoto err;\n-\t}\n \tring = kzalloc(sizeof(*ring), GFP_KERNEL);\n \tif (!ring)\n-\t\tgoto err;\n+\t\treturn NULL;\n \n \tspin_lock_init(&ring->lock);\n \tINIT_LIST_HEAD(&ring->queue);\n@@ -359,25 +347,45 @@ static struct tb_ring *tb_ring_alloc(struct tb_nhi *nhi, u32 hop, int size,\n \tring->tail = 0;\n \tring->running = false;\n \n-\tif (ring_request_msix(ring, flags & RING_FLAG_NO_SUSPEND))\n-\t\tgoto err;\n-\n \tring->descriptors = dma_alloc_coherent(&ring->nhi->pdev->dev,\n \t\t\tsize * sizeof(*ring->descriptors),\n \t\t\t&ring->descriptors_dma, GFP_KERNEL | __GFP_ZERO);\n \tif (!ring->descriptors)\n-\t\tgoto err;\n+\t\tgoto err_free_ring;\n \n+\tif (ring_request_msix(ring, flags & RING_FLAG_NO_SUSPEND))\n+\t\tgoto err_free_descs;\n+\n+\tspin_lock_irq(&nhi->lock);\n+\tif (hop >= nhi->hop_count) {\n+\t\tdev_WARN(&nhi->pdev->dev, \"invalid hop: %d\\n\", hop);\n+\t\tgoto err_release_msix;\n+\t}\n+\tif (transmit && nhi->tx_rings[hop]) {\n+\t\tdev_WARN(&nhi->pdev->dev, \"TX hop %d already allocated\\n\", hop);\n+\t\tgoto err_release_msix;\n+\t} else if (!transmit && nhi->rx_rings[hop]) {\n+\t\tdev_WARN(&nhi->pdev->dev, \"RX hop %d already allocated\\n\", hop);\n+\t\tgoto err_release_msix;\n+\t}\n \tif (transmit)\n \t\tnhi->tx_rings[hop] = ring;\n \telse\n \t\tnhi->rx_rings[hop] = ring;\n-\tmutex_unlock(&nhi->lock);\n+\tspin_unlock_irq(&nhi->lock);\n+\n \treturn ring;\n \n-err:\n+err_release_msix:\n+\tspin_unlock_irq(&nhi->lock);\n+\tring_release_msix(ring);\n+err_free_descs:\n+\tdma_free_coherent(&ring->nhi->pdev->dev,\n+\t\t\t  ring->size * sizeof(*ring->descriptors),\n+\t\t\t  ring->descriptors, ring->descriptors_dma);\n+err_free_ring:\n \tkfree(ring);\n-\tmutex_unlock(&nhi->lock);\n+\n \treturn NULL;\n }\n \n@@ -421,8 +429,8 @@ void tb_ring_start(struct tb_ring *ring)\n \tu16 frame_size;\n \tu32 flags;\n \n-\tmutex_lock(&ring->nhi->lock);\n-\tspin_lock_irq(&ring->lock);\n+\tspin_lock_irq(&ring->nhi->lock);\n+\tspin_lock(&ring->lock);\n \tif (ring->nhi->going_away)\n \t\tgoto err;\n \tif (ring->running) {\n@@ -469,8 +477,8 @@ void tb_ring_start(struct tb_ring *ring)\n \tring_interrupt_active(ring, true);\n \tring->running = true;\n err:\n-\tspin_unlock_irq(&ring->lock);\n-\tmutex_unlock(&ring->nhi->lock);\n+\tspin_unlock(&ring->lock);\n+\tspin_unlock_irq(&ring->nhi->lock);\n }\n EXPORT_SYMBOL_GPL(tb_ring_start);\n \n@@ -489,8 +497,8 @@ EXPORT_SYMBOL_GPL(tb_ring_start);\n  */\n void tb_ring_stop(struct tb_ring *ring)\n {\n-\tmutex_lock(&ring->nhi->lock);\n-\tspin_lock_irq(&ring->lock);\n+\tspin_lock_irq(&ring->nhi->lock);\n+\tspin_lock(&ring->lock);\n \tdev_info(&ring->nhi->pdev->dev, \"stopping %s %d\\n\",\n \t\t RING_TYPE(ring), ring->hop);\n \tif (ring->nhi->going_away)\n@@ -511,8 +519,8 @@ void tb_ring_stop(struct tb_ring *ring)\n \tring->running = false;\n \n err:\n-\tspin_unlock_irq(&ring->lock);\n-\tmutex_unlock(&ring->nhi->lock);\n+\tspin_unlock(&ring->lock);\n+\tspin_unlock_irq(&ring->nhi->lock);\n \n \t/*\n \t * schedule ring->work to invoke callbacks on all remaining frames.\n@@ -534,7 +542,7 @@ EXPORT_SYMBOL_GPL(tb_ring_stop);\n  */\n void tb_ring_free(struct tb_ring *ring)\n {\n-\tmutex_lock(&ring->nhi->lock);\n+\tspin_lock_irq(&ring->nhi->lock);\n \t/*\n \t * Dissociate the ring from the NHI. This also ensures that\n \t * nhi_interrupt_work cannot reschedule ring->work.\n@@ -564,7 +572,7 @@ void tb_ring_free(struct tb_ring *ring)\n \t\t RING_TYPE(ring),\n \t\t ring->hop);\n \n-\tmutex_unlock(&ring->nhi->lock);\n+\tspin_unlock_irq(&ring->nhi->lock);\n \t/**\n \t * ring->work can no longer be scheduled (it is scheduled only\n \t * by nhi_interrupt_work, ring_stop and ring_msix). Wait for it\n@@ -639,7 +647,7 @@ static void nhi_interrupt_work(struct work_struct *work)\n \tint type = 0; /* current interrupt type 0: TX, 1: RX, 2: RX overflow */\n \tstruct tb_ring *ring;\n \n-\tmutex_lock(&nhi->lock);\n+\tspin_lock_irq(&nhi->lock);\n \n \t/*\n \t * Starting at REG_RING_NOTIFY_BASE there are three status bitfields\n@@ -677,7 +685,7 @@ static void nhi_interrupt_work(struct work_struct *work)\n \t\t/* we do not check ring->running, this is done in ring->work */\n \t\tschedule_work(&ring->work);\n \t}\n-\tmutex_unlock(&nhi->lock);\n+\tspin_unlock_irq(&nhi->lock);\n }\n \n static irqreturn_t nhi_msi(int irq, void *data)\n@@ -766,7 +774,6 @@ static void nhi_shutdown(struct tb_nhi *nhi)\n \t\tdevm_free_irq(&nhi->pdev->dev, nhi->pdev->irq, nhi);\n \t\tflush_work(&nhi->interrupt_work);\n \t}\n-\tmutex_destroy(&nhi->lock);\n \tida_destroy(&nhi->msix_ida);\n }\n \n@@ -855,7 +862,7 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id)\n \t\treturn res;\n \t}\n \n-\tmutex_init(&nhi->lock);\n+\tspin_lock_init(&nhi->lock);\n \n \tpci_set_master(pdev);\n \ndiff --git a/include/linux/thunderbolt.h b/include/linux/thunderbolt.h\nindex 51af0a5fa52f..62adb97d77f1 100644\n--- a/include/linux/thunderbolt.h\n+++ b/include/linux/thunderbolt.h\n@@ -415,7 +415,7 @@ static inline struct tb_xdomain *tb_service_parent(struct tb_service *svc)\n  * @hop_count: Number of rings (end point hops) supported by NHI.\n  */\n struct tb_nhi {\n-\tstruct mutex lock;\n+\tspinlock_t lock;\n \tstruct pci_dev *pdev;\n \tvoid __iomem *iobase;\n \tstruct tb_ring **tx_rings;\n","prefixes":["12/16"]}