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

Re: [Xen-devel] [PATCH v5 08/10] x86/PCI: read MSI-X table entry count early



On Tue, Aug 06, 2019 at 03:10:40PM +0200, Jan Beulich wrote:
> Rather than doing this every time we set up interrupts for a device
> anew (and then in two distinct places) fill this invariant field
> right after allocating struct arch_msix.
> 
> While at it also obtain the MSI-X capability structure position just
> once, in msix_capability_init(), rather than in each caller.
> 
> Furthermore take the opportunity and eliminate the multi_msix_capable()
> alias of msix_table_size().
> 
> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
> ---
> v5: New.
> 
> --- a/xen/arch/x86/msi.c
> +++ b/xen/arch/x86/msi.c
> @@ -821,10 +821,8 @@ static u64 read_pci_mem_bar(u16 seg, u8
>   * requested MSI-X entries with allocated irqs or non-zero for otherwise.
>   **/
>  static int msix_capability_init(struct pci_dev *dev,
> -                                unsigned int pos,
>                                  struct msi_info *msi,
> -                                struct msi_desc **desc,
> -                                unsigned int nr_entries)
> +                                struct msi_desc **desc)
>  {
>      struct arch_msix *msix = dev->msix;
>      struct msi_desc *entry = NULL;
> @@ -838,6 +836,11 @@ static int msix_capability_init(struct p
>      u8 slot = PCI_SLOT(dev->devfn);
>      u8 func = PCI_FUNC(dev->devfn);
>      bool maskall = msix->host_maskall;
> +    unsigned int pos = pci_find_cap_offset(seg, bus, slot, func,
> +                                           PCI_CAP_ID_MSIX);
> +
> +    if ( !pos )
> +        return -ENODEV;
>      ASSERT(pcidevs_locked());
> @@ -912,10 +915,9 @@ static int msix_capability_init(struct p
>          u64 pba_paddr;
>          u32 pba_offset;
> -        msix->nr_entries = nr_entries;
>          msix->table.first = PFN_DOWN(table_paddr);
>          msix->table.last = PFN_DOWN(table_paddr +
> -                                    nr_entries * PCI_MSIX_ENTRY_SIZE - 1);
> +                                    msix->nr_entries * PCI_MSIX_ENTRY_SIZE - 
> 1);
>          WARN_ON(rangeset_overlaps_range(mmio_ro_ranges, msix->table.first,
>                                          msix->table.last));
> @@ -927,7 +929,7 @@ static int msix_capability_init(struct p
>          msix->pba.first = PFN_DOWN(pba_paddr);
>          msix->pba.last = PFN_DOWN(pba_paddr +
> -                                  BITS_TO_LONGS(nr_entries) - 1);
> +                                  BITS_TO_LONGS(msix->nr_entries) - 1);
>          WARN_ON(rangeset_overlaps_range(mmio_ro_ranges, msix->pba.first,
>                                          msix->pba.last));
>      }
> @@ -999,7 +1001,6 @@ static int msix_capability_init(struct p
>              /* XXX How to deal with existing mappings? */
>          }
>      }
> -    WARN_ON(msix->nr_entries != nr_entries);
>      WARN_ON(msix->table.first != (table_paddr >> PAGE_SHIFT));
>      ++msix->used_entries;
> @@ -1093,22 +1094,17 @@ static void __pci_disable_msi(struct msi
>   **/
>  static int __pci_enable_msix(struct msi_info *msi, struct msi_desc **desc)
>  {
> -    int pos, nr_entries;
>      struct pci_dev *pdev;
> -    u16 control;
>      u8 slot = PCI_SLOT(msi->devfn);
>      u8 func = PCI_FUNC(msi->devfn);
>      struct msi_desc *old_desc;

Missing newline.

>      ASSERT(pcidevs_locked());
>      pdev = pci_get_pdev(msi->seg, msi->bus, msi->devfn);
> -    pos = pci_find_cap_offset(msi->seg, msi->bus, slot, func, 
> PCI_CAP_ID_MSIX);
> -    if ( !pdev || !pos )
> +    if ( !pdev || !pdev->msix )
>          return -ENODEV;
> -    control = pci_conf_read16(pdev->sbdf, msix_control_reg(pos));
> -    nr_entries = multi_msix_capable(control);
> -    if ( msi->entry_nr >= nr_entries )
> +    if ( msi->entry_nr >= pdev->msix->nr_entries )
>          return -EINVAL;
>      old_desc = find_msi_entry(pdev, msi->irq, PCI_CAP_ID_MSIX);
> @@ -1127,7 +1123,7 @@ static int __pci_enable_msix(struct msi_
>          __pci_disable_msi(old_desc);
>      }
> -    return msix_capability_init(pdev, pos, msi, desc, nr_entries);
> +    return msix_capability_init(pdev, msi, desc);
>  }
>  static void _pci_cleanup_msix(struct arch_msix *msix)
> @@ -1187,16 +1183,10 @@ int pci_prepare_msix(u16 seg, u8 bus, u8
>  {
>      int rc;
>      struct pci_dev *pdev;
> -    u8 slot = PCI_SLOT(devfn), func = PCI_FUNC(devfn);
> -    unsigned int pos = pci_find_cap_offset(seg, bus, slot, func,
> -                                           PCI_CAP_ID_MSIX);

You seem to be missing an empty newline here?

>      if ( !use_msi )
>          return 0;

Same here.

> -    if ( !pos )
> -        return -ENODEV;
> -
>      pcidevs_lock();
>      pdev = pci_get_pdev(seg, bus, devfn);
>      if ( !pdev )
> @@ -1209,13 +1199,7 @@ int pci_prepare_msix(u16 seg, u8 bus, u8
>          rc = 0;
>      }
>      else
> -    {
> -        uint16_t control = pci_conf_read16(PCI_SBDF3(seg, bus, devfn),
> -                                           msix_control_reg(pos));
> -
> -        rc = msix_capability_init(pdev, pos, NULL, NULL,
> -                                  multi_msix_capable(control));
> -    }
> +        rc = msix_capability_init(pdev, NULL, NULL);
>      pcidevs_unlock();
>      return rc;
> --- a/xen/drivers/passthrough/pci.c
> +++ b/xen/drivers/passthrough/pci.c
> @@ -324,6 +324,7 @@ static void apply_quirks(struct pci_dev
>  static struct pci_dev *alloc_pdev(struct pci_seg *pseg, u8 bus, u8 devfn)
>  {
>      struct pci_dev *pdev;
> +    unsigned int pos;

This chunk doesn't seem to match my current code, as there's an empty
newline between the declarations and list_for_each_entry.

>      list_for_each_entry ( pdev, &pseg->alldevs_list, alldevs_list )
>          if ( pdev->bus == bus && pdev->devfn == devfn )
> @@ -339,10 +340,12 @@ static struct pci_dev *alloc_pdev(struct
>      pdev->domain = NULL;
>      INIT_LIST_HEAD(&pdev->msi_list);
> -    if ( pci_find_cap_offset(pseg->nr, bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
> -                             PCI_CAP_ID_MSIX) )
> +    pos = pci_find_cap_offset(pseg->nr, bus, PCI_SLOT(devfn), 
> PCI_FUNC(devfn),
> +                              PCI_CAP_ID_MSIX);
> +    if ( pos )
>      {
>          struct arch_msix *msix = xzalloc(struct arch_msix);
> +        uint16_t ctrl;
>          if ( !msix )
>          {
> @@ -350,6 +353,10 @@ static struct pci_dev *alloc_pdev(struct
>              return NULL;
>          }
>          spin_lock_init(&msix->table_lock);
> +
> +        ctrl = pci_conf_read16(pdev->sbdf, msix_control_reg(pos));
> +        msix->nr_entries = msix_table_size(ctrl);

Since you store the number of entries here, why not also store the
position of the MSI-X capability since it's also immutable?

That would prevent having to fetch it again in msix_capability_init.

Thanks, Roger.

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.