All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alex Williamson <alex.williamson@redhat.com>
To: Piotr Gregor <piotrgregor@rsyncme.org>
Cc: Bjorn Helgaas <bhelgaas@google.com>,
	"Michael S. Tsirkin" <mst@redhat.com>,
	GregKroah-Hartman <gregkh@linuxfoundation.org>,
	Neo Jia <cjia@nvidia.com>, Kirti Wankhede <kwankhede@nvidia.com>,
	Vlad Tsyrklevich <vlad@tsyrklevich.net>,
	Arvind Yadav <arvind.yadav.cs@gmail.com>,
	Yongji Xie <xyjxie@linux.vnet.ibm.com>,
	linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org,
	kvm@vger.kernel.org
Subject: Re: [PATCH] PCI: Move test of INTx masking to pci_setup_device
Date: Thu, 25 May 2017 16:26:02 -0600	[thread overview]
Message-ID: <20170525162602.4094caa0@w520.home> (raw)
In-Reply-To: <20170525213222.GA27295@westernst>

On Thu, 25 May 2017 22:32:25 +0100
Piotr Gregor <piotrgregor@rsyncme.org> wrote:

> The test for INTx masking via config space command performed
> in pci_intx_mask_supported should be performed before PCI device
> can be used. This is to avoid reading/writing of PCI_COMMAND_INTX_DISABLE
> register which may collide with MSI/MSI-X interrupts.
> 
> This patch moves test performed in pci_intx_mask_supported
> to __pci_intx_mask_supported and unexports the former.
> The result of INTx masking test is saved in broken_intx_masking
> field of struct pci_dev (which now has extended meaning: if true
> then the test has failed or the feature is not supported).
> The __pci_intx_mask_supported test is moved to pci_setup_device.
> The result can be queried at any time later from the pci_dev
> using same interface as before (though whith changed implementation)
> 
> static inline bool pci_intx_mask_supported(struct pci_dev *pdev)
> {
>         /*
>          * INTx masking is supported if device passed INTx test
>          * and it's INTx masking feature works properly.
>          */
>         return !pdev->broken_intx_masking;
> }
> 
> so current users of pci_intx_mask_supported: uio and vfio, keep
> their code unchanged.
> 
> Signed-off-by: Piotr Gregor <piotrgregor@rsyncme.org>
> ---
>  drivers/pci/pci.c   | 45 ++++++++++++++++++++++++---------------------
>  drivers/pci/probe.c |  3 +++
>  include/linux/pci.h | 13 +++++++++++--
>  3 files changed, 38 insertions(+), 23 deletions(-)
> 
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index b01bd5b..8d5628e 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -3709,44 +3709,47 @@ void pci_intx(struct pci_dev *pdev, int enable)
>  EXPORT_SYMBOL_GPL(pci_intx);
>  
>  /**
> - * pci_intx_mask_supported - probe for INTx masking support
> + * pci_intx_mask_supported - probe for INTx masking support in pci_setup_device
>   * @dev: the PCI device to operate on
>   *
> - * Check if the device dev support INTx masking via the config space
> - * command word.
> + * Check if the device dev supports INTx masking via the config space
> + * command word. Executed when PCI device is setup. Result is saved
> + * in broken_intx_masking field of pci_dev and can be checked
> + * with pci_intx_mask_supported after PCI device has been setup
> + * (avoids testing of PCI_COMMAND_INTX_DISABLE register at runtime).
>   */
> -bool pci_intx_mask_supported(struct pci_dev *dev)
> +bool __pci_intx_mask_supported(struct pci_dev *dev)
>  {
> -	bool mask_supported = false;
> -	u16 orig, new;
> +	u16 orig, toggle, new;
>  
> +	/*
> +	 * If device doesn't support this feature though it could pass the test.
> +	 */
>  	if (dev->broken_intx_masking)
>  		return false;
>  
>  	pci_cfg_access_lock(dev);
>  
> +	/*
> +	 * Perform the test.
> +	 */
>  	pci_read_config_word(dev, PCI_COMMAND, &orig);
> -	pci_write_config_word(dev, PCI_COMMAND,
> -			      orig ^ PCI_COMMAND_INTX_DISABLE);
> +	toggle = orig ^ PCI_COMMAND_INTX_DISABLE;
> +	pci_write_config_word(dev, PCI_COMMAND, toggle);
>  	pci_read_config_word(dev, PCI_COMMAND, &new);
>  
>  	/*
> -	 * There's no way to protect against hardware bugs or detect them
> -	 * reliably, but as long as we know what the value should be, let's
> -	 * go ahead and check it.
> +	 * Restore initial state.
>  	 */
> -	if ((new ^ orig) & ~PCI_COMMAND_INTX_DISABLE) {
> -		dev_err(&dev->dev, "Command register changed from 0x%x to 0x%x: driver or hardware bug?\n",
> -			orig, new);
> -	} else if ((new ^ orig) & PCI_COMMAND_INTX_DISABLE) {
> -		mask_supported = true;
> -		pci_write_config_word(dev, PCI_COMMAND, orig);
> -	}
> +	pci_write_config_word(dev, PCI_COMMAND, orig);
>  
>  	pci_cfg_access_unlock(dev);
> -	return mask_supported;
> +
> +	if (new == toggle)
> +		return true;
> +
> +	return false;
>  }
> -EXPORT_SYMBOL_GPL(pci_intx_mask_supported);
>  
>  static bool pci_check_and_set_intx_mask(struct pci_dev *dev, bool mask)
>  {
> @@ -3798,7 +3801,7 @@ static bool pci_check_and_set_intx_mask(struct pci_dev *dev, bool mask)
>   * @dev: the PCI device to operate on
>   *
>   * Check if the device dev has its INTx line asserted, mask it and
> - * return true in that case. False is returned if not interrupt was
> + * return true in that case. False is returned if no interrupt was
>   * pending.
>   */
>  bool pci_check_and_mask_intx(struct pci_dev *dev)
> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
> index 19c8950..b343b14 100644
> --- a/drivers/pci/probe.c
> +++ b/drivers/pci/probe.c
> @@ -1399,6 +1399,9 @@ int pci_setup_device(struct pci_dev *dev)
>  		}
>  	}
>  
> +	if (!dev->broken_intx_masking && !__pci_intx_mask_supported(dev))
> +		dev->broken_intx_masking = 1;

This is still harder than it needs to be, we could just name the
function pci_test_intx_masking() and let it set broken_intx_masking
directly, returning immediately if already set via a quirk.  Also,
shouldn't we move the test function to this file and make it static?
Thanks,

Alex

> +
>  	switch (dev->hdr_type) {		    /* header type */
>  	case PCI_HEADER_TYPE_NORMAL:		    /* standard header */
>  		if (class == PCI_CLASS_BRIDGE_PCI)
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 33c2b0b..58c6fe3 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -366,7 +366,7 @@ struct pci_dev {
>  	unsigned int	is_thunderbolt:1; /* Thunderbolt controller */
>  	unsigned int    __aer_firmware_first_valid:1;
>  	unsigned int	__aer_firmware_first:1;
> -	unsigned int	broken_intx_masking:1;
> +	unsigned int	broken_intx_masking:1; /* INTx masking can't be used */
>  	unsigned int	io_window_1k:1;	/* Intel P2P bridge 1K I/O windows */
>  	unsigned int	irq_managed:1;
>  	unsigned int	has_secondary_link:1;
> @@ -1003,6 +1003,15 @@ int __must_check pci_reenable_device(struct pci_dev *);
>  int __must_check pcim_enable_device(struct pci_dev *pdev);
>  void pcim_pin_device(struct pci_dev *pdev);
>  
> +static inline bool pci_intx_mask_supported(struct pci_dev *pdev)
> +{
> +	/*
> +	 * INTx masking is supported if device passed INTx test and it's INTx
> +	 * masking feature works properly.
> +	 */
> +	return !pdev->broken_intx_masking;
> +}
> +
>  static inline int pci_is_enabled(struct pci_dev *pdev)
>  {
>  	return (atomic_read(&pdev->enable_cnt) > 0);
> @@ -1026,7 +1035,7 @@ int __must_check pci_set_mwi(struct pci_dev *dev);
>  int pci_try_set_mwi(struct pci_dev *dev);
>  void pci_clear_mwi(struct pci_dev *dev);
>  void pci_intx(struct pci_dev *dev, int enable);
> -bool pci_intx_mask_supported(struct pci_dev *dev);
> +bool __pci_intx_mask_supported(struct pci_dev *dev);
>  bool pci_check_and_mask_intx(struct pci_dev *dev);
>  bool pci_check_and_unmask_intx(struct pci_dev *dev);
>  int pci_wait_for_pending(struct pci_dev *dev, int pos, u16 mask);

  reply	other threads:[~2017-05-25 22:26 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-05-25 21:32 [PATCH] PCI: Move test of INTx masking to pci_setup_device Piotr Gregor
2017-05-25 22:26 ` Alex Williamson [this message]
  -- strict thread matches above, loose matches on Subject: below --
2017-05-26 21:02 Piotr Gregor
2017-05-26 21:31 ` Alex Williamson
2017-05-29  0:05 ` Michael S. Tsirkin
2017-06-16 22:54 ` Bjorn Helgaas
2017-06-17 17:45   ` Piotr Gregor
2017-06-18  1:14     ` Bjorn Helgaas
2017-06-19  0:26       ` Piotr Gregor
2017-05-25 18:13 Piotr Gregor
2017-05-25 18:22 ` Michael S. Tsirkin
2017-05-25 18:38   ` Alex Williamson
2017-05-25 20:17     ` Piotr Gregor

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=20170525162602.4094caa0@w520.home \
    --to=alex.williamson@redhat.com \
    --cc=arvind.yadav.cs@gmail.com \
    --cc=bhelgaas@google.com \
    --cc=cjia@nvidia.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=kvm@vger.kernel.org \
    --cc=kwankhede@nvidia.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=mst@redhat.com \
    --cc=piotrgregor@rsyncme.org \
    --cc=vlad@tsyrklevich.net \
    --cc=xyjxie@linux.vnet.ibm.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.