Re: [PATCH 3/4] PCI: endpoint: pci-epf-test: Don't free doorbell IRQ unless requested

Koichiro Den <[email protected]>
Newsgroups dev.linux.lists.ntb,org.kernel.vger.linux-kernel,org.kernel.vger.linux-pci
Message-ID <3p2xxxpbsmkxqbwsdtl7v5itv5fnmyi72sltnsn52xtxtnzc4z@oxj5ktatnp4g>
On Mon, Feb 16, 2026 at 11:30:44PM +0900, Koichiro Den wrote:
> On Mon, Feb 16, 2026 at 12:35:56PM +0100, Niklas Cassel wrote:
> > On Mon, Feb 16, 2026 at 12:09:13AM +0900, Koichiro Den wrote:
> > > pci_epf_test_enable_doorbell() allocates a doorbell and then installs
> > > the interrupt handler with request_threaded_irq(). On failures before
> > > the IRQ is successfully requested (e.g. no free BAR,
> > > request_threaded_irq() failure), the error path jumps to
> > > err_doorbell_cleanup and calls pci_epf_test_doorbell_cleanup().
> > > 
> > > pci_epf_test_doorbell_cleanup() unconditionally calls free_irq() for the
> > > doorbell virq, which can trigger "Trying to free already-free IRQ"
> > > warnings when the IRQ was never requested or when request_threaded_irq()
> > > failed.
> > > 
> > > Track whether the doorbell IRQ has been successfully requested and only
> > > call free_irq() when it has.
> > > 
> > > Fixes: eff0c286aa91 ("PCI: endpoint: pci-epf-test: Add doorbell test support")
> > > Signed-off-by: Koichiro Den <[email protected]>
> > > ---
> > >  drivers/pci/endpoint/functions/pci-epf-test.c | 9 ++++++++-
> > >  1 file changed, 8 insertions(+), 1 deletion(-)
> > > 
> > > diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c
> > > index 148a34e51f6b..defe1e2ea427 100644
> > > --- a/drivers/pci/endpoint/functions/pci-epf-test.c
> > > +++ b/drivers/pci/endpoint/functions/pci-epf-test.c
> > > @@ -86,6 +86,7 @@ struct pci_epf_test {
> > >  	bool			dma_private;
> > >  	const struct pci_epc_features *epc_features;
> > >  	struct pci_epf_bar	db_bar;
> > > +	bool			db_irq_requested;
> > 
> > It would be nice if we could avoid this, it looks a bit odd.
> > 
> > 
> > >  	size_t			bar_size[PCI_STD_NUM_BARS];
> > >  };
> > >  
> > > @@ -715,7 +716,10 @@ static void pci_epf_test_doorbell_cleanup(struct pci_epf_test *epf_test)
> > >  	struct pci_epf_test_reg *reg = epf_test->reg[epf_test->test_reg_bar];
> > >  	struct pci_epf *epf = epf_test->epf;
> > >  
> > > -	free_irq(epf->db_msg[0].virq, epf_test);
> > > +	if (epf_test->db_irq_requested && epf->db_msg) {
> > > +		free_irq(epf->db_msg[0].virq, epf_test);
> > > +		epf_test->db_irq_requested = false;
> > > +	}
> > >  	reg->doorbell_bar = cpu_to_le32(NO_BAR);
> > >  
> > >  	pci_epf_free_doorbell(epf);
> > > @@ -732,6 +736,8 @@ static void pci_epf_test_enable_doorbell(struct pci_epf_test *epf_test,
> > >  	size_t offset;
> > >  	int ret;
> > >  
> > > +	epf_test->db_irq_requested = false;
> > > +
> > >  	ret = pci_epf_alloc_doorbell(epf, 1);
> > >  	if (ret)
> > >  		goto set_status_err;
> > > @@ -751,6 +757,7 @@ static void pci_epf_test_enable_doorbell(struct pci_epf_test *epf_test,
> > >  		goto err_doorbell_cleanup;
> > >  	}
> > >  
> > > +	epf_test->db_irq_requested = true;
> > >  	reg->doorbell_data = cpu_to_le32(msg->data);
> > >  	reg->doorbell_bar = cpu_to_le32(bar);
> > >  
> > 
> > Can't we do something like:
> > 
> > -For all goto's after request_threaded_irq() success case:
> > jump to a label that also cleans up the IRQ.
> > 
> > For failures before or at request_threaded_irq(), jump to
> > a label that does not call free_irq().
> 
> I thought this would be a minimal change to avoid the problematic case, but I
> agree it's not very clean (the "db_irq_requested" flag looks a bit odd).
> 
> So I'll split pci_epf_test_doorbell_cleanup() into two helper functions to match
> your suggested structure.
> 
> > 
> > 
> > 
> > pci_epf_test_disable_doorbell() should probably return error
> > if (!epf_test->db_bar.size)
> > 
> > (before pci_epf_test_disable_doorbell() calls free_irq())
> > 
> > pci_epf_test_disable_doorbell() should probably also memset
> > epf_test->db_bar.
> 
> and I'll take care of these suggestions as well.

I revisited the latest doorbell code with those latter suggestions in mind.
Looking at the current flow, it seems we may not actually need these additional
safeguards.

- any error path inside pci_epf_test_enable_doorbell() resets reg->doorbell_bar
  to NO_BAR.
- pci_epf_test_disable_doorbell() performs its cleanup only if reg->doorbell_bar
  is not NO_BAR. When it runs, it always resets reg->doorbell_bar to NO_BAR, so
  it cannot effectively run twice.

Given that the guarding logic is already centralized around reg->doorbell_bar,
explicitly clearing epf_test->db_bar does not seem strictly necessary.

It would be more of a refactoring cleanup than a functional fix.

Koichiro

> 
> Thanks for the review,
> Koichiro
> 
> > 
> > 
> > Kind regards,
> > Niklas
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.