cvmx-shmem.c revision 215976
1130561Sobrien/***********************license start*************** 2130561Sobrien * Copyright (c) 2003-2010 Cavium Networks (support@cavium.com). All rights 3130561Sobrien * reserved. 4130561Sobrien * 5130561Sobrien * 6130561Sobrien * Redistribution and use in source and binary forms, with or without 7130561Sobrien * modification, are permitted provided that the following conditions are 8130561Sobrien * met: 9130561Sobrien * 10130561Sobrien * * Redistributions of source code must retain the above copyright 11130561Sobrien * notice, this list of conditions and the following disclaimer. 12130561Sobrien * 13130561Sobrien * * Redistributions in binary form must reproduce the above 14130561Sobrien * copyright notice, this list of conditions and the following 15130561Sobrien * disclaimer in the documentation and/or other materials provided 16130561Sobrien * with the distribution. 17130561Sobrien 18218822Sdim * * Neither the name of Cavium Networks nor the names of 19130561Sobrien * its contributors may be used to endorse or promote products 20130561Sobrien * derived from this software without specific prior written 21130561Sobrien * permission. 22130561Sobrien 23130561Sobrien * This Software, including technical data, may be subject to U.S. export control 24130561Sobrien * laws, including the U.S. Export Administration Act and its associated 25130561Sobrien * regulations, and may be subject to export or import regulations in other 26130561Sobrien * countries. 27130561Sobrien 28130561Sobrien * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 29130561Sobrien * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR 30130561Sobrien * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 31130561Sobrien * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 32130561Sobrien * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 33130561Sobrien * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 34130561Sobrien * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 35130561Sobrien * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 36130561Sobrien * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 37130561Sobrien * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 38130561Sobrien ***********************license end**************************************/ 39130561Sobrien 40130561Sobrien 41130561Sobrien 42130561Sobrien/** 43130561Sobrien * @file 44130561Sobrien * cvmx-shmem supplies the cross application shared memory implementation 45130561Sobrien * 46130561Sobrien * <hr>$Revision: 41586 $<hr> 47130561Sobrien */ 48130561Sobrien#include "cvmx.h" 49130561Sobrien#include "cvmx-bootmem.h" 50130561Sobrien#include "cvmx-tlb.h" 51130561Sobrien#include "cvmx-shmem.h" 52130561Sobrien 53130561Sobrien//#define DEBUG 54130561Sobrien 55130561Sobrienstruct cvmx_shmem_smdr *__smdr = NULL; 56130561Sobrien 57130561Sobrien#ifdef CVMX_BUILD_FOR_LINUX_USER 58130561Sobrienstatic int __cvmx_shmem_devmemfd = 0; /* fd for /dev/mem */ 59130561Sobrien#endif 60130561Sobrien 61130561Sobrien#define __CHECK_APP_SMDR do { \ 62130561Sobrien if (__smdr == NULL) { \ 63130561Sobrien cvmx_dprintf("cvmx_shmem: %s is not set up, Quit line %d \n", \ 64130561Sobrien CVMX_SHMEM_DSCPTR_NAME, __LINE__ ); \ 65130561Sobrien exit(-1); \ 66130561Sobrien } \ 67130561Sobrien }while(0) 68130561Sobrien 69130561Sobrien 70130561Sobrien 71130561Sobrien/** 72130561Sobrien * @INTERNAL 73130561Sobrien * Virtual sbrk, assigning virtual address in a global virtual address space. 74130561Sobrien * 75130561Sobrien * @param alignment alignment requirement in bytes 76130561Sobrien * @param size size in bytes 77130561Sobrien */ 78130561Sobrienstatic inline void *__cvmx_shmem_vsbrk_64(uint64_t alignment, uint64_t size) 79130561Sobrien{ 80130561Sobrien uint64_t nbase_64 = CAST64(__smdr->break64); 81130561Sobrien void *nbase = NULL; 82130561Sobrien 83130561Sobrien /* Skip unaligned bytes */ 84130561Sobrien if (nbase_64 & alignment) 85130561Sobrien nbase_64 += ~(nbase_64 & alignment) + 1; 86130561Sobrien 87130561Sobrien if (nbase_64 + size < CVMX_SHMEM_VADDR64_END) 88130561Sobrien { 89130561Sobrien nbase = CASTPTR(void *, nbase_64); 90130561Sobrien __smdr->break64 = nbase + size; 91130561Sobrien } 92130561Sobrien 93130561Sobrien return nbase; 94130561Sobrien} 95130561Sobrien 96130561Sobrien/** 97130561Sobrien * @INTERNAL 98130561Sobrien * Initialize all SMDR entries, only need to be called once 99130561Sobrien * 100130561Sobrien * @param smdr pointer to the SMDR 101130561Sobrien */ 102130561Sobrienstatic inline void __smdr_new(struct cvmx_shmem_smdr *smdr) { 103130561Sobrien 104130561Sobrien if (smdr != NULL) 105130561Sobrien { 106130561Sobrien int i; 107130561Sobrien 108130561Sobrien cvmx_spinlock_init (&smdr->lock); 109130561Sobrien cvmx_spinlock_lock (&smdr->lock); 110130561Sobrien 111130561Sobrien for ( i = 0; i < CVMX_SHMEM_NUM_DSCPTR; i++ ) 112130561Sobrien { 113130561Sobrien smdr -> shmd[i].owner = CVMX_SHMEM_OWNER_NONE; 114130561Sobrien smdr -> shmd[i].is_named_block = 0; 115130561Sobrien smdr -> shmd[i].use_count = 0; 116130561Sobrien smdr -> shmd[i].name = NULL; 117130561Sobrien smdr -> shmd[i].vaddr = NULL; 118130561Sobrien smdr -> shmd[i].paddr = 0; 119130561Sobrien smdr -> shmd[i].size = 0; 120130561Sobrien smdr -> shmd[i].alignment = 0; 121130561Sobrien }; 122130561Sobrien 123130561Sobrien /* Init vaddr */ 124130561Sobrien smdr->break64 = (void *)CVMX_SHMEM_VADDR64_START; 125130561Sobrien cvmx_spinlock_unlock (&smdr->lock); 126130561Sobrien } 127130561Sobrien 128130561Sobrien /* Make sure the shmem descriptor region is created */ 129130561Sobrien __CHECK_APP_SMDR; 130130561Sobrien}; 131130561Sobrien 132130561Sobrien 133130561Sobrien 134130561Sobrien/** 135130561Sobrien * @INTERNAL 136130561Sobrien * Initialize __smdr pointer, if SMDR exits already. If not, create a new 137130561Sobrien * one. Once SMDR is created (as a bootmem named block), it is persistent. 138130561Sobrien */ 139130561Sobrienstatic inline struct cvmx_shmem_smdr *__smdr_init() 140130561Sobrien{ 141130561Sobrien const cvmx_bootmem_named_block_desc_t *smdr_nblk = NULL; 142130561Sobrien size_t smdr_size = sizeof(*__smdr); 143130561Sobrien char *smdr_name = CVMX_SHMEM_DSCPTR_NAME; 144130561Sobrien 145130561Sobrien __smdr = (struct cvmx_shmem_smdr *) cvmx_bootmem_alloc_named(smdr_size, 0x10000, smdr_name); 146130561Sobrien 147130561Sobrien if (__smdr) 148130561Sobrien __smdr_new (__smdr); 149130561Sobrien else 150130561Sobrien { 151130561Sobrien /* Check if SMDR exists already */ 152130561Sobrien smdr_nblk = cvmx_bootmem_find_named_block(smdr_name); 153130561Sobrien if (smdr_nblk) 154130561Sobrien { 155130561Sobrien __smdr = (struct cvmx_shmem_smdr *) 156130561Sobrien (cvmx_phys_to_ptr(smdr_nblk->base_addr)); 157130561Sobrien 158130561Sobrien cvmx_spinlock_lock (&__smdr->lock); 159130561Sobrien if (smdr_nblk->size != smdr_size) 160130561Sobrien { 161130561Sobrien cvmx_dprintf("SMDR named block is created by another " 162130561Sobrien "application with different size %lu, " 163130561Sobrien "expecting %lu \n", 164130561Sobrien (long unsigned int)smdr_nblk->size, (long unsigned int)smdr_size); 165130561Sobrien __smdr = NULL; 166130561Sobrien } 167130561Sobrien cvmx_spinlock_unlock (&__smdr->lock); 168130561Sobrien } 169130561Sobrien } 170130561Sobrien 171130561Sobrien if (!__smdr) 172130561Sobrien cvmx_dprintf("cvmx_shmem: Failed to allocate or find SMDR from bootmem \n"); 173130561Sobrien 174130561Sobrien return __smdr; 175130561Sobrien}; 176130561Sobrien 177130561Sobrien 178130561Sobrien/** 179130561Sobrien * @INTERNAL 180130561Sobrien * Generic Iterator function for all SMDR entries 181130561Sobrien * 182130561Sobrien * @param void(*f)(dscptr) the function to be invoked for every descriptor 183130561Sobrien * @param param 184130561Sobrien * 185130561Sobrien * @return the descriptor iterator stopped at. 186130561Sobrien */ 187130561Sobrienstatic struct cvmx_shmem_dscptr *__smdr_iterator(struct cvmx_shmem_dscptr *(*f)(struct cvmx_shmem_dscptr *dscptr, void *p), void *param ) 188130561Sobrien{ 189130561Sobrien struct cvmx_shmem_dscptr *d, *dscptr = NULL; 190130561Sobrien int i; 191130561Sobrien 192130561Sobrien __CHECK_APP_SMDR; 193130561Sobrien 194130561Sobrien for (i = 0; i < CVMX_SHMEM_NUM_DSCPTR; i++) 195130561Sobrien { 196130561Sobrien d = &__smdr->shmd[i]; 197130561Sobrien if ((dscptr = (*f)(d, param)) != NULL) 198130561Sobrien break; /* stop iteration */ 199130561Sobrien } 200130561Sobrien 201130561Sobrien return dscptr; 202130561Sobrien} 203130561Sobrien 204130561Sobrien 205130561Sobrien/** 206130561Sobrien * @INTERNAL 207130561Sobrien * SMDR name match functor. to be used for iterator. 208130561Sobrien * 209130561Sobrien * @param dscptr descriptor passed in by the iterator 210130561Sobrien * @param name string to match against 211130561Sobrien * 212130561Sobrien * @return !NULL descriptor matched 213130561Sobrien * NULL not match 214130561Sobrien */ 215130561Sobrienstatic struct cvmx_shmem_dscptr *__cvmx_shmem_smdr_match_name(struct cvmx_shmem_dscptr *dscptr, void *name) 216130561Sobrien{ 217130561Sobrien char *name_to_match = (char *) name; 218130561Sobrien struct cvmx_shmem_dscptr *ret = NULL; 219130561Sobrien 220130561Sobrien if (dscptr->owner == CVMX_SHMEM_OWNER_NONE) 221130561Sobrien return NULL; 222130561Sobrien 223130561Sobrien if (strcmp(dscptr->name, name_to_match) == 0) 224130561Sobrien ret = dscptr; 225130561Sobrien 226130561Sobrien return ret; 227130561Sobrien} 228130561Sobrien 229130561Sobrien/** 230130561Sobrien * @INTERNAL 231130561Sobrien * Find by name 232130561Sobrien * 233130561Sobrien * @param name string to match against 234130561Sobrien * 235130561Sobrien * @return !NULL descriptor matched 236130561Sobrien * NULL not match 237130561Sobrien */ 238130561Sobrienstatic struct cvmx_shmem_dscptr *__cvmx_shmem_smdr_find_by_name(char *name) 239130561Sobrien{ 240130561Sobrien return __smdr_iterator( __cvmx_shmem_smdr_match_name, name); 241130561Sobrien} 242130561Sobrien 243130561Sobrien/** 244130561Sobrien * @INTERNAL 245130561Sobrien * SMDR is free functor. to be used for iterator. 246130561Sobrien * 247130561Sobrien * @param dscptr descriptor passed in by the iterator 248130561Sobrien * @param nouse 249130561Sobrien * 250130561Sobrien * @return !NULL descriptor is free 251130561Sobrien * NULL descriptor is not free 252130561Sobrien */ 253130561Sobrienstatic struct cvmx_shmem_dscptr *__cvmx_shmem_smdr_is_free(struct cvmx_shmem_dscptr* dscptr, void *nouse) 254130561Sobrien{ 255130561Sobrien if (dscptr->owner == CVMX_SHMEM_OWNER_NONE) 256130561Sobrien return dscptr; 257130561Sobrien else 258130561Sobrien return NULL; 259130561Sobrien} 260130561Sobrien 261130561Sobrien/** 262130561Sobrien * @INTERNAL 263130561Sobrien * Search SMDR to find the first free descriptor 264130561Sobrien * 265130561Sobrien * @return !NULL free descriptor found 266130561Sobrien * NULL nothing found 267130561Sobrien */ 268130561Sobrienstruct cvmx_shmem_dscptr *__cvmx_shmem_smdr_find_free_dscptr(void) 269130561Sobrien{ 270130561Sobrien return __smdr_iterator(__cvmx_shmem_smdr_is_free, NULL); 271130561Sobrien} 272130561Sobrien 273130561Sobrien/** 274130561Sobrien * @INTERNAL 275130561Sobrien * free a descriptor 276130561Sobrien * 277130561Sobrien * @param dscptr descriptor to be freed 278130561Sobrien */ 279130561Sobrienstatic void __cvmx_shmem_smdr_free(struct cvmx_shmem_dscptr *dscptr) 280130561Sobrien{ 281130561Sobrien dscptr->owner = CVMX_SHMEM_OWNER_NONE; 282130561Sobrien} 283130561Sobrien 284130561Sobrien 285130561Sobrien/** 286130561Sobrien * Per core shmem init function 287130561Sobrien * 288130561Sobrien * @return cvmx_shmem_smdr* pointer to __smdr 289130561Sobrien */ 290130561Sobrienstruct cvmx_shmem_smdr *cvmx_shmem_init() 291130561Sobrien{ 292130561Sobrien return __smdr_init(); 293130561Sobrien} 294130561Sobrien 295130561Sobrien/** 296130561Sobrien * Open shared memory based on named block 297130561Sobrien * 298130561Sobrien * @return dscptr descriptor of the opened named block 299130561Sobrien */ 300130561Sobrienstruct cvmx_shmem_dscptr *cvmx_shmem_named_block_open(char *name, uint32_t size, int oflag) 301130561Sobrien{ 302130561Sobrien const cvmx_bootmem_named_block_desc_t *shmem_nblk = NULL; 303130561Sobrien struct cvmx_shmem_dscptr *dscptr = NULL; 304130561Sobrien int nblk_allocated = 0; /* Assume we don't need to allocate a new 305130561Sobrien bootmem block */ 306130561Sobrien void *vaddr = NULL; 307130561Sobrien const uint64_t size_4k = 4*1024, size_512mb = 512*1024*1024; 308130561Sobrien 309130561Sobrien __CHECK_APP_SMDR; 310130561Sobrien 311130561Sobrien /* Check size, Make sure it is minimal 4K, no bigger than 512MB */ 312130561Sobrien if (size > size_512mb) { 313130561Sobrien cvmx_dprintf("Shared memory size can not be bigger than 512MB \n"); 314130561Sobrien return NULL; 315130561Sobrien } 316130561Sobrien if (size < size_4k) 317130561Sobrien size = size_4k; 318130561Sobrien 319130561Sobrien size = __upper_power_of_two(size); 320130561Sobrien 321130561Sobrien cvmx_spinlock_lock(&__smdr->lock); 322130561Sobrien 323130561Sobrien shmem_nblk = cvmx_bootmem_find_named_block(name); 324130561Sobrien if ((shmem_nblk == NULL) && (oflag & CVMX_SHMEM_O_CREAT)) 325130561Sobrien { 326130561Sobrien void *p; 327130561Sobrien /* The named block does not exist, create it if caller specifies 328130561Sobrien the O_CREAT flag */ 329130561Sobrien nblk_allocated = 1; 330130561Sobrien p = cvmx_bootmem_alloc_named(size, size, name); 331130561Sobrien if (p) 332130561Sobrien shmem_nblk = cvmx_bootmem_find_named_block(name); 333130561Sobrien#ifdef DEBUG 334130561Sobrien cvmx_dprintf("cvmx-shmem-dbg:" 335130561Sobrien "creating a new block %s: blk %p, shmem_nblk %p \n", 336130561Sobrien name, p, shmem_nblk); 337130561Sobrien#endif 338130561Sobrien } 339130561Sobrien 340130561Sobrien if (shmem_nblk == NULL) 341130561Sobrien goto err; 342130561Sobrien 343130561Sobrien /* We are now holding a valid named block */ 344130561Sobrien 345130561Sobrien dscptr = __cvmx_shmem_smdr_find_by_name(name); 346130561Sobrien if (dscptr) 347130561Sobrien { 348130561Sobrien if (nblk_allocated) 349130561Sobrien { 350130561Sobrien /* name conflict between bootmem name space and SMDR name space */ 351130561Sobrien cvmx_dprintf("cvmx-shmem: SMDR descriptor name conflict, %s \n", name); 352130561Sobrien goto err; 353130561Sobrien } 354130561Sobrien /* Make sure size and alignment matches with existing descriptor */ 355130561Sobrien if ((size != dscptr->size) || (size != dscptr -> alignment)) 356130561Sobrien goto err; 357130561Sobrien } 358130561Sobrien else 359130561Sobrien { 360130561Sobrien /* Create a new descriptor */ 361130561Sobrien dscptr = __cvmx_shmem_smdr_find_free_dscptr(); 362130561Sobrien if (dscptr) 363130561Sobrien goto init; 364130561Sobrien else 365130561Sobrien { 366130561Sobrien cvmx_dprintf("cvmx-shmem: SMDR out of descriptors \n"); 367130561Sobrien goto err; 368130561Sobrien } 369130561Sobrien } 370130561Sobrien 371130561Sobrien /* Maintain the reference count */ 372130561Sobrien if (dscptr != NULL) 373130561Sobrien dscptr->use_count += 1; 374130561Sobrien 375130561Sobrien cvmx_spinlock_unlock(&__smdr->lock); 376130561Sobrien return dscptr; 377130561Sobrien 378130561Sobrienerr: 379130561Sobrien#ifdef DEBUG 380130561Sobrien cvmx_dprintf("cvmx-shmem-dbg: named block open failed \n"); 381130561Sobrien#endif 382130561Sobrien 383130561Sobrien if (dscptr) 384130561Sobrien __cvmx_shmem_smdr_free(dscptr); 385130561Sobrien if (shmem_nblk && nblk_allocated) 386130561Sobrien cvmx_bootmem_free_named(name); 387130561Sobrien cvmx_spinlock_unlock(&__smdr->lock); 388130561Sobrien 389130561Sobrien return NULL; 390130561Sobrien 391130561Sobrieninit: 392130561Sobrien 393130561Sobrien#ifdef DEBUG 394130561Sobrien cvmx_dprintf("cvmx-shmem-dbg: init SMDR descriptor %p \n", dscptr); 395130561Sobrien#endif 396130561Sobrien 397130561Sobrien /* Assign vaddr for single address space mapping */ 398130561Sobrien vaddr = __cvmx_shmem_vsbrk_64(size, size); 399130561Sobrien if (vaddr == NULL) { 400130561Sobrien /* Failed to allocate virtual address, clean up */ 401130561Sobrien goto err; 402130561Sobrien } 403130561Sobrien 404130561Sobrien#ifdef DEBUG 405130561Sobrien cvmx_dprintf("cmvx-shmem-dbg: allocated vaddr %p \n", vaddr); 406130561Sobrien#endif 407130561Sobrien dscptr->vaddr = vaddr; 408130561Sobrien 409130561Sobrien /* Store descriptor information, name, alignment,size... */ 410130561Sobrien dscptr->owner = cvmx_get_core_num(); 411130561Sobrien dscptr->is_named_block = 1; 412130561Sobrien dscptr->use_count = 1; 413130561Sobrien dscptr->name =shmem_nblk->name ; 414130561Sobrien dscptr->paddr = shmem_nblk->base_addr; 415130561Sobrien dscptr->size = size; 416130561Sobrien dscptr->alignment = size; 417130561Sobrien 418130561Sobrien /* Store permission bits */ 419130561Sobrien if (oflag & CVMX_SHMEM_O_WRONLY) 420130561Sobrien dscptr->p_wronly = 1; 421130561Sobrien if (oflag & CVMX_SHMEM_O_RDWR) 422130561Sobrien 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