Loading drivers/usb/pd/policy_engine.c +58 −15 Original line number Diff line number Diff line Loading @@ -338,8 +338,10 @@ struct usbpd { enum power_role current_pr; bool in_pr_swap; bool pd_phy_opened; struct completion swap_complete; bool send_request; struct completion is_ready; struct mutex swap_lock; struct dual_role_phy_instance *dual_role; struct dual_role_phy_desc dr_desc; bool send_pr_swap; Loading Loading @@ -463,6 +465,9 @@ static inline void pd_reset_protocol(struct usbpd *pd) */ pd->rx_msgid = -1; pd->tx_msgid = 0; pd->send_request = false; pd->send_pr_swap = false; pd->send_dr_swap = false; } static int pd_send_msg(struct usbpd *pd, u8 hdr_type, const u32 *data, Loading Loading @@ -842,7 +847,7 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) } kobject_uevent(&pd->dev.kobj, KOBJ_CHANGE); complete(&pd->swap_complete); complete(&pd->is_ready); dual_role_instance_changed(pd->dual_role); break; Loading Loading @@ -977,7 +982,7 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) case PE_SNK_READY: pd->in_explicit_contract = true; kobject_uevent(&pd->dev.kobj, KOBJ_CHANGE); complete(&pd->swap_complete); complete(&pd->is_ready); dual_role_instance_changed(pd->dual_role); break; Loading Loading @@ -2075,6 +2080,9 @@ static void usbpd_sm(struct work_struct *w) vconn_swap(pd); } else if (IS_DATA(rx_msg, MSG_VDM)) { handle_vdm_rx(pd, rx_msg); } else if (pd->send_request) { pd->send_request = false; usbpd_set_state(pd, PE_SNK_SELECT_CAPABILITY); } else if (pd->send_pr_swap && is_sink_tx_ok(pd)) { pd->send_pr_swap = false; ret = pd_send_msg(pd, MSG_PR_SWAP, NULL, 0, SOP_MSG); Loading Loading @@ -2540,17 +2548,21 @@ static int usbpd_dr_set_property(struct dual_role_phy_instance *dual_role, return -EAGAIN; } reinit_completion(&pd->swap_complete); mutex_lock(&pd->swap_lock); reinit_completion(&pd->is_ready); pd->send_dr_swap = true; kick_sm(pd, 0); /* wait for operation to complete */ if (!wait_for_completion_timeout(&pd->swap_complete, if (!wait_for_completion_timeout(&pd->is_ready, msecs_to_jiffies(100))) { usbpd_err(&pd->dev, "data_role swap timed out\n"); mutex_unlock(&pd->swap_lock); return -ETIMEDOUT; } mutex_unlock(&pd->swap_lock); if ((*val == DUAL_ROLE_PROP_DR_HOST && pd->current_dr != DR_DFP) || (*val == DUAL_ROLE_PROP_DR_DEVICE && Loading Loading @@ -2591,17 +2603,21 @@ static int usbpd_dr_set_property(struct dual_role_phy_instance *dual_role, return -EAGAIN; } reinit_completion(&pd->swap_complete); mutex_lock(&pd->swap_lock); reinit_completion(&pd->is_ready); pd->send_pr_swap = true; kick_sm(pd, 0); /* wait for operation to complete */ if (!wait_for_completion_timeout(&pd->swap_complete, if (!wait_for_completion_timeout(&pd->is_ready, msecs_to_jiffies(2000))) { usbpd_err(&pd->dev, "power_role swap timed out\n"); mutex_unlock(&pd->swap_lock); return -ETIMEDOUT; } mutex_unlock(&pd->swap_lock); if ((*val == DUAL_ROLE_PROP_PR_SRC && pd->current_pr != PR_SRC) || (*val == DUAL_ROLE_PROP_PR_SNK && Loading Loading @@ -2864,36 +2880,62 @@ static ssize_t select_pdo_store(struct device *dev, int pdo, uv = 0, ua = 0; int ret; mutex_lock(&pd->swap_lock); /* Only allowed if we are already in explicit sink contract */ if (pd->current_state != PE_SNK_READY || !is_sink_tx_ok(pd)) { usbpd_err(&pd->dev, "select_pdo: Cannot select new PDO yet\n"); return -EBUSY; ret = -EBUSY; goto out; } ret = sscanf(buf, "%d %d %d %d", &src_cap_id, &pdo, &uv, &ua); if (ret != 2 && ret != 4) { usbpd_err(&pd->dev, "select_pdo: Must specify <src cap id> <PDO> [<uV> <uA>]\n"); return -EINVAL; ret = -EINVAL; goto out; } if (src_cap_id != pd->src_cap_id) { usbpd_err(&pd->dev, "select_pdo: src_cap_id mismatch. Requested:%d, current:%d\n", src_cap_id, pd->src_cap_id); return -EINVAL; ret = -EINVAL; goto out; } if (pdo < 1 || pdo > 7) { usbpd_err(&pd->dev, "select_pdo: invalid PDO:%d\n", pdo); return -EINVAL; ret = -EINVAL; goto out; } ret = pd_select_pdo(pd, pdo, uv, ua); if (ret) return ret; goto out; usbpd_set_state(pd, PE_SNK_SELECT_CAPABILITY); reinit_completion(&pd->is_ready); pd->send_request = true; kick_sm(pd, 0); return size; /* wait for operation to complete */ if (!wait_for_completion_timeout(&pd->is_ready, msecs_to_jiffies(1000))) { usbpd_err(&pd->dev, "select_pdo: request timed out\n"); ret = -ETIMEDOUT; goto out; } /* determine if request was accepted/rejected */ if (pd->selected_pdo != pd->requested_pdo || pd->current_voltage != pd->requested_voltage) { usbpd_err(&pd->dev, "select_pdo: request rejected\n"); ret = -EINVAL; } out: pd->send_request = false; mutex_unlock(&pd->swap_lock); return ret ? ret : size; } static ssize_t select_pdo_show(struct device *dev, Loading Loading @@ -3123,6 +3165,7 @@ struct usbpd *usbpd_create(struct device *parent) INIT_WORK(&pd->sm_work, usbpd_sm); hrtimer_init(&pd->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); pd->timer.function = pd_timeout; mutex_init(&pd->swap_lock); pd->usb_psy = power_supply_get_by_name("usb"); if (!pd->usb_psy) { Loading Loading @@ -3233,7 +3276,7 @@ struct usbpd *usbpd_create(struct device *parent) spin_lock_init(&pd->rx_lock); INIT_LIST_HEAD(&pd->rx_q); INIT_LIST_HEAD(&pd->svid_handlers); init_completion(&pd->swap_complete); init_completion(&pd->is_ready); pd->psy_nb.notifier_call = psy_changed; ret = power_supply_reg_notifier(&pd->psy_nb); Loading Loading
drivers/usb/pd/policy_engine.c +58 −15 Original line number Diff line number Diff line Loading @@ -338,8 +338,10 @@ struct usbpd { enum power_role current_pr; bool in_pr_swap; bool pd_phy_opened; struct completion swap_complete; bool send_request; struct completion is_ready; struct mutex swap_lock; struct dual_role_phy_instance *dual_role; struct dual_role_phy_desc dr_desc; bool send_pr_swap; Loading Loading @@ -463,6 +465,9 @@ static inline void pd_reset_protocol(struct usbpd *pd) */ pd->rx_msgid = -1; pd->tx_msgid = 0; pd->send_request = false; pd->send_pr_swap = false; pd->send_dr_swap = false; } static int pd_send_msg(struct usbpd *pd, u8 hdr_type, const u32 *data, Loading Loading @@ -842,7 +847,7 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) } kobject_uevent(&pd->dev.kobj, KOBJ_CHANGE); complete(&pd->swap_complete); complete(&pd->is_ready); dual_role_instance_changed(pd->dual_role); break; Loading Loading @@ -977,7 +982,7 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) case PE_SNK_READY: pd->in_explicit_contract = true; kobject_uevent(&pd->dev.kobj, KOBJ_CHANGE); complete(&pd->swap_complete); complete(&pd->is_ready); dual_role_instance_changed(pd->dual_role); break; Loading Loading @@ -2075,6 +2080,9 @@ static void usbpd_sm(struct work_struct *w) vconn_swap(pd); } else if (IS_DATA(rx_msg, MSG_VDM)) { handle_vdm_rx(pd, rx_msg); } else if (pd->send_request) { pd->send_request = false; usbpd_set_state(pd, PE_SNK_SELECT_CAPABILITY); } else if (pd->send_pr_swap && is_sink_tx_ok(pd)) { pd->send_pr_swap = false; ret = pd_send_msg(pd, MSG_PR_SWAP, NULL, 0, SOP_MSG); Loading Loading @@ -2540,17 +2548,21 @@ static int usbpd_dr_set_property(struct dual_role_phy_instance *dual_role, return -EAGAIN; } reinit_completion(&pd->swap_complete); mutex_lock(&pd->swap_lock); reinit_completion(&pd->is_ready); pd->send_dr_swap = true; kick_sm(pd, 0); /* wait for operation to complete */ if (!wait_for_completion_timeout(&pd->swap_complete, if (!wait_for_completion_timeout(&pd->is_ready, msecs_to_jiffies(100))) { usbpd_err(&pd->dev, "data_role swap timed out\n"); mutex_unlock(&pd->swap_lock); return -ETIMEDOUT; } mutex_unlock(&pd->swap_lock); if ((*val == DUAL_ROLE_PROP_DR_HOST && pd->current_dr != DR_DFP) || (*val == DUAL_ROLE_PROP_DR_DEVICE && Loading Loading @@ -2591,17 +2603,21 @@ static int usbpd_dr_set_property(struct dual_role_phy_instance *dual_role, return -EAGAIN; } reinit_completion(&pd->swap_complete); mutex_lock(&pd->swap_lock); reinit_completion(&pd->is_ready); pd->send_pr_swap = true; kick_sm(pd, 0); /* wait for operation to complete */ if (!wait_for_completion_timeout(&pd->swap_complete, if (!wait_for_completion_timeout(&pd->is_ready, msecs_to_jiffies(2000))) { usbpd_err(&pd->dev, "power_role swap timed out\n"); mutex_unlock(&pd->swap_lock); return -ETIMEDOUT; } mutex_unlock(&pd->swap_lock); if ((*val == DUAL_ROLE_PROP_PR_SRC && pd->current_pr != PR_SRC) || (*val == DUAL_ROLE_PROP_PR_SNK && Loading Loading @@ -2864,36 +2880,62 @@ static ssize_t select_pdo_store(struct device *dev, int pdo, uv = 0, ua = 0; int ret; mutex_lock(&pd->swap_lock); /* Only allowed if we are already in explicit sink contract */ if (pd->current_state != PE_SNK_READY || !is_sink_tx_ok(pd)) { usbpd_err(&pd->dev, "select_pdo: Cannot select new PDO yet\n"); return -EBUSY; ret = -EBUSY; goto out; } ret = sscanf(buf, "%d %d %d %d", &src_cap_id, &pdo, &uv, &ua); if (ret != 2 && ret != 4) { usbpd_err(&pd->dev, "select_pdo: Must specify <src cap id> <PDO> [<uV> <uA>]\n"); return -EINVAL; ret = -EINVAL; goto out; } if (src_cap_id != pd->src_cap_id) { usbpd_err(&pd->dev, "select_pdo: src_cap_id mismatch. Requested:%d, current:%d\n", src_cap_id, pd->src_cap_id); return -EINVAL; ret = -EINVAL; goto out; } if (pdo < 1 || pdo > 7) { usbpd_err(&pd->dev, "select_pdo: invalid PDO:%d\n", pdo); return -EINVAL; ret = -EINVAL; goto out; } ret = pd_select_pdo(pd, pdo, uv, ua); if (ret) return ret; goto out; usbpd_set_state(pd, PE_SNK_SELECT_CAPABILITY); reinit_completion(&pd->is_ready); pd->send_request = true; kick_sm(pd, 0); return size; /* wait for operation to complete */ if (!wait_for_completion_timeout(&pd->is_ready, msecs_to_jiffies(1000))) { usbpd_err(&pd->dev, "select_pdo: request timed out\n"); ret = -ETIMEDOUT; goto out; } /* determine if request was accepted/rejected */ if (pd->selected_pdo != pd->requested_pdo || pd->current_voltage != pd->requested_voltage) { usbpd_err(&pd->dev, "select_pdo: request rejected\n"); ret = -EINVAL; } out: pd->send_request = false; mutex_unlock(&pd->swap_lock); return ret ? ret : size; } static ssize_t select_pdo_show(struct device *dev, Loading Loading @@ -3123,6 +3165,7 @@ struct usbpd *usbpd_create(struct device *parent) INIT_WORK(&pd->sm_work, usbpd_sm); hrtimer_init(&pd->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); pd->timer.function = pd_timeout; mutex_init(&pd->swap_lock); pd->usb_psy = power_supply_get_by_name("usb"); if (!pd->usb_psy) { Loading Loading @@ -3233,7 +3276,7 @@ struct usbpd *usbpd_create(struct device *parent) spin_lock_init(&pd->rx_lock); INIT_LIST_HEAD(&pd->rx_q); INIT_LIST_HEAD(&pd->svid_handlers); init_completion(&pd->swap_complete); init_completion(&pd->is_ready); pd->psy_nb.notifier_call = psy_changed; ret = power_supply_reg_notifier(&pd->psy_nb); Loading