aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/ia64/kernel/iosapic.c57
-rw-r--r--include/asm-ia64/iosapic.h4
2 files changed, 31 insertions, 30 deletions
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
index b3dcdb7e7fc7..29fea0a8c2c6 100644
--- a/arch/ia64/kernel/iosapic.c
+++ b/arch/ia64/kernel/iosapic.c
@@ -125,6 +125,7 @@ static struct iosapic {
125#ifdef CONFIG_NUMA 125#ifdef CONFIG_NUMA
126 unsigned short node; /* numa node association via pxm */ 126 unsigned short node; /* numa node association via pxm */
127#endif 127#endif
128 spinlock_t lock; /* lock for indirect reg access */
128} iosapic_lists[NR_IOSAPICS]; 129} iosapic_lists[NR_IOSAPICS];
129 130
130struct iosapic_rte_info { 131struct iosapic_rte_info {
@@ -153,6 +154,16 @@ static unsigned char pcat_compat __devinitdata; /* 8259 compatibility flag */
153static int iosapic_kmalloc_ok; 154static int iosapic_kmalloc_ok;
154static LIST_HEAD(free_rte_list); 155static LIST_HEAD(free_rte_list);
155 156
157static inline void
158iosapic_write(struct iosapic *iosapic, unsigned int reg, u32 val)
159{
160 unsigned long flags;
161
162 spin_lock_irqsave(&iosapic->lock, flags);
163 __iosapic_write(iosapic->addr, reg, val);
164 spin_unlock_irqrestore(&iosapic->lock, flags);
165}
166
156/* 167/*
157 * Find an IOSAPIC associated with a GSI 168 * Find an IOSAPIC associated with a GSI
158 */ 169 */
@@ -226,7 +237,6 @@ set_rte (unsigned int gsi, unsigned int vector, unsigned int dest, int mask)
226{ 237{
227 unsigned long pol, trigger, dmode; 238 unsigned long pol, trigger, dmode;
228 u32 low32, high32; 239 u32 low32, high32;
229 char __iomem *addr;
230 int rte_index; 240 int rte_index;
231 char redir; 241 char redir;
232 struct iosapic_rte_info *rte; 242 struct iosapic_rte_info *rte;
@@ -238,7 +248,6 @@ set_rte (unsigned int gsi, unsigned int vector, unsigned int dest, int mask)
238 return; /* not an IOSAPIC interrupt */ 248 return; /* not an IOSAPIC interrupt */
239 249
240 rte_index = rte->rte_index; 250 rte_index = rte->rte_index;
241 addr = rte->iosapic->addr;
242 pol = iosapic_intr_info[vector].polarity; 251 pol = iosapic_intr_info[vector].polarity;
243 trigger = iosapic_intr_info[vector].trigger; 252 trigger = iosapic_intr_info[vector].trigger;
244 dmode = iosapic_intr_info[vector].dmode; 253 dmode = iosapic_intr_info[vector].dmode;
@@ -268,8 +277,8 @@ set_rte (unsigned int gsi, unsigned int vector, unsigned int dest, int mask)
268 /* dest contains both id and eid */ 277 /* dest contains both id and eid */
269 high32 = (dest << IOSAPIC_DEST_SHIFT); 278 high32 = (dest << IOSAPIC_DEST_SHIFT);
270 279
271 iosapic_write(addr, IOSAPIC_RTE_HIGH(rte_index), high32); 280 iosapic_write(rte->iosapic, IOSAPIC_RTE_HIGH(rte_index), high32);
272 iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); 281 iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte_index), low32);
273 iosapic_intr_info[vector].low32 = low32; 282 iosapic_intr_info[vector].low32 = low32;
274 iosapic_intr_info[vector].dest = dest; 283 iosapic_intr_info[vector].dest = dest;
275} 284}
@@ -292,7 +301,7 @@ kexec_disable_iosapic(void)
292 iosapic_intr_info + IA64_NUM_VECTORS; ++info, ++vec) { 301 iosapic_intr_info + IA64_NUM_VECTORS; ++info, ++vec) {
293 list_for_each_entry(rte, &info->rtes, 302 list_for_each_entry(rte, &info->rtes,
294 rte_list) { 303 rte_list) {
295 iosapic_write(rte->iosapic->addr, 304 iosapic_write(rte->iosapic,
296 IOSAPIC_RTE_LOW(rte->rte_index), 305 IOSAPIC_RTE_LOW(rte->rte_index),
297 IOSAPIC_MASK|vec); 306 IOSAPIC_MASK|vec);
298 iosapic_eoi(rte->iosapic->addr, vec); 307 iosapic_eoi(rte->iosapic->addr, vec);
@@ -304,8 +313,6 @@ kexec_disable_iosapic(void)
304static void 313static void
305mask_irq (unsigned int irq) 314mask_irq (unsigned int irq)
306{ 315{
307 unsigned long flags;
308 char __iomem *addr;
309 u32 low32; 316 u32 low32;
310 int rte_index; 317 int rte_index;
311 ia64_vector vec = irq_to_vector(irq); 318 ia64_vector vec = irq_to_vector(irq);
@@ -314,22 +321,17 @@ mask_irq (unsigned int irq)
314 if (list_empty(&iosapic_intr_info[vec].rtes)) 321 if (list_empty(&iosapic_intr_info[vec].rtes))
315 return; /* not an IOSAPIC interrupt! */ 322 return; /* not an IOSAPIC interrupt! */
316 323
317 spin_lock_irqsave(&iosapic_lock, flags);
318 /* set only the mask bit */ 324 /* set only the mask bit */
319 low32 = iosapic_intr_info[vec].low32 |= IOSAPIC_MASK; 325 low32 = iosapic_intr_info[vec].low32 |= IOSAPIC_MASK;
320 list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) { 326 list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) {
321 addr = rte->iosapic->addr;
322 rte_index = rte->rte_index; 327 rte_index = rte->rte_index;
323 iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); 328 iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte_index), low32);
324 } 329 }
325 spin_unlock_irqrestore(&iosapic_lock, flags);
326} 330}
327 331
328static void 332static void
329unmask_irq (unsigned int irq) 333unmask_irq (unsigned int irq)
330{ 334{
331 unsigned long flags;
332 char __iomem *addr;
333 u32 low32; 335 u32 low32;
334 int rte_index; 336 int rte_index;
335 ia64_vector vec = irq_to_vector(irq); 337 ia64_vector vec = irq_to_vector(irq);
@@ -338,14 +340,11 @@ unmask_irq (unsigned int irq)
338 if (list_empty(&iosapic_intr_info[vec].rtes)) 340 if (list_empty(&iosapic_intr_info[vec].rtes))
339 return; /* not an IOSAPIC interrupt! */ 341 return; /* not an IOSAPIC interrupt! */
340 342
341 spin_lock_irqsave(&iosapic_lock, flags);
342 low32 = iosapic_intr_info[vec].low32 &= ~IOSAPIC_MASK; 343 low32 = iosapic_intr_info[vec].low32 &= ~IOSAPIC_MASK;
343 list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) { 344 list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) {
344 addr = rte->iosapic->addr;
345 rte_index = rte->rte_index; 345 rte_index = rte->rte_index;
346 iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); 346 iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte_index), low32);
347 } 347 }
348 spin_unlock_irqrestore(&iosapic_lock, flags);
349} 348}
350 349
351 350
@@ -353,13 +352,12 @@ static void
353iosapic_set_affinity (unsigned int irq, cpumask_t mask) 352iosapic_set_affinity (unsigned int irq, cpumask_t mask)
354{ 353{
355#ifdef CONFIG_SMP 354#ifdef CONFIG_SMP
356 unsigned long flags;
357 u32 high32, low32; 355 u32 high32, low32;
358 int dest, rte_index; 356 int dest, rte_index;
359 char __iomem *addr;
360 int redir = (irq & IA64_IRQ_REDIRECTED) ? 1 : 0; 357 int redir = (irq & IA64_IRQ_REDIRECTED) ? 1 : 0;
361 ia64_vector vec; 358 ia64_vector vec;
362 struct iosapic_rte_info *rte; 359 struct iosapic_rte_info *rte;
360 struct iosapic *iosapic;
363 361
364 irq &= (~IA64_IRQ_REDIRECTED); 362 irq &= (~IA64_IRQ_REDIRECTED);
365 vec = irq_to_vector(irq); 363 vec = irq_to_vector(irq);
@@ -377,7 +375,6 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask)
377 /* dest contains both id and eid */ 375 /* dest contains both id and eid */
378 high32 = dest << IOSAPIC_DEST_SHIFT; 376 high32 = dest << IOSAPIC_DEST_SHIFT;
379 377
380 spin_lock_irqsave(&iosapic_lock, flags);
381 low32 = iosapic_intr_info[vec].low32 & ~(7 << IOSAPIC_DELIVERY_SHIFT); 378 low32 = iosapic_intr_info[vec].low32 & ~(7 << IOSAPIC_DELIVERY_SHIFT);
382 if (redir) 379 if (redir)
383 /* change delivery mode to lowest priority */ 380 /* change delivery mode to lowest priority */
@@ -389,12 +386,11 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask)
389 iosapic_intr_info[vec].low32 = low32; 386 iosapic_intr_info[vec].low32 = low32;
390 iosapic_intr_info[vec].dest = dest; 387 iosapic_intr_info[vec].dest = dest;
391 list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) { 388 list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) {
392 addr = rte->iosapic->addr; 389 iosapic = rte->iosapic;
393 rte_index = rte->rte_index; 390 rte_index = rte->rte_index;
394 iosapic_write(addr, IOSAPIC_RTE_HIGH(rte_index), high32); 391 iosapic_write(iosapic, IOSAPIC_RTE_HIGH(rte_index), high32);
395 iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32); 392 iosapic_write(iosapic, IOSAPIC_RTE_LOW(rte_index), low32);
396 } 393 }
397 spin_unlock_irqrestore(&iosapic_lock, flags);
398#endif 394#endif
399} 395}
400 396
@@ -499,7 +495,7 @@ iosapic_version (char __iomem *addr)
499 * unsigned int reserved2 : 8; 495 * unsigned int reserved2 : 8;
500 * } 496 * }
501 */ 497 */
502 return iosapic_read(addr, IOSAPIC_VERSION); 498 return __iosapic_read(addr, IOSAPIC_VERSION);
503} 499}
504 500
505static int iosapic_find_sharable_vector (unsigned long trigger, 501static int iosapic_find_sharable_vector (unsigned long trigger,
@@ -857,8 +853,7 @@ iosapic_unregister_intr (unsigned int gsi)
857 853
858 /* Mask the interrupt */ 854 /* Mask the interrupt */
859 low32 = iosapic_intr_info[vector].low32 | IOSAPIC_MASK; 855 low32 = iosapic_intr_info[vector].low32 | IOSAPIC_MASK;
860 iosapic_write(rte->iosapic->addr, 856 iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte->rte_index), low32);
861 IOSAPIC_RTE_LOW(rte->rte_index), low32);
862 857
863 iosapic_intr_info[vector].count--; 858 iosapic_intr_info[vector].count--;
864 iosapic_free_rte(rte); 859 iosapic_free_rte(rte);
@@ -1060,9 +1055,14 @@ iosapic_init (unsigned long phys_addr, unsigned int gsi_base)
1060 unsigned long flags; 1055 unsigned long flags;
1061 1056
1062 spin_lock_irqsave(&iosapic_lock, flags); 1057 spin_lock_irqsave(&iosapic_lock, flags);
1058 index = find_iosapic(gsi_base);
1059 if (index >= 0) {
1060 spin_unlock_irqrestore(&iosapic_lock, flags);
1061 return -EBUSY;
1062 }
1063
1063 addr = ioremap(phys_addr, 0); 1064 addr = ioremap(phys_addr, 0);
1064 ver = iosapic_version(addr); 1065 ver = iosapic_version(addr);
1065
1066 if ((err = iosapic_check_gsi_range(gsi_base, ver))) { 1066 if ((err = iosapic_check_gsi_range(gsi_base, ver))) {
1067 iounmap(addr); 1067 iounmap(addr);
1068 spin_unlock_irqrestore(&iosapic_lock, flags); 1068 spin_unlock_irqrestore(&iosapic_lock, flags);
@@ -1083,6 +1083,7 @@ iosapic_init (unsigned long phys_addr, unsigned int gsi_base)
1083#ifdef CONFIG_NUMA 1083#ifdef CONFIG_NUMA
1084 iosapic_lists[index].node = MAX_NUMNODES; 1084 iosapic_lists[index].node = MAX_NUMNODES;
1085#endif 1085#endif
1086 spin_lock_init(&iosapic_lists[index].lock);
1086 spin_unlock_irqrestore(&iosapic_lock, flags); 1087 spin_unlock_irqrestore(&iosapic_lock, flags);
1087 1088
1088 if ((gsi_base == 0) && pcat_compat) { 1089 if ((gsi_base == 0) && pcat_compat) {
diff --git a/include/asm-ia64/iosapic.h b/include/asm-ia64/iosapic.h
index 421cb6b62a7c..09bdc3898df8 100644
--- a/include/asm-ia64/iosapic.h
+++ b/include/asm-ia64/iosapic.h
@@ -53,13 +53,13 @@
53 53
54#define NR_IOSAPICS 256 54#define NR_IOSAPICS 256
55 55
56static inline unsigned int iosapic_read(char __iomem *iosapic, unsigned int reg) 56static inline unsigned int __iosapic_read(char __iomem *iosapic, unsigned int reg)
57{ 57{
58 writel(reg, iosapic + IOSAPIC_REG_SELECT); 58 writel(reg, iosapic + IOSAPIC_REG_SELECT);
59 return readl(iosapic + IOSAPIC_WINDOW); 59 return readl(iosapic + IOSAPIC_WINDOW);
60} 60}
61 61
62static inline void iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val) 62static inline void __iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val)
63{ 63{
64 writel(reg, iosapic + IOSAPIC_REG_SELECT); 64 writel(reg, iosapic + IOSAPIC_REG_SELECT);
65 writel(val, iosapic + IOSAPIC_WINDOW); 65 writel(val, iosapic + IOSAPIC_WINDOW);