Message ID | 1465995674-15816-10-git-send-email-riteshh@codeaurora.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
在 2016/6/15 21:01, Ritesh Harjani 写道: > From: Asutosh Das <asutoshd@codeaurora.org> > > Halt can be used in error cases to get control of the > bus. This is used to remove a task from device queue > and/or other recovery mechanisms. where to ues it? cmdq_irq or sdhci_irq? > > Signed-off-by: Asutosh Das <asutoshd@codeaurora.org> > Signed-off-by: Venkat Gopalakrishnan <venkatg@codeaurora.org> > [riteshh@codeaurora.org: fixed merge conflicts] > Signed-off-by: Ritesh Harjani <riteshh@codeaurora.org> > --- > drivers/mmc/host/cmdq_hci.c | 35 +++++++++++++++++++++++++++++++++++ > 1 file changed, 35 insertions(+) > > diff --git a/drivers/mmc/host/cmdq_hci.c b/drivers/mmc/host/cmdq_hci.c > index 68c8e03..64be0ce 100644 > --- a/drivers/mmc/host/cmdq_hci.c > +++ b/drivers/mmc/host/cmdq_hci.c > @@ -29,6 +29,9 @@ > #define DCMD_SLOT 31 > #define NUM_SLOTS 32 > > +/* 1 sec */ > +#define HALT_TIMEOUT_MS 1000 > + > static inline u8 *get_desc(struct cmdq_host *cq_host, u8 tag) > { > return cq_host->desc_base + (tag * cq_host->slot_sz); > @@ -570,11 +573,42 @@ irqreturn_t cmdq_irq(struct mmc_host *mmc, u32 intmask) > cmdq_dumpregs(cq_host); > } > > + if (status & CQIS_HAC) { > + /* halt is completed, wakeup waiting thread */ > + complete(&cq_host->halt_comp); > + } > + > out: > return IRQ_HANDLED; > } > EXPORT_SYMBOL(cmdq_irq); > > +/* May sleep */ > +static int cmdq_halt(struct mmc_host *mmc, bool halt) > +{ > + struct cmdq_host *cq_host = (struct cmdq_host *)mmc_cmdq_private(mmc); > + u32 val; > + > + if (halt) { > + cmdq_writel(cq_host, cmdq_readl(cq_host, CQCTL) | HALT, > + CQCTL); > + val = wait_for_completion_timeout(&cq_host->halt_comp, > + msecs_to_jiffies(HALT_TIMEOUT_MS)); > + /* halt done: re-enable legacy interrupts */ > + if (cq_host->ops->clear_set_irqs) > + cq_host->ops->clear_set_irqs(mmc, false); > + > + return val ? 0 : -ETIMEDOUT; > + } else { > + if (cq_host->ops->clear_set_irqs) > + cq_host->ops->clear_set_irqs(mmc, true); > + cmdq_writel(cq_host, cmdq_readl(cq_host, CQCTL) & ~HALT, > + CQCTL); > + } > + > + return 0; > +} > + > static void cmdq_post_req(struct mmc_host *host, struct mmc_request *mrq, > int err) > { > @@ -597,6 +631,7 @@ static const struct mmc_cmdq_host_ops cmdq_host_ops = { > .disable = cmdq_disable, > .request = cmdq_request, > .post_req = cmdq_post_req, > + .halt = cmdq_halt, > }; > > struct cmdq_host *cmdq_pltfm_init(struct platform_device *pdev) >
Hi, On 6/17/2016 2:21 PM, Shawn Lin wrote: > 在 2016/6/15 21:01, Ritesh Harjani 写道: >> From: Asutosh Das <asutoshd@codeaurora.org> >> >> Halt can be used in error cases to get control of the >> bus. This is used to remove a task from device queue >> and/or other recovery mechanisms. > > where to ues it? cmdq_irq or sdhci_irq? Below cmdq_halt will be used by higher layers to get legacy bus control to send legacy commands. Like during clock-scaling, we may need to send tuning commands for which we may wait for the device queue to be empty and then halt the controller to send legacy tuning commands. > >> >> Signed-off-by: Asutosh Das <asutoshd@codeaurora.org> >> Signed-off-by: Venkat Gopalakrishnan <venkatg@codeaurora.org> >> [riteshh@codeaurora.org: fixed merge conflicts] >> Signed-off-by: Ritesh Harjani <riteshh@codeaurora.org> >> --- >> drivers/mmc/host/cmdq_hci.c | 35 +++++++++++++++++++++++++++++++++++ >> 1 file changed, 35 insertions(+) >> >> diff --git a/drivers/mmc/host/cmdq_hci.c b/drivers/mmc/host/cmdq_hci.c >> index 68c8e03..64be0ce 100644 >> --- a/drivers/mmc/host/cmdq_hci.c >> +++ b/drivers/mmc/host/cmdq_hci.c >> @@ -29,6 +29,9 @@ >> #define DCMD_SLOT 31 >> #define NUM_SLOTS 32 >> >> +/* 1 sec */ >> +#define HALT_TIMEOUT_MS 1000 >> + >> static inline u8 *get_desc(struct cmdq_host *cq_host, u8 tag) >> { >> return cq_host->desc_base + (tag * cq_host->slot_sz); >> @@ -570,11 +573,42 @@ irqreturn_t cmdq_irq(struct mmc_host *mmc, u32 >> intmask) >> cmdq_dumpregs(cq_host); >> } >> >> + if (status & CQIS_HAC) { >> + /* halt is completed, wakeup waiting thread */ >> + complete(&cq_host->halt_comp); >> + } >> + >> out: >> return IRQ_HANDLED; >> } >> EXPORT_SYMBOL(cmdq_irq); >> >> +/* May sleep */ >> +static int cmdq_halt(struct mmc_host *mmc, bool halt) >> +{ >> + struct cmdq_host *cq_host = (struct cmdq_host >> *)mmc_cmdq_private(mmc); >> + u32 val; >> + >> + if (halt) { >> + cmdq_writel(cq_host, cmdq_readl(cq_host, CQCTL) | HALT, >> + CQCTL); >> + val = wait_for_completion_timeout(&cq_host->halt_comp, >> + msecs_to_jiffies(HALT_TIMEOUT_MS)); >> + /* halt done: re-enable legacy interrupts */ >> + if (cq_host->ops->clear_set_irqs) >> + cq_host->ops->clear_set_irqs(mmc, false); >> + >> + return val ? 0 : -ETIMEDOUT; >> + } else { >> + if (cq_host->ops->clear_set_irqs) >> + cq_host->ops->clear_set_irqs(mmc, true); >> + cmdq_writel(cq_host, cmdq_readl(cq_host, CQCTL) & ~HALT, >> + CQCTL); >> + } >> + >> + return 0; >> +} >> + >> static void cmdq_post_req(struct mmc_host *host, struct mmc_request >> *mrq, >> int err) >> { >> @@ -597,6 +631,7 @@ static const struct mmc_cmdq_host_ops >> cmdq_host_ops = { >> .disable = cmdq_disable, >> .request = cmdq_request, >> .post_req = cmdq_post_req, >> + .halt = cmdq_halt, >> }; >> >> struct cmdq_host *cmdq_pltfm_init(struct platform_device *pdev) >> > > -- BR Ritesh -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/drivers/mmc/host/cmdq_hci.c b/drivers/mmc/host/cmdq_hci.c index 68c8e03..64be0ce 100644 --- a/drivers/mmc/host/cmdq_hci.c +++ b/drivers/mmc/host/cmdq_hci.c @@ -29,6 +29,9 @@ #define DCMD_SLOT 31 #define NUM_SLOTS 32 +/* 1 sec */ +#define HALT_TIMEOUT_MS 1000 + static inline u8 *get_desc(struct cmdq_host *cq_host, u8 tag) { return cq_host->desc_base + (tag * cq_host->slot_sz); @@ -570,11 +573,42 @@ irqreturn_t cmdq_irq(struct mmc_host *mmc, u32 intmask) cmdq_dumpregs(cq_host); } + if (status & CQIS_HAC) { + /* halt is completed, wakeup waiting thread */ + complete(&cq_host->halt_comp); + } + out: return IRQ_HANDLED; } EXPORT_SYMBOL(cmdq_irq); +/* May sleep */ +static int cmdq_halt(struct mmc_host *mmc, bool halt) +{ + struct cmdq_host *cq_host = (struct cmdq_host *)mmc_cmdq_private(mmc); + u32 val; + + if (halt) { + cmdq_writel(cq_host, cmdq_readl(cq_host, CQCTL) | HALT, + CQCTL); + val = wait_for_completion_timeout(&cq_host->halt_comp, + msecs_to_jiffies(HALT_TIMEOUT_MS)); + /* halt done: re-enable legacy interrupts */ + if (cq_host->ops->clear_set_irqs) + cq_host->ops->clear_set_irqs(mmc, false); + + return val ? 0 : -ETIMEDOUT; + } else { + if (cq_host->ops->clear_set_irqs) + cq_host->ops->clear_set_irqs(mmc, true); + cmdq_writel(cq_host, cmdq_readl(cq_host, CQCTL) & ~HALT, + CQCTL); + } + + return 0; +} + static void cmdq_post_req(struct mmc_host *host, struct mmc_request *mrq, int err) { @@ -597,6 +631,7 @@ static const struct mmc_cmdq_host_ops cmdq_host_ops = { .disable = cmdq_disable, .request = cmdq_request, .post_req = cmdq_post_req, + .halt = cmdq_halt, }; struct cmdq_host *cmdq_pltfm_init(struct platform_device *pdev)