ACK: [SRU][F][G][PATCH v3 1/1] s390/pci: Fix zpci_alloc_domain() over allocation
Kleber Souza
kleber.souza at canonical.com
Wed May 13 09:56:01 UTC 2020
On 13.05.20 11:54, Kleber Souza wrote:
> On 06.05.20 09:21, frank.heimes at canonical.com wrote:
>> From: Niklas Schnelle <schnelle at 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 at 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 at canonical.com>
>
>
> Acked-by: Kleber Sacilotto de Souza <kleber.souza at 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);
>> }
>>
>>
>
More information about the kernel-team
mailing list