diff options
Diffstat (limited to 'arch/ia64/kernel/iosapic.c')
-rw-r--r-- | arch/ia64/kernel/iosapic.c | 258 |
1 files changed, 122 insertions, 136 deletions
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index 4c531953e2e1..bcf91dceaf5d 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c | |||
@@ -147,7 +147,7 @@ static struct iosapic_intr_info { | |||
147 | unsigned char polarity: 1; /* interrupt polarity | 147 | unsigned char polarity: 1; /* interrupt polarity |
148 | * (see iosapic.h) */ | 148 | * (see iosapic.h) */ |
149 | unsigned char trigger : 1; /* trigger mode (see iosapic.h) */ | 149 | unsigned char trigger : 1; /* trigger mode (see iosapic.h) */ |
150 | } iosapic_intr_info[IA64_NUM_VECTORS]; | 150 | } iosapic_intr_info[NR_IRQS]; |
151 | 151 | ||
152 | static unsigned char pcat_compat __devinitdata; /* 8259 compatibility flag */ | 152 | static unsigned char pcat_compat __devinitdata; /* 8259 compatibility flag */ |
153 | 153 | ||
@@ -181,17 +181,18 @@ find_iosapic (unsigned int gsi) | |||
181 | return -1; | 181 | return -1; |
182 | } | 182 | } |
183 | 183 | ||
184 | static inline int | 184 | static inline int __gsi_to_irq(unsigned int gsi) |
185 | _gsi_to_vector (unsigned int gsi) | ||
186 | { | 185 | { |
186 | int irq; | ||
187 | struct iosapic_intr_info *info; | 187 | struct iosapic_intr_info *info; |
188 | struct iosapic_rte_info *rte; | 188 | struct iosapic_rte_info *rte; |
189 | 189 | ||
190 | for (info = iosapic_intr_info; info < | 190 | for (irq = 0; irq < NR_IRQS; irq++) { |
191 | iosapic_intr_info + IA64_NUM_VECTORS; ++info) | 191 | info = &iosapic_intr_info[irq]; |
192 | list_for_each_entry(rte, &info->rtes, rte_list) | 192 | list_for_each_entry(rte, &info->rtes, rte_list) |
193 | if (rte->iosapic->gsi_base + rte->rte_index == gsi) | 193 | if (rte->iosapic->gsi_base + rte->rte_index == gsi) |
194 | return info - iosapic_intr_info; | 194 | return irq; |
195 | } | ||
195 | return -1; | 196 | return -1; |
196 | } | 197 | } |
197 | 198 | ||
@@ -202,7 +203,10 @@ _gsi_to_vector (unsigned int gsi) | |||
202 | inline int | 203 | inline int |
203 | gsi_to_vector (unsigned int gsi) | 204 | gsi_to_vector (unsigned int gsi) |
204 | { | 205 | { |
205 | return _gsi_to_vector(gsi); | 206 | int irq = __gsi_to_irq(gsi); |
207 | if (irq < 0) | ||
208 | return -1; | ||
209 | return irq_to_vector(irq); | ||
206 | } | 210 | } |
207 | 211 | ||
208 | int | 212 | int |
@@ -210,62 +214,48 @@ gsi_to_irq (unsigned int gsi) | |||
210 | { | 214 | { |
211 | unsigned long flags; | 215 | unsigned long flags; |
212 | int irq; | 216 | int irq; |
213 | /* | 217 | |
214 | * XXX fix me: this assumes an identity mapping between IA-64 vector | ||
215 | * and Linux irq numbers... | ||
216 | */ | ||
217 | spin_lock_irqsave(&iosapic_lock, flags); | 218 | spin_lock_irqsave(&iosapic_lock, flags); |
218 | irq = _gsi_to_vector(gsi); | 219 | irq = __gsi_to_irq(gsi); |
219 | spin_unlock_irqrestore(&iosapic_lock, flags); | 220 | spin_unlock_irqrestore(&iosapic_lock, flags); |
220 | |||
221 | return irq; | 221 | return irq; |
222 | } | 222 | } |
223 | 223 | ||
224 | static struct iosapic_rte_info *gsi_vector_to_rte(unsigned int gsi, | 224 | static struct iosapic_rte_info *find_rte(unsigned int irq, unsigned int gsi) |
225 | unsigned int vec) | ||
226 | { | 225 | { |
227 | struct iosapic_rte_info *rte; | 226 | struct iosapic_rte_info *rte; |
228 | 227 | ||
229 | list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) | 228 | list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list) |
230 | if (rte->iosapic->gsi_base + rte->rte_index == gsi) | 229 | if (rte->iosapic->gsi_base + rte->rte_index == gsi) |
231 | return rte; | 230 | return rte; |
232 | return NULL; | 231 | return NULL; |
233 | } | 232 | } |
234 | 233 | ||
235 | static void | 234 | static void |
236 | set_rte (unsigned int gsi, unsigned int vector, unsigned int dest, int mask) | 235 | set_rte (unsigned int gsi, unsigned int irq, unsigned int dest, int mask) |
237 | { | 236 | { |
238 | unsigned long pol, trigger, dmode; | 237 | unsigned long pol, trigger, dmode; |
239 | u32 low32, high32; | 238 | u32 low32, high32; |
240 | int rte_index; | 239 | int rte_index; |
241 | char redir; | 240 | char redir; |
242 | struct iosapic_rte_info *rte; | 241 | struct iosapic_rte_info *rte; |
242 | ia64_vector vector = irq_to_vector(irq); | ||
243 | 243 | ||
244 | DBG(KERN_DEBUG"IOSAPIC: routing vector %d to 0x%x\n", vector, dest); | 244 | DBG(KERN_DEBUG"IOSAPIC: routing vector %d to 0x%x\n", vector, dest); |
245 | 245 | ||
246 | rte = gsi_vector_to_rte(gsi, vector); | 246 | rte = find_rte(irq, gsi); |
247 | if (!rte) | 247 | if (!rte) |
248 | return; /* not an IOSAPIC interrupt */ | 248 | return; /* not an IOSAPIC interrupt */ |
249 | 249 | ||
250 | rte_index = rte->rte_index; | 250 | rte_index = rte->rte_index; |
251 | pol = iosapic_intr_info[vector].polarity; | 251 | pol = iosapic_intr_info[irq].polarity; |
252 | trigger = iosapic_intr_info[vector].trigger; | 252 | trigger = iosapic_intr_info[irq].trigger; |
253 | dmode = iosapic_intr_info[vector].dmode; | 253 | dmode = iosapic_intr_info[irq].dmode; |
254 | 254 | ||
255 | redir = (dmode == IOSAPIC_LOWEST_PRIORITY) ? 1 : 0; | 255 | redir = (dmode == IOSAPIC_LOWEST_PRIORITY) ? 1 : 0; |
256 | 256 | ||
257 | #ifdef CONFIG_SMP | 257 | #ifdef CONFIG_SMP |
258 | { | 258 | set_irq_affinity_info(irq, (int)(dest & 0xffff), redir); |
259 | unsigned int irq; | ||
260 | |||
261 | for (irq = 0; irq < NR_IRQS; ++irq) | ||
262 | if (irq_to_vector(irq) == vector) { | ||
263 | set_irq_affinity_info(irq, | ||
264 | (int)(dest & 0xffff), | ||
265 | redir); | ||
266 | break; | ||
267 | } | ||
268 | } | ||
269 | #endif | 259 | #endif |
270 | 260 | ||
271 | low32 = ((pol << IOSAPIC_POLARITY_SHIFT) | | 261 | low32 = ((pol << IOSAPIC_POLARITY_SHIFT) | |
@@ -279,8 +269,8 @@ set_rte (unsigned int gsi, unsigned int vector, unsigned int dest, int mask) | |||
279 | 269 | ||
280 | iosapic_write(rte->iosapic, IOSAPIC_RTE_HIGH(rte_index), high32); | 270 | iosapic_write(rte->iosapic, IOSAPIC_RTE_HIGH(rte_index), high32); |
281 | iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte_index), low32); | 271 | iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte_index), low32); |
282 | iosapic_intr_info[vector].low32 = low32; | 272 | iosapic_intr_info[irq].low32 = low32; |
283 | iosapic_intr_info[vector].dest = dest; | 273 | iosapic_intr_info[irq].dest = dest; |
284 | } | 274 | } |
285 | 275 | ||
286 | static void | 276 | static void |
@@ -296,9 +286,12 @@ kexec_disable_iosapic(void) | |||
296 | { | 286 | { |
297 | struct iosapic_intr_info *info; | 287 | struct iosapic_intr_info *info; |
298 | struct iosapic_rte_info *rte; | 288 | struct iosapic_rte_info *rte; |
299 | u8 vec = 0; | 289 | ia64_vector vec; |
300 | for (info = iosapic_intr_info; info < | 290 | int irq; |
301 | iosapic_intr_info + IA64_NUM_VECTORS; ++info, ++vec) { | 291 | |
292 | for (irq = 0; irq < NR_IRQS; irq++) { | ||
293 | info = &iosapic_intr_info[irq]; | ||
294 | vec = irq_to_vector(irq); | ||
302 | list_for_each_entry(rte, &info->rtes, | 295 | list_for_each_entry(rte, &info->rtes, |
303 | rte_list) { | 296 | rte_list) { |
304 | iosapic_write(rte->iosapic, | 297 | iosapic_write(rte->iosapic, |
@@ -315,15 +308,14 @@ mask_irq (unsigned int irq) | |||
315 | { | 308 | { |
316 | u32 low32; | 309 | u32 low32; |
317 | int rte_index; | 310 | int rte_index; |
318 | ia64_vector vec = irq_to_vector(irq); | ||
319 | struct iosapic_rte_info *rte; | 311 | struct iosapic_rte_info *rte; |
320 | 312 | ||
321 | if (list_empty(&iosapic_intr_info[vec].rtes)) | 313 | if (list_empty(&iosapic_intr_info[irq].rtes)) |
322 | return; /* not an IOSAPIC interrupt! */ | 314 | return; /* not an IOSAPIC interrupt! */ |
323 | 315 | ||
324 | /* set only the mask bit */ | 316 | /* set only the mask bit */ |
325 | low32 = iosapic_intr_info[vec].low32 |= IOSAPIC_MASK; | 317 | low32 = iosapic_intr_info[irq].low32 |= IOSAPIC_MASK; |
326 | list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) { | 318 | list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list) { |
327 | rte_index = rte->rte_index; | 319 | rte_index = rte->rte_index; |
328 | iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte_index), low32); | 320 | iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte_index), low32); |
329 | } | 321 | } |
@@ -334,14 +326,13 @@ unmask_irq (unsigned int irq) | |||
334 | { | 326 | { |
335 | u32 low32; | 327 | u32 low32; |
336 | int rte_index; | 328 | int rte_index; |
337 | ia64_vector vec = irq_to_vector(irq); | ||
338 | struct iosapic_rte_info *rte; | 329 | struct iosapic_rte_info *rte; |
339 | 330 | ||
340 | if (list_empty(&iosapic_intr_info[vec].rtes)) | 331 | if (list_empty(&iosapic_intr_info[irq].rtes)) |
341 | return; /* not an IOSAPIC interrupt! */ | 332 | return; /* not an IOSAPIC interrupt! */ |
342 | 333 | ||
343 | low32 = iosapic_intr_info[vec].low32 &= ~IOSAPIC_MASK; | 334 | low32 = iosapic_intr_info[irq].low32 &= ~IOSAPIC_MASK; |
344 | list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) { | 335 | list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list) { |
345 | rte_index = rte->rte_index; | 336 | rte_index = rte->rte_index; |
346 | iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte_index), low32); | 337 | iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte_index), low32); |
347 | } | 338 | } |
@@ -355,19 +346,17 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask) | |||
355 | u32 high32, low32; | 346 | u32 high32, low32; |
356 | int dest, rte_index; | 347 | int dest, rte_index; |
357 | int redir = (irq & IA64_IRQ_REDIRECTED) ? 1 : 0; | 348 | int redir = (irq & IA64_IRQ_REDIRECTED) ? 1 : 0; |
358 | ia64_vector vec; | ||
359 | struct iosapic_rte_info *rte; | 349 | struct iosapic_rte_info *rte; |
360 | struct iosapic *iosapic; | 350 | struct iosapic *iosapic; |
361 | 351 | ||
362 | irq &= (~IA64_IRQ_REDIRECTED); | 352 | irq &= (~IA64_IRQ_REDIRECTED); |
363 | vec = irq_to_vector(irq); | ||
364 | 353 | ||
365 | if (cpus_empty(mask)) | 354 | if (cpus_empty(mask)) |
366 | return; | 355 | return; |
367 | 356 | ||
368 | dest = cpu_physical_id(first_cpu(mask)); | 357 | dest = cpu_physical_id(first_cpu(mask)); |
369 | 358 | ||
370 | if (list_empty(&iosapic_intr_info[vec].rtes)) | 359 | if (list_empty(&iosapic_intr_info[irq].rtes)) |
371 | return; /* not an IOSAPIC interrupt */ | 360 | return; /* not an IOSAPIC interrupt */ |
372 | 361 | ||
373 | set_irq_affinity_info(irq, dest, redir); | 362 | set_irq_affinity_info(irq, dest, redir); |
@@ -375,7 +364,7 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask) | |||
375 | /* dest contains both id and eid */ | 364 | /* dest contains both id and eid */ |
376 | high32 = dest << IOSAPIC_DEST_SHIFT; | 365 | high32 = dest << IOSAPIC_DEST_SHIFT; |
377 | 366 | ||
378 | low32 = iosapic_intr_info[vec].low32 & ~(7 << IOSAPIC_DELIVERY_SHIFT); | 367 | low32 = iosapic_intr_info[irq].low32 & ~(7 << IOSAPIC_DELIVERY_SHIFT); |
379 | if (redir) | 368 | if (redir) |
380 | /* change delivery mode to lowest priority */ | 369 | /* change delivery mode to lowest priority */ |
381 | low32 |= (IOSAPIC_LOWEST_PRIORITY << IOSAPIC_DELIVERY_SHIFT); | 370 | low32 |= (IOSAPIC_LOWEST_PRIORITY << IOSAPIC_DELIVERY_SHIFT); |
@@ -383,9 +372,9 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask) | |||
383 | /* change delivery mode to fixed */ | 372 | /* change delivery mode to fixed */ |
384 | low32 |= (IOSAPIC_FIXED << IOSAPIC_DELIVERY_SHIFT); | 373 | low32 |= (IOSAPIC_FIXED << IOSAPIC_DELIVERY_SHIFT); |
385 | 374 | ||
386 | iosapic_intr_info[vec].low32 = low32; | 375 | iosapic_intr_info[irq].low32 = low32; |
387 | iosapic_intr_info[vec].dest = dest; | 376 | iosapic_intr_info[irq].dest = dest; |
388 | list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) { | 377 | list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list) { |
389 | iosapic = rte->iosapic; | 378 | iosapic = rte->iosapic; |
390 | rte_index = rte->rte_index; | 379 | rte_index = rte->rte_index; |
391 | iosapic_write(iosapic, IOSAPIC_RTE_HIGH(rte_index), high32); | 380 | iosapic_write(iosapic, IOSAPIC_RTE_HIGH(rte_index), high32); |
@@ -412,7 +401,7 @@ iosapic_end_level_irq (unsigned int irq) | |||
412 | struct iosapic_rte_info *rte; | 401 | struct iosapic_rte_info *rte; |
413 | 402 | ||
414 | move_native_irq(irq); | 403 | move_native_irq(irq); |
415 | list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) | 404 | list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list) |
416 | iosapic_eoi(rte->iosapic->addr, vec); | 405 | iosapic_eoi(rte->iosapic->addr, vec); |
417 | } | 406 | } |
418 | 407 | ||
@@ -498,10 +487,9 @@ iosapic_version (char __iomem *addr) | |||
498 | return __iosapic_read(addr, IOSAPIC_VERSION); | 487 | return __iosapic_read(addr, IOSAPIC_VERSION); |
499 | } | 488 | } |
500 | 489 | ||
501 | static int iosapic_find_sharable_vector (unsigned long trigger, | 490 | static int iosapic_find_sharable_irq(unsigned long trigger, unsigned long pol) |
502 | unsigned long pol) | ||
503 | { | 491 | { |
504 | int i, vector = -ENOSPC, min_count = -1; | 492 | int i, irq = -ENOSPC, min_count = -1; |
505 | struct iosapic_intr_info *info; | 493 | struct iosapic_intr_info *info; |
506 | 494 | ||
507 | /* | 495 | /* |
@@ -511,19 +499,18 @@ static int iosapic_find_sharable_vector (unsigned long trigger, | |||
511 | if (trigger == IOSAPIC_EDGE) | 499 | if (trigger == IOSAPIC_EDGE) |
512 | return -EINVAL; | 500 | return -EINVAL; |
513 | 501 | ||
514 | for (i = IA64_FIRST_DEVICE_VECTOR; i <= IA64_LAST_DEVICE_VECTOR; i++) { | 502 | for (i = 0; i <= NR_IRQS; i++) { |
515 | info = &iosapic_intr_info[i]; | 503 | info = &iosapic_intr_info[i]; |
516 | if (info->trigger == trigger && info->polarity == pol && | 504 | if (info->trigger == trigger && info->polarity == pol && |
517 | (info->dmode == IOSAPIC_FIXED || info->dmode == | 505 | (info->dmode == IOSAPIC_FIXED || info->dmode == |
518 | IOSAPIC_LOWEST_PRIORITY)) { | 506 | IOSAPIC_LOWEST_PRIORITY)) { |
519 | if (min_count == -1 || info->count < min_count) { | 507 | if (min_count == -1 || info->count < min_count) { |
520 | vector = i; | 508 | irq = i; |
521 | min_count = info->count; | 509 | min_count = info->count; |
522 | } | 510 | } |
523 | } | 511 | } |
524 | } | 512 | } |
525 | 513 | return irq; | |
526 | return vector; | ||
527 | } | 514 | } |
528 | 515 | ||
529 | /* | 516 | /* |
@@ -531,26 +518,25 @@ static int iosapic_find_sharable_vector (unsigned long trigger, | |||
531 | * assign a new vector for the other and make the vector available | 518 | * assign a new vector for the other and make the vector available |
532 | */ | 519 | */ |
533 | static void __init | 520 | static void __init |
534 | iosapic_reassign_vector (int vector) | 521 | iosapic_reassign_vector (int irq) |
535 | { | 522 | { |
536 | int irq, new_vector; | 523 | int new_irq; |
537 | 524 | ||
538 | if (!list_empty(&iosapic_intr_info[vector].rtes)) { | 525 | if (!list_empty(&iosapic_intr_info[irq].rtes)) { |
539 | irq = create_irq(); | 526 | new_irq = create_irq(); |
540 | if (irq < 0) | 527 | if (new_irq < 0) |
541 | panic("%s: out of interrupt vectors!\n", __FUNCTION__); | 528 | panic("%s: out of interrupt vectors!\n", __FUNCTION__); |
542 | new_vector = irq_to_vector(irq); | ||
543 | printk(KERN_INFO "Reassigning vector %d to %d\n", | 529 | printk(KERN_INFO "Reassigning vector %d to %d\n", |
544 | vector, new_vector); | 530 | irq_to_vector(irq), irq_to_vector(new_irq)); |
545 | memcpy(&iosapic_intr_info[new_vector], &iosapic_intr_info[vector], | 531 | memcpy(&iosapic_intr_info[new_irq], &iosapic_intr_info[irq], |
546 | sizeof(struct iosapic_intr_info)); | 532 | sizeof(struct iosapic_intr_info)); |
547 | INIT_LIST_HEAD(&iosapic_intr_info[new_vector].rtes); | 533 | INIT_LIST_HEAD(&iosapic_intr_info[new_irq].rtes); |
548 | list_move(iosapic_intr_info[vector].rtes.next, | 534 | list_move(iosapic_intr_info[irq].rtes.next, |
549 | &iosapic_intr_info[new_vector].rtes); | 535 | &iosapic_intr_info[new_irq].rtes); |
550 | memset(&iosapic_intr_info[vector], 0, | 536 | memset(&iosapic_intr_info[irq], 0, |
551 | sizeof(struct iosapic_intr_info)); | 537 | sizeof(struct iosapic_intr_info)); |
552 | iosapic_intr_info[vector].low32 = IOSAPIC_MASK; | 538 | iosapic_intr_info[irq].low32 = IOSAPIC_MASK; |
553 | INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes); | 539 | INIT_LIST_HEAD(&iosapic_intr_info[irq].rtes); |
554 | } | 540 | } |
555 | } | 541 | } |
556 | 542 | ||
@@ -595,13 +581,13 @@ static void iosapic_free_rte (struct iosapic_rte_info *rte) | |||
595 | kfree(rte); | 581 | kfree(rte); |
596 | } | 582 | } |
597 | 583 | ||
598 | static inline int vector_is_shared (int vector) | 584 | static inline int irq_is_shared (int irq) |
599 | { | 585 | { |
600 | return (iosapic_intr_info[vector].count > 1); | 586 | return (iosapic_intr_info[irq].count > 1); |
601 | } | 587 | } |
602 | 588 | ||
603 | static int | 589 | static int |
604 | register_intr (unsigned int gsi, int vector, unsigned char delivery, | 590 | register_intr (unsigned int gsi, int irq, unsigned char delivery, |
605 | unsigned long polarity, unsigned long trigger) | 591 | unsigned long polarity, unsigned long trigger) |
606 | { | 592 | { |
607 | irq_desc_t *idesc; | 593 | irq_desc_t *idesc; |
@@ -616,7 +602,7 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery, | |||
616 | return -ENODEV; | 602 | return -ENODEV; |
617 | } | 603 | } |
618 | 604 | ||
619 | rte = gsi_vector_to_rte(gsi, vector); | 605 | rte = find_rte(irq, gsi); |
620 | if (!rte) { | 606 | if (!rte) { |
621 | rte = iosapic_alloc_rte(); | 607 | rte = iosapic_alloc_rte(); |
622 | if (!rte) { | 608 | if (!rte) { |
@@ -628,12 +614,12 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery, | |||
628 | rte->iosapic = &iosapic_lists[index]; | 614 | rte->iosapic = &iosapic_lists[index]; |
629 | rte->rte_index = gsi - rte->iosapic->gsi_base; | 615 | rte->rte_index = gsi - rte->iosapic->gsi_base; |
630 | rte->refcnt++; | 616 | rte->refcnt++; |
631 | list_add_tail(&rte->rte_list, &iosapic_intr_info[vector].rtes); | 617 | list_add_tail(&rte->rte_list, &iosapic_intr_info[irq].rtes); |
632 | iosapic_intr_info[vector].count++; | 618 | iosapic_intr_info[irq].count++; |
633 | iosapic_lists[index].rtes_inuse++; | 619 | iosapic_lists[index].rtes_inuse++; |
634 | } | 620 | } |
635 | else if (vector_is_shared(vector)) { | 621 | else if (irq_is_shared(irq)) { |
636 | struct iosapic_intr_info *info = &iosapic_intr_info[vector]; | 622 | struct iosapic_intr_info *info = &iosapic_intr_info[irq]; |
637 | if (info->trigger != trigger || info->polarity != polarity) { | 623 | if (info->trigger != trigger || info->polarity != polarity) { |
638 | printk (KERN_WARNING | 624 | printk (KERN_WARNING |
639 | "%s: cannot override the interrupt\n", | 625 | "%s: cannot override the interrupt\n", |
@@ -642,21 +628,21 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery, | |||
642 | } | 628 | } |
643 | } | 629 | } |
644 | 630 | ||
645 | iosapic_intr_info[vector].polarity = polarity; | 631 | iosapic_intr_info[irq].polarity = polarity; |
646 | iosapic_intr_info[vector].dmode = delivery; | 632 | iosapic_intr_info[irq].dmode = delivery; |
647 | iosapic_intr_info[vector].trigger = trigger; | 633 | iosapic_intr_info[irq].trigger = trigger; |
648 | 634 | ||
649 | if (trigger == IOSAPIC_EDGE) | 635 | if (trigger == IOSAPIC_EDGE) |
650 | irq_type = &irq_type_iosapic_edge; | 636 | irq_type = &irq_type_iosapic_edge; |
651 | else | 637 | else |
652 | irq_type = &irq_type_iosapic_level; | 638 | irq_type = &irq_type_iosapic_level; |
653 | 639 | ||
654 | idesc = irq_desc + vector; | 640 | idesc = irq_desc + irq; |
655 | if (idesc->chip != irq_type) { | 641 | if (idesc->chip != irq_type) { |
656 | if (idesc->chip != &no_irq_type) | 642 | if (idesc->chip != &no_irq_type) |
657 | printk(KERN_WARNING | 643 | printk(KERN_WARNING |
658 | "%s: changing vector %d from %s to %s\n", | 644 | "%s: changing vector %d from %s to %s\n", |
659 | __FUNCTION__, vector, | 645 | __FUNCTION__, irq_to_vector(irq), |
660 | idesc->chip->name, irq_type->name); | 646 | idesc->chip->name, irq_type->name); |
661 | idesc->chip = irq_type; | 647 | idesc->chip = irq_type; |
662 | } | 648 | } |
@@ -664,7 +650,7 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery, | |||
664 | } | 650 | } |
665 | 651 | ||
666 | static unsigned int | 652 | static unsigned int |
667 | get_target_cpu (unsigned int gsi, int vector) | 653 | get_target_cpu (unsigned int gsi, int irq) |
668 | { | 654 | { |
669 | #ifdef CONFIG_SMP | 655 | #ifdef CONFIG_SMP |
670 | static int cpu = -1; | 656 | static int cpu = -1; |
@@ -674,8 +660,8 @@ get_target_cpu (unsigned int gsi, int vector) | |||
674 | * In case of vector shared by multiple RTEs, all RTEs that | 660 | * In case of vector shared by multiple RTEs, all RTEs that |
675 | * share the vector need to use the same destination CPU. | 661 | * share the vector need to use the same destination CPU. |
676 | */ | 662 | */ |
677 | if (!list_empty(&iosapic_intr_info[vector].rtes)) | 663 | if (!list_empty(&iosapic_intr_info[irq].rtes)) |
678 | return iosapic_intr_info[vector].dest; | 664 | return iosapic_intr_info[irq].dest; |
679 | 665 | ||
680 | /* | 666 | /* |
681 | * If the platform supports redirection via XTP, let it | 667 | * If the platform supports redirection via XTP, let it |
@@ -692,7 +678,7 @@ get_target_cpu (unsigned int gsi, int vector) | |||
692 | return cpu_physical_id(smp_processor_id()); | 678 | return cpu_physical_id(smp_processor_id()); |
693 | 679 | ||
694 | #ifdef CONFIG_ACPI | 680 | #ifdef CONFIG_ACPI |
695 | if (cpe_vector > 0 && vector == IA64_CPEP_VECTOR) | 681 | if (cpe_vector > 0 && irq_to_vector(irq) == IA64_CPEP_VECTOR) |
696 | return get_cpei_target_cpu(); | 682 | return get_cpei_target_cpu(); |
697 | #endif | 683 | #endif |
698 | 684 | ||
@@ -718,8 +704,8 @@ get_target_cpu (unsigned int gsi, int vector) | |||
718 | if (!num_cpus) | 704 | if (!num_cpus) |
719 | goto skip_numa_setup; | 705 | goto skip_numa_setup; |
720 | 706 | ||
721 | /* Use vector assignment to distribute across cpus in node */ | 707 | /* Use irq assignment to distribute across cpus in node */ |
722 | cpu_index = vector % num_cpus; | 708 | cpu_index = irq % num_cpus; |
723 | 709 | ||
724 | for (numa_cpu = first_cpu(cpu_mask) ; i < cpu_index ; i++) | 710 | for (numa_cpu = first_cpu(cpu_mask) ; i < cpu_index ; i++) |
725 | numa_cpu = next_cpu(numa_cpu, cpu_mask); | 711 | numa_cpu = next_cpu(numa_cpu, cpu_mask); |
@@ -754,7 +740,7 @@ int | |||
754 | iosapic_register_intr (unsigned int gsi, | 740 | iosapic_register_intr (unsigned int gsi, |
755 | unsigned long polarity, unsigned long trigger) | 741 | unsigned long polarity, unsigned long trigger) |
756 | { | 742 | { |
757 | int irq, vector, mask = 1, err; | 743 | int irq, mask = 1, err; |
758 | unsigned int dest; | 744 | unsigned int dest; |
759 | unsigned long flags; | 745 | unsigned long flags; |
760 | struct iosapic_rte_info *rte; | 746 | struct iosapic_rte_info *rte; |
@@ -766,9 +752,9 @@ iosapic_register_intr (unsigned int gsi, | |||
766 | * don't touch the RTE. | 752 | * don't touch the RTE. |
767 | */ | 753 | */ |
768 | spin_lock_irqsave(&iosapic_lock, flags); | 754 | spin_lock_irqsave(&iosapic_lock, flags); |
769 | vector = gsi_to_vector(gsi); | 755 | irq = __gsi_to_irq(gsi); |
770 | if (vector > 0) { | 756 | if (irq > 0) { |
771 | rte = gsi_vector_to_rte(gsi, vector); | 757 | rte = find_rte(irq, gsi); |
772 | rte->refcnt++; | 758 | rte->refcnt++; |
773 | goto unlock_iosapic_lock; | 759 | goto unlock_iosapic_lock; |
774 | } | 760 | } |
@@ -776,18 +762,17 @@ iosapic_register_intr (unsigned int gsi, | |||
776 | /* If vector is running out, we try to find a sharable vector */ | 762 | /* If vector is running out, we try to find a sharable vector */ |
777 | irq = create_irq(); | 763 | irq = create_irq(); |
778 | if (irq < 0) { | 764 | if (irq < 0) { |
779 | vector = iosapic_find_sharable_vector(trigger, polarity); | 765 | irq = iosapic_find_sharable_irq(trigger, polarity); |
780 | if (vector < 0) | 766 | if (irq < 0) |
781 | goto unlock_iosapic_lock; | 767 | goto unlock_iosapic_lock; |
782 | } else | 768 | } |
783 | vector = irq_to_vector(irq); | ||
784 | 769 | ||
785 | spin_lock(&irq_desc[vector].lock); | 770 | spin_lock(&irq_desc[irq].lock); |
786 | dest = get_target_cpu(gsi, vector); | 771 | dest = get_target_cpu(gsi, irq); |
787 | err = register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, | 772 | err = register_intr(gsi, irq, IOSAPIC_LOWEST_PRIORITY, |
788 | polarity, trigger); | 773 | polarity, trigger); |
789 | if (err < 0) { | 774 | if (err < 0) { |
790 | vector = err; | 775 | irq = err; |
791 | goto unlock_all; | 776 | goto unlock_all; |
792 | } | 777 | } |
793 | 778 | ||
@@ -795,27 +780,27 @@ iosapic_register_intr (unsigned int gsi, | |||
795 | * If the vector is shared and already unmasked for other | 780 | * If the vector is shared and already unmasked for other |
796 | * interrupt sources, don't mask it. | 781 | * interrupt sources, don't mask it. |
797 | */ | 782 | */ |
798 | low32 = iosapic_intr_info[vector].low32; | 783 | low32 = iosapic_intr_info[irq].low32; |
799 | if (vector_is_shared(vector) && !(low32 & IOSAPIC_MASK)) | 784 | if (irq_is_shared(irq) && !(low32 & IOSAPIC_MASK)) |
800 | mask = 0; | 785 | mask = 0; |
801 | set_rte(gsi, vector, dest, mask); | 786 | set_rte(gsi, irq, dest, mask); |
802 | 787 | ||
803 | printk(KERN_INFO "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d\n", | 788 | printk(KERN_INFO "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d\n", |
804 | gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"), | 789 | gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"), |
805 | (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), | 790 | (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), |
806 | cpu_logical_id(dest), dest, vector); | 791 | cpu_logical_id(dest), dest, irq_to_vector(irq)); |
807 | unlock_all: | 792 | unlock_all: |
808 | spin_unlock(&irq_desc[vector].lock); | 793 | spin_unlock(&irq_desc[irq].lock); |
809 | unlock_iosapic_lock: | 794 | unlock_iosapic_lock: |
810 | spin_unlock_irqrestore(&iosapic_lock, flags); | 795 | spin_unlock_irqrestore(&iosapic_lock, flags); |
811 | return vector; | 796 | return irq; |
812 | } | 797 | } |
813 | 798 | ||
814 | void | 799 | void |
815 | iosapic_unregister_intr (unsigned int gsi) | 800 | iosapic_unregister_intr (unsigned int gsi) |
816 | { | 801 | { |
817 | unsigned long flags; | 802 | unsigned long flags; |
818 | int irq, vector, index; | 803 | int irq, index; |
819 | irq_desc_t *idesc; | 804 | irq_desc_t *idesc; |
820 | u32 low32; | 805 | u32 low32; |
821 | unsigned long trigger, polarity; | 806 | unsigned long trigger, polarity; |
@@ -834,10 +819,9 @@ iosapic_unregister_intr (unsigned int gsi) | |||
834 | WARN_ON(1); | 819 | WARN_ON(1); |
835 | return; | 820 | return; |
836 | } | 821 | } |
837 | vector = irq_to_vector(irq); | ||
838 | 822 | ||
839 | spin_lock_irqsave(&iosapic_lock, flags); | 823 | spin_lock_irqsave(&iosapic_lock, flags); |
840 | if ((rte = gsi_vector_to_rte(gsi, vector)) == NULL) { | 824 | if ((rte = find_rte(irq, gsi)) == NULL) { |
841 | printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n", | 825 | printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n", |
842 | gsi); | 826 | gsi); |
843 | WARN_ON(1); | 827 | WARN_ON(1); |
@@ -854,36 +838,36 @@ iosapic_unregister_intr (unsigned int gsi) | |||
854 | spin_unlock(&idesc->lock); | 838 | spin_unlock(&idesc->lock); |
855 | 839 | ||
856 | /* Mask the interrupt */ | 840 | /* Mask the interrupt */ |
857 | low32 = iosapic_intr_info[vector].low32 | IOSAPIC_MASK; | 841 | low32 = iosapic_intr_info[irq].low32 | IOSAPIC_MASK; |
858 | iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte->rte_index), low32); | 842 | iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte->rte_index), low32); |
859 | 843 | ||
860 | iosapic_intr_info[vector].count--; | 844 | iosapic_intr_info[irq].count--; |
861 | iosapic_free_rte(rte); | 845 | iosapic_free_rte(rte); |
862 | index = find_iosapic(gsi); | 846 | index = find_iosapic(gsi); |
863 | iosapic_lists[index].rtes_inuse--; | 847 | iosapic_lists[index].rtes_inuse--; |
864 | WARN_ON(iosapic_lists[index].rtes_inuse < 0); | 848 | WARN_ON(iosapic_lists[index].rtes_inuse < 0); |
865 | 849 | ||
866 | trigger = iosapic_intr_info[vector].trigger; | 850 | trigger = iosapic_intr_info[irq].trigger; |
867 | polarity = iosapic_intr_info[vector].polarity; | 851 | polarity = iosapic_intr_info[irq].polarity; |
868 | dest = iosapic_intr_info[vector].dest; | 852 | dest = iosapic_intr_info[irq].dest; |
869 | printk(KERN_INFO | 853 | printk(KERN_INFO |
870 | "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d unregistered\n", | 854 | "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d unregistered\n", |
871 | gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"), | 855 | gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"), |
872 | (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), | 856 | (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), |
873 | cpu_logical_id(dest), dest, vector); | 857 | cpu_logical_id(dest), dest, irq_to_vector(irq)); |
874 | 858 | ||
875 | if (list_empty(&iosapic_intr_info[vector].rtes)) { | 859 | if (list_empty(&iosapic_intr_info[irq].rtes)) { |
876 | /* Sanity check */ | 860 | /* Sanity check */ |
877 | BUG_ON(iosapic_intr_info[vector].count); | 861 | BUG_ON(iosapic_intr_info[irq].count); |
878 | #ifdef CONFIG_SMP | 862 | #ifdef CONFIG_SMP |
879 | /* Clear affinity */ | 863 | /* Clear affinity */ |
880 | cpus_setall(idesc->affinity); | 864 | cpus_setall(idesc->affinity); |
881 | #endif | 865 | #endif |
882 | /* Clear the interrupt information */ | 866 | /* Clear the interrupt information */ |
883 | memset(&iosapic_intr_info[vector], 0, | 867 | memset(&iosapic_intr_info[irq], 0, |
884 | sizeof(struct iosapic_intr_info)); | 868 | sizeof(struct iosapic_intr_info)); |
885 | iosapic_intr_info[vector].low32 |= IOSAPIC_MASK; | 869 | iosapic_intr_info[irq].low32 |= IOSAPIC_MASK; |
886 | INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes); | 870 | INIT_LIST_HEAD(&iosapic_intr_info[irq].rtes); |
887 | 871 | ||
888 | /* Destroy IRQ */ | 872 | /* Destroy IRQ */ |
889 | destroy_irq(irq); | 873 | destroy_irq(irq); |
@@ -908,11 +892,12 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi, | |||
908 | switch (int_type) { | 892 | switch (int_type) { |
909 | case ACPI_INTERRUPT_PMI: | 893 | case ACPI_INTERRUPT_PMI: |
910 | vector = iosapic_vector; | 894 | vector = iosapic_vector; |
895 | irq = vector; /* FIXME */ | ||
911 | /* | 896 | /* |
912 | * since PMI vector is alloc'd by FW(ACPI) not by kernel, | 897 | * since PMI vector is alloc'd by FW(ACPI) not by kernel, |
913 | * we need to make sure the vector is available | 898 | * we need to make sure the vector is available |
914 | */ | 899 | */ |
915 | iosapic_reassign_vector(vector); | 900 | iosapic_reassign_vector(irq); |
916 | delivery = IOSAPIC_PMI; | 901 | delivery = IOSAPIC_PMI; |
917 | break; | 902 | break; |
918 | case ACPI_INTERRUPT_INIT: | 903 | case ACPI_INTERRUPT_INIT: |
@@ -924,6 +909,7 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi, | |||
924 | break; | 909 | break; |
925 | case ACPI_INTERRUPT_CPEI: | 910 | case ACPI_INTERRUPT_CPEI: |
926 | vector = IA64_CPE_VECTOR; | 911 | vector = IA64_CPE_VECTOR; |
912 | irq = vector; /* FIXME */ | ||
927 | delivery = IOSAPIC_LOWEST_PRIORITY; | 913 | delivery = IOSAPIC_LOWEST_PRIORITY; |
928 | mask = 1; | 914 | mask = 1; |
929 | break; | 915 | break; |
@@ -933,7 +919,7 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi, | |||
933 | return -1; | 919 | return -1; |
934 | } | 920 | } |
935 | 921 | ||
936 | register_intr(gsi, vector, delivery, polarity, trigger); | 922 | register_intr(gsi, irq, delivery, polarity, trigger); |
937 | 923 | ||
938 | printk(KERN_INFO | 924 | printk(KERN_INFO |
939 | "PLATFORM int %s (0x%x): GSI %u (%s, %s) -> CPU %d (0x%04x)" | 925 | "PLATFORM int %s (0x%x): GSI %u (%s, %s) -> CPU %d (0x%04x)" |
@@ -943,7 +929,7 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi, | |||
943 | (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), | 929 | (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), |
944 | cpu_logical_id(dest), dest, vector); | 930 | cpu_logical_id(dest), dest, vector); |
945 | 931 | ||
946 | set_rte(gsi, vector, dest, mask); | 932 | set_rte(gsi, irq, dest, mask); |
947 | return vector; | 933 | return vector; |
948 | } | 934 | } |
949 | 935 | ||
@@ -955,30 +941,30 @@ iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi, | |||
955 | unsigned long polarity, | 941 | unsigned long polarity, |
956 | unsigned long trigger) | 942 | unsigned long trigger) |
957 | { | 943 | { |
958 | int vector; | 944 | int vector, irq; |
959 | unsigned int dest = cpu_physical_id(smp_processor_id()); | 945 | unsigned int dest = cpu_physical_id(smp_processor_id()); |
960 | 946 | ||
961 | vector = isa_irq_to_vector(isa_irq); | 947 | vector = isa_irq_to_vector(isa_irq); |
962 | 948 | irq = vector; /* FIXME */ | |
963 | register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, trigger); | 949 | register_intr(gsi, irq, IOSAPIC_LOWEST_PRIORITY, polarity, trigger); |
964 | 950 | ||
965 | DBG("ISA: IRQ %u -> GSI %u (%s,%s) -> CPU %d (0x%04x) vector %d\n", | 951 | DBG("ISA: IRQ %u -> GSI %u (%s,%s) -> CPU %d (0x%04x) vector %d\n", |
966 | isa_irq, gsi, trigger == IOSAPIC_EDGE ? "edge" : "level", | 952 | isa_irq, gsi, trigger == IOSAPIC_EDGE ? "edge" : "level", |
967 | polarity == IOSAPIC_POL_HIGH ? "high" : "low", | 953 | polarity == IOSAPIC_POL_HIGH ? "high" : "low", |
968 | cpu_logical_id(dest), dest, vector); | 954 | cpu_logical_id(dest), dest, vector); |
969 | 955 | ||
970 | set_rte(gsi, vector, dest, 1); | 956 | set_rte(gsi, irq, dest, 1); |
971 | } | 957 | } |
972 | 958 | ||
973 | void __init | 959 | void __init |
974 | iosapic_system_init (int system_pcat_compat) | 960 | iosapic_system_init (int system_pcat_compat) |
975 | { | 961 | { |
976 | int vector; | 962 | int irq; |
977 | 963 | ||
978 | for (vector = 0; vector < IA64_NUM_VECTORS; ++vector) { | 964 | for (irq = 0; irq < NR_IRQS; ++irq) { |
979 | iosapic_intr_info[vector].low32 = IOSAPIC_MASK; | 965 | iosapic_intr_info[irq].low32 = IOSAPIC_MASK; |
980 | /* mark as unused */ | 966 | /* mark as unused */ |
981 | INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes); | 967 | INIT_LIST_HEAD(&iosapic_intr_info[irq].rtes); |
982 | } | 968 | } |
983 | 969 | ||
984 | pcat_compat = system_pcat_compat; | 970 | pcat_compat = system_pcat_compat; |