Message ID | 20200506072102.11107-2-frank.heimes@canonical.com |
---|---|
State | New |
Headers | show |
Series | s390x/pci: do not allow to create more pci functions than configured via CONFIG_PCI_NR_FUNCTIONS | expand |
On 06.05.20 09:21, frank.heimes@canonical.com wrote: > From: Niklas Schnelle <schnelle@linux.ibm.com> > > BugLink: https://bugs.launchpad.net/bugs/1874057 > > Until now zpci_alloc_domain() only prevented more than > CONFIG_PCI_NR_FUNCTIONS from being added when using automatic domain > allocation. When explicit UIDs were defined UIDs above > CONFIG_PCI_NR_FUNCTIONS were not counted at all. > When more PCI functions are added this could lead to various errors > including under sized IRQ vectors and similar issues. > > Fix this by explicitly tracking the number of allocated domains. > > Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com> > Reviewed-by: Pierre Morel <pmorel at linux.ibm.com> > Signed-off-by: Vasily Gorbik <gor at linux.ibm.com> > (backported from commit 969ae01bab2fe938b4c8324836038b5ac1c78fac) > Signed-off-by: Frank Heimes <frank.heimes@canonical.com> Acked-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com> > --- > arch/s390/include/asm/pci.h | 1 + > arch/s390/pci/pci.c | 34 ++++++++++++++++++++-------------- > 2 files changed, 21 insertions(+), 14 deletions(-) > > diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h > index 6087a4e9b2bf..7850e8c8c79a 100644 > --- a/arch/s390/include/asm/pci.h > +++ b/arch/s390/include/asm/pci.h > @@ -28,6 +28,7 @@ int pci_proc_domain(struct pci_bus *); > > #define ZPCI_NR_DMA_SPACES 1 > #define ZPCI_NR_DEVICES CONFIG_PCI_NR_FUNCTIONS > +#define ZPCI_DOMAIN_BITMAP_SIZE (1 << 16) > > /* PCI Function Controls */ > #define ZPCI_FC_FN_ENABLED 0x80 > diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c > index 6105b1b6e49b..0af46683dd66 100644 > --- a/arch/s390/pci/pci.c > +++ b/arch/s390/pci/pci.c > @@ -39,8 +39,9 @@ > static LIST_HEAD(zpci_list); > static DEFINE_SPINLOCK(zpci_list_lock); > > -static DECLARE_BITMAP(zpci_domain, ZPCI_NR_DEVICES); > +static DECLARE_BITMAP(zpci_domain, ZPCI_DOMAIN_BITMAP_SIZE); > static DEFINE_SPINLOCK(zpci_domain_lock); > +static unsigned int zpci_num_domains_allocated; > > #define ZPCI_IOMAP_ENTRIES \ > min(((unsigned long) ZPCI_NR_DEVICES * PCI_BAR_COUNT / 2), \ > @@ -651,39 +652,44 @@ struct dev_pm_ops pcibios_pm_ops = { > > static int zpci_alloc_domain(struct zpci_dev *zdev) > { > + spin_lock(&zpci_domain_lock); > + if (zpci_num_domains_allocated > (ZPCI_NR_DEVICES - 1)) { > + spin_unlock(&zpci_domain_lock); > + pr_err("Adding PCI function %08x failed because the configured limit of %d is reached\n", > + zdev->fid, ZPCI_NR_DEVICES); > + return -ENOSPC; > + } > + > if (zpci_unique_uid) { > zdev->domain = (u16) zdev->uid; > - if (zdev->domain >= ZPCI_NR_DEVICES) > - return 0; > - > - spin_lock(&zpci_domain_lock); > if (test_bit(zdev->domain, zpci_domain)) { > spin_unlock(&zpci_domain_lock); > + pr_err("Adding PCI function %08x failed because domain %04x is already assigned\n", > + zdev->fid, zdev->domain); > return -EEXIST; > } > set_bit(zdev->domain, zpci_domain); > + zpci_num_domains_allocated++; > spin_unlock(&zpci_domain_lock); > return 0; > } > - > - spin_lock(&zpci_domain_lock); > + /* > + * We can always auto allocate domains below ZPCI_NR_DEVICES. > + * There is either a free domain or we have reached the maximum in > + * which case we would have bailed earlier. > + */ > zdev->domain = find_first_zero_bit(zpci_domain, ZPCI_NR_DEVICES); > - if (zdev->domain == ZPCI_NR_DEVICES) { > - spin_unlock(&zpci_domain_lock); > - return -ENOSPC; > - } > set_bit(zdev->domain, zpci_domain); > + zpci_num_domains_allocated++; > spin_unlock(&zpci_domain_lock); > return 0; > } > > static void zpci_free_domain(struct zpci_dev *zdev) > { > - if (zdev->domain >= ZPCI_NR_DEVICES) > - return; > - > spin_lock(&zpci_domain_lock); > clear_bit(zdev->domain, zpci_domain); > + zpci_num_domains_allocated--; > spin_unlock(&zpci_domain_lock); > } > >
On 13.05.20 11:54, Kleber Souza wrote: > On 06.05.20 09:21, frank.heimes@canonical.com wrote: >> From: Niklas Schnelle <schnelle@linux.ibm.com> >> >> BugLink: https://bugs.launchpad.net/bugs/1874057 Hi Frank, I forgot to mention, can you please fix the nominations on the bug report? Thanks, Kleber >> >> Until now zpci_alloc_domain() only prevented more than >> CONFIG_PCI_NR_FUNCTIONS from being added when using automatic domain >> allocation. When explicit UIDs were defined UIDs above >> CONFIG_PCI_NR_FUNCTIONS were not counted at all. >> When more PCI functions are added this could lead to various errors >> including under sized IRQ vectors and similar issues. >> >> Fix this by explicitly tracking the number of allocated domains. >> >> Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com> >> Reviewed-by: Pierre Morel <pmorel at linux.ibm.com> >> Signed-off-by: Vasily Gorbik <gor at linux.ibm.com> >> (backported from commit 969ae01bab2fe938b4c8324836038b5ac1c78fac) >> Signed-off-by: Frank Heimes <frank.heimes@canonical.com> > > > Acked-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com> > >> --- >> arch/s390/include/asm/pci.h | 1 + >> arch/s390/pci/pci.c | 34 ++++++++++++++++++++-------------- >> 2 files changed, 21 insertions(+), 14 deletions(-) >> >> diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h >> index 6087a4e9b2bf..7850e8c8c79a 100644 >> --- a/arch/s390/include/asm/pci.h >> +++ b/arch/s390/include/asm/pci.h >> @@ -28,6 +28,7 @@ int pci_proc_domain(struct pci_bus *); >> >> #define ZPCI_NR_DMA_SPACES 1 >> #define ZPCI_NR_DEVICES CONFIG_PCI_NR_FUNCTIONS >> +#define ZPCI_DOMAIN_BITMAP_SIZE (1 << 16) >> >> /* PCI Function Controls */ >> #define ZPCI_FC_FN_ENABLED 0x80 >> diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c >> index 6105b1b6e49b..0af46683dd66 100644 >> --- a/arch/s390/pci/pci.c >> +++ b/arch/s390/pci/pci.c >> @@ -39,8 +39,9 @@ >> static LIST_HEAD(zpci_list); >> static DEFINE_SPINLOCK(zpci_list_lock); >> >> -static DECLARE_BITMAP(zpci_domain, ZPCI_NR_DEVICES); >> +static DECLARE_BITMAP(zpci_domain, ZPCI_DOMAIN_BITMAP_SIZE); >> static DEFINE_SPINLOCK(zpci_domain_lock); >> +static unsigned int zpci_num_domains_allocated; >> >> #define ZPCI_IOMAP_ENTRIES \ >> min(((unsigned long) ZPCI_NR_DEVICES * PCI_BAR_COUNT / 2), \ >> @@ -651,39 +652,44 @@ struct dev_pm_ops pcibios_pm_ops = { >> >> static int zpci_alloc_domain(struct zpci_dev *zdev) >> { >> + spin_lock(&zpci_domain_lock); >> + if (zpci_num_domains_allocated > (ZPCI_NR_DEVICES - 1)) { >> + spin_unlock(&zpci_domain_lock); >> + pr_err("Adding PCI function %08x failed because the configured limit of %d is reached\n", >> + zdev->fid, ZPCI_NR_DEVICES); >> + return -ENOSPC; >> + } >> + >> if (zpci_unique_uid) { >> zdev->domain = (u16) zdev->uid; >> - if (zdev->domain >= ZPCI_NR_DEVICES) >> - return 0; >> - >> - spin_lock(&zpci_domain_lock); >> if (test_bit(zdev->domain, zpci_domain)) { >> spin_unlock(&zpci_domain_lock); >> + pr_err("Adding PCI function %08x failed because domain %04x is already assigned\n", >> + zdev->fid, zdev->domain); >> return -EEXIST; >> } >> set_bit(zdev->domain, zpci_domain); >> + zpci_num_domains_allocated++; >> spin_unlock(&zpci_domain_lock); >> return 0; >> } >> - >> - spin_lock(&zpci_domain_lock); >> + /* >> + * We can always auto allocate domains below ZPCI_NR_DEVICES. >> + * There is either a free domain or we have reached the maximum in >> + * which case we would have bailed earlier. >> + */ >> zdev->domain = find_first_zero_bit(zpci_domain, ZPCI_NR_DEVICES); >> - if (zdev->domain == ZPCI_NR_DEVICES) { >> - spin_unlock(&zpci_domain_lock); >> - return -ENOSPC; >> - } >> set_bit(zdev->domain, zpci_domain); >> + zpci_num_domains_allocated++; >> spin_unlock(&zpci_domain_lock); >> return 0; >> } >> >> static void zpci_free_domain(struct zpci_dev *zdev) >> { >> - if (zdev->domain >= ZPCI_NR_DEVICES) >> - return; >> - >> spin_lock(&zpci_domain_lock); >> clear_bit(zdev->domain, zpci_domain); >> + zpci_num_domains_allocated--; >> spin_unlock(&zpci_domain_lock); >> } >> >> >
Yes of course - done. (Sorry, some of the tickets were opened when the dev. of 'groovy' was not opened, and I forgot to adjust the nominations later ...) BR, Frank On Wed, May 13, 2020 at 11:56 AM Kleber Souza <kleber.souza@canonical.com> wrote: > On 13.05.20 11:54, Kleber Souza wrote: > > On 06.05.20 09:21, frank.heimes@canonical.com wrote: > >> From: Niklas Schnelle <schnelle@linux.ibm.com> > >> > >> BugLink: https://bugs.launchpad.net/bugs/1874057 > > Hi Frank, > > I forgot to mention, can you please fix the nominations on the bug report? > > > Thanks, > Kleber > > >> > >> Until now zpci_alloc_domain() only prevented more than > >> CONFIG_PCI_NR_FUNCTIONS from being added when using automatic domain > >> allocation. When explicit UIDs were defined UIDs above > >> CONFIG_PCI_NR_FUNCTIONS were not counted at all. > >> When more PCI functions are added this could lead to various errors > >> including under sized IRQ vectors and similar issues. > >> > >> Fix this by explicitly tracking the number of allocated domains. > >> > >> Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com> > >> Reviewed-by: Pierre Morel <pmorel at linux.ibm.com> > >> Signed-off-by: Vasily Gorbik <gor at linux.ibm.com> > >> (backported from commit 969ae01bab2fe938b4c8324836038b5ac1c78fac) > >> Signed-off-by: Frank Heimes <frank.heimes@canonical.com> > > > > > > Acked-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com> > > > >> --- > >> arch/s390/include/asm/pci.h | 1 + > >> arch/s390/pci/pci.c | 34 ++++++++++++++++++++-------------- > >> 2 files changed, 21 insertions(+), 14 deletions(-) > >> > >> diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h > >> index 6087a4e9b2bf..7850e8c8c79a 100644 > >> --- a/arch/s390/include/asm/pci.h > >> +++ b/arch/s390/include/asm/pci.h > >> @@ -28,6 +28,7 @@ int pci_proc_domain(struct pci_bus *); > >> > >> #define ZPCI_NR_DMA_SPACES 1 > >> #define ZPCI_NR_DEVICES CONFIG_PCI_NR_FUNCTIONS > >> +#define ZPCI_DOMAIN_BITMAP_SIZE (1 << 16) > >> > >> /* PCI Function Controls */ > >> #define ZPCI_FC_FN_ENABLED 0x80 > >> diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c > >> index 6105b1b6e49b..0af46683dd66 100644 > >> --- a/arch/s390/pci/pci.c > >> +++ b/arch/s390/pci/pci.c > >> @@ -39,8 +39,9 @@ > >> static LIST_HEAD(zpci_list); > >> static DEFINE_SPINLOCK(zpci_list_lock); > >> > >> -static DECLARE_BITMAP(zpci_domain, ZPCI_NR_DEVICES); > >> +static DECLARE_BITMAP(zpci_domain, ZPCI_DOMAIN_BITMAP_SIZE); > >> static DEFINE_SPINLOCK(zpci_domain_lock); > >> +static unsigned int zpci_num_domains_allocated; > >> > >> #define ZPCI_IOMAP_ENTRIES \ > >> min(((unsigned long) ZPCI_NR_DEVICES * PCI_BAR_COUNT / 2), \ > >> @@ -651,39 +652,44 @@ struct dev_pm_ops pcibios_pm_ops = { > >> > >> static int zpci_alloc_domain(struct zpci_dev *zdev) > >> { > >> + spin_lock(&zpci_domain_lock); > >> + if (zpci_num_domains_allocated > (ZPCI_NR_DEVICES - 1)) { > >> + spin_unlock(&zpci_domain_lock); > >> + pr_err("Adding PCI function %08x failed because the > configured limit of %d is reached\n", > >> + zdev->fid, ZPCI_NR_DEVICES); > >> + return -ENOSPC; > >> + } > >> + > >> if (zpci_unique_uid) { > >> zdev->domain = (u16) zdev->uid; > >> - if (zdev->domain >= ZPCI_NR_DEVICES) > >> - return 0; > >> - > >> - spin_lock(&zpci_domain_lock); > >> if (test_bit(zdev->domain, zpci_domain)) { > >> spin_unlock(&zpci_domain_lock); > >> + pr_err("Adding PCI function %08x failed because > domain %04x is already assigned\n", > >> + zdev->fid, zdev->domain); > >> return -EEXIST; > >> } > >> set_bit(zdev->domain, zpci_domain); > >> + zpci_num_domains_allocated++; > >> spin_unlock(&zpci_domain_lock); > >> return 0; > >> } > >> - > >> - spin_lock(&zpci_domain_lock); > >> + /* > >> + * We can always auto allocate domains below ZPCI_NR_DEVICES. > >> + * There is either a free domain or we have reached the maximum in > >> + * which case we would have bailed earlier. > >> + */ > >> zdev->domain = find_first_zero_bit(zpci_domain, ZPCI_NR_DEVICES); > >> - if (zdev->domain == ZPCI_NR_DEVICES) { > >> - spin_unlock(&zpci_domain_lock); > >> - return -ENOSPC; > >> - } > >> set_bit(zdev->domain, zpci_domain); > >> + zpci_num_domains_allocated++; > >> spin_unlock(&zpci_domain_lock); > >> return 0; > >> } > >> > >> static void zpci_free_domain(struct zpci_dev *zdev) > >> { > >> - if (zdev->domain >= ZPCI_NR_DEVICES) > >> - return; > >> - > >> spin_lock(&zpci_domain_lock); > >> clear_bit(zdev->domain, zpci_domain); > >> + zpci_num_domains_allocated--; > >> spin_unlock(&zpci_domain_lock); > >> } > >> > >> > > > >
On 06.05.20 09:21, frank.heimes@canonical.com wrote: > From: Niklas Schnelle <schnelle@linux.ibm.com> > > BugLink: https://bugs.launchpad.net/bugs/1874057 > > Until now zpci_alloc_domain() only prevented more than > CONFIG_PCI_NR_FUNCTIONS from being added when using automatic domain > allocation. When explicit UIDs were defined UIDs above > CONFIG_PCI_NR_FUNCTIONS were not counted at all. > When more PCI functions are added this could lead to various errors > including under sized IRQ vectors and similar issues. > > Fix this by explicitly tracking the number of allocated domains. > > Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com> > Reviewed-by: Pierre Morel <pmorel at linux.ibm.com> > Signed-off-by: Vasily Gorbik <gor at linux.ibm.com> > (backported from commit 969ae01bab2fe938b4c8324836038b5ac1c78fac) > Signed-off-by: Frank Heimes <frank.heimes@canonical.com> Acked-by: Stefan Bader <stefan.bader@canonical.com> > --- > arch/s390/include/asm/pci.h | 1 + > arch/s390/pci/pci.c | 34 ++++++++++++++++++++-------------- > 2 files changed, 21 insertions(+), 14 deletions(-) > > diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h > index 6087a4e9b2bf..7850e8c8c79a 100644 > --- a/arch/s390/include/asm/pci.h > +++ b/arch/s390/include/asm/pci.h > @@ -28,6 +28,7 @@ int pci_proc_domain(struct pci_bus *); > > #define ZPCI_NR_DMA_SPACES 1 > #define ZPCI_NR_DEVICES CONFIG_PCI_NR_FUNCTIONS > +#define ZPCI_DOMAIN_BITMAP_SIZE (1 << 16) > > /* PCI Function Controls */ > #define ZPCI_FC_FN_ENABLED 0x80 > diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c > index 6105b1b6e49b..0af46683dd66 100644 > --- a/arch/s390/pci/pci.c > +++ b/arch/s390/pci/pci.c > @@ -39,8 +39,9 @@ > static LIST_HEAD(zpci_list); > static DEFINE_SPINLOCK(zpci_list_lock); > > -static DECLARE_BITMAP(zpci_domain, ZPCI_NR_DEVICES); > +static DECLARE_BITMAP(zpci_domain, ZPCI_DOMAIN_BITMAP_SIZE); > static DEFINE_SPINLOCK(zpci_domain_lock); > +static unsigned int zpci_num_domains_allocated; > > #define ZPCI_IOMAP_ENTRIES \ > min(((unsigned long) ZPCI_NR_DEVICES * PCI_BAR_COUNT / 2), \ > @@ -651,39 +652,44 @@ struct dev_pm_ops pcibios_pm_ops = { > > static int zpci_alloc_domain(struct zpci_dev *zdev) > { > + spin_lock(&zpci_domain_lock); > + if (zpci_num_domains_allocated > (ZPCI_NR_DEVICES - 1)) { > + spin_unlock(&zpci_domain_lock); > + pr_err("Adding PCI function %08x failed because the configured limit of %d is reached\n", > + zdev->fid, ZPCI_NR_DEVICES); > + return -ENOSPC; > + } > + > if (zpci_unique_uid) { > zdev->domain = (u16) zdev->uid; > - if (zdev->domain >= ZPCI_NR_DEVICES) > - return 0; > - > - spin_lock(&zpci_domain_lock); > if (test_bit(zdev->domain, zpci_domain)) { > spin_unlock(&zpci_domain_lock); > + pr_err("Adding PCI function %08x failed because domain %04x is already assigned\n", > + zdev->fid, zdev->domain); > return -EEXIST; > } > set_bit(zdev->domain, zpci_domain); > + zpci_num_domains_allocated++; > spin_unlock(&zpci_domain_lock); > return 0; > } > - > - spin_lock(&zpci_domain_lock); > + /* > + * We can always auto allocate domains below ZPCI_NR_DEVICES. > + * There is either a free domain or we have reached the maximum in > + * which case we would have bailed earlier. > + */ > zdev->domain = find_first_zero_bit(zpci_domain, ZPCI_NR_DEVICES); > - if (zdev->domain == ZPCI_NR_DEVICES) { > - spin_unlock(&zpci_domain_lock); > - return -ENOSPC; > - } > set_bit(zdev->domain, zpci_domain); > + zpci_num_domains_allocated++; > spin_unlock(&zpci_domain_lock); > return 0; > } > > static void zpci_free_domain(struct zpci_dev *zdev) > { > - if (zdev->domain >= ZPCI_NR_DEVICES) > - return; > - > spin_lock(&zpci_domain_lock); > clear_bit(zdev->domain, zpci_domain); > + zpci_num_domains_allocated--; > spin_unlock(&zpci_domain_lock); > } > >
diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h index 6087a4e9b2bf..7850e8c8c79a 100644 --- a/arch/s390/include/asm/pci.h +++ b/arch/s390/include/asm/pci.h @@ -28,6 +28,7 @@ int pci_proc_domain(struct pci_bus *); #define ZPCI_NR_DMA_SPACES 1 #define ZPCI_NR_DEVICES CONFIG_PCI_NR_FUNCTIONS +#define ZPCI_DOMAIN_BITMAP_SIZE (1 << 16) /* PCI Function Controls */ #define ZPCI_FC_FN_ENABLED 0x80 diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index 6105b1b6e49b..0af46683dd66 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -39,8 +39,9 @@ static LIST_HEAD(zpci_list); static DEFINE_SPINLOCK(zpci_list_lock); -static DECLARE_BITMAP(zpci_domain, ZPCI_NR_DEVICES); +static DECLARE_BITMAP(zpci_domain, ZPCI_DOMAIN_BITMAP_SIZE); static DEFINE_SPINLOCK(zpci_domain_lock); +static unsigned int zpci_num_domains_allocated; #define ZPCI_IOMAP_ENTRIES \ min(((unsigned long) ZPCI_NR_DEVICES * PCI_BAR_COUNT / 2), \ @@ -651,39 +652,44 @@ struct dev_pm_ops pcibios_pm_ops = { static int zpci_alloc_domain(struct zpci_dev *zdev) { + spin_lock(&zpci_domain_lock); + if (zpci_num_domains_allocated > (ZPCI_NR_DEVICES - 1)) { + spin_unlock(&zpci_domain_lock); + pr_err("Adding PCI function %08x failed because the configured limit of %d is reached\n", + zdev->fid, ZPCI_NR_DEVICES); + return -ENOSPC; + } + if (zpci_unique_uid) { zdev->domain = (u16) zdev->uid; - if (zdev->domain >= ZPCI_NR_DEVICES) - return 0; - - spin_lock(&zpci_domain_lock); if (test_bit(zdev->domain, zpci_domain)) { spin_unlock(&zpci_domain_lock); + pr_err("Adding PCI function %08x failed because domain %04x is already assigned\n", + zdev->fid, zdev->domain); return -EEXIST; } set_bit(zdev->domain, zpci_domain); + zpci_num_domains_allocated++; spin_unlock(&zpci_domain_lock); return 0; } - - spin_lock(&zpci_domain_lock); + /* + * We can always auto allocate domains below ZPCI_NR_DEVICES. + * There is either a free domain or we have reached the maximum in + * which case we would have bailed earlier. + */ zdev->domain = find_first_zero_bit(zpci_domain, ZPCI_NR_DEVICES); - if (zdev->domain == ZPCI_NR_DEVICES) { - spin_unlock(&zpci_domain_lock); - return -ENOSPC; - } set_bit(zdev->domain, zpci_domain); + zpci_num_domains_allocated++; spin_unlock(&zpci_domain_lock); return 0; } static void zpci_free_domain(struct zpci_dev *zdev) { - if (zdev->domain >= ZPCI_NR_DEVICES) - return; - spin_lock(&zpci_domain_lock); clear_bit(zdev->domain, zpci_domain); + zpci_num_domains_allocated--; spin_unlock(&zpci_domain_lock); }