Re: [PATCH] pci: Handle the case when PCI_COMMAND register hasn't changed in INTx masking test

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

 



Would the pci_setup_device() be a good place to move this check into?

On Tue, May 23, 2017 at 5:39 PM, Alex Williamson
<alex.williamson@xxxxxxxxxx> wrote:
> On Tue, 23 May 2017 11:19:29 -0500
> Bjorn Helgaas <helgaas@xxxxxxxxxx> wrote:
>
>> [+cc Alex]
>>
>> On Mon, May 22, 2017 at 06:38:20PM -0500, Bjorn Helgaas wrote:
>> > Hi Piotr,
>> >
>> > On Wed, May 10, 2017 at 01:30:01PM +0100, Piotr Gregor wrote:
>> > > The check for interrupt masking support is done by reading
>> > > the PCI_COMMAND config word
>> > >
>> > >   pci_read_config_word(dev, PCI_COMMAND, &orig);
>> > >
>> > > then flipping the PCI_COMMAND_INTX_DISABLE bit and writing result back
>> > >
>> > >   pci_write_config_word(dev, PCI_COMMAND,
>> > >           orig ^ PCI_COMMAND_INTX_DISABLE);
>> > >
>> > > The expected result is that following read of the PCI_COMMAND
>> > >
>> > >   pci_read_config_word(dev, PCI_COMMAND, &new);
>> > >
>> > > returns PCI_COMMAND with only PCI_COMMAND_INTX_DISABLE bit changed.
>> > >
>> > > There are two possible outcomes:
>> > >
>> > >   1.      Command is the same (hasn't changed)
>> > >   2.      Commmand has changed
>> > >
>> > > And the second of them may be decoupled to:
>> > >
>> > >   2.1     Command changed only for PCI_COMMAND_INTX_DISABLE bit
>> > >           (hasn't changed for bits different than PCI_COMMAND_INTX_DISABLE)
>> > >   2.2     Command changed for bit(s) different than PCI_COMMAND_INTX_DISABLE bit
>> > >           (and maybe for PCI_COMMAND_INTX_DISABLE too)
>> > >
>> > > The 2.1 is expected result and anything else is error.
>> > > The 2.2 outcome is handled by pci_intx_mask_supported by printing
>> > > appropriate message to the log, but outcome 1 is not handled.
>> > >
>> > > Log the message about command not being changed at all.
>> > >
>> > > Signed-off-by: Piotr Gregor <piotrgregor@xxxxxxxxxxx>
>> > > ---
>> > >  drivers/pci/pci.c | 14 ++++++++++++--
>> > >  1 file changed, 12 insertions(+), 2 deletions(-)
>> > >
>> > > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
>> > > index b01bd5b..67a611e 100644
>> > > --- a/drivers/pci/pci.c
>> > > +++ b/drivers/pci/pci.c
>> > > @@ -3712,7 +3712,7 @@ EXPORT_SYMBOL_GPL(pci_intx);
>> > >   * pci_intx_mask_supported - probe for INTx masking support
>> > >   * @dev: the PCI device to operate on
>> > >   *
>> > > - * Check if the device dev support INTx masking via the config space
>> > > + * Check if the device dev supports INTx masking via the config space
>> > >   * command word.
>> > >   */
>> > >  bool pci_intx_mask_supported(struct pci_dev *dev)
>> > > @@ -3736,11 +3736,21 @@ bool pci_intx_mask_supported(struct pci_dev *dev)
>> > >    * go ahead and check it.
>> > >    */
>> > >   if ((new ^ orig) & ~PCI_COMMAND_INTX_DISABLE) {
>> > > +         /*
>> > > +          * If anything else than PCI_COMMAND_INTX_DISABLE bit has
>> > > +          * changed (and maybe PCI_COMMAND_INTX_DISABLE too)
>> > > +          */
>> > >           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) {
>> > > +         /*
>> > > +          * OK. Only PCI_COMMAND_INTX_DISABLE bit has changed
>> > > +          */
>> > >           mask_supported = true;
>> > >           pci_write_config_word(dev, PCI_COMMAND, orig);
>> > > + } else {
>> > > +         dev_err(&dev->dev, "Command register hasn't changed when written from 0x%x to 0x%x: driver or hardware bug?\n",
>> > > +                 orig, new);
>> >
>> > Bit 10 was a reserved bit in PCI r2.2 and was defined as
>> > PCI_COMMAND_INTX_DISABLE in r2.3 of the spec, so I don't think we
>> > should treat this as an error.
>
> Agreed, the only reason I can think that we'd ever want to point this
> out as a hardware bug would be if the device is PCI-express or if we
> can find other evidence in config space that the device should be
> compliant to the PCI 2.3 spec.  Also, dev_err is sort of justified in
> the original error case because something unexpected happened.  The
> register is being poked from somewhere else or changed spontaneously.
> Not supporting INTx masking is a completely valid state for hardware,
> so I'd at best consider it a dev_dbg level test.
>
>>
>> If we make a change here, I think it should be simplified to look like
>> this:
>>
>>   pci_cfg_access_lock(dev);
>>
>>   pci_read_config_word(dev, PCI_COMMAND, &orig);
>>   toggle = orig ^ PCI_COMMAND_INTX_DISABLE;
>>   pci_write_config_word(dev, PCI_COMMAND, toggle);
>>   pci_read_config_word(dev, PCI_COMMAND, &new);
>>   pci_write_config_word(dev, PCI_COMMAND, orig);
>>
>>   pci_cfg_access_unlock(dev);
>>
>>   if (new == toggle)
>>     return true;
>>
>>   return false;
>>
>> I don't really see the value in cluttering the code to check for
>> things that "can't happen."  There's an infinite amount of that sort
>> of stuff.  If we know about possible issues, that's one thing, but
>> this seems like just looking for trouble.
>
> I can imagine it being useful to allow a user to have some visibility
> to this property for a device, but a printk doesn't feel like a useful
> way to do that.  I don't know if it's worth a sysfs attribute though.
>
>> It makes me a little nervous to have this interface that toggles
>> PCI_COMMAND_INTX_DISABLE at run-time.  This could be called after a
>> driver has set up interrupts, and I think there are some interactions
>> between INTx and MSI/MSI-X that might cause unexpected things to
>> happen if we toggle PCI_COMMAND_INTX_DISABLE.
>>
>> I'd rather have the core check it once during enumeration (before we
>> give it to a driver and before any interrupts are configured) and save
>> the result in struct pci_dev.
>
> I think that would be fine, the only users are uio and vfio, the former
> testing it in the probe function, the latter testing it before giving
> the user access to the device (and therefore before interrupts are
> configured).  Thanks,
>
> Alex
>
>>
>> > >   }
>> > >
>> > >   pci_cfg_access_unlock(dev);
>> > > @@ -3798,7 +3808,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 interrupt wasn't
>> > >   * pending.
>>
>> We should definitely fix this typo.  Maybe "if no interrupt was
>> pending"?
>>
>> > >   */
>> > >  bool pci_check_and_mask_intx(struct pci_dev *dev)
>> > > --
>> > > 2.1.4
>> > >
>



[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