diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/ia64/sn/kernel/irq.c | 50 | ||||
-rw-r--r-- | arch/ia64/sn/pci/pcibr/pcibr_provider.c | 4 | ||||
-rw-r--r-- | arch/ia64/sn/pci/tioca_provider.c | 1 |
3 files changed, 33 insertions, 22 deletions
diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c index 84d276a14ecb..af061dba246f 100644 --- a/arch/ia64/sn/kernel/irq.c +++ b/arch/ia64/sn/kernel/irq.c | |||
@@ -317,6 +317,16 @@ void sn_irq_unfixup(struct pci_dev *pci_dev) | |||
317 | pci_dev_put(pci_dev); | 317 | pci_dev_put(pci_dev); |
318 | } | 318 | } |
319 | 319 | ||
320 | static inline void | ||
321 | sn_call_force_intr_provider(struct sn_irq_info *sn_irq_info) | ||
322 | { | ||
323 | struct sn_pcibus_provider *pci_provider; | ||
324 | |||
325 | pci_provider = sn_pci_provider[sn_irq_info->irq_bridge_type]; | ||
326 | if (pci_provider && pci_provider->force_interrupt) | ||
327 | (*pci_provider->force_interrupt)(sn_irq_info); | ||
328 | } | ||
329 | |||
320 | static void force_interrupt(int irq) | 330 | static void force_interrupt(int irq) |
321 | { | 331 | { |
322 | struct sn_irq_info *sn_irq_info; | 332 | struct sn_irq_info *sn_irq_info; |
@@ -325,11 +335,9 @@ static void force_interrupt(int irq) | |||
325 | return; | 335 | return; |
326 | 336 | ||
327 | rcu_read_lock(); | 337 | rcu_read_lock(); |
328 | list_for_each_entry_rcu(sn_irq_info, sn_irq_lh[irq], list) { | 338 | list_for_each_entry_rcu(sn_irq_info, sn_irq_lh[irq], list) |
329 | if (IS_PCI_BRIDGE_ASIC(sn_irq_info->irq_bridge_type) && | 339 | sn_call_force_intr_provider(sn_irq_info); |
330 | (sn_irq_info->irq_bridge != NULL)) | 340 | |
331 | pcibr_force_interrupt(sn_irq_info); | ||
332 | } | ||
333 | rcu_read_unlock(); | 341 | rcu_read_unlock(); |
334 | } | 342 | } |
335 | 343 | ||
@@ -351,6 +359,14 @@ static void sn_check_intr(int irq, struct sn_irq_info *sn_irq_info) | |||
351 | struct pcidev_info *pcidev_info; | 359 | struct pcidev_info *pcidev_info; |
352 | struct pcibus_info *pcibus_info; | 360 | struct pcibus_info *pcibus_info; |
353 | 361 | ||
362 | /* | ||
363 | * Bridge types attached to TIO (anything but PIC) do not need this WAR | ||
364 | * since they do not target Shub II interrupt registers. If that | ||
365 | * ever changes, this check needs to accomodate. | ||
366 | */ | ||
367 | if (sn_irq_info->irq_bridge_type != PCIIO_ASIC_TYPE_PIC) | ||
368 | return; | ||
369 | |||
354 | pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; | 370 | pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; |
355 | if (!pcidev_info) | 371 | if (!pcidev_info) |
356 | return; | 372 | return; |
@@ -377,16 +393,12 @@ static void sn_check_intr(int irq, struct sn_irq_info *sn_irq_info) | |||
377 | break; | 393 | break; |
378 | } | 394 | } |
379 | if (!test_bit(irr_bit, &irr_reg)) { | 395 | if (!test_bit(irr_bit, &irr_reg)) { |
380 | if (!test_bit(irq, pda->sn_soft_irr)) { | 396 | if (!test_bit(irq, pda->sn_in_service_ivecs)) { |
381 | if (!test_bit(irq, pda->sn_in_service_ivecs)) { | 397 | regval &= 0xff; |
382 | regval &= 0xff; | 398 | if (sn_irq_info->irq_int_bit & regval & |
383 | if (sn_irq_info->irq_int_bit & regval & | 399 | sn_irq_info->irq_last_intr) { |
384 | sn_irq_info->irq_last_intr) { | 400 | regval &= ~(sn_irq_info->irq_int_bit & regval); |
385 | regval &= | 401 | sn_call_force_intr_provider(sn_irq_info); |
386 | ~(sn_irq_info-> | ||
387 | irq_int_bit & regval); | ||
388 | pcibr_force_interrupt(sn_irq_info); | ||
389 | } | ||
390 | } | 402 | } |
391 | } | 403 | } |
392 | } | 404 | } |
@@ -404,13 +416,7 @@ void sn_lb_int_war_check(void) | |||
404 | rcu_read_lock(); | 416 | rcu_read_lock(); |
405 | for (i = pda->sn_first_irq; i <= pda->sn_last_irq; i++) { | 417 | for (i = pda->sn_first_irq; i <= pda->sn_last_irq; i++) { |
406 | list_for_each_entry_rcu(sn_irq_info, sn_irq_lh[i], list) { | 418 | list_for_each_entry_rcu(sn_irq_info, sn_irq_lh[i], list) { |
407 | /* | 419 | sn_check_intr(i, sn_irq_info); |
408 | * Only call for PCI bridges that are fully | ||
409 | * initialized. | ||
410 | */ | ||
411 | if (IS_PCI_BRIDGE_ASIC(sn_irq_info->irq_bridge_type) && | ||
412 | (sn_irq_info->irq_bridge != NULL)) | ||
413 | sn_check_intr(i, sn_irq_info); | ||
414 | } | 420 | } |
415 | } | 421 | } |
416 | rcu_read_unlock(); | 422 | rcu_read_unlock(); |
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c index f8cfe8acdc3c..ff9c7de925d1 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c | |||
@@ -178,6 +178,9 @@ void pcibr_force_interrupt(struct sn_irq_info *sn_irq_info) | |||
178 | struct pcibus_info *pcibus_info; | 178 | struct pcibus_info *pcibus_info; |
179 | int bit = sn_irq_info->irq_int_bit; | 179 | int bit = sn_irq_info->irq_int_bit; |
180 | 180 | ||
181 | if (! sn_irq_info->irq_bridge) | ||
182 | return; | ||
183 | |||
181 | pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; | 184 | pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; |
182 | if (pcidev_info) { | 185 | if (pcidev_info) { |
183 | pcibus_info = | 186 | pcibus_info = |
@@ -222,6 +225,7 @@ struct sn_pcibus_provider pcibr_provider = { | |||
222 | .dma_map_consistent = pcibr_dma_map_consistent, | 225 | .dma_map_consistent = pcibr_dma_map_consistent, |
223 | .dma_unmap = pcibr_dma_unmap, | 226 | .dma_unmap = pcibr_dma_unmap, |
224 | .bus_fixup = pcibr_bus_fixup, | 227 | .bus_fixup = pcibr_bus_fixup, |
228 | .force_interrupt = pcibr_force_interrupt | ||
225 | }; | 229 | }; |
226 | 230 | ||
227 | int | 231 | int |
diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c index 2fef7c10d6e5..4ea04cfa30ff 100644 --- a/arch/ia64/sn/pci/tioca_provider.c +++ b/arch/ia64/sn/pci/tioca_provider.c | |||
@@ -657,6 +657,7 @@ static struct sn_pcibus_provider tioca_pci_interfaces = { | |||
657 | .dma_map_consistent = tioca_dma_map, | 657 | .dma_map_consistent = tioca_dma_map, |
658 | .dma_unmap = tioca_dma_unmap, | 658 | .dma_unmap = tioca_dma_unmap, |
659 | .bus_fixup = tioca_bus_fixup, | 659 | .bus_fixup = tioca_bus_fixup, |
660 | .force_interrupt = NULL | ||
660 | }; | 661 | }; |
661 | 662 | ||
662 | /** | 663 | /** |