From: Bjorn Helgaas <bhelgaas@google.com>
To: Alexander Gordeev <agordeev@redhat.com>
Cc: linux-kernel@vger.kernel.org, linux-mips@linux-mips.org,
linuxppc-dev@lists.ozlabs.org, linux-s390@vger.kernel.org,
x86@kernel.org, linux-pci@vger.kernel.org
Subject: Re: [PATCH 2/2] PCI/MSI: Phase out pci_enable_msi_block()
Date: Wed, 30 Apr 2014 17:49:33 -0600 [thread overview]
Message-ID: <20140430234933.GB31315@google.com> (raw)
In-Reply-To: <20140414132834.GA9164@dhcp-26-207.brq.redhat.com>
On Mon, Apr 14, 2014 at 03:28:35PM +0200, Alexander Gordeev wrote:
> There are no users of pci_enable_msi_block() function have
> left. Obsolete it in favor of pci_enable_msi_range() and
> pci_enable_msi_exact() functions.
I mistakenly assumed this would have to wait because I thought there were
other pci_enable_msi_block() users that wouldn't be removed until the v3.16
merge window. But I think I was wrong: I put your GenWQE patch in my tree,
and I think that was the last use, so I can just add this patch on top.
But I need a little help understanding the changelog:
> Up until now, when enabling MSI mode for a device a single
> successful call to arch_msi_check_device() was followed by
> a single call to arch_setup_msi_irqs() function.
I understand this part; the following two paths call
arch_msi_check_device() once and then arch_setup_msi_irqs() once:
pci_enable_msi_block
pci_msi_check_device
arch_msi_check_device
msi_capability_init
arch_setup_msi_irqs
pci_enable_msix
pci_msi_check_device
arch_msi_check_device
msix_capability_init
arch_setup_msi_irqs
> Yet, if arch_msi_check_device() returned success we should be
> able to call arch_setup_msi_irqs() multiple times - while it
> returns a number of MSI vectors that could have been allocated
> (a third state).
I don't know what you mean by "a third state."
Previously we only called arch_msi_check_device() once. After your patch,
pci_enable_msi_range() can call it several times. The only non-trivial
implementation of arch_msi_check_device() is in powerpc, and all the
ppc_md.msi_check_device() possibilities look safe to call multiple times.
After your patch, the pci_enable_msi_range() path can also call
arch_setup_msi_irqs() several times. I don't see a problem with that --
even if the first call succeeds and allocates something, then a subsequent
call fails, I assume the allocations will be cleaned up when
msi_capability_init() calls free_msi_irqs().
> This update makes use of the assumption described above. It
> could have broke things had the architectures done any pre-
> allocations or switch to some state in a call to function
> arch_msi_check_device(). But because arch_msi_check_device()
> is expected stateless and MSI resources are allocated in a
> follow-up call to arch_setup_msi_irqs() we should be fine.
I guess you mean that your patch assumes arch_msi_check_device() is
stateless. That looks like a safe assumption to me.
arch_setup_msi_irqs() is clearly not stateless, but I assume
free_msi_irqs() is enough to clean up any state if we fail.
Bjorn
> Signed-off-by: Alexander Gordeev <agordeev@redhat.com>
> Cc: linux-mips@linux-mips.org
> Cc: linuxppc-dev@lists.ozlabs.org
> Cc: linux-s390@vger.kernel.org
> Cc: x86@kernel.org
> Cc: linux-pci@vger.kernel.org
> ---
> drivers/pci/msi.c | 79 +++++++++++++++++++++-----------------------------
> include/linux/pci.h | 5 +--
> 2 files changed, 34 insertions(+), 50 deletions(-)
>
> diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
> index 955ab79..fc669ab 100644
> --- a/drivers/pci/msi.c
> +++ b/drivers/pci/msi.c
> @@ -883,50 +883,6 @@ int pci_msi_vec_count(struct pci_dev *dev)
> }
> EXPORT_SYMBOL(pci_msi_vec_count);
>
> -/**
> - * pci_enable_msi_block - configure device's MSI capability structure
> - * @dev: device to configure
> - * @nvec: number of interrupts to configure
> - *
> - * Allocate IRQs for a device with the MSI capability.
> - * This function returns a negative errno if an error occurs. If it
> - * is unable to allocate the number of interrupts requested, it returns
> - * the number of interrupts it might be able to allocate. If it successfully
> - * allocates at least the number of interrupts requested, it returns 0 and
> - * updates the @dev's irq member to the lowest new interrupt number; the
> - * other interrupt numbers allocated to this device are consecutive.
> - */
> -int pci_enable_msi_block(struct pci_dev *dev, int nvec)
> -{
> - int status, maxvec;
> -
> - if (dev->current_state != PCI_D0)
> - return -EINVAL;
> -
> - maxvec = pci_msi_vec_count(dev);
> - if (maxvec < 0)
> - return maxvec;
> - if (nvec > maxvec)
> - return maxvec;
> -
> - status = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSI);
> - if (status)
> - return status;
> -
> - WARN_ON(!!dev->msi_enabled);
> -
> - /* Check whether driver already requested MSI-X irqs */
> - if (dev->msix_enabled) {
> - dev_info(&dev->dev, "can't enable MSI "
> - "(MSI-X already enabled)\n");
> - return -EINVAL;
> - }
> -
> - status = msi_capability_init(dev, nvec);
> - return status;
> -}
> -EXPORT_SYMBOL(pci_enable_msi_block);
> -
> void pci_msi_shutdown(struct pci_dev *dev)
> {
> struct msi_desc *desc;
> @@ -1132,14 +1088,45 @@ void pci_msi_init_pci_dev(struct pci_dev *dev)
> **/
> int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec)
> {
> - int nvec = maxvec;
> + int nvec;
> int rc;
>
> + if (dev->current_state != PCI_D0)
> + return -EINVAL;
> +
> + WARN_ON(!!dev->msi_enabled);
> +
> + /* Check whether driver already requested MSI-X irqs */
> + if (dev->msix_enabled) {
> + dev_info(&dev->dev,
> + "can't enable MSI (MSI-X already enabled)\n");
> + return -EINVAL;
> + }
> +
> if (maxvec < minvec)
> return -ERANGE;
>
> + nvec = pci_msi_vec_count(dev);
> + if (nvec < 0)
> + return nvec;
> + else if (nvec < minvec)
> + return -EINVAL;
> + else if (nvec > maxvec)
> + nvec = maxvec;
> +
> + do {
> + rc = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSI);
> + if (rc < 0) {
> + return rc;
> + } else if (rc > 0) {
> + if (rc < minvec)
> + return -ENOSPC;
> + nvec = rc;
> + }
> + } while (rc);
> +
> do {
> - rc = pci_enable_msi_block(dev, nvec);
> + rc = msi_capability_init(dev, nvec);
> if (rc < 0) {
> return rc;
> } else if (rc > 0) {
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index aab57b4..499755e 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -1158,7 +1158,6 @@ struct msix_entry {
>
> #ifdef CONFIG_PCI_MSI
> int pci_msi_vec_count(struct pci_dev *dev);
> -int pci_enable_msi_block(struct pci_dev *dev, int nvec);
> void pci_msi_shutdown(struct pci_dev *dev);
> void pci_disable_msi(struct pci_dev *dev);
> int pci_msix_vec_count(struct pci_dev *dev);
> @@ -1188,8 +1187,6 @@ static inline int pci_enable_msix_exact(struct pci_dev *dev,
> }
> #else
> static inline int pci_msi_vec_count(struct pci_dev *dev) { return -ENOSYS; }
> -static inline int pci_enable_msi_block(struct pci_dev *dev, int nvec)
> -{ return -ENOSYS; }
> static inline void pci_msi_shutdown(struct pci_dev *dev) { }
> static inline void pci_disable_msi(struct pci_dev *dev) { }
> static inline int pci_msix_vec_count(struct pci_dev *dev) { return -ENOSYS; }
> @@ -1244,7 +1241,7 @@ static inline void pcie_set_ecrc_checking(struct pci_dev *dev) { }
> static inline void pcie_ecrc_get_policy(char *str) { }
> #endif
>
> -#define pci_enable_msi(pdev) pci_enable_msi_block(pdev, 1)
> +#define pci_enable_msi(pdev) pci_enable_msi_exact(pdev, 1)
>
> #ifdef CONFIG_HT_IRQ
> /* The functions a driver should call */
> --
> 1.7.7.6
>
> --
> Regards,
> Alexander Gordeev
> agordeev@redhat.com
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
WARNING: multiple messages have this Message-ID (diff)
From: Bjorn Helgaas <bhelgaas@google.com>
To: Alexander Gordeev <agordeev@redhat.com>
Cc: linux-mips@linux-mips.org, linux-s390@vger.kernel.org,
linux-pci@vger.kernel.org, x86@kernel.org,
linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org
Subject: Re: [PATCH 2/2] PCI/MSI: Phase out pci_enable_msi_block()
Date: Wed, 30 Apr 2014 17:49:33 -0600 [thread overview]
Message-ID: <20140430234933.GB31315@google.com> (raw)
In-Reply-To: <20140414132834.GA9164@dhcp-26-207.brq.redhat.com>
On Mon, Apr 14, 2014 at 03:28:35PM +0200, Alexander Gordeev wrote:
> There are no users of pci_enable_msi_block() function have
> left. Obsolete it in favor of pci_enable_msi_range() and
> pci_enable_msi_exact() functions.
I mistakenly assumed this would have to wait because I thought there were
other pci_enable_msi_block() users that wouldn't be removed until the v3.16
merge window. But I think I was wrong: I put your GenWQE patch in my tree,
and I think that was the last use, so I can just add this patch on top.
But I need a little help understanding the changelog:
> Up until now, when enabling MSI mode for a device a single
> successful call to arch_msi_check_device() was followed by
> a single call to arch_setup_msi_irqs() function.
I understand this part; the following two paths call
arch_msi_check_device() once and then arch_setup_msi_irqs() once:
pci_enable_msi_block
pci_msi_check_device
arch_msi_check_device
msi_capability_init
arch_setup_msi_irqs
pci_enable_msix
pci_msi_check_device
arch_msi_check_device
msix_capability_init
arch_setup_msi_irqs
> Yet, if arch_msi_check_device() returned success we should be
> able to call arch_setup_msi_irqs() multiple times - while it
> returns a number of MSI vectors that could have been allocated
> (a third state).
I don't know what you mean by "a third state."
Previously we only called arch_msi_check_device() once. After your patch,
pci_enable_msi_range() can call it several times. The only non-trivial
implementation of arch_msi_check_device() is in powerpc, and all the
ppc_md.msi_check_device() possibilities look safe to call multiple times.
After your patch, the pci_enable_msi_range() path can also call
arch_setup_msi_irqs() several times. I don't see a problem with that --
even if the first call succeeds and allocates something, then a subsequent
call fails, I assume the allocations will be cleaned up when
msi_capability_init() calls free_msi_irqs().
> This update makes use of the assumption described above. It
> could have broke things had the architectures done any pre-
> allocations or switch to some state in a call to function
> arch_msi_check_device(). But because arch_msi_check_device()
> is expected stateless and MSI resources are allocated in a
> follow-up call to arch_setup_msi_irqs() we should be fine.
I guess you mean that your patch assumes arch_msi_check_device() is
stateless. That looks like a safe assumption to me.
arch_setup_msi_irqs() is clearly not stateless, but I assume
free_msi_irqs() is enough to clean up any state if we fail.
Bjorn
> Signed-off-by: Alexander Gordeev <agordeev@redhat.com>
> Cc: linux-mips@linux-mips.org
> Cc: linuxppc-dev@lists.ozlabs.org
> Cc: linux-s390@vger.kernel.org
> Cc: x86@kernel.org
> Cc: linux-pci@vger.kernel.org
> ---
> drivers/pci/msi.c | 79 +++++++++++++++++++++-----------------------------
> include/linux/pci.h | 5 +--
> 2 files changed, 34 insertions(+), 50 deletions(-)
>
> diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
> index 955ab79..fc669ab 100644
> --- a/drivers/pci/msi.c
> +++ b/drivers/pci/msi.c
> @@ -883,50 +883,6 @@ int pci_msi_vec_count(struct pci_dev *dev)
> }
> EXPORT_SYMBOL(pci_msi_vec_count);
>
> -/**
> - * pci_enable_msi_block - configure device's MSI capability structure
> - * @dev: device to configure
> - * @nvec: number of interrupts to configure
> - *
> - * Allocate IRQs for a device with the MSI capability.
> - * This function returns a negative errno if an error occurs. If it
> - * is unable to allocate the number of interrupts requested, it returns
> - * the number of interrupts it might be able to allocate. If it successfully
> - * allocates at least the number of interrupts requested, it returns 0 and
> - * updates the @dev's irq member to the lowest new interrupt number; the
> - * other interrupt numbers allocated to this device are consecutive.
> - */
> -int pci_enable_msi_block(struct pci_dev *dev, int nvec)
> -{
> - int status, maxvec;
> -
> - if (dev->current_state != PCI_D0)
> - return -EINVAL;
> -
> - maxvec = pci_msi_vec_count(dev);
> - if (maxvec < 0)
> - return maxvec;
> - if (nvec > maxvec)
> - return maxvec;
> -
> - status = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSI);
> - if (status)
> - return status;
> -
> - WARN_ON(!!dev->msi_enabled);
> -
> - /* Check whether driver already requested MSI-X irqs */
> - if (dev->msix_enabled) {
> - dev_info(&dev->dev, "can't enable MSI "
> - "(MSI-X already enabled)\n");
> - return -EINVAL;
> - }
> -
> - status = msi_capability_init(dev, nvec);
> - return status;
> -}
> -EXPORT_SYMBOL(pci_enable_msi_block);
> -
> void pci_msi_shutdown(struct pci_dev *dev)
> {
> struct msi_desc *desc;
> @@ -1132,14 +1088,45 @@ void pci_msi_init_pci_dev(struct pci_dev *dev)
> **/
> int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec)
> {
> - int nvec = maxvec;
> + int nvec;
> int rc;
>
> + if (dev->current_state != PCI_D0)
> + return -EINVAL;
> +
> + WARN_ON(!!dev->msi_enabled);
> +
> + /* Check whether driver already requested MSI-X irqs */
> + if (dev->msix_enabled) {
> + dev_info(&dev->dev,
> + "can't enable MSI (MSI-X already enabled)\n");
> + return -EINVAL;
> + }
> +
> if (maxvec < minvec)
> return -ERANGE;
>
> + nvec = pci_msi_vec_count(dev);
> + if (nvec < 0)
> + return nvec;
> + else if (nvec < minvec)
> + return -EINVAL;
> + else if (nvec > maxvec)
> + nvec = maxvec;
> +
> + do {
> + rc = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSI);
> + if (rc < 0) {
> + return rc;
> + } else if (rc > 0) {
> + if (rc < minvec)
> + return -ENOSPC;
> + nvec = rc;
> + }
> + } while (rc);
> +
> do {
> - rc = pci_enable_msi_block(dev, nvec);
> + rc = msi_capability_init(dev, nvec);
> if (rc < 0) {
> return rc;
> } else if (rc > 0) {
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index aab57b4..499755e 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -1158,7 +1158,6 @@ struct msix_entry {
>
> #ifdef CONFIG_PCI_MSI
> int pci_msi_vec_count(struct pci_dev *dev);
> -int pci_enable_msi_block(struct pci_dev *dev, int nvec);
> void pci_msi_shutdown(struct pci_dev *dev);
> void pci_disable_msi(struct pci_dev *dev);
> int pci_msix_vec_count(struct pci_dev *dev);
> @@ -1188,8 +1187,6 @@ static inline int pci_enable_msix_exact(struct pci_dev *dev,
> }
> #else
> static inline int pci_msi_vec_count(struct pci_dev *dev) { return -ENOSYS; }
> -static inline int pci_enable_msi_block(struct pci_dev *dev, int nvec)
> -{ return -ENOSYS; }
> static inline void pci_msi_shutdown(struct pci_dev *dev) { }
> static inline void pci_disable_msi(struct pci_dev *dev) { }
> static inline int pci_msix_vec_count(struct pci_dev *dev) { return -ENOSYS; }
> @@ -1244,7 +1241,7 @@ static inline void pcie_set_ecrc_checking(struct pci_dev *dev) { }
> static inline void pcie_ecrc_get_policy(char *str) { }
> #endif
>
> -#define pci_enable_msi(pdev) pci_enable_msi_block(pdev, 1)
> +#define pci_enable_msi(pdev) pci_enable_msi_exact(pdev, 1)
>
> #ifdef CONFIG_HT_IRQ
> /* The functions a driver should call */
> --
> 1.7.7.6
>
> --
> Regards,
> Alexander Gordeev
> agordeev@redhat.com
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
next prev parent reply other threads:[~2014-04-30 23:49 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-04-14 7:14 [PATCH 0/2] Phase out pci_enable_msi_block() Alexander Gordeev
2014-04-14 7:14 ` Alexander Gordeev
2014-04-14 7:14 ` [PATCH 1/2] GenWQE: Use pci_enable_msi_exact() instead of pci_enable_msi_block() Alexander Gordeev
2014-04-14 11:54 ` Greg Kroah-Hartman
2014-04-25 18:19 ` Bjorn Helgaas
2014-04-25 18:27 ` Greg Kroah-Hartman
2014-04-14 7:14 ` [PATCH 2/2] PCI/MSI: Phase out pci_enable_msi_block() Alexander Gordeev
2014-04-14 7:14 ` Alexander Gordeev
2014-04-14 12:09 ` Alexander Gordeev
2014-04-14 12:09 ` Alexander Gordeev
2014-04-14 13:28 ` Alexander Gordeev
2014-04-14 13:28 ` Alexander Gordeev
2014-04-30 21:19 ` Alexander Gordeev
2014-04-30 21:19 ` Alexander Gordeev
2014-04-30 23:49 ` Bjorn Helgaas [this message]
2014-04-30 23:49 ` Bjorn Helgaas
2014-05-01 16:07 ` Alexander Gordeev
2014-05-01 16:07 ` Alexander Gordeev
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=20140430234933.GB31315@google.com \
--to=bhelgaas@google.com \
--cc=agordeev@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mips@linux-mips.org \
--cc=linux-pci@vger.kernel.org \
--cc=linux-s390@vger.kernel.org \
--cc=linuxppc-dev@lists.ozlabs.org \
--cc=x86@kernel.org \
/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.