1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * PCI Streaming Cache operations: initialization and configuration 31*7c478bd9Sstevel@tonic-gate */ 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 35*7c478bd9Sstevel@tonic-gate #include <vm/seg_kmem.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/async.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/spl.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/pci/pci_obj.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/x_call.h> /* XCALL_PIL */ 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate /*LINTLIBRARY*/ 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate void 46*7c478bd9Sstevel@tonic-gate sc_create(pci_t *pci_p) 47*7c478bd9Sstevel@tonic-gate { 48*7c478bd9Sstevel@tonic-gate dev_info_t *dip = pci_p->pci_dip; 49*7c478bd9Sstevel@tonic-gate sc_t *sc_p; 50*7c478bd9Sstevel@tonic-gate uint64_t paddr; 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate #ifdef lint 53*7c478bd9Sstevel@tonic-gate dip = dip; 54*7c478bd9Sstevel@tonic-gate #endif 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate if (!pci_stream_buf_exists) 57*7c478bd9Sstevel@tonic-gate return; 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate /* 60*7c478bd9Sstevel@tonic-gate * Allocate streaming cache state structure and link it to 61*7c478bd9Sstevel@tonic-gate * the pci state structure. 62*7c478bd9Sstevel@tonic-gate */ 63*7c478bd9Sstevel@tonic-gate sc_p = (sc_t *)kmem_zalloc(sizeof (sc_t), KM_SLEEP); 64*7c478bd9Sstevel@tonic-gate pci_p->pci_sc_p = sc_p; 65*7c478bd9Sstevel@tonic-gate sc_p->sc_pci_p = pci_p; 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate pci_sc_setup(sc_p); 68*7c478bd9Sstevel@tonic-gate sc_p->sc_sync_reg_pa = va_to_pa((char *)sc_p->sc_sync_reg); 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate DEBUG3(DBG_ATTACH, dip, "sc_create: ctrl=%x, invl=%x, sync=%x\n", 71*7c478bd9Sstevel@tonic-gate sc_p->sc_ctrl_reg, sc_p->sc_invl_reg, 72*7c478bd9Sstevel@tonic-gate sc_p->sc_sync_reg); 73*7c478bd9Sstevel@tonic-gate DEBUG2(DBG_ATTACH, dip, "sc_create: ctx_invl=%x ctx_match=%x\n", 74*7c478bd9Sstevel@tonic-gate sc_p->sc_ctx_invl_reg, sc_p->sc_ctx_match_reg); 75*7c478bd9Sstevel@tonic-gate DEBUG3(DBG_ATTACH, dip, 76*7c478bd9Sstevel@tonic-gate "sc_create: data_diag=%x, tag_diag=%x, ltag_diag=%x\n", 77*7c478bd9Sstevel@tonic-gate sc_p->sc_data_diag_acc, sc_p->sc_tag_diag_acc, 78*7c478bd9Sstevel@tonic-gate sc_p->sc_ltag_diag_acc); 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate /* 81*7c478bd9Sstevel@tonic-gate * Allocate the flush/sync buffer. Make sure it's properly 82*7c478bd9Sstevel@tonic-gate * aligned. 83*7c478bd9Sstevel@tonic-gate */ 84*7c478bd9Sstevel@tonic-gate sc_p->sc_sync_flag_base = 85*7c478bd9Sstevel@tonic-gate vmem_xalloc(static_alloc_arena, PCI_SYNC_FLAG_SIZE, 86*7c478bd9Sstevel@tonic-gate PCI_SYNC_FLAG_SIZE, 0, 0, NULL, NULL, VM_SLEEP); 87*7c478bd9Sstevel@tonic-gate sc_p->sc_sync_flag_vaddr = (uint64_t *)sc_p->sc_sync_flag_base; 88*7c478bd9Sstevel@tonic-gate paddr = (uint64_t)hat_getpfnum(kas.a_hat, 89*7c478bd9Sstevel@tonic-gate (caddr_t)sc_p->sc_sync_flag_vaddr); 90*7c478bd9Sstevel@tonic-gate paddr <<= MMU_PAGESHIFT; 91*7c478bd9Sstevel@tonic-gate paddr += (uint64_t) 92*7c478bd9Sstevel@tonic-gate ((uintptr_t)sc_p->sc_sync_flag_vaddr & ~MMU_PAGEMASK); 93*7c478bd9Sstevel@tonic-gate sc_p->sc_sync_flag_pa = paddr; 94*7c478bd9Sstevel@tonic-gate DEBUG2(DBG_ATTACH, dip, "sc_create: sync buffer - vaddr=%x paddr=%x\n", 95*7c478bd9Sstevel@tonic-gate sc_p->sc_sync_flag_vaddr, sc_p->sc_sync_flag_pa); 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate /* 98*7c478bd9Sstevel@tonic-gate * Create a mutex to go along with it. While the mutex is held, 99*7c478bd9Sstevel@tonic-gate * all interrupts should be blocked. This will prevent driver 100*7c478bd9Sstevel@tonic-gate * interrupt routines from attempting to acquire the mutex while 101*7c478bd9Sstevel@tonic-gate * held by a lower priority interrupt routine. Note also that 102*7c478bd9Sstevel@tonic-gate * we now block cross calls as well, to prevent issues with 103*7c478bd9Sstevel@tonic-gate * relocation. 104*7c478bd9Sstevel@tonic-gate */ 105*7c478bd9Sstevel@tonic-gate mutex_init(&sc_p->sc_sync_mutex, NULL, MUTEX_DRIVER, 106*7c478bd9Sstevel@tonic-gate (void *)ipltospl(XCALL_PIL)); 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate sc_configure(sc_p); 109*7c478bd9Sstevel@tonic-gate } 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate void 112*7c478bd9Sstevel@tonic-gate sc_destroy(pci_t *pci_p) 113*7c478bd9Sstevel@tonic-gate { 114*7c478bd9Sstevel@tonic-gate sc_t *sc_p; 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate if (!pci_stream_buf_exists) 117*7c478bd9Sstevel@tonic-gate return; 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate sc_p = pci_p->pci_sc_p; 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate DEBUG0(DBG_DETACH, pci_p->pci_dip, "sc_destroy:\n"); 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gate vmem_xfree(static_alloc_arena, sc_p->sc_sync_flag_base, 124*7c478bd9Sstevel@tonic-gate PCI_SYNC_FLAG_SIZE); 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate /* 127*7c478bd9Sstevel@tonic-gate * Free the streaming cache state structure. 128*7c478bd9Sstevel@tonic-gate */ 129*7c478bd9Sstevel@tonic-gate kmem_free(sc_p, sizeof (sc_t)); 130*7c478bd9Sstevel@tonic-gate pci_p->pci_sc_p = NULL; 131*7c478bd9Sstevel@tonic-gate } 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate void 134*7c478bd9Sstevel@tonic-gate sc_configure(sc_t *sc_p) 135*7c478bd9Sstevel@tonic-gate { 136*7c478bd9Sstevel@tonic-gate int i, instance; 137*7c478bd9Sstevel@tonic-gate uint64_t l; 138*7c478bd9Sstevel@tonic-gate dev_info_t *dip; 139*7c478bd9Sstevel@tonic-gate 140*7c478bd9Sstevel@tonic-gate if (!sc_p) 141*7c478bd9Sstevel@tonic-gate return; 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate dip = sc_p->sc_pci_p->pci_dip; 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate /* 146*7c478bd9Sstevel@tonic-gate * Invalidate all streaming cache entries via the diagnostic 147*7c478bd9Sstevel@tonic-gate * access registers. 148*7c478bd9Sstevel@tonic-gate */ 149*7c478bd9Sstevel@tonic-gate DEBUG0(DBG_ATTACH, dip, "sc_configure:\n"); 150*7c478bd9Sstevel@tonic-gate *sc_p->sc_ctrl_reg |= COMMON_SC_CTRL_DIAG_ENABLE; 151*7c478bd9Sstevel@tonic-gate for (i = 0; i < PCI_SBUF_ENTRIES; i++) { 152*7c478bd9Sstevel@tonic-gate sc_p->sc_tag_diag_acc[i] = 0x0ull; 153*7c478bd9Sstevel@tonic-gate sc_p->sc_ltag_diag_acc[i] = 0x0ull; 154*7c478bd9Sstevel@tonic-gate } 155*7c478bd9Sstevel@tonic-gate 156*7c478bd9Sstevel@tonic-gate /* 157*7c478bd9Sstevel@tonic-gate * Configure the streaming cache: 158*7c478bd9Sstevel@tonic-gate */ 159*7c478bd9Sstevel@tonic-gate l = 0; 160*7c478bd9Sstevel@tonic-gate instance = ddi_get_instance(dip); 161*7c478bd9Sstevel@tonic-gate if (pci_stream_buf_enable & (1 << instance)) 162*7c478bd9Sstevel@tonic-gate l |= COMMON_SC_CTRL_ENABLE; 163*7c478bd9Sstevel@tonic-gate if (pci_rerun_disable & (1 << instance)) 164*7c478bd9Sstevel@tonic-gate l |= COMMON_SC_CTRL_RR__DISABLE; 165*7c478bd9Sstevel@tonic-gate if (pci_lock_sbuf & (1 << instance)) 166*7c478bd9Sstevel@tonic-gate l |= COMMON_SC_CTRL_LRU_LE; 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate /* 169*7c478bd9Sstevel@tonic-gate * Get any SC configuration changes specific to the chip. 170*7c478bd9Sstevel@tonic-gate */ 171*7c478bd9Sstevel@tonic-gate l |= pci_sc_configure(sc_p->sc_pci_p); 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate DEBUG1(DBG_ATTACH, dip, 174*7c478bd9Sstevel@tonic-gate "sc_configure: writing %x to sc csr\n", l); 175*7c478bd9Sstevel@tonic-gate *sc_p->sc_ctrl_reg = l; 176*7c478bd9Sstevel@tonic-gate } 177