cvmx-shmem.c revision 232812
157416Smarkm/***********************license start*************** 257416Smarkm * Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights 357416Smarkm * reserved. 457416Smarkm * 557416Smarkm * 657416Smarkm * Redistribution and use in source and binary forms, with or without 757416Smarkm * modification, are permitted provided that the following conditions are 857416Smarkm * met: 957416Smarkm * 1057416Smarkm * * Redistributions of source code must retain the above copyright 1157416Smarkm * notice, this list of conditions and the following disclaimer. 1257416Smarkm * 1357416Smarkm * * Redistributions in binary form must reproduce the above 1457416Smarkm * copyright notice, this list of conditions and the following 1557416Smarkm * disclaimer in the documentation and/or other materials provided 1657416Smarkm * with the distribution. 1757416Smarkm 1857416Smarkm * * Neither the name of Cavium Inc. nor the names of 1957416Smarkm * its contributors may be used to endorse or promote products 2057416Smarkm * derived from this software without specific prior written 2157416Smarkm * permission. 2257416Smarkm 2357416Smarkm * This Software, including technical data, may be subject to U.S. export control 2457416Smarkm * laws, including the U.S. Export Administration Act and its associated 2557416Smarkm * regulations, and may be subject to export or import regulations in other 2657416Smarkm * countries. 2757416Smarkm 2857416Smarkm * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 2957416Smarkm * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR 3057416Smarkm * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 3157416Smarkm * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 3257416Smarkm * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 3357416Smarkm * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 3457416Smarkm * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 3557416Smarkm * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 3657416Smarkm * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 3757416Smarkm * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 3857416Smarkm ***********************license end**************************************/ 3957416Smarkm 4057416Smarkm 4157416Smarkm 4257416Smarkm/** 4357416Smarkm * @file 4457416Smarkm * cvmx-shmem supplies the cross application shared memory implementation 4557416Smarkm * 4657416Smarkm * <hr>$Revision: 41586 $<hr> 4757416Smarkm */ 4857416Smarkm#include "cvmx.h" 4957416Smarkm#include "cvmx-bootmem.h" 5057416Smarkm#include "cvmx-tlb.h" 5157416Smarkm#include "cvmx-shmem.h" 5257416Smarkm 5357416Smarkm//#define DEBUG 5457416Smarkm 5557416Smarkmstruct cvmx_shmem_smdr *__smdr = NULL; 5657416Smarkm 5757416Smarkm#ifdef CVMX_BUILD_FOR_LINUX_USER 5857416Smarkmstatic int __cvmx_shmem_devmemfd = 0; /* fd for /dev/mem */ 5957416Smarkm#endif 6057416Smarkm 6157416Smarkm#define __CHECK_APP_SMDR do { \ 6257416Smarkm if (__smdr == NULL) { \ 6357416Smarkm cvmx_dprintf("cvmx_shmem: %s is not set up, Quit line %d \n", \ 6457416Smarkm CVMX_SHMEM_DSCPTR_NAME, __LINE__ ); \ 6557416Smarkm exit(-1); \ 6657416Smarkm } \ 6757416Smarkm }while(0) 6857416Smarkm 6957416Smarkm 7057416Smarkm 7157416Smarkm/** 7257416Smarkm * @INTERNAL 7357416Smarkm * Virtual sbrk, assigning virtual address in a global virtual address space. 7457416Smarkm * 7557416Smarkm * @param alignment alignment requirement in bytes 7657416Smarkm * @param size size in bytes 7757416Smarkm */ 7857416Smarkmstatic inline void *__cvmx_shmem_vsbrk_64(uint64_t alignment, uint64_t size) 7957416Smarkm{ 8057416Smarkm uint64_t nbase_64 = CAST64(__smdr->break64); 8157416Smarkm void *nbase = NULL; 8257416Smarkm 8357416Smarkm /* Skip unaligned bytes */ 8457416Smarkm if (nbase_64 & alignment) 8557416Smarkm nbase_64 += ~(nbase_64 & alignment) + 1; 8657416Smarkm 8757416Smarkm if (nbase_64 + size < CVMX_SHMEM_VADDR64_END) 8857416Smarkm { 8957416Smarkm nbase = CASTPTR(void *, nbase_64); 9057416Smarkm __smdr->break64 = nbase + size; 9157416Smarkm } 9257416Smarkm 9357416Smarkm return nbase; 9457416Smarkm} 9557416Smarkm 9657416Smarkm/** 9757416Smarkm * @INTERNAL 9857416Smarkm * Initialize all SMDR entries, only need to be called once 9957416Smarkm * 10057416Smarkm * @param smdr pointer to the SMDR 10157416Smarkm */ 10257416Smarkmstatic inline void __smdr_new(struct cvmx_shmem_smdr *smdr) { 10357416Smarkm 10457416Smarkm if (smdr != NULL) 10557416Smarkm { 10657416Smarkm int i; 10757416Smarkm 10857416Smarkm cvmx_spinlock_init (&smdr->lock); 10957416Smarkm cvmx_spinlock_lock (&smdr->lock); 11057416Smarkm 11157416Smarkm for ( i = 0; i < CVMX_SHMEM_NUM_DSCPTR; i++ ) 11257416Smarkm { 11357416Smarkm smdr -> shmd[i].owner = CVMX_SHMEM_OWNER_NONE; 11457416Smarkm smdr -> shmd[i].is_named_block = 0; 11557416Smarkm smdr -> shmd[i].use_count = 0; 11657416Smarkm smdr -> shmd[i].name = NULL; 11757416Smarkm smdr -> shmd[i].vaddr = NULL; 11857416Smarkm smdr -> shmd[i].paddr = 0; 11957416Smarkm smdr -> shmd[i].size = 0; 12057416Smarkm smdr -> shmd[i].alignment = 0; 12157416Smarkm }; 12257416Smarkm 12357416Smarkm /* Init vaddr */ 12457416Smarkm smdr->break64 = (void *)CVMX_SHMEM_VADDR64_START; 12557416Smarkm cvmx_spinlock_unlock (&smdr->lock); 12657416Smarkm } 12757416Smarkm 12857416Smarkm /* Make sure the shmem descriptor region is created */ 12957416Smarkm __CHECK_APP_SMDR; 13057416Smarkm}; 13157416Smarkm 13257416Smarkm 13357416Smarkm 13457416Smarkm/** 13557416Smarkm * @INTERNAL 13657416Smarkm * Initialize __smdr pointer, if SMDR exits already. If not, create a new 13757416Smarkm * one. Once SMDR is created (as a bootmem named block), it is persistent. 13857416Smarkm */ 13957416Smarkmstatic inline struct cvmx_shmem_smdr *__smdr_init() 14057416Smarkm{ 14157416Smarkm const cvmx_bootmem_named_block_desc_t *smdr_nblk = NULL; 14257416Smarkm size_t smdr_size = sizeof(*__smdr); 14357416Smarkm char *smdr_name = CVMX_SHMEM_DSCPTR_NAME; 14457416Smarkm 14557416Smarkm __smdr = (struct cvmx_shmem_smdr *) cvmx_bootmem_alloc_named(smdr_size, 0x10000, smdr_name); 14657416Smarkm 14757416Smarkm if (__smdr) 14857416Smarkm __smdr_new (__smdr); 14957416Smarkm else 15057416Smarkm { 15157416Smarkm /* Check if SMDR exists already */ 15257416Smarkm smdr_nblk = cvmx_bootmem_find_named_block(smdr_name); 15357416Smarkm if (smdr_nblk) 15457416Smarkm { 15557416Smarkm __smdr = (struct cvmx_shmem_smdr *) 15657416Smarkm (cvmx_phys_to_ptr(smdr_nblk->base_addr)); 15757416Smarkm 15857416Smarkm cvmx_spinlock_lock (&__smdr->lock); 15957416Smarkm if (smdr_nblk->size != smdr_size) 16057416Smarkm { 16157416Smarkm cvmx_dprintf("SMDR named block is created by another " 16257416Smarkm "application with different size %lu, " 16357416Smarkm "expecting %lu \n", 16457416Smarkm (long unsigned int)smdr_nblk->size, (long unsigned int)smdr_size); 16557416Smarkm __smdr = NULL; 16657416Smarkm } 16757416Smarkm cvmx_spinlock_unlock (&__smdr->lock); 16857416Smarkm } 16957416Smarkm } 17057416Smarkm 17157416Smarkm if (!__smdr) 17257416Smarkm cvmx_dprintf("cvmx_shmem: Failed to allocate or find SMDR from bootmem \n"); 17357416Smarkm 17457416Smarkm return __smdr; 17557416Smarkm}; 17657416Smarkm 17757416Smarkm 17857416Smarkm/** 17957416Smarkm * @INTERNAL 18057416Smarkm * Generic Iterator function for all SMDR entries 18157416Smarkm * 18257416Smarkm * @param void(*f)(dscptr) the function to be invoked for every descriptor 18357416Smarkm * @param param 18457416Smarkm * 18557416Smarkm * @return the descriptor iterator stopped at. 18657416Smarkm */ 18757416Smarkmstatic struct cvmx_shmem_dscptr *__smdr_iterator(struct cvmx_shmem_dscptr *(*f)(struct cvmx_shmem_dscptr *dscptr, void *p), void *param ) 18857416Smarkm{ 18957416Smarkm struct cvmx_shmem_dscptr *d, *dscptr = NULL; 19057416Smarkm int i; 19157416Smarkm 19257416Smarkm __CHECK_APP_SMDR; 19357416Smarkm 19457416Smarkm for (i = 0; i < CVMX_SHMEM_NUM_DSCPTR; i++) 19557416Smarkm { 19657416Smarkm d = &__smdr->shmd[i]; 19757416Smarkm if ((dscptr = (*f)(d, param)) != NULL) 19857416Smarkm break; /* stop iteration */ 19957416Smarkm } 20057416Smarkm 20157416Smarkm return dscptr; 20257416Smarkm} 20357416Smarkm 20457416Smarkm 20557416Smarkm/** 20657416Smarkm * @INTERNAL 20757416Smarkm * SMDR name match functor. to be used for iterator. 20857416Smarkm * 20957416Smarkm * @param dscptr descriptor passed in by the iterator 21057416Smarkm * @param name string to match against 21157416Smarkm * 21257416Smarkm * @return !NULL descriptor matched 21357416Smarkm * NULL not match 21457416Smarkm */ 21557416Smarkmstatic struct cvmx_shmem_dscptr *__cvmx_shmem_smdr_match_name(struct cvmx_shmem_dscptr *dscptr, void *name) 21657416Smarkm{ 21757416Smarkm char *name_to_match = (char *) name; 21857416Smarkm struct cvmx_shmem_dscptr *ret = NULL; 21957416Smarkm 22057416Smarkm if (dscptr->owner == CVMX_SHMEM_OWNER_NONE) 22157416Smarkm return NULL; 22257416Smarkm 22357416Smarkm if (strcmp(dscptr->name, name_to_match) == 0) 22457416Smarkm ret = dscptr; 22557416Smarkm 22657416Smarkm return ret; 22757416Smarkm} 22857416Smarkm 22957416Smarkm/** 23057416Smarkm * @INTERNAL 23157416Smarkm * Find by name 23257416Smarkm * 23357416Smarkm * @param name string to match against 23457416Smarkm * 23557416Smarkm * @return !NULL descriptor matched 23657416Smarkm * NULL not match 23757416Smarkm */ 23857416Smarkmstatic struct cvmx_shmem_dscptr *__cvmx_shmem_smdr_find_by_name(char *name) 23957416Smarkm{ 24057416Smarkm return __smdr_iterator( __cvmx_shmem_smdr_match_name, name); 24157416Smarkm} 24257416Smarkm 24357416Smarkm/** 24457416Smarkm * @INTERNAL 24557416Smarkm * SMDR is free functor. to be used for iterator. 24657416Smarkm * 24757416Smarkm * @param dscptr descriptor passed in by the iterator 24857416Smarkm * @param nouse 24957416Smarkm * 25057416Smarkm * @return !NULL descriptor is free 25157416Smarkm * NULL descriptor is not free 25257416Smarkm */ 25357416Smarkmstatic struct cvmx_shmem_dscptr *__cvmx_shmem_smdr_is_free(struct cvmx_shmem_dscptr* dscptr, void *nouse) 25457416Smarkm{ 25557416Smarkm if (dscptr->owner == CVMX_SHMEM_OWNER_NONE) 25657416Smarkm return dscptr; 25757416Smarkm else 25857416Smarkm return NULL; 25957416Smarkm} 26057416Smarkm 26157416Smarkm/** 26257416Smarkm * @INTERNAL 26357416Smarkm * Search SMDR to find the first free descriptor 26457416Smarkm * 26557416Smarkm * @return !NULL free descriptor found 26657416Smarkm * NULL nothing found 26757416Smarkm */ 26857416Smarkmstruct cvmx_shmem_dscptr *__cvmx_shmem_smdr_find_free_dscptr(void) 26957416Smarkm{ 27057416Smarkm return __smdr_iterator(__cvmx_shmem_smdr_is_free, NULL); 27157416Smarkm} 27257416Smarkm 27357416Smarkm/** 27457416Smarkm * @INTERNAL 27557416Smarkm * free a descriptor 27657416Smarkm * 27757416Smarkm * @param dscptr descriptor to be freed 27857416Smarkm */ 27957416Smarkmstatic void __cvmx_shmem_smdr_free(struct cvmx_shmem_dscptr *dscptr) 28057416Smarkm{ 28157416Smarkm dscptr->owner = CVMX_SHMEM_OWNER_NONE; 28257416Smarkm} 28357416Smarkm 28457416Smarkm 28557416Smarkm/** 28657416Smarkm * Per core shmem init function 28757416Smarkm * 28857416Smarkm * @return cvmx_shmem_smdr* pointer to __smdr 28957416Smarkm */ 29057416Smarkmstruct cvmx_shmem_smdr *cvmx_shmem_init() 29157416Smarkm{ 29257416Smarkm return __smdr_init(); 29357416Smarkm} 29457416Smarkm 29557416Smarkm/** 29657416Smarkm * Open shared memory based on named block 29757416Smarkm * 29857416Smarkm * @return dscptr descriptor of the opened named block 29957416Smarkm */ 30057416Smarkmstruct cvmx_shmem_dscptr *cvmx_shmem_named_block_open(char *name, uint32_t size, int oflag) 30157416Smarkm{ 30257416Smarkm const cvmx_bootmem_named_block_desc_t *shmem_nblk = NULL; 30357416Smarkm struct cvmx_shmem_dscptr *dscptr = NULL; 30457416Smarkm int nblk_allocated = 0; /* Assume we don't need to allocate a new 30557416Smarkm bootmem block */ 30657416Smarkm void *vaddr = NULL; 30757416Smarkm const uint64_t size_4k = 4*1024, size_512mb = 512*1024*1024; 30857416Smarkm 30957416Smarkm __CHECK_APP_SMDR; 31057416Smarkm 31157416Smarkm /* Check size, Make sure it is minimal 4K, no bigger than 512MB */ 31257416Smarkm if (size > size_512mb) { 31357416Smarkm cvmx_dprintf("Shared memory size can not be bigger than 512MB \n"); 31457416Smarkm return NULL; 31557416Smarkm } 31657416Smarkm if (size < size_4k) 31757416Smarkm size = size_4k; 31857416Smarkm 31957416Smarkm size = __upper_power_of_two(size); 32057416Smarkm 32157416Smarkm cvmx_spinlock_lock(&__smdr->lock); 32257416Smarkm 32357416Smarkm shmem_nblk = cvmx_bootmem_find_named_block(name); 32457416Smarkm if ((shmem_nblk == NULL) && (oflag & CVMX_SHMEM_O_CREAT)) 32557416Smarkm { 32657416Smarkm void *p; 32757416Smarkm /* The named block does not exist, create it if caller specifies 32857416Smarkm the O_CREAT flag */ 329 nblk_allocated = 1; 330 p = cvmx_bootmem_alloc_named(size, size, name); 331 if (p) 332 shmem_nblk = cvmx_bootmem_find_named_block(name); 333#ifdef DEBUG 334 cvmx_dprintf("cvmx-shmem-dbg:" 335 "creating a new block %s: blk %p, shmem_nblk %p \n", 336 name, p, shmem_nblk); 337#endif 338 } 339 340 if (shmem_nblk == NULL) 341 goto err; 342 343 /* We are now holding a valid named block */ 344 345 dscptr = __cvmx_shmem_smdr_find_by_name(name); 346 if (dscptr) 347 { 348 if (nblk_allocated) 349 { 350 /* name conflict between bootmem name space and SMDR name space */ 351 cvmx_dprintf("cvmx-shmem: SMDR descriptor name conflict, %s \n", name); 352 goto err; 353 } 354 /* Make sure size and alignment matches with existing descriptor */ 355 if ((size != dscptr->size) || (size != dscptr -> alignment)) 356 goto err; 357 } 358 else 359 { 360 /* Create a new descriptor */ 361 dscptr = __cvmx_shmem_smdr_find_free_dscptr(); 362 if (dscptr) 363 goto init; 364 else 365 { 366 cvmx_dprintf("cvmx-shmem: SMDR out of descriptors \n"); 367 goto err; 368 } 369 } 370 371 /* Maintain the reference count */ 372 if (dscptr != NULL) 373 dscptr->use_count += 1; 374 375 cvmx_spinlock_unlock(&__smdr->lock); 376 return dscptr; 377 378err: 379#ifdef DEBUG 380 cvmx_dprintf("cvmx-shmem-dbg: named block open failed \n"); 381#endif 382 383 if (dscptr) 384 __cvmx_shmem_smdr_free(dscptr); 385 if (shmem_nblk && nblk_allocated) 386 cvmx_bootmem_free_named(name); 387 cvmx_spinlock_unlock(&__smdr->lock); 388 389 return NULL; 390 391init: 392 393#ifdef DEBUG 394 cvmx_dprintf("cvmx-shmem-dbg: init SMDR descriptor %p \n", dscptr); 395#endif 396 397 /* Assign vaddr for single address space mapping */ 398 vaddr = __cvmx_shmem_vsbrk_64(size, size); 399 if (vaddr == NULL) { 400 /* Failed to allocate virtual address, clean up */ 401 goto err; 402 } 403 404#ifdef DEBUG 405 cvmx_dprintf("cmvx-shmem-dbg: allocated vaddr %p \n", vaddr); 406#endif 407 dscptr->vaddr = vaddr; 408 409 /* Store descriptor information, name, alignment,size... */ 410 dscptr->owner = cvmx_get_core_num(); 411 dscptr->is_named_block = 1; 412 dscptr->use_count = 1; 413 dscptr->name =shmem_nblk->name ; 414 dscptr->paddr = shmem_nblk->base_addr; 415 dscptr->size = size; 416 dscptr->alignment = size; 417 418 /* Store permission bits */ 419 if (oflag & CVMX_SHMEM_O_WRONLY) 420 dscptr->p_wronly = 1; 421 if (oflag & CVMX_SHMEM_O_RDWR) 422 dscptr->p_rdwr = 1; 423 424 cvmx_spinlock_unlock(&__smdr->lock); 425 return dscptr; 426} 427 428/** 429 * @INTERNAL 430 * 431 * For stand along SE application only. 432 * 433 * Add TLB mapping to map the shared memory 434 * 435 * @param dscptr shared memory descriptor 436 * @param pflag protection flags 437 * 438 * @return vaddr the virtual address mapped for the shared memory 439 */ 440#ifndef CVMX_BUILD_FOR_LINUX_USER 441void *__cvmx_shmem_map_standalone(struct cvmx_shmem_dscptr *dscptr, int pflag) 442{ 443 int free_index; 444 445 /* Find a free tlb entry */ 446 free_index = cvmx_tlb_allocate_runtime_entry(); 447 448 if (free_index < 0 ) 449 { 450 cvmx_dprintf("cvmx-shmem: shmem_map failed, out TLB entries \n"); 451 return NULL; 452 } 453 454#ifdef DEBUG 455 cvmx_dprintf("cmvx-shmem-dbg:" 456 "shmem_map TLB %d: vaddr %p paddr %lx, size %x \n", 457 free_index, dscptr->vaddr, dscptr->paddr, dscptr->size ); 458#endif 459 460 cvmx_tlb_write_runtime_entry(free_index, CAST64(dscptr->vaddr), 461 dscptr->paddr, dscptr->size, 462 TLB_DIRTY | TLB_VALID | TLB_GLOBAL); 463 464 return dscptr -> vaddr; 465} 466#endif 467 468/** 469 * @INTERNAL 470 * 471 * For Linux user application only 472 * 473 * Add mmap the shared memory 474 * 475 * @param dscptr shared memory descriptor 476 * @param pflag protection flags 477 * 478 * @return vaddr the virtual address mapped for the shared memory 479 */ 480#ifdef CVMX_BUILD_FOR_LINUX_USER 481static inline void *__cvmx_shmem_map_linux(struct cvmx_shmem_dscptr *dscptr, int pflag) 482{ 483 void *vaddr = NULL; 484 485 if(__cvmx_shmem_devmemfd == 0) 486 { 487 __cvmx_shmem_devmemfd = open("/dev/mem", O_RDWR); 488 if (__cvmx_shmem_devmemfd < 0) 489 { 490 cvmx_dprintf("Failed to open /dev/mem\n"); 491 exit(-1); 492 } 493 } 494 495 vaddr = mmap(dscptr->vaddr, dscptr->size, PROT_READ|PROT_WRITE, 496 MAP_SHARED, __cvmx_shmem_devmemfd, 0); 497 498 /* Make sure the mmap maps to the same virtual address specified in 499 * descriptor 500 */ 501 if ((vaddr!=NULL) && (vaddr != dscptr->vaddr)) 502 { 503 munmap(vaddr, dscptr->size); 504 vaddr = NULL; 505 } 506 return vaddr; 507} 508#endif 509 510/** 511 * cvmx_shmem API 512 * 513 * Add mapping for the shared memory 514 * 515 * @param dscptr shared memory descriptor 516 * @param pflag protection flags 517 * 518 * @return vaddr the virtual address mapped for the shared memory 519 */ 520void *cvmx_shmem_map(struct cvmx_shmem_dscptr *dscptr, int pflag) 521{ 522 void *vaddr = NULL; 523#ifdef CVMX_BUILD_FOR_LINUX_USER 524 vaddr = __cvmx_shmem_map_linux(dscptr, pflag); 525#else 526 vaddr = __cvmx_shmem_map_standalone(dscptr, pflag); 527#endif 528 return vaddr; 529} 530 531 532/** 533 * @INTERNAL 534 * 535 * For Linux user application only 536 * 537 * ummap the shared memory 538 * 539 * @param dscptr shared memory descriptor 540 * 541 */ 542#ifdef CVMX_BUILD_FOR_LINUX_USER 543static inline void __cvmx_shmem_unmap_linux(struct cvmx_shmem_dscptr* dscptr) 544{ 545 if (__cvmx_shmem_devmemfd && dscptr) 546 munmap(dscptr->vaddr, dscptr->size); 547} 548#endif 549 550 551/** 552 * @INTERNAL 553 * 554 * For stand along SE application only. 555 * 556 * ummap the shared memory 557 * 558 * @param dscptr shared memory descriptor 559 * 560 */ 561#ifndef CVMX_BUILD_FOR_LINUX_USER 562static inline void 563__cvmx_shmem_unmap_standalone(struct cvmx_shmem_dscptr *dscptr) 564{ 565 int index; 566 567 index = cvmx_tlb_lookup(CAST64(dscptr->vaddr)); 568 569#ifdef DEBUG 570 cvmx_dprintf("cmvx-shmem-dbg:" 571 "shmem_unmap TLB %d \n", index); 572#endif 573 cvmx_tlb_free_runtime_entry(index); 574} 575#endif 576 577/** 578 * ummap the shared memory 579 * 580 * @param dscptr shared memory descriptor 581 * 582 */ 583void cvmx_shmem_unmap(struct cvmx_shmem_dscptr *dscptr) 584{ 585#ifdef CVMX_BUILD_FOR_LINUX_USER 586 __cvmx_shmem_unmap_linux(dscptr); 587#else 588 __cvmx_shmem_unmap_standalone(dscptr); 589#endif 590} 591 592/** 593 * @INTERNAL 594 * 595 * Common implementation of closing a descriptor. 596 * 597 * @param dscptr shared memory descriptor 598 * @param remove 1: remove the descriptor and named block if this 599 * this is the last user of the descriptor 600 * 0: do not remove 601 * @return 0: Success 602 * !0: Failed 603 * 604 */ 605static inline int __cvmx_shmem_close_dscptr(struct cvmx_shmem_dscptr *dscptr, int remove) 606{ 607 cvmx_spinlock_lock(&dscptr->lock); 608 609 if (dscptr->use_count >0) 610 dscptr->use_count-= 1; 611 612 if ((dscptr->use_count == 0) && remove) 613 { 614 /* Free this descriptor */ 615 __cvmx_shmem_smdr_free(dscptr); 616 617 /* Free named block if this is the last user, and the block 618 is created by the application */ 619 if (dscptr->is_named_block) 620 { 621#ifdef DEBUG 622 cvmx_dprintf("cvmx-shmem-dbg: remove named block %s \n", dscptr->name); 623#endif 624 cvmx_bootmem_phy_named_block_free(dscptr->name, 0); 625 } 626 } 627 cvmx_spinlock_unlock(&dscptr->lock); 628 return 0; 629} 630 631 632/** 633 * @INTERNAL 634 * 635 * For stand along SE application only. 636 * 637 * close a descriptor. 638 * 639 * @param dscptr shared memory descriptor 640 * @param remove 1: remove the descriptor and named block if this 641 * this is the last user of the descriptor 642 * 0: do not remove 643 * @return 0: Success 644 * !0: Failed 645 * 646 */ 647#ifndef CVMX_BUILD_FOR_LINUX_USER 648static inline int __cvmx_shmem_close_standalone(struct cvmx_shmem_dscptr *dscptr, int remove) 649{ 650 return __cvmx_shmem_close_dscptr(dscptr, remove); 651} 652#endif 653 654/** 655 * @INTERNAL 656 * 657 * For Linux user application only. 658 * 659 * close a descriptor. 660 * 661 * @param dscptr shared memory descriptor 662 * @param remove 1: remove the descriptor and named block if this 663 * this is the last user of the descriptor 664 * 0: do not remove 665 * @return 0: Success 666 * !0: Failed 667 * 668 */ 669#ifdef CVMX_BUILD_FOR_LINUX_USER 670int __cvmx_shmem_close_linux(struct cvmx_shmem_dscptr *dscptr, int remove) 671{ 672 int ret; 673 ret = __cvmx_shmem_close_dscptr(dscptr, remove); 674 675 if (ret && __cvmx_shmem_devmemfd) 676 { 677 close(__cvmx_shmem_devmemfd); 678 __cvmx_shmem_devmemfd=0; 679 } 680 681 return ret; 682 683} 684#endif 685 686/** 687 * 688 * close a descriptor. 689 * 690 * @param dscptr shared memory descriptor 691 * @param remove 1: remove the descriptor and named block if this 692 * this is the last user of the descriptor 693 * 0: do not remove 694 * @return 0: Success 695 * !0: Failed 696 * 697 */ 698int cvmx_shmem_close(struct cvmx_shmem_dscptr *dscptr, int remove) 699{ 700 int ret; 701#ifdef CVMX_BUILD_FOR_LINUX_USER 702 ret = __cvmx_shmem_close_linux(dscptr, remove); 703#else 704 ret = __cvmx_shmem_close_standalone(dscptr, remove); 705#endif 706 return ret; 707} 708 709#ifdef DEBUG 710/** 711 * @INTERNAL 712 * SMDR non-free descriptor dump functor. to be used for iterator. 713 * 714 * @param dscptr descriptor passed in by the iterator 715 * 716 * @return NULL always 717 */ 718static struct cvmx_shmem_dscptr *__cvmx_shmem_smdr_display_dscptr(struct cvmx_shmem_dscptr *dscptr, void *nouse) 719{ 720 if ((dscptr != NULL ) && (dscptr -> owner != CVMX_SHMEM_OWNER_NONE)) 721 { 722 cvmx_dprintf(" %s: phy: %lx, size %d, alignment %lx, virt %p use_count %d\n", 723 dscptr->name, dscptr-> paddr, 724 dscptr->size, dscptr-> alignment, 725 dscptr->vaddr, dscptr->use_count); 726 } 727 728 return NULL; 729} 730#endif 731 732/** 733 * SMDR descriptor show 734 * 735 * list all non-free descriptors 736 */ 737void cvmx_shmem_show(void) 738{ 739 __CHECK_APP_SMDR; 740 741#ifdef DEBUG 742 cvmx_dprintf("SMDR descriptor list: \n"); 743 cvmx_spinlock_lock(&__smdr->lock); 744 __smdr_iterator(__cvmx_shmem_smdr_display_dscptr, NULL); 745 cvmx_spinlock_unlock(&__smdr->lock); 746 cvmx_dprintf("\n\n"); 747#endif 748} 749