forked from Minki/linux
usb: typec: ucsi: Wait for the USB role switches
When role switch module probe late than ucsi module, fwnode_usb_role_switch_get() will return -EPROBE_DEFER, it is better to restart ucsi init work to find it again every 100ms, total wait time is 10 second. It also means change ucsi init work to delayed_work. Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> Signed-off-by: Linyu Yuan <quic_linyyuan@quicinc.com> Link: https://lore.kernel.org/r/1650881886-25530-3-git-send-email-quic_linyyuan@quicinc.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
87d0e2f41b
commit
3c16251153
@ -1053,6 +1053,14 @@ static int ucsi_register_port(struct ucsi *ucsi, int index)
|
||||
con->num = index + 1;
|
||||
con->ucsi = ucsi;
|
||||
|
||||
cap->fwnode = ucsi_find_fwnode(con);
|
||||
con->usb_role_sw = fwnode_usb_role_switch_get(cap->fwnode);
|
||||
if (IS_ERR(con->usb_role_sw)) {
|
||||
dev_err(ucsi->dev, "con%d: failed to get usb role switch\n",
|
||||
con->num);
|
||||
return PTR_ERR(con->usb_role_sw);
|
||||
}
|
||||
|
||||
/* Delay other interactions with the con until registration is complete */
|
||||
mutex_lock(&con->lock);
|
||||
|
||||
@ -1088,7 +1096,6 @@ static int ucsi_register_port(struct ucsi *ucsi, int index)
|
||||
if (con->cap.op_mode & UCSI_CONCAP_OPMODE_DEBUG_ACCESSORY)
|
||||
*accessory = TYPEC_ACCESSORY_DEBUG;
|
||||
|
||||
cap->fwnode = ucsi_find_fwnode(con);
|
||||
cap->driver_data = con;
|
||||
cap->ops = &ucsi_ops;
|
||||
|
||||
@ -1146,13 +1153,6 @@ static int ucsi_register_port(struct ucsi *ucsi, int index)
|
||||
ucsi_port_psy_changed(con);
|
||||
}
|
||||
|
||||
con->usb_role_sw = fwnode_usb_role_switch_get(cap->fwnode);
|
||||
if (IS_ERR(con->usb_role_sw)) {
|
||||
dev_err(ucsi->dev, "con%d: failed to get usb role switch\n",
|
||||
con->num);
|
||||
con->usb_role_sw = NULL;
|
||||
}
|
||||
|
||||
/* Only notify USB controller if partner supports USB data */
|
||||
if (!(UCSI_CONSTAT_PARTNER_FLAGS(con->status.flags) & UCSI_CONSTAT_PARTNER_FLAG_USB))
|
||||
u_role = USB_ROLE_NONE;
|
||||
@ -1285,12 +1285,20 @@ err:
|
||||
|
||||
static void ucsi_init_work(struct work_struct *work)
|
||||
{
|
||||
struct ucsi *ucsi = container_of(work, struct ucsi, work);
|
||||
struct ucsi *ucsi = container_of(work, struct ucsi, work.work);
|
||||
int ret;
|
||||
|
||||
ret = ucsi_init(ucsi);
|
||||
if (ret)
|
||||
dev_err(ucsi->dev, "PPM init failed (%d)\n", ret);
|
||||
|
||||
if (ret == -EPROBE_DEFER) {
|
||||
if (ucsi->work_count++ > UCSI_ROLE_SWITCH_WAIT_COUNT)
|
||||
return;
|
||||
|
||||
queue_delayed_work(system_long_wq, &ucsi->work,
|
||||
UCSI_ROLE_SWITCH_INTERVAL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1330,7 +1338,7 @@ struct ucsi *ucsi_create(struct device *dev, const struct ucsi_operations *ops)
|
||||
if (!ucsi)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
INIT_WORK(&ucsi->work, ucsi_init_work);
|
||||
INIT_DELAYED_WORK(&ucsi->work, ucsi_init_work);
|
||||
mutex_init(&ucsi->ppm_lock);
|
||||
ucsi->dev = dev;
|
||||
ucsi->ops = ops;
|
||||
@ -1365,7 +1373,7 @@ int ucsi_register(struct ucsi *ucsi)
|
||||
if (!ucsi->version)
|
||||
return -ENODEV;
|
||||
|
||||
queue_work(system_long_wq, &ucsi->work);
|
||||
queue_delayed_work(system_long_wq, &ucsi->work, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1382,7 +1390,7 @@ void ucsi_unregister(struct ucsi *ucsi)
|
||||
u64 cmd = UCSI_SET_NOTIFICATION_ENABLE;
|
||||
|
||||
/* Make sure that we are not in the middle of driver initialization */
|
||||
cancel_work_sync(&ucsi->work);
|
||||
cancel_delayed_work_sync(&ucsi->work);
|
||||
|
||||
/* Disable notifications */
|
||||
ucsi->ops->async_write(ucsi, UCSI_CONTROL, &cmd, sizeof(cmd));
|
||||
|
@ -287,7 +287,11 @@ struct ucsi {
|
||||
struct ucsi_capability cap;
|
||||
struct ucsi_connector *connector;
|
||||
|
||||
struct work_struct work;
|
||||
struct delayed_work work;
|
||||
int work_count;
|
||||
#define UCSI_ROLE_SWITCH_RETRY_PER_HZ 10
|
||||
#define UCSI_ROLE_SWITCH_INTERVAL (HZ / UCSI_ROLE_SWITCH_RETRY_PER_HZ)
|
||||
#define UCSI_ROLE_SWITCH_WAIT_COUNT (10 * UCSI_ROLE_SWITCH_RETRY_PER_HZ)
|
||||
|
||||
/* PPM Communication lock */
|
||||
struct mutex ppm_lock;
|
||||
|
Loading…
Reference in New Issue
Block a user