Message ID | 20170919152936.14498-6-roger.pau@citrix.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
>>> On 19.09.17 at 17:29, <roger.pau@citrix.com> wrote: > --- a/xen/drivers/passthrough/pci.c > +++ b/xen/drivers/passthrough/pci.c > @@ -603,6 +603,56 @@ static int iommu_add_device(struct pci_dev *pdev); > static int iommu_enable_device(struct pci_dev *pdev); > static int iommu_remove_device(struct pci_dev *pdev); > > +int pci_size_mem_bar(pci_sbdf_t sbdf, unsigned int pos, bool last, > + uint64_t *paddr, uint64_t *psize, unsigned int flags) > +{ > + uint32_t hi = 0, bar = pci_conf_read32(sbdf.seg, sbdf.bus, sbdf.dev, > + sbdf.func, pos); > + uint64_t addr, size; > + bool vf = flags & PCI_BAR_VF; Honestly I'm not convinced of the utility of this variable; same for the "rom" one in the next patch. > + ASSERT((bar & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY); > + pci_conf_write32(sbdf.seg, sbdf.bus, sbdf.dev, sbdf.func, pos, ~0); > + if ( (bar & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == > + PCI_BASE_ADDRESS_MEM_TYPE_64 ) > + { > + if ( last ) > + { > + printk(XENLOG_WARNING > + "%sdevice %04x:%02x:%02x.%u with 64-bit %sBAR in last slot\n", > + vf ? "SR-IOV " : "", sbdf.seg, sbdf.bus, sbdf.dev, sbdf.func, > + vf ? "vf " : ""); > + return -EINVAL; > + } > + hi = pci_conf_read32(sbdf.seg, sbdf.bus, sbdf.dev, sbdf.func, pos + 4); > + pci_conf_write32(sbdf.seg, sbdf.bus, sbdf.dev, sbdf.func, pos + 4, ~0); > + } > + size = pci_conf_read32(sbdf.seg, sbdf.bus, sbdf.dev, sbdf.func, pos) & > + PCI_BASE_ADDRESS_MEM_MASK; > + if ( (bar & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == > + PCI_BASE_ADDRESS_MEM_TYPE_64 ) > + { > + size |= (uint64_t)pci_conf_read32(sbdf.seg, sbdf.bus, sbdf.dev, > + sbdf.func, pos + 4) << 32; > + pci_conf_write32(sbdf.seg, sbdf.bus, sbdf.dev, sbdf.func, pos + 4, hi); > + } > + else if ( size ) > + size |= (uint64_t)~0 << 32; > + pci_conf_write32(sbdf.seg, sbdf.bus, sbdf.dev, sbdf.func, pos, bar); > + size = -size; > + addr = (bar & PCI_BASE_ADDRESS_MEM_MASK) | ((uint64_t)hi << 32); > + > + if ( paddr ) > + *paddr = addr; You need addr only inside the if() - no need for the local variable, and no need to calculate it unconditionally. > --- a/xen/include/xen/pci.h > +++ b/xen/include/xen/pci.h > @@ -189,6 +189,10 @@ const char *parse_pci(const char *, unsigned int *seg, unsigned int *bus, > const char *parse_pci_seg(const char *, unsigned int *seg, unsigned int *bus, > unsigned int *dev, unsigned int *func, bool *def_seg); > > +#define _PCI_BAR_VF 0 > +#define PCI_BAR_VF (1u << _PCI_BAR_VF) Do you really need both? I know we have quite a few cases where flags are being defined this way, but that's usually when bit operations (test_bit() and alike) are intended on the flags fields. Jan
On Wed, Oct 04, 2017 at 08:32:06AM +0000, Jan Beulich wrote: > >>> On 19.09.17 at 17:29, <roger.pau@citrix.com> wrote: > > --- a/xen/include/xen/pci.h > > +++ b/xen/include/xen/pci.h > > @@ -189,6 +189,10 @@ const char *parse_pci(const char *, unsigned int *seg, unsigned int *bus, > > const char *parse_pci_seg(const char *, unsigned int *seg, unsigned int *bus, > > unsigned int *dev, unsigned int *func, bool *def_seg); > > > > +#define _PCI_BAR_VF 0 > > +#define PCI_BAR_VF (1u << _PCI_BAR_VF) > > Do you really need both? I know we have quite a few cases where flags > are being defined this way, but that's usually when bit operations > (test_bit() and alike) are intended on the flags fields. Ack, would you then rather prefer to have 1, or (1u << 0)? (to keep it in line with the other flag that will be added later). Thanks, Roger.
>>> On 04.10.17 at 15:31, <roger.pau@citrix.com> wrote: > On Wed, Oct 04, 2017 at 08:32:06AM +0000, Jan Beulich wrote: >> >>> On 19.09.17 at 17:29, <roger.pau@citrix.com> wrote: >> > --- a/xen/include/xen/pci.h >> > +++ b/xen/include/xen/pci.h >> > @@ -189,6 +189,10 @@ const char *parse_pci(const char *, unsigned int *seg, unsigned int *bus, >> > const char *parse_pci_seg(const char *, unsigned int *seg, unsigned int *bus, >> > unsigned int *dev, unsigned int *func, bool *def_seg); >> > >> > +#define _PCI_BAR_VF 0 >> > +#define PCI_BAR_VF (1u << _PCI_BAR_VF) >> >> Do you really need both? I know we have quite a few cases where flags >> are being defined this way, but that's usually when bit operations >> (test_bit() and alike) are intended on the flags fields. > > Ack, would you then rather prefer to have 1, or (1u << 0)? (to keep it > in line with the other flag that will be added later). 1u please, as that's going to be mandatory once someone adds a definition for the 32nd flag bit. The other option would be to use a plain hex constant without involving the shift operator. Jan
diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c index 975485fe05..ba58b4d0cc 100644 --- a/xen/drivers/passthrough/pci.c +++ b/xen/drivers/passthrough/pci.c @@ -603,6 +603,56 @@ static int iommu_add_device(struct pci_dev *pdev); static int iommu_enable_device(struct pci_dev *pdev); static int iommu_remove_device(struct pci_dev *pdev); +int pci_size_mem_bar(pci_sbdf_t sbdf, unsigned int pos, bool last, + uint64_t *paddr, uint64_t *psize, unsigned int flags) +{ + uint32_t hi = 0, bar = pci_conf_read32(sbdf.seg, sbdf.bus, sbdf.dev, + sbdf.func, pos); + uint64_t addr, size; + bool vf = flags & PCI_BAR_VF; + + ASSERT((bar & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY); + pci_conf_write32(sbdf.seg, sbdf.bus, sbdf.dev, sbdf.func, pos, ~0); + if ( (bar & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == + PCI_BASE_ADDRESS_MEM_TYPE_64 ) + { + if ( last ) + { + printk(XENLOG_WARNING + "%sdevice %04x:%02x:%02x.%u with 64-bit %sBAR in last slot\n", + vf ? "SR-IOV " : "", sbdf.seg, sbdf.bus, sbdf.dev, sbdf.func, + vf ? "vf " : ""); + return -EINVAL; + } + hi = pci_conf_read32(sbdf.seg, sbdf.bus, sbdf.dev, sbdf.func, pos + 4); + pci_conf_write32(sbdf.seg, sbdf.bus, sbdf.dev, sbdf.func, pos + 4, ~0); + } + size = pci_conf_read32(sbdf.seg, sbdf.bus, sbdf.dev, sbdf.func, pos) & + PCI_BASE_ADDRESS_MEM_MASK; + if ( (bar & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == + PCI_BASE_ADDRESS_MEM_TYPE_64 ) + { + size |= (uint64_t)pci_conf_read32(sbdf.seg, sbdf.bus, sbdf.dev, + sbdf.func, pos + 4) << 32; + pci_conf_write32(sbdf.seg, sbdf.bus, sbdf.dev, sbdf.func, pos + 4, hi); + } + else if ( size ) + size |= (uint64_t)~0 << 32; + pci_conf_write32(sbdf.seg, sbdf.bus, sbdf.dev, sbdf.func, pos, bar); + size = -size; + addr = (bar & PCI_BASE_ADDRESS_MEM_MASK) | ((uint64_t)hi << 32); + + if ( paddr ) + *paddr = addr; + *psize = size; + + if ( (bar & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == + PCI_BASE_ADDRESS_MEM_TYPE_64 ) + return 2; + + return 1; +} + int pci_add_device(u16 seg, u8 bus, u8 devfn, const struct pci_dev_info *info, nodeid_t node) { @@ -674,11 +724,16 @@ int pci_add_device(u16 seg, u8 bus, u8 devfn, unsigned int i; BUILD_BUG_ON(ARRAY_SIZE(pdev->vf_rlen) != PCI_SRIOV_NUM_BARS); - for ( i = 0; i < PCI_SRIOV_NUM_BARS; ++i ) + for ( i = 0; i < PCI_SRIOV_NUM_BARS; ) { unsigned int idx = pos + PCI_SRIOV_BAR + i * 4; u32 bar = pci_conf_read32(seg, bus, slot, func, idx); - u32 hi = 0; + pci_sbdf_t sbdf = { + .seg = seg, + .bus = bus, + .dev = slot, + .func = func, + }; if ( (bar & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO ) @@ -689,38 +744,13 @@ int pci_add_device(u16 seg, u8 bus, u8 devfn, seg, bus, slot, func, i); continue; } - pci_conf_write32(seg, bus, slot, func, idx, ~0); - if ( (bar & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == - PCI_BASE_ADDRESS_MEM_TYPE_64 ) - { - if ( i >= PCI_SRIOV_NUM_BARS ) - { - printk(XENLOG_WARNING - "SR-IOV device %04x:%02x:%02x.%u with 64-bit" - " vf BAR in last slot\n", - seg, bus, slot, func); - break; - } - hi = pci_conf_read32(seg, bus, slot, func, idx + 4); - pci_conf_write32(seg, bus, slot, func, idx + 4, ~0); - } - pdev->vf_rlen[i] = pci_conf_read32(seg, bus, slot, func, idx) & - PCI_BASE_ADDRESS_MEM_MASK; - if ( (bar & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == - PCI_BASE_ADDRESS_MEM_TYPE_64 ) - { - pdev->vf_rlen[i] |= (u64)pci_conf_read32(seg, bus, - slot, func, - idx + 4) << 32; - pci_conf_write32(seg, bus, slot, func, idx + 4, hi); - } - else if ( pdev->vf_rlen[i] ) - pdev->vf_rlen[i] |= (u64)~0 << 32; - pci_conf_write32(seg, bus, slot, func, idx, bar); - pdev->vf_rlen[i] = -pdev->vf_rlen[i]; - if ( (bar & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == - PCI_BASE_ADDRESS_MEM_TYPE_64 ) - ++i; + ret = pci_size_mem_bar(sbdf, idx, i == PCI_SRIOV_NUM_BARS - 1, + NULL, &pdev->vf_rlen[i], PCI_BAR_VF); + if ( ret < 0 ) + break; + + ASSERT(ret); + i += ret; } } else diff --git a/xen/include/xen/pci.h b/xen/include/xen/pci.h index b7a6abfc53..2bee6a3247 100644 --- a/xen/include/xen/pci.h +++ b/xen/include/xen/pci.h @@ -189,6 +189,10 @@ const char *parse_pci(const char *, unsigned int *seg, unsigned int *bus, const char *parse_pci_seg(const char *, unsigned int *seg, unsigned int *bus, unsigned int *dev, unsigned int *func, bool *def_seg); +#define _PCI_BAR_VF 0 +#define PCI_BAR_VF (1u << _PCI_BAR_VF) +int pci_size_mem_bar(pci_sbdf_t sbdf, unsigned int pos, bool last, + uint64_t *addr, uint64_t *size, unsigned int flags); bool_t pcie_aer_get_firmware_first(const struct pci_dev *);