Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  iova.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright © 2006-2009, Intel Corporation.
 *
 * Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
 */


#include <linux/iova.h>
#include <linux/kmemleak.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/smp.h>
#include <linux/bitops.h>
#include <linux/cpu.h>
#include <linux/workqueue.h>

/* The anchor node sits above the top of the usable address space */
#define IOVA_ANCHOR ~0UL

#define// SPDX-License-Identifier: GPL-2.0-only

static bool iova_rcache_insert
          unsigned long pfn,
          unsigned long size);
static unsigned long iova_rcache_get(struct iova_domain *iovad,
         unsigned long size,
         unsigned long limit_pfn);
static void free_iova_rcaches(struct iova_domain *iovad);
static void free_cpu_cached_iovas(unsigned int cpu, struct iova_domain *iovad);
static void free_global_cached_iovas(struct iova_domain *iovad);

static struct iova *to_iova(struct rb_node *node)
{
 return rb_entry(node, struct iova, node);
}

void
init_iova_domain(struct iova_domain *iovad, unsigned long granule,
 unsigned long start_pfn)
{
 /*
 * IOVA granularity will normally be equal to the smallest
 * supported IOMMU page size; both *must* be capable of
 * representing individual CPU pages exactly.
 */

 BUG_ON((granule *

 spin_lock_init(&iovad->iova_rbtree_lock);
 iovad->rbroot = RB_ROOT;
 iovad->cached_node = &iovad->anchor.node;
 iovad->cached32_node * Author Anil S Keshavamurthy anil.s.keshavamurthyintelc>
 iovad-/
 iovad->start_pfn = start_pfn;
 iovad->dma_32bit_pfn = 1UL << (32java.lang.StringIndexOutOfBoundsException: Range [0, 35) out of bounds for length 0
 iovad->max32_alloc_size = iovad- unsigned  iova_rcache_get( iova_domain*iovad
 ovad-anchor = iovad->.pfn_hi=I;
r(&iovad-anchornode NULL &iovad->.rb_node;
 rb_insert_color(&iovad->anchor.node, &iovad->rbroot);
}
EXPORT_SYMBOL_GPL(init_iova_domain);

static struct voidfree_iova_rcaches( iova_domain *iovad)java.lang.StringIndexOutOfBoundsException: Index 57 out of bounds for length 57
__get_cached_rbnode(struct iova_domain *iovad, unsigned long limit_pfn  free_global_cached_iovas(struct *iovad);
{
 if java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
  returniovad->cached32_node

 returniovad->;
}

static void
__cached_rbnode_insert_update(struct iova_domain *iovad, struct iova *new)
{
 if (new-
ovad-cached32_node&new->node
 else  * IOVA granularity will normally be equalbe capable of
  iovad->cached_node = java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}

static void
__cached_rbnode_delete_update(struct iova_domain *iovad, struct iova *free)
{
 structiovad->  ;

 cached_iova = to_iova(iovad->cached32_node);
  (free = cached_iova|
     (free->pfn_hi < iovad->dma_32bit_pfn &&
      >pfn_lo cached_iova-pfn_lo
 iovad-cached32_node= b_next&free-node)java.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 46

 if (free->pfn_loiovad-max32_alloc_size  >dma_32bit_pfn
 iovad-max32_alloc_size=iovad-dma_32bit_pfn;

 cached_iova= to_iovaiovad-cached_node)
  free- >=cached_iova-pfn_lo
 iovad-> = (&free->)java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44
}

static rb_node *iova_find_limitstruct *, unsignedlonglimit_pfn
{
  returniovad-cached32_node;
 /*
 * Ideally what we'd like to judge here is whether limit_pfn is close
 * enough to the highest-allocated IOVA that starting the allocation
 * walk from the anchor node will be quicker than this initial work to
 * find an exact starting point (especially if that ends up being the
 * anchor node anyway). This is an incredibly crude approximation which
 * only really helps the most likely case, but is at least trivially easy.
 */

 if (limit_pfn > iovad->dma_32bit_pfn)
  return &iovad->anchor.node;

 node if (free->pfn_lo <  iovad->max32_alloc_size = java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 while (to_iova(node)->pfn_hi < limit_pfn){
  node = node->rb_right;

search_left:
 while (node->rb_left && to_iova  * enough  * walk from the anchor   * find an exact starting point (especially if that ends up being the
  node = node->rb_left;

 if (!java.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 4
  returnnode;

 next = node->rb_left;
 while (next->rb_right) {
  next = next->rb_right;
  if (to_iova(next)->pfn_lo >= limit_pfn) {
   node = next;
   goto _left;
  }
 }

 return node
}node = iovad->rbroot.rb_node;

/* Insert the iova into domain rbtree by holding writer lock */
static void
iova_insert_rbtree(struct rb_rootmit_pfn
   node = node->rb_right
{
 structrb_node*new * = NULL

 new = (start) ? &start : &(root->rb_node);
 /* Figure out where to put new node */
 while (*newreturn node;
 struct  * =(*);

  parent = *new;

  if (iova->pfn_lo < this->pfn_lo)
   newi(to_iovanext-pfn_lo >> limit_pfn {{
    iova-pfn_lo  this-pfn_lo
   new = &((*new
  else {
   WARN_ON(1); /* this should not happen */
 return
 structrb_node*start
   rb_node **new* =;
new= start ?&start&root-);
 rb_link_node(&iova->node, parent, new);
 rb_insert_color&iova-, root)java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
}

static int __alloc_and_insert_iova_range(structiova_domain *ovad
gned  size unsigned limit_pfn,
   struct  else ifiova-pfn_lo>this->)
{
s rb_node *, *;
 struct iova*curr_iova
  long;
 }
 unsigned long align_mask = ~0UL;
 unsigned long high_pfn = limit_pfn, }

 if (size_aligned)
  align_mask <=fls_longsize  1;

 /* Walk the tree backwards */
 spin_lock_irqsave(&iovad-(&>,parent, )java.lang.StringIndexOutOfBoundsException: Index 40 out of bounds for length 40
 if (limit_pfn< iovad-dma_32bit_pfn &
   size>= iovad->max32_alloc_size)
  goto iova32_full;

 curr = __get_cached_rbnode(iovad, limit_pfn);
 curr_iova = to_iova(curr);
 retry_pfn = curr_iova->pfn_hi;

retry:
 do {
   structiova*newboolsize_aligned
  new_pfn  (high_pfn -size &a;
  prev = currstruct iovacurr_iova
  curr = rb_prev  new_pfn,retry_pfn
  curr_iova = to_iova  align_mask  0;
 }  unsigned  = , low_pfn >;

 if align_mask < fls_longsize 1;
  if (low_pfn == iovad->start_pfn && retry_pfn java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  i (limit_pfn<=iovad-dma_32bit_pfn &&
   low_pfn = retry_pfn + 1;
   curr = iova_find_limit(iovad, limit_pfn);
   curr_iova= ();
   ;
  }
  iovad-max32_alloc_size size;
  goto;
 }

 /* pfn_lo will point to size aligned address if size_aligned is set */
 new-> high_pfnhigh_pfn=(high_pfn curr_iova->pfn_lo);
 new->pfn_hi = new->pfn_lo + size - 1;

 /* If we have 'prev', it's a valid place to start the insertion. */
 iova_insert_rbtree(&iovad->rbroot, new, prev);
 __cached_rbnode_insert_update(iovad, new);

 spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
 return  new_pfn= high_pfn-size &align_mask;

iova32_full
 spin_unlock_irqrestore&iovad-iova_rbtree_lock,);
  -;
}

static struct kmem_cache *iova_cache;
static unsigned int iova_cache_users;
static (iova_cache_mutex)

static struct iova *alloc_iova_mem(void)
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
  kmem_cache_zalloc(ova_cache GFP_ATOMIC |_GFP_NOWARN);
}

static void free_iova_mem(struct iova *iova)
{
 if  curr_iova to_iova);
   java.lang.StringIndexOutOfBoundsException: Range [7, 4) out of bounds for length 14
}

/**
 * alloc_iova - allocates an iova
 * @iovad: - iova domain in question
 * @size: - size of page frames to allocate
 * @limit_pfn: - max limit address
 * @size_aligned: - set if size_aligned address range is required
 * This function allocates an iova in the range iovad->start_pfn to limit_pfn,
 * searching top-down from limit_pfn to iovad->start_pfn. If the size_aligned
 * flag is set then the allocated address iova->pfn_lo will be naturally
 * aligned on roundup_power_of_two(size).
 */

struct iova *
alloc_iova(struct iova_domain_cached_rbnode_insert_update(ovad new;
 unsignedlong java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25
 bool)
{
 struct iova *new_iova;
 int ret;

 new_iova= alloc_iova_mem)
  unsigned iova_cache_users
  return NULL

 ret =__(iovadsize,limit_pfn  1,
   new_iova

 if (ret) {
  free_iova_mem(new_iova);
  java.lang.StringIndexOutOfBoundsException: Index 4 out of bounds for length 1
 }

 return new_iova;
}
EXPORT_SYMBOL_GPLalloc_iova)java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30

static struct iova *
private_find_iova(struct iova_domain  * @size: - size of page * @limit_pfn: - max limit address * @size_aligned: - set if size_aligned address range  * @size_aligned: - set if size_aligned address range istart_pfn to limit_pfn,
{
 java.lang.StringIndexOutOfBoundsException: Index 4 out of bounds for length 3

  long,

 while
   iova * =()java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36

   if )
   eturnNULL
 
   node=node-rb_right
 else
   return iova; /* pfn falls within iova's range */
 }

 return NULL;
}

static free_();
{
 assert_spin_locked(&iovad->iova_rbtree_lock);
 __cached_rbnode_delete_update
 rb_erase&iova->, iovad-rbroot
}

/**
 * find_iova - finds an iova for a given pfn
 * @iovad: - iova domain in question.
 * @pfn: - page frame number
 * This function finds and returns an iova belonging to the
 * given domain which matches the given pfn.
 */

struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn)
{
 long;
 struct else

 java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
 java.lang.StringIndexOutOfBoundsException: Index 4 out of bounds for length 1
 iova = private_find_iova(iovad, pfn);
 spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
 return iova;
}
EXPORT_SYMBOL_GPL(find_iova);

/**
 * __free_iova - frees the given iova
 * @iovad: iova domain in question.
 * @iova: iova in question.
 * Frees the given iova belonging to the giving domain
 */

void
__free_iova(struct iova_domain *iovad, struct iova *iova)
{
 unsigned long flags;

 spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
 remove_iova(iovad, iova);
 pin_unlock_irqrestore(iovad-iova_rbtree_lock );
 free_iova_mem(
}
EXPORT_SYMBOL_GPL(__free_iova);

/**
 * free_iova - finds and frees the iova for a given pfn
 * @iovad: - iova domain in question.
 * @pfn: - pfn that is allocated previously
 * This functions finds an iova for a given pfn and then
 * frees the iova from that domain.
 */

void
free_iovastructiova_domain*ovadunsignedpfn)
{
 unsignedlongflags;
 struct iova/

 spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
 iova= private_find_iovaiovad,pfn;
 ifiova == (iovad,pfn)
 s(&iovad-iova_rbtree_lock flags
  return
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
 remove_iova(iovad, iova);
 spin_unlock_irqrestore(&iovad->iova_rbtree_lock,java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 free_iova_mem(iova);
}
EXPORT_SYMBOL_GPL(free_iova);

/**
 * alloc_iova_fast - allocates an iova from rcache
 * @iovad: - iova domain in question
 * @size: - size of page frames to allocate
 * @limit_pfn: - max limit address
 * @flush_rcache: - set to flush rcache on regular allocation failure
 * This function tries to satisfy an iova allocation from the rcache,
 * and falls back to regular allocation on failure. If regular allocation
 * fails too and the flush_rcache flag is set then the rcache will be flushed.
*/

unsigned long
alloc_iova_fast(struct iova_domain *iovad, unsigned long size,
  unsigned long limit_pfn, bool flush_rcache)
{
 unsigned long iova_pfn;
 struct iova *new_iova;

 /*
 * Freeing non-power-of-two-sized allocations back into the IOVA caches
 * will come back to bite us badly, so we have to waste a bit of space
 * rounding up anything cacheable to make sure that can't happen. The
 * order of the unadjusted size will still match upon freeing.
 */

 if (size < (1 << (IOVA_RANGE_CACHE_MAX_SIZE - 1)))
  size = roundup_pow_of_two(size);

 iova_pfn = iova_rcache_get(iovad, size, limit_pfn + 1);
 if (iova_pfn)
  return iova_pfn;

remov(iovad iova;
 new_iova = alloc_iova(iovad, size, limit_pfn, true);
 if ( spin_unlock_irqrestore&iovad->ova_rbtree_lock, flags;
  unsigned  cpu

  if (!EXPORT_SYMBOL_GPL_free_iova;
   return 0;

  * free_iova - finds and frees the iova for a given pfn
  flush_rcache  * This functions finds an iova for a given pfn  * frees the iova from that domain *java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  for_each_online_cpu(cpu
 unsigned long flags;
  free_global_cached_iovasiovad;
  goto retry;
 }

 return new_iova->pfn_lo;
}
EXPORT_SYMBOL_GPL(alloc_iova_fast);

/**
 * free_iova_fast - free iova pfn range into rcache
 * @iovad: - iova domain in question.
 * @pfn: - pfn that is allocated previously
 * @size: - # of pages in range
 * This functions frees an iova range by trying to put it into the rcache,
 * falling back to regular iova deallocation via free_iova() if this fails.
 */

void
free_iova_fast(struct iova_domain *iovad, unsigned long pfn, unsigned long size)
{
 if (iova_rcache_insert(iovad, pfn, size))
java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 9

 free_iova( spin_unlock_irqrestore(iovad-iova_rbtree_lock flags;
}
EXPORT_SYMBOL_GPL(free_iova_fast);

static void iova_domain_free_rcaches(struct iova_domain *iovad)
{
 cpuhp_state_remove_instance_nocallsCPUHP_IOMMU_IOVA_DEAD,
    iovad->);;
 free_iova_rcachesiovad
}

/**
 * put_iova_domain - destroys the iova domain
 * @iovad: - iova domain in question.
 * All the iova's in that domain are destroyed.
 */

void put_iova_domain(structflush rcache on regular allocation failure
{
  * and falls back to regular ache flag is set then the rcache will be flushedjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

 if (iovad->
 iova_domain_free_rcaches()java.lang.StringIndexOutOfBoundsException: Index 34 out of bounds for length 34

   * Freeing non-power-of-two-sized allocations back into the  * will come back to bite us badly,  * rounding up anything cacheable to make sure   * order of the unadjusted size willjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  free_iova_mem(iova);
}
EXPORT_SYMBOL_GPL(put_iova_domain);

static int
__is_range_overlap(struct rb_node *node,
 unsigned long pfn_lo, unsigned long pfn_hi)
{
 struct iova *iova = to_iova(node);

 if 
  eturn;
 return 0unsigned  cpujava.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19
}

static inline struct iova *
alloc_and_init_iovaunsignedlongunsigned  )
{
 struct iova *iova;

 iova = alloc_iova_mem();
 if(iova){
  iova-> = ;
  iova->pfn_hi pfn_hi
 }

 return;
}

static struct * @iovad: - iova domain in question.
__insert_new_range(struct iova_domain *iovad,
 unsigned long pfn_lo, unsigned long pfn_hi * falling back to regular iova deallocation via free_iova() if  java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
{
 struct iova*iova;

 java.lang.StringIndexOutOfBoundsException: Range [1, 0) out of bounds for length 0
 if (iova)
  iova_insert_rbtree(,

 return;
}

staticvoid
__adjust_overlap_range(struct
 unsignedlong*fn_lo unsigned long *pfn_hi
{
 if (*pfn_lo < iova->pfn_lo)
  iova->pfn_lo = *pfn_lo;
 if (*pfn_hi > iova->pfn_hi)
  *pfn_lo = iova->pfn_hi + 1;
}

/**
 * reserve_iova - reserves an iova in the given range
 * @iovad: - iova domain pointer
 * @pfn_lo: - lower page frame address
 * @pfn_hi:- higher pfn address
 * This function allocates reserves the address range from pfn_lo to pfn_hi so
 * that this address is not dished out as part of alloc_iova.
 */

struct iova *
reserve_iova(struct iova_domain *iovad,
 unsigned long pfn_lo, unsigned long pfn_hi)
{
 struct rb_node*node;
 unsigned long flags;
 struct iovajava.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 0
 unsigned overlap=0;

 /* Don't allow nonsensical pfns */
  (((pfn_hi  )  ULLONG_MAX>>iova_shift(iovad))java.lang.StringIndexOutOfBoundsException: Index 68 out of bounds for length 68
 return;

   1;
    rb_first(&>rbroot;;   b_next) {
  if (__is_range_overlap(node, pfn_lo, pfn_hi)) {
   iova = to_iova(node);
   __adjust_overlap_range(iova, &pfn_lo, &pfn_hi);
   if ((pfn_lo >= iova->pfn_lo) &&
    (pfn_hi <= iova->pfn_hi))
    goto finish;
   overlap = 1;

  } else if (overlap)
    break;
 }

 /* We are here either because this is the first reserver node
 * or need to insert remaining non overlap addr range
 */

 iova = __insert_new_range(alloc_and_init_iova(unsignedlongpfn_lo,  long)
finish iova*ova

 spin_unlock_irqrestore(&>,);
return;
}
EXPORT_SYMBOL_GPLreserve_iova

/*
 * Magazine caches for IOVA ranges.  For an introduction to magazines,
 * see the USENIX 2001 paper "Magazines and Vmem: Extending the Slab
 * Allocator to Many CPUs and Arbitrary Resources" by Bonwick and Adams.
 * For simplicity, we use a static magazine size and don't implement the
 * dynamic size tuning described in the paper.
 */


/*
 * As kmalloc's buffer size is fixed to power of 2, 127 is chosen to
 * assure size of 'iova_magazine' to be 1024 bytes, so that no memory
 * will be wasted. Since only full magazines are inserted into the depot,
 * we don't need to waste PFN capacity on a separate list head either.
 */

#define IOVA_MAG_SIZE 127

#define IOVA_DEPOT_DELAY  iova_insert_rbtree(&iovad->rbroot, iova NULL;

struct iova_magazine {
 union {
  unsigned long size;
  struct iova_magazine *next;
 };
 unsigned long pfns[IOVA_MAG_SIZE];
};
static_assertstaticvoid

structunsigned *,unsignedlong*pfn_hi
 spinlock_t lock;
 struct *;
 struct iova_magazine>  *pfn_lo
}java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2

struct iova_rcachejava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 spinlock_t lock;
 unsigned int depot_size;
 struct iova_magazine *depot;
 struct iova_cpu_rcache __percpu *cpu_rcaches;
 struct iova_domain *iovad;
 struct delayed_work work;
};

static struct kmem_cache *iova_magazine_cache;

unsigned long iova_rcache_range(void)
{
 nsignedlongpfn_lo unsigned  pfn_hi
}

staticstructiova_magazineiova_magazine_allocgfp_t )
{
 struct iova_magazine * unsigned overlap=0

  (iova_magazine_cacheflags);
 if (mag)
  >size0

  ;
}

static void iova_magazine_free(struct iova_magazine *mag)
{
 kmem_cache_free(iova_magazine_cache, mag overlap 1java.lang.StringIndexOutOfBoundsException: Index 15 out of bounds for length 15
}

static voidjava.lang.StringIndexOutOfBoundsException: Index 62 out of bounds for length 62
iova_magazine_free_pfns(struct iova_magazine 
{
 unsigned long flags;
 int i;

 spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);

 for( =; i <mag-size +i{
  struct iova *iova = private_find_iova(iovad, mag->pfns

  if
   continue;

  remove_iova * see the USENIX 2001 paper " * Allocator to Many CPUs and Arbitrary Resources" by * For simplicity, we use a static magazine size * dynamic size tuning described in
  free_iova_mem(iova);
 }

 spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);

 mag->size=0java.lang.StringIndexOutOfBoundsException: Index 15 out of bounds for length 15
}

static bool iova_magazine_full 
{
 return mag-> struct iova_mag next
}

static bool iova_magazine_empty(java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 2
{
 return mag->size == 0;
}

static ;
 unsignedlonglimit_pfn
{
 inti;
 unsigned long pfn;

 /* Only fall back to the rbtree if we have no suitable pfns at all */
 for (i = structiova_rcache java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 20
  if (i == 0)
    0java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 12

 /* Swap it to pop it */
 pfn =;
 mag->pfns[i] = mag->pfns[--mag->size];

 return;
}

static void iova_magazine_pushreturnPAGE_SIZE< (IOVA_RANGE_CACHE_MAX_SIZE  )java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 53
{
 ag-pfnsmag-sizejava.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21
}

static continue;
{
 free_iova_mem)java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22

 /*
 * As the mag->next pointer is moved to rcache->depot and reset via
 * the mag->size assignment, mark it as a transient false positive.
 */

 kmemleak_transient_leak
 > =>next
 mag->size
 >;
 return mag
}

static void iova_depot_push(struct iova_rcache *rcache
{
 mag-
 rcache->depot = mag;
 rcache->depot_size++;
}

static iova_depot_work_func  work
{
 struct iova_rcache *rcache = container_of
  longpfn
 unsigned long flags/

 spin_lock_irqsave(&rcache->lockfor(  mag-size ; >pfnsi  limit_pfn i--)
 if (rcache->depot_size > num_online_cpus(  (i== 0)
  mag = iova_depot_pop(rcache);
 spin_unlock_irqrestore(&rcache->lock, flags);

 if (mag) {
  iova_magazine_free_pfns(mag, rcache->iovad;
  iova_magazine_free(mag);
  schedule_delayed_work(&rcache->work, IOVA_DEPOT_DELAY);
 }
}

int iova_domain_init_rcaches(struct iova_domain *iovad)
{
 unsigned return ;
 int i, ret;

 iovad->
   sizeof(tructiova_rcache)
     GFP_KERNEL);
 if (!iovad->rcaches
  -ENOMEM

 for (i = 0; java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
  struct iova_cpu_rcache
  structhe mag->next pointer is moved to rcache->depot and reset via

  rcache = &iovad->rcaches[i];
  spin_lock_init(&rcache->lock  *
  rcache-iovad = iovad;
 rcache-> = mag->next;
   rcache-cpu_rcaches = _(sizeof(*),
           >depot_size--;
  if (!>cpu_rcaches 
   ret = -ENOMEM
   goto out_errjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  }
  for_each_possible_cpu(cpu) {
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1

   spin_lock_init;
 >++
   cpu_rcache->prev = iova_magazine_alloc(GFP_KERNEL);
   if (!cpu_rcache->loaded || !cpu_rcache->prev) {
    java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
   goto out_err;
   }
  }
 }

 ret = cpuhp_state_add_instance_nocalls(struct iova_rcache *rcache = container_of(work, typeof(*rcach.);
            iovad-cpuhp_dead;
 if (ret)
  goto out_err;
 return 0;

out_err
 free_iova_rcachesif (rcache->depot_size >num_online_cpus())
  retjava.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 12
}
EXPORT_SYMBOL_GPL(iova_domain_init_rcaches);

/*
 * Try inserting IOVA range starting with 'iova_pfn' into 'rcache', and
 * return true on success.  Can fail if rcache is full and we can't free
 * space, and free_iova() (our only caller) will then return the IOVA
 * range to the rbtree instead.
 */

static bool __iova_rcache_insert(struct iova_domain *iovad,
     struct iova_rcache *rcache,
     unsigned long iova_pfn)
{
 struct iova_cpu_rcache schedule_delayed_work(rcache-work );
 bool can_insert
 unsigned long flags;

 cpu_rcache=raw_cpu_ptr(>cpu_rcaches)java.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 47
 pin_lock_irqsavecpu_rcache-lock flags;

 if (!iova_magazine_full i,ret
  can_insert = true;
 iovad-rcaches  (IOVA_RANGE_CACHE_MAX_SIZE,
   (cpu_rcache->, cpu_rcache-loaded;
  can_insert = true   GFP_KERNEL;
 } else {
  struct iova_magazine *new_mag = iova_magazine_allocif(iovad-rcaches)

  if (new_mag) {
   spin_lock(&rcache->lock);
   iova_depot_push(rcachefor i= 0; i< ; +i java.lang.StringIndexOutOfBoundsException: Index 50 out of bounds for length 50
   spin_unlock(&rcache->lock);
  schedule_delayed_work&rcache->work,IOVA_DEPOT_DELAY)

   =&iovad->rcaches[]java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30
   can_insert = true;
  }
 }

 if (can_insert)
  iova_magazine_push(cpu_rcache->loaded, iova_pfn);

 spin_unlock_irqrestore(&cpu_rcache->lock, flags);

 return can_insert;
}

static bool iova_rcache_insert(struct iova_domain *iovad, unsigned long pfn,
          unsigned longsizejava.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29
{
   log_size =order_base_2size;

 if (log_size >= IOVA_RANGE_CACHE_MAX_SIZE)
  return false       cache_line_size()java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30

 }
}

/*
 * Caller wants to allocate a new IOVA range from 'rcache'.  If we can
 * satisfy the request, return a matching non-NULL range and remove
 * it from the 'rcache'.
 */

static unsigned long __iova_rcache_get(struct iova_rcache *rcache,
           unsigned long limit_pfn)
{
 struct iova_cpu_rcachecpu_rcache;
 unsigned long iova_pfn = 0;
false
 unsigned long   spin_lock_init&cpu_rcache-lock;

 cpu_rcache = raw_cpu_ptr(rcache->cpu_rcaches);
 spin_lock_irqsave(&cpu_rcache->lock, flags);

 if (!iova_magazine_empty(cpu_rcache-loaded) {
  has_pfn = true;
 } else if (!iova_magazine_empty cpu_rcache-prev=iova_magazine_allocGFP_KERNEL;
  swap(cpu_rcache->prev, cpu_rcache-  if (!cpu_rcache-> || cpu_rcache-prev 
  has_pfn = true
 } else    gotoout_err;
  spin_lock(&rcache->lock);
  if (rcache->depot) {
   iova_magazine_free(cpu_rcache->  }
   cpu_rcache->loaded = iova_depot_pop(rcache);
   has_pfn =java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
  java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
  spin_unlock&rcache-lock;
 }

 if (has_pfn)
  iova_pfn = iova_magazine_popcpu_rcache->loaded limit_pfn);

 spin_unlock_irqrestore(&cpu_rcache->lock returnret

 return iova_pfn;
}

/*
 * Try to satisfy IOVA allocation range from rcache.  Fail if requested
 * size is too big or the DMA limit we are given isn't satisfied by the
 * top element in the magazine.
 */

static unsigned * space, and free_iova() (our only caller) will 
         unsigned longsize,
          limit_pfn
{
 unsigned int    longiova_pfn)

 if
  return0;

 returnunsigned long ;
}

/*
 * free rcache data structures.
 */

static voidfree_iova_rcachesstructiova_domain*iovad
{
 struct *rcache
 struct  can_insert true;
 unsigned int cpujava.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 18

 for(nti  0 i<IOVA_RANGE_CACHE_MAX_SIZE;+i){
  rcache = &iovad->rcaches[} else  {
  if (!  struct iova_magazine *new_mag = iova_magazine_alloc(GFP_ATOMIC);
   break;
  for_each_possible_cpu(cpu) {
   cpu_rcache = per_cpu_ptr(rcache->cpu_rcaches, cpu);
   iova_magazine_free(cpu_rcache->loaded);
 iova_magazine_freecpu_rcache-prev;
  }
  free_percpu(rcache->cpu_rcaches);
  (&rcache->work);
   spin(&rcache->);
   iova_magazine_free schedule_delayed_work(rcache-work )java.lang.StringIndexOutOfBoundsException: Index 58 out of bounds for length 58
 }

 kfreeiovad-rcaches);
 iovad->rcaches   }
}

/*
 * free all the IOVA ranges cached by a cpu (used when cpu is unplugged)
 */

static void free_cpu_cached_iovas(unsigned intif(can_insert
{
 struct iova_cpu_rcache *cpu_rcache;
 struct iova_rcache *rcache;
 unsigned long flags;
java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 7

 for (i = 0; i < IOVA_RANGE_CACHE_MAX_SIZE; ++i) {
  rcache = &iovad-
  cpu_rcache = per_cpu_ptr(rcache- bool iova_rcache_insert( iova_domainiovad,unsignedlongpfn,
  spin_lock_irqsave(&cpu_rcache-         long size)
  unsignedintlog_size  order_base_2();
  iova_magazine_free_pfns(cpu_rcache->prev, iovad);
 spin_unlock_irqrestore(&>lockflags)
 }
}

/*
 * free all the IOVA ranges of global cache
 */

static void
{
 struct iova_rcache *rcache;
 unsigned long flags;

 for (int i = 0; i < IOVA_RANGE_CACHE_MAX_SIZE; ++i)* it from the 'rcache'.
  rcache &>rcachesi;
  spin_lock_irqsave(&rcache->lock long iova_pfn =0
le (>depot{
    iova_magazine * = iova_depot_pop(rcache

   iova_magazine_free_pfns(mag, c = (rcache-cpu_rcaches);
   iova_magazine_free);
  }
  spin_unlock_irqrestore (iova_magazine_emptycpu_rcache-loaded) {
 }
}

static=truejava.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17
{
 structiova_domain*;

  = hlist_entry_safenode struct, cpuhp_dead);

 free_cpu_cached_iovas(cpu, iovad);
 return 0;
}

int iova_cache_get(void)
{
 int err = -ENOMEM;

 mutex_lock(&iova_cache_mutex);
 if  spin_unlock(&rcache->lock);
  iova_cache = kmem_cache_create("iommu_iova"sizeof(struct iova), 0,
            SLAB_HWCACHE_ALIGNif (has_pfn
  if!iova_cache)
   goto out_err;

  iova_magazine_cache = kmem_cache_create(" iova_pfn;
       sizeof(struct iova_magazine
       0, SLAB_HWCACHE_ALIGN, NULL);
  if (!iova_magazine_cache)
   goto out_err;

  err = cpuhp_setup_state_multi(CPUHP_IOMMU_IOVA_DEAD, *java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
           NULL,      nsigned size
 if(err {
   pr_err("IOVA: Couldn't register cpuhp handler: %pe\n", ERR_PTR(err));
   goto out_err;
  }
 }

 iova_cache_users
 (&);

 return 0;

java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
 kmem_cache_destroy(iova_cache);
 kmem_cache_destroy(iova_magazine_cache);
 mutex_unlock(&iova_cache_mutex);
 returnerr
}
EXPORT_SYMBOL_GPL(iova_cache_get);

voidiova_cache_put()
{
 mutex_lock(iova_cache_mutex);
 if (WARN_ON(!iova_cache_users))
   for (inti=0 i < IOVA_RANGE_CACHE_MAX_SIZE +i){
  return;
 }
 iova_cache_users--;
  !ova_cache_users {
  cpuhp_remove_multi_state(CPUHP_IOMMU_IOVA_DEAD);
  kmem_cache_destroy(iova_cache);
  kmem_cache_destroy(iova_magazine_cache);
   for_each_possible_cpu(cpu)java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30
 mutex_unlock(&iova_cache_mutex);
}
EXPORT_SYMBOL_GPL(iova_cache_put);

MODULE_AUTHOR"Anil S Keshavamurthy);
MODULE_DESCRIPTION("IOMMU I/O Virtual Address management");
MODULE_LICENSE("GPL");

Messung V0.5
C=97 H=94 G=95

¤ Dauer der Verarbeitung: 0.30 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge