diff mbox series

[v3,6/6] thunderbolt: Change TMU mode to HiFi uni-directional once DisplayPort tunneled

Message ID 20220511140549.10571-7-gil.fine@intel.com
State New
Headers show
Series thunderbolt: CL1 support for USB4 and Titan Ridge | expand

Commit Message

Gil Fine May 11, 2022, 2:05 p.m. UTC
Here we configure TMU mode to HiFi uni-directional once DP tunnel
is created. This is due to accuracy requirement for DP tunneling
as appears in CM guide 1.0, section 7.3.2.
Due to Intel hardware limitation, once we changed the TMU mode to HiFi
uni-directional (when DP tunnel exists), we don't change TMU mode back to
normal uni-directional, even if DP tunnel is torn down later.

Signed-off-by: Gil Fine <gil.fine@intel.com>
---
 drivers/thunderbolt/tb.c  | 28 ++++++++++++++++++++++++++++
 drivers/thunderbolt/tb.h  |  5 +++++
 drivers/thunderbolt/tmu.c | 14 ++++++++++++++
 3 files changed, 47 insertions(+)

Comments

Mika Westerberg May 16, 2022, 8:34 a.m. UTC | #1
Hi Gil,

On Sun, May 15, 2022 at 11:27:46PM +0300, Gil Fine wrote:
> > > +int tb_switch_tmu_config_enable(struct device *dev, void *data)
> > 
> > Also can we please make it take some real type and not something
> > arbitrary?
> You mean the names, right?
> Something like:
> int tb_switch_tmu_config_enable(struct device *parent, void *rate)
> If so, yes, I will

I mean use a real type, not void *.

> > 
> > Can it be const too?
> IIUC, it shall be a function pointer with specified signature otherwise it will fail
> at compilation

Okay then I suggest to make a reasonable "API" function that handles
all this internally that does not take arbitrary pointers. Remember to
document it in kernel-doc too.
Mika Westerberg May 16, 2022, 1:19 p.m. UTC | #2
Hi Gil,

On Mon, May 16, 2022 at 04:21:41PM +0300, Gil Fine wrote:
> > So instead I suggest to put the device_for_each_child() in tmu.c and
> > then the tb_switch_tmu_config_enable() static right above it. Please
> > also name the resulting API function consistently.
> 
> OK, got you and fixed that.
> Please let me know when you think that I can send out the v4 series.

You can send it whenever you want but I think it can go to v5.20 and not
v5.19 since I was planning to send out my pull request for Greg
tomorrow. I can pick it up after v5.19-rc1 is released.
Gil Fine May 16, 2022, 1:21 p.m. UTC | #3
Hi Mika,

On Mon, May 16, 2022 at 12:34:06PM +0300, Mika Westerberg wrote:
> On Mon, May 16, 2022 at 11:59:03AM +0300, Gil Fine wrote:
> > Hi Mika,
> > 
> > On Mon, May 16, 2022 at 11:34:15AM +0300, Mika Westerberg wrote:
> > > Hi Gil,
> > > 
> > > On Sun, May 15, 2022 at 11:27:46PM +0300, Gil Fine wrote:
> > > > > > +int tb_switch_tmu_config_enable(struct device *dev, void *data)
> > > > > 
> > > > > Also can we please make it take some real type and not something
> > > > > arbitrary?
> > > > You mean the names, right?
> > > > Something like:
> > > > int tb_switch_tmu_config_enable(struct device *parent, void *rate)
> > > > If so, yes, I will
> > > 
> > > I mean use a real type, not void *.
> > > 
> > > > > 
> > > > > Can it be const too?
> > > > IIUC, it shall be a function pointer with specified signature otherwise it will fail
> > > > at compilation
> > > 
> > > Okay then I suggest to make a reasonable "API" function that handles
> > > all this internally that does not take arbitrary pointers. Remember to
> > > document it in kernel-doc too.
> > 
> > This is a function pointer that shall be passed to device_for_each_child()
> > And it has to be defined as:
> > 
> > int (*fn)(struct device *dev, void *data)
> > 
> > Similar as here e.g.:
> > 
> > static int remove_retimer(struct device *dev, void *data)
> > {
> > »·······struct tb_retimer *rt = tb_to_retimer(dev);
> > »·······struct tb_port *port = data;
> > 
> > »·······if (rt && rt->port == port)
> > »·······»·······tb_retimer_remove(rt);
> > »·······return 0;
> > }
> > 
> > void tb_retimer_remove_all(struct tb_port *port)
> > {
> > »·······struct usb4_port *usb4;
> > 
> > »·······usb4 = port->usb4;
> > »·······if (usb4)
> > »·······»·······device_for_each_child_reverse(&usb4->dev, port,
> > »·······»·······»·······»·······»·······      remove_retimer);
> > }
> > 
> > So not sure I get you...
> 
> The difference is that above it is static function not exposed outside
> of that file and used directly below its implementation.
> 
> In your case you make it non-static "API" function exported from tmu.c
> and called from tb.c.
> 
> So instead I suggest to put the device_for_each_child() in tmu.c and
> then the tb_switch_tmu_config_enable() static right above it. Please
> also name the resulting API function consistently.

OK, got you and fixed that.
Please let me know when you think that I can send out the v4 series.
Greg KH May 16, 2022, 1:43 p.m. UTC | #4
On Mon, May 16, 2022 at 04:45:48PM +0300, Gil Fine wrote:
> This e-mail and any attachments may contain confidential material for
> the sole use of the intended recipient(s). Any review or distribution
> by others is strictly prohibited. If you are not the intended
> recipient, please contact the sender and delete all copies.
> 

Now deleted.  This footer is not compatible with kernel development,
sorry.
Gil Fine May 16, 2022, 1:45 p.m. UTC | #5
On Mon, May 16, 2022 at 04:19:46PM +0300, Mika Westerberg wrote:
> Hi Gil,
> 
> On Mon, May 16, 2022 at 04:21:41PM +0300, Gil Fine wrote:
> > > So instead I suggest to put the device_for_each_child() in tmu.c and
> > > then the tb_switch_tmu_config_enable() static right above it. Please
> > > also name the resulting API function consistently.
> > 
> > OK, got you and fixed that.
> > Please let me know when you think that I can send out the v4 series.
> 
> You can send it whenever you want but I think it can go to v5.20 and not
> v5.19 since I was planning to send out my pull request for Greg
> tomorrow. I can pick it up after v5.19-rc1 is released.

Ohh I see, I was hoping to meet v5.19
Can't you send it also as part of your your pull request tomorrow?
Or it is not mature enough yet...?
Mika Westerberg May 16, 2022, 2:54 p.m. UTC | #6
On Mon, May 16, 2022 at 04:45:48PM +0300, Gil Fine wrote:
> On Mon, May 16, 2022 at 04:19:46PM +0300, Mika Westerberg wrote:
> > Hi Gil,
> > 
> > On Mon, May 16, 2022 at 04:21:41PM +0300, Gil Fine wrote:
> > > > So instead I suggest to put the device_for_each_child() in tmu.c and
> > > > then the tb_switch_tmu_config_enable() static right above it. Please
> > > > also name the resulting API function consistently.
> > > 
> > > OK, got you and fixed that.
> > > Please let me know when you think that I can send out the v4 series.
> > 
> > You can send it whenever you want but I think it can go to v5.20 and not
> > v5.19 since I was planning to send out my pull request for Greg
> > tomorrow. I can pick it up after v5.19-rc1 is released.
> 
> Ohh I see, I was hoping to meet v5.19
> Can't you send it also as part of your your pull request tomorrow?
> Or it is not mature enough yet...?

Well typically it is expected that patches have been sitting in
linux-next for a while before going to the upstream maintainer (Greg in
this case). This is to ensure they get at least some attention from the
various build robots and also people running linux-next on their
hardware.
diff mbox series

Patch

diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c
index f512197e719b..d0f85a8c56de 100644
--- a/drivers/thunderbolt/tb.c
+++ b/drivers/thunderbolt/tb.c
@@ -50,6 +50,8 @@  struct tb_hotplug_event {
 };
 
 static void tb_handle_hotplug(struct work_struct *work);
+static void tb_enable_tmu_1st_child(struct tb *tb,
+				    enum tb_switch_tmu_rate rate);
 
 static void tb_queue_hotplug(struct tb *tb, u64 route, u8 port, bool unplug)
 {
@@ -118,6 +120,13 @@  static void tb_switch_discover_tunnels(struct tb_switch *sw,
 		switch (port->config.type) {
 		case TB_TYPE_DP_HDMI_IN:
 			tunnel = tb_tunnel_discover_dp(tb, port, alloc_hopids);
+			/*
+			 * In case of DP tunnel exists, change TMU mode to
+			 * HiFi for CL0s to work.
+			 */
+			if (tunnel)
+				tb_enable_tmu_1st_child(tb,
+						TB_SWITCH_TMU_RATE_HIFI);
 			break;
 
 		case TB_TYPE_PCIE_DOWN:
@@ -235,6 +244,19 @@  static int tb_enable_tmu(struct tb_switch *sw)
 	return tb_switch_tmu_enable(sw);
 }
 
+/*
+ * Once a DP tunnel exists in the domain, we set the TMU mode so that
+ * it meets the accuracy requirements and also enables CLx entry (CL0s).
+ * We set the TMU mode of the first depth router(s) for CL0s to work.
+ */
+static void tb_enable_tmu_1st_child(struct tb *tb, enum tb_switch_tmu_rate rate)
+{
+	struct tb_sw_tmu_config tmu = { .rate = rate };
+
+	device_for_each_child(&tb->root_switch->dev, &tmu,
+			      tb_switch_tmu_config_enable);
+}
+
 /**
  * tb_find_unused_port() - return the first inactive port on @sw
  * @sw: Switch to find the port on
@@ -985,6 +1007,12 @@  static void tb_tunnel_dp(struct tb *tb)
 
 	list_add_tail(&tunnel->list, &tcm->tunnel_list);
 	tb_reclaim_usb3_bandwidth(tb, in, out);
+	/*
+	 * In case of DP tunnel exists, change TMU mode to
+	 * HiFi for CL0s to work.
+	 */
+	tb_enable_tmu_1st_child(tb, TB_SWITCH_TMU_RATE_HIFI);
+
 	return;
 
 err_free:
diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h
index a16fffba9dd2..3dbd9d919d5f 100644
--- a/drivers/thunderbolt/tb.h
+++ b/drivers/thunderbolt/tb.h
@@ -110,6 +110,10 @@  struct tb_switch_tmu {
 	enum tb_switch_tmu_rate rate_request;
 };
 
+struct tb_sw_tmu_config {
+	enum tb_switch_tmu_rate rate;
+};
+
 enum tb_clx {
 	TB_CLX_DISABLE,
 	/* CL0s and CL1 are enabled and supported together */
@@ -934,6 +938,7 @@  int tb_switch_tmu_enable(struct tb_switch *sw);
 void tb_switch_tmu_configure(struct tb_switch *sw,
 			     enum tb_switch_tmu_rate rate,
 			     bool unidirectional);
+int tb_switch_tmu_config_enable(struct device *dev, void *data);
 /**
  * tb_switch_tmu_is_enabled() - Checks if the specified TMU mode is enabled
  * @sw: Router whose TMU mode to check
diff --git a/drivers/thunderbolt/tmu.c b/drivers/thunderbolt/tmu.c
index e822ab90338b..b8ff9f64a71e 100644
--- a/drivers/thunderbolt/tmu.c
+++ b/drivers/thunderbolt/tmu.c
@@ -727,6 +727,20 @@  int tb_switch_tmu_enable(struct tb_switch *sw)
 	return tb_switch_tmu_set_time_disruption(sw, false);
 }
 
+int tb_switch_tmu_config_enable(struct device *dev, void *data)
+{
+	if (tb_is_switch(dev)) {
+		struct tb_switch *sw = tb_to_switch(dev);
+		struct tb_sw_tmu_config *tmu = data;
+
+		tb_switch_tmu_configure(sw, tmu->rate, tb_switch_is_clx_enabled(sw, TB_CL1));
+		if (tb_switch_tmu_enable(sw))
+			tb_sw_dbg(sw, "Fail switching TMU to HiFi for 1st depth router\n");
+	}
+
+	return 0;
+}
+
 /**
  * tb_switch_tmu_configure() - Configure the TMU rate and directionality
  * @sw: Router whose mode to change