@@ -70,7 +70,11 @@ static void otg_stop_hnp_polling(struct otg_fsm *fsm)
if (!fsm->host_req_flag)
return;
- cancel_delayed_work_sync(&fsm->hnp_polling_work);
+ /*
+ * We don't call cancel_delayed_work_sync() here because the
+ * worker is synchronized to this function via the fsm lock.
+ */
+ cancel_delayed_work(&fsm->hnp_polling_work);
}
/* Called when leaving a state. Do state clean up jobs here */
@@ -136,23 +140,27 @@ static void otg_leave_state(struct otg_fsm *fsm, enum usb_otg_state old_state)
}
}
+static int __otg_statemachine(struct otg_fsm *fsm);
+
static void otg_hnp_polling_work(struct work_struct *work)
{
struct otg_fsm *fsm = container_of(to_delayed_work(work),
struct otg_fsm, hnp_polling_work);
struct usb_device *udev;
- enum usb_otg_state state = fsm->otg->state;
+ enum usb_otg_state state;
u8 flag;
int retval;
+ mutex_lock(&fsm->lock);
+ state = fsm->otg->state;
if (state != OTG_STATE_A_HOST && state != OTG_STATE_B_HOST)
- return;
+ goto unlock;
udev = usb_hub_find_child(fsm->otg->host->root_hub, 1);
if (!udev) {
dev_err(fsm->otg->host->controller,
"no usb dev connected, can't start HNP polling\n");
- return;
+ goto unlock;
}
*fsm->host_req_flag = 0;
@@ -168,7 +176,7 @@ static void otg_hnp_polling_work(struct work_struct *work)
USB_CTRL_GET_TIMEOUT);
if (retval != 1) {
dev_err(&udev->dev, "Get one byte OTG status failed\n");
- return;
+ goto unlock;
}
flag = *fsm->host_req_flag;
@@ -176,10 +184,10 @@ static void otg_hnp_polling_work(struct work_struct *work)
/* Continue HNP polling */
schedule_delayed_work(&fsm->hnp_polling_work,
msecs_to_jiffies(T_HOST_REQ_POLL));
- return;
+ goto unlock;
} else if (flag != HOST_REQUEST_FLAG) {
dev_err(&udev->dev, "host request flag %d is invalid\n", flag);
- return;
+ goto unlock;
}
/* Host request flag is set */
@@ -200,7 +208,9 @@ static void otg_hnp_polling_work(struct work_struct *work)
fsm->b_bus_req = 0;
}
- otg_statemachine(fsm);
+ __otg_statemachine(fsm);
+unlock:
+ mutex_unlock(&fsm->lock);
}
static void otg_start_hnp_polling(struct otg_fsm *fsm)
@@ -340,12 +350,10 @@ static int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state)
}
/* State change judgement */
-int otg_statemachine(struct otg_fsm *fsm)
+static int __otg_statemachine(struct otg_fsm *fsm)
{
enum usb_otg_state state;
- mutex_lock(&fsm->lock);
-
state = fsm->otg->state;
fsm->state_changed = 0;
/* State machine state change judgement */
@@ -458,9 +466,16 @@ int otg_statemachine(struct otg_fsm *fsm)
default:
break;
}
- mutex_unlock(&fsm->lock);
VDBG("quit statemachine, changed = %d\n", fsm->state_changed);
return fsm->state_changed;
}
+
+int otg_statemachine(struct otg_fsm *fsm)
+{
+ int ret;
+ mutex_lock(&fsm->lock);
+ ret = __otg_statemachine(fsm);
+ mutex_unlock(&fsm->lock);
+}
EXPORT_SYMBOL_GPL(otg_statemachine);