Re: [PATCH v2 03/15] media: intel/ipu6: add IPU6 buttress interface driver

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

 



Bingbu,

On Wed, 2024-01-03 at 21:18 +0800, Bingbu Cao wrote:
> Andreas,
> 
> On 1/3/24 9:11 PM, Bingbu Cao wrote:
> > Andreas,
> > 
> > On 1/3/24 5:22 PM, Andreas Helbech Kleist wrote:
> > > Hi Bingbu,
> > > 
> > > On Tue, 2023-10-24 at 19:29 +0800, bingbu.cao@xxxxxxxxx wrote:
> > > > From: Bingbu Cao <bingbu.cao@xxxxxxxxx>
> > > > 
> > > > The IPU6 buttress is the interface between IPU device (input system
> > > > and processing system) with rest of the SoC. It contains overall IPU
> > > > hardware control registers, these control registers are used as the
> > > > interfaces with the Intel Converged Security Engine and Punit to do
> > > > firmware authentication and power management.
> > > > 
> > > > Signed-off-by: Bingbu Cao <bingbu.cao@xxxxxxxxx>
> > > > ---
> > > 
> > > ...
> > > 
> > > > +static irqreturn_t ipu6_buttress_call_isr(struct ipu6_bus_device *adev)
> > > > +{
> > > > +	irqreturn_t ret = IRQ_WAKE_THREAD;
> > > > +
> > > > +	if (!adev || !adev->auxdrv || !adev->auxdrv_data)
> > > > +		return IRQ_NONE;
> > > > +
> > > > +	if (adev->auxdrv_data->isr)
> > > > +		ret = adev->auxdrv_data->isr(adev);
> > > > +
> > > > +	if (ret == IRQ_WAKE_THREAD && !adev->auxdrv_data->isr_threaded)
> > > > +		ret = IRQ_NONE;
> > > > +
> > > > +	return ret;
> > > > +}
> > > > +
> > > > +irqreturn_t ipu6_buttress_isr(int irq, void *isp_ptr)
> > > > +{
> > > > +	struct ipu6_device *isp = isp_ptr;
> > > > +	struct ipu6_bus_device *adev[] = { isp->isys, isp->psys };
> > > > +	struct ipu6_buttress *b = &isp->buttress;
> > > > +	u32 reg_irq_sts = BUTTRESS_REG_ISR_STATUS;
> > > > +	irqreturn_t ret = IRQ_NONE;
> > > > +	u32 disable_irqs = 0;
> > > > +	u32 irq_status;
> > > > +	u32 i, count = 0;
> > > > +
> > > > +	pm_runtime_get_noresume(&isp->pdev->dev);
> > > > +
> > > > +	irq_status = readl(isp->base + reg_irq_sts);
> > > > +	if (!irq_status) {
> > > > +		pm_runtime_put_noidle(&isp->pdev->dev);
> > > > +		return IRQ_NONE;
> > > > +	}
> > > > +
> > > > +	do {
> > > > +		writel(irq_status, isp->base + BUTTRESS_REG_ISR_CLEAR);
> > > > +
> > > > +		for (i = 0; i < ARRAY_SIZE(ipu6_adev_irq_mask); i++) {
> > > > +			irqreturn_t r = ipu6_buttress_call_isr(adev[i]);
> > > > +
> > > > +			if (!(irq_status & ipu6_adev_irq_mask[i]))
> > > > +				continue;
> > > > +
> > > > +			if (r == IRQ_WAKE_THREAD) {
> > > > +				ret = IRQ_WAKE_THREAD;
> > > > +				disable_irqs |= ipu6_adev_irq_mask[i];
> > > > +			} else if (ret == IRQ_NONE && r == IRQ_HANDLED) {
> > > > +				ret = IRQ_HANDLED;
> > > > +			}
> > > > +		}
> > > 
> > > It seems wrong to call the ISR for a adev[i] before checking the
> > > corresponding IRQ mask. If the mask is not set, the ISR is still
> > > called, but the result is thrown away.
> > > 
> > > I started investigating this because I'm seeing "general protection
> > > fault, probably for non-canonical address 0x6b6b6b6b6b6b6b6b" in this
> > > function when unbinding the IPU4 driver.
> > > 
> > > How do you ensure that the ISR is not called on a ipu6-bus device that
> > > has been deleted? Specifically in ipu6_pci_remove, ipu6_bus_del_devices
> > > is called before ipu6_buttress_exit (which disables buttress IRQs).
> > > Perhaps the above for loop should really be a "for each ipu6-bus
> > > device" loop?
> > 
> > You are right, the buttress_exit() should be called before
> > ipu6_bus_del_devices().
> > 
> > Even with this, driver cannot guarantee that hardware irq was actually
> > disabled on IPU4. In some error cases, HW could report unmasked errors on
> > IPU4 (no such case on IPU6), if I remember correctly.

Thanks for the info, that's good to know.

> > Have you check whether devm_free_irq() in ipu6_pci_remove() can help you?

It looks like it might help.

> BTW, could you share the irq_status in your case?

Sorry, I don't have a log of it. And it seems to be a bit heisenbug-
like - it doesn't always happen when I add logging :/

/Andreas





[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux