[PATCH] usb: typec: ucsi: Test patch for confirming events
From: Heikki Krogerus
Date: Wed Jun 09 2021 - 08:48:23 EST
NOT-Signed-off-by: Heikki Krogerus <heikki.krogerus@xxxxxxxxxxxxxxx>
---
drivers/usb/typec/ucsi/ucsi.c | 80 ++++++++++++-----------------------
1 file changed, 27 insertions(+), 53 deletions(-)
diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
index bd39fe2cb1d0b..53718e655edbf 100644
--- a/drivers/usb/typec/ucsi/ucsi.c
+++ b/drivers/usb/typec/ucsi/ucsi.c
@@ -748,16 +748,34 @@ static void ucsi_connector_work(struct work_struct *work)
{
struct ucsi_con_event *event = container_of(work, struct ucsi_con_event, work);
struct ucsi_connector *con = event->con;
+ struct ucsi_connector_status status;
struct ucsi *ucsi = con->ucsi;
enum typec_role role;
enum usb_role u_role = USB_ROLE_NONE;
+ u64 command;
int ret;
+ kfree(event);
+
+ command = UCSI_GET_CONNECTOR_STATUS | UCSI_CONNECTOR_NUMBER(con->num);
+ ret = ucsi_send_command(ucsi, command, &status, sizeof(status));
+ if (ret < 0)
+ dev_err(ucsi->dev, "GET_CONNECTOR_STATUS failed (%d)\n", ret);
+
+ if (!status.change) {
+ dev_dbg(ucsi->dev, "con%d: spurious event\n", con->num);
+ /* XXX: Force connection check. */
+ status.change = UCSI_CONSTAT_CONNECT_CHANGE;
+ }
+
+ ret = ucsi_acknowledge_connector_change(ucsi);
+ if (ret)
+ dev_err(ucsi->dev, "%s: ACK failed (%d)", __func__, ret);
+
mutex_lock(&con->lock);
- trace_ucsi_connector_change(con->num, &event->status);
- con->status = event->status;
- kfree(event);
+ trace_ucsi_connector_change(con->num, &status);
+ con->status = status;
role = !!(con->status.flags & UCSI_CONSTAT_PWR_DIR);
@@ -816,53 +834,6 @@ static void ucsi_connector_work(struct work_struct *work)
mutex_unlock(&con->lock);
}
-/*
- * We can not read the connector status in ucsi_connector_change() function
- * below because there may be already a command pending. This work is scheduled
- * separately only because of that.
- *
- * This function must finish fast so we do not loose the next events. Every
- * event will have a separate job queued for it in the connector specific
- * workqueue. That way the next event can be generated safely before the
- * previous ones are fully processed.
- */
-static void ucsi_handle_connector_change(struct work_struct *work)
-{
- struct ucsi_connector *con = container_of(work, struct ucsi_connector, work);
- struct ucsi_connector_status status;
- struct ucsi_con_event *event;
- u64 command;
- int ret;
-
- command = UCSI_GET_CONNECTOR_STATUS | UCSI_CONNECTOR_NUMBER(con->num);
- ret = ucsi_send_command(con->ucsi, command, &status, sizeof(status));
- if (ret < 0) {
- dev_err(con->ucsi->dev, "GET_CONNECTOR_STATUS failed (%d)\n", ret);
- goto out_ack;
- }
-
- if (!status.change) {
- dev_dbg(con->ucsi->dev, "con%d: spurious event\n", con->num);
- goto out_ack;
- }
-
- event = kzalloc(sizeof(*event), GFP_KERNEL);
- if (!event)
- goto out_ack;
-
- INIT_WORK(&event->work, ucsi_connector_work);
- event->status = status;
- event->con = con;
- queue_work(con->wq, &event->work);
-
-out_ack:
- clear_bit(EVENT_PENDING, &con->ucsi->flags);
-
- ret = ucsi_acknowledge_connector_change(con->ucsi);
- if (ret)
- dev_err(con->ucsi->dev, "%s: ACK failed (%d)", __func__, ret);
-}
-
/**
* ucsi_connector_change - Process Connector Change Event
* @ucsi: UCSI Interface
@@ -871,16 +842,20 @@ static void ucsi_handle_connector_change(struct work_struct *work)
void ucsi_connector_change(struct ucsi *ucsi, u8 num)
{
struct ucsi_connector *con = &ucsi->connector[num - 1];
+ struct ucsi_con_event *event;
if (!(ucsi->ntfy & UCSI_ENABLE_NTFY_CONNECTOR_CHANGE)) {
dev_dbg(ucsi->dev, "Bogus connector change event\n");
return;
}
- if (test_and_set_bit(EVENT_PENDING, &ucsi->flags))
+ event = kzalloc(sizeof(*event), GFP_KERNEL);
+ if (!event)
return;
- schedule_work(&con->work);
+ INIT_WORK(&event->work, ucsi_connector_work);
+ event->con = con;
+ queue_work(con->wq, &event->work);
}
EXPORT_SYMBOL_GPL(ucsi_connector_change);
@@ -1078,7 +1053,6 @@ static int ucsi_register_port(struct ucsi *ucsi, int index)
if (!con->wq)
return -ENOMEM;
- INIT_WORK(&con->work, ucsi_handle_connector_change);
init_completion(&con->complete);
mutex_init(&con->lock);
con->num = index + 1;
--
2.30.2
--/TeB+Hja9PywstF5--