Linux PCI subsystem development
 help / color / mirror / Atom feed
From: Casey Leedom <leedom@chelsio.com>
To: Bjorn Helgaas <bhelgaas@google.com>
Cc: Vipul Pandya <vipul@chelsio.com>,
	"linux-pci@vger.kernel.org" <linux-pci@vger.kernel.org>,
	tomreu@chelsio.com, divy@chelsio.com, dm@chelsio.com,
	nirranjan@chelsio.com
Subject: Re: [PATCH] pci: Enable bus master till the FLR completes
Date: Fri, 26 Jul 2013 15:53:40 -0700	[thread overview]
Message-ID: <51F2FDF4.6060706@chelsio.com> (raw)
In-Reply-To: <CAErSpo7bxZKWqdR2MCOvz4=n_pO=u59KSsHZzJMBoN8qQ+E+Dw@mail.gmail.com>

Thanks for the review comments. I'll work with Vipul to get these 
properly incorporated. Answers to your comments are inline below:


On 07/26/13 15:27, Bjorn Helgaas wrote:
> On Mon, Jul 1, 2013 at 5:22 AM, Vipul Pandya <vipul@chelsio.com> wrote:
>> From: Casey Leedom <leedom@chelsio.com>
>>
>> T4 can wedge if there are DMAs in flight within the chip and Bus master has
>> been disabled.  We need to have it on till the Function Level Reset completes.
>> T4 can also suffer a Head Of Line blocking problem if MSI-X interrupts are
>> disabled before the FLR has completed.
>>
>> Signed-off-by: Casey Leedom <leedom@chelsio.com>
>> ---
>>   drivers/pci/quirks.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 91 insertions(+)
>>
>> diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
>> index e85d230..6357ba1 100644
>> --- a/drivers/pci/quirks.c
>> +++ b/drivers/pci/quirks.c
>> @@ -3208,6 +3208,95 @@ reset_complete:
>>          return 0;
>>   }
>>
>> +/*
>> + * Device-specific reset method for Chelsio T4-based adapters.
>> + */
>> +static int reset_chelsio_generic_dev(struct pci_dev *dev, int probe)
>> +{
>> +       u16 old_command;
>> +       u16 status, msix_flags;
>> +       int i, rc, msix_pos;
>> +
>> +       /*
>> +        * If this isn't a Chelsio T4-based device, return -ENOTTY indicating
>> +        * that we have no device-specific reset method.
>> +        */
>> +       if ((dev->device & 0xf000) != 0x4000)
>> +               return -ENOTTY;
>> +
>> +       /*
>> +        * If this is the "probe" phase, return 0 indicating that we can
>> +        * reset this device.
>> +        */
>> +       if (probe)
>> +               return 0;
>> +
>> +       /*
>> +        * T4 can wedge if their are DMAs in flight within the chip and Bus
>> +        * master has been disabled.  We need to have it on till the Function
>> +        * Level Reset completes.
>> +        */
>> +       pci_read_config_word(dev, PCI_COMMAND, &old_command);
>> +       pci_write_config_word(dev, PCI_COMMAND,
>> +                             old_command | PCI_COMMAND_MASTER);
>> +
>> +       /*
>> +        * Perform the actual device function reset, saving and restoring
>> +        * configuration information around the reset.
>> +        */
>> +       pci_save_state(dev);
>> +
>> +       /*
>> +        * T4 also suffers a Head-Of-Line blocking problem if MSI-X interrupts
>> +        * are disabled when an MSI-X interrupt message needs to be delivered.
>> +        * So we briefly re-enable MSI-X interrupts for the duration of the
>> +        * FLR.  The pci_restore_state() below will restore the original
>> +        * MSI-X state.
>> +        */
>> +       msix_pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
> dev->msix_cap contains the capability offset already.

Thanks. I didn't know about that.

>> +       pci_read_config_word(dev, msix_pos+PCI_MSIX_FLAGS, &msix_flags);
>> +       if ((msix_flags & PCI_MSIX_FLAGS_ENABLE) == 0)
>> +               pci_write_config_word(dev, msix_pos+PCI_MSIX_FLAGS,
>> +                                     msix_flags |
>> +                                     PCI_MSIX_FLAGS_ENABLE |
>> +                                     PCI_MSIX_FLAGS_MASKALL);
>> +
>> +       /*
>> +        * This reset code is a copy of the guts of pcie_flr() because that's
>> +        * not an exported function.
>> +        */
>> +
>> +       /* Wait for Transaction Pending bit clean */
>> +       for (i = 0; i < 4; i++) {
>> +               if (i)
>> +                       msleep((1 << (i - 1)) * 100);
>> +
>> +               pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &status);
>> +               if (!(status & PCI_EXP_DEVSTA_TRPND))
>> +                       goto clear;
>> +       }
> This is at least the fifth copy of this loop:
>
>    pcie_flr()
>    pci_af_flr()
>    bnx2x_do_flr()
>    reset_intel_82599_sfp_virtfn()
>
> Can we factor this out and just implement it once?  Maybe even make it
> smart enough to look at the PCIe DEVSTA if it exists, and fall back to
> using PCI_AF_STATUS register if *it* exists?

Should such a task be taken up in the patch we're trying to submit or 
should it be a follow on patch? I had thought that, in general, patches 
were supposed to essentially do "one thing." Thanks for your insight on 
this.

>> +
>> +       dev_err(&dev->dev, "transaction is not cleared; proceeding with reset anyway\n");
>> +
>> +clear:
>> +       pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR);
>> +       msleep(100);
>> +
>> +       /*
>> +        * End of pcie_flr() code sequence.
>> +        */
>> +
>> +       rc = 0;
>> +       pci_restore_state(dev);
>> +
>> +       /*
>> +        * Restore the original PCI Configuration Space Command word (which
>> +        * probably had Bus Master disabled).
> Why was Bus Master probably originally disabled?  I don't see anything
> in the pci_reset_function() path that would have disabled it before
> getting to this function.
>
> But I don't think you need the comment anyway.  "Probably had Bus
> Master disabled" isn't anything one can rely on.

Sorry, I probably should have included our example. In this case it's 
coming from KVM's kvm_free_assigned_device() routine which calls 
pci_reset_function() where we do:

/*
* both INTx and MSI are disabled after the Interrupt Disable bit
* is set and the Bus Master bit is cleared.
*/
pci_write_config_word(dev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE);

rc = pci_dev_reset(dev, 0);

The pci_dev_reset(dev, 0) eventually dives into pcie_flr() where the 
Function Level Reset is performed — with Bus Master cleared by 
pci_reset_function() as above.

I'm happy to enhance the comment with this information since I'm a 
comment maven.

>> +        */
>> +       pci_write_config_word(dev, PCI_COMMAND, old_command);
>> +       return rc;
> "rc" appears useless.

I agree. I was probably trying to follow coding styles as slavishly as 
possible with some intermediate coding efforts and didn't see that the 
final result had made "rc" pointless.

Casey

>> +}
>> +
>>   #define PCI_DEVICE_ID_INTEL_82599_SFP_VF   0x10ed
>>   #define PCI_DEVICE_ID_INTEL_IVB_M_VGA      0x0156
>>   #define PCI_DEVICE_ID_INTEL_IVB_M2_VGA     0x0166
>> @@ -3221,6 +3310,8 @@ static const struct pci_dev_reset_methods pci_dev_reset_methods[] = {
>>                  reset_ivb_igd },
>>          { PCI_VENDOR_ID_INTEL, PCI_ANY_ID,
>>                  reset_intel_generic_dev },
>> +       { PCI_VENDOR_ID_CHELSIO, PCI_ANY_ID,
>> +               reset_chelsio_generic_dev },
>>          { 0 }
>>   };
>>
>> --
>> 1.8.0
>>


  reply	other threads:[~2013-07-26 23:01 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-07-01 11:22 [PATCH] pci: Enable bus master till the FLR completes Vipul Pandya
2013-07-26 22:27 ` Bjorn Helgaas
2013-07-26 22:53   ` Casey Leedom [this message]
2013-07-26 23:08     ` Bjorn Helgaas

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=51F2FDF4.6060706@chelsio.com \
    --to=leedom@chelsio.com \
    --cc=bhelgaas@google.com \
    --cc=divy@chelsio.com \
    --cc=dm@chelsio.com \
    --cc=linux-pci@vger.kernel.org \
    --cc=nirranjan@chelsio.com \
    --cc=tomreu@chelsio.com \
    --cc=vipul@chelsio.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox