|
@@ -68,22 +68,6 @@
|
|
|
#define for_each_irq_pin(entry, head) \
|
|
|
for (entry = head; entry; entry = entry->next)
|
|
|
|
|
|
-#ifdef CONFIG_IRQ_REMAP
|
|
|
-static void irq_remap_modify_chip_defaults(struct irq_chip *chip);
|
|
|
-static inline bool irq_remapped(struct irq_cfg *cfg)
|
|
|
-{
|
|
|
- return cfg->irq_2_iommu.iommu != NULL;
|
|
|
-}
|
|
|
-#else
|
|
|
-static inline bool irq_remapped(struct irq_cfg *cfg)
|
|
|
-{
|
|
|
- return false;
|
|
|
-}
|
|
|
-static inline void irq_remap_modify_chip_defaults(struct irq_chip *chip)
|
|
|
-{
|
|
|
-}
|
|
|
-#endif
|
|
|
-
|
|
|
/*
|
|
|
* Is the SiS APIC rmw bug present ?
|
|
|
* -1 = don't know, 0 = no, 1 = yes
|
|
@@ -326,7 +310,7 @@ static __attribute_const__ struct io_apic __iomem *io_apic_base(int idx)
|
|
|
+ (mpc_ioapic_addr(idx) & ~PAGE_MASK);
|
|
|
}
|
|
|
|
|
|
-static inline void io_apic_eoi(unsigned int apic, unsigned int vector)
|
|
|
+void io_apic_eoi(unsigned int apic, unsigned int vector)
|
|
|
{
|
|
|
struct io_apic __iomem *io_apic = io_apic_base(apic);
|
|
|
writel(vector, &io_apic->eoi);
|
|
@@ -573,19 +557,10 @@ static void unmask_ioapic_irq(struct irq_data *data)
|
|
|
* Otherwise, we simulate the EOI message manually by changing the trigger
|
|
|
* mode to edge and then back to level, with RTE being masked during this.
|
|
|
*/
|
|
|
-static void __eoi_ioapic_pin(int apic, int pin, int vector, struct irq_cfg *cfg)
|
|
|
+void native_eoi_ioapic_pin(int apic, int pin, int vector)
|
|
|
{
|
|
|
if (mpc_ioapic_ver(apic) >= 0x20) {
|
|
|
- /*
|
|
|
- * Intr-remapping uses pin number as the virtual vector
|
|
|
- * in the RTE. Actual vector is programmed in
|
|
|
- * intr-remapping table entry. Hence for the io-apic
|
|
|
- * EOI we use the pin number.
|
|
|
- */
|
|
|
- if (cfg && irq_remapped(cfg))
|
|
|
- io_apic_eoi(apic, pin);
|
|
|
- else
|
|
|
- io_apic_eoi(apic, vector);
|
|
|
+ io_apic_eoi(apic, vector);
|
|
|
} else {
|
|
|
struct IO_APIC_route_entry entry, entry1;
|
|
|
|
|
@@ -606,14 +581,15 @@ static void __eoi_ioapic_pin(int apic, int pin, int vector, struct irq_cfg *cfg)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static void eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
|
|
|
+void eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
|
|
|
{
|
|
|
struct irq_pin_list *entry;
|
|
|
unsigned long flags;
|
|
|
|
|
|
raw_spin_lock_irqsave(&ioapic_lock, flags);
|
|
|
for_each_irq_pin(entry, cfg->irq_2_pin)
|
|
|
- __eoi_ioapic_pin(entry->apic, entry->pin, cfg->vector, cfg);
|
|
|
+ x86_io_apic_ops.eoi_ioapic_pin(entry->apic, entry->pin,
|
|
|
+ cfg->vector);
|
|
|
raw_spin_unlock_irqrestore(&ioapic_lock, flags);
|
|
|
}
|
|
|
|
|
@@ -650,7 +626,7 @@ static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
|
|
|
}
|
|
|
|
|
|
raw_spin_lock_irqsave(&ioapic_lock, flags);
|
|
|
- __eoi_ioapic_pin(apic, pin, entry.vector, NULL);
|
|
|
+ x86_io_apic_ops.eoi_ioapic_pin(apic, pin, entry.vector);
|
|
|
raw_spin_unlock_irqrestore(&ioapic_lock, flags);
|
|
|
}
|
|
|
|
|
@@ -1304,25 +1280,18 @@ static void ioapic_register_intr(unsigned int irq, struct irq_cfg *cfg,
|
|
|
fasteoi = false;
|
|
|
}
|
|
|
|
|
|
- if (irq_remapped(cfg)) {
|
|
|
- irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
|
|
|
- irq_remap_modify_chip_defaults(chip);
|
|
|
+ if (setup_remapped_irq(irq, cfg, chip))
|
|
|
fasteoi = trigger != 0;
|
|
|
- }
|
|
|
|
|
|
hdl = fasteoi ? handle_fasteoi_irq : handle_edge_irq;
|
|
|
irq_set_chip_and_handler_name(irq, chip, hdl,
|
|
|
fasteoi ? "fasteoi" : "edge");
|
|
|
}
|
|
|
|
|
|
-static int setup_ioapic_entry(int irq, struct IO_APIC_route_entry *entry,
|
|
|
- unsigned int destination, int vector,
|
|
|
- struct io_apic_irq_attr *attr)
|
|
|
+int native_setup_ioapic_entry(int irq, struct IO_APIC_route_entry *entry,
|
|
|
+ unsigned int destination, int vector,
|
|
|
+ struct io_apic_irq_attr *attr)
|
|
|
{
|
|
|
- if (irq_remapping_enabled)
|
|
|
- return setup_ioapic_remapped_entry(irq, entry, destination,
|
|
|
- vector, attr);
|
|
|
-
|
|
|
memset(entry, 0, sizeof(*entry));
|
|
|
|
|
|
entry->delivery_mode = apic->irq_delivery_mode;
|
|
@@ -1370,8 +1339,8 @@ static void setup_ioapic_irq(unsigned int irq, struct irq_cfg *cfg,
|
|
|
attr->ioapic, mpc_ioapic_id(attr->ioapic), attr->ioapic_pin,
|
|
|
cfg->vector, irq, attr->trigger, attr->polarity, dest);
|
|
|
|
|
|
- if (setup_ioapic_entry(irq, &entry, dest, cfg->vector, attr)) {
|
|
|
- pr_warn("Failed to setup ioapic entry for ioapic %d, pin %d\n",
|
|
|
+ if (x86_io_apic_ops.setup_entry(irq, &entry, dest, cfg->vector, attr)) {
|
|
|
+ pr_warn("Failed to setup ioapic entry for ioapic %d, pin %d\n",
|
|
|
mpc_ioapic_id(attr->ioapic), attr->ioapic_pin);
|
|
|
__clear_irq_vector(irq, cfg);
|
|
|
|
|
@@ -1479,9 +1448,6 @@ static void __init setup_timer_IRQ0_pin(unsigned int ioapic_idx,
|
|
|
struct IO_APIC_route_entry entry;
|
|
|
unsigned int dest;
|
|
|
|
|
|
- if (irq_remapping_enabled)
|
|
|
- return;
|
|
|
-
|
|
|
memset(&entry, 0, sizeof(entry));
|
|
|
|
|
|
/*
|
|
@@ -1513,9 +1479,63 @@ static void __init setup_timer_IRQ0_pin(unsigned int ioapic_idx,
|
|
|
ioapic_write_entry(ioapic_idx, pin, entry);
|
|
|
}
|
|
|
|
|
|
-__apicdebuginit(void) print_IO_APIC(int ioapic_idx)
|
|
|
+void native_io_apic_print_entries(unsigned int apic, unsigned int nr_entries)
|
|
|
{
|
|
|
int i;
|
|
|
+
|
|
|
+ pr_debug(" NR Dst Mask Trig IRR Pol Stat Dmod Deli Vect:\n");
|
|
|
+
|
|
|
+ for (i = 0; i <= nr_entries; i++) {
|
|
|
+ struct IO_APIC_route_entry entry;
|
|
|
+
|
|
|
+ entry = ioapic_read_entry(apic, i);
|
|
|
+
|
|
|
+ pr_debug(" %02x %02X ", i, entry.dest);
|
|
|
+ pr_cont("%1d %1d %1d %1d %1d "
|
|
|
+ "%1d %1d %02X\n",
|
|
|
+ entry.mask,
|
|
|
+ entry.trigger,
|
|
|
+ entry.irr,
|
|
|
+ entry.polarity,
|
|
|
+ entry.delivery_status,
|
|
|
+ entry.dest_mode,
|
|
|
+ entry.delivery_mode,
|
|
|
+ entry.vector);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void intel_ir_io_apic_print_entries(unsigned int apic,
|
|
|
+ unsigned int nr_entries)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ pr_debug(" NR Indx Fmt Mask Trig IRR Pol Stat Indx2 Zero Vect:\n");
|
|
|
+
|
|
|
+ for (i = 0; i <= nr_entries; i++) {
|
|
|
+ struct IR_IO_APIC_route_entry *ir_entry;
|
|
|
+ struct IO_APIC_route_entry entry;
|
|
|
+
|
|
|
+ entry = ioapic_read_entry(apic, i);
|
|
|
+
|
|
|
+ ir_entry = (struct IR_IO_APIC_route_entry *)&entry;
|
|
|
+
|
|
|
+ pr_debug(" %02x %04X ", i, ir_entry->index);
|
|
|
+ pr_cont("%1d %1d %1d %1d %1d "
|
|
|
+ "%1d %1d %X %02X\n",
|
|
|
+ ir_entry->format,
|
|
|
+ ir_entry->mask,
|
|
|
+ ir_entry->trigger,
|
|
|
+ ir_entry->irr,
|
|
|
+ ir_entry->polarity,
|
|
|
+ ir_entry->delivery_status,
|
|
|
+ ir_entry->index2,
|
|
|
+ ir_entry->zero,
|
|
|
+ ir_entry->vector);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+__apicdebuginit(void) print_IO_APIC(int ioapic_idx)
|
|
|
+{
|
|
|
union IO_APIC_reg_00 reg_00;
|
|
|
union IO_APIC_reg_01 reg_01;
|
|
|
union IO_APIC_reg_02 reg_02;
|
|
@@ -1568,58 +1588,7 @@ __apicdebuginit(void) print_IO_APIC(int ioapic_idx)
|
|
|
|
|
|
printk(KERN_DEBUG ".... IRQ redirection table:\n");
|
|
|
|
|
|
- if (irq_remapping_enabled) {
|
|
|
- printk(KERN_DEBUG " NR Indx Fmt Mask Trig IRR"
|
|
|
- " Pol Stat Indx2 Zero Vect:\n");
|
|
|
- } else {
|
|
|
- printk(KERN_DEBUG " NR Dst Mask Trig IRR Pol"
|
|
|
- " Stat Dmod Deli Vect:\n");
|
|
|
- }
|
|
|
-
|
|
|
- for (i = 0; i <= reg_01.bits.entries; i++) {
|
|
|
- if (irq_remapping_enabled) {
|
|
|
- struct IO_APIC_route_entry entry;
|
|
|
- struct IR_IO_APIC_route_entry *ir_entry;
|
|
|
-
|
|
|
- entry = ioapic_read_entry(ioapic_idx, i);
|
|
|
- ir_entry = (struct IR_IO_APIC_route_entry *) &entry;
|
|
|
- printk(KERN_DEBUG " %02x %04X ",
|
|
|
- i,
|
|
|
- ir_entry->index
|
|
|
- );
|
|
|
- pr_cont("%1d %1d %1d %1d %1d "
|
|
|
- "%1d %1d %X %02X\n",
|
|
|
- ir_entry->format,
|
|
|
- ir_entry->mask,
|
|
|
- ir_entry->trigger,
|
|
|
- ir_entry->irr,
|
|
|
- ir_entry->polarity,
|
|
|
- ir_entry->delivery_status,
|
|
|
- ir_entry->index2,
|
|
|
- ir_entry->zero,
|
|
|
- ir_entry->vector
|
|
|
- );
|
|
|
- } else {
|
|
|
- struct IO_APIC_route_entry entry;
|
|
|
-
|
|
|
- entry = ioapic_read_entry(ioapic_idx, i);
|
|
|
- printk(KERN_DEBUG " %02x %02X ",
|
|
|
- i,
|
|
|
- entry.dest
|
|
|
- );
|
|
|
- pr_cont("%1d %1d %1d %1d %1d "
|
|
|
- "%1d %1d %02X\n",
|
|
|
- entry.mask,
|
|
|
- entry.trigger,
|
|
|
- entry.irr,
|
|
|
- entry.polarity,
|
|
|
- entry.delivery_status,
|
|
|
- entry.dest_mode,
|
|
|
- entry.delivery_mode,
|
|
|
- entry.vector
|
|
|
- );
|
|
|
- }
|
|
|
- }
|
|
|
+ x86_io_apic_ops.print_entries(ioapic_idx, reg_01.bits.entries);
|
|
|
}
|
|
|
|
|
|
__apicdebuginit(void) print_IO_APICs(void)
|
|
@@ -1921,30 +1890,14 @@ void __init enable_IO_APIC(void)
|
|
|
clear_IO_APIC();
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Not an __init, needed by the reboot code
|
|
|
- */
|
|
|
-void disable_IO_APIC(void)
|
|
|
+void native_disable_io_apic(void)
|
|
|
{
|
|
|
- /*
|
|
|
- * Clear the IO-APIC before rebooting:
|
|
|
- */
|
|
|
- clear_IO_APIC();
|
|
|
-
|
|
|
- if (!legacy_pic->nr_legacy_irqs)
|
|
|
- return;
|
|
|
-
|
|
|
/*
|
|
|
* If the i8259 is routed through an IOAPIC
|
|
|
* Put that IOAPIC in virtual wire mode
|
|
|
* so legacy interrupts can be delivered.
|
|
|
- *
|
|
|
- * With interrupt-remapping, for now we will use virtual wire A mode,
|
|
|
- * as virtual wire B is little complex (need to configure both
|
|
|
- * IOAPIC RTE as well as interrupt-remapping table entry).
|
|
|
- * As this gets called during crash dump, keep this simple for now.
|
|
|
*/
|
|
|
- if (ioapic_i8259.pin != -1 && !irq_remapping_enabled) {
|
|
|
+ if (ioapic_i8259.pin != -1) {
|
|
|
struct IO_APIC_route_entry entry;
|
|
|
|
|
|
memset(&entry, 0, sizeof(entry));
|
|
@@ -1964,12 +1917,25 @@ void disable_IO_APIC(void)
|
|
|
ioapic_write_entry(ioapic_i8259.apic, ioapic_i8259.pin, entry);
|
|
|
}
|
|
|
|
|
|
+ if (cpu_has_apic || apic_from_smp_config())
|
|
|
+ disconnect_bsp_APIC(ioapic_i8259.pin != -1);
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Not an __init, needed by the reboot code
|
|
|
+ */
|
|
|
+void disable_IO_APIC(void)
|
|
|
+{
|
|
|
/*
|
|
|
- * Use virtual wire A mode when interrupt remapping is enabled.
|
|
|
+ * Clear the IO-APIC before rebooting:
|
|
|
*/
|
|
|
- if (cpu_has_apic || apic_from_smp_config())
|
|
|
- disconnect_bsp_APIC(!irq_remapping_enabled &&
|
|
|
- ioapic_i8259.pin != -1);
|
|
|
+ clear_IO_APIC();
|
|
|
+
|
|
|
+ if (!legacy_pic->nr_legacy_irqs)
|
|
|
+ return;
|
|
|
+
|
|
|
+ x86_io_apic_ops.disable();
|
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_X86_32
|
|
@@ -2322,12 +2288,8 @@ static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq
|
|
|
|
|
|
apic = entry->apic;
|
|
|
pin = entry->pin;
|
|
|
- /*
|
|
|
- * With interrupt-remapping, destination information comes
|
|
|
- * from interrupt-remapping table entry.
|
|
|
- */
|
|
|
- if (!irq_remapped(cfg))
|
|
|
- io_apic_write(apic, 0x11 + pin*2, dest);
|
|
|
+
|
|
|
+ io_apic_write(apic, 0x11 + pin*2, dest);
|
|
|
reg = io_apic_read(apic, 0x10 + pin*2);
|
|
|
reg &= ~IO_APIC_REDIR_VECTOR_MASK;
|
|
|
reg |= vector;
|
|
@@ -2369,9 +2331,10 @@ int __ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int
|
|
|
-ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
|
|
|
- bool force)
|
|
|
+
|
|
|
+int native_ioapic_set_affinity(struct irq_data *data,
|
|
|
+ const struct cpumask *mask,
|
|
|
+ bool force)
|
|
|
{
|
|
|
unsigned int dest, irq = data->irq;
|
|
|
unsigned long flags;
|
|
@@ -2548,33 +2511,6 @@ static void ack_apic_level(struct irq_data *data)
|
|
|
ioapic_irqd_unmask(data, cfg, masked);
|
|
|
}
|
|
|
|
|
|
-#ifdef CONFIG_IRQ_REMAP
|
|
|
-static void ir_ack_apic_edge(struct irq_data *data)
|
|
|
-{
|
|
|
- ack_APIC_irq();
|
|
|
-}
|
|
|
-
|
|
|
-static void ir_ack_apic_level(struct irq_data *data)
|
|
|
-{
|
|
|
- ack_APIC_irq();
|
|
|
- eoi_ioapic_irq(data->irq, data->chip_data);
|
|
|
-}
|
|
|
-
|
|
|
-static void ir_print_prefix(struct irq_data *data, struct seq_file *p)
|
|
|
-{
|
|
|
- seq_printf(p, " IR-%s", data->chip->name);
|
|
|
-}
|
|
|
-
|
|
|
-static void irq_remap_modify_chip_defaults(struct irq_chip *chip)
|
|
|
-{
|
|
|
- chip->irq_print_chip = ir_print_prefix;
|
|
|
- chip->irq_ack = ir_ack_apic_edge;
|
|
|
- chip->irq_eoi = ir_ack_apic_level;
|
|
|
-
|
|
|
- chip->irq_set_affinity = set_remapped_irq_affinity;
|
|
|
-}
|
|
|
-#endif /* CONFIG_IRQ_REMAP */
|
|
|
-
|
|
|
static struct irq_chip ioapic_chip __read_mostly = {
|
|
|
.name = "IO-APIC",
|
|
|
.irq_startup = startup_ioapic_irq,
|
|
@@ -2582,7 +2518,7 @@ static struct irq_chip ioapic_chip __read_mostly = {
|
|
|
.irq_unmask = unmask_ioapic_irq,
|
|
|
.irq_ack = ack_apic_edge,
|
|
|
.irq_eoi = ack_apic_level,
|
|
|
- .irq_set_affinity = ioapic_set_affinity,
|
|
|
+ .irq_set_affinity = native_ioapic_set_affinity,
|
|
|
.irq_retrigger = ioapic_retrigger_irq,
|
|
|
};
|
|
|
|
|
@@ -2781,8 +2717,7 @@ static inline void __init check_timer(void)
|
|
|
* 8259A.
|
|
|
*/
|
|
|
if (pin1 == -1) {
|
|
|
- if (irq_remapping_enabled)
|
|
|
- panic("BIOS bug: timer not connected to IO-APIC");
|
|
|
+ panic_if_irq_remap("BIOS bug: timer not connected to IO-APIC");
|
|
|
pin1 = pin2;
|
|
|
apic1 = apic2;
|
|
|
no_pin1 = 1;
|
|
@@ -2814,8 +2749,7 @@ static inline void __init check_timer(void)
|
|
|
clear_IO_APIC_pin(0, pin1);
|
|
|
goto out;
|
|
|
}
|
|
|
- if (irq_remapping_enabled)
|
|
|
- panic("timer doesn't work through Interrupt-remapped IO-APIC");
|
|
|
+ panic_if_irq_remap("timer doesn't work through Interrupt-remapped IO-APIC");
|
|
|
local_irq_disable();
|
|
|
clear_IO_APIC_pin(apic1, pin1);
|
|
|
if (!no_pin1)
|
|
@@ -3058,15 +2992,15 @@ void destroy_irq(unsigned int irq)
|
|
|
|
|
|
irq_set_status_flags(irq, IRQ_NOREQUEST|IRQ_NOPROBE);
|
|
|
|
|
|
- if (irq_remapped(cfg))
|
|
|
- free_remapped_irq(irq);
|
|
|
+ free_remapped_irq(irq);
|
|
|
+
|
|
|
raw_spin_lock_irqsave(&vector_lock, flags);
|
|
|
__clear_irq_vector(irq, cfg);
|
|
|
raw_spin_unlock_irqrestore(&vector_lock, flags);
|
|
|
free_irq_at(irq, cfg);
|
|
|
}
|
|
|
|
|
|
-static inline void destroy_irqs(unsigned int irq, unsigned int count)
|
|
|
+void destroy_irqs(unsigned int irq, unsigned int count)
|
|
|
{
|
|
|
unsigned int i;
|
|
|
|
|
@@ -3077,37 +3011,16 @@ static inline void destroy_irqs(unsigned int irq, unsigned int count)
|
|
|
/*
|
|
|
* MSI message composition
|
|
|
*/
|
|
|
-#ifdef CONFIG_PCI_MSI
|
|
|
-static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq,
|
|
|
- struct msi_msg *msg, u8 hpet_id)
|
|
|
+void native_compose_msi_msg(struct pci_dev *pdev,
|
|
|
+ unsigned int irq, unsigned int dest,
|
|
|
+ struct msi_msg *msg, u8 hpet_id)
|
|
|
{
|
|
|
- struct irq_cfg *cfg;
|
|
|
- int err;
|
|
|
- unsigned dest;
|
|
|
+ struct irq_cfg *cfg = irq_cfg(irq);
|
|
|
|
|
|
- if (disable_apic)
|
|
|
- return -ENXIO;
|
|
|
-
|
|
|
- cfg = irq_cfg(irq);
|
|
|
- err = assign_irq_vector(irq, cfg, apic->target_cpus());
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- err = apic->cpu_mask_to_apicid_and(cfg->domain,
|
|
|
- apic->target_cpus(), &dest);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- if (irq_remapped(cfg)) {
|
|
|
- compose_remapped_msi_msg(pdev, irq, dest, msg, hpet_id);
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ msg->address_hi = MSI_ADDR_BASE_HI;
|
|
|
|
|
|
if (x2apic_enabled())
|
|
|
- msg->address_hi = MSI_ADDR_BASE_HI |
|
|
|
- MSI_ADDR_EXT_DEST_ID(dest);
|
|
|
- else
|
|
|
- msg->address_hi = MSI_ADDR_BASE_HI;
|
|
|
+ msg->address_hi |= MSI_ADDR_EXT_DEST_ID(dest);
|
|
|
|
|
|
msg->address_lo =
|
|
|
MSI_ADDR_BASE_LO |
|
|
@@ -3126,6 +3039,30 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq,
|
|
|
MSI_DATA_DELIVERY_FIXED:
|
|
|
MSI_DATA_DELIVERY_LOWPRI) |
|
|
|
MSI_DATA_VECTOR(cfg->vector);
|
|
|
+}
|
|
|
+
|
|
|
+#ifdef CONFIG_PCI_MSI
|
|
|
+static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq,
|
|
|
+ struct msi_msg *msg, u8 hpet_id)
|
|
|
+{
|
|
|
+ struct irq_cfg *cfg;
|
|
|
+ int err;
|
|
|
+ unsigned dest;
|
|
|
+
|
|
|
+ if (disable_apic)
|
|
|
+ return -ENXIO;
|
|
|
+
|
|
|
+ cfg = irq_cfg(irq);
|
|
|
+ err = assign_irq_vector(irq, cfg, apic->target_cpus());
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ err = apic->cpu_mask_to_apicid_and(cfg->domain,
|
|
|
+ apic->target_cpus(), &dest);
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ x86_msi.compose_msi_msg(pdev, irq, dest, msg, hpet_id);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -3165,8 +3102,8 @@ static struct irq_chip msi_chip = {
|
|
|
.irq_retrigger = ioapic_retrigger_irq,
|
|
|
};
|
|
|
|
|
|
-static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,
|
|
|
- unsigned int irq_base, unsigned int irq_offset)
|
|
|
+int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,
|
|
|
+ unsigned int irq_base, unsigned int irq_offset)
|
|
|
{
|
|
|
struct irq_chip *chip = &msi_chip;
|
|
|
struct msi_msg msg;
|
|
@@ -3186,10 +3123,7 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,
|
|
|
if (!irq_offset)
|
|
|
write_msi_msg(irq, &msg);
|
|
|
|
|
|
- if (irq_remapped(irq_get_chip_data(irq))) {
|
|
|
- irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
|
|
|
- irq_remap_modify_chip_defaults(chip);
|
|
|
- }
|
|
|
+ setup_remapped_irq(irq, irq_get_chip_data(irq), chip);
|
|
|
|
|
|
irq_set_chip_and_handler_name(irq, chip, handle_edge_irq, "edge");
|
|
|
|
|
@@ -3198,44 +3132,28 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-int setup_msix_irqs(struct pci_dev *dev, int nvec)
|
|
|
+int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
|
|
|
{
|
|
|
- int node, ret, sub_handle, index = 0;
|
|
|
unsigned int irq, irq_want;
|
|
|
struct msi_desc *msidesc;
|
|
|
+ int node, ret;
|
|
|
+
|
|
|
+ /* Multiple MSI vectors only supported with interrupt remapping */
|
|
|
+ if (type == PCI_CAP_ID_MSI && nvec > 1)
|
|
|
+ return 1;
|
|
|
|
|
|
node = dev_to_node(&dev->dev);
|
|
|
irq_want = nr_irqs_gsi;
|
|
|
- sub_handle = 0;
|
|
|
list_for_each_entry(msidesc, &dev->msi_list, list) {
|
|
|
irq = create_irq_nr(irq_want, node);
|
|
|
if (irq == 0)
|
|
|
return -ENOSPC;
|
|
|
+
|
|
|
irq_want = irq + 1;
|
|
|
- if (!irq_remapping_enabled)
|
|
|
- goto no_ir;
|
|
|
|
|
|
- if (!sub_handle) {
|
|
|
- /*
|
|
|
- * allocate the consecutive block of IRTE's
|
|
|
- * for 'nvec'
|
|
|
- */
|
|
|
- index = msi_alloc_remapped_irq(dev, irq, nvec);
|
|
|
- if (index < 0) {
|
|
|
- ret = index;
|
|
|
- goto error;
|
|
|
- }
|
|
|
- } else {
|
|
|
- ret = msi_setup_remapped_irq(dev, irq, index,
|
|
|
- sub_handle);
|
|
|
- if (ret < 0)
|
|
|
- goto error;
|
|
|
- }
|
|
|
-no_ir:
|
|
|
ret = setup_msi_irq(dev, msidesc, irq, 0);
|
|
|
if (ret < 0)
|
|
|
goto error;
|
|
|
- sub_handle++;
|
|
|
}
|
|
|
return 0;
|
|
|
|
|
@@ -3244,74 +3162,6 @@ error:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-int setup_msi_irqs(struct pci_dev *dev, int nvec)
|
|
|
-{
|
|
|
- int node, ret, sub_handle, index = 0;
|
|
|
- unsigned int irq;
|
|
|
- struct msi_desc *msidesc;
|
|
|
-
|
|
|
- if (nvec > 1 && !irq_remapping_enabled)
|
|
|
- return 1;
|
|
|
-
|
|
|
- nvec = __roundup_pow_of_two(nvec);
|
|
|
-
|
|
|
- WARN_ON(!list_is_singular(&dev->msi_list));
|
|
|
- msidesc = list_entry(dev->msi_list.next, struct msi_desc, list);
|
|
|
- WARN_ON(msidesc->irq);
|
|
|
- WARN_ON(msidesc->msi_attrib.multiple);
|
|
|
-
|
|
|
- node = dev_to_node(&dev->dev);
|
|
|
- irq = __create_irqs(nr_irqs_gsi, nvec, node);
|
|
|
- if (irq == 0)
|
|
|
- return -ENOSPC;
|
|
|
-
|
|
|
- if (!irq_remapping_enabled) {
|
|
|
- ret = setup_msi_irq(dev, msidesc, irq, 0);
|
|
|
- if (ret < 0)
|
|
|
- goto error;
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- msidesc->msi_attrib.multiple = ilog2(nvec);
|
|
|
- for (sub_handle = 0; sub_handle < nvec; sub_handle++) {
|
|
|
- if (!sub_handle) {
|
|
|
- index = msi_alloc_remapped_irq(dev, irq, nvec);
|
|
|
- if (index < 0) {
|
|
|
- ret = index;
|
|
|
- goto error;
|
|
|
- }
|
|
|
- } else {
|
|
|
- ret = msi_setup_remapped_irq(dev, irq + sub_handle,
|
|
|
- index, sub_handle);
|
|
|
- if (ret < 0)
|
|
|
- goto error;
|
|
|
- }
|
|
|
- ret = setup_msi_irq(dev, msidesc, irq, sub_handle);
|
|
|
- if (ret < 0)
|
|
|
- goto error;
|
|
|
- }
|
|
|
- return 0;
|
|
|
-
|
|
|
-error:
|
|
|
- destroy_irqs(irq, nvec);
|
|
|
-
|
|
|
- /*
|
|
|
- * Restore altered MSI descriptor fields and prevent just destroyed
|
|
|
- * IRQs from tearing down again in default_teardown_msi_irqs()
|
|
|
- */
|
|
|
- msidesc->irq = 0;
|
|
|
- msidesc->msi_attrib.multiple = 0;
|
|
|
-
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
|
|
|
-{
|
|
|
- if (type == PCI_CAP_ID_MSI)
|
|
|
- return setup_msi_irqs(dev, nvec);
|
|
|
- return setup_msix_irqs(dev, nvec);
|
|
|
-}
|
|
|
-
|
|
|
void native_teardown_msi_irq(unsigned int irq)
|
|
|
{
|
|
|
destroy_irq(irq);
|
|
@@ -3399,26 +3249,19 @@ static struct irq_chip hpet_msi_type = {
|
|
|
.irq_retrigger = ioapic_retrigger_irq,
|
|
|
};
|
|
|
|
|
|
-int arch_setup_hpet_msi(unsigned int irq, unsigned int id)
|
|
|
+int default_setup_hpet_msi(unsigned int irq, unsigned int id)
|
|
|
{
|
|
|
struct irq_chip *chip = &hpet_msi_type;
|
|
|
struct msi_msg msg;
|
|
|
int ret;
|
|
|
|
|
|
- if (irq_remapping_enabled) {
|
|
|
- ret = setup_hpet_msi_remapped(irq, id);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
- }
|
|
|
-
|
|
|
ret = msi_compose_msg(NULL, irq, &msg, id);
|
|
|
if (ret < 0)
|
|
|
return ret;
|
|
|
|
|
|
hpet_msi_write(irq_get_handler_data(irq), &msg);
|
|
|
irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
|
|
|
- if (irq_remapped(irq_get_chip_data(irq)))
|
|
|
- irq_remap_modify_chip_defaults(chip);
|
|
|
+ setup_remapped_irq(irq, irq_get_chip_data(irq), chip);
|
|
|
|
|
|
irq_set_chip_and_handler_name(irq, chip, handle_edge_irq, "edge");
|
|
|
return 0;
|
|
@@ -3784,10 +3627,7 @@ void __init setup_ioapic_dest(void)
|
|
|
else
|
|
|
mask = apic->target_cpus();
|
|
|
|
|
|
- if (irq_remapping_enabled)
|
|
|
- set_remapped_irq_affinity(idata, mask, false);
|
|
|
- else
|
|
|
- ioapic_set_affinity(idata, mask, false);
|
|
|
+ x86_io_apic_ops.set_affinity(idata, mask, false);
|
|
|
}
|
|
|
|
|
|
}
|