Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

xen/xenbus: add xenbus_setup_ring() service function

Most PV device frontends share very similar code for setting up shared
ring buffers:

- allocate page(s)
- init the ring admin data
- give the backend access to the ring via grants

Tearing down the ring requires similar actions in all frontends again:

- remove grants
- free the page(s)

Provide service functions xenbus_setup_ring() and xenbus_teardown_ring()
for that purpose.

Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Signed-off-by: Juergen Gross <jgross@suse.com>

+73
+69
drivers/xen/xenbus/xenbus_client.c
··· 407 407 } 408 408 EXPORT_SYMBOL_GPL(xenbus_grant_ring); 409 409 410 + /* 411 + * xenbus_setup_ring 412 + * @dev: xenbus device 413 + * @vaddr: pointer to starting virtual address of the ring 414 + * @nr_pages: number of pages to be granted 415 + * @grefs: grant reference array to be filled in 416 + * 417 + * Allocate physically contiguous pages for a shared ring buffer and grant it 418 + * to the peer of the given device. The ring buffer is initially filled with 419 + * zeroes. The virtual address of the ring is stored at @vaddr and the 420 + * grant references are stored in the @grefs array. In case of error @vaddr 421 + * will be set to NULL and @grefs will be filled with INVALID_GRANT_REF. 422 + */ 423 + int xenbus_setup_ring(struct xenbus_device *dev, gfp_t gfp, void **vaddr, 424 + unsigned int nr_pages, grant_ref_t *grefs) 425 + { 426 + unsigned long ring_size = nr_pages * XEN_PAGE_SIZE; 427 + unsigned int i; 428 + int ret; 429 + 430 + *vaddr = alloc_pages_exact(ring_size, gfp | __GFP_ZERO); 431 + if (!*vaddr) { 432 + ret = -ENOMEM; 433 + goto err; 434 + } 435 + 436 + ret = xenbus_grant_ring(dev, *vaddr, nr_pages, grefs); 437 + if (ret) 438 + goto err; 439 + 440 + return 0; 441 + 442 + err: 443 + if (*vaddr) 444 + free_pages_exact(*vaddr, ring_size); 445 + for (i = 0; i < nr_pages; i++) 446 + grefs[i] = INVALID_GRANT_REF; 447 + *vaddr = NULL; 448 + 449 + return ret; 450 + } 451 + EXPORT_SYMBOL_GPL(xenbus_setup_ring); 452 + 453 + /* 454 + * xenbus_teardown_ring 455 + * @vaddr: starting virtual address of the ring 456 + * @nr_pages: number of pages 457 + * @grefs: grant reference array 458 + * 459 + * Remove grants for the shared ring buffer and free the associated memory. 460 + * On return the grant reference array is filled with INVALID_GRANT_REF. 461 + */ 462 + void xenbus_teardown_ring(void **vaddr, unsigned int nr_pages, 463 + grant_ref_t *grefs) 464 + { 465 + unsigned int i; 466 + 467 + for (i = 0; i < nr_pages; i++) { 468 + if (grefs[i] != INVALID_GRANT_REF) { 469 + gnttab_end_foreign_access(grefs[i], 0); 470 + grefs[i] = INVALID_GRANT_REF; 471 + } 472 + } 473 + 474 + if (*vaddr) 475 + free_pages_exact(*vaddr, nr_pages * XEN_PAGE_SIZE); 476 + *vaddr = NULL; 477 + } 478 + EXPORT_SYMBOL_GPL(xenbus_teardown_ring); 410 479 411 480 /** 412 481 * Allocate an event channel for the given xenbus_device, assigning the newly
+4
include/xen/xenbus.h
··· 226 226 int xenbus_switch_state(struct xenbus_device *dev, enum xenbus_state new_state); 227 227 int xenbus_grant_ring(struct xenbus_device *dev, void *vaddr, 228 228 unsigned int nr_pages, grant_ref_t *grefs); 229 + int xenbus_setup_ring(struct xenbus_device *dev, gfp_t gfp, void **vaddr, 230 + unsigned int nr_pages, grant_ref_t *grefs); 231 + void xenbus_teardown_ring(void **vaddr, unsigned int nr_pages, 232 + grant_ref_t *grefs); 229 233 int xenbus_map_ring_valloc(struct xenbus_device *dev, grant_ref_t *gnt_refs, 230 234 unsigned int nr_grefs, void **vaddr); 231 235