On Mon, Mar 09, 2015 at 10:09:21AM +0800, Li Jun wrote: > From: Li Jun <b47624@xxxxxxxxxxxxx> > > Add a dedicataed normal timer for HNP polling since it's cyclical, while > in peripheral mode, change a/b_bus_req to be 1 will make it response > to host request flag with 1, then role switch will be started. use a_bus_req/b_bus_req Why hnp polling timer can't use chipidea fsm hrtimer list? > > Signed-off-by: Li Jun <jun.li@xxxxxxxxxxxxx> > --- > drivers/usb/chipidea/ci.h | 4 ++++ > drivers/usb/chipidea/otg_fsm.c | 49 +++++++++++++++++++++++++++++++++++++--- > drivers/usb/chipidea/otg_fsm.h | 2 ++ > 3 files changed, 52 insertions(+), 3 deletions(-) > > diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h > index aeec5f0..3192a44 100644 > --- a/drivers/usb/chipidea/ci.h > +++ b/drivers/usb/chipidea/ci.h > @@ -166,6 +166,8 @@ struct hw_bank { > * @hr_timeouts: time out list for active otg fsm timers > * @enabled_otg_timer_bits: bits of enabled otg timers > * @next_otg_timer: next nearest enabled timer to be expired > + * @hnp_polling_timer: cyclical timer for hnp polling > + * @hnp_polling_req: indicates there is hnp polling request > * @work: work for role changing > * @wq: workqueue thread > * @qh_pool: allocation pool for queue heads > @@ -212,6 +214,8 @@ struct ci_hdrc { > ktime_t hr_timeouts[NUM_OTG_FSM_TIMERS]; > unsigned enabled_otg_timer_bits; > enum otg_fsm_timer next_otg_timer; > + struct timer_list hnp_polling_timer; > + bool hnp_polling_req; > struct work_struct work; > struct workqueue_struct *wq; > > diff --git a/drivers/usb/chipidea/otg_fsm.c b/drivers/usb/chipidea/otg_fsm.c > index 083acf4..ed79ae7 100644 > --- a/drivers/usb/chipidea/otg_fsm.c > +++ b/drivers/usb/chipidea/otg_fsm.c > @@ -66,6 +66,11 @@ set_a_bus_req(struct device *dev, struct device_attribute *attr, > return count; > } > ci->fsm.a_bus_req = 1; > + if (ci->fsm.otg->state == OTG_STATE_A_PERIPHERAL) { > + ci->gadget.host_request_flag = 1; > + mutex_unlock(&ci->fsm.lock); > + return count; > + } > } > > ci_otg_queue_work(ci); > @@ -144,8 +149,14 @@ set_b_bus_req(struct device *dev, struct device_attribute *attr, > mutex_lock(&ci->fsm.lock); > if (buf[0] == '0') > ci->fsm.b_bus_req = 0; > - else if (buf[0] == '1') > + else if (buf[0] == '1') { > ci->fsm.b_bus_req = 1; > + if (ci->fsm.otg->state == OTG_STATE_B_PERIPHERAL) { > + ci->gadget.host_request_flag = 1; > + mutex_unlock(&ci->fsm.lock); > + return count; > + } > + } > > ci_otg_queue_work(ci); > mutex_unlock(&ci->fsm.lock); > @@ -203,6 +214,7 @@ static unsigned otg_timer_ms[] = { > 0, > TB_DATA_PLS, > TB_SSEND_SRP, > + 0, > }; > > /* > @@ -358,6 +370,7 @@ static int (*otg_timer_handlers[])(struct ci_hdrc *) = { > NULL, /* A_WAIT_ENUM */ > b_data_pls_tmout, /* B_DATA_PLS */ > b_ssend_srp_tmout, /* B_SSEND_SRP */ > + NULL, /* HNP_POLLING */ > }; > > /* > @@ -404,15 +417,32 @@ static enum hrtimer_restart ci_otg_hrtimer_func(struct hrtimer *t) > return HRTIMER_NORESTART; > } > > +static void hnp_polling_timer_work(unsigned long arg) > +{ > + struct ci_hdrc *ci = (struct ci_hdrc *)arg; > + > + ci->hnp_polling_req = true; > + ci_otg_queue_work(ci); > +} > + > /* Initialize timers */ > static int ci_otg_init_timers(struct ci_hdrc *ci) > { > hrtimer_init(&ci->otg_fsm_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); > ci->otg_fsm_hrtimer.function = ci_otg_hrtimer_func; > > + setup_timer(&ci->hnp_polling_timer, hnp_polling_timer_work, > + (unsigned long)ci); > + > return 0; > } > > +static void ci_otg_add_hnp_polling_timer(struct ci_hdrc *ci) > +{ > + mod_timer(&ci->hnp_polling_timer, > + jiffies + msecs_to_jiffies(T_HOST_REQ_POLL)); > +} > + > /* -------------------------------------------------------------*/ > /* Operations that will be called from OTG Finite State Machine */ > /* -------------------------------------------------------------*/ > @@ -420,8 +450,12 @@ static void ci_otg_fsm_add_timer(struct otg_fsm *fsm, enum otg_fsm_timer t) > { > struct ci_hdrc *ci = container_of(fsm, struct ci_hdrc, fsm); > > - if (t < NUM_OTG_FSM_TIMERS) > - ci_otg_add_timer(ci, t); > + if (t < NUM_OTG_FSM_TIMERS) { > + if (t == HNP_POLLING) > + ci_otg_add_hnp_polling_timer(ci); > + else > + ci_otg_add_timer(ci, t); > + } > return; > } > > @@ -569,6 +603,14 @@ int ci_otg_fsm_work(struct ci_hdrc *ci) > return 0; > > pm_runtime_get_sync(ci->dev); > + if (ci->hnp_polling_req) { > + ci->hnp_polling_req = false; > + if (otg_hnp_polling(&ci->fsm) != HOST_REQUEST_FLAG) { > + pm_runtime_put_sync(ci->dev); > + return 0; > + } > + } > + When you do the polling device, it seems you disable the interrupt. > if (otg_statemachine(&ci->fsm)) { > if (ci->fsm.otg->state == OTG_STATE_A_IDLE) { > /* > @@ -817,4 +859,5 @@ int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci) > void ci_hdrc_otg_fsm_remove(struct ci_hdrc *ci) > { > sysfs_remove_group(&ci->dev->kobj, &inputs_attr_group); > + del_timer_sync(&ci->hnp_polling_timer); > } > diff --git a/drivers/usb/chipidea/otg_fsm.h b/drivers/usb/chipidea/otg_fsm.h > index 2689375..fbd6dc7 100644 > --- a/drivers/usb/chipidea/otg_fsm.h > +++ b/drivers/usb/chipidea/otg_fsm.h > @@ -62,6 +62,8 @@ > /* SSEND time before SRP */ > #define TB_SSEND_SRP (1500) /* minimum 1.5 sec, section:5.1.2 */ > > +#define T_HOST_REQ_POLL (1500) /* HNP polling interval 1s~2s */ > + > #ifdef CONFIG_USB_OTG_FSM > > int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci); > -- -- Best Regards, Peter Chen -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html