All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mika Westerberg <mika.westerberg@linux.intel.com>
To: linux-kernel@vger.kernel.org
Cc: Michael Jamet <michael.jamet@intel.com>,
	Yehezkel Bernat <YehezkelShB@gmail.com>,
	Andreas Noever <andreas.noever@gmail.com>,
	Lukas Wunner <lukas@wunner.de>,
	"David S . Miller" <davem@davemloft.net>,
	Andy Shevchenko <andriy.shevchenko@linux.intel.com>,
	Christian Kellner <ckellner@redhat.com>,
	Mario.Limonciello@dell.com, Joe Perches <joe@perches.com>,
	Mika Westerberg <mika.westerberg@linux.intel.com>,
	netdev@vger.kernel.org
Subject: [PATCH v4 30/36] thunderbolt: Add support for DMA tunnels
Date: Wed, 10 Apr 2019 16:36:47 +0300	[thread overview]
Message-ID: <20190410133653.88061-31-mika.westerberg@linux.intel.com> (raw)
In-Reply-To: <20190410133653.88061-1-mika.westerberg@linux.intel.com>

In addition to PCIe and Display Port tunnels it is also possible to
create tunnels that forward DMA traffic from the host interface adapter
(NHI) to a NULL port that is connected to another domain through a
Thunderbolt cable. These tunnels can be used to carry software messages
such as networking packets.

To support this we introduce another tunnel type (TB_TUNNEL_DMA) that
supports paths from NHI to NULL port and back.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 drivers/thunderbolt/path.c    | 22 +++++++--
 drivers/thunderbolt/switch.c  | 22 +++++++++
 drivers/thunderbolt/tb.h      |  4 ++
 drivers/thunderbolt/tb_regs.h |  3 ++
 drivers/thunderbolt/tunnel.c  | 93 ++++++++++++++++++++++++++++++++++-
 drivers/thunderbolt/tunnel.h  | 10 ++++
 6 files changed, 149 insertions(+), 5 deletions(-)

diff --git a/drivers/thunderbolt/path.c b/drivers/thunderbolt/path.c
index 3fc92881a197..e4c22f53ef4d 100644
--- a/drivers/thunderbolt/path.c
+++ b/drivers/thunderbolt/path.c
@@ -341,7 +341,8 @@ static void __tb_path_deallocate_nfc(struct tb_path *path, int first_hop)
 	}
 }
 
-static int __tb_path_deactivate_hop(struct tb_port *port, int hop_index)
+static int __tb_path_deactivate_hop(struct tb_port *port, int hop_index,
+				    bool clear_fc)
 {
 	struct tb_regs_hop hop;
 	ktime_t timeout;
@@ -369,8 +370,20 @@ static int __tb_path_deactivate_hop(struct tb_port *port, int hop_index)
 		if (ret)
 			return ret;
 
-		if (!hop.pending)
+		if (!hop.pending) {
+			if (clear_fc) {
+				/* Clear flow control */
+				hop.ingress_fc = 0;
+				hop.egress_fc = 0;
+				hop.ingress_shared_buffer = 0;
+				hop.egress_shared_buffer = 0;
+
+				return tb_port_write(port, &hop, TB_CFG_HOPS,
+						     2 * hop_index, 2);
+			}
+
 			return 0;
+		}
 
 		usleep_range(10, 20);
 	} while (ktime_before(ktime_get(), timeout));
@@ -384,7 +397,8 @@ static void __tb_path_deactivate_hops(struct tb_path *path, int first_hop)
 
 	for (i = first_hop; i < path->path_length; i++) {
 		res = __tb_path_deactivate_hop(path->hops[i].in_port,
-					       path->hops[i].in_hop_index);
+					       path->hops[i].in_hop_index,
+					       path->clear_fc);
 		if (res && res != -ENODEV)
 			tb_port_warn(path->hops[i].in_port,
 				     "hop deactivation failed for hop %d, index %d\n",
@@ -459,7 +473,7 @@ int tb_path_activate(struct tb_path *path)
 
 		/* If it is left active deactivate it first */
 		__tb_path_deactivate_hop(path->hops[i].in_port,
-				path->hops[i].in_hop_index);
+				path->hops[i].in_hop_index, path->clear_fc);
 
 		/* dword 0 */
 		hop.next_hop = path->hops[i].next_hop_index;
diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c
index 1de1afa24182..ecf53d986a5c 100644
--- a/drivers/thunderbolt/switch.c
+++ b/drivers/thunderbolt/switch.c
@@ -555,6 +555,28 @@ int tb_port_add_nfc_credits(struct tb_port *port, int credits)
 			     TB_CFG_PORT, 4, 1);
 }
 
+/**
+ * tb_port_set_initial_credits() - Set initial port link credits allocated
+ * @port: Port to set the initial credits
+ * @credits: Number of credits to to allocate
+ *
+ * Set initial credits value to be used for ingress shared buffering.
+ */
+int tb_port_set_initial_credits(struct tb_port *port, u32 credits)
+{
+	u32 data;
+	int ret;
+
+	ret = tb_port_read(port, &data, TB_CFG_PORT, 5, 1);
+	if (ret)
+		return ret;
+
+	data &= ~TB_PORT_LCA_MASK;
+	data |= (credits << TB_PORT_LCA_SHIFT) & TB_PORT_LCA_MASK;
+
+	return tb_port_write(port, &data, TB_CFG_PORT, 5, 1);
+}
+
 /**
  * tb_port_clear_counter() - clear a counter in TB_CFG_COUNTER
  *
diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h
index 89b5d18f6035..119a00837992 100644
--- a/drivers/thunderbolt/tb.h
+++ b/drivers/thunderbolt/tb.h
@@ -207,6 +207,8 @@ enum tb_path_port {
  * @weight: Weight of the path inside the priority group
  * @drop_packages: Drop packages from queue tail or head
  * @activated: Is the path active
+ * @clear_fc: Clear all flow control from the path config space entries
+ *	      when deactivating this path
  * @hops: Path hops
  * @path_length: How many hops the path uses
  *
@@ -227,6 +229,7 @@ struct tb_path {
 	int weight:4;
 	bool drop_packages;
 	bool activated;
+	bool clear_fc;
 	struct tb_path_hop *hops;
 	int path_length;
 };
@@ -583,6 +586,7 @@ static inline bool tb_switch_is_fr(const struct tb_switch *sw)
 
 int tb_wait_for_port(struct tb_port *port, bool wait_if_unplugged);
 int tb_port_add_nfc_credits(struct tb_port *port, int credits);
+int tb_port_set_initial_credits(struct tb_port *port, u32 credits);
 int tb_port_clear_counter(struct tb_port *port, int counter);
 int tb_port_alloc_in_hopid(struct tb_port *port, int hopid, int max_hopid);
 void tb_port_release_in_hopid(struct tb_port *port, int hopid);
diff --git a/drivers/thunderbolt/tb_regs.h b/drivers/thunderbolt/tb_regs.h
index 3ce705184e2c..deb9d4a977b9 100644
--- a/drivers/thunderbolt/tb_regs.h
+++ b/drivers/thunderbolt/tb_regs.h
@@ -215,6 +215,9 @@ struct tb_regs_port_header {
 #define TB_PORT_NFC_CREDITS_MASK	GENMASK(19, 0)
 #define TB_PORT_MAX_CREDITS_SHIFT	20
 #define TB_PORT_MAX_CREDITS_MASK	GENMASK(26, 20)
+/* DWORD 5 */
+#define TB_PORT_LCA_SHIFT		22
+#define TB_PORT_LCA_MASK		GENMASK(28, 22)
 
 /* Display Port adapter registers */
 
diff --git a/drivers/thunderbolt/tunnel.c b/drivers/thunderbolt/tunnel.c
index 0bc6639c6e74..9f9b26b12d0a 100644
--- a/drivers/thunderbolt/tunnel.c
+++ b/drivers/thunderbolt/tunnel.c
@@ -27,7 +27,10 @@
 #define TB_DP_AUX_PATH_OUT		1
 #define TB_DP_AUX_PATH_IN		2
 
-static const char * const tb_tunnel_names[] = { "PCI", "DP" };
+#define TB_DMA_PATH_OUT			0
+#define TB_DMA_PATH_IN			1
+
+static const char * const tb_tunnel_names[] = { "PCI", "DP", "DMA" };
 
 #define __TB_TUNNEL_PRINT(level, tunnel, fmt, arg...)                   \
 	do {                                                            \
@@ -471,6 +474,94 @@ struct tb_tunnel *tb_tunnel_alloc_dp(struct tb *tb, struct tb_port *in,
 	return NULL;
 }
 
+static u32 tb_dma_credits(struct tb_port *nhi)
+{
+	u32 max_credits;
+
+	max_credits = (nhi->config.nfc_credits & TB_PORT_MAX_CREDITS_MASK) >>
+		TB_PORT_MAX_CREDITS_SHIFT;
+	return min(max_credits, 13U);
+}
+
+static int tb_dma_activate(struct tb_tunnel *tunnel, bool active)
+{
+	struct tb_port *nhi = tunnel->src_port;
+	u32 credits;
+
+	credits = active ? tb_dma_credits(nhi) : 0;
+	return tb_port_set_initial_credits(nhi, credits);
+}
+
+static void tb_dma_init_path(struct tb_path *path, unsigned int isb,
+			     unsigned int efc, u32 credits)
+{
+	int i;
+
+	path->egress_fc_enable = efc;
+	path->ingress_fc_enable = TB_PATH_ALL;
+	path->egress_shared_buffer = TB_PATH_NONE;
+	path->ingress_shared_buffer = isb;
+	path->priority = 5;
+	path->weight = 1;
+	path->clear_fc = true;
+
+	for (i = 0; i < path->path_length; i++)
+		path->hops[i].initial_credits = credits;
+}
+
+/**
+ * tb_tunnel_alloc_dma() - allocate a DMA tunnel
+ * @tb: Pointer to the domain structure
+ * @nhi: Host controller port
+ * @dst: Destination null port which the other domain is connected to
+ * @transmit_ring: NHI ring number used to send packets towards the
+ *		   other domain
+ * @transmit_path: HopID used for transmitting packets
+ * @receive_ring: NHI ring number used to receive packets from the
+ *		  other domain
+ * @reveive_path: HopID used for receiving packets
+ *
+ * Return: Returns a tb_tunnel on success or NULL on failure.
+ */
+struct tb_tunnel *tb_tunnel_alloc_dma(struct tb *tb, struct tb_port *nhi,
+				      struct tb_port *dst, int transmit_ring,
+				      int transmit_path, int receive_ring,
+				      int receive_path)
+{
+	struct tb_tunnel *tunnel;
+	struct tb_path *path;
+	u32 credits;
+
+	tunnel = tb_tunnel_alloc(tb, 2, TB_TUNNEL_DMA);
+	if (!tunnel)
+		return NULL;
+
+	tunnel->activate = tb_dma_activate;
+	tunnel->src_port = nhi;
+	tunnel->dst_port = dst;
+
+	credits = tb_dma_credits(nhi);
+
+	path = tb_path_alloc(tb, dst, receive_path, nhi, receive_ring, 0, "DMA RX");
+	if (!path) {
+		tb_tunnel_free(tunnel);
+		return NULL;
+	}
+	tb_dma_init_path(path, TB_PATH_NONE, TB_PATH_SOURCE | TB_PATH_INTERNAL,
+			 credits);
+	tunnel->paths[TB_DMA_PATH_IN] = path;
+
+	path = tb_path_alloc(tb, nhi, transmit_ring, dst, transmit_path, 0, "DMA TX");
+	if (!path) {
+		tb_tunnel_free(tunnel);
+		return NULL;
+	}
+	tb_dma_init_path(path, TB_PATH_SOURCE, TB_PATH_ALL, credits);
+	tunnel->paths[TB_DMA_PATH_OUT] = path;
+
+	return tunnel;
+}
+
 /**
  * tb_tunnel_free() - free a tunnel
  * @tunnel: Tunnel to be freed
diff --git a/drivers/thunderbolt/tunnel.h b/drivers/thunderbolt/tunnel.h
index 0373779f43ba..c68bbcd3a62c 100644
--- a/drivers/thunderbolt/tunnel.h
+++ b/drivers/thunderbolt/tunnel.h
@@ -14,6 +14,7 @@
 enum tb_tunnel_type {
 	TB_TUNNEL_PCI,
 	TB_TUNNEL_DP,
+	TB_TUNNEL_DMA,
 };
 
 /**
@@ -47,6 +48,10 @@ struct tb_tunnel *tb_tunnel_alloc_pci(struct tb *tb, struct tb_port *up,
 struct tb_tunnel *tb_tunnel_discover_dp(struct tb *tb, struct tb_port *in);
 struct tb_tunnel *tb_tunnel_alloc_dp(struct tb *tb, struct tb_port *in,
 				     struct tb_port *out);
+struct tb_tunnel *tb_tunnel_alloc_dma(struct tb *tb, struct tb_port *nhi,
+				      struct tb_port *dst, int transmit_ring,
+				      int transmit_path, int receive_ring,
+				      int receive_path);
 
 void tb_tunnel_free(struct tb_tunnel *tunnel);
 int tb_tunnel_activate(struct tb_tunnel *tunnel);
@@ -64,5 +69,10 @@ static inline bool tb_tunnel_is_dp(const struct tb_tunnel *tunnel)
 	return tunnel->type == TB_TUNNEL_DP;
 }
 
+static inline bool tb_tunnel_is_dma(const struct tb_tunnel *tunnel)
+{
+	return tunnel->type == TB_TUNNEL_DMA;
+}
+
 #endif
 
-- 
2.20.1


  parent reply	other threads:[~2019-04-10 13:40 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-04-10 13:36 [PATCH v4 00/36] thunderbolt: Software connection manager improvements Mika Westerberg
2019-04-10 13:36 ` [PATCH v4 01/36] net: thunderbolt: Unregister ThunderboltIP protocol handler when suspending Mika Westerberg
2019-04-10 13:36 ` [PATCH v4 02/36] thunderbolt: Remove unused work field in struct tb_switch Mika Westerberg
2019-04-10 13:36 ` [PATCH v4 03/36] thunderbolt: Drop duplicated get_switch_at_route() Mika Westerberg
2019-04-10 13:36 ` [PATCH v4 04/36] thunderbolt: Block reads and writes if switch is unplugged Mika Westerberg
2019-04-10 13:36 ` [PATCH v4 06/36] thunderbolt: Do not allocate switch if depth is greater than 6 Mika Westerberg
2019-04-10 13:36 ` [PATCH v4 07/36] thunderbolt: Enable TMU access when accessing port space on legacy devices Mika Westerberg
2019-04-10 13:36 ` [PATCH v4 08/36] thunderbolt: Add dummy read after port capability list walk on Light Ridge Mika Westerberg
2019-04-10 13:36 ` [PATCH v4 09/36] thunderbolt: Move LC specific functionality into a separate file Mika Westerberg
2019-04-10 13:36 ` [PATCH v4 10/36] thunderbolt: Configure lanes when switch is initialized Mika Westerberg
2019-04-10 13:36 ` [PATCH v4 11/36] thunderbolt: Set sleep bit when suspending switch Mika Westerberg
2019-04-10 13:36 ` [PATCH v4 12/36] thunderbolt: Properly disable path Mika Westerberg
2019-04-10 13:36 ` [PATCH v4 13/36] thunderbolt: Cache adapter specific capability offset into struct port Mika Westerberg
2019-04-10 13:36 ` [PATCH v4 14/36] thunderbolt: Rename tunnel_pci to tunnel Mika Westerberg
2019-04-10 13:36 ` [PATCH v4 15/36] thunderbolt: Generalize tunnel creation functionality Mika Westerberg
2019-04-10 13:36 ` [PATCH v4 16/36] thunderbolt: Add functions for allocating and releasing HopIDs Mika Westerberg
2019-04-10 13:36 ` [PATCH v4 17/36] thunderbolt: Assign remote for both ports in case of dual link Mika Westerberg
2019-04-10 13:36 ` [PATCH v4 18/36] thunderbolt: Add helper function to iterate from one port to another Mika Westerberg
2019-04-10 13:36 ` [PATCH v4 19/36] thunderbolt: Extend tunnel creation to more than 2 adjacent switches Mika Westerberg
2019-04-10 13:36 ` [PATCH v4 20/36] thunderbolt: Deactivate all paths before restarting them Mika Westerberg
2019-04-10 13:36 ` [PATCH v4 21/36] thunderbolt: Discover preboot PCIe paths the boot firmware established Mika Westerberg
2019-04-10 13:36 ` [PATCH v4 22/36] thunderbolt: Add support for full PCIe daisy chains Mika Westerberg
2019-04-10 13:36 ` [PATCH v4 23/36] thunderbolt: Scan only valid NULL adapter ports in hotplug Mika Westerberg
2019-04-10 13:36 ` [PATCH v4 24/36] thunderbolt: Generalize port finding routines to support all port types Mika Westerberg
2019-04-10 13:36 ` [PATCH v4 25/36] thunderbolt: Rework NFC credits handling Mika Westerberg
2019-04-10 13:36 ` [PATCH v4 26/36] thunderbolt: Add support for Display Port tunnels Mika Westerberg
2019-04-10 13:36 ` [PATCH v4 27/36] thunderbolt: Do not tear down tunnels when driver is unloaded Mika Westerberg
2019-04-10 13:36 ` [PATCH v4 28/36] thunderbolt: Run tb_xdp_handle_request() in system workqueue Mika Westerberg
2019-04-10 13:36 ` [PATCH v4 29/36] thunderbolt: Add XDomain UUID exchange support Mika Westerberg
2019-04-10 13:36 ` Mika Westerberg [this message]
2019-04-10 13:36 ` [PATCH v4 31/36] thunderbolt: Make tb_switch_alloc() return ERR_PTR() Mika Westerberg
2019-04-10 13:36 ` [PATCH v4 32/36] thunderbolt: Add support for XDomain connections Mika Westerberg
2019-04-10 13:36 ` [PATCH v4 33/36] thunderbolt: Make __TB_[SW|PORT]_PRINT take const parameters Mika Westerberg
2019-04-10 13:36 ` [PATCH v4 34/36] thunderbolt: Make rest of the logging to happen at debug level Mika Westerberg
2019-04-10 13:36 ` [PATCH v4 35/36] thunderbolt: Reword output of tb_dump_hop() Mika Westerberg
2019-04-10 13:36 ` [PATCH v4 36/36] thunderbolt: Start firmware on Titan Ridge Apple systems Mika Westerberg
2019-04-18  8:26 ` [PATCH v4 00/36] thunderbolt: Software connection manager improvements Mika Westerberg

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190410133653.88061-31-mika.westerberg@linux.intel.com \
    --to=mika.westerberg@linux.intel.com \
    --cc=Mario.Limonciello@dell.com \
    --cc=YehezkelShB@gmail.com \
    --cc=andreas.noever@gmail.com \
    --cc=andriy.shevchenko@linux.intel.com \
    --cc=ckellner@redhat.com \
    --cc=davem@davemloft.net \
    --cc=joe@perches.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lukas@wunner.de \
    --cc=michael.jamet@intel.com \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.