On 2/13/23 22:56, Xu Yang wrote:
The kernel will dump in the below cases: sysfs: cannot create duplicate filename '/devices/virtual/usb_power_delivery/pd1/source-capabilities' 1. After soft reset has completed, an Explicit Contract negotiation occurs. The sink device will receive source capabilitys again. This will cause a duplicate source-capabilities file be created. 2. Power swap twice on a device that is initailly sink role. This will unregister existing capabilities when above cases occurs. Fixes: 8203d26905ee ("usb: typec: tcpm: Register USB Power Delivery Capabilities") cc: <stable@xxxxxxxxxxxxxxx> Signed-off-by: Xu Yang <xu.yang_2@xxxxxxx>
Reviewed-by: Guenter Roeck <linux@xxxxxxxxxxxx>
--- v2: unregister existing capabilities on specific cases v3: add changelog and modify commit message --- drivers/usb/typec/tcpm/tcpm.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index a0d943d78580..7d8c53d96c3b 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -4570,6 +4570,8 @@ static void run_state_machine(struct tcpm_port *port) case SOFT_RESET: port->message_id = 0; port->rx_msgid = -1; + /* remove existing capabilities */ + usb_power_delivery_unregister_capabilities(port->partner_source_caps); tcpm_pd_send_control(port, PD_CTRL_ACCEPT); tcpm_ams_finish(port); if (port->pwr_role == TYPEC_SOURCE) { @@ -4589,6 +4591,8 @@ static void run_state_machine(struct tcpm_port *port) case SOFT_RESET_SEND: port->message_id = 0; port->rx_msgid = -1; + /* remove existing capabilities */ + usb_power_delivery_unregister_capabilities(port->partner_source_caps); if (tcpm_pd_send_control(port, PD_CTRL_SOFT_RESET)) tcpm_set_state_cond(port, hard_reset_state(port), 0); else @@ -4718,6 +4722,8 @@ static void run_state_machine(struct tcpm_port *port) tcpm_set_state(port, SNK_STARTUP, 0); break; case PR_SWAP_SNK_SRC_SINK_OFF: + /* will be source, remove existing capabilities */ + usb_power_delivery_unregister_capabilities(port->partner_source_caps); /* * Prevent vbus discharge circuit from turning on during PR_SWAP * as this is not a disconnect.