Merge branch 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull irq fixes from Thomas Gleixner:
 "A set of fixes mostly for the ARM/GIC world:

   - Fix the MSI affinity handling in the ls-scfg irq chip driver so it
     updates and uses the effective affinity mask correctly

   - Prevent binding LPIs to offline CPUs and respect the Cavium erratum
     which requires that LPIs which belong to an offline NUMA node are
     not bound to a CPU on a different NUMA node.

   - Free only the amount of allocated interrupts in the GIC-V2M driver
     instead of trying to free log2(nrirqs).

   - Prevent emitting SYNC and VSYNC targetting non existing interrupt
     collections in the GIC-V3 ITS driver

   - Ensure that the GIV-V3 interrupt redistributor is correctly
     reprogrammed on CPU hotplug

   - Remove a stale unused helper function"

* 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  irqdesc: Delete irq_desc_get_msi_desc()
  irqchip/gic-v3-its: Fix reprogramming of redistributors on CPU hotplug
  irqchip/gic-v3-its: Only emit VSYNC if targetting a valid collection
  irqchip/gic-v3-its: Only emit SYNC if targetting a valid collection
  irqchip/gic-v3-its: Don't bind LPI to unavailable NUMA node
  irqchip/gic-v2m: Fix SPI release on error path
  irqchip/ls-scfg-msi: Fix MSI affinity handling
  genirq/debugfs: Add missing IRQCHIP_SUPPORTS_LEVEL_MSI debug
This commit is contained in:
Linus Torvalds 2018-06-24 19:01:18 +08:00
commit 78fea6334f
6 changed files with 60 additions and 21 deletions

View File

@ -199,7 +199,7 @@ static int gicv2m_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
fail:
irq_domain_free_irqs_parent(domain, virq, nr_irqs);
gicv2m_unalloc_msi(v2m, hwirq, get_count_order(nr_irqs));
gicv2m_unalloc_msi(v2m, hwirq, nr_irqs);
return err;
}

View File

@ -182,6 +182,22 @@ static struct its_collection *dev_event_to_col(struct its_device *its_dev,
return its->collections + its_dev->event_map.col_map[event];
}
static struct its_collection *valid_col(struct its_collection *col)
{
if (WARN_ON_ONCE(col->target_address & GENMASK_ULL(0, 15)))
return NULL;
return col;
}
static struct its_vpe *valid_vpe(struct its_node *its, struct its_vpe *vpe)
{
if (valid_col(its->collections + vpe->col_idx))
return vpe;
return NULL;
}
/*
* ITS command descriptors - parameters to be encoded in a command
* block.
@ -439,7 +455,7 @@ static struct its_collection *its_build_mapti_cmd(struct its_node *its,
its_fixup_cmd(cmd);
return col;
return valid_col(col);
}
static struct its_collection *its_build_movi_cmd(struct its_node *its,
@ -458,7 +474,7 @@ static struct its_collection *its_build_movi_cmd(struct its_node *its,
its_fixup_cmd(cmd);
return col;
return valid_col(col);
}
static struct its_collection *its_build_discard_cmd(struct its_node *its,
@ -476,7 +492,7 @@ static struct its_collection *its_build_discard_cmd(struct its_node *its,
its_fixup_cmd(cmd);
return col;
return valid_col(col);
}
static struct its_collection *its_build_inv_cmd(struct its_node *its,
@ -494,7 +510,7 @@ static struct its_collection *its_build_inv_cmd(struct its_node *its,
its_fixup_cmd(cmd);
return col;
return valid_col(col);
}
static struct its_collection *its_build_int_cmd(struct its_node *its,
@ -512,7 +528,7 @@ static struct its_collection *its_build_int_cmd(struct its_node *its,
its_fixup_cmd(cmd);
return col;
return valid_col(col);
}
static struct its_collection *its_build_clear_cmd(struct its_node *its,
@ -530,7 +546,7 @@ static struct its_collection *its_build_clear_cmd(struct its_node *its,
its_fixup_cmd(cmd);
return col;
return valid_col(col);
}
static struct its_collection *its_build_invall_cmd(struct its_node *its,
@ -554,7 +570,7 @@ static struct its_vpe *its_build_vinvall_cmd(struct its_node *its,
its_fixup_cmd(cmd);
return desc->its_vinvall_cmd.vpe;
return valid_vpe(its, desc->its_vinvall_cmd.vpe);
}
static struct its_vpe *its_build_vmapp_cmd(struct its_node *its,
@ -576,7 +592,7 @@ static struct its_vpe *its_build_vmapp_cmd(struct its_node *its,
its_fixup_cmd(cmd);
return desc->its_vmapp_cmd.vpe;
return valid_vpe(its, desc->its_vmapp_cmd.vpe);
}
static struct its_vpe *its_build_vmapti_cmd(struct its_node *its,
@ -599,7 +615,7 @@ static struct its_vpe *its_build_vmapti_cmd(struct its_node *its,
its_fixup_cmd(cmd);
return desc->its_vmapti_cmd.vpe;
return valid_vpe(its, desc->its_vmapti_cmd.vpe);
}
static struct its_vpe *its_build_vmovi_cmd(struct its_node *its,
@ -622,7 +638,7 @@ static struct its_vpe *its_build_vmovi_cmd(struct its_node *its,
its_fixup_cmd(cmd);
return desc->its_vmovi_cmd.vpe;
return valid_vpe(its, desc->its_vmovi_cmd.vpe);
}
static struct its_vpe *its_build_vmovp_cmd(struct its_node *its,
@ -640,7 +656,7 @@ static struct its_vpe *its_build_vmovp_cmd(struct its_node *its,
its_fixup_cmd(cmd);
return desc->its_vmovp_cmd.vpe;
return valid_vpe(its, desc->its_vmovp_cmd.vpe);
}
static u64 its_cmd_ptr_to_offset(struct its_node *its,
@ -1824,11 +1840,16 @@ static int its_alloc_tables(struct its_node *its)
static int its_alloc_collections(struct its_node *its)
{
int i;
its->collections = kcalloc(nr_cpu_ids, sizeof(*its->collections),
GFP_KERNEL);
if (!its->collections)
return -ENOMEM;
for (i = 0; i < nr_cpu_ids; i++)
its->collections[i].target_address = ~0ULL;
return 0;
}
@ -2310,7 +2331,14 @@ static int its_irq_domain_activate(struct irq_domain *domain,
cpu_mask = cpumask_of_node(its_dev->its->numa_node);
/* Bind the LPI to the first possible CPU */
cpu = cpumask_first(cpu_mask);
cpu = cpumask_first_and(cpu_mask, cpu_online_mask);
if (cpu >= nr_cpu_ids) {
if (its_dev->its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_23144)
return -EINVAL;
cpu = cpumask_first(cpu_online_mask);
}
its_dev->event_map.col_map[event] = cpu;
irq_data_update_effective_affinity(d, cpumask_of(cpu));
@ -3399,6 +3427,16 @@ static int redist_disable_lpis(void)
u64 timeout = USEC_PER_SEC;
u64 val;
/*
* If coming via a CPU hotplug event, we don't need to disable
* LPIs before trying to re-enable them. They are already
* configured and all is well in the world. Detect this case
* by checking the allocation of the pending table for the
* current CPU.
*/
if (gic_data_rdist()->pend_page)
return 0;
if (!gic_rdists_supports_plpis()) {
pr_info("CPU%d: LPIs not supported\n", smp_processor_id());
return -ENXIO;

View File

@ -93,8 +93,12 @@ static void ls_scfg_msi_compose_msg(struct irq_data *data, struct msi_msg *msg)
msg->address_lo = lower_32_bits(msi_data->msiir_addr);
msg->data = data->hwirq;
if (msi_affinity_flag)
msg->data |= cpumask_first(data->common->affinity);
if (msi_affinity_flag) {
const struct cpumask *mask;
mask = irq_data_get_effective_affinity_mask(data);
msg->data |= cpumask_first(mask);
}
iommu_dma_map_msi_msg(data->irq, msg);
}
@ -121,7 +125,7 @@ static int ls_scfg_msi_set_affinity(struct irq_data *irq_data,
return -EINVAL;
}
cpumask_copy(irq_data->common->affinity, mask);
irq_data_update_effective_affinity(irq_data, cpumask_of(cpu));
return IRQ_SET_MASK_OK;
}

View File

@ -503,6 +503,7 @@ struct irq_chip {
* IRQCHIP_SKIP_SET_WAKE: Skip chip.irq_set_wake(), for this irq chip
* IRQCHIP_ONESHOT_SAFE: One shot does not require mask/unmask
* IRQCHIP_EOI_THREADED: Chip requires eoi() on unmask in threaded mode
* IRQCHIP_SUPPORTS_LEVEL_MSI Chip can provide two doorbells for Level MSIs
*/
enum {
IRQCHIP_SET_TYPE_MASKED = (1 << 0),

View File

@ -145,11 +145,6 @@ static inline void *irq_desc_get_handler_data(struct irq_desc *desc)
return desc->irq_common_data.handler_data;
}
static inline struct msi_desc *irq_desc_get_msi_desc(struct irq_desc *desc)
{
return desc->irq_common_data.msi_desc;
}
/*
* Architectures call this to let the generic IRQ layer
* handle an interrupt.

View File

@ -55,6 +55,7 @@ static const struct irq_bit_descr irqchip_flags[] = {
BIT_MASK_DESCR(IRQCHIP_SKIP_SET_WAKE),
BIT_MASK_DESCR(IRQCHIP_ONESHOT_SAFE),
BIT_MASK_DESCR(IRQCHIP_EOI_THREADED),
BIT_MASK_DESCR(IRQCHIP_SUPPORTS_LEVEL_MSI),
};
static void