Re: [PATCH 4/4] usb: dwc3: second part of hibernation support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

On Tue, Feb 07, 2012 at 11:50:54AM -0800, Paul Zimmerman wrote:
> > -----Original Message-----
> > From: Felipe Balbi [mailto:balbi@xxxxxx]
> > Sent: Monday, February 06, 2012 11:03 PM
> > 
> > On Mon, Feb 06, 2012 at 07:20:16PM -0800, Paul Zimmerman wrote:
> > > This patch adds the actual hibernation code, and allows it to be
> > > enabled in the Kconfig.
> > 
> > Actually, is there any real reason someone would not use such a feature
> > if it's available in HW ?
> > 
> > I mean, the guy chose to enable support for it on your core
> > configuration tool, right ?
> 
> It's a dangerous feature if it's not implemented 100% correctly.
> It can cause the system to freeze solid. So I think it's best to
> make it an optional feature, at least for the time being.

Could be, on the other hand, we want those failures to appear ASAP, so
we fix them promptly. If we keep it disabled, we will most likely loose
users, I'm afraid.

Another argument is that we can keep this for testing for a loooong
period of time before merging it to mainline. That's why we have
linux-next and that's why we both have devices with DWC3 controller.
Well there are a few more companies who might pitch in soon, so we might
just get more people to help testing patches.

> < snip >
> 
> > hmm, so this is all haps-specific ?? Isn't PCIe supposed to be
> > standardized, how come you have vendor-specific registers ??
> 
> The HAPS implementation is non-standard, sorry. There's nothing
> I can do about that.

Can you talk more about what you're doing here ? Are you talking to
HAPS' PCIe controller ? I mean, something on the FPGA, or something on
the PCB ? I'm trying to understand whose registers are these ?

> < snip >
> 
> > > +/*
> > > + * Platform-specific power control routine, for HAPS board
> > > + */
> > > +void dwc3_haps_power_ctl(struct dwc3 *dwc, int on)
> > > +{
> > > +	u32	reg;
> > > +	int	cnt = 0;
> > > +
> > > +	if (on) {
> > > +		/*
> > > +		 * Enable core well power
> > > +		 */
> > > +
> > > +		/* This is "faked" by the FPGA */
> > > +
> > > +		/*
> > > +		 * Communicate with power controller to set power state to D0
> > > +		 */
> > > +
> > > +		reg = dwc3_readl(dwc->regs, DWC3_HAPS_GASKET_POWER_CTL);
> > > +		dev_vdbg(dwc->dev, "R1=0x%08x before write\n", reg);
> > > +		reg = (reg & ~DWC3_HAPS_GASKET_POWER_DSTATE_MASK) |
> > > +				DWC3_HAPS_GASKET_POWER_DSTATE_D0;
> > > +		dwc3_writel(dwc->regs, DWC3_HAPS_GASKET_POWER_CTL, reg);
> > > +		reg = dwc3_readl(dwc->regs, DWC3_HAPS_GASKET_POWER_CTL);
> > > +		dev_vdbg(dwc->dev, "R1=0x%08x after write\n", reg);
> > 
> > isn't this the same as pci_set_power_state(pci, PCI_D0); ??
> 
> Since the HAPS has a non-standard implementation, not part of the PCI
> interface, the PCI power control functions won't work, AFAIK.

I'm not a PCI expert, but you ought to find a way to hide it under some
abstraction. Describing HAPS better would help other guys pitch in with
ideas.

I'm adding linux-pci@vger to the Cc list in order to ask for some help.

There is anyway a set of PCI pm platform_ops which you might be able to
use in order to hide this, I don't know. Like I said, I'm not very
confortable with the PCI subsystem.

> > > +		/*
> > > +		 * Wait until both PMUs confirm that they have entered D0
> > > +		 */
> > > +
> > > +		dev_vdbg(dwc->dev, "Asked for D0 state, awaiting response\n");
> > > +
> > > +		do {
> > > +			udelay(1);
> > > +			reg = dwc3_readl(dwc->regs, DWC3_HAPS_GASKET_DEBUG);
> > > +			if (++cnt > 10000000) {
> > > +				cnt = 0;
> > > +				dev_vdbg(dwc->dev, "0x%08x\n", reg);
> > > +			}
> > > +		} while ((reg & DWC3_HAPS_GASKET_DEBUG_DSTATE_MASK) !=
> > > +				DWC3_HAPS_GASKET_DEBUG_DSTATE_D0);
> > > +	} else {
> > > +		/*
> > > +		 * Communicate with power controller to set power state to D3
> > > +		 */
> > > +
> > > +		reg = dwc3_readl(dwc->regs, DWC3_HAPS_GASKET_POWER_CTL);
> > > +		dev_vdbg(dwc->dev, "R1=0x%08x before write\n", reg);
> > > +		reg = (reg & ~DWC3_HAPS_GASKET_POWER_DSTATE_MASK) |
> > > +				DWC3_HAPS_GASKET_POWER_DSTATE_D3;
> > > +		dwc3_writel(dwc->regs, DWC3_HAPS_GASKET_POWER_CTL, reg);
> > > +		reg = dwc3_readl(dwc->regs, DWC3_HAPS_GASKET_POWER_CTL);
> > > +		dev_vdbg(dwc->dev, "R1=0x%08x after write\n", reg);
> > 
> > likewise pci_set_poer_state(pci, PCI_D3hot); or D3cold, I don't know ??
> 
> ditto
> 
> > > +
> > > +		/*
> > > +		 * Wait until both PMUs confirm that they have entered D3
> > > +		 */
> > > +
> > > +		dev_vdbg(dwc->dev, "Asked for D3 state, awaiting response\n");
> > > +
> > > +		do {
> > > +			udelay(1);
> > > +			reg = dwc3_readl(dwc->regs, DWC3_HAPS_GASKET_DEBUG);
> > > +			if (++cnt >= 10000000) {
> > > +				cnt = 0;
> > > +				dev_vdbg(dwc->dev, "0x%08x\n", reg);
> > > +			}
> > > +		} while ((reg & DWC3_HAPS_GASKET_DEBUG_DSTATE_MASK) !=
> > > +				DWC3_HAPS_GASKET_DEBUG_DSTATE_D3);
> > > +	}
> > > +}
> > > +
> > > +/*
> > > + * Platform-specific PME interrupt handler, for HAPS board
> > > + */
> > > +int dwc3_haps_pme_intr(struct dwc3 *dwc)
> > 
> > if it's an IRQ handler, why aren't you requesting the IRQ and why ins't
> > this returning irqreturn_t ?
> 
> It's not a normal interrupt handler, it's part of the non-standard HAPS
> implementation of power control. In a normal platform there would be a
> separate interrupt for this.

I see. Another of HAPS' details. It would be very nice to uncover all of
this platform-specific details and find proper places for those.

> < snip >
> 
> > this is unnecessary. You should be using pm_runtime APIs for this ;-)
> > Please don't duplicate effort, we have our pm runtime layer for this
> > sort of situation.
> > 
> > If you use pm_runtime, you will enter hibernation whenever your pm usage
> > counter reaches zero, and we can be as aggressive as we want.
> 
> Can you point me to an existing kernel driver that uses the pm_runtime
> calls to perform what we need here? It must guarantee that after some

git grep -e "pm_runtime_" drivers/ will have show you many examples.
There's also lots of information under
Documentation/power/runtime_pm.txt

> function (pm_runtime_get?) is called, nothing will attempt to touch any

pm_runtime_get() will, well, do a get. In short, it will enable the
platform for access. In case of e.g. OMAP, we will be enabling the
correct clock nodes in order to be able to use the correct interconnect
to access device's register.

> of the controller registers except the ones that are guaranteed to be
> alive, namely the two HAPS-specific functions above. In particular, it
> must prevent calls from the upper layers into the gadget API from
> touching the controller registers.

that's something which is very driver specific ;-) So we must guarantee
in the driver that this will not happen. It's not very complex to
achieve that, though.

Actually, what most people do, is that they call pm_runtime_get_sync()
before an access to the device is needed, and pm_runtime_put() when the
device isn't needed anymore.

There's no way a generic pm layer can achieve that without help from the
driver. See that with your ad-hoc PM implementation, you have a bunch of
busy loops waiting for the device to come out of hibernation, those
loops will be handled by the generic PM layer, but the driver has to
help ;-)

-- 
balbi

Attachment: signature.asc
Description: Digital signature


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux