aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/ia64/sn/kernel/irq.c50
-rw-r--r--arch/ia64/sn/pci/pcibr/pcibr_provider.c4
-rw-r--r--arch/ia64/sn/pci/tioca_provider.c1
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
320static inline void
321sn_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
320static void force_interrupt(int irq) 330static 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
227int 231int
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/**