Skip to content

Commit c281d18

Browse files
committed
Merge tag 'thunderbolt-for-v6.9-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt into usb-linus
Mika writes: thunderbolt: Fixes for v6.9-rc5 This includes following USB4/Thunderbolt fixes for v6.9-rc5: - Avoid creating DisplayPort tunnels for the adapters on the same router - Correct wake configurations after device router unplug - Fix immediate wake when "wakeup_count" is used to enter system sleep. All these have been in linux-next with no reported issues. * tag 'thunderbolt-for-v6.9-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt: thunderbolt: Avoid notify PM core about runtime PM resume thunderbolt: Fix wake configurations after device unplug thunderbolt: Do not create DisplayPort tunnels on adapters of the same router
2 parents 34b990e + dcd12ac commit c281d18

File tree

4 files changed

+56
-18
lines changed

4 files changed

+56
-18
lines changed

drivers/thunderbolt/switch.c

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3180,22 +3180,29 @@ void tb_switch_unconfigure_link(struct tb_switch *sw)
31803180
{
31813181
struct tb_port *up, *down;
31823182

3183-
if (sw->is_unplugged)
3184-
return;
31853183
if (!tb_route(sw) || tb_switch_is_icm(sw))
31863184
return;
31873185

3186+
/*
3187+
* Unconfigure downstream port so that wake-on-connect can be
3188+
* configured after router unplug. No need to unconfigure upstream port
3189+
* since its router is unplugged.
3190+
*/
31883191
up = tb_upstream_port(sw);
3189-
if (tb_switch_is_usb4(up->sw))
3190-
usb4_port_unconfigure(up);
3191-
else
3192-
tb_lc_unconfigure_port(up);
3193-
31943192
down = up->remote;
31953193
if (tb_switch_is_usb4(down->sw))
31963194
usb4_port_unconfigure(down);
31973195
else
31983196
tb_lc_unconfigure_port(down);
3197+
3198+
if (sw->is_unplugged)
3199+
return;
3200+
3201+
up = tb_upstream_port(sw);
3202+
if (tb_switch_is_usb4(up->sw))
3203+
usb4_port_unconfigure(up);
3204+
else
3205+
tb_lc_unconfigure_port(up);
31993206
}
32003207

32013208
static void tb_switch_credits_init(struct tb_switch *sw)
@@ -3441,7 +3448,26 @@ static int tb_switch_set_wake(struct tb_switch *sw, unsigned int flags)
34413448
return tb_lc_set_wake(sw, flags);
34423449
}
34433450

3444-
int tb_switch_resume(struct tb_switch *sw)
3451+
static void tb_switch_check_wakes(struct tb_switch *sw)
3452+
{
3453+
if (device_may_wakeup(&sw->dev)) {
3454+
if (tb_switch_is_usb4(sw))
3455+
usb4_switch_check_wakes(sw);
3456+
}
3457+
}
3458+
3459+
/**
3460+
* tb_switch_resume() - Resume a switch after sleep
3461+
* @sw: Switch to resume
3462+
* @runtime: Is this resume from runtime suspend or system sleep
3463+
*
3464+
* Resumes and re-enumerates router (and all its children), if still plugged
3465+
* after suspend. Don't enumerate device router whose UID was changed during
3466+
* suspend. If this is resume from system sleep, notifies PM core about the
3467+
* wakes occurred during suspend. Disables all wakes, except USB4 wake of
3468+
* upstream port for USB4 routers that shall be always enabled.
3469+
*/
3470+
int tb_switch_resume(struct tb_switch *sw, bool runtime)
34453471
{
34463472
struct tb_port *port;
34473473
int err;
@@ -3490,6 +3516,9 @@ int tb_switch_resume(struct tb_switch *sw)
34903516
if (err)
34913517
return err;
34923518

3519+
if (!runtime)
3520+
tb_switch_check_wakes(sw);
3521+
34933522
/* Disable wakes */
34943523
tb_switch_set_wake(sw, 0);
34953524

@@ -3519,7 +3548,8 @@ int tb_switch_resume(struct tb_switch *sw)
35193548
*/
35203549
if (tb_port_unlock(port))
35213550
tb_port_warn(port, "failed to unlock port\n");
3522-
if (port->remote && tb_switch_resume(port->remote->sw)) {
3551+
if (port->remote &&
3552+
tb_switch_resume(port->remote->sw, runtime)) {
35233553
tb_port_warn(port,
35243554
"lost during suspend, disconnecting\n");
35253555
tb_sw_set_unplugged(port->remote->sw);

drivers/thunderbolt/tb.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1801,6 +1801,12 @@ static struct tb_port *tb_find_dp_out(struct tb *tb, struct tb_port *in)
18011801
continue;
18021802
}
18031803

1804+
/* Needs to be on different routers */
1805+
if (in->sw == port->sw) {
1806+
tb_port_dbg(port, "skipping DP OUT on same router\n");
1807+
continue;
1808+
}
1809+
18041810
tb_port_dbg(port, "DP OUT available\n");
18051811

18061812
/*
@@ -2936,7 +2942,7 @@ static int tb_resume_noirq(struct tb *tb)
29362942
if (!tb_switch_is_usb4(tb->root_switch))
29372943
tb_switch_reset(tb->root_switch);
29382944

2939-
tb_switch_resume(tb->root_switch);
2945+
tb_switch_resume(tb->root_switch, false);
29402946
tb_free_invalid_tunnels(tb);
29412947
tb_free_unplugged_children(tb->root_switch);
29422948
tb_restore_children(tb->root_switch);
@@ -3062,7 +3068,7 @@ static int tb_runtime_resume(struct tb *tb)
30623068
struct tb_tunnel *tunnel, *n;
30633069

30643070
mutex_lock(&tb->lock);
3065-
tb_switch_resume(tb->root_switch);
3071+
tb_switch_resume(tb->root_switch, true);
30663072
tb_free_invalid_tunnels(tb);
30673073
tb_restore_children(tb->root_switch);
30683074
list_for_each_entry_safe(tunnel, n, &tcm->tunnel_list, list)

drivers/thunderbolt/tb.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -827,7 +827,7 @@ int tb_switch_configuration_valid(struct tb_switch *sw);
827827
int tb_switch_add(struct tb_switch *sw);
828828
void tb_switch_remove(struct tb_switch *sw);
829829
void tb_switch_suspend(struct tb_switch *sw, bool runtime);
830-
int tb_switch_resume(struct tb_switch *sw);
830+
int tb_switch_resume(struct tb_switch *sw, bool runtime);
831831
int tb_switch_reset(struct tb_switch *sw);
832832
int tb_switch_wait_for_bit(struct tb_switch *sw, u32 offset, u32 bit,
833833
u32 value, int timeout_msec);
@@ -1288,6 +1288,7 @@ static inline bool tb_switch_is_usb4(const struct tb_switch *sw)
12881288
return usb4_switch_version(sw) > 0;
12891289
}
12901290

1291+
void usb4_switch_check_wakes(struct tb_switch *sw);
12911292
int usb4_switch_setup(struct tb_switch *sw);
12921293
int usb4_switch_configuration_valid(struct tb_switch *sw);
12931294
int usb4_switch_read_uid(struct tb_switch *sw, u64 *uid);

drivers/thunderbolt/usb4.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -155,17 +155,20 @@ static inline int usb4_switch_op_data(struct tb_switch *sw, u16 opcode,
155155
tx_dwords, rx_data, rx_dwords);
156156
}
157157

158-
static void usb4_switch_check_wakes(struct tb_switch *sw)
158+
/**
159+
* usb4_switch_check_wakes() - Check for wakes and notify PM core about them
160+
* @sw: Router whose wakes to check
161+
*
162+
* Checks wakes occurred during suspend and notify the PM core about them.
163+
*/
164+
void usb4_switch_check_wakes(struct tb_switch *sw)
159165
{
160166
bool wakeup_usb4 = false;
161167
struct usb4_port *usb4;
162168
struct tb_port *port;
163169
bool wakeup = false;
164170
u32 val;
165171

166-
if (!device_may_wakeup(&sw->dev))
167-
return;
168-
169172
if (tb_route(sw)) {
170173
if (tb_sw_read(sw, &val, TB_CFG_SWITCH, ROUTER_CS_6, 1))
171174
return;
@@ -244,8 +247,6 @@ int usb4_switch_setup(struct tb_switch *sw)
244247
u32 val = 0;
245248
int ret;
246249

247-
usb4_switch_check_wakes(sw);
248-
249250
if (!tb_route(sw))
250251
return 0;
251252

0 commit comments

Comments
 (0)