Commit 78fea633 authored by Linus Torvalds's avatar Linus Torvalds

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
parents e0bc833d bed9df97
...@@ -199,7 +199,7 @@ static int gicv2m_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, ...@@ -199,7 +199,7 @@ static int gicv2m_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
fail: fail:
irq_domain_free_irqs_parent(domain, virq, nr_irqs); 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; return err;
} }
......
...@@ -182,6 +182,22 @@ static struct its_collection *dev_event_to_col(struct its_device *its_dev, ...@@ -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]; 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 * ITS command descriptors - parameters to be encoded in a command
* block. * block.
...@@ -439,7 +455,7 @@ static struct its_collection *its_build_mapti_cmd(struct its_node *its, ...@@ -439,7 +455,7 @@ static struct its_collection *its_build_mapti_cmd(struct its_node *its,
its_fixup_cmd(cmd); its_fixup_cmd(cmd);
return col; return valid_col(col);
} }
static struct its_collection *its_build_movi_cmd(struct its_node *its, 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, ...@@ -458,7 +474,7 @@ static struct its_collection *its_build_movi_cmd(struct its_node *its,
its_fixup_cmd(cmd); its_fixup_cmd(cmd);
return col; return valid_col(col);
} }
static struct its_collection *its_build_discard_cmd(struct its_node *its, 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, ...@@ -476,7 +492,7 @@ static struct its_collection *its_build_discard_cmd(struct its_node *its,
its_fixup_cmd(cmd); its_fixup_cmd(cmd);
return col; return valid_col(col);
} }
static struct its_collection *its_build_inv_cmd(struct its_node *its, 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, ...@@ -494,7 +510,7 @@ static struct its_collection *its_build_inv_cmd(struct its_node *its,
its_fixup_cmd(cmd); its_fixup_cmd(cmd);
return col; return valid_col(col);
} }
static struct its_collection *its_build_int_cmd(struct its_node *its, 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, ...@@ -512,7 +528,7 @@ static struct its_collection *its_build_int_cmd(struct its_node *its,
its_fixup_cmd(cmd); its_fixup_cmd(cmd);
return col; return valid_col(col);
} }
static struct its_collection *its_build_clear_cmd(struct its_node *its, 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, ...@@ -530,7 +546,7 @@ static struct its_collection *its_build_clear_cmd(struct its_node *its,
its_fixup_cmd(cmd); its_fixup_cmd(cmd);
return col; return valid_col(col);
} }
static struct its_collection *its_build_invall_cmd(struct its_node *its, 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, ...@@ -554,7 +570,7 @@ static struct its_vpe *its_build_vinvall_cmd(struct its_node *its,
its_fixup_cmd(cmd); 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, 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, ...@@ -576,7 +592,7 @@ static struct its_vpe *its_build_vmapp_cmd(struct its_node *its,
its_fixup_cmd(cmd); 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, 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, ...@@ -599,7 +615,7 @@ static struct its_vpe *its_build_vmapti_cmd(struct its_node *its,
its_fixup_cmd(cmd); 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, 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, ...@@ -622,7 +638,7 @@ static struct its_vpe *its_build_vmovi_cmd(struct its_node *its,
its_fixup_cmd(cmd); 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, 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, ...@@ -640,7 +656,7 @@ static struct its_vpe *its_build_vmovp_cmd(struct its_node *its,
its_fixup_cmd(cmd); 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, static u64 its_cmd_ptr_to_offset(struct its_node *its,
...@@ -1824,11 +1840,16 @@ static int its_alloc_tables(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) static int its_alloc_collections(struct its_node *its)
{ {
int i;
its->collections = kcalloc(nr_cpu_ids, sizeof(*its->collections), its->collections = kcalloc(nr_cpu_ids, sizeof(*its->collections),
GFP_KERNEL); GFP_KERNEL);
if (!its->collections) if (!its->collections)
return -ENOMEM; return -ENOMEM;
for (i = 0; i < nr_cpu_ids; i++)
its->collections[i].target_address = ~0ULL;
return 0; return 0;
} }
...@@ -2310,7 +2331,14 @@ static int its_irq_domain_activate(struct irq_domain *domain, ...@@ -2310,7 +2331,14 @@ static int its_irq_domain_activate(struct irq_domain *domain,
cpu_mask = cpumask_of_node(its_dev->its->numa_node); cpu_mask = cpumask_of_node(its_dev->its->numa_node);
/* Bind the LPI to the first possible CPU */ /* 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; its_dev->event_map.col_map[event] = cpu;
irq_data_update_effective_affinity(d, cpumask_of(cpu)); irq_data_update_effective_affinity(d, cpumask_of(cpu));
...@@ -3399,6 +3427,16 @@ static int redist_disable_lpis(void) ...@@ -3399,6 +3427,16 @@ static int redist_disable_lpis(void)
u64 timeout = USEC_PER_SEC; u64 timeout = USEC_PER_SEC;
u64 val; 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()) { if (!gic_rdists_supports_plpis()) {
pr_info("CPU%d: LPIs not supported\n", smp_processor_id()); pr_info("CPU%d: LPIs not supported\n", smp_processor_id());
return -ENXIO; return -ENXIO;
......
...@@ -93,8 +93,12 @@ static void ls_scfg_msi_compose_msg(struct irq_data *data, struct msi_msg *msg) ...@@ -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->address_lo = lower_32_bits(msi_data->msiir_addr);
msg->data = data->hwirq; msg->data = data->hwirq;
if (msi_affinity_flag) if (msi_affinity_flag) {
msg->data |= cpumask_first(data->common->affinity); 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); iommu_dma_map_msi_msg(data->irq, msg);
} }
...@@ -121,7 +125,7 @@ static int ls_scfg_msi_set_affinity(struct irq_data *irq_data, ...@@ -121,7 +125,7 @@ static int ls_scfg_msi_set_affinity(struct irq_data *irq_data,
return -EINVAL; return -EINVAL;
} }
cpumask_copy(irq_data->common->affinity, mask); irq_data_update_effective_affinity(irq_data, cpumask_of(cpu));
return IRQ_SET_MASK_OK; return IRQ_SET_MASK_OK;
} }
......
...@@ -503,6 +503,7 @@ struct irq_chip { ...@@ -503,6 +503,7 @@ struct irq_chip {
* IRQCHIP_SKIP_SET_WAKE: Skip chip.irq_set_wake(), for this 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_ONESHOT_SAFE: One shot does not require mask/unmask
* IRQCHIP_EOI_THREADED: Chip requires eoi() on unmask in threaded mode * IRQCHIP_EOI_THREADED: Chip requires eoi() on unmask in threaded mode
* IRQCHIP_SUPPORTS_LEVEL_MSI Chip can provide two doorbells for Level MSIs
*/ */
enum { enum {
IRQCHIP_SET_TYPE_MASKED = (1 << 0), IRQCHIP_SET_TYPE_MASKED = (1 << 0),
......
...@@ -145,11 +145,6 @@ static inline void *irq_desc_get_handler_data(struct irq_desc *desc) ...@@ -145,11 +145,6 @@ static inline void *irq_desc_get_handler_data(struct irq_desc *desc)
return desc->irq_common_data.handler_data; 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 * Architectures call this to let the generic IRQ layer
* handle an interrupt. * handle an interrupt.
......
...@@ -55,6 +55,7 @@ static const struct irq_bit_descr irqchip_flags[] = { ...@@ -55,6 +55,7 @@ static const struct irq_bit_descr irqchip_flags[] = {
BIT_MASK_DESCR(IRQCHIP_SKIP_SET_WAKE), BIT_MASK_DESCR(IRQCHIP_SKIP_SET_WAKE),
BIT_MASK_DESCR(IRQCHIP_ONESHOT_SAFE), BIT_MASK_DESCR(IRQCHIP_ONESHOT_SAFE),
BIT_MASK_DESCR(IRQCHIP_EOI_THREADED), BIT_MASK_DESCR(IRQCHIP_EOI_THREADED),
BIT_MASK_DESCR(IRQCHIP_SUPPORTS_LEVEL_MSI),
}; };
static void static void
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment