Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/1032826/?format=api
{ "id": 1032826, "url": "http://patchwork.ozlabs.org/api/patches/1032826/?format=api", "web_url": "http://patchwork.ozlabs.org/project/netdev/patch/20190129150143.12681-12-mika.westerberg@linux.intel.com/", "project": { "id": 7, "url": "http://patchwork.ozlabs.org/api/projects/7/?format=api", "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": "<20190129150143.12681-12-mika.westerberg@linux.intel.com>", "list_archive_url": null, "date": "2019-01-29T15:01:26", "name": "[11/28] thunderbolt: Generalize tunnel creation functionality", "commit_ref": null, "pull_url": null, "state": "not-applicable", "archived": false, "hash": "806722c4329dcb8df4f8c93f1009017d2fb48d53", "submitter": { "id": 14534, "url": "http://patchwork.ozlabs.org/api/people/14534/?format=api", "name": "Mika Westerberg", "email": "mika.westerberg@linux.intel.com" }, "delegate": { "id": 34, "url": "http://patchwork.ozlabs.org/api/users/34/?format=api", "username": "davem", "first_name": "David", "last_name": "Miller", "email": "davem@davemloft.net" }, "mbox": "http://patchwork.ozlabs.org/project/netdev/patch/20190129150143.12681-12-mika.westerberg@linux.intel.com/mbox/", "series": [ { "id": 88859, "url": "http://patchwork.ozlabs.org/api/series/88859/?format=api", "web_url": "http://patchwork.ozlabs.org/project/netdev/list/?series=88859", "date": "2019-01-29T15:01:18", "name": "thunderbolt: Software connection manager improvements", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/88859/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/1032826/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/1032826/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<netdev-owner@vger.kernel.org>", "X-Original-To": "patchwork-incoming-netdev@ozlabs.org", "Delivered-To": "patchwork-incoming-netdev@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>)", "ozlabs.org; dmarc=none (p=none dis=none)\n\theader.from=linux.intel.com" ], "Received": [ "from vger.kernel.org (vger.kernel.org [209.132.180.67])\n\tby ozlabs.org (Postfix) with ESMTP id 43pqXL4wvCz9sDP\n\tfor <patchwork-incoming-netdev@ozlabs.org>;\n\tWed, 30 Jan 2019 02:04:18 +1100 (AEDT)", "(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S1728333AbfA2PBx (ORCPT\n\t<rfc822;patchwork-incoming-netdev@ozlabs.org>);\n\tTue, 29 Jan 2019 10:01:53 -0500", "from mga04.intel.com ([192.55.52.120]:40215 \"EHLO mga04.intel.com\"\n\trhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP\n\tid S1728197AbfA2PBw (ORCPT <rfc822;netdev@vger.kernel.org>);\n\tTue, 29 Jan 2019 10:01:52 -0500", "from orsmga003.jf.intel.com ([10.7.209.27])\n\tby fmsmga104.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t29 Jan 2019 07:01:51 -0800", "from black.fi.intel.com ([10.237.72.28])\n\tby orsmga003.jf.intel.com with ESMTP; 29 Jan 2019 07:01:48 -0800", "by black.fi.intel.com (Postfix, from userid 1001)\n\tid ABC6417F; Tue, 29 Jan 2019 17:01:44 +0200 (EET)" ], "X-Amp-Result": "SKIPPED(no attachment in message)", "X-Amp-File-Uploaded": "False", "X-ExtLoop1": "1", "X-IronPort-AV": "E=Sophos;i=\"5.56,537,1539673200\"; d=\"scan'208\";a=\"122266139\"", "From": "Mika Westerberg <mika.westerberg@linux.intel.com>", "To": "linux-kernel@vger.kernel.org", "Cc": "Michael Jamet <michael.jamet@intel.com>,\n\tYehezkel Bernat <YehezkelShB@gmail.com>,\n\tAndreas Noever <andreas.noever@gmail.com>,\n\tLukas Wunner <lukas@wunner.de>, \"David S . Miller\" <davem@davemloft.net>,\n\tMika Westerberg <mika.westerberg@linux.intel.com>,\n\tAndy Shevchenko <andriy.shevchenko@linux.intel.com>,\n\tnetdev@vger.kernel.org", "Subject": "[PATCH 11/28] thunderbolt: Generalize tunnel creation functionality", "Date": "Tue, 29 Jan 2019 18:01:26 +0300", "Message-Id": "<20190129150143.12681-12-mika.westerberg@linux.intel.com>", "X-Mailer": "git-send-email 2.20.1", "In-Reply-To": "<20190129150143.12681-1-mika.westerberg@linux.intel.com>", "References": "<20190129150143.12681-1-mika.westerberg@linux.intel.com>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "Sender": "netdev-owner@vger.kernel.org", "Precedence": "bulk", "List-ID": "<netdev.vger.kernel.org>", "X-Mailing-List": "netdev@vger.kernel.org" }, "content": "To be able to tunnel non-PCIe traffic, separate tunnel functionality\ninto generic and PCIe specific parts. Rename struct tb_pci_tunnel to\ntb_tunnel, and make it hold an array of paths instead of just two.\nUpdate all the tunneling functions to take this structure as parameter.\n\nWe also move tb_pci_port_active() to switch.c (and rename it) where we\nwill be keeping all port and switch related functions.\n\nSigned-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>\n---\n drivers/thunderbolt/switch.c | 13 ++\n drivers/thunderbolt/tb.c | 30 ++--\n drivers/thunderbolt/tb.h | 2 +\n drivers/thunderbolt/tb_regs.h | 4 +\n drivers/thunderbolt/tunnel.c | 298 ++++++++++++++++++++--------------\n drivers/thunderbolt/tunnel.h | 38 +++--\n 6 files changed, 235 insertions(+), 150 deletions(-)", "diff": "diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c\nindex fcafe4095de5..93b26c901637 100644\n--- a/drivers/thunderbolt/switch.c\n+++ b/drivers/thunderbolt/switch.c\n@@ -606,6 +606,19 @@ static int tb_init_port(struct tb_port *port)\n \n }\n \n+/**\n+ * tb_pci_port_enable() - Enable PCIe adapter port\n+ * @port: PCIe port to enable\n+ * @enable: Enable/disable the PCIe adapter\n+ */\n+int tb_pci_port_enable(struct tb_port *port, bool enable)\n+{\n+\tu32 word = enable ? TB_PCI_EN : 0x0;\n+\tif (port->cap_adap < 0)\n+\t\treturn -ENXIO;\n+\treturn tb_port_write(port, &word, TB_CFG_PORT, port->cap_adap, 1);\n+}\n+\n /* switch utility functions */\n \n static void tb_dump_switch(struct tb *tb, struct tb_regs_switch_header *sw)\ndiff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c\nindex 6047afc6f7b8..8986f4a179bd 100644\n--- a/drivers/thunderbolt/tb.c\n+++ b/drivers/thunderbolt/tb.c\n@@ -91,14 +91,14 @@ static void tb_scan_port(struct tb_port *port)\n static void tb_free_invalid_tunnels(struct tb *tb)\n {\n \tstruct tb_cm *tcm = tb_priv(tb);\n-\tstruct tb_pci_tunnel *tunnel;\n-\tstruct tb_pci_tunnel *n;\n+\tstruct tb_tunnel *tunnel;\n+\tstruct tb_tunnel *n;\n \n \tlist_for_each_entry_safe(tunnel, n, &tcm->tunnel_list, list) {\n-\t\tif (tb_pci_is_invalid(tunnel)) {\n-\t\t\ttb_pci_deactivate(tunnel);\n+\t\tif (tb_tunnel_is_invalid(tunnel)) {\n+\t\t\ttb_tunnel_deactivate(tunnel);\n \t\t\tlist_del(&tunnel->list);\n-\t\t\ttb_pci_free(tunnel);\n+\t\t\ttb_tunnel_free(tunnel);\n \t\t}\n \t}\n }\n@@ -178,7 +178,7 @@ static void tb_activate_pcie_devices(struct tb *tb)\n \tstruct tb_switch *sw;\n \tstruct tb_port *up_port;\n \tstruct tb_port *down_port;\n-\tstruct tb_pci_tunnel *tunnel;\n+\tstruct tb_tunnel *tunnel;\n \tstruct tb_cm *tcm = tb_priv(tb);\n \n \t/* scan for pcie devices at depth 1*/\n@@ -214,17 +214,17 @@ static void tb_activate_pcie_devices(struct tb *tb)\n \t\t\t\t \"All PCIe down ports are occupied, aborting\\n\");\n \t\t\tcontinue;\n \t\t}\n-\t\ttunnel = tb_pci_alloc(tb, up_port, down_port);\n+\t\ttunnel = tb_tunnel_alloc_pci(tb, up_port, down_port);\n \t\tif (!tunnel) {\n \t\t\ttb_port_info(up_port,\n \t\t\t\t \"PCIe tunnel allocation failed, aborting\\n\");\n \t\t\tcontinue;\n \t\t}\n \n-\t\tif (tb_pci_activate(tunnel)) {\n+\t\tif (tb_tunnel_activate(tunnel)) {\n \t\t\ttb_port_info(up_port,\n \t\t\t\t \"PCIe tunnel activation failed, aborting\\n\");\n-\t\t\ttb_pci_free(tunnel);\n+\t\t\ttb_tunnel_free(tunnel);\n \t\t\tcontinue;\n \t\t}\n \n@@ -350,13 +350,13 @@ static void tb_handle_event(struct tb *tb, enum tb_cfg_pkg_type type,\n static void tb_stop(struct tb *tb)\n {\n \tstruct tb_cm *tcm = tb_priv(tb);\n-\tstruct tb_pci_tunnel *tunnel;\n-\tstruct tb_pci_tunnel *n;\n+\tstruct tb_tunnel *tunnel;\n+\tstruct tb_tunnel *n;\n \n \t/* tunnels are only present after everything has been initialized */\n \tlist_for_each_entry_safe(tunnel, n, &tcm->tunnel_list, list) {\n-\t\ttb_pci_deactivate(tunnel);\n-\t\ttb_pci_free(tunnel);\n+\t\ttb_tunnel_deactivate(tunnel);\n+\t\ttb_tunnel_free(tunnel);\n \t}\n \ttb_switch_remove(tb->root_switch);\n \ttcm->hotplug_active = false; /* signal tb_handle_hotplug to quit */\n@@ -415,7 +415,7 @@ static int tb_suspend_noirq(struct tb *tb)\n static int tb_resume_noirq(struct tb *tb)\n {\n \tstruct tb_cm *tcm = tb_priv(tb);\n-\tstruct tb_pci_tunnel *tunnel, *n;\n+\tstruct tb_tunnel *tunnel, *n;\n \n \ttb_dbg(tb, \"resuming...\\n\");\n \n@@ -426,7 +426,7 @@ static int tb_resume_noirq(struct tb *tb)\n \ttb_free_invalid_tunnels(tb);\n \ttb_free_unplugged_children(tb->root_switch);\n \tlist_for_each_entry_safe(tunnel, n, &tcm->tunnel_list, list)\n-\t\ttb_pci_restart(tunnel);\n+\t\ttb_tunnel_restart(tunnel);\n \tif (!list_empty(&tcm->tunnel_list)) {\n \t\t/*\n \t\t * the pcie links need some time to get going.\ndiff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h\nindex 43a1d7dfba73..ca7e78190920 100644\n--- a/drivers/thunderbolt/tb.h\n+++ b/drivers/thunderbolt/tb.h\n@@ -444,6 +444,8 @@ int tb_port_clear_counter(struct tb_port *port, int counter);\n int tb_switch_find_vse_cap(struct tb_switch *sw, enum tb_switch_vse_cap vsec);\n int tb_port_find_cap(struct tb_port *port, enum tb_port_cap cap);\n \n+int tb_pci_port_enable(struct tb_port *port, bool enable);\n+\n struct tb_path *tb_path_alloc(struct tb *tb, int num_hops);\n void tb_path_free(struct tb_path *path);\n int tb_path_activate(struct tb_path *path);\ndiff --git a/drivers/thunderbolt/tb_regs.h b/drivers/thunderbolt/tb_regs.h\nindex 82ac4ec8757f..75e935acade5 100644\n--- a/drivers/thunderbolt/tb_regs.h\n+++ b/drivers/thunderbolt/tb_regs.h\n@@ -211,6 +211,10 @@ struct tb_regs_port_header {\n \n } __packed;\n \n+/* PCIe adapter registers */\n+\n+#define TB_PCI_EN\t\t\tBIT(31)\n+\n /* Hop register from TB_CFG_HOPS. 8 byte per entry. */\n struct tb_regs_hop {\n \t/* DWORD 0 */\ndiff --git a/drivers/thunderbolt/tunnel.c b/drivers/thunderbolt/tunnel.c\nindex bd1194f65d14..20ce28276f7a 100644\n--- a/drivers/thunderbolt/tunnel.c\n+++ b/drivers/thunderbolt/tunnel.c\n@@ -1,8 +1,9 @@\n // SPDX-License-Identifier: GPL-2.0\n /*\n- * Thunderbolt Cactus Ridge driver - Tunneling support\n+ * Thunderbolt driver - Tunneling support\n *\n * Copyright (c) 2014 Andreas Noever <andreas.noever@gmail.com>\n+ * Copyright (C) 2019, Intel Corporation\n */\n \n #include <linux/slab.h>\n@@ -11,14 +12,17 @@\n #include \"tunnel.h\"\n #include \"tb.h\"\n \n+#define TB_PCI_PATH_DOWN\t\t0\n+#define TB_PCI_PATH_UP\t\t\t1\n+\n #define __TB_TUNNEL_PRINT(level, tunnel, fmt, arg...) \\\n \tdo { \\\n-\t\tstruct tb_pci_tunnel *__tunnel = (tunnel); \\\n+\t\tstruct tb_tunnel *__tunnel = (tunnel); \\\n \t\tlevel(__tunnel->tb, \"%llx:%x <-> %llx:%x (PCI): \" fmt, \\\n-\t\t tb_route(__tunnel->down_port->sw), \\\n-\t\t __tunnel->down_port->port, \\\n-\t\t tb_route(__tunnel->up_port->sw), \\\n-\t\t __tunnel->up_port->port, \\\n+\t\t tb_route(__tunnel->src_port->sw), \\\n+\t\t __tunnel->src_port->port, \\\n+\t\t tb_route(__tunnel->dst_port->sw), \\\n+\t\t __tunnel->dst_port->port, \\\n \t\t ## arg); \\\n \t} while (0)\n \n@@ -29,6 +33,38 @@\n #define tb_tunnel_info(tunnel, fmt, arg...) \\\n \t__TB_TUNNEL_PRINT(tb_info, tunnel, fmt, ##arg)\n \n+static struct tb_tunnel *tb_tunnel_alloc(struct tb *tb, size_t npaths)\n+{\n+\tstruct tb_tunnel *tunnel;\n+\n+\ttunnel = kzalloc(sizeof(*tunnel), GFP_KERNEL);\n+\tif (!tunnel)\n+\t\treturn NULL;\n+\n+\ttunnel->paths = kcalloc(npaths, sizeof(tunnel->paths[0]), GFP_KERNEL);\n+\tif (!tunnel->paths) {\n+\t\ttb_tunnel_free(tunnel);\n+\t\treturn NULL;\n+\t}\n+\n+\tINIT_LIST_HEAD(&tunnel->list);\n+\ttunnel->tb = tb;\n+\ttunnel->npaths = npaths;\n+\n+\treturn tunnel;\n+}\n+\n+static int tb_pci_activate(struct tb_tunnel *tunnel, bool activate)\n+{\n+\tint res;\n+\n+\tres = tb_pci_port_enable(tunnel->src_port, activate);\n+\tif (res)\n+\t\treturn res;\n+\n+\treturn tb_pci_port_enable(tunnel->dst_port, activate);\n+}\n+\n static void tb_pci_init_path(struct tb_path *path)\n {\n \tpath->egress_fc_enable = TB_PATH_SOURCE | TB_PATH_INTERNAL;\n@@ -42,7 +78,10 @@ static void tb_pci_init_path(struct tb_path *path)\n }\n \n /**\n- * tb_pci_alloc() - allocate a pci tunnel\n+ * tb_tunnel_alloc_pci() - allocate a pci tunnel\n+ * @tb: Pointer to the domain structure\n+ * @up: PCIe upstream adapter port\n+ * @down: PCIe downstream adapter port\n *\n * Allocate a PCI tunnel. The ports must be of type TB_TYPE_PCIE_UP and\n * TB_TYPE_PCIE_DOWN.\n@@ -54,170 +93,185 @@ static void tb_pci_init_path(struct tb_path *path)\n * my thunderbolt devices). Therefore at most ONE path per device may be\n * activated.\n *\n- * Return: Returns a tb_pci_tunnel on success or NULL on failure.\n+ * Return: Returns a tb_tunnel on success or NULL on failure.\n */\n-struct tb_pci_tunnel *tb_pci_alloc(struct tb *tb, struct tb_port *up,\n-\t\t\t\t struct tb_port *down)\n+struct tb_tunnel *tb_tunnel_alloc_pci(struct tb *tb, struct tb_port *up,\n+\t\t\t\t struct tb_port *down)\n {\n-\tstruct tb_pci_tunnel *tunnel = kzalloc(sizeof(*tunnel), GFP_KERNEL);\n+\tstruct tb_path *path_to_up;\n+\tstruct tb_path *path_to_down;\n+\tstruct tb_tunnel *tunnel;\n+\n+\ttunnel = tb_tunnel_alloc(tb, 2);\n \tif (!tunnel)\n-\t\tgoto err;\n-\ttunnel->tb = tb;\n-\ttunnel->down_port = down;\n-\ttunnel->up_port = up;\n-\tINIT_LIST_HEAD(&tunnel->list);\n-\ttunnel->path_to_up = tb_path_alloc(up->sw->tb, 2);\n-\tif (!tunnel->path_to_up)\n-\t\tgoto err;\n-\ttunnel->path_to_down = tb_path_alloc(up->sw->tb, 2);\n-\tif (!tunnel->path_to_down)\n-\t\tgoto err;\n-\ttb_pci_init_path(tunnel->path_to_up);\n-\ttb_pci_init_path(tunnel->path_to_down);\n-\n-\ttunnel->path_to_up->hops[0].in_port = down;\n-\ttunnel->path_to_up->hops[0].in_hop_index = 8;\n-\ttunnel->path_to_up->hops[0].in_counter_index = -1;\n-\ttunnel->path_to_up->hops[0].out_port = tb_upstream_port(up->sw)->remote;\n-\ttunnel->path_to_up->hops[0].next_hop_index = 8;\n-\n-\ttunnel->path_to_up->hops[1].in_port = tb_upstream_port(up->sw);\n-\ttunnel->path_to_up->hops[1].in_hop_index = 8;\n-\ttunnel->path_to_up->hops[1].in_counter_index = -1;\n-\ttunnel->path_to_up->hops[1].out_port = up;\n-\ttunnel->path_to_up->hops[1].next_hop_index = 8;\n-\n-\ttunnel->path_to_down->hops[0].in_port = up;\n-\ttunnel->path_to_down->hops[0].in_hop_index = 8;\n-\ttunnel->path_to_down->hops[0].in_counter_index = -1;\n-\ttunnel->path_to_down->hops[0].out_port = tb_upstream_port(up->sw);\n-\ttunnel->path_to_down->hops[0].next_hop_index = 8;\n-\n-\ttunnel->path_to_down->hops[1].in_port =\n-\t\ttb_upstream_port(up->sw)->remote;\n-\ttunnel->path_to_down->hops[1].in_hop_index = 8;\n-\ttunnel->path_to_down->hops[1].in_counter_index = -1;\n-\ttunnel->path_to_down->hops[1].out_port = down;\n-\ttunnel->path_to_down->hops[1].next_hop_index = 8;\n-\treturn tunnel;\n+\t\treturn NULL;\n \n-err:\n-\tif (tunnel) {\n-\t\tif (tunnel->path_to_down)\n-\t\t\ttb_path_free(tunnel->path_to_down);\n-\t\tif (tunnel->path_to_up)\n-\t\t\ttb_path_free(tunnel->path_to_up);\n-\t\tkfree(tunnel);\n+\ttunnel->activate = tb_pci_activate;\n+\ttunnel->src_port = down;\n+\ttunnel->dst_port = up;\n+\n+\tpath_to_up = tb_path_alloc(tb, 2);\n+\tif (!path_to_up) {\n+\t\ttb_tunnel_free(tunnel);\n+\t\treturn NULL;\n \t}\n-\treturn NULL;\n+\ttunnel->paths[TB_PCI_PATH_UP] = path_to_up;\n+\n+\tpath_to_down = tb_path_alloc(tb, 2);\n+\tif (!path_to_down) {\n+\t\ttb_tunnel_free(tunnel);\n+\t\treturn NULL;\n+\t}\n+\ttunnel->paths[TB_PCI_PATH_DOWN] = path_to_down;\n+\n+\ttb_pci_init_path(path_to_up);\n+\ttb_pci_init_path(path_to_down);\n+\n+\tpath_to_up->hops[0].in_port = down;\n+\tpath_to_up->hops[0].in_hop_index = 8;\n+\tpath_to_up->hops[0].in_counter_index = -1;\n+\tpath_to_up->hops[0].out_port = tb_upstream_port(up->sw)->remote;\n+\tpath_to_up->hops[0].next_hop_index = 8;\n+\n+\tpath_to_up->hops[1].in_port = tb_upstream_port(up->sw);\n+\tpath_to_up->hops[1].in_hop_index = 8;\n+\tpath_to_up->hops[1].in_counter_index = -1;\n+\tpath_to_up->hops[1].out_port = up;\n+\tpath_to_up->hops[1].next_hop_index = 8;\n+\n+\tpath_to_down->hops[0].in_port = up;\n+\tpath_to_down->hops[0].in_hop_index = 8;\n+\tpath_to_down->hops[0].in_counter_index = -1;\n+\tpath_to_down->hops[0].out_port = tb_upstream_port(up->sw);\n+\tpath_to_down->hops[0].next_hop_index = 8;\n+\n+\tpath_to_down->hops[1].in_port = tb_upstream_port(up->sw)->remote;\n+\tpath_to_down->hops[1].in_hop_index = 8;\n+\tpath_to_down->hops[1].in_counter_index = -1;\n+\tpath_to_down->hops[1].out_port = down;\n+\tpath_to_down->hops[1].next_hop_index = 8;\n+\n+\treturn tunnel;\n }\n \n /**\n- * tb_pci_free() - free a tunnel\n+ * tb_tunnel_free() - free a tunnel\n+ * @tunnel: Tunnel to be freed\n *\n * The tunnel must have been deactivated.\n */\n-void tb_pci_free(struct tb_pci_tunnel *tunnel)\n+void tb_tunnel_free(struct tb_tunnel *tunnel)\n {\n-\tif (tunnel->path_to_up->activated || tunnel->path_to_down->activated) {\n-\t\ttb_tunnel_WARN(tunnel, \"trying to free an activated tunnel\\n\");\n+\tint i;\n+\n+\tif (!tunnel)\n \t\treturn;\n+\n+\tfor (i = 0; i < tunnel->npaths; i++) {\n+\t\tif (tunnel->paths[i] && tunnel->paths[i]->activated) {\n+\t\t\ttb_tunnel_WARN(tunnel,\n+\t\t\t\t \"trying to free an activated tunnel\\n\");\n+\t\t\treturn;\n+\t\t}\n \t}\n-\ttb_path_free(tunnel->path_to_up);\n-\ttb_path_free(tunnel->path_to_down);\n+\n+\tfor (i = 0; i < tunnel->npaths; i++) {\n+\t\tif (tunnel->paths[i])\n+\t\t\ttb_path_free(tunnel->paths[i]);\n+\t}\n+\n+\tkfree(tunnel->paths);\n \tkfree(tunnel);\n }\n \n /**\n- * tb_pci_is_invalid - check whether an activated path is still valid\n+ * tb_tunnel_is_invalid - check whether an activated path is still valid\n+ * @tunnel: Tunnel to check\n */\n-bool tb_pci_is_invalid(struct tb_pci_tunnel *tunnel)\n+bool tb_tunnel_is_invalid(struct tb_tunnel *tunnel)\n {\n-\tWARN_ON(!tunnel->path_to_up->activated);\n-\tWARN_ON(!tunnel->path_to_down->activated);\n+\tint i;\n \n-\treturn tb_path_is_invalid(tunnel->path_to_up)\n-\t || tb_path_is_invalid(tunnel->path_to_down);\n-}\n+\tfor (i = 0; i < tunnel->npaths; i++) {\n+\t\tWARN_ON(!tunnel->paths[i]->activated);\n+\t\tif (tb_path_is_invalid(tunnel->paths[i]))\n+\t\t\treturn true;\n+\t}\n \n-/**\n- * tb_pci_port_active() - activate/deactivate PCI capability\n- *\n- * Return: Returns 0 on success or an error code on failure.\n- */\n-static int tb_pci_port_active(struct tb_port *port, bool active)\n-{\n-\tu32 word = active ? 0x80000000 : 0x0;\n-\tif (port->cap_adap < 0)\n-\t\treturn -ENXIO;\n-\treturn tb_port_write(port, &word, TB_CFG_PORT, port->cap_adap, 1);\n+\treturn false;\n }\n \n /**\n- * tb_pci_restart() - activate a tunnel after a hardware reset\n+ * tb_tunnel_restart() - activate a tunnel after a hardware reset\n+ * @tunnel: Tunnel to restart\n+ *\n+ * Return: 0 on success and negative errno in case if failure\n */\n-int tb_pci_restart(struct tb_pci_tunnel *tunnel)\n+int tb_tunnel_restart(struct tb_tunnel *tunnel)\n {\n-\tint res;\n-\ttunnel->path_to_up->activated = false;\n-\ttunnel->path_to_down->activated = false;\n+\tint res, i;\n \n \ttb_tunnel_info(tunnel, \"activating\\n\");\n \n-\tres = tb_path_activate(tunnel->path_to_up);\n-\tif (res)\n-\t\tgoto err;\n-\tres = tb_path_activate(tunnel->path_to_down);\n-\tif (res)\n-\t\tgoto err;\n+\tfor (i = 0; i < tunnel->npaths; i++) {\n+\t\ttunnel->paths[i]->activated = false;\n+\t\tres = tb_path_activate(tunnel->paths[i]);\n+\t\tif (res)\n+\t\t\tgoto err;\n+\t}\n \n-\tres = tb_pci_port_active(tunnel->down_port, true);\n-\tif (res)\n-\t\tgoto err;\n+\tif (tunnel->activate) {\n+\t\tres = tunnel->activate(tunnel, true);\n+\t\tif (res)\n+\t\t\tgoto err;\n+\t}\n \n-\tres = tb_pci_port_active(tunnel->up_port, true);\n-\tif (res)\n-\t\tgoto err;\n \treturn 0;\n+\n err:\n \ttb_tunnel_warn(tunnel, \"activation failed\\n\");\n-\ttb_pci_deactivate(tunnel);\n+\ttb_tunnel_deactivate(tunnel);\n \treturn res;\n }\n \n /**\n- * tb_pci_activate() - activate a tunnel\n+ * tb_tunnel_activate() - activate a tunnel\n+ * @tunnel: Tunnel to activate\n *\n * Return: Returns 0 on success or an error code on failure.\n */\n-int tb_pci_activate(struct tb_pci_tunnel *tunnel)\n+int tb_tunnel_activate(struct tb_tunnel *tunnel)\n {\n-\tif (tunnel->path_to_up->activated || tunnel->path_to_down->activated) {\n-\t\ttb_tunnel_WARN(tunnel,\n-\t\t\t \"trying to activate an already activated tunnel\\n\");\n-\t\treturn -EINVAL;\n-\t}\n+\tint i;\n \n-\treturn tb_pci_restart(tunnel);\n-}\n+\ttb_tunnel_info(tunnel, \"activating\\n\");\n \n+\tfor (i = 0; i < tunnel->npaths; i++) {\n+\t\tif (tunnel->paths[i]->activated) {\n+\t\t\ttb_tunnel_WARN(tunnel,\n+\t\t\t\t \"trying to activate an already activated tunnel\\n\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n \n+\treturn tb_tunnel_restart(tunnel);\n+}\n \n /**\n- * tb_pci_deactivate() - deactivate a tunnel\n+ * tb_tunnel_deactivate() - deactivate a tunnel\n+ * @tunnel: Tunnel to deactivate\n */\n-void tb_pci_deactivate(struct tb_pci_tunnel *tunnel)\n+void tb_tunnel_deactivate(struct tb_tunnel *tunnel)\n {\n+\tint i;\n+\n \ttb_tunnel_info(tunnel, \"deactivating\\n\");\n-\t/*\n-\t * TODO: enable reset by writing 0x04000000 to TB_CAP_PCIE + 1 on up\n-\t * port. Seems to have no effect?\n-\t */\n-\ttb_pci_port_active(tunnel->up_port, false);\n-\ttb_pci_port_active(tunnel->down_port, false);\n-\tif (tunnel->path_to_down->activated)\n-\t\ttb_path_deactivate(tunnel->path_to_down);\n-\tif (tunnel->path_to_up->activated)\n-\t\ttb_path_deactivate(tunnel->path_to_up);\n-}\n \n+\tif (tunnel->activate)\n+\t\ttunnel->activate(tunnel, false);\n+\n+\tfor (i = 0; i < tunnel->npaths; i++) {\n+\t\tif (tunnel->paths[i]->activated)\n+\t\t\ttb_path_deactivate(tunnel->paths[i]);\n+\t}\n+}\ndiff --git a/drivers/thunderbolt/tunnel.h b/drivers/thunderbolt/tunnel.h\nindex dff0f27d6ab5..b4e992165e56 100644\n--- a/drivers/thunderbolt/tunnel.h\n+++ b/drivers/thunderbolt/tunnel.h\n@@ -1,8 +1,9 @@\n /* SPDX-License-Identifier: GPL-2.0 */\n /*\n- * Thunderbolt Cactus Ridge driver - Tunneling support\n+ * Thunderbolt driver - Tunneling support\n *\n * Copyright (c) 2014 Andreas Noever <andreas.noever@gmail.com>\n+ * Copyright (C) 2019, Intel Corporation\n */\n \n #ifndef TB_TUNNEL_H_\n@@ -10,22 +11,33 @@\n \n #include \"tb.h\"\n \n-struct tb_pci_tunnel {\n+/**\n+ * struct tb_tunnel - Tunnel between two ports\n+ * @tb: Pointer to the domain\n+ * @src_port: Source port of the tunnel\n+ * @dst_port: Destination port of the tunnel\n+ * @paths: All paths required by the tunnel\n+ * @npaths: Number of paths in @paths\n+ * @activate: Optional tunnel specific activation/deactivation\n+ * @list: Tunnels are linked using this field\n+ */\n+struct tb_tunnel {\n \tstruct tb *tb;\n-\tstruct tb_port *up_port;\n-\tstruct tb_port *down_port;\n-\tstruct tb_path *path_to_up;\n-\tstruct tb_path *path_to_down;\n+\tstruct tb_port *src_port;\n+\tstruct tb_port *dst_port;\n+\tstruct tb_path **paths;\n+\tsize_t npaths;\n+\tint (*activate)(struct tb_tunnel *tunnel, bool activate);\n \tstruct list_head list;\n };\n \n-struct tb_pci_tunnel *tb_pci_alloc(struct tb *tb, struct tb_port *up,\n-\t\t\t\t struct tb_port *down);\n-void tb_pci_free(struct tb_pci_tunnel *tunnel);\n-int tb_pci_activate(struct tb_pci_tunnel *tunnel);\n-int tb_pci_restart(struct tb_pci_tunnel *tunnel);\n-void tb_pci_deactivate(struct tb_pci_tunnel *tunnel);\n-bool tb_pci_is_invalid(struct tb_pci_tunnel *tunnel);\n+struct tb_tunnel *tb_tunnel_alloc_pci(struct tb *tb, struct tb_port *up,\n+\t\t\t\t struct tb_port *down);\n+void tb_tunnel_free(struct tb_tunnel *tunnel);\n+int tb_tunnel_activate(struct tb_tunnel *tunnel);\n+int tb_tunnel_restart(struct tb_tunnel *tunnel);\n+void tb_tunnel_deactivate(struct tb_tunnel *tunnel);\n+bool tb_tunnel_is_invalid(struct tb_tunnel *tunnel);\n \n #endif\n \n", "prefixes": [ "11/28" ] }