FD.io VPP  v16.09
Vector Packet Processing
linux_pci.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /*
16  * pci.c: Linux user space PCI bus management.
17  *
18  * Copyright (c) 2008 Eliot Dresselhaus
19  *
20  * Permission is hereby granted, free of charge, to any person obtaining
21  * a copy of this software and associated documentation files (the
22  * "Software"), to deal in the Software without restriction, including
23  * without limitation the rights to use, copy, modify, merge, publish,
24  * distribute, sublicense, and/or sell copies of the Software, and to
25  * permit persons to whom the Software is furnished to do so, subject to
26  * the following conditions:
27  *
28  * The above copyright notice and this permission notice shall be
29  * included in all copies or substantial portions of the Software.
30  *
31  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38  */
39 
40 #include <vlib/vlib.h>
41 #include <vlib/pci/pci.h>
42 #include <vlib/unix/unix.h>
43 
44 #include <sys/types.h>
45 #include <sys/stat.h>
46 #include <fcntl.h>
47 #include <dirent.h>
48 #include <sys/ioctl.h>
49 #include <net/if.h>
50 #include <linux/ethtool.h>
51 #include <linux/sockios.h>
52 
53 typedef struct
54 {
55  /* /sys/bus/pci/devices/... directory name for this device. */
57 
58  /* Resource file descriptors. */
60 
61  /* File descriptor for config space read/write. */
62  int config_fd;
63 
64  /* File descriptor for /dev/uio%d */
65  int uio_fd;
66 
67  /* Minor device for uio device. */
69 
70  /* Index given by unix_file_add. */
72 
74 
75 /* Pool of PCI devices. */
76 typedef struct
77 {
81 
83 
84 /* Call to allocate/initialize the pci subsystem.
85  This is not an init function so that users can explicitly enable
86  pci only when it's needed. */
88 
90  char *uio_driver_name);
91 
93 
95 vlib_pci_bind_to_uio (vlib_pci_device_t * d, char *uio_driver_name)
96 {
97  clib_error_t *error = 0;
98  u8 *s = 0;
99  DIR *dir = 0;
100  struct dirent *e;
101  int fd;
103  u8 *dev_dir_name = format (0, "/sys/bus/pci/devices/%U",
105 
106  c = &d->config0.header;
107 
108  /* if uio sub-directory exists, we are fine, device is
109  already bound to UIO driver */
110  s = format (s, "%v/uio%c", dev_dir_name, 0);
111  if (access ((char *) s, F_OK) == 0)
112  goto done;
113  vec_reset_length (s);
114 
115  /* walk trough all linux interfaces and if interface belonging to
116  this device is founf check if interface is admin up */
117  dir = opendir ("/sys/class/net");
118  s = format (s, "%U%c", format_vlib_pci_addr, &d->bus_address, 0);
119 
120  if (!dir)
121  {
122  error = clib_error_return (0, "Skipping PCI device %U: failed to "
123  "read /sys/class/net",
125  goto done;
126  }
127 
128  fd = socket (PF_INET, SOCK_DGRAM, 0);
129  if (fd < 0)
130  {
131  error = clib_error_return_unix (0, "socket");
132  goto done;
133  }
134 
135  while ((e = readdir (dir)))
136  {
137  struct ifreq ifr;
138  struct ethtool_drvinfo drvinfo;
139 
140  if (e->d_name[0] == '.') /* skip . and .. */
141  continue;
142 
143  memset (&ifr, 0, sizeof ifr);
144  memset (&drvinfo, 0, sizeof drvinfo);
145  ifr.ifr_data = (char *) &drvinfo;
146  strncpy (ifr.ifr_name, e->d_name, IFNAMSIZ - 1);
147  drvinfo.cmd = ETHTOOL_GDRVINFO;
148  if (ioctl (fd, SIOCETHTOOL, &ifr) < 0)
149  {
150  /* Some interfaces (eg "lo") don't support this ioctl */
151  if ((errno != ENOTSUP) && (errno != ENODEV))
152  clib_unix_warning ("ioctl fetch intf %s bus info error",
153  e->d_name);
154  continue;
155  }
156 
157  if (strcmp ((char *) s, drvinfo.bus_info))
158  continue;
159 
160  memset (&ifr, 0, sizeof (ifr));
161  strncpy (ifr.ifr_name, e->d_name, IFNAMSIZ - 1);
162  if (ioctl (fd, SIOCGIFFLAGS, &ifr) < 0)
163  {
164  error = clib_error_return_unix (0, "ioctl fetch intf %s flags",
165  e->d_name);
166  close (fd);
167  goto done;
168  }
169 
170  if (ifr.ifr_flags & IFF_UP)
171  {
172  error = clib_error_return (0, "Skipping PCI device %U as host "
173  "interface %s is up",
175  e->d_name);
176  close (fd);
177  goto done;
178  }
179  }
180 
181  close (fd);
182  vec_reset_length (s);
183 
184  s = format (s, "%v/driver/unbind%c", dev_dir_name, 0);
185  vlib_sysfs_write ((char *) s, "%U", format_vlib_pci_addr, &d->bus_address);
186  vec_reset_length (s);
187 
188  s = format (s, "/sys/bus/pci/drivers/%s/new_id%c", uio_driver_name, 0);
189  vlib_sysfs_write ((char *) s, "0x%04x 0x%04x", c->vendor_id, c->device_id);
190  vec_reset_length (s);
191 
192  s = format (s, "/sys/bus/pci/drivers/%s/bind%c", uio_driver_name, 0);
193  vlib_sysfs_write ((char *) s, "%U", format_vlib_pci_addr, &d->bus_address);
194 
195 done:
196  closedir (dir);
197  vec_free (s);
198  vec_free (dev_dir_name);
199  return error;
200 }
201 
202 
203 static clib_error_t *
204 scan_uio_dir (void *arg, u8 * path_name, u8 * file_name)
205 {
206  linux_pci_device_t *l = arg;
207  unformat_input_t input;
208 
209  unformat_init_string (&input, (char *) file_name, vec_len (file_name));
210 
211  if (!unformat (&input, "uio%d", &l->uio_minor))
212  abort ();
213 
214  unformat_free (&input);
215  return 0;
216 }
217 
218 static clib_error_t *
220 {
221  vlib_pci_main_t *pm = &pci_main;
223  int __attribute__ ((unused)) rv;
224 
225  u32 icount;
226  rv = read (uf->file_descriptor, &icount, 4);
227 
228  d = pool_elt_at_index (pm->pci_devs, uf->private_data);
229 
230  if (d->interrupt_handler)
231  d->interrupt_handler (d);
232 
234 
235  return /* no error */ 0;
236 }
237 
238 static clib_error_t *
240 {
241  u32 error_index = (u32) uf->private_data;
242 
243  return clib_error_return (0, "pci device %d: error", error_index);
244 }
245 
246 static void
248 {
249  vlib_pci_main_t *pm = &pci_main;
252 
253  pool_get (lpm->linux_pci_devices, l);
254  l[0] = pdev[0];
255 
257 
258  dev->os_handle = l - lpm->linux_pci_devices;
259 
260  {
261  u8 *uio_dir = format (0, "%s/uio", l->dev_dir_name);
262  foreach_directory_file ((char *) uio_dir, scan_uio_dir, l, /* scan_dirs */
263  1);
264  vec_free (uio_dir);
265  }
266 
267  {
268  char *uio_name = (char *) format (0, "/dev/uio%d%c", l->uio_minor, 0);
269  l->uio_fd = open (uio_name, O_RDWR);
270  if (l->uio_fd < 0)
271  clib_unix_error ("open `%s'", uio_name);
272  vec_free (uio_name);
273  }
274 
275  {
276  unix_file_t template = { 0 };
277  unix_main_t *um = &unix_main;
278 
279  template.read_function = linux_pci_uio_read_ready;
280  template.file_descriptor = l->uio_fd;
281  template.error_function = linux_pci_uio_error_ready;
282  template.private_data = dev - pm->pci_devs;
283 
284  l->unix_file_index = unix_file_add (um, &template);
285  }
286 }
287 
288 static void
290 {
291  int i;
292  for (i = 0; i < vec_len (l->resource_fds); i++)
293  if (l->resource_fds[i] > 0)
294  close (l->resource_fds[i]);
295  if (l->config_fd > 0)
296  close (l->config_fd);
297  if (l->uio_fd > 0)
298  close (l->uio_fd);
299  vec_free (l->resource_fds);
300  vec_free (l->dev_dir_name);
301 }
302 
303 /* Configuration space read/write. */
304 clib_error_t *
306  vlib_read_or_write_t read_or_write,
307  uword address, void *data, u32 n_bytes)
308 {
311  int n;
312 
314 
315  if (read_or_write == VLIB_READ)
316  n = pread (p->config_fd, data, n_bytes, address);
317  else
318  n = pwrite (p->config_fd, data, n_bytes, address);
319 
320  if (n != n_bytes)
321  return clib_error_return_unix (0, "%s",
322  read_or_write == VLIB_READ
323  ? "read" : "write");
324 
325  return 0;
326 }
327 
328 static clib_error_t *
330  u32 resource, u8 * addr, void **result)
331 {
334  struct stat stat_buf;
335  u8 *file_name;
336  int fd;
337  clib_error_t *error;
338  int flags = MAP_SHARED;
339 
340  error = 0;
341  p = pool_elt_at_index (pm->linux_pci_devices, os_handle);
342 
343  file_name = format (0, "%v/resource%d%c", p->dev_dir_name, resource, 0);
344  fd = open ((char *) file_name, O_RDWR);
345  if (fd < 0)
346  {
347  error = clib_error_return_unix (0, "open `%s'", file_name);
348  goto done;
349  }
350 
351  if (fstat (fd, &stat_buf) < 0)
352  {
353  error = clib_error_return_unix (0, "fstat `%s'", file_name);
354  goto done;
355  }
356 
357  vec_validate (p->resource_fds, resource);
358  p->resource_fds[resource] = fd;
359  if (addr != 0)
360  flags |= MAP_FIXED;
361 
362  *result = mmap (addr,
363  /* size */ stat_buf.st_size,
364  PROT_READ | PROT_WRITE, flags,
365  /* file */ fd,
366  /* offset */ 0);
367  if (*result == (void *) -1)
368  {
369  error = clib_error_return_unix (0, "mmap `%s'", file_name);
370  goto done;
371  }
372 
373 done:
374  if (error)
375  {
376  if (fd >= 0)
377  close (fd);
378  }
379  vec_free (file_name);
380  return error;
381 }
382 
383 clib_error_t *
384 vlib_pci_map_resource (vlib_pci_device_t * dev, u32 resource, void **result)
385 {
387  (dev->os_handle, resource, 0 /* addr */ ,
388  result));
389 }
390 
391 clib_error_t *
393  u32 resource, u8 * addr, void **result)
394 {
396  (dev->os_handle, resource, addr, result));
397 }
398 
399 void
401 {
404 
407  pool_put (pm->linux_pci_devices, l);
408 }
409 
410 pci_device_registration_t * __attribute__ ((unused))
412 {
413  uword i;
414 
415  /* Null vendor id marks end of initialized list. */
416  for (i = 0; r->supported_devices[i].vendor_id != 0; i++)
417  ;
418 
419  return clib_elf_section_data_next (r, i * sizeof (r->supported_devices[0]));
420 }
421 
422 static clib_error_t *
424  vlib_pci_device_t * dev,
425  linux_pci_device_t * pdev)
426 {
427  vlib_pci_main_t *pm = &pci_main;
431  clib_error_t *error;
432 
433  c = &dev->config0.header;
434 
435  r = pm->pci_device_registrations;
436 
437  while (r)
438  {
439  for (i = r->supported_devices; i->vendor_id != 0; i++)
440  if (i->vendor_id == c->vendor_id && i->device_id == c->device_id)
441  {
442  error = vlib_pci_bind_to_uio (dev, "uio_pci_generic");
443  if (error)
444  {
445  clib_error_report (error);
446  continue;
447  }
448 
449  add_device (dev, pdev);
450  dev->interrupt_handler = r->interrupt_handler;
451  return r->init_function (vm, dev);
452  }
453  r = r->next_registration;
454  }
455  /* No driver, close the PCI config-space FD */
456  close (pdev->config_fd);
457  return 0;
458 }
459 
460 static clib_error_t *
463 {
464  return init_device_from_registered (vm, dev, pdev);
465 }
466 
467 static clib_error_t *
468 scan_device (void *arg, u8 * dev_dir_name, u8 * ignored)
469 {
470  vlib_main_t *vm = arg;
471  vlib_pci_main_t *pm = &pci_main;
472  int fd;
473  u8 *f;
474  clib_error_t *error = 0;
475  vlib_pci_device_t *dev;
476  linux_pci_device_t pdev = { 0 };
477 
478  f = format (0, "%v/config%c", dev_dir_name, 0);
479  fd = open ((char *) f, O_RDWR);
480 
481  /* Try read-only access if write fails. */
482  if (fd < 0)
483  fd = open ((char *) f, O_RDONLY);
484 
485  if (fd < 0)
486  {
487  error = clib_error_return_unix (0, "open `%s'", f);
488  goto done;
489  }
490 
491  pool_get (pm->pci_devs, dev);
492 
493  /* You can only read more that 64 bytes of config space as root; so we try to
494  read the full space but fall back to just the first 64 bytes. */
495  if (read (fd, &dev->config_data, sizeof (dev->config_data)) !=
496  sizeof (dev->config_data)
497  && read (fd, &dev->config0,
498  sizeof (dev->config0)) != sizeof (dev->config0))
499  {
500  pool_put (pm->pci_devs, dev);
501  error = clib_error_return_unix (0, "read `%s'", f);
502  close (fd);
503  goto done;
504  }
505 
506  {
507  static pci_config_header_t all_ones;
508  if (all_ones.vendor_id == 0)
509  memset (&all_ones, ~0, sizeof (all_ones));
510 
511  if (!memcmp (&dev->config0.header, &all_ones, sizeof (all_ones)))
512  {
513  pool_put (pm->pci_devs, dev);
514  error = clib_error_return (0, "invalid PCI config for `%s'", f);
515  close (fd);
516  goto done;
517  }
518  }
519 
520  if (dev->config0.header.header_type == 0)
522  else
524 
525  /* Parse bus, dev, function from directory name. */
526  {
527  unformat_input_t input;
528 
529  unformat_init_string (&input, (char *) dev_dir_name,
530  vec_len (dev_dir_name));
531 
532  if (!unformat (&input, "/sys/bus/pci/devices/%U",
534  abort ();
535 
536  unformat_free (&input);
537 
538  }
539 
540 
541  pdev.config_fd = fd;
542  pdev.dev_dir_name = dev_dir_name;
543 
545  dev - pm->pci_devs);
546 
547  error = init_device (vm, dev, &pdev);
548 
549  vec_reset_length (f);
550  f = format (f, "%v/vpd%c", dev_dir_name, 0);
551  fd = open ((char *) f, O_RDONLY);
552  if (fd >= 0)
553  {
554  while (1)
555  {
556  u8 tag[3];
557  u8 *data = 0;
558  int len;
559 
560  if (read (fd, &tag, 3) != 3)
561  break;
562 
563  if (tag[0] != 0x82 && tag[0] != 0x90 && tag[0] != 0x91)
564  break;
565 
566  len = (tag[2] << 8) | tag[1];
567  vec_validate (data, len);
568 
569  if (read (fd, data, len) != len)
570  {
571  vec_free (data);
572  break;
573  }
574  if (tag[0] == 0x82)
575  dev->product_name = data;
576  else if (tag[0] == 0x90)
577  dev->vpd_r = data;
578  else if (tag[0] == 0x91)
579  dev->vpd_w = data;
580 
581  data = 0;
582  }
583  close (fd);
584  }
585 
586  vec_reset_length (f);
587  f = format (f, "%v/driver%c", dev_dir_name, 0);
588  dev->driver_name = vlib_sysfs_link_to_name ((char *) f);
589 
590  dev->numa_node = -1;
591  vec_reset_length (f);
592  f = format (f, "%v/numa_node%c", dev_dir_name, 0);
593  vlib_sysfs_read ((char *) f, "%u", &dev->numa_node);
594 
595 done:
596  vec_free (f);
597  return error;
598 }
599 
600 clib_error_t *
602 {
603  vlib_pci_main_t *pm = &pci_main;
604  clib_error_t *error;
605 
606  pm->vlib_main = vm;
607 
608  if ((error = vlib_call_init_function (vm, unix_input_init)))
609  return error;
610 
611  ASSERT (sizeof (vlib_pci_addr_t) == sizeof (u32));
612  pm->pci_dev_index_by_pci_addr = hash_create (0, sizeof (uword));
613 
614  error = foreach_directory_file ("/sys/bus/pci/devices", scan_device, vm,
615  /* scan_dirs */ 0);
616 
617  /* Complain and continue. might not be root, etc. */
618  if (error)
619  clib_error_report (error);
620 
621  return error;
622 }
623 
625 
626 /*
627  * fd.io coding-style-patch-verification: ON
628  *
629  * Local Variables:
630  * eval: (c-set-style "gnu")
631  * End:
632  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:396
u8 * vpd_w
Definition: pci.h:80
static clib_error_t * os_map_pci_resource_internal(uword os_handle, u32 resource, u8 *addr, void **result)
Definition: linux_pci.c:329
format_function_t format_vlib_pci_addr
Definition: pci.h:232
#define hash_set(h, key, value)
Definition: hash.h:254
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
u8 * vlib_sysfs_link_to_name(char *link)
Definition: util.c:166
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:966
static void linux_pci_device_free(linux_pci_device_t *l)
Definition: linux_pci.c:289
static clib_error_t * init_device(vlib_main_t *vm, vlib_pci_device_t *dev, linux_pci_device_t *pdev)
Definition: linux_pci.c:461
pci_config_type1_regs_t config1
Definition: pci.h:64
pci_device_registration_t * pci_device_registrations
Definition: pci.h:112
vlib_read_or_write_t
Definition: defs.h:54
clib_error_t * vlib_pci_bind_to_uio(vlib_pci_device_t *d, char *uio_driver_name)
Definition: linux_pci.c:95
#define clib_error_report(e)
Definition: error.h:125
unformat_function_t unformat_vlib_pci_addr
Definition: pci.h:231
static void add_device(vlib_pci_device_t *dev, linux_pci_device_t *pdev)
Definition: linux_pci.c:247
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:200
vlib_pci_addr_t bus_address
Definition: pci.h:58
static uword unix_file_add(unix_main_t *um, unix_file_t *template)
Definition: unix.h:136
int numa_node
Definition: pci.h:75
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
u8 * product_name
Definition: pci.h:78
static void pci_config_type1_little_to_host(pci_config_type1_regs_t *r)
Definition: pci_config.h:346
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
clib_error_t * foreach_directory_file(char *dir_name, clib_error_t *(*f)(void *arg, u8 *path_name, u8 *file_name), void *arg, int scan_dirs)
Definition: util.c:49
uword * pci_dev_index_by_pci_addr
Definition: pci.h:113
clib_error_t * vlib_pci_map_resource_fixed(vlib_pci_device_t *dev, u32 resource, u8 *addr, void **result)
Definition: linux_pci.c:392
static void unformat_free(unformat_input_t *i)
Definition: format.h:161
struct _pci_device_registration pci_device_registration_t
clib_error_t * vlib_pci_read_write_config(vlib_pci_device_t *dev, vlib_read_or_write_t read_or_write, uword address, void *data, u32 n_bytes)
Definition: linux_pci.c:305
vlib_main_t * vlib_main
Definition: linux_pci.c:78
void unformat_init_string(unformat_input_t *input, char *string, int string_len)
Definition: unformat.c:1017
static clib_error_t * init_device_from_registered(vlib_main_t *vm, vlib_pci_device_t *dev, linux_pci_device_t *pdev)
Definition: linux_pci.c:423
#define vlib_call_init_function(vm, x)
Definition: init.h:161
static clib_error_t * linux_pci_uio_read_ready(unix_file_t *uf)
Definition: linux_pci.c:219
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:369
u32 file_descriptor
Definition: unix.h:52
uword private_data
Definition: unix.h:59
vlib_pci_device_t * pci_devs
Definition: pci.h:111
#define clib_error_return_unix(e, args...)
Definition: error.h:114
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:214
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:334
void(* interrupt_handler)(struct vlib_pci_device *dev)
Definition: pci.h:69
static clib_error_t * vlib_pci_intr_enable(vlib_pci_device_t *dev)
Definition: pci.h:170
clib_error_t * linux_pci_init(vlib_main_t *vm)
Definition: linux_pci.c:601
void vlib_pci_free_device(vlib_pci_device_t *dev)
Definition: linux_pci.c:400
static void pci_config_type0_little_to_host(pci_config_type0_regs_t *r)
Definition: pci_config.h:272
svmdb_client_t * c
static clib_error_t * unix_input_init(vlib_main_t *vm)
Definition: input.c:242
vlib_pci_main_t pci_main
Definition: pci.c:53
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:300
#define clib_unix_warning(format, args...)
Definition: error.h:68
u8 config_data[256]
Definition: pci.h:65
clib_error_t * vlib_sysfs_write(char *file_name, char *fmt,...)
Definition: util.c:102
pci_config_type0_regs_t config0
Definition: pci.h:63
#define hash_create(elts, value_bytes)
Definition: hash.h:647
#define clib_elf_section_data_next(a, extra)
Definition: elf_clib.h:57
clib_error_t * vlib_sysfs_read(char *file_name, char *fmt,...)
Definition: util.c:126
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
static clib_error_t * scan_device(void *arg, u8 *dev_dir_name, u8 *ignored)
Definition: linux_pci.c:468
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:418
clib_error_t * pci_bus_init(vlib_main_t *vm)
Definition: pci.c:167
static clib_error_t * scan_uio_dir(void *arg, u8 *path_name, u8 *file_name)
Definition: linux_pci.c:204
clib_error_t * vlib_pci_map_resource(vlib_pci_device_t *dev, u32 resource, void **result)
Definition: linux_pci.c:384
unix_main_t unix_main
Definition: main.c:57
#define clib_unix_error(format, args...)
Definition: error.h:65
u64 uword
Definition: types.h:112
Definition: defs.h:56
linux_pci_main_t linux_pci_main
Definition: linux_pci.c:92
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
Definition: unix.h:49
pci_device_registration_t * pci_device_next_registered(pci_device_registration_t *r)
Definition: linux_pci.c:411
u16 device_id
Definition: pci.h:89
static clib_error_t * linux_pci_uio_error_ready(unix_file_t *uf)
Definition: linux_pci.c:239
uword os_handle
Definition: pci.h:56
vhost_vring_addr_t addr
Definition: vhost-user.h:82
#define clib_error_return(e, args...)
Definition: error.h:111
struct _unformat_input_t unformat_input_t
u32 flags
Definition: vhost-user.h:76
u8 * vpd_r
Definition: pci.h:79
linux_pci_device_t * linux_pci_devices
Definition: linux_pci.c:79
vlib_main_t * vlib_main
Definition: pci.h:110
u8 * driver_name
Definition: pci.h:72
pci_config_header_t header
Definition: pci_config.h:240
u16 vendor_id
Definition: pci.h:89