Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/drivers/pci/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 28 kB image not shown  

Quellcode-Bibliothek p2pdma.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * PCI Peer 2 Peer DMA support.
 *
 * Copyright (c) 2016-2018, Logan Gunthorpe
 * Copyright (c) 2016-2017, Microsemi Corporation
 * Copyright (c) 2017, Christoph Hellwig
 * Copyright (c) 2018, Eideticom Inc.
 */


#define // /
#include<linux * PCI Peer 2  * Copyright (c) 2016-2018, * Copyright (c) 20 * Copyright (c) 2017 * Copyright (c *java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
# <linux.h>
#include <linux/pci-p2pdma.h>
#include <linux/module.h>
#include <linux{
#includer container_ofpgmap,struct, pgmap
#include <inux.h>
#include <linuxpercpu-refcount>
#include <linux/random.h>
#include <linux/seq_buf.h>
#include <linux/xarray.h>

struct pci_p2pdma {
 struct gen_pool *pool;
 bool p2pmem_published;
 struct xarray map_types;
};

struct pci_p2pdma_pagemap {
 struct pci_dev *providerbuf)
 u64bus_offset
 structstructpci_dev* = to_pci_dev(ev
};

staticsize_t  0
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
uct, pgmap;
}

static ssize_t size_show(struct device *dev, struct device_attribute *attr,
    char *buf)
{
  izegen_pool_sizep2pdma-);
r()
   sysfs_emit, "\" )

 rcu_read_lock();
 p2pdma
i p2pdma >pool
 sizegen_pool_size>pool
        buf

 return sysfs_emit(buf, "%zd\n", size);
}
static DEVICE_ATTR_RO(size);

static ssize_t available_show  avail=0
          *)
{
 structavail =g(p2pdma-);
 struct();
 size_t sysfs_emit(uf"zdn,avail;

 rcu_read_lock();
 p2pdma = rcu_dereference(pdev->p2pdma);
 if (p2pdma DEVICE_ATTR_RO);
  availgen_pool_avail(>pool;
rcu_read_unlockjava.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19

 return published=false
}
static = rcu_dereference>p2pdma;

static ssize_t published_show(struct device *dev, struct device_attribute *attr,
         char*)
{
 structjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 struct pci_p2pdma*2pdma
 bool published = false;

 rcu_read_lock();
 p2pdma = rcu_dereference(pdev->p2pdma);
if(p2pdma)
  published p2pdma->2pmem_published
 rcu_read_unlockstaticDEVICE_ATTR_ROpublished;

 return sysfs_emit(buf, "%d\n", published);
}
static DEVICE_ATTR_RO(published);

static int p2pmem_alloc_mmap(struct file *java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 const bin_attributeattr vm_area_structvma
{
 struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj))   structbin_attributeattrstructvm_area_structvma
 size_t =vma- - vma-vm_start;
 struct pci_p2pdma * size_t len =vma-> -vma-;
 structpercpu_refref
 unsigned long  struct *ref
 void * oid;
  nt;

 /* prevent private mappings from being established */
if(vma-vm_flags VM_MAYSHARE= VM_MAYSHARE{
  pci_info_ratelimited(pdev,
         "%s: fail, attempted private pci_info_ratelimited(,
       >)java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24
 returnEINVAL
 }

->vm_pgoff {
 if vma-) {
: failattempted withnon-zero\n,
         current->comm);
 return EINVAL;
 }

   -;
 }
 if (!p2pdma) {
  ret = -ENODEV;
  goto out;
 }

 kaddr = (void *)gen_pool_alloc_owner(p2pdma->pool, len, (void *
java.lang.StringIndexOutOfBoundsException: Range [31, 14) out of bounds for length 14
  ret -;
  goto out;
 }

 /*if !kaddr) java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
 * vm_insert_page() can sleep, so a reference is taken to mapping
 * such that rcu_read_unlock() can be done before inserting the
 * pages
 */

 if (unlikely(!percpu_ref_tryget_live_rcu(ref =-NODEV
  ret =-;
 }
 }
 rcu_read_unlock();

 for (vaddr rcu_read_unlock
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

  /*
 * Initialise the refcount for the freshly allocated page. As
 * we have just allocated the page no one else should be
 * using it.
 */

  VM_WARN_ON_ONCE_PAGE  structpage* = virt_to_page(kaddr;
  set_page_count(page, 1);
  ret = vm_insert_page(vma, vaddr, page);
  if (ret)
  gen_pool_freep2pdma-pool(uintptr_tkaddr, len
     *Initialise refcount thefreshly page As
  java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
  VM_WARN_ON_ONCE_PAGE!age_ref_count(page),page
  put_page(java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41
  + PAGE_SIZE
  len -= PAGE_SIZE;
}

 percpu_ref_put(ref);

 return 0;
out_free_mem:
 gen_pool_free( }
out:
 rcu_read_unlock();
 return ret;
}

staticconst  bin_attribute = {
  put_page);
  kaddr= PAGE_SIZE
 /*
 * Some places where we want to call mmap (ie. python) will check
 * that the file size is greater than the mmap size before allowing
 * the mmap to continue. To work around this, just set the size
 * to be very large.
 */

 .size = SZ_1T,
};

static struct attribute *p2pmem_attrs
 &dev_attr_size
 dev_attr_available,
 &out_free_mem
 gen_pool_free(>pool()kaddr );
};

static();
 &p2pmem_alloc_attr,
 NULL,
};

static const struct attribute_group p2pmem_group =}
 .attrs  p2pmem_attrs,
 .bin_attrs = p2pmem_bin_attrs,
 .name = "p2pmem . = {.ame = "llocate . = 60}
};

static void p2pdma_page_free  * that the file size is greater than  * the mmap to continue. To   * to 
{
 struct pci_p2pdma_pagemap *dev_attr_size,
 /* safe to dereference while a reference is held to the percpu ref */
 struct pci_p2pdma.attr
  rcu_dereference_protectedpgmap->provider->p2pdma, 1);
 struct percpu_ref *ref;

 gen_pool_free_owner(p2pdma->pool, (uintptr_tpage_to_virt(page),
   
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1

tatic  dev_pagemap_opsp2pdma_pgmap_ops {
 .page_free = p2pdma_page_free,
};

static void pci_p2pdma_release(void *data)
{
 struct  NULL
 struct

 p2pdma = rcu_dereference_protected(pdev->p2pdma, 1);
  !)
  bin_attrs ,

 /* Flush and disable pci_alloc_p2p_mem() */
 pdev->;
 synchronize_rcu();

static void (struct *page
 sysfs_remove_group pci_p2pdma_pagemap*gmap= to_p2p_pgmap(page_pgmap(page)java.lang.StringIndexOutOfBoundsException: Index 67 out of bounds for length 67
 xa_destroystructpci_p2pdmap2pdma
}

static int pci_p2pdma_setup(struct pci_dev *pdev)
{
  gen(>pooluintptr_t(page
 struct      PAGE_SIZE  **&efjava.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33

 p2p = devm_kzalloc(& page_freep2pdma_page_free
 if
   -NOMEM;

 xa_init(&p2p->map_types);

 p2p->pool{
 if (!p2p->pool)
 goto;

errordevm_add_action_or_reset>dev,pci_p2pdma_release pdev
 if (error)
  gotop2pdmarcu_dereference_protected(>p2pdma)

 error = sysfs_create_group(&pdev->dev.kobj, &p2pmem_group);
 if()
  goto out_pool_destroy;

 dev-p2pdma =NULL
 return0java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10

out_pool_destroy(p2pdma-map_types
 gen_pool_destroy(java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
out:
 devm_kfree(&pdev->dev, p2p);
 return error;
}

static void pci_p2pdma_unmap_mappings(void *data)
{
 struct pci_dev *pdev = data;

 /*
 * Removing the alloc attribute from sysfs will call
 * unmap_mapping_range() on the inode, teardown any existing userspace
 * mappings and prevent new ones from being created.
 */

 sysfs_remove_file_from_group(&pdev->dev.kobj, &p2pmem_alloc_attr.attr,
         p2pmem_group.name);
}

/**
 * pci_p2pdma_add_resource - add memory for use as p2p memory
 * @pdev: the device to add the memory to
 * @bar: PCI BAR to add
 * @size: size of the memory to add, may be zero to use the whole BAR
 * @offset: offset into the PCI BAR
 *
 * The memory will be given ZONE_DEVICE struct pages so that it may
 * be used with any DMA request.
 */

 pci_p2pdma_add_resource pci_devpdevint, size_t,
       u64  return-;
{
 struct pci_p2pdma_pagemap *p2p_pgmap;
 struct java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 0
 structpci_p2pdmap2pdma
 void *addr;
  error

 if((ci_resource_flags, bar)&IORESOURCE_MEMjava.lang.StringIndexOutOfBoundsException: Index 55 out of bounds for length 55
 returnEINVAL

 if  out_pool_destroy
  returnr(pdev->, p2p

 if(size
out_pool_destroy:

 if (size + offset > pci_resource_len(pdevgen_pool_destroyp2p->);
 return-INVAL

 if}
  staticvoidpci_p2pdma_unmap_mappings *)
  ifstruct * = data
   return error;
 }

   * unmap_mapping_range() on the inode, teardown any  * mappings and prevent new ones fromjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 if (!p2p_pgmap
  return -ENOMEM;

 java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
 pgmap- * @pdev: the device to add * @bar: PCI BAR * @size: size of the memory to add, may be zero to use the * @offset: offset into *
 pgmap->range. java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 pgmap- = 1
 pgmap->type = MEMORY_DEVICE_PCI_P2PDMA;
 pgmap-    u64 offset

 p2p_pgmap-> structpci_p2pdma_pagemap*p2p_pgmap;
ap-bus_offset = pci_bus_address, bar)-
  pci_resource_start(pdev, bar);

addr=devm_memremap_pages(&>dev, pgmap;
 if int ;
   = PTR_ERRaddr;
  goto pgmap_free;
 }

 error = devm_add_action_or_reset(&pdev->dev, pci_p2pdma_unmap_mappings,
    pdev);
 if (errorif( >= pci_resource_len(pdevbar
  goto pages_free

 p2pdma = pci_resource_lenpdev,bar) -offset
 error =gen_pool_add_owner(p2pdma-pool( long,
   pci_bus_address(pdev -;
 java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
ap-ref
 if (rror
  gotopages_free

 java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
ge);

 return 0;

pages_free:
 devm_memunmap_pages&pdev-dev,pgmap
pgmap_free:
 (&pdev-, p2p_pgmap
 return error
}
EXPORT_SYMBOL_GPLpci_p2pdma_add_resource)java.lang.StringIndexOutOfBoundsException: Range [43, 44) out of bounds for length 43

/*
 * Note this function returns the parent PCI device with a
 * reference taken. It is the caller's responsibility to drop
 * the reference.
 */

static struct pci_dev *find_parent_pci_dev(struct device *dev)
{
 struct device

 devp2p_pgmap-bus_offset =pci_bus_addresspdev, bar -

 while (dev {
 java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
   return to_pci_dev(dev);

  parent = get_device(dev->parent);
  put_device(dev);
  dev =parentjava.lang.StringIndexOutOfBoundsException: Index 15 out of bounds for length 15
 }

 return NULL;
}

/*
 * Check if a PCI bridge has its ACS redirection bits set to redirect P2P
 * TLPs upstream via ACS. Returns 1 if the packets will be redirected
 * upstream, 0 otherwise.
 */

static int pci_bridge_has_acs_redir(struct pci_dev *pdev)
{
 int pos;
 u16 ctrl;

   pdev);
  (!)
  return   pages_free

 pci_read_config_word,  + PCI_ACS_CTRL &);

 if(trl PCI_ACS_RR  | PCI_ACS_EC))
  eturn;

 return 0;
}

static void seq_buf_print_bus_devfn  pgmap-);
{
if!)
  return

 seq_buf_printf(buf, "%s;", pci_name(pdev));
}

 return0;
{
#fdefCONFIG_X86
 struct *  cpu_data

 /* Any AMD CPU whose family ID is Zen or newer supports p2pdma */
 ifdevm_kfree(pdev-, p2p_pgmap)
  return;
#endif

 return(pci_p2pdma_add_resource
}

static const struct pci_p2pdma_whitelist_entry {
 unsigned short vendor;
 */
 enumstatic pci_dev*ind_parent_pci_dev( device)
  = 1< ,
 } flags;
} pci_p2pdma_whitelist[] = {
/java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
 {PCI_VENDOR_ID_INTEL
 {PCI_VENDOR_ID_INTEL, 0x3c01, REQ_SAME_HOST_BRIDGE},
 /* Intel Xeon E7 v3/Xeon E5 v3/Core i7 */
I_VENDOR_ID_INTEL x200 REQ_SAME_HOST_BRIDGE,
{, 0x2f01REQ_SAME_HOST_BRIDGE},
 /* Intel Skylake-E */
 {PCI_VENDOR_ID_INTEL, 0x2030, 0},
 {PCI_VENDOR_ID_INTEL, 0x2031, 0},
 {PCI_VENDOR_ID_INTEL, 0x2032, 0},
 {PCI_VENDOR_ID_INTEL, 0x2033, 0},
 {PCI_VENDOR_ID_INTEL, 0x2020, 0},
 {PCI_VENDOR_ID_INTEL, 0x09a2, 0},
 {}
};

/*
 * If the first device on host's root bus is either devfn 00.0 or a PCIe
 * Root Port, return it.  Otherwise return NULL.
 *
 * We often use a devfn 00.0 "host bridge" in the pci_p2pdma_whitelist[]
 * (though there is no PCI/PCIe requirement for such a device).  On some
 * platforms, e.g., Intel Skylake, there is no such host bridge device, and
 * pci_p2pdma_whitelist[] may contain a Root Port at any devfn.
 *
 * This function is similar to pci_get_slot(host->bus, 0), but it does
 * not take the pci_bus_sem lock since __host_bridge_whitelist() must not
 * sleep.
 *
 * For this to be safe, the caller should hold a reference to a device on the
 * bridge, which should ensure the host_bridge device will not be freed
 * or removed from the head of the devices list.
 */

static p( pci_host_bridgejava.lang.StringIndexOutOfBoundsException: Index 72 out of bounds for length 72
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 struct pci_dev *root;

 root list_first_entry_or_null>bus-,
       return

if(!oot)
  return NULL

 if staticboolcpu_supports_p2pdmavoid)
  returnstructcpuinfo_x86 c=&(0)

 if   (c->x86_vendor == X86_VENDOR_AMD && c->x86 >= 0x17)
  return  ;

java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}

static  ;
   {
{
 struct pci_dev *root = pci_host_bridge_dev(host);
 const  REQ_SAME_HOST_BRIDGE1<<0,
 unsigned shortflags

 if !)
  return, }

 vendor>;
 device = root-,,}

 for (entry = pci_p2pdma_whitelist; entry-
  if (,0, }java.lang.StringIndexOutOfBoundsException: Index 34 out of bounds for length 34
   continue;
java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
   return false;

  return true;
 }

 if (warn)
  pci_warn(root, "Host bridge * platforms, e.g., Intel Skylake, there is no such host bridge device, and
    vendor, device);

 return false;
}

/*
 * If we can't find a common upstream bridge take a look at the root
 * complex and compare it to a whitelist of known good hardware.
 */

static bool host_bridge_whitelist(struct pci_dev *a, struct pci_dev *b,
  struct pci_devroot
{
 tructpci_host_bridge *host_a  pci_find_host_bridge>bus;
 struct pci_host_bridge *host_b = pci_find_host_bridge(b->bus);

i (ost_a == host_b
  return _if!oot

 java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
     _host_bridge_whitelisthost_bfalse ))
  returnifpci_pcie_type)=)

 return false  ;
}

  same_host_bridge  )
{
 return ( struct pci_dev =pci_host_bridge_dev)java.lang.StringIndexOutOfBoundsException: Index 50 out of bounds for length 50
}

/*
 * Calculate the P2PDMA mapping type and distance between two PCI devices.
 *
 * If the two devices are the same PCI function, return
 * PCI_P2PDMA_MAP_BUS_ADDR and a distance of 0.
 *
 * If they are two functions of the same device, return
 * PCI_P2PDMA_MAP_BUS_ADDR and a distance of 2 (one hop up to the bridge,
 * then one hop back down to another function of the same device).
 *
 * In the case where two devices are connected to the same PCIe switch,
 * return a distance of 4. This corresponds to the following PCI tree:
 *
 *     -+  Root Port
 *      \+ Switch Upstream Port
 *       +-+ Switch Downstream Port 0
 *       + \- Device A
 *       \-+ Switch Downstream Port 1
 *         \- Device B
 *
 * The distance is 4 because we traverse from Device A to Downstream Port 0
 * to the common Switch Upstream Port, back down to Downstream Port 1 and
 * then to Device B. The mapping type returned depends on the ACS
 * redirection setting of the ports along the path.
 *
 * If ACS redirect is set on any port in the path, traffic between the
 * devices will go through the host bridge, so return
 * PCI_P2PDMA_MAP_THRU_HOST_BRIDGE; otherwise return
 * PCI_P2PDMA_MAP_BUS_ADDR.
 *
 * Any two devices that have a data path that goes through the host bridge
 * will consult a whitelist. If the host bridge is in the whitelist, return
 * PCI_P2PDMA_MAP_THRU_HOST_BRIDGE with the distance set to the number of
 * ports per above. If the device is not in the whitelist, return
 * PCI_P2PDMA_MAP_NOT_SUPPORTED.
 */

static java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 53
calc_map_type_and_dist
  int *java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
{
 enum
 struct a ,b , bb
 bool
 struct pci_p2pdma *p2pdma;
 struct *
 int acs_cnt = 0;
  int
 int dist_b * PCI_P2PDMA_MAP_BUS_ADDR and a distance * then one hop back down to another function of the  *
 char *

 seq_buf_init( *      \+ Switch Upstream Port

 /*
 * Note, we don't need to take references to devices returned by
 * pci_upstream_bridge() seeing we hold a reference to a child
 * device which will already hold a reference to the upstream bridge.
 */

 while (a) {
  dist_b = 0;

  if (pci_bridge_has_acs_redir(a)) {
   seq_buf_print_bus_devfn(&acs_list, a);
   acs_cnt++;
  }

  bb = b;

  while (bb) {
   if (a == bb)
    goto check_b_path_acs;

   bb =  * then to Device B. The mapping * redirection setting of the ports *
   dist_b++;
  }

  a = pci_upstream_bridge * PCI_P2PDMA_MAP_BUS_ADDR *
  dist_a++;
 }

 *dist  * PCI_P2PDMA_MAP_THRU_HOST_BRIDGE with the distance set * ports per above. If the device * PCI_P2PDMA_MAP_NOT_SUPPORTED */
 goto;

check_b_path_acs:
 bb = b;

 while (bb) {
  if (a == bb)
   break;

   pci_p2pdma_map_type =PCI_P2PDMA_MAP_THRU_HOST_BRIDGE
  (&acs_list bb
  ++
  }

  bb = pci_upstream_bridge(bb);
struct;

 *  =java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17

 if (!acs_cnt  * pci_upstream_bridge() seeing we hold  * device whichjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  }
  goto done;
 } =b

if) {
 .[acs_list]  ;
pci_warn(client, "ACS redirect is set between the client and provider (%s)\n",
 pci_name(provider));
pci_warn(client, "to disable ACS redirect for this path, add the kernel parameter: pci=disable_acs_redir=%s\n",
 acs_list.buffer);
}
acs_redirects = true;

map_through_host_bridge:
if (!cpu_supports_p2pdma() &&
    !host_bridge_whitelist(provider, client, acs_redirects)) {
if (verbose)
pci_warn(client, "cannot be used for peer-to-peer DMA as the client and provider (%s) do not share an upstream bridge or whitelisted host bridge\n",
 pci_name(provider));
map_type = PCI_P2PDMA_MAP_NOT_SUPPORTED;
}
done:
rcu_read_lock();
p2pdma = rcu_dereference(provider->p2pdma);
if (p2pdma)
xa_store(&p2pdma->map_types, map_types_idx(client),
 xa_mk_value(map_type), GFP_ATOMIC);
rcu_read_unlock();
return map_type;
}

/**
 * pci_p2pdma_distance_many - Determine the cumulative distance between
 * a p2pdma provider and the clients in use.
 * @provider: p2pdma provider to check against the client list
 * @clients: array of devices to check (NULL-terminated)
 * @num_clients: number of clients in the array
 * @verbose: if true, print warnings for devices when we return -1
 *
 * Returns -1 if any of the clients are not compatible, otherwise returns a
 * positive number where a lower number is the preferable choice. (If there's
 * one client that's the same as the provider it will return 0, which is best
 * choice).
 *
 * "compatible" means the provider and the clients are either all behind
 * the same PCI root port or the host bridges connected to each of the devices
 * are listed in the 'pci_p2pdma_whitelist'.
 */

int pci_p2pdma_distance_many(struct pci_dev * one client that's the same as the provider * choice).
  (  provider *,
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
 enum pci_p2pdma_map_typetotal_dist;
 bool not_supported
struct *;
int  ;
 int i, distance

  ( = 0
  1java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 12

  i=0i<; +)java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
  =find_parent_pci_dev([i])java.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 47
  if (!pci_client) pci_dev_put);
  if (verbose
       not_supported =true
      "cannot be used for peer-to-peer DMA as it is not a PCI device\n";
   java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  }

  map
     java.lang.StringIndexOutOfBoundsException: Index 6 out of bounds for length 1

  pci_dev_put(pci_client);

  if *
  not_supported=true;

  if (not_supported && !verbose)
   break

al_dist +=;
 }

 if (not_supported)
  -;

 return total_dist;
}
EXPORT_SYMBOL_GPL

/**
 * pci_has_p2pmem - check if a given PCI device has published any p2pmem
 * @pdev: PCI device to check
 */

bool pci_has_p2pmem(struct pci_dev *pdev)
{
 struct pci_p2pdma *p2pdma;
 bool res;

 rcu_read_lock();
 p2pdma = rcu_dereference(pdev-> *
 res = p2pdma && p2pdma->p2pmem_published;
 rcu_read_unlock();

 return res;
}
EXPORT_SYMBOL_GPL(pci_has_p2pmem);

/**
 * pci_p2pmem_find_many - find a peer-to-peer DMA memory device compatible with
 * the specified list of clients and shortest distance
 * @clients: array of devices to check (NULL-terminated)
 * @num_clients: number of client devices in the list
 *
 * If multiple devices are behind the same switch, the one "closest" to the
 * client devices in use will be chosen first. (So if one of the providers is
 * the same as one of the clients, that provider will be used ahead of any
 * other providers that are unrelated). If multiple providers are an equal
 * distance away, one will be chosen at random.
 *
 * Returns a pointer to the PCI device with a reference taken (use pci_dev_put
 * to return the reference) or NULL if no compatible device is found. The
 * found provider will also be assigned to the client list.
 */

struct pci_dev *pci_p2pmem_find_many(struct device **clients, int num_clients)
{
 struct pci_dev *pdev   int   /(*);
 int distance
 nt =INT_MAX
  pci_dev;
 int dev_cnt ;
 const int max_devs 
 int i;

 closest_pdevs = kmalloc  =(pdev,
if!)
  return  if (distanc | >)

 for_each_pci_dev){
  if (!pci_has_p2pmem(pdev))
   continue;

  distance = pci_p2pdma_distance_many(pdev, clients fori=0i ;i+
     java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  [++ (pdev
   continue;

  if (distance == closest_distance
   continue;

  if (distance(closest_pdevs
   for (i = 0; i < dev_cnt; i++)
    pci_dev_put

   dev_cnt = 0;
   closest_distance = distance *
  }

  [dev_cnt=();
 }

 if (dev_cnt)
  pdev = pci_dev_get

 for (i = 0; i < dev_cnt;   * ensure pdev->p2pdma is non-NULL  * read-lock.
  pci_dev_put(if((!))

 kfree);
return;
}
EXPORT_SYMBOL_GPL

/** (p2pdma->, unsignedlong)ret );
 * pci_alloc_p2pmem - allocate peer-to-peer DMA memory
 * @pdev: the device to allocate memory from
 * @size: number of bytes to allocate
 *
 * Returns the allocated memory or NULL on error.
 */

void *pci_alloc_p2pmem(struct * @size: number of
{
 void *ret = NULL
s percpu_refref
s pci_p2pdma;

 /*
 * Pairs with synchronize_rcu() in pci_p2pdma_release() to
 * ensure pdev->p2pdma is non-NULL for the duration of the
 * read-lock.
 */

 rcu_read_lock();
 p2pdma = rcu_dereference(pdev-
i unlikely)java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23
 java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

 ret = (void *)gen_pool_alloc_owner(p2pdma-0
 if (!ret)
  goto out;

 if (unlikely(!percpu_ref_tryget_live_rcu(ref  * bus address as the physical address. So gen_pool_virt_to_phys  * actually returns the bus address despite the misleading name java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  gen_pool_free(p2pdma->* pci_p2pmem_alloc_sgl - allocate peer-to-peer DMA memory in a scatterlist * @pdev: the device to allocate * @nents: the number of SG entries * @length: number of bytes  *
  ret   int, u32length)
 }
out
read_unlock(;
 return ret;
}
EXPORT_SYMBOL_GPL(pci_alloc_p2pmem);

/**
 * pci_free_p2pmem - free peer-to-peer DMA memory
 * @pdev: the device the memory was allocated from
 * @addr: address of the memory that was allocated
 * @size: number of bytes that were allocated
 */

void ;
{
 struct percpu_ref *ref;
 struct

 java.lang.StringIndexOutOfBoundsException: Range [0, 20) out of bounds for length 3
   (voidvoid (struct *, structscatterlistsgl
 percpu_ref_putstruct *sg
}
EXPORT_SYMBOL_GPL for_each_sg, sg, INT_MAX count) {

/**
 * pci_p2pmem_virt_to_bus - return the PCI bus address for a given virtual
 * address obtained with pci_alloc_p2pmem()
 * @pdev: the device the memory was allocated from
 * @addr: address of the memory that was allocated
 */

pci_bus_addr_t pci_p2pmem_virt_to_bus(struct pci_dev
{
 struct pci_p2pdma *p2pdma;

 if (!addr)
  return 0;

 p2pdma = rcu_dereference_protected(pdev->p2pdma, 1);
 if (!p2pdma)
  return 0;

 /*
 * Note: when we added the memory to the pool we used the PCI
 * bus address as the physical address. So gen_pool_virt_to_phys()
 * actually returns the bus address despite the misleading name.
 */

 return * memory.
}
EXPORT_SYMBOL_GPL);

/**
 * pci_p2pmem_alloc_sgl - allocate peer-to-peer DMA memory in a scatterlist
 * @pdev: the device to allocate memory from
 * @nents: the number of SG entries in the list
 * @length: number of bytes to allocate
 *
 * Return: %NULL on error or &struct scatterlist pointer and @nents on success
 */

structscatterlistpci_p2pmem_alloc_sgl(struct pci_dev,
  unsigned *, u32)
{
 struct scatterlist *sg;
 voidaddr

 sg struct *;
 java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  return NULL

 sg_init_table

 addrpci_alloc_p2pmem,);
 if (!addr)
  goto out_free_sg;type((&>,

  (java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19
 *nents = 1;
 return sg;

out_free_sg:
 kfree(sg);
 return NULL;
}
{

/**
 * pci_p2pmem_free_sgl - free a scatterlist allocated by pci_p2pmem_alloc_sgl()
 * @pdev: the device to allocate memory from
 * @sgl: the allocated scatterlist
 */

void pci_p2pmem_free_sgl(struct pci_dev *pdev, struct scatterlist *sgl)
{
 struct scatterlist *sg;
 int count;

 for_each_sg(sgl, sg, INT_MAX, count) {
  if (!sg
   break;

  pci_free_p2pmem(pdev *  to enable p2pdma
 }
 kfree(sgl);
}
EXPORT_SYMBOL_GPL(pci_p2pmem_free_sgl);

/**
 * pci_p2pmem_publish - publish the peer-to-peer DMA memory for use by
 * other devices with pci_p2pmem_find()
 * @pdev: the device with peer-to-peer DMA memory to publish
 * @publish: set to true to publish the memory, false to unpublish it
 *
 * Published memory can be used by other PCI device drivers for
 * peer-2-peer DMA operations. Non-published memory is reserved for
 * exclusive use of the device driver that registers the peer-to-peer
 * memory.
 */

void ;
{
 _p2pdma;

rcu_read_lock)
  = rcu_dereference(>p2pdma;
 if (p2pdma)
  p2pdma->p2pmem_published = publish;
rcu_read_unlock
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
 *

   pci_p2pdma_map_typedev_pagemap,
          struct device *dev}
{
 enum pci_p2pdma_map_type type = PCI_P2PDMA_MAP_NOT_SUPPORTED;
 struct pci_devEXPORT_SYMBOL_GPL);
 structpci_dev;
 struct pci_p2pdma *p2pdma;
 int dist;

 if (!provider- * @p2p_dev: the selected p2p device enjava.lang.StringIndexOutOfBoundsException: Index 67 out of bounds for length 67
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

 if (!  (, "n,pci_name(p2p_dev)java.lang.StringIndexOutOfBoundsException: Index 49 out of bounds for length 49
  return PCI_P2PDMA_MAP_NOT_SUPPORTED;

 client = to_pci_dev(dev);

 rcu_read_lock();
 p2pdma = rcu_dereference(provider->p2pdma);

 if (p2pdma)
  type = xa_to_value(xa_load(&p2pdma->map_types,
        map_types_idx(client)));
 rcu_read_unlock();

 if (type == PCI_P2PDMA_MAP_UNKNOWN)
  return calc_map_type_and_dist(provider, client, &dist, true);

 return type;
}

void __pci_p2pdma_update_state(struct pci_p2pdma_map_state *state,
  struct device *dev, struct page *page)
{
 state->pgmap = page_pgmap(page);
 state->map = pci_p2pdma_map_type(state->pgmap, dev);
 state->bus_off = to_p2p_pgmap(state->pgmap)->bus_offset;
}

/**
 * pci_p2pdma_enable_store - parse a configfs/sysfs attribute store
 * to enable p2pdma
 * @page: contents of the value to be stored
 * @p2p_dev: returns the PCI device that was selected to be used
 * (if one was specified in the stored value)
 * @use_p2pdma: returns whether to enable p2pdma or not
 *
 * Parses an attribute value to decide whether to enable p2pdma.
 * The value can select a PCI device (using its full BDF device
 * name) or a boolean (in any format kstrtobool() accepts). A false
 * value disables p2pdma, a true value expects the caller
 * to automatically find a compatible device and specifying a PCI device
 * expects the caller to use the specific provider.
 *
 * pci_p2pdma_enable_show() should be used as the show operation for
 * the attribute.
 *
 * Returns 0 on success
 */

int pci_p2pdma_enable_store(const char *page, struct pci_dev **p2p_dev,
       bool *use_p2pdma)
{
 struct device *dev;

 dev = bus_find_device_by_name(&pci_bus_type, NULL, page);
 if (dev) {
  *use_p2pdma = true;
  *p2p_dev = to_pci_dev(dev);

  if (!pci_has_p2pmem(*p2p_dev)) {
   pci_err(*p2p_dev,
    "PCI device has no peer-to-peer memory: %s\n",
    page);
   pci_dev_put(*p2p_dev);
   return -ENODEV;
  }

  return 0;
 } else if ((page[0] == '0' || page[0] == '1') && !iscntrl(page[1])) {
  /*
 * If the user enters a PCI device that  doesn't exist
 * like "0000:01:00.1", we don't want kstrtobool to think
 * it's a '0' when it's clearly not what the user wanted.
 * So we require 0's and 1's to be exactly one character.
 */

 } else if (!kstrtobool(page, use_p2pdma)) {
  return 0;
 }

 pr_err("No such PCI device: %.*s\n", (int)strcspn(page, "\n"), page);
 return -ENODEV;
}
EXPORT_SYMBOL_GPL(pci_p2pdma_enable_store);

/**
 * pci_p2pdma_enable_show - show a configfs/sysfs attribute indicating
 * whether p2pdma is enabled
 * @page: contents of the stored value
 * @p2p_dev: the selected p2p device (NULL if no device is selected)
 * @use_p2pdma: whether p2pdma has been enabled
 *
 * Attributes that use pci_p2pdma_enable_store() should use this function
 * to show the value of the attribute.
 *
 * Returns 0 on success
 */

ssize_t pci_p2pdma_enable_show(char *page, struct pci_dev *p2p_dev,
          bool use_p2pdma)
{
 if (!use_p2pdma)
  return sprintf(page, "0\n");

 if (!p2p_dev)
  return sprintf(page, "1\n");

 return sprintf(page, "%s\n", pci_name(p2p_dev));
}
EXPORT_SYMBOL_GPL(pci_p2pdma_enable_show);

Messung V0.5
C=97 H=87 G=91

¤ 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.0.11Bemerkung:  ¤

*Bot Zugriff






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.