Re: [PATCH V6 03/10] PCI/DOE: Add Data Object Exchange Aux Driver

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

 



On Thu, Feb 03, 2022 at 04:40:27PM -0600, Bjorn Helgaas wrote:
> On Mon, Jan 31, 2022 at 11:19:45PM -0800, ira.weiny@xxxxxxxxx wrote:
> > From: Jonathan Cameron <Jonathan.Cameron@xxxxxxxxxx>
> > 
> > Introduced in a PCI ECN [1], DOE provides a config space based mailbox
> > with standard protocol discovery.  Each mailbox is accessed through a
> > DOE Extended Capability.
> > 
> > Define an auxiliary device driver which control DOE auxiliary devices
> > registered on the auxiliary bus.
> > 
> > A DOE mailbox is allowed to support any number of protocols while some
> > DOE protocol specifications apply additional restrictions.
> > 
> > The protocols supported are queried and cached.  pci_doe_supports_prot()
> > can be used to determine if the DOE device supports the protocol
> > specified.
> > 
> > A synchronous interface is provided in pci_doe_exchange_sync() to
> > perform a single query / response exchange from the driver through the
> > device specified.
> > 
> > Testing was conducted against QEMU using:
> > 
> > https://lore.kernel.org/qemu-devel/1619454964-10190-1-git-send-email-cbrowy@xxxxxxxxxxxxxxxx/
> > 
> > This code is based on Jonathan's V4 series here:
> > 
> > https://lore.kernel.org/linux-cxl/20210524133938.2815206-1-Jonathan.Cameron@xxxxxxxxxx/
> 
> Details like references to previous versions can go below the "---"
> so they are omitted from the merged commit.  Many/most maintainers now
> include a Link: tag that facilitates tracing back from a commit to the
> mailing list history.

Done.

> 
> > [1] https://members.pcisig.com/wg/PCI-SIG/document/14143
> >     Data Object Exchange (DOE) - Approved 12 March 2020
> 
> Please update the "PCI ECN" text above and this citation to PCIe r6.0,
> sec 6.30.  No need to reference the ECN now that it's part of the
> published spec.

Done.

> 
> > +config PCI_DOE_DRIVER
> > +	tristate "PCI Data Object Exchange (DOE) driver"
> > +	select AUXILIARY_BUS
> > +	help
> > +	  Driver for DOE auxiliary devices.
> > +
> > +	  DOE provides a simple mailbox in PCI config space that is used by a
> > +	  number of different protocols.  DOE is defined in the Data Object
> > +	  Exchange ECN to the PCIe r5.0 spec.
> 
> Not sure this is relevant in Kconfig help, but if it is, update the
> citation to PCIe r6.0, sec 6.30.

I removed it.  I agree it will probably not age well.

> 
> > +obj-$(CONFIG_PCI_DOE_DRIVER)	+= pci-doe.o
> >  obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += xen-pcifront.o
> >  
> > +pci-doe-y := doe.o
> 
> Why do we need this doe.o to pci-doe.o dance?  Why not just rename
> doe.c to pci-doe.c?  It looks like that's what we do with pci-stub.c
> and pci-pf-stub.c, which are also tristate.

Not sure.  I think I may have just carried that from the cxl side when I moved
it here to pci.

I agree pci-doe is good.  I'll adjust the series as needed.

> 
> > +++ b/drivers/pci/doe.c
> > @@ -0,0 +1,675 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Data Object Exchange ECN
> > + * https://members.pcisig.com/wg/PCI-SIG/document/14143
> 
> Update citation.  Maybe copyright dates, too.



> 
> > + * Copyright (C) 2021 Huawei
> 
> > +/* Timeout of 1 second from 6.xx.1 (Operation), ECN - Data Object Exchange */
> 
> Update citation.

Done.

> 
> > +/**
> > + * struct pci_doe - A single DOE mailbox driver
> > + *
> > + * @doe_dev: The DOE Auxiliary device being driven
> > + * @abort_c: Completion used for initial abort handling
> > + * @irq: Interrupt used for signaling DOE ready or abort
> > + * @irq_name: Name used to identify the irq for a particular DOE
> 
> s/ irq / IRQ /

Done.

> 
> > +static int pci_doe_cache_protocols(struct pci_doe *doe)
> > +{
> > +	u8 index = 0;
> > +	int num_prots;
> > +	int rc;
> > +
> > +	/* Discovery protocol must always be supported and must report itself */
> > +	num_prots = 1;
> > +	doe->prots = devm_kcalloc(&doe->doe_dev->adev.dev, num_prots,
> > +				  sizeof(*doe->prots), GFP_KERNEL);
> > +	if (doe->prots == NULL)
> 
> More idiomatic (and as you did below):
> 
>   if (!doe->prots)

Done.

> 
> > +		return -ENOMEM;
> > +
> > +	do {
> > +		struct pci_doe_protocol *prot;
> > +
> > +		prot = &doe->prots[num_prots - 1];
> > +		rc = pci_doe_discovery(doe, &index, &prot->vid, &prot->type);
> > +		if (rc)
> > +			return rc;
> > +
> > +		if (index) {
> > +			struct pci_doe_protocol *prot_new;
> > +
> > +			num_prots++;
> > +			prot_new = devm_krealloc(&doe->doe_dev->adev.dev,
> > +						 doe->prots,
> > +						 sizeof(*doe->prots) *
> > +							num_prots,
> > +						 GFP_KERNEL);
> > +			if (prot_new == NULL)
> 
> Ditto.

Done.

> 
> > +				return -ENOMEM;
> > +			doe->prots = prot_new;
> > +		}
> > +	} while (index);
> > +
> > +	doe->num_prots = num_prots;
> > +	return 0;
> > +}
> 
> > +static int pci_doe_reg_irq(struct pci_doe *doe)
> > +{
> > +	struct pci_dev *pdev = doe->doe_dev->pdev;
> > +	bool poll = !pci_dev_msi_enabled(pdev);
> > +	int offset = doe->doe_dev->cap_offset;
> > +	int rc, irq;
> > +	u32 val;
> > +
> 
>   if (poll)
>     return 0;
> 
> or maybe just:
> 
>   if (!pci_dev_msi_enabled(pdev))
>     return 0;
> 
> No need to read PCI_DOE_CAP or indent all this code.

Good point. done.

> 
> > +	pci_read_config_dword(pdev, offset + PCI_DOE_CAP, &val);
> > +
> > +	if (!poll && FIELD_GET(PCI_DOE_CAP_INT, val)) {
> > +		irq = pci_irq_vector(pdev, FIELD_GET(PCI_DOE_CAP_IRQ, val));
> > +		if (irq < 0)
> > +			return irq;
> > +
> > +		doe->irq_name = devm_kasprintf(&doe->doe_dev->adev.dev,
> > +						GFP_KERNEL,
> > +						"DOE[%s]",
> 
> Fill line.

Done.

> 
> > +						doe->doe_dev->adev.name);
> > +		if (!doe->irq_name)
> > +			return -ENOMEM;
> > +
> > +		rc = devm_request_irq(&pdev->dev, irq, pci_doe_irq, 0,
> > +				      doe->irq_name, doe);
> > +		if (rc)
> > +			return rc;
> > +
> > +		doe->irq = irq;
> > +		pci_write_config_dword(pdev, offset + PCI_DOE_CTRL,
> > +				       PCI_DOE_CTRL_INT_EN);
> > +	}
> > +
> > +	return 0;
> > +}
> 
> > +static int pci_doe_probe(struct auxiliary_device *aux_dev,
> > +			 const struct auxiliary_device_id *id)
> > +{
> > +	struct pci_doe_dev *doe_dev = container_of(aux_dev,
> > +					struct pci_doe_dev,
> > +					adev);
> 
> Fill line.

Done.

> 
> > +	struct pci_doe *doe;
> > +	int rc;
> > +
> > +	doe = devm_kzalloc(&aux_dev->dev, sizeof(*doe), GFP_KERNEL);
> > +	if (!doe)
> > +		return -ENOMEM;
> > +
> > +	mutex_init(&doe->state_lock);
> > +	init_completion(&doe->abort_c);
> > +	doe->doe_dev = doe_dev;
> > +	init_waitqueue_head(&doe->wq);
> > +	INIT_DELAYED_WORK(&doe->statemachine, doe_statemachine_work);
> > +	dev_set_drvdata(&aux_dev->dev, doe);
> > +
> > +	rc = pci_doe_reg_irq(doe);
> 
> "request_irq" or "setup_irq" or something?  "reg" is a little
> ambiguous.

Ok pci_doe_request_irq() since we are wrapping devm_request_irq()

> 
> > +	if (rc)
> > +		return rc;
> > +
> > +	/* Reset the mailbox by issuing an abort */
> > +	rc = pci_doe_abort(doe);
> > +	if (rc)
> > +		return rc;
> > +
> > +	rc = pci_doe_cache_protocols(doe);
> > +	if (rc)
> > +		return rc;
> > +
> > +	return 0;
> 
> Same as:
> 
>   return pci_doe_cache_protocols(doe);

Done.

> 
> > +static int __init pci_doe_init_module(void)
> > +{
> > +	int ret;
> > +
> > +	ret = auxiliary_driver_register(&pci_doe_auxiliary_drv);
> > +	if (ret) {
> > +		pr_err("Failed pci_doe auxiliary_driver_register() ret=%d\n",
> > +		       ret);
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> 
> Same as:
> 
>   if (ret)
>     pr_err(...);
> 
>   return ret;

Done.

> 
> > +++ b/include/linux/pci-doe.h
> > @@ -0,0 +1,60 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Data Object Exchange was added as an ECN to the PCIe r5.0 spec.
> 
> Update citation.

Done.

> 
> > +struct pci_doe_dev {
> > +	struct auxiliary_device adev;
> > +	struct pci_dev *pdev;
> > +	int cap_offset;
> 
> Can you name this "doe_cap", in the style of "msi_cap", "msix_cap",
> etc?

I can.  However, I feel I have to point out that msi[x]_cap both have comments
thusly:

        u8                      msi_cap;        /* MSI capability offset */
        u8                      msix_cap;       /* MSI-X capability offset */

Whereas cap_offset when read in the code is nicely self documenting.

...
        int offset = doe->doe_dev->cap_offset;
...

So I feel like it should be left as cap_offset;

Also there are 2 drivers which use cap_offset as well.


drivers/pci/hotplug/shpchp.h|102| u32 cap_offset;
drivers/pci/hotplug/shpchp_hpc.c|201| u32 cap_offset = ctrl->cap_offset;

drivers/pci/controller/pcie-altera.c|112| u32 cap_offset;               /* PCIe capability structure register offset */
drivers/pci/controller/pcie-altera.c|144| pcie->pcie_data->cap_offset +

And I don't think the comment on the altera device is needed...

So let me know if you feel strongly enough to change it.

Ira



[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux