Print this page
5045 use atomic_{inc,dec}_* instead of atomic_add_*


   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #pragma ident   "%Z%%M% %I%     %E% SMI"
  28 
  29 #include <sys/types.h>
  30 #include <sys/conf.h>
  31 #include <sys/ddi.h>
  32 #include <sys/sunddi.h>
  33 #include <sys/ddi_impldefs.h>
  34 #include <sys/obpdefs.h>
  35 #include <sys/cmn_err.h>
  36 #include <sys/errno.h>
  37 #include <sys/kmem.h>
  38 #include <sys/vmem.h>
  39 #include <sys/debug.h>
  40 #include <sys/sysmacros.h>
  41 #include <sys/machsystm.h>
  42 #include <sys/machparam.h>
  43 #include <sys/modctl.h>
  44 #include <sys/atomic.h>
  45 #include <sys/fhc.h>
  46 #include <sys/ac.h>
  47 #include <sys/jtag.h>
  48 #include <sys/cpu_module.h>


 175                         return (EFAULT);                /* !broken user app */
 176                 }
 177                 mutex_exit(&test_mutex);
 178                 fhc_bdlist_unlock();
 179                 AC_ERR_SET(pkt, AC_ERR_MEM_BK);
 180                 return (EBUSY);                         /* signal bank in use */
 181         }
 182 
 183         /*
 184          * at this point, we have an available bank to test.
 185          * create a test buffer
 186          */
 187         test = kmem_zalloc(sizeof (struct test_info), KM_SLEEP);
 188         test->va = vmem_alloc(heap_arena, PAGESIZE, VM_SLEEP);
 189 
 190         /* fill in all the test info details now */
 191         test->mem_info = mem_info;
 192         test->board = softsp->board;
 193         test->bank = pkt->bank;
 194         test->bufp = kmem_alloc(TEST_PAGESIZE, KM_SLEEP);
 195         test->info.handle = atomic_add_32_nv(&mem_test_sequence_id, 1);
 196         (void) drv_getparm(PPID, (ulong_t *)(&(test->info.tester_pid)));
 197         test->info.prev_condition = mem_info->condition;
 198         test->info.page_size = TEST_PAGESIZE;
 199         /* If Blackbird ever gets a variable line size, this will change. */
 200         test->info.line_size = cpunodes[CPU->cpu_id].ecache_linesize;
 201         decode = (pkt->bank == Bank0) ?
 202             *softsp->ac_memdecode0 : *softsp->ac_memdecode1;
 203         test->info.afar_base = GRP_REALBASE(decode);
 204         test->info.bank_size = GRP_UK2SPAN(decode);
 205 
 206         /* return the information to the user */
 207         if (ddi_copyout(&test->info, pkt->cmd_cfga.private,
 208             sizeof (ac_mem_test_start_t), flag) != 0) {
 209 
 210                 /* oh well, tear down the test now */
 211                 kmem_free(test->bufp, TEST_PAGESIZE);
 212                 vmem_free(heap_arena, test->va, PAGESIZE);
 213                 kmem_free(test, sizeof (struct test_info));
 214 
 215                 fhc_bdlist_unlock();


 387         }
 388 #else /* _MULTI_DATAMODEL */
 389         if (ddi_copyin(pkt->cmd_cfga.private, &t_read,
 390             sizeof (ac_mem_test_read_t), flag) != 0)
 391                 return (EFAULT);
 392 #endif /* _MULTI_DATAMODEL */
 393 
 394         /* verify the handle */
 395         mutex_enter(&test_mutex);
 396         for (test = test_base; test != NULL; test = test->next) {
 397                 if (test->info.handle == t_read.handle)
 398                         break;
 399         }
 400         if (test == NULL) {
 401                 mutex_exit(&test_mutex);
 402                 AC_ERR_SET(pkt, AC_ERR_MEM_TEST);
 403                 return (EINVAL);
 404         }
 405 
 406         /* bump the busy bit */
 407         atomic_add_32(&test->in_test, 1);
 408         mutex_exit(&test_mutex);
 409 
 410         /* verify the remaining parameters */
 411         if ((t_read.address.page_num >=
 412             test->info.bank_size / test->info.page_size) ||
 413             (t_read.address.line_count == 0) ||
 414             (t_read.address.line_count >
 415             test->info.page_size / test->info.line_size) ||
 416             (t_read.address.line_offset >=
 417             test->info.page_size / test->info.line_size) ||
 418             ((t_read.address.line_offset + t_read.address.line_count) >
 419             test->info.page_size / test->info.line_size)) {
 420                 AC_ERR_SET(pkt, AC_ERR_MEM_TEST_PAR);
 421                 retval = EINVAL;
 422                 goto read_done;
 423         }
 424 
 425         page_offset = t_read.address.line_offset * test->info.line_size;
 426         page_pa = test->info.afar_base +
 427             t_read.address.page_num * test->info.page_size;


 481          * If there was a data error, attempt to return the error_buf
 482          * to the user.
 483          */
 484         if (error_found) {
 485                 if (ddi_copyout(&error_buf, t_read.error_buf,
 486                     sizeof (sunfire_processor_error_regs_t), flag) != 0) {
 487                         retval = EFAULT;
 488                         /* Keep going */
 489                 }
 490         }
 491 
 492         /*
 493          * Then, return the page to the user (always)
 494          */
 495         if (ddi_copyout(dst_va, (caddr_t)(t_read.page_buf) + page_offset,
 496             t_read.address.line_count * test->info.line_size, flag) != 0) {
 497                 retval = EFAULT;
 498         }
 499 
 500 read_done:
 501         atomic_add_32(&test->in_test, -1);
 502         return (retval);
 503 }
 504 
 505 int
 506 ac_mem_test_write(ac_cfga_pkt_t *pkt, int flag)
 507 {
 508         struct test_info *test;
 509         uint_t page_offset;
 510         uint64_t page_pa;
 511         uint_t pstate_save;
 512         caddr_t src_va, dst_va;
 513         int retval = DDI_SUCCESS;
 514         ac_mem_test_write_t t_write;
 515 
 516 #ifdef _MULTI_DATAMODEL
 517         switch (ddi_model_convert_from(flag & FMODELS)) {
 518         case DDI_MODEL_ILP32: {
 519                 ac_mem_test_write32_t t_write32;
 520 
 521                 if (ddi_copyin(pkt->cmd_cfga.private, &t_write32,


 533                 break;
 534         }
 535 #else /* _MULTI_DATAMODEL */
 536         if (ddi_copyin(pkt->cmd_cfga.private, &t_write,
 537             sizeof (ac_mem_test_write_t), flag) != 0)
 538                 return (EFAULT);
 539 #endif /* _MULTI_DATAMODEL */
 540 
 541         /* verify the handle */
 542         mutex_enter(&test_mutex);
 543         for (test = test_base; test != NULL; test = test->next) {
 544                 if (test->info.handle == t_write.handle)
 545                         break;
 546         }
 547         if (test == NULL) {
 548                 mutex_exit(&test_mutex);
 549                 return (EINVAL);
 550         }
 551 
 552         /* bump the busy bit */
 553         atomic_add_32(&test->in_test, 1);
 554         mutex_exit(&test_mutex);
 555 
 556         /* verify the remaining parameters */
 557         if ((t_write.address.page_num >=
 558             test->info.bank_size / test->info.page_size) ||
 559             (t_write.address.line_count == 0) ||
 560             (t_write.address.line_count >
 561             test->info.page_size / test->info.line_size) ||
 562             (t_write.address.line_offset >=
 563             test->info.page_size / test->info.line_size) ||
 564             ((t_write.address.line_offset + t_write.address.line_count) >
 565             test->info.page_size / test->info.line_size)) {
 566                 AC_ERR_SET(pkt, AC_ERR_MEM_TEST_PAR);
 567                 retval = EINVAL;
 568                 goto write_done;
 569         }
 570 
 571         page_offset = t_write.address.line_offset * test->info.line_size;
 572         page_pa = test->info.afar_base +
 573             t_write.address.page_num * test->info.page_size;


 585         kpreempt_disable();
 586 
 587         /* we need a va for the block instructions */
 588         ac_mapin(page_pa, test->va);
 589 
 590         pstate_save = disable_vec_intr();
 591 
 592         /* copy the data again (using our very special copy) */
 593         ac_blkcopy(src_va, dst_va, t_write.address.line_count,
 594             test->info.line_size);
 595 
 596         enable_vec_intr(pstate_save);
 597 
 598         /* tear down translation (who needs an mmu) */
 599         ac_unmap(test->va);
 600 
 601         /* we're back! */
 602         kpreempt_enable();
 603 
 604 write_done:
 605         atomic_add_32(&test->in_test, -1);
 606         return (retval);
 607 }


   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 


  27 #include <sys/types.h>
  28 #include <sys/conf.h>
  29 #include <sys/ddi.h>
  30 #include <sys/sunddi.h>
  31 #include <sys/ddi_impldefs.h>
  32 #include <sys/obpdefs.h>
  33 #include <sys/cmn_err.h>
  34 #include <sys/errno.h>
  35 #include <sys/kmem.h>
  36 #include <sys/vmem.h>
  37 #include <sys/debug.h>
  38 #include <sys/sysmacros.h>
  39 #include <sys/machsystm.h>
  40 #include <sys/machparam.h>
  41 #include <sys/modctl.h>
  42 #include <sys/atomic.h>
  43 #include <sys/fhc.h>
  44 #include <sys/ac.h>
  45 #include <sys/jtag.h>
  46 #include <sys/cpu_module.h>


 173                         return (EFAULT);                /* !broken user app */
 174                 }
 175                 mutex_exit(&test_mutex);
 176                 fhc_bdlist_unlock();
 177                 AC_ERR_SET(pkt, AC_ERR_MEM_BK);
 178                 return (EBUSY);                         /* signal bank in use */
 179         }
 180 
 181         /*
 182          * at this point, we have an available bank to test.
 183          * create a test buffer
 184          */
 185         test = kmem_zalloc(sizeof (struct test_info), KM_SLEEP);
 186         test->va = vmem_alloc(heap_arena, PAGESIZE, VM_SLEEP);
 187 
 188         /* fill in all the test info details now */
 189         test->mem_info = mem_info;
 190         test->board = softsp->board;
 191         test->bank = pkt->bank;
 192         test->bufp = kmem_alloc(TEST_PAGESIZE, KM_SLEEP);
 193         test->info.handle = atomic_inc_32_nv(&mem_test_sequence_id);
 194         (void) drv_getparm(PPID, (ulong_t *)(&(test->info.tester_pid)));
 195         test->info.prev_condition = mem_info->condition;
 196         test->info.page_size = TEST_PAGESIZE;
 197         /* If Blackbird ever gets a variable line size, this will change. */
 198         test->info.line_size = cpunodes[CPU->cpu_id].ecache_linesize;
 199         decode = (pkt->bank == Bank0) ?
 200             *softsp->ac_memdecode0 : *softsp->ac_memdecode1;
 201         test->info.afar_base = GRP_REALBASE(decode);
 202         test->info.bank_size = GRP_UK2SPAN(decode);
 203 
 204         /* return the information to the user */
 205         if (ddi_copyout(&test->info, pkt->cmd_cfga.private,
 206             sizeof (ac_mem_test_start_t), flag) != 0) {
 207 
 208                 /* oh well, tear down the test now */
 209                 kmem_free(test->bufp, TEST_PAGESIZE);
 210                 vmem_free(heap_arena, test->va, PAGESIZE);
 211                 kmem_free(test, sizeof (struct test_info));
 212 
 213                 fhc_bdlist_unlock();


 385         }
 386 #else /* _MULTI_DATAMODEL */
 387         if (ddi_copyin(pkt->cmd_cfga.private, &t_read,
 388             sizeof (ac_mem_test_read_t), flag) != 0)
 389                 return (EFAULT);
 390 #endif /* _MULTI_DATAMODEL */
 391 
 392         /* verify the handle */
 393         mutex_enter(&test_mutex);
 394         for (test = test_base; test != NULL; test = test->next) {
 395                 if (test->info.handle == t_read.handle)
 396                         break;
 397         }
 398         if (test == NULL) {
 399                 mutex_exit(&test_mutex);
 400                 AC_ERR_SET(pkt, AC_ERR_MEM_TEST);
 401                 return (EINVAL);
 402         }
 403 
 404         /* bump the busy bit */
 405         atomic_inc_32(&test->in_test);
 406         mutex_exit(&test_mutex);
 407 
 408         /* verify the remaining parameters */
 409         if ((t_read.address.page_num >=
 410             test->info.bank_size / test->info.page_size) ||
 411             (t_read.address.line_count == 0) ||
 412             (t_read.address.line_count >
 413             test->info.page_size / test->info.line_size) ||
 414             (t_read.address.line_offset >=
 415             test->info.page_size / test->info.line_size) ||
 416             ((t_read.address.line_offset + t_read.address.line_count) >
 417             test->info.page_size / test->info.line_size)) {
 418                 AC_ERR_SET(pkt, AC_ERR_MEM_TEST_PAR);
 419                 retval = EINVAL;
 420                 goto read_done;
 421         }
 422 
 423         page_offset = t_read.address.line_offset * test->info.line_size;
 424         page_pa = test->info.afar_base +
 425             t_read.address.page_num * test->info.page_size;


 479          * If there was a data error, attempt to return the error_buf
 480          * to the user.
 481          */
 482         if (error_found) {
 483                 if (ddi_copyout(&error_buf, t_read.error_buf,
 484                     sizeof (sunfire_processor_error_regs_t), flag) != 0) {
 485                         retval = EFAULT;
 486                         /* Keep going */
 487                 }
 488         }
 489 
 490         /*
 491          * Then, return the page to the user (always)
 492          */
 493         if (ddi_copyout(dst_va, (caddr_t)(t_read.page_buf) + page_offset,
 494             t_read.address.line_count * test->info.line_size, flag) != 0) {
 495                 retval = EFAULT;
 496         }
 497 
 498 read_done:
 499         atomic_dec_32(&test->in_test);
 500         return (retval);
 501 }
 502 
 503 int
 504 ac_mem_test_write(ac_cfga_pkt_t *pkt, int flag)
 505 {
 506         struct test_info *test;
 507         uint_t page_offset;
 508         uint64_t page_pa;
 509         uint_t pstate_save;
 510         caddr_t src_va, dst_va;
 511         int retval = DDI_SUCCESS;
 512         ac_mem_test_write_t t_write;
 513 
 514 #ifdef _MULTI_DATAMODEL
 515         switch (ddi_model_convert_from(flag & FMODELS)) {
 516         case DDI_MODEL_ILP32: {
 517                 ac_mem_test_write32_t t_write32;
 518 
 519                 if (ddi_copyin(pkt->cmd_cfga.private, &t_write32,


 531                 break;
 532         }
 533 #else /* _MULTI_DATAMODEL */
 534         if (ddi_copyin(pkt->cmd_cfga.private, &t_write,
 535             sizeof (ac_mem_test_write_t), flag) != 0)
 536                 return (EFAULT);
 537 #endif /* _MULTI_DATAMODEL */
 538 
 539         /* verify the handle */
 540         mutex_enter(&test_mutex);
 541         for (test = test_base; test != NULL; test = test->next) {
 542                 if (test->info.handle == t_write.handle)
 543                         break;
 544         }
 545         if (test == NULL) {
 546                 mutex_exit(&test_mutex);
 547                 return (EINVAL);
 548         }
 549 
 550         /* bump the busy bit */
 551         atomic_inc_32(&test->in_test);
 552         mutex_exit(&test_mutex);
 553 
 554         /* verify the remaining parameters */
 555         if ((t_write.address.page_num >=
 556             test->info.bank_size / test->info.page_size) ||
 557             (t_write.address.line_count == 0) ||
 558             (t_write.address.line_count >
 559             test->info.page_size / test->info.line_size) ||
 560             (t_write.address.line_offset >=
 561             test->info.page_size / test->info.line_size) ||
 562             ((t_write.address.line_offset + t_write.address.line_count) >
 563             test->info.page_size / test->info.line_size)) {
 564                 AC_ERR_SET(pkt, AC_ERR_MEM_TEST_PAR);
 565                 retval = EINVAL;
 566                 goto write_done;
 567         }
 568 
 569         page_offset = t_write.address.line_offset * test->info.line_size;
 570         page_pa = test->info.afar_base +
 571             t_write.address.page_num * test->info.page_size;


 583         kpreempt_disable();
 584 
 585         /* we need a va for the block instructions */
 586         ac_mapin(page_pa, test->va);
 587 
 588         pstate_save = disable_vec_intr();
 589 
 590         /* copy the data again (using our very special copy) */
 591         ac_blkcopy(src_va, dst_va, t_write.address.line_count,
 592             test->info.line_size);
 593 
 594         enable_vec_intr(pstate_save);
 595 
 596         /* tear down translation (who needs an mmu) */
 597         ac_unmap(test->va);
 598 
 599         /* we're back! */
 600         kpreempt_enable();
 601 
 602 write_done:
 603         atomic_dec_32(&test->in_test);
 604         return (retval);
 605 }