+struct ucsi_work {
+ struct delayed_work work;
+ unsigned long delay;
+ unsigned int count;
+ struct ucsi_connector *con;
+ int (*cb)(struct ucsi_connector *);
+};
+
+static void ucsi_poll_worker(struct work_struct *work)
+{
+ struct ucsi_work *uwork = container_of(work, struct ucsi_work, work.work);
+ struct ucsi_connector *con = uwork->con;
+ int ret;
+
+ mutex_lock(&con->lock);
+
+ if (!con->partner) {
+ mutex_unlock(&con->lock);
+ kfree(uwork);
+ return;
+ }
+
+ ret = uwork->cb(con);
+
+ if (uwork->count-- && (ret == -EBUSY || ret == -ETIMEDOUT))
+ queue_delayed_work(con->wq, &uwork->work, uwork->delay);
+ else
+ kfree(uwork);
+
+ mutex_unlock(&con->lock);
+}
+
+static int ucsi_partner_task(struct ucsi_connector *con,
+ int (*cb)(struct ucsi_connector *),
+ int retries, unsigned long delay)
+{
+ struct ucsi_work *uwork;
+
+ if (!con->partner)
+ return 0;
+
+ uwork = kzalloc(sizeof(*uwork), GFP_KERNEL);
+ if (!uwork)
+ return -ENOMEM;
+
+ INIT_DELAYED_WORK(&uwork->work, ucsi_poll_worker);
+ uwork->count = retries;
+ uwork->delay = delay;
+ uwork->con = con;
+ uwork->cb = cb;
+
+ queue_delayed_work(con->wq, &uwork->work, delay);
+
+ return 0;
+}
+
+/* -------------------------------------------------------------------------- */
+