From: Michael Ellerman <michael@ellerman.id.au>
To: Matthew Wilcox <matthew@wil.cx>
Cc: linux-pci@vger.kernel.org, kaneshige.kenji@jp.fujitsu.com,
mingo@elte.hu, tglx@linutronix.de, davem@davemloft.net,
dan.j.williams@intel.com, Martine.Silbermann@hp.com,
benh@kernel.crashing.org, linux-kernel@vger.kernel.org,
Matthew Wilcox <willy@linux.intel.com>
Subject: Re: [PATCH 2/4] PCI: Support multiple MSI
Date: Mon, 07 Jul 2008 12:05:25 +1000 [thread overview]
Message-ID: <1215396326.19157.15.camel@localhost> (raw)
In-Reply-To: <1215264855-4372-2-git-send-email-matthew@wil.cx>
[-- Attachment #1: Type: text/plain, Size: 9758 bytes --]
On Sat, 2008-07-05 at 09:34 -0400, Matthew Wilcox wrote:
> Add the new API pci_enable_msi_block() to allow drivers to
> request multiple MSIs. Reimplement pci_enable_msi in terms
> of pci_enable_msi_block. Add a default implementation of
> arch_setup_msi_block() that only allows one MSI to be requested.
I don't think you need arch_setup_msi_block() at all.
We already have an arch hook that takes a number of irqs, it's
arch_setup_msi_irqs(), plural. It also has the type passed to it (MSI or
MSI-X), so it can decide if it needs to allocate the irq numbers
contiguously.
Or am I missing something?
cheers
> diff --git a/arch/powerpc/kernel/msi.c b/arch/powerpc/kernel/msi.c
> index c62d101..317c7c8 100644
> --- a/arch/powerpc/kernel/msi.c
> +++ b/arch/powerpc/kernel/msi.c
> @@ -32,7 +32,7 @@ int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
> return ppc_md.setup_msi_irqs(dev, nvec, type);
> }
>
> -void arch_teardown_msi_irqs(struct pci_dev *dev)
> +void arch_teardown_msi_irqs(struct pci_dev *dev, int nvec)
> {
> return ppc_md.teardown_msi_irqs(dev);
> }
> diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
> index 92992a8..6cbdf11 100644
> --- a/drivers/pci/msi.c
> +++ b/drivers/pci/msi.c
> @@ -40,18 +40,31 @@ arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *entry)
> }
>
> int __attribute__ ((weak))
> +arch_setup_msi_block(struct pci_dev *pdev, struct msi_desc *desc, int nvec)
> +{
> + if (nvec > 1)
> + return 1;
> + return arch_setup_msi_irq(pdev, desc);
> +}
> +
> +int __attribute__ ((weak))
> arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
> {
> - struct msi_desc *entry;
> + struct msi_desc *desc;
> int ret;
>
> - list_for_each_entry(entry, &dev->msi_list, list) {
> - ret = arch_setup_msi_irq(dev, entry);
> - if (ret)
> - return ret;
> + if (type == PCI_CAP_ID_MSI) {
> + desc = list_first_entry(&dev->msi_list, struct msi_desc, list);
> + ret = arch_setup_msi_block(dev, desc, nvec);
> + } else {
> + list_for_each_entry(desc, &dev->msi_list, list) {
> + ret = arch_setup_msi_irq(dev, desc);
> + if (ret)
> + break;
> + }
> }
>
> - return 0;
> + return ret;
> }
>
> void __attribute__ ((weak)) arch_teardown_msi_irq(unsigned int irq)
> @@ -60,13 +73,16 @@ void __attribute__ ((weak)) arch_teardown_msi_irq(unsigned int irq)
> }
>
> void __attribute__ ((weak))
> -arch_teardown_msi_irqs(struct pci_dev *dev)
> +arch_teardown_msi_irqs(struct pci_dev *dev, int nvec)
> {
> struct msi_desc *entry;
>
> list_for_each_entry(entry, &dev->msi_list, list) {
> - if (entry->irq != 0)
> - arch_teardown_msi_irq(entry->irq);
> + int i;
> + if (entry->irq == 0)
> + continue;
> + for (i = 0; i < nvec; i++)
> + arch_teardown_msi_irq(entry->irq + i);
> }
> }
>
> @@ -350,7 +366,7 @@ EXPORT_SYMBOL_GPL(pci_restore_msi_state);
> * multiple messages. A return of zero indicates the successful setup
> * of an entry zero with the new MSI irq or non-zero for otherwise.
> **/
> -static int msi_capability_init(struct pci_dev *dev)
> +static int msi_capability_init(struct pci_dev *dev, int nr_irqs)
> {
> struct msi_desc *entry;
> int pos, ret;
> @@ -394,7 +410,7 @@ static int msi_capability_init(struct pci_dev *dev)
> list_add_tail(&entry->list, &dev->msi_list);
>
> /* Configure MSI capability structure */
> - ret = arch_setup_msi_irqs(dev, 1, PCI_CAP_ID_MSI);
> + ret = arch_setup_msi_irqs(dev, nr_irqs, PCI_CAP_ID_MSI);
> if (ret) {
> msi_free_irqs(dev);
> return ret;
> @@ -546,36 +562,47 @@ static int pci_msi_check_device(struct pci_dev* dev, int nvec, int type)
> }
>
> /**
> - * pci_enable_msi - configure device's MSI capability structure
> - * @dev: pointer to the pci_dev data structure of MSI device function
> + * pci_enable_msi_block - configure device's MSI capability structure
> + * @pdev: Device to configure
> + * @nr_irqs: Number of IRQs requested
> + *
> + * Allocate IRQs for a device with the MSI capability.
> + * This function returns a negative errno if an error occurs. On success,
> + * this function returns the number of IRQs actually allocated. Since
> + * MSIs are required to be a power of two, the number of IRQs allocated
> + * may be rounded up to the next power of two (if the number requested is
> + * not a power of two). Fewer IRQs than requested may be allocated if the
> + * system does not have the resources for the full number.
> *
> - * Setup the MSI capability structure of device function with
> - * a single MSI irq upon its software driver call to request for
> - * MSI mode enabled on its hardware device function. A return of zero
> - * indicates the successful setup of an entry zero with the new MSI
> - * irq or non-zero for otherwise.
> + * If successful, the @pdev's irq member will be updated to the lowest new
> + * IRQ allocated; the other IRQs allocated to this device will be consecutive.
> **/
> -int pci_enable_msi(struct pci_dev* dev)
> +int pci_enable_msi_block(struct pci_dev *pdev, unsigned int nr_irqs)
> {
> int status;
>
> - status = pci_msi_check_device(dev, 1, PCI_CAP_ID_MSI);
> + /* MSI only supports up to 32 interrupts */
> + if (nr_irqs > 32)
> + return 32;
> +
> + status = pci_msi_check_device(pdev, nr_irqs, PCI_CAP_ID_MSI);
> if (status)
> return status;
>
> - WARN_ON(!!dev->msi_enabled);
> + WARN_ON(!!pdev->msi_enabled);
>
> - /* Check whether driver already requested for MSI-X irqs */
> - if (dev->msix_enabled) {
> + /* Check whether driver already requested MSI-X irqs */
> + if (pdev->msix_enabled) {
> printk(KERN_INFO "PCI: %s: Can't enable MSI. "
> "Device already has MSI-X enabled\n",
> - pci_name(dev));
> + pci_name(pdev));
> return -EINVAL;
> }
> - status = msi_capability_init(dev);
> +
> + status = msi_capability_init(pdev, nr_irqs);
> return status;
> }
> -EXPORT_SYMBOL(pci_enable_msi);
> +EXPORT_SYMBOL(pci_enable_msi_block);
>
> void pci_msi_shutdown(struct pci_dev* dev)
> {
> @@ -621,26 +648,30 @@ EXPORT_SYMBOL(pci_disable_msi);
>
> static int msi_free_irqs(struct pci_dev* dev)
> {
> - struct msi_desc *entry, *tmp;
> + int i, nvec = 1;
> + struct msi_desc *desc, *tmp;
>
> - list_for_each_entry(entry, &dev->msi_list, list) {
> - if (entry->irq)
> - BUG_ON(irq_has_action(entry->irq));
> + list_for_each_entry(desc, &dev->msi_list, list) {
> + nvec = 1 << desc->msi_attrib.multiple;
> + if (!desc->irq)
> + continue;
> + for (i = 0; i < nvec; i++)
> + BUG_ON(irq_has_action(desc->irq + i));
> }
>
> - arch_teardown_msi_irqs(dev);
> + arch_teardown_msi_irqs(dev, nvec);
>
> - list_for_each_entry_safe(entry, tmp, &dev->msi_list, list) {
> - if (entry->msi_attrib._type == MSIX_ATTRIB) {
> - writel(1, entry->mask_base + entry->msi_attrib.entry_nr
> + list_for_each_entry_safe(desc, tmp, &dev->msi_list, list) {
> + if (desc->msi_attrib._type == MSIX_ATTRIB) {
> + writel(1, desc->mask_base + desc->msi_attrib.entry_nr
> * PCI_MSIX_ENTRY_SIZE
> + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET);
>
> - if (list_is_last(&entry->list, &dev->msi_list))
> - iounmap(entry->mask_base);
> + if (list_is_last(&desc->list, &dev->msi_list))
> + iounmap(desc->mask_base);
> }
> - list_del(&entry->list);
> - kfree(entry);
> + list_del(&desc->list);
> + kfree(desc);
> }
>
> return 0;
> diff --git a/include/linux/msi.h b/include/linux/msi.h
> index d322148..4731fe7 100644
> --- a/include/linux/msi.h
> +++ b/include/linux/msi.h
> @@ -45,9 +45,10 @@ struct msi_desc {
> * The arch hook for setup up msi irqs
> */
> int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc);
> +int arch_setup_msi_block(struct pci_dev *dev, struct msi_desc *desc, int nvec);
> void arch_teardown_msi_irq(unsigned int irq);
> extern int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
> -extern void arch_teardown_msi_irqs(struct pci_dev *dev);
> +extern void arch_teardown_msi_irqs(struct pci_dev *dev, int nvec);
> extern int arch_msi_check_device(struct pci_dev* dev, int nvec, int type);
>
>
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index d18b1dd..f7ca7f8 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -699,7 +699,7 @@ struct msix_entry {
>
>
> #ifndef CONFIG_PCI_MSI
> -static inline int pci_enable_msi(struct pci_dev *dev)
> +static inline int pci_enable_msi_block(struct pci_dev *dev, unsigned int count)
> {
> return -1;
> }
> @@ -726,7 +726,7 @@ static inline void msi_remove_pci_irq_vectors(struct pci_dev *dev)
> static inline void pci_restore_msi_state(struct pci_dev *dev)
> { }
> #else
> -extern int pci_enable_msi(struct pci_dev *dev);
> +extern int pci_enable_msi_block(struct pci_dev *dev, unsigned int count);
> extern void pci_msi_shutdown(struct pci_dev *dev);
> extern void pci_disable_msi(struct pci_dev *dev);
> extern int pci_enable_msix(struct pci_dev *dev,
> @@ -737,6 +737,8 @@ extern void msi_remove_pci_irq_vectors(struct pci_dev *dev);
> extern void pci_restore_msi_state(struct pci_dev *dev);
> #endif
>
> +#define pci_enable_msi(pdev) pci_enable_msi_block(pdev, 1)
> +
> #ifdef CONFIG_HT_IRQ
> /* The functions a driver should call */
> int ht_create_irq(struct pci_dev *dev, int idx);
--
Michael Ellerman
OzLabs, IBM Australia Development Lab
wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)
We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
next prev parent reply other threads:[~2008-07-07 2:05 UTC|newest]
Thread overview: 43+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-07-03 2:44 Multiple MSI Matthew Wilcox
2008-07-03 3:24 ` Benjamin Herrenschmidt
2008-07-03 3:59 ` Matthew Wilcox
2008-07-03 4:41 ` Benjamin Herrenschmidt
2008-07-03 6:44 ` Michael Ellerman
2008-07-03 9:10 ` Arnd Bergmann
2008-07-03 9:17 ` Benjamin Herrenschmidt
2008-07-03 11:31 ` Matthew Wilcox
2008-07-03 11:41 ` Benjamin Herrenschmidt
2008-07-04 1:52 ` Michael Ellerman
2008-07-04 8:08 ` Alan Cox
2008-07-03 11:34 ` Matthew Wilcox
2008-07-07 16:17 ` Grant Grundler
2008-07-07 16:39 ` Matthew Wilcox
2008-07-07 16:51 ` Grant Grundler
2008-07-07 23:06 ` Benjamin Herrenschmidt
2008-07-10 0:55 ` Michael Ellerman
2008-07-05 13:27 ` Matthew Wilcox
2008-07-05 13:34 ` [PATCH 1/4] PCI MSI: Store the number of messages in the msi_desc Matthew Wilcox
2008-07-07 2:05 ` Michael Ellerman
2008-07-07 2:41 ` Matthew Wilcox
2008-07-07 3:26 ` Benjamin Herrenschmidt
2008-07-07 3:48 ` Michael Ellerman
2008-07-07 12:04 ` Matthew Wilcox
2008-07-07 16:02 ` Grant Grundler
2008-07-07 16:19 ` Matthew Wilcox
2008-07-10 1:32 ` Michael Ellerman
2008-07-10 1:35 ` Matthew Wilcox
2008-07-05 13:34 ` [PATCH 2/4] PCI: Support multiple MSI Matthew Wilcox
2008-07-07 2:05 ` Michael Ellerman [this message]
2008-07-07 2:45 ` Matthew Wilcox
2008-07-07 3:56 ` Michael Ellerman
2008-07-07 11:31 ` Matthew Wilcox
2008-07-10 1:32 ` Michael Ellerman
2008-07-10 1:43 ` Matthew Wilcox
2008-07-10 4:00 ` Michael Ellerman
2008-07-05 13:34 ` [PATCH 3/4] AHCI: Request multiple MSIs Matthew Wilcox
2008-07-07 16:45 ` Grant Grundler
2008-07-07 17:48 ` Matthew Wilcox
2008-07-20 7:49 ` Grant Grundler
2008-07-05 13:34 ` [PATCH 4/4] x86-64: Support for " Matthew Wilcox
2008-07-05 13:43 ` Multiple MSI Matthew Wilcox
2008-07-05 22:38 ` Matthew Wilcox
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1215396326.19157.15.camel@localhost \
--to=michael@ellerman.id.au \
--cc=Martine.Silbermann@hp.com \
--cc=benh@kernel.crashing.org \
--cc=dan.j.williams@intel.com \
--cc=davem@davemloft.net \
--cc=kaneshige.kenji@jp.fujitsu.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=matthew@wil.cx \
--cc=mingo@elte.hu \
--cc=tglx@linutronix.de \
--cc=willy@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.