1 /* $NetBSD: tsp_dma.c,v 1.22 2021/07/19 01:06:14 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 1997, 1998, 2021 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /*- 34 * Copyright (c) 1999 by Ross Harvey. All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. All advertising materials mentioning features or use of this software 45 * must display the following acknowledgement: 46 * This product includes software developed by Ross Harvey. 47 * 4. The name of Ross Harvey may not be used to endorse or promote products 48 * derived from this software without specific prior written permission. 49 * 50 * THIS SOFTWARE IS PROVIDED BY ROSS HARVEY ``AS IS'' AND ANY EXPRESS 51 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 52 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURP0SE 53 * ARE DISCLAIMED. IN NO EVENT SHALL ROSS HARVEY BE LIABLE FOR ANY 54 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 56 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 57 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 58 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 59 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 60 * SUCH DAMAGE. 61 */ 62 63 #include <sys/cdefs.h> 64 __KERNEL_RCSID(0, "$NetBSD: tsp_dma.c,v 1.22 2021/07/19 01:06:14 thorpej Exp $"); 65 66 #include <sys/param.h> 67 #include <sys/systm.h> 68 #include <sys/kernel.h> 69 #include <sys/device.h> 70 71 #include <uvm/uvm_extern.h> 72 73 #include <machine/autoconf.h> 74 #define _ALPHA_BUS_DMA_PRIVATE 75 #include <sys/bus.h> 76 #include <machine/rpb.h> 77 78 #include <dev/pci/pcireg.h> 79 #include <dev/pci/pcivar.h> 80 #include <alpha/pci/tsreg.h> 81 #include <alpha/pci/tsvar.h> 82 83 #define tsp_dma() { Generate ctags(1) key. } 84 85 static bus_dma_tag_t tsp_dma_get_tag(bus_dma_tag_t, alpha_bus_t); 86 87 static int tsp_bus_dmamap_load_sgmap(bus_dma_tag_t, bus_dmamap_t, void *, 88 bus_size_t, struct proc *, int); 89 90 static int tsp_bus_dmamap_load_mbuf_sgmap(bus_dma_tag_t, bus_dmamap_t, 91 struct mbuf *, int); 92 93 static int tsp_bus_dmamap_load_uio_sgmap(bus_dma_tag_t, bus_dmamap_t, 94 struct uio *, int); 95 96 static int tsp_bus_dmamap_load_raw_sgmap(bus_dma_tag_t, bus_dmamap_t, 97 bus_dma_segment_t *, int, bus_size_t, int); 98 99 static void tsp_bus_dmamap_unload_sgmap(bus_dma_tag_t, bus_dmamap_t); 100 101 static void tsp_tlb_invalidate(struct tsp_config *); 102 103 /* 104 * XXX Need to figure out what this is, if any. Initialize it to 105 * XXX something that should be safe. 106 */ 107 #define TSP_SGMAP_PFTHRESH 256 108 109 /* 110 * Quoting the 21272 programmer's reference manual: 111 * 112 * <quote> 113 * 10.1.4.4 Monster Window DMA Address Translation 114 * 115 * In case of a PCI dual-address cycle command, the high-order PCI address 116 * bits <63:40> are compared to the constant value 0x0000_01 (that is, bit 117 * <40> = 1; all other bits = 0). If these bits match, a monster window hit 118 * has occurred and the low-order PCI address bits <34:0> are used unchanged 119 * as the system address bits <34:0>. PCI address bits <39:35> are ignored. 120 * The high-order 32 PCI address bits are available on b_ad<31:0> in the 121 * second cycle of a DAC, and also on b_ad<63:32> in the first cycle of a 122 * DAC if b_req64_l is asserted. 123 * </quote> 124 * 125 * This means that we can address up to 32GB of RAM using a direct-mapped 126 * 64-bit DMA tag. This leaves us possibly having to fall back on SGMAP 127 * DMA on a Titan system (those support up to 64GB of RAM), and we may have 128 * to address that with an additional large SGMAP DAC window at another 129 * time. XXX Does the Titan Monster Window support the extra bit? 130 */ 131 #define TSP_MONSTER_DMA_WINDOW_BASE 0x100##00000000UL 132 #define TSP_MONSTER_DMA_WINDOW_SIZE 0x008##00000000UL 133 134 /* 135 * Basic 24-bit ISA DMA window is 8MB @ 8MB. The firmware will 136 * have set this up in Window 0. 137 */ 138 #define TSP_SGMAP_MAPPED_LO_BASE (8UL * 1024 * 1024) 139 #define TSP_SGMAP_MAPPED_LO_SIZE (8UL * 1024 * 1024) 140 141 /* 142 * Basic 32-bit PCI DMA window is 1GB @ 2GB. The firmware will 143 * have set this up in Window 1. 144 */ 145 #define TSP_DIRECT_MAPPED_BASE (2UL * 1024 * 1024 * 1024) 146 #define TSP_DIRECT_MAPPED_SIZE (1UL * 1024 * 1024 * 1024) 147 148 /* 149 * For systems that have > 1GB of RAM, but PCI devices that don't 150 * support dual-address cycle, we will also set up an additional 151 * SGMAP DMA window 1GB @ 3GB. We will use Window 2 for this purpose. 152 */ 153 #define TSP_SGMAP_MAPPED_HI_BASE (3UL * 1024 * 1024 * 1024) 154 #define TSP_SGMAP_MAPPED_HI_SIZE (1UL * 1024 * 1024 * 1024) 155 156 /* 157 * Window 3 is still available for use in the future. Window 3 supports 158 * dual address cycle. 159 */ 160 161 static void 162 tsp_dma_shutdown(void *arg) 163 { 164 struct tsp_config *pcp = arg; 165 struct ts_pchip *pccsr = pcp->pc_csr; 166 int i; 167 168 /* 169 * Restore the initial values, to make the firmware happy. 170 */ 171 for (i = 0; i < 4; i++) { 172 pccsr->tsp_wsba[i].tsg_r = pcp->pc_saved_windows.wsba[i]; 173 pccsr->tsp_wsm[i].tsg_r = pcp->pc_saved_windows.wsm[i]; 174 pccsr->tsp_tba[i].tsg_r = pcp->pc_saved_windows.tba[i]; 175 alpha_mb(); 176 } 177 pccsr->tsp_pctl.tsg_r = pcp->pc_saved_pctl; 178 alpha_mb(); 179 } 180 181 void 182 tsp_dma_init(struct tsp_config *pcp) 183 { 184 bus_dma_tag_t t; 185 bus_dma_tag_t t_sg_hi = NULL; 186 struct ts_pchip *pccsr = pcp->pc_csr; 187 bus_addr_t tbase; 188 int i; 189 190 /* 191 * Save our configuration to restore at shutdown, just 192 * in case the firmware would get cranky with us. 193 */ 194 for (i = 0; i < 4; i++) { 195 pcp->pc_saved_windows.wsba[i] = pccsr->tsp_wsba[i].tsg_r; 196 pcp->pc_saved_windows.wsm[i] = pccsr->tsp_wsm[i].tsg_r; 197 pcp->pc_saved_windows.tba[i] = pccsr->tsp_tba[i].tsg_r; 198 } 199 pcp->pc_saved_pctl = pccsr->tsp_pctl.tsg_r; 200 shutdownhook_establish(tsp_dma_shutdown, pcp); 201 202 /* Ensure the Monster Window is enabled. */ 203 alpha_mb(); 204 pccsr->tsp_pctl.tsg_r |= PCTL_MWIN; 205 alpha_mb(); 206 207 /* 208 * If we have more than 1GB of RAM, then set up an sgmap-mapped 209 * DMA window for non-DAC PCI. This is better than using the ISA 210 * window, which is pretty small and PCI devices could starve it. 211 * 212 * N.B. avail_end is "last-usable PFN + 1". 213 */ 214 if (uvm_physseg_get_avail_end(uvm_physseg_get_last()) > 215 atop(TSP_DIRECT_MAPPED_SIZE)) { 216 t = t_sg_hi = &pcp->pc_dmat_sgmap_hi; 217 t->_cookie = pcp; 218 t->_wbase = TSP_SGMAP_MAPPED_HI_BASE; 219 t->_wsize = TSP_SGMAP_MAPPED_HI_SIZE; 220 t->_next_window = NULL; 221 t->_boundary = 0; 222 t->_sgmap = &pcp->pc_sgmap_hi; 223 /* 224 * According to section 8.1.2.2 of the Tsunami/Typhoon 225 * hardware reference manual (DS-0025A-TE), the SGMAP 226 * TLB is arranged as 168 locations of 4 consecutive 227 * quadwords. It seems that on some revisions of the 228 * Pchip, SGMAP translation is not perfectly reliable 229 * unless we align the DMA segments to the TLBs natural 230 * boundaries (observed on the API CS20). 231 * 232 * N.B. the Titan (as observed on a Compaq DS25) does not 233 * seem to have this problem, but we'll play it safe and 234 * run this way on both variants. 235 */ 236 t->_sgmap_minalign = PAGE_SIZE * 4; 237 t->_pfthresh = TSP_SGMAP_PFTHRESH; 238 t->_get_tag = tsp_dma_get_tag; 239 t->_dmamap_create = alpha_sgmap_dmamap_create; 240 t->_dmamap_destroy = alpha_sgmap_dmamap_destroy; 241 t->_dmamap_load = tsp_bus_dmamap_load_sgmap; 242 t->_dmamap_load_mbuf = tsp_bus_dmamap_load_mbuf_sgmap; 243 t->_dmamap_load_uio = tsp_bus_dmamap_load_uio_sgmap; 244 t->_dmamap_load_raw = tsp_bus_dmamap_load_raw_sgmap; 245 t->_dmamap_unload = tsp_bus_dmamap_unload_sgmap; 246 t->_dmamap_sync = _bus_dmamap_sync; 247 248 t->_dmamem_alloc = _bus_dmamem_alloc; 249 t->_dmamem_free = _bus_dmamem_free; 250 t->_dmamem_map = _bus_dmamem_map; 251 t->_dmamem_unmap = _bus_dmamem_unmap; 252 t->_dmamem_mmap = _bus_dmamem_mmap; 253 } 254 255 /* 256 * Initialize the DMA tag used for direct-mapped 64-bit DMA. 257 */ 258 t = &pcp->pc_dmat64_direct; 259 t->_cookie = pcp; 260 t->_wbase = TSP_MONSTER_DMA_WINDOW_BASE; 261 t->_wsize = TSP_MONSTER_DMA_WINDOW_SIZE; 262 t->_next_window = t_sg_hi; 263 t->_boundary = 0; 264 t->_sgmap = NULL; 265 t->_get_tag = tsp_dma_get_tag; 266 t->_dmamap_create = _bus_dmamap_create; 267 t->_dmamap_destroy = _bus_dmamap_destroy; 268 t->_dmamap_load = _bus_dmamap_load_direct; 269 t->_dmamap_load_mbuf = _bus_dmamap_load_mbuf_direct; 270 t->_dmamap_load_uio = _bus_dmamap_load_uio_direct; 271 t->_dmamap_load_raw = _bus_dmamap_load_raw_direct; 272 t->_dmamap_unload = _bus_dmamap_unload; 273 t->_dmamap_sync = _bus_dmamap_sync; 274 275 t->_dmamem_alloc = _bus_dmamem_alloc; 276 t->_dmamem_free = _bus_dmamem_free; 277 t->_dmamem_map = _bus_dmamem_map; 278 t->_dmamem_unmap = _bus_dmamem_unmap; 279 t->_dmamem_mmap = _bus_dmamem_mmap; 280 281 /* 282 * Initialize the DMA tag used for direct-mapped DMA. 283 */ 284 t = &pcp->pc_dmat_direct; 285 t->_cookie = pcp; 286 t->_wbase = TSP_DIRECT_MAPPED_BASE; 287 t->_wsize = TSP_DIRECT_MAPPED_SIZE; 288 t->_next_window = t_sg_hi; 289 t->_boundary = 0; 290 t->_sgmap = NULL; 291 t->_get_tag = tsp_dma_get_tag; 292 t->_dmamap_create = _bus_dmamap_create; 293 t->_dmamap_destroy = _bus_dmamap_destroy; 294 t->_dmamap_load = _bus_dmamap_load_direct; 295 t->_dmamap_load_mbuf = _bus_dmamap_load_mbuf_direct; 296 t->_dmamap_load_uio = _bus_dmamap_load_uio_direct; 297 t->_dmamap_load_raw = _bus_dmamap_load_raw_direct; 298 t->_dmamap_unload = _bus_dmamap_unload; 299 t->_dmamap_sync = _bus_dmamap_sync; 300 301 t->_dmamem_alloc = _bus_dmamem_alloc; 302 t->_dmamem_free = _bus_dmamem_free; 303 t->_dmamem_map = _bus_dmamem_map; 304 t->_dmamem_unmap = _bus_dmamem_unmap; 305 t->_dmamem_mmap = _bus_dmamem_mmap; 306 307 /* 308 * Initialize the DMA tag used for ISA sgmap-mapped DMA. 309 */ 310 t = &pcp->pc_dmat_sgmap_lo; 311 t->_cookie = pcp; 312 t->_wbase = TSP_SGMAP_MAPPED_LO_BASE; 313 t->_wsize = TSP_SGMAP_MAPPED_LO_SIZE; 314 t->_next_window = NULL; 315 t->_boundary = 0; 316 t->_sgmap = &pcp->pc_sgmap_lo; 317 /* 318 * This appears to be needed to make DMA on the ALI southbridge 319 * that's present in some systems happy. ??? 320 */ 321 t->_sgmap_minalign = (64UL * 1024); 322 t->_pfthresh = TSP_SGMAP_PFTHRESH; 323 t->_get_tag = tsp_dma_get_tag; 324 t->_dmamap_create = alpha_sgmap_dmamap_create; 325 t->_dmamap_destroy = alpha_sgmap_dmamap_destroy; 326 t->_dmamap_load = tsp_bus_dmamap_load_sgmap; 327 t->_dmamap_load_mbuf = tsp_bus_dmamap_load_mbuf_sgmap; 328 t->_dmamap_load_uio = tsp_bus_dmamap_load_uio_sgmap; 329 t->_dmamap_load_raw = tsp_bus_dmamap_load_raw_sgmap; 330 t->_dmamap_unload = tsp_bus_dmamap_unload_sgmap; 331 t->_dmamap_sync = _bus_dmamap_sync; 332 333 t->_dmamem_alloc = _bus_dmamem_alloc; 334 t->_dmamem_free = _bus_dmamem_free; 335 t->_dmamem_map = _bus_dmamem_map; 336 t->_dmamem_unmap = _bus_dmamem_unmap; 337 t->_dmamem_mmap = _bus_dmamem_mmap; 338 339 /* 340 * Initialize the SGMAPs. Align page tables to 32k in case 341 * window is somewhat larger than expected. 342 */ 343 alpha_sgmap_init(t, &pcp->pc_sgmap_lo, "tsp_sgmap_lo", 344 TSP_SGMAP_MAPPED_LO_BASE, 0, TSP_SGMAP_MAPPED_LO_SIZE, 345 sizeof(uint64_t), NULL, (32*1024)); 346 if (t_sg_hi != NULL) { 347 alpha_sgmap_init(t_sg_hi, &pcp->pc_sgmap_hi, "tsp_sgmap_hi", 348 TSP_SGMAP_MAPPED_HI_BASE, 0, TSP_SGMAP_MAPPED_HI_SIZE, 349 sizeof(uint64_t), NULL, (32*1024)); 350 } 351 352 /* 353 * Enable window 0 and enable SG PTE mapping. 354 */ 355 alpha_mb(); 356 pccsr->tsp_wsba[0].tsg_r = 357 TSP_SGMAP_MAPPED_LO_BASE | WSBA_SG | WSBA_ENA; 358 alpha_mb(); 359 pccsr->tsp_wsm[0].tsg_r = WSM_8MB; 360 alpha_mb(); 361 tbase = pcp->pc_sgmap_lo.aps_ptpa; 362 if (tbase & ~0x7fffffc00UL) 363 panic("tsp_dma_init: bad page table address"); 364 pccsr->tsp_tba[0].tsg_r = tbase; 365 alpha_mb(); 366 367 /* 368 * Enable window 1 in direct mode. 369 */ 370 alpha_mb(); 371 pccsr->tsp_wsba[1].tsg_r = TSP_DIRECT_MAPPED_BASE | WSBA_ENA; 372 alpha_mb(); 373 pccsr->tsp_wsm[1].tsg_r = WSM_1GB; 374 alpha_mb(); 375 pccsr->tsp_tba[1].tsg_r = 0; 376 alpha_mb(); 377 378 if (t_sg_hi != NULL) { 379 /* 380 * Enable window 2 and enable SG PTE mapping. 381 */ 382 alpha_mb(); 383 pccsr->tsp_wsba[2].tsg_r = 384 TSP_SGMAP_MAPPED_HI_BASE | WSBA_SG | WSBA_ENA; 385 alpha_mb(); 386 pccsr->tsp_wsm[2].tsg_r = WSM_1GB; 387 alpha_mb(); 388 tbase = pcp->pc_sgmap_hi.aps_ptpa; 389 if (tbase & ~0x7fffffc00UL) 390 panic("tsp_dma_init: bad page table address"); 391 pccsr->tsp_tba[2].tsg_r = tbase; 392 alpha_mb(); 393 } 394 395 /* 396 * Disable window 3. 397 */ 398 alpha_mb(); 399 pccsr->tsp_wsba[3].tsg_r = 0; 400 alpha_mb(); 401 pccsr->tsp_wsm[3].tsg_r = 0; 402 alpha_mb(); 403 pccsr->tsp_tba[3].tsg_r = 0; 404 alpha_mb(); 405 406 tsp_tlb_invalidate(pcp); 407 alpha_mb(); 408 } 409 410 /* 411 * Return the bus dma tag to be used for the specified bus type. 412 * INTERNAL USE ONLY! 413 */ 414 static bus_dma_tag_t 415 tsp_dma_get_tag(bus_dma_tag_t t, alpha_bus_t bustype) 416 { 417 struct tsp_config *pcp = t->_cookie; 418 419 switch (bustype) { 420 case ALPHA_BUS_PCI: 421 case ALPHA_BUS_EISA: 422 /* 423 * The direct mapped window will work for most systems, 424 * most of the time. When it doesn't, we chain to the sgmap 425 * window automatically. 426 */ 427 return (&pcp->pc_dmat_direct); 428 429 case ALPHA_BUS_ISA: 430 /* 431 * ISA doesn't have enough address bits to use 432 * the direct-mapped DMA window, so we must use 433 * SGMAPs. 434 */ 435 return (&pcp->pc_dmat_sgmap_lo); 436 437 default: 438 panic("tsp_dma_get_tag: shouldn't be here, really..."); 439 } 440 } 441 442 /* 443 * Load a TSP SGMAP-mapped DMA map with a linear buffer. 444 */ 445 static int 446 tsp_bus_dmamap_load_sgmap(bus_dma_tag_t t, bus_dmamap_t map, void *buf, bus_size_t buflen, struct proc *p, int flags) 447 { 448 int error; 449 450 error = pci_sgmap_pte64_load(t, map, buf, buflen, p, flags, 451 t->_sgmap); 452 if (error == 0) 453 tsp_tlb_invalidate(t->_cookie); 454 455 return (error); 456 } 457 458 /* 459 * Load a TSP SGMAP-mapped DMA map with an mbuf chain. 460 */ 461 static int 462 tsp_bus_dmamap_load_mbuf_sgmap(bus_dma_tag_t t, bus_dmamap_t map, struct mbuf *m, int flags) 463 { 464 int error; 465 466 error = pci_sgmap_pte64_load_mbuf(t, map, m, flags, t->_sgmap); 467 if (error == 0) 468 tsp_tlb_invalidate(t->_cookie); 469 470 return (error); 471 } 472 473 /* 474 * Load a TSP SGMAP-mapped DMA map with a uio. 475 */ 476 static int 477 tsp_bus_dmamap_load_uio_sgmap(bus_dma_tag_t t, bus_dmamap_t map, struct uio *uio, int flags) 478 { 479 int error; 480 481 error = pci_sgmap_pte64_load_uio(t, map, uio, flags, t->_sgmap); 482 if (error == 0) 483 tsp_tlb_invalidate(t->_cookie); 484 485 return (error); 486 } 487 488 /* 489 * Load a TSP SGMAP-mapped DMA map with raw memory. 490 */ 491 static int 492 tsp_bus_dmamap_load_raw_sgmap(bus_dma_tag_t t, bus_dmamap_t map, bus_dma_segment_t *segs, int nsegs, bus_size_t size, int flags) 493 { 494 int error; 495 496 error = pci_sgmap_pte64_load_raw(t, map, segs, nsegs, size, flags, 497 t->_sgmap); 498 if (error == 0) 499 tsp_tlb_invalidate(t->_cookie); 500 501 return (error); 502 } 503 504 /* 505 * Unload a TSP DMA map. 506 */ 507 static void 508 tsp_bus_dmamap_unload_sgmap(bus_dma_tag_t t, bus_dmamap_t map) 509 { 510 511 /* 512 * Invalidate any SGMAP page table entries used by this 513 * mapping. 514 */ 515 pci_sgmap_pte64_unload(t, map, t->_sgmap); 516 tsp_tlb_invalidate(t->_cookie); 517 518 /* 519 * Do the generic bits of the unload. 520 */ 521 _bus_dmamap_unload_common(t, map); 522 } 523 524 /* 525 * Flush the TSP scatter/gather TLB. 526 */ 527 static void 528 tsp_tlb_invalidate(struct tsp_config *pcp) 529 { 530 531 alpha_mb(); 532 *pcp->pc_tlbia = 0; 533 alpha_mb(); 534 } 535