Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

thunderbolt: Avoid notify PM core about runtime PM resume

Currently we notify PM core about occurred wakes after any resume. This
is not actually needed after resume from runtime suspend. Hence, notify
PM core about occurred wakes only after resume from system sleep. Also,
if the wake occurred in USB4 router upstream port, we don't notify the
PM core about it since it is not actually needed and can cause
unexpected autowake (e.g. if /sys/power/wakeup_count is used).

While there add the missing kernel-doc for tb_switch_resume().

Signed-off-by: Gil Fine <gil.fine@linux.intel.com>
Cc: stable@vger.kernel.org
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>

authored by

Gil Fine and committed by
Mika Westerberg
dcd12aca c38fa07d

+36 -11
+25 -2
drivers/thunderbolt/switch.c
··· 3448 3448 return tb_lc_set_wake(sw, flags); 3449 3449 } 3450 3450 3451 - 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) 3452 3471 { 3453 3472 struct tb_port *port; 3454 3473 int err; ··· 3516 3497 if (err) 3517 3498 return err; 3518 3499 3500 + if (!runtime) 3501 + tb_switch_check_wakes(sw); 3502 + 3519 3503 /* Disable wakes */ 3520 3504 tb_switch_set_wake(sw, 0); 3521 3505 ··· 3548 3526 */ 3549 3527 if (tb_port_unlock(port)) 3550 3528 tb_port_warn(port, "failed to unlock port\n"); 3551 - if (port->remote && tb_switch_resume(port->remote->sw)) { 3529 + if (port->remote && 3530 + tb_switch_resume(port->remote->sw, runtime)) { 3552 3531 tb_port_warn(port, 3553 3532 "lost during suspend, disconnecting\n"); 3554 3533 tb_sw_set_unplugged(port->remote->sw);
+2 -2
drivers/thunderbolt/tb.c
··· 2942 2942 if (!tb_switch_is_usb4(tb->root_switch)) 2943 2943 tb_switch_reset(tb->root_switch); 2944 2944 2945 - tb_switch_resume(tb->root_switch); 2945 + tb_switch_resume(tb->root_switch, false); 2946 2946 tb_free_invalid_tunnels(tb); 2947 2947 tb_free_unplugged_children(tb->root_switch); 2948 2948 tb_restore_children(tb->root_switch); ··· 3068 3068 struct tb_tunnel *tunnel, *n; 3069 3069 3070 3070 mutex_lock(&tb->lock); 3071 - tb_switch_resume(tb->root_switch); 3071 + tb_switch_resume(tb->root_switch, true); 3072 3072 tb_free_invalid_tunnels(tb); 3073 3073 tb_restore_children(tb->root_switch); 3074 3074 list_for_each_entry_safe(tunnel, n, &tcm->tunnel_list, list)
+2 -1
drivers/thunderbolt/tb.h
··· 827 827 int tb_switch_add(struct tb_switch *sw); 828 828 void tb_switch_remove(struct tb_switch *sw); 829 829 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); 831 831 int tb_switch_reset(struct tb_switch *sw); 832 832 int tb_switch_wait_for_bit(struct tb_switch *sw, u32 offset, u32 bit, 833 833 u32 value, int timeout_msec); ··· 1288 1288 return usb4_switch_version(sw) > 0; 1289 1289 } 1290 1290 1291 + void usb4_switch_check_wakes(struct tb_switch *sw); 1291 1292 int usb4_switch_setup(struct tb_switch *sw); 1292 1293 int usb4_switch_configuration_valid(struct tb_switch *sw); 1293 1294 int usb4_switch_read_uid(struct tb_switch *sw, u64 *uid);
+7 -6
drivers/thunderbolt/usb4.c
··· 155 155 tx_dwords, rx_data, rx_dwords); 156 156 } 157 157 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) 159 165 { 160 166 bool wakeup_usb4 = false; 161 167 struct usb4_port *usb4; 162 168 struct tb_port *port; 163 169 bool wakeup = false; 164 170 u32 val; 165 - 166 - if (!device_may_wakeup(&sw->dev)) 167 - return; 168 171 169 172 if (tb_route(sw)) { 170 173 if (tb_sw_read(sw, &val, TB_CFG_SWITCH, ROUTER_CS_6, 1)) ··· 246 243 bool tbt3, xhci; 247 244 u32 val = 0; 248 245 int ret; 249 - 250 - usb4_switch_check_wakes(sw); 251 246 252 247 if (!tb_route(sw)) 253 248 return 0;