Print this page
5045 use atomic_{inc,dec}_* instead of atomic_add_*
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/sun4u/sunfire/io/ac_test.c
+++ new/usr/src/uts/sun4u/sunfire/io/ac_test.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 -#pragma ident "%Z%%M% %I% %E% SMI"
28 -
29 27 #include <sys/types.h>
30 28 #include <sys/conf.h>
31 29 #include <sys/ddi.h>
32 30 #include <sys/sunddi.h>
33 31 #include <sys/ddi_impldefs.h>
34 32 #include <sys/obpdefs.h>
35 33 #include <sys/cmn_err.h>
36 34 #include <sys/errno.h>
37 35 #include <sys/kmem.h>
38 36 #include <sys/vmem.h>
39 37 #include <sys/debug.h>
40 38 #include <sys/sysmacros.h>
41 39 #include <sys/machsystm.h>
42 40 #include <sys/machparam.h>
43 41 #include <sys/modctl.h>
44 42 #include <sys/atomic.h>
45 43 #include <sys/fhc.h>
46 44 #include <sys/ac.h>
47 45 #include <sys/jtag.h>
48 46 #include <sys/cpu_module.h>
49 47 #include <sys/spitregs.h>
50 48 #include <sys/vm.h>
51 49 #include <vm/seg_kmem.h>
52 50 #include <vm/hat_sfmmu.h>
53 51
54 52 /* memory setup parameters */
55 53 #define TEST_PAGESIZE MMU_PAGESIZE
56 54
57 55 struct test_info {
58 56 struct test_info *next; /* linked list of tests */
59 57 struct ac_mem_info *mem_info;
60 58 uint_t board;
61 59 uint_t bank;
62 60 caddr_t bufp; /* pointer to buffer page */
63 61 caddr_t va; /* test target VA */
64 62 ac_mem_test_start_t info;
65 63 uint_t in_test; /* count of threads in test */
66 64 };
67 65
68 66 /* list of tests in progress (list protected test_mutex) */
69 67 static struct test_info *test_base = NULL;
70 68 static kmutex_t test_mutex;
71 69 static int test_mutex_initialized = FALSE;
72 70
73 71 static mem_test_handle_t mem_test_sequence_id = 0;
74 72
75 73 void
76 74 ac_mapin(uint64_t pa, caddr_t va)
77 75 {
78 76 pfn_t pfn;
79 77 tte_t tte;
80 78
81 79 pfn = pa >> MMU_PAGESHIFT;
82 80 tte.tte_inthi = TTE_VALID_INT | TTE_SZ_INT(TTE8K) |
83 81 TTE_PFN_INTHI(pfn);
84 82 tte.tte_intlo = TTE_PFN_INTLO(pfn) | TTE_CP_INT |
85 83 TTE_PRIV_INT | TTE_LCK_INT | TTE_HWWR_INT;
86 84 sfmmu_dtlb_ld_kva(va, &tte);
87 85
88 86 }
89 87
90 88 void
91 89 ac_unmap(caddr_t va)
92 90 {
93 91 vtag_flushpage(va, (uint64_t)ksfmmup);
94 92 }
95 93
96 94 int
97 95 ac_mem_test_start(ac_cfga_pkt_t *pkt, int flag)
98 96 {
99 97 struct ac_soft_state *softsp;
100 98 struct ac_mem_info *mem_info;
101 99 struct bd_list *board;
102 100 struct test_info *test;
103 101 uint64_t decode;
104 102
105 103 /* XXX if ac ever detaches... */
106 104 if (test_mutex_initialized == FALSE) {
107 105 mutex_init(&test_mutex, NULL, MUTEX_DEFAULT, NULL);
108 106 test_mutex_initialized = TRUE;
109 107 }
110 108
111 109 /*
112 110 * Is the specified bank testable?
113 111 */
114 112
115 113 board = fhc_bdlist_lock(pkt->softsp->board);
116 114 if (board == NULL || board->ac_softsp == NULL) {
117 115 fhc_bdlist_unlock();
118 116 AC_ERR_SET(pkt, AC_ERR_BD);
119 117 return (EINVAL);
120 118 }
121 119 ASSERT(pkt->softsp == board->ac_softsp);
122 120
123 121 /* verify the board is of the correct type */
124 122 switch (board->sc.type) {
125 123 case CPU_BOARD:
126 124 case MEM_BOARD:
127 125 break;
128 126 default:
129 127 fhc_bdlist_unlock();
130 128 AC_ERR_SET(pkt, AC_ERR_BD_TYPE);
131 129 return (EINVAL);
132 130 }
133 131
134 132 /*
135 133 * Memory must be in the spare state to be testable.
136 134 * However, spare memory that is testing can't be tested
137 135 * again, instead return the current test info.
138 136 */
139 137 softsp = pkt->softsp;
140 138 mem_info = &softsp->bank[pkt->bank];
141 139 if (!MEM_BOARD_VISIBLE(board) ||
142 140 fhc_bd_busy(softsp->board) ||
143 141 mem_info->rstate != SYSC_CFGA_RSTATE_CONNECTED ||
144 142 mem_info->ostate != SYSC_CFGA_OSTATE_UNCONFIGURED) {
145 143 fhc_bdlist_unlock();
146 144 AC_ERR_SET(pkt, AC_ERR_BD_STATE);
147 145 return (EINVAL);
148 146 }
149 147 if (mem_info->busy) { /* oops, testing? */
150 148 /*
151 149 * find the test entry
152 150 */
153 151 ASSERT(test_mutex_initialized);
154 152 mutex_enter(&test_mutex);
155 153 for (test = test_base; test != NULL; test = test->next) {
156 154 if (test->board == softsp->board &&
157 155 test->bank == pkt->bank)
158 156 break;
159 157 }
160 158 if (test == NULL) {
161 159 mutex_exit(&test_mutex);
162 160 fhc_bdlist_unlock();
163 161 /* Not busy testing. */
164 162 AC_ERR_SET(pkt, AC_ERR_BD_STATE);
165 163 return (EINVAL);
166 164 }
167 165
168 166 /*
169 167 * return the current test information to the new caller
170 168 */
171 169 if (ddi_copyout(&test->info, pkt->cmd_cfga.private,
172 170 sizeof (ac_mem_test_start_t), flag) != 0) {
173 171 mutex_exit(&test_mutex);
174 172 fhc_bdlist_unlock();
175 173 return (EFAULT); /* !broken user app */
176 174 }
177 175 mutex_exit(&test_mutex);
178 176 fhc_bdlist_unlock();
179 177 AC_ERR_SET(pkt, AC_ERR_MEM_BK);
180 178 return (EBUSY); /* signal bank in use */
181 179 }
182 180
183 181 /*
184 182 * at this point, we have an available bank to test.
↓ open down ↓ |
146 lines elided |
↑ open up ↑ |
185 183 * create a test buffer
186 184 */
187 185 test = kmem_zalloc(sizeof (struct test_info), KM_SLEEP);
188 186 test->va = vmem_alloc(heap_arena, PAGESIZE, VM_SLEEP);
189 187
190 188 /* fill in all the test info details now */
191 189 test->mem_info = mem_info;
192 190 test->board = softsp->board;
193 191 test->bank = pkt->bank;
194 192 test->bufp = kmem_alloc(TEST_PAGESIZE, KM_SLEEP);
195 - test->info.handle = atomic_add_32_nv(&mem_test_sequence_id, 1);
193 + test->info.handle = atomic_inc_32_nv(&mem_test_sequence_id);
196 194 (void) drv_getparm(PPID, (ulong_t *)(&(test->info.tester_pid)));
197 195 test->info.prev_condition = mem_info->condition;
198 196 test->info.page_size = TEST_PAGESIZE;
199 197 /* If Blackbird ever gets a variable line size, this will change. */
200 198 test->info.line_size = cpunodes[CPU->cpu_id].ecache_linesize;
201 199 decode = (pkt->bank == Bank0) ?
202 200 *softsp->ac_memdecode0 : *softsp->ac_memdecode1;
203 201 test->info.afar_base = GRP_REALBASE(decode);
204 202 test->info.bank_size = GRP_UK2SPAN(decode);
205 203
206 204 /* return the information to the user */
207 205 if (ddi_copyout(&test->info, pkt->cmd_cfga.private,
208 206 sizeof (ac_mem_test_start_t), flag) != 0) {
209 207
210 208 /* oh well, tear down the test now */
211 209 kmem_free(test->bufp, TEST_PAGESIZE);
212 210 vmem_free(heap_arena, test->va, PAGESIZE);
213 211 kmem_free(test, sizeof (struct test_info));
214 212
215 213 fhc_bdlist_unlock();
216 214 return (EFAULT);
217 215 }
218 216
219 217 mem_info->busy = TRUE;
220 218
221 219 /* finally link us into the test database */
222 220 mutex_enter(&test_mutex);
223 221 test->next = test_base;
224 222 test_base = test;
225 223 mutex_exit(&test_mutex);
226 224
227 225 fhc_bdlist_unlock();
228 226
229 227 #ifdef DEBUG
230 228 cmn_err(CE_NOTE, "!memtest: start test[%u]: board %d, bank %d",
231 229 test->info.handle, test->board, test->bank);
232 230 #endif /* DEBUG */
233 231 return (DDI_SUCCESS);
234 232 }
235 233
236 234 int
237 235 ac_mem_test_stop(ac_cfga_pkt_t *pkt, int flag)
238 236 {
239 237 struct test_info *test, **prev;
240 238 ac_mem_test_stop_t stop;
241 239
242 240 /* get test result information */
243 241 if (ddi_copyin(pkt->cmd_cfga.private, &stop,
244 242 sizeof (ac_mem_test_stop_t), flag) != 0)
245 243 return (EFAULT);
246 244
247 245 /* bdlist protects all state changes... */
248 246 (void) fhc_bdlist_lock(-1);
249 247
250 248 /* find the test */
251 249 mutex_enter(&test_mutex);
252 250 prev = &test_base;
253 251 for (test = test_base; test != NULL; test = test->next) {
254 252 if (test->info.handle == stop.handle)
255 253 break; /* found the test */
256 254 prev = &test->next;
257 255 }
258 256 if (test == NULL) {
259 257 mutex_exit(&test_mutex);
260 258 fhc_bdlist_unlock();
261 259 AC_ERR_SET(pkt, AC_ERR_MEM_TEST);
262 260 return (EINVAL);
263 261 }
264 262
265 263 #ifdef DEBUG
266 264 cmn_err(CE_NOTE,
267 265 "!memtest: stop test[%u]: board %d, bank %d,"
268 266 " condition %d",
269 267 test->info.handle, test->board,
270 268 test->bank, stop.condition);
271 269 #endif /* DEBUG */
272 270
273 271 /* first unlink us from the test list (to allow no more entries) */
274 272 *prev = test->next;
275 273
276 274 /* then, wait for current tests to complete */
277 275 while (test->in_test != 0)
278 276 delay(1);
279 277
280 278 mutex_exit(&test_mutex);
281 279
282 280 /* clean up the test related allocations */
283 281 vmem_free(heap_arena, test->va, PAGESIZE);
284 282 kmem_free(test->bufp, TEST_PAGESIZE);
285 283
286 284 /* update the bank condition accordingly */
287 285 test->mem_info->condition = stop.condition;
288 286 test->mem_info->status_change = ddi_get_time();
289 287
290 288 test->mem_info->busy = FALSE;
291 289
292 290 /* finally, delete the test element */
293 291 kmem_free(test, sizeof (struct test_info));
294 292
295 293 fhc_bdlist_unlock();
296 294
297 295 return (DDI_SUCCESS);
298 296 }
299 297
300 298 void
301 299 ac_mem_test_stop_on_close(uint_t board, uint_t bank)
302 300 {
303 301 struct test_info *test, **prev;
304 302 sysc_cfga_cond_t condition = SYSC_CFGA_COND_UNKNOWN;
305 303
306 304 /* bdlist protects all state changes... */
307 305 (void) fhc_bdlist_lock(-1);
308 306
309 307 /* find the test */
310 308 mutex_enter(&test_mutex);
311 309 prev = &test_base;
312 310 for (test = test_base; test != NULL; test = test->next) {
313 311 if (test->board == board && test->bank == bank)
314 312 break; /* found the test */
315 313 prev = &test->next;
316 314 }
317 315 if (test == NULL) {
318 316 /* No test running, nothing to do. */
319 317 mutex_exit(&test_mutex);
320 318 fhc_bdlist_unlock();
321 319 return;
322 320 }
323 321
324 322 #ifdef DEBUG
325 323 cmn_err(CE_NOTE, "!memtest: stop test[%u] on close: "
326 324 "board %d, bank %d, condition %d", test->info.handle,
327 325 test->board, test->bank, condition);
328 326 #endif /* DEBUG */
329 327
330 328 /* first unlink us from the test list (to allow no more entries) */
331 329 *prev = test->next;
332 330
333 331 ASSERT(test->in_test == 0);
334 332
335 333 mutex_exit(&test_mutex);
336 334
337 335 /* clean up the test related allocations */
338 336 vmem_free(heap_arena, test->va, PAGESIZE);
339 337 kmem_free(test->bufp, TEST_PAGESIZE);
340 338
341 339 /* update the bank condition accordingly */
342 340 test->mem_info->condition = condition;
343 341 test->mem_info->status_change = ddi_get_time();
344 342
345 343 test->mem_info->busy = FALSE;
346 344
347 345 /* finally, delete the test element */
348 346 kmem_free(test, sizeof (struct test_info));
349 347
350 348 fhc_bdlist_unlock();
351 349 }
352 350
353 351 int
354 352 ac_mem_test_read(ac_cfga_pkt_t *pkt, int flag)
355 353 {
356 354 struct test_info *test;
357 355 uint_t page_offset;
358 356 uint64_t page_pa;
359 357 uint_t pstate_save;
360 358 caddr_t src_va, dst_va;
361 359 uint64_t orig_err;
362 360 int retval = DDI_SUCCESS;
363 361 sunfire_processor_error_regs_t error_buf;
364 362 int error_found;
365 363 ac_mem_test_read_t t_read;
366 364
367 365 #ifdef _MULTI_DATAMODEL
368 366 switch (ddi_model_convert_from(flag & FMODELS)) {
369 367 case DDI_MODEL_ILP32: {
370 368 ac_mem_test_read32_t t_read32;
371 369
372 370 if (ddi_copyin(pkt->cmd_cfga.private, &t_read32,
373 371 sizeof (ac_mem_test_read32_t), flag) != 0)
374 372 return (EFAULT);
375 373 t_read.handle = t_read32.handle;
376 374 t_read.page_buf = (void *)(uintptr_t)t_read32.page_buf;
377 375 t_read.address = t_read32.address;
378 376 t_read.error_buf = (sunfire_processor_error_regs_t *)
379 377 (uintptr_t)t_read32.error_buf;
380 378 break;
381 379 }
382 380 case DDI_MODEL_NONE:
383 381 if (ddi_copyin(pkt->cmd_cfga.private, &t_read,
384 382 sizeof (ac_mem_test_read_t), flag) != 0)
385 383 return (EFAULT);
386 384 break;
387 385 }
388 386 #else /* _MULTI_DATAMODEL */
389 387 if (ddi_copyin(pkt->cmd_cfga.private, &t_read,
390 388 sizeof (ac_mem_test_read_t), flag) != 0)
391 389 return (EFAULT);
392 390 #endif /* _MULTI_DATAMODEL */
393 391
394 392 /* verify the handle */
395 393 mutex_enter(&test_mutex);
396 394 for (test = test_base; test != NULL; test = test->next) {
↓ open down ↓ |
191 lines elided |
↑ open up ↑ |
397 395 if (test->info.handle == t_read.handle)
398 396 break;
399 397 }
400 398 if (test == NULL) {
401 399 mutex_exit(&test_mutex);
402 400 AC_ERR_SET(pkt, AC_ERR_MEM_TEST);
403 401 return (EINVAL);
404 402 }
405 403
406 404 /* bump the busy bit */
407 - atomic_add_32(&test->in_test, 1);
405 + atomic_inc_32(&test->in_test);
408 406 mutex_exit(&test_mutex);
409 407
410 408 /* verify the remaining parameters */
411 409 if ((t_read.address.page_num >=
412 410 test->info.bank_size / test->info.page_size) ||
413 411 (t_read.address.line_count == 0) ||
414 412 (t_read.address.line_count >
415 413 test->info.page_size / test->info.line_size) ||
416 414 (t_read.address.line_offset >=
417 415 test->info.page_size / test->info.line_size) ||
418 416 ((t_read.address.line_offset + t_read.address.line_count) >
419 417 test->info.page_size / test->info.line_size)) {
420 418 AC_ERR_SET(pkt, AC_ERR_MEM_TEST_PAR);
421 419 retval = EINVAL;
422 420 goto read_done;
423 421 }
424 422
425 423 page_offset = t_read.address.line_offset * test->info.line_size;
426 424 page_pa = test->info.afar_base +
427 425 t_read.address.page_num * test->info.page_size;
428 426 dst_va = test->bufp + page_offset;
429 427 src_va = test->va + page_offset;
430 428
431 429 /* time to go quiet */
432 430 kpreempt_disable();
433 431
434 432 /* we need a va for the block instructions */
435 433 ac_mapin(page_pa, test->va);
436 434
437 435 pstate_save = disable_vec_intr();
438 436
439 437 /* disable errors */
440 438 orig_err = get_error_enable();
441 439 set_error_enable(orig_err & ~(EER_CEEN | EER_NCEEN));
442 440
443 441 /* copy the data again (using our very special copy) */
444 442 ac_blkcopy(src_va, dst_va, t_read.address.line_count,
445 443 test->info.line_size);
446 444
447 445 /* process errors (if any) */
448 446 error_buf.module_id = CPU->cpu_id;
449 447 get_asyncflt(&(error_buf.afsr));
450 448 get_asyncaddr(&(error_buf.afar));
451 449 get_udb_errors(&(error_buf.udbh_error_reg),
452 450 &(error_buf.udbl_error_reg));
453 451
454 452 /*
455 453 * clean up after our no-error copy but before enabling ints.
456 454 * XXX what to do about other error types?
457 455 */
458 456 if (error_buf.afsr & (P_AFSR_CE | P_AFSR_UE)) {
459 457 extern void clr_datapath(void); /* XXX */
460 458
461 459 clr_datapath();
462 460 set_asyncflt(error_buf.afsr);
463 461 retval = EIO;
464 462 error_found = TRUE;
465 463 } else {
466 464 error_found = FALSE;
467 465 }
468 466
469 467 /* errors back on */
470 468 set_error_enable(orig_err);
471 469
472 470 enable_vec_intr(pstate_save);
473 471
474 472 /* tear down translation (who needs an mmu) */
475 473 ac_unmap(test->va);
476 474
477 475 /* we're back! */
478 476 kpreempt_enable();
479 477
480 478 /*
481 479 * If there was a data error, attempt to return the error_buf
482 480 * to the user.
483 481 */
484 482 if (error_found) {
485 483 if (ddi_copyout(&error_buf, t_read.error_buf,
486 484 sizeof (sunfire_processor_error_regs_t), flag) != 0) {
487 485 retval = EFAULT;
488 486 /* Keep going */
489 487 }
490 488 }
↓ open down ↓ |
73 lines elided |
↑ open up ↑ |
491 489
492 490 /*
493 491 * Then, return the page to the user (always)
494 492 */
495 493 if (ddi_copyout(dst_va, (caddr_t)(t_read.page_buf) + page_offset,
496 494 t_read.address.line_count * test->info.line_size, flag) != 0) {
497 495 retval = EFAULT;
498 496 }
499 497
500 498 read_done:
501 - atomic_add_32(&test->in_test, -1);
499 + atomic_dec_32(&test->in_test);
502 500 return (retval);
503 501 }
504 502
505 503 int
506 504 ac_mem_test_write(ac_cfga_pkt_t *pkt, int flag)
507 505 {
508 506 struct test_info *test;
509 507 uint_t page_offset;
510 508 uint64_t page_pa;
511 509 uint_t pstate_save;
512 510 caddr_t src_va, dst_va;
513 511 int retval = DDI_SUCCESS;
514 512 ac_mem_test_write_t t_write;
515 513
516 514 #ifdef _MULTI_DATAMODEL
517 515 switch (ddi_model_convert_from(flag & FMODELS)) {
518 516 case DDI_MODEL_ILP32: {
519 517 ac_mem_test_write32_t t_write32;
520 518
521 519 if (ddi_copyin(pkt->cmd_cfga.private, &t_write32,
522 520 sizeof (ac_mem_test_write32_t), flag) != 0)
523 521 return (EFAULT);
524 522 t_write.handle = t_write32.handle;
525 523 t_write.page_buf = (void *)(uintptr_t)t_write32.page_buf;
526 524 t_write.address = t_write32.address;
527 525 break;
528 526 }
529 527 case DDI_MODEL_NONE:
530 528 if (ddi_copyin(pkt->cmd_cfga.private, &t_write,
531 529 sizeof (ac_mem_test_write_t), flag) != 0)
532 530 return (EFAULT);
533 531 break;
534 532 }
535 533 #else /* _MULTI_DATAMODEL */
536 534 if (ddi_copyin(pkt->cmd_cfga.private, &t_write,
537 535 sizeof (ac_mem_test_write_t), flag) != 0)
538 536 return (EFAULT);
539 537 #endif /* _MULTI_DATAMODEL */
540 538
541 539 /* verify the handle */
542 540 mutex_enter(&test_mutex);
↓ open down ↓ |
31 lines elided |
↑ open up ↑ |
543 541 for (test = test_base; test != NULL; test = test->next) {
544 542 if (test->info.handle == t_write.handle)
545 543 break;
546 544 }
547 545 if (test == NULL) {
548 546 mutex_exit(&test_mutex);
549 547 return (EINVAL);
550 548 }
551 549
552 550 /* bump the busy bit */
553 - atomic_add_32(&test->in_test, 1);
551 + atomic_inc_32(&test->in_test);
554 552 mutex_exit(&test_mutex);
555 553
556 554 /* verify the remaining parameters */
557 555 if ((t_write.address.page_num >=
558 556 test->info.bank_size / test->info.page_size) ||
559 557 (t_write.address.line_count == 0) ||
560 558 (t_write.address.line_count >
561 559 test->info.page_size / test->info.line_size) ||
562 560 (t_write.address.line_offset >=
563 561 test->info.page_size / test->info.line_size) ||
564 562 ((t_write.address.line_offset + t_write.address.line_count) >
565 563 test->info.page_size / test->info.line_size)) {
566 564 AC_ERR_SET(pkt, AC_ERR_MEM_TEST_PAR);
567 565 retval = EINVAL;
568 566 goto write_done;
569 567 }
570 568
571 569 page_offset = t_write.address.line_offset * test->info.line_size;
572 570 page_pa = test->info.afar_base +
573 571 t_write.address.page_num * test->info.page_size;
574 572 src_va = test->bufp + page_offset;
575 573 dst_va = test->va + page_offset;
576 574
577 575 /* copy in the specified user data */
578 576 if (ddi_copyin((caddr_t)(t_write.page_buf) + page_offset, src_va,
579 577 t_write.address.line_count * test->info.line_size, flag) != 0) {
580 578 retval = EFAULT;
581 579 goto write_done;
582 580 }
583 581
584 582 /* time to go quiet */
585 583 kpreempt_disable();
586 584
587 585 /* we need a va for the block instructions */
588 586 ac_mapin(page_pa, test->va);
589 587
590 588 pstate_save = disable_vec_intr();
591 589
592 590 /* copy the data again (using our very special copy) */
593 591 ac_blkcopy(src_va, dst_va, t_write.address.line_count,
594 592 test->info.line_size);
↓ open down ↓ |
31 lines elided |
↑ open up ↑ |
595 593
596 594 enable_vec_intr(pstate_save);
597 595
598 596 /* tear down translation (who needs an mmu) */
599 597 ac_unmap(test->va);
600 598
601 599 /* we're back! */
602 600 kpreempt_enable();
603 601
604 602 write_done:
605 - atomic_add_32(&test->in_test, -1);
603 + atomic_dec_32(&test->in_test);
606 604 return (retval);
607 605 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX