Skip to content

Commit

Permalink
thunderbolt: Avoid notify PM core about runtime PM resume
Browse files Browse the repository at this point in the history
commit dcd12ac upstream.

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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Gil Fine authored and gregkh committed Apr 27, 2024
1 parent f01d661 commit e724f27
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 11 deletions.
27 changes: 25 additions & 2 deletions drivers/thunderbolt/switch.c
Expand Up @@ -3441,7 +3441,26 @@ static int tb_switch_set_wake(struct tb_switch *sw, unsigned int flags)
return tb_lc_set_wake(sw, flags);
}

int tb_switch_resume(struct tb_switch *sw)
static void tb_switch_check_wakes(struct tb_switch *sw)
{
if (device_may_wakeup(&sw->dev)) {
if (tb_switch_is_usb4(sw))
usb4_switch_check_wakes(sw);
}
}

/**
* tb_switch_resume() - Resume a switch after sleep
* @sw: Switch to resume
* @runtime: Is this resume from runtime suspend or system sleep
*
* Resumes and re-enumerates router (and all its children), if still plugged
* after suspend. Don't enumerate device router whose UID was changed during
* suspend. If this is resume from system sleep, notifies PM core about the
* wakes occurred during suspend. Disables all wakes, except USB4 wake of
* upstream port for USB4 routers that shall be always enabled.
*/
int tb_switch_resume(struct tb_switch *sw, bool runtime)
{
struct tb_port *port;
int err;
Expand Down Expand Up @@ -3490,6 +3509,9 @@ int tb_switch_resume(struct tb_switch *sw)
if (err)
return err;

if (!runtime)
tb_switch_check_wakes(sw);

/* Disable wakes */
tb_switch_set_wake(sw, 0);

Expand Down Expand Up @@ -3519,7 +3541,8 @@ int tb_switch_resume(struct tb_switch *sw)
*/
if (tb_port_unlock(port))
tb_port_warn(port, "failed to unlock port\n");
if (port->remote && tb_switch_resume(port->remote->sw)) {
if (port->remote &&
tb_switch_resume(port->remote->sw, runtime)) {
tb_port_warn(port,
"lost during suspend, disconnecting\n");
tb_sw_set_unplugged(port->remote->sw);
Expand Down
4 changes: 2 additions & 2 deletions drivers/thunderbolt/tb.c
Expand Up @@ -2760,7 +2760,7 @@ static int tb_resume_noirq(struct tb *tb)
/* remove any pci devices the firmware might have setup */
tb_switch_reset(tb->root_switch);

tb_switch_resume(tb->root_switch);
tb_switch_resume(tb->root_switch, false);
tb_free_invalid_tunnels(tb);
tb_free_unplugged_children(tb->root_switch);
tb_restore_children(tb->root_switch);
Expand Down Expand Up @@ -2886,7 +2886,7 @@ static int tb_runtime_resume(struct tb *tb)
struct tb_tunnel *tunnel, *n;

mutex_lock(&tb->lock);
tb_switch_resume(tb->root_switch);
tb_switch_resume(tb->root_switch, true);
tb_free_invalid_tunnels(tb);
tb_restore_children(tb->root_switch);
list_for_each_entry_safe(tunnel, n, &tcm->tunnel_list, list)
Expand Down
3 changes: 2 additions & 1 deletion drivers/thunderbolt/tb.h
Expand Up @@ -817,7 +817,7 @@ int tb_switch_configuration_valid(struct tb_switch *sw);
int tb_switch_add(struct tb_switch *sw);
void tb_switch_remove(struct tb_switch *sw);
void tb_switch_suspend(struct tb_switch *sw, bool runtime);
int tb_switch_resume(struct tb_switch *sw);
int tb_switch_resume(struct tb_switch *sw, bool runtime);
int tb_switch_reset(struct tb_switch *sw);
int tb_switch_wait_for_bit(struct tb_switch *sw, u32 offset, u32 bit,
u32 value, int timeout_msec);
Expand Down Expand Up @@ -1278,6 +1278,7 @@ static inline bool tb_switch_is_usb4(const struct tb_switch *sw)
return usb4_switch_version(sw) > 0;
}

void usb4_switch_check_wakes(struct tb_switch *sw);
int usb4_switch_setup(struct tb_switch *sw);
int usb4_switch_configuration_valid(struct tb_switch *sw);
int usb4_switch_read_uid(struct tb_switch *sw, u64 *uid);
Expand Down
13 changes: 7 additions & 6 deletions drivers/thunderbolt/usb4.c
Expand Up @@ -155,17 +155,20 @@ static inline int usb4_switch_op_data(struct tb_switch *sw, u16 opcode,
tx_dwords, rx_data, rx_dwords);
}

static void usb4_switch_check_wakes(struct tb_switch *sw)
/**
* usb4_switch_check_wakes() - Check for wakes and notify PM core about them
* @sw: Router whose wakes to check
*
* Checks wakes occurred during suspend and notify the PM core about them.
*/
void usb4_switch_check_wakes(struct tb_switch *sw)
{
bool wakeup_usb4 = false;
struct usb4_port *usb4;
struct tb_port *port;
bool wakeup = false;
u32 val;

if (!device_may_wakeup(&sw->dev))
return;

if (tb_route(sw)) {
if (tb_sw_read(sw, &val, TB_CFG_SWITCH, ROUTER_CS_6, 1))
return;
Expand Down Expand Up @@ -244,8 +247,6 @@ int usb4_switch_setup(struct tb_switch *sw)
u32 val = 0;
int ret;

usb4_switch_check_wakes(sw);

if (!tb_route(sw))
return 0;

Expand Down

0 comments on commit e724f27

Please sign in to comment.