[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 15 #include <asm/iommu.h> 16 16 #include <asm/irq.h> 17 17 #include <asm/upa.h> 18 + #include <asm/pstate.h> 18 19 19 20 #include "pci_impl.h" 20 21 #include "iommu_common.h" ··· 327 326 return ret; 328 327 } 329 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 + 330 367 static unsigned int schizo_irq_build(struct pci_pbm_info *pbm, 331 368 struct pci_dev *pdev, 332 369 unsigned int ino) ··· 407 368 408 369 bucket = __bucket(build_irq(pil, ign_fixup, iclr, imap)); 409 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 + } 410 380 411 381 return __irq(bucket); 412 382 } ··· 2062 2014 2063 2015 pbm->pbm_regs = pr_regs[0].phys_addr; 2064 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; 2065 2020 2066 2021 sprintf(pbm->name, 2067 2022 (chip_type == PBM_CHIP_TYPE_TOMATILLO ?
+3
include/asm-sparc64/pbm.h
··· 145 145 /* Physical address base of PBM registers. */ 146 146 unsigned long pbm_regs; 147 147 148 + /* Physical address of DMA sync register, if any. */ 149 + unsigned long sync_reg; 150 + 148 151 /* Opaque 32-bit system bus Port ID. */ 149 152 u32 portid; 150 153