usb: dwc3-msm: Do dwc3_msm_gadget_vbus_draw() in sleepable context
The gadget mode notification to draw a specific current may
occur in context with interrupts disabled, however the charger
driver's implementation of power_supply_set_property() for
POWER_SUPPLY_CURRENT_MAX currently uses a mutex. Since
sleeping is disallowed in this case, instead schedule a
work function to do the call.
Change-Id: I810ad8c102124ce22de72d83b6df58c8fc991251
Signed-off-by: Jack Pham <jackp@codeaurora.org>
Signed-off-by: Mayank Rana <mrana@codeaurora.org>
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index bee16ac..ea36f41 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -186,6 +186,7 @@
u32 bus_perf_client;
struct msm_bus_scale_pdata *bus_scale_table;
struct power_supply *usb_psy;
+ struct work_struct vbus_draw_work;
bool in_host_mode;
unsigned int tx_fifo_size;
bool vbus_active;
@@ -1585,6 +1586,15 @@
}
+static void dwc3_msm_vbus_draw_work(struct work_struct *w)
+{
+ struct dwc3_msm *mdwc = container_of(w, struct dwc3_msm,
+ vbus_draw_work);
+ struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3);
+
+ dwc3_msm_gadget_vbus_draw(mdwc, dwc->vbus_draw);
+}
+
static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned int event)
{
struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
@@ -1670,7 +1680,7 @@
break;
case DWC3_CONTROLLER_SET_CURRENT_DRAW_EVENT:
dev_dbg(mdwc->dev, "DWC3_CONTROLLER_SET_CURRENT_DRAW_EVENT received\n");
- dwc3_msm_gadget_vbus_draw(mdwc, dwc->vbus_draw);
+ schedule_work(&mdwc->vbus_draw_work);
break;
case DWC3_CONTROLLER_RESTART_USB_SESSION:
dev_dbg(mdwc->dev, "DWC3_CONTROLLER_RESTART_USB_SESSION received\n");
@@ -2568,6 +2578,7 @@
INIT_WORK(&mdwc->resume_work, dwc3_resume_work);
INIT_WORK(&mdwc->restart_usb_work, dwc3_restart_usb_work);
INIT_WORK(&mdwc->bus_vote_w, dwc3_msm_bus_vote_w);
+ INIT_WORK(&mdwc->vbus_draw_work, dwc3_msm_vbus_draw_work);
INIT_DELAYED_WORK(&mdwc->sm_work, dwc3_otg_sm_work);
mdwc->dwc3_wq = alloc_ordered_workqueue("dwc3_wq", 0);