From 0c924e6706a9a1fbf1d363effb6e3613ca0649f6 Mon Sep 17 00:00:00 2001 From: Jack Pham Date: Tue, 12 Jul 2016 17:39:12 -0700 Subject: usb: pd: Fix ERROR_RECOVERY handling When entering ERROR_RECOVERY, the forced disconnect should be processed first by queuing the work function to handle it in the usual way. The required minimum delay should then be done after this, before restoring the port to dual-role, and thereby re-establishing the source/sink connection. Change-Id: I672cdb59277af103045236232e54dc24f9f7fb01 Signed-off-by: Jack Pham --- drivers/usb/pd/policy_engine.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c index 0cc57e41ebb1..b011efe189e7 100644 --- a/drivers/usb/pd/policy_engine.c +++ b/drivers/usb/pd/policy_engine.c @@ -575,8 +575,8 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) case PE_ERROR_RECOVERY: /* perform hard disconnect/reconnect */ pd->in_pr_swap = false; set_power_role(pd, PR_NONE); - hrtimer_start(&pd->timer, ms_to_ktime(ERROR_RECOVERY_TIME), - HRTIMER_MODE_REL); + pd->typec_mode = POWER_SUPPLY_TYPEC_NONE; + queue_work(pd->wq, &pd->sm_work); break; /* Source states */ @@ -1271,12 +1271,18 @@ static void usbpd_sm(struct work_struct *w) reset_vdm_state(pd); + if (pd->current_state == PE_ERROR_RECOVERY) + /* forced disconnect, wait before resetting to DRP */ + usleep_range(ERROR_RECOVERY_TIME * USEC_PER_MSEC, + (ERROR_RECOVERY_TIME + 5) * USEC_PER_MSEC); + /* Set CC back to DRP toggle */ val.intval = POWER_SUPPLY_TYPEC_PR_DUAL; power_supply_set_property(pd->usb_psy, POWER_SUPPLY_PROP_TYPEC_POWER_ROLE, &val); pd->current_state = PE_UNKNOWN; + return; } -- cgit v1.2.3