1 /* 2 * MSI hooks for standard x86 apic 3 */ 4 5 #include <linux/pci.h> 6 #include <linux/irq.h> 7 #include <linux/msi.h> 8 #include <asm/smp.h> 9 10 /* 11 * Shifts for APIC-based data 12 */ 13 14 #define MSI_DATA_VECTOR_SHIFT 0 15 #define MSI_DATA_VECTOR(v) (((u8)v) << MSI_DATA_VECTOR_SHIFT) 16 17 #define MSI_DATA_DELIVERY_SHIFT 8 18 #define MSI_DATA_DELIVERY_FIXED (0 << MSI_DATA_DELIVERY_SHIFT) 19 #define MSI_DATA_DELIVERY_LOWPRI (1 << MSI_DATA_DELIVERY_SHIFT) 20 21 #define MSI_DATA_LEVEL_SHIFT 14 22 #define MSI_DATA_LEVEL_DEASSERT (0 << MSI_DATA_LEVEL_SHIFT) 23 #define MSI_DATA_LEVEL_ASSERT (1 << MSI_DATA_LEVEL_SHIFT) 24 25 #define MSI_DATA_TRIGGER_SHIFT 15 26 #define MSI_DATA_TRIGGER_EDGE (0 << MSI_DATA_TRIGGER_SHIFT) 27 #define MSI_DATA_TRIGGER_LEVEL (1 << MSI_DATA_TRIGGER_SHIFT) 28 29 /* 30 * Shift/mask fields for APIC-based bus address 31 */ 32 33 #define MSI_TARGET_CPU_SHIFT 4 34 #define MSI_ADDR_HEADER 0xfee00000 35 36 #define MSI_ADDR_DESTID_MASK 0xfff0000f 37 #define MSI_ADDR_DESTID_CPU(cpu) ((cpu) << MSI_TARGET_CPU_SHIFT) 38 39 #define MSI_ADDR_DESTMODE_SHIFT 2 40 #define MSI_ADDR_DESTMODE_PHYS (0 << MSI_ADDR_DESTMODE_SHIFT) 41 #define MSI_ADDR_DESTMODE_LOGIC (1 << MSI_ADDR_DESTMODE_SHIFT) 42 43 #define MSI_ADDR_REDIRECTION_SHIFT 3 44 #define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT) 45 #define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT) 46 47 static struct irq_chip ia64_msi_chip; 48 49 #ifdef CONFIG_SMP 50 static void ia64_set_msi_irq_affinity(unsigned int irq, cpumask_t cpu_mask) 51 { 52 struct msi_msg msg; 53 u32 addr; 54 55 read_msi_msg(irq, &msg); 56 57 addr = msg.address_lo; 58 addr &= MSI_ADDR_DESTID_MASK; 59 addr |= MSI_ADDR_DESTID_CPU(cpu_physical_id(first_cpu(cpu_mask))); 60 msg.address_lo = addr; 61 62 write_msi_msg(irq, &msg); 63 irq_desc[irq].affinity = cpu_mask; 64 } 65 #endif /* CONFIG_SMP */ 66 67 int ia64_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) 68 { 69 struct msi_msg msg; 70 unsigned long dest_phys_id; 71 int irq, vector; 72 73 irq = create_irq(); 74 if (irq < 0) 75 return irq; 76 77 set_irq_msi(irq, desc); 78 dest_phys_id = cpu_physical_id(first_cpu(cpu_online_map)); 79 vector = irq_to_vector(irq); 80 81 msg.address_hi = 0; 82 msg.address_lo = 83 MSI_ADDR_HEADER | 84 MSI_ADDR_DESTMODE_PHYS | 85 MSI_ADDR_REDIRECTION_CPU | 86 MSI_ADDR_DESTID_CPU(dest_phys_id); 87 88 msg.data = 89 MSI_DATA_TRIGGER_EDGE | 90 MSI_DATA_LEVEL_ASSERT | 91 MSI_DATA_DELIVERY_FIXED | 92 MSI_DATA_VECTOR(vector); 93 94 write_msi_msg(irq, &msg); 95 set_irq_chip_and_handler(irq, &ia64_msi_chip, handle_edge_irq); 96 97 return irq; 98 } 99 100 void ia64_teardown_msi_irq(unsigned int irq) 101 { 102 destroy_irq(irq); 103 } 104 105 static void ia64_ack_msi_irq(unsigned int irq) 106 { 107 move_native_irq(irq); 108 ia64_eoi(); 109 } 110 111 static int ia64_msi_retrigger_irq(unsigned int irq) 112 { 113 unsigned int vector = irq_to_vector(irq); 114 ia64_resend_irq(vector); 115 116 return 1; 117 } 118 119 /* 120 * Generic ops used on most IA64 platforms. 121 */ 122 static struct irq_chip ia64_msi_chip = { 123 .name = "PCI-MSI", 124 .mask = mask_msi_irq, 125 .unmask = unmask_msi_irq, 126 .ack = ia64_ack_msi_irq, 127 #ifdef CONFIG_SMP 128 .set_affinity = ia64_set_msi_irq_affinity, 129 #endif 130 .retrigger = ia64_msi_retrigger_irq, 131 }; 132 133 134 int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) 135 { 136 if (platform_setup_msi_irq) 137 return platform_setup_msi_irq(pdev, desc); 138 139 return ia64_setup_msi_irq(pdev, desc); 140 } 141 142 void arch_teardown_msi_irq(unsigned int irq) 143 { 144 if (platform_teardown_msi_irq) 145 return platform_teardown_msi_irq(irq); 146 147 return ia64_teardown_msi_irq(irq); 148 } 149