[SPARC64]: Do proper DMA IRQ syncing on Tomatillo

This was the main impetus behind adding the PCI IRQ shim.

In order to properly order DMA writes wrt. interrupts, you have to
write to a PCI controller register, then poll for that bit clearing.
There is one bit for each interrupt source, and setting this register
bit tells Tomatillo to drain all pending DMA from that device.

Furthermore, Tomatillo's with revision less than 4 require us to do a
block store due to some memory transaction ordering issues it has on
JBUS.

Signed-off-by: David S. Miller <davem@davemloft.net>

+54
+51
arch/sparc64/kernel/pci_schizo.c
··· 15 #include <asm/iommu.h> 16 #include <asm/irq.h> 17 #include <asm/upa.h> 18 19 #include "pci_impl.h" 20 #include "iommu_common.h" ··· 327 return ret; 328 } 329 330 static unsigned int schizo_irq_build(struct pci_pbm_info *pbm, 331 struct pci_dev *pdev, 332 unsigned int ino) ··· 407 408 bucket = __bucket(build_irq(pil, ign_fixup, iclr, imap)); 409 bucket->flags |= IBF_PCI; 410 411 return __irq(bucket); 412 } ··· 2062 2063 pbm->pbm_regs = pr_regs[0].phys_addr; 2064 pbm->controller_regs = pr_regs[1].phys_addr - 0x10000UL; 2065 2066 sprintf(pbm->name, 2067 (chip_type == PBM_CHIP_TYPE_TOMATILLO ?
··· 15 #include <asm/iommu.h> 16 #include <asm/irq.h> 17 #include <asm/upa.h> 18 + #include <asm/pstate.h> 19 20 #include "pci_impl.h" 21 #include "iommu_common.h" ··· 326 return ret; 327 } 328 329 + static void tomatillo_wsync_handler(struct ino_bucket *bucket, void *_arg1, void *_arg2) 330 + { 331 + unsigned long sync_reg = (unsigned long) _arg2; 332 + u64 mask = 1 << (__irq_ino(__irq(bucket)) & IMAP_INO); 333 + u64 val; 334 + int limit; 335 + 336 + schizo_write(sync_reg, mask); 337 + 338 + limit = 100000; 339 + val = 0; 340 + while (--limit) { 341 + val = schizo_read(sync_reg); 342 + if (!(val & mask)) 343 + break; 344 + } 345 + if (limit <= 0) { 346 + printk("tomatillo_wsync_handler: DMA won't sync [%lx:%lx]\n", 347 + val, mask); 348 + } 349 + 350 + if (_arg1) { 351 + static unsigned char cacheline[64] 352 + __attribute__ ((aligned (64))); 353 + 354 + __asm__ __volatile__("rd %%fprs, %0\n\t" 355 + "or %0, %4, %1\n\t" 356 + "wr %1, 0x0, %%fprs\n\t" 357 + "stda %%f0, [%5] %6\n\t" 358 + "wr %0, 0x0, %%fprs\n\t" 359 + "membar #Sync" 360 + : "=&r" (mask), "=&r" (val) 361 + : "0" (mask), "1" (val), 362 + "i" (FPRS_FEF), "r" (&cacheline[0]), 363 + "i" (ASI_BLK_COMMIT_P)); 364 + } 365 + } 366 + 367 static unsigned int schizo_irq_build(struct pci_pbm_info *pbm, 368 struct pci_dev *pdev, 369 unsigned int ino) ··· 368 369 bucket = __bucket(build_irq(pil, ign_fixup, iclr, imap)); 370 bucket->flags |= IBF_PCI; 371 + 372 + if (pdev && pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) { 373 + struct irq_desc *p = bucket->irq_info; 374 + 375 + p->pre_handler = tomatillo_wsync_handler; 376 + p->pre_handler_arg1 = ((pbm->chip_version <= 4) ? 377 + (void *) 1 : (void *) 0); 378 + p->pre_handler_arg2 = (void *) pbm->sync_reg; 379 + } 380 381 return __irq(bucket); 382 } ··· 2014 2015 pbm->pbm_regs = pr_regs[0].phys_addr; 2016 pbm->controller_regs = pr_regs[1].phys_addr - 0x10000UL; 2017 + 2018 + if (chip_type == PBM_CHIP_TYPE_TOMATILLO) 2019 + pbm->sync_reg = pr_regs[3].phys_addr + 0x1a18UL; 2020 2021 sprintf(pbm->name, 2022 (chip_type == PBM_CHIP_TYPE_TOMATILLO ?
+3
include/asm-sparc64/pbm.h
··· 145 /* Physical address base of PBM registers. */ 146 unsigned long pbm_regs; 147 148 /* Opaque 32-bit system bus Port ID. */ 149 u32 portid; 150
··· 145 /* Physical address base of PBM registers. */ 146 unsigned long pbm_regs; 147 148 + /* Physical address of DMA sync register, if any. */ 149 + unsigned long sync_reg; 150 + 151 /* Opaque 32-bit system bus Port ID. */ 152 u32 portid; 153