| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -142,6 +142,11 @@ u32 mp_pin_to_gsi(int ioapic, int pin)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return mp_ioapic_gsi_routing(ioapic)->gsi_base + pin;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static inline bool mp_is_legacy_irq(int irq)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return irq >= 0 && irq < nr_legacy_irqs();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * Initialize all legacy IRQs and all pins on the first IOAPIC
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * if we have legacy interrupt controller. Kernel boot option "pirq="
 | 
			
		
		
	
	
		
			
				
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -152,7 +157,7 @@ static inline int mp_init_irq_at_boot(int ioapic, int irq)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (!nr_legacy_irqs())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return ioapic == 0 || (irq >= 0 && irq < nr_legacy_irqs());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return ioapic == 0 || mp_is_legacy_irq(irq);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static inline struct mp_pin_info *mp_pin_info(int ioapic_idx, int pin)
 | 
			
		
		
	
	
		
			
				
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -231,7 +236,7 @@ struct irq_pin_list {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static struct irq_pin_list *alloc_irq_pin_list(int node)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return kzalloc_node(sizeof(struct irq_pin_list), GFP_KERNEL, node);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return kzalloc_node(sizeof(struct irq_pin_list), GFP_ATOMIC, node);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static void alloc_ioapic_saved_registers(int idx)
 | 
			
		
		
	
	
		
			
				
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -560,6 +565,17 @@ void native_eoi_ioapic_pin(int apic, int pin, int vector)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				void eoi_ioapic_pin(int vector, struct irq_cfg *cfg)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					unsigned long flags;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					struct irq_pin_list *entry;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					raw_spin_lock_irqsave(&ioapic_lock, flags);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					for_each_irq_pin(entry, cfg->irq_2_pin)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						native_eoi_ioapic_pin(entry->apic, entry->pin, vector);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				void eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					struct irq_pin_list *entry;
 | 
			
		
		
	
	
		
			
				
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -603,9 +619,8 @@ static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							entry.trigger = IOAPIC_LEVEL;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							ioapic_write_entry(apic, pin, entry);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						raw_spin_lock_irqsave(&ioapic_lock, flags);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						x86_io_apic_ops.eoi_ioapic_pin(apic, pin, entry.vector);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						native_eoi_ioapic_pin(apic, pin, entry.vector);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
	
		
			
				
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -1023,95 +1038,121 @@ static bool mp_check_pin_attr(int irq, struct irq_alloc_info *info)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					       data->polarity == info->ioapic_polarity;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static int alloc_irq_from_domain(struct irq_domain *domain, u32 gsi, int pin,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static int alloc_irq_from_domain(struct irq_domain *domain, int ioapic, u32 gsi,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								 struct irq_alloc_info *info)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					bool legacy = false;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					int irq = -1;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					int ioapic = mp_irqdomain_ioapic_idx(domain);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					int type = ioapics[ioapic].irqdomain_cfg.type;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					switch (type) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					case IOAPIC_DOMAIN_LEGACY:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						/*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						 * Dynamically allocate IRQ number for non-ISA IRQs in the first 16
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						 * GSIs on some weird platforms.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						 * Dynamically allocate IRQ number for non-ISA IRQs in the first
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						 * 16 GSIs on some weird platforms.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						 */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (gsi < nr_legacy_irqs())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							irq = irq_create_mapping(domain, pin);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						else if (irq_create_strict_mappings(domain, gsi, pin, 1) == 0)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (!ioapic_initialized || gsi >= nr_legacy_irqs())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							irq = gsi;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						legacy = mp_is_legacy_irq(irq);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					case IOAPIC_DOMAIN_STRICT:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (irq_create_strict_mappings(domain, gsi, pin, 1) == 0)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							irq = gsi;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						irq = gsi;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					case IOAPIC_DOMAIN_DYNAMIC:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						irq = irq_create_mapping(domain, pin);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					default:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						WARN(1, "ioapic: unknown irqdomain type %d\n", type);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return -1;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return irq > 0 ? irq : -1;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return __irq_domain_alloc_irqs(domain, irq, 1,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								       ioapic_alloc_attr_node(info),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								       info, legacy);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * Need special handling for ISA IRQs because there may be multiple IOAPIC pins
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * sharing the same ISA IRQ number and irqdomain only supports 1:1 mapping
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * between IOAPIC pin and IRQ number. A typical IOAPIC has 24 pins, pin 0-15 are
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * used for legacy IRQs and pin 16-23 are used for PCI IRQs (PIRQ A-H).
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * When ACPI is disabled, only legacy IRQ numbers (IRQ0-15) are available, and
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * some BIOSes may use MP Interrupt Source records to override IRQ numbers for
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * PIRQs instead of reprogramming the interrupt routing logic. Thus there may be
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * multiple pins sharing the same legacy IRQ number when ACPI is disabled.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static int alloc_isa_irq_from_domain(struct irq_domain *domain,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								     int irq, int ioapic, int pin,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								     struct irq_alloc_info *info)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					struct mp_chip_data *data;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					struct irq_data *irq_data = irq_get_irq_data(irq);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					int node = ioapic_alloc_attr_node(info);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					/*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 * Legacy ISA IRQ has already been allocated, just add pin to
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 * the pin list assoicated with this IRQ and program the IOAPIC
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 * entry. The IOAPIC entry
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (irq_data && irq_data->parent_data) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						struct irq_cfg *cfg = irqd_cfg(irq_data);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (!mp_check_pin_attr(irq, info))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							return -EBUSY;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (__add_pin_to_irq_node(cfg, node, ioapic, info->ioapic_pin))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							return -ENOMEM;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					} else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						irq = __irq_domain_alloc_irqs(domain, irq, 1, node, info, true);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (irq >= 0) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							irq_data = irq_domain_get_irq_data(domain, irq);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							data = irq_data->chip_data;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							data->isa_irq = true;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return irq;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static int mp_map_pin_to_irq(u32 gsi, int idx, int ioapic, int pin,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							     unsigned int flags, struct irq_alloc_info *info)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					int irq;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					bool legacy = false;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					struct irq_alloc_info tmp;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					struct mp_chip_data *data;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					struct irq_domain *domain = mp_ioapic_irqdomain(ioapic);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					struct mp_pin_info *pinfo = mp_pin_info(ioapic, pin);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (!domain)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return -1;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return -ENOSYS;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					mutex_lock(&ioapic_mutex);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					/*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 * Don't use irqdomain to manage ISA IRQs because there may be
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 * multiple IOAPIC pins sharing the same ISA IRQ number and
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 * irqdomain only supports 1:1 mapping between IOAPIC pin and
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 * IRQ number. A typical IOAPIC has 24 pins, pin 0-15 are used
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 * for legacy IRQs and pin 16-23 are used for PCI IRQs (PIRQ A-H).
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 * When ACPI is disabled, only legacy IRQ numbers (IRQ0-15) are
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 * available, and some BIOSes may use MP Interrupt Source records
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 * to override IRQ numbers for PIRQs instead of reprogramming
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 * the interrupt routing logic. Thus there may be multiple pins
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 * sharing the same legacy IRQ number when ACPI is disabled.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (idx >= 0 && test_bit(mp_irqs[idx].srcbus, mp_bus_not_pci)) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						irq = mp_irqs[idx].srcbusirq;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (flags & IOAPIC_MAP_ALLOC) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (pinfo->count == 0 &&
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    mp_irqdomain_map(domain, irq, pin) != 0)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								irq = -1;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						legacy = mp_is_legacy_irq(irq);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							/* special handling for timer IRQ0 */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					mutex_lock(&ioapic_mutex);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (!(flags & IOAPIC_MAP_ALLOC)) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (!legacy) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							irq = irq_find_mapping(domain, pin);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (irq == 0)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								pinfo->count++;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								irq = -ENOENT;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					} else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						irq = irq_find_mapping(domain, pin);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (irq <= 0 && (flags & IOAPIC_MAP_ALLOC))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							irq = alloc_irq_from_domain(domain, gsi, pin, info);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						ioapic_copy_alloc_attr(&tmp, info, gsi, ioapic, pin);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (legacy)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							irq = alloc_isa_irq_from_domain(domain, irq,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
											ioapic, pin, &tmp);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						else if ((irq = irq_find_mapping(domain, pin)) == 0)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							irq = alloc_irq_from_domain(domain, ioapic, gsi, &tmp);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						else if (!mp_check_pin_attr(irq, &tmp))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							irq = -EBUSY;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (irq >= 0) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							data = irq_get_chip_data(irq);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							data->count++;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (flags & IOAPIC_MAP_ALLOC) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						/* special handling for legacy IRQs */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (irq < nr_legacy_irqs() && pinfo->count == 1 &&
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    mp_irqdomain_map(domain, irq, pin) != 0)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							irq = -1;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (irq > 0)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							pinfo->count++;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						else if (pinfo->count == 0)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							pinfo->set = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					mutex_unlock(&ioapic_mutex);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return irq > 0 ? irq : -1;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return irq;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static int pin_2_irq(int idx, int ioapic, int pin, unsigned int flags)
 | 
			
		
		
	
	
		
			
				
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -1166,26 +1207,19 @@ int mp_map_gsi_to_irq(u32 gsi, unsigned int flags,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				void mp_unmap_irq(int irq)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					struct irq_data *data = irq_get_irq_data(irq);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					struct mp_pin_info *info;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					int ioapic, pin;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					struct irq_data *irq_data = irq_get_irq_data(irq);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					struct mp_chip_data *data;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (!data || !data->domain)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (!irq_data || !irq_data->domain)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					ioapic = (int)(long)data->domain->host_data;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					pin = (int)data->hwirq;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					info = mp_pin_info(ioapic, pin);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					data = irq_data->chip_data;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (!data || data->isa_irq)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					mutex_lock(&ioapic_mutex);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (--info->count == 0) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						info->set = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (irq < nr_legacy_irqs() &&
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						    ioapics[ioapic].irqdomain_cfg.type == IOAPIC_DOMAIN_LEGACY)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							mp_irqdomain_unmap(data->domain, irq);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						else
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							irq_dispose_mapping(irq);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (--data->count == 0)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						irq_domain_free_irqs(irq, 1);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					mutex_unlock(&ioapic_mutex);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
	
		
			
				
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -1252,7 +1286,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static struct irq_chip ioapic_chip;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static struct irq_chip ioapic_chip, ioapic_ir_chip;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#ifdef CONFIG_X86_32
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static inline int IO_APIC_irq_trigger(int irq)
 | 
			
		
		
	
	
		
			
				
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -1595,7 +1629,7 @@ void __init print_IO_APICs(void)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						struct irq_pin_list *entry;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						chip = irq_get_chip(irq);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (chip != &ioapic_chip)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (chip != &ioapic_chip && chip != &ioapic_ir_chip)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							continue;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						cfg = irq_cfg(irq);
 | 
			
		
		
	
	
		
			
				
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -2057,12 +2091,12 @@ static inline void ioapic_irqd_unmask(struct irq_data *data,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#endif
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static void ack_ioapic_level(struct irq_data *data)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static void ioapic_ack_level(struct irq_data *data)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					struct irq_cfg *cfg = irqd_cfg(data);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					int i, irq = data->irq;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					unsigned long v;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					bool masked;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					int i;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					irq_complete_move(cfg);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					masked = ioapic_irqd_mask(data, cfg);
 | 
			
		
		
	
	
		
			
				
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -2117,22 +2151,70 @@ static void ack_ioapic_level(struct irq_data *data)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (!(v & (1 << (i & 0x1f)))) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						atomic_inc(&irq_mis_count);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						eoi_ioapic_irq(irq, cfg);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						eoi_ioapic_pin(cfg->vector, cfg);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					ioapic_irqd_unmask(data, cfg, masked);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static void ioapic_ir_ack_level(struct irq_data *irq_data)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					struct mp_chip_data *data = irq_data->chip_data;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					/*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 * 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.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					ack_APIC_irq();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					eoi_ioapic_pin(data->entry.vector, irqd_cfg(irq_data));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static int ioapic_set_affinity(struct irq_data *irq_data,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							       const struct cpumask *mask, bool force)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					struct irq_data *parent = irq_data->parent_data;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					struct mp_chip_data *data = irq_data->chip_data;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					unsigned int dest, irq = irq_data->irq;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					struct irq_cfg *cfg;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					unsigned long flags;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					int ret;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					ret = parent->chip->irq_set_affinity(parent, mask, force);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					raw_spin_lock_irqsave(&ioapic_lock, flags);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (ret >= 0 && ret != IRQ_SET_MASK_OK_DONE) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						cfg = irqd_cfg(irq_data);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						data->entry.dest = cfg->dest_apicid;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						data->entry.vector = cfg->vector;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						/* Only the high 8 bits are valid. */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						dest = SET_APIC_LOGICAL_ID(cfg->dest_apicid);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						__target_IO_APIC_irq(irq, dest, cfg);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return ret;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static struct irq_chip ioapic_chip __read_mostly = {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					.name			= "IO-APIC",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					.irq_startup		= startup_ioapic_irq,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					.irq_mask		= mask_ioapic_irq,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					.irq_unmask		= unmask_ioapic_irq,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					.irq_ack		= apic_ack_edge,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					.irq_eoi		= ack_ioapic_level,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					.irq_set_affinity	= native_ioapic_set_affinity,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					.irq_retrigger		= apic_retrigger_irq,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					.irq_ack		= irq_chip_ack_parent,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					.irq_eoi		= ioapic_ack_level,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					.irq_set_affinity	= ioapic_set_affinity,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					.flags			= IRQCHIP_SKIP_SET_WAKE,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				};
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static struct irq_chip ioapic_ir_chip __read_mostly = {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					.name			= "IR-IO-APIC",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					.irq_startup		= startup_ioapic_irq,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					.irq_mask		= mask_ioapic_irq,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					.irq_unmask		= unmask_ioapic_irq,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					.irq_ack		= irq_chip_ack_parent,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					.irq_eoi		= ioapic_ir_ack_level,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					.irq_set_affinity	= ioapic_set_affinity,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					.flags			= IRQCHIP_SKIP_SET_WAKE,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				};
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
	
		
			
				
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -2265,6 +2347,24 @@ static int __init disable_timer_pin_setup(char *arg)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				early_param("disable_timer_pin_1", disable_timer_pin_setup);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static int mp_alloc_timer_irq(int ioapic, int pin)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					int irq = -1;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					struct irq_alloc_info info;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					struct irq_domain *domain = mp_ioapic_irqdomain(ioapic);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (domain) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						ioapic_set_alloc_attr(&info, NUMA_NO_NODE, 0, 0);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						info.ioapic_id = mpc_ioapic_id(ioapic);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						info.ioapic_pin = pin;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						mutex_lock(&ioapic_mutex);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						irq = alloc_isa_irq_from_domain(domain, 0, ioapic, pin, &info);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						mutex_unlock(&ioapic_mutex);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return irq;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * This code may look a bit paranoid, but it's supposed to cooperate with
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * a wide range of boards and BIOS bugs.  Fortunately only the timer IRQ
 | 
			
		
		
	
	
		
			
				
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -2287,7 +2387,6 @@ static inline void __init check_timer(void)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 * get/set the timer IRQ vector:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					legacy_pic->mask(0);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					assign_irq_vector(0, cfg, apic->target_cpus());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					/*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 * As IRQ0 is to be enabled in the 8259A, the virtual
 | 
			
		
		
	
	
		
			
				
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -2328,15 +2427,12 @@ static inline void __init check_timer(void)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (pin1 != -1) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						/*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						 * Ok, does IRQ0 through the IOAPIC work?
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						 */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						/* Ok, does IRQ0 through the IOAPIC work? */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (no_pin1) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							add_pin_to_irq_node(cfg, node, apic1, pin1);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							setup_timer_IRQ0_pin(apic1, pin1, cfg->vector);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							mp_alloc_timer_irq(apic1, pin1);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						} else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							/* for edge trigger, setup_ioapic_irq already
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							 * leave it unmasked.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							/*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							 * for edge trigger, it's already unmasked,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							 * so only need to unmask if it is level-trigger
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							 * do we really have level trigger timer?
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							 */
 | 
			
		
		
	
	
		
			
				
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -2345,6 +2441,7 @@ static inline void __init check_timer(void)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (idx != -1 && irq_trigger(idx))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								unmask_ioapic(cfg);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						irq_domain_activate_irq(irq_get_irq_data(0));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (timer_irq_works()) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (disable_timer_pin_1 > 0)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								clear_IO_APIC_pin(0, pin1);
 | 
			
		
		
	
	
		
			
				
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -2365,7 +2462,7 @@ static inline void __init check_timer(void)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						 * legacy devices should be connected to IO APIC #0
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						 */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						replace_pin_at_irq_node(cfg, node, apic1, pin1, apic2, pin2);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						setup_timer_IRQ0_pin(apic2, pin2, cfg->vector);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						irq_domain_activate_irq(irq_get_irq_data(0));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						legacy_pic->unmask(0);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (timer_irq_works()) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							apic_printk(APIC_QUIET, KERN_INFO "....... works.\n");
 | 
			
		
		
	
	
		
			
				
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -2443,6 +2540,8 @@ static inline void __init check_timer(void)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static int mp_irqdomain_create(int ioapic)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					size_t size;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					struct irq_alloc_info info;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					struct irq_domain *parent;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					int hwirqs = mp_ioapic_pin_count(ioapic);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					struct ioapic *ip = &ioapics[ioapic];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					struct ioapic_domain_cfg *cfg = &ip->irqdomain_cfg;
 | 
			
		
		
	
	
		
			
				
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -2456,9 +2555,18 @@ static int mp_irqdomain_create(int ioapic)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (cfg->type == IOAPIC_DOMAIN_INVALID)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					init_irq_alloc_info(&info, NULL);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					info.type = X86_IRQ_ALLOC_TYPE_IOAPIC;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					info.ioapic_id = mpc_ioapic_id(ioapic);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					parent = irq_remapping_get_ir_irq_domain(&info);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (!parent)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						parent = x86_vector_domain;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					ip->irqdomain = irq_domain_add_linear(cfg->dev, hwirqs, cfg->ops,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									      (void *)(long)ioapic);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if(!ip->irqdomain) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (ip->irqdomain) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						ip->irqdomain->parent = parent;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					} else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						kfree(ip->pin_info);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						ip->pin_info = NULL;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return -ENOMEM;
 | 
			
		
		
	
	
		
			
				
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -3072,7 +3180,6 @@ int mp_unregister_ioapic(u32 gsi_base)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					int ioapic, pin;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					int found = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					struct mp_pin_info *pin_info;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					for_each_ioapic(ioapic)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (ioapics[ioapic].gsi_config.gsi_base == gsi_base) {
 | 
			
		
		
	
	
		
			
				
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -3085,11 +3192,17 @@ int mp_unregister_ioapic(u32 gsi_base)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					for_each_pin(ioapic, pin) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						pin_info = mp_pin_info(ioapic, pin);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (pin_info->count) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							pr_warn("pin%d on IOAPIC%d is still in use.\n",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								pin, ioapic);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							return -EBUSY;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						u32 gsi = mp_pin_to_gsi(ioapic, pin);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						int irq = mp_map_gsi_to_irq(gsi, 0, NULL);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						struct mp_chip_data *data;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						if (irq >= 0) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							data = irq_get_chip_data(irq);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (data && data->count) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								pr_warn("pin%d on IOAPIC%d is still in use.\n",
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									pin, ioapic);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								return -EBUSY;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
	
		
			
				
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -3241,7 +3354,8 @@ int mp_irqdomain_alloc(struct irq_domain *domain, unsigned int virq,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					irq_data->hwirq = info->ioapic_pin;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					irq_data->chip = &ioapic_chip;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					irq_data->chip = (domain->parent == x86_vector_domain) ?
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							  &ioapic_chip : &ioapic_ir_chip;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					irq_data->chip_data = data;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					mp_irqdomain_get_attr(mp_pin_to_gsi(ioapic, pin), data, info);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
	
		
			
				
					| 
						
					 | 
				
			
			 | 
			 | 
			
				
 
 |