FAILED: patch "[PATCH] irqchip/gic-v3-its: Align PCI Multi-MSI allocation on their" failed to apply to 4.9-stable tree
[email protected]
maintainerThe patch below does not apply to the 4.9-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 8208d1708b88b412ca97f50a6d951242c88cbbac Mon Sep 17 00:00:00 2001
From: Marc Zyngier <[email protected]>
Date: Fri, 18 Jan 2019 14:08:59 +0000
Subject: [PATCH] irqchip/gic-v3-its: Align PCI Multi-MSI allocation on their
size
The way we allocate events works fine in most cases, except when multiple PCI devices share an ITS-visible DevID, and that one of them is trying to use MultiMSI allocation.
In that case, our allocation is not guaranteed to be zero-based anymore, and we have to make sure we allocate it on a boundary that is compatible with the PCI Multi-MSI constraints.
Fix this by allocating the full region upfront instead of iterating over the number of MSIs. MSI-X are always allocated one by one, so this shouldn't change anything on that front.
drivers/irqchip/irq-gic-v3-its.c +13 -12
@@ -2399,13 +2399,14 @@ static void its_free_device(struct its_device *its_dev)kfree (its_dev); } -static int its_alloc_device_irq (struct its_device *dev,irq_hw_number_t *hwirq) +static int its_alloc_device_irq (struct its_device *dev,int nvecs,irq_hw_number_t *hwirq) {int idx; - idx =find_first_zero_bit (dev->event_map.lpi_map, - dev->event_map.nr_lpis); -if (idx == dev->event_map.nr_lpis) + idx =bitmap_find_free_region (dev->event_map.lpi_map, + dev->event_map.nr_lpis, +get_count_order (nvecs)); +if (idx <0 )return -ENOSPC ; *hwirq = dev->event_map.lpi_base + idx;
@@ -2501,21 +2502,21 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,int err;int i; -for (i =0 ; i < nr_irqs; i++) { - err =its_alloc_device_irq (its_dev, &hwirq); -if (err) -return err; + err =its_alloc_device_irq (its_dev, nr_irqs, &hwirq); +if (err) +return err; - err =its_irq_gic_domain_alloc (domain, virq + i, hwirq); +for (i =0 ; i < nr_irqs; i++) { + err =its_irq_gic_domain_alloc (domain, virq + i, hwirq + i);if (err)return err;irq_domain_set_hwirq_and_chip (domain, virq + i, - hwirq, &its_irq_chip, its_dev); + hwirq + i, &its_irq_chip, its_dev);irqd_set_single_target (irq_desc_get_irq_data (irq_to_desc (virq + i)));pr_debug ("ID:%d pID:%d vID:%d\n" , - (int )(hwirq - its_dev->event_map.lpi_base), - (int ) hwirq, virq + i); + (int )(hwirq + i - its_dev->event_map.lpi_base), + (int )(hwirq + i), virq + i); }return 0 ;