On 4/20/22 11:09 AM, Juergen Gross wrote:
>
> +/*
> + * xenbus_setup_ring
> + * @dev: xenbus device
> + * @vaddr: pointer to starting virtual address of the ring
> + * @nr_pages: number of pages to be granted
> + * @grefs: grant reference array to be filled in
> + *
> + * Allocate physically contiguous pages for a shared ring buffer and grant it
> + * to the peer of the given device. The ring buffer is initially filled with
> + * zeroes. The virtual address of the ring is stored at @vaddr and the
> + * grant references are stored in the @grefs array. In case of error @vaddr
> + * will be set to NULL and @grefs will be filled with INVALID_GRANT_REF.
> + */
> +int xenbus_setup_ring(struct xenbus_device *dev, gfp_t gfp, void **vaddr,
> + unsigned int nr_pages, grant_ref_t *grefs)
> +{
> + unsigned long ring_size = nr_pages * XEN_PAGE_SIZE;
> + unsigned int i;
> + int ret;
> +
> + *vaddr = alloc_pages_exact(ring_size, gfp | __GFP_ZERO);
> + if (!*vaddr) {
> + ret = -ENOMEM;
> + goto err;
> + }
> +
> + ret = xenbus_grant_ring(dev, *vaddr, nr_pages, grefs);
> + if (ret)
> + goto err;
> +
> + return 0;
> +
> + err:
> + if (*vaddr)
> + free_pages_exact(*vaddr, ring_size);
> + for (i = 0; i < nr_pages; i++)
> + grefs[i] = INVALID_GRANT_REF;
> + *vaddr = NULL;
> +
> + return ret;
> +}
We can create a wrapper around this function that will also call SHARED_RING_INIT() and FRONT_RING_INIT(). A bunch of drivers do that.
-boris
On 20.04.22 20:44, Boris Ostrovsky wrote:
>
> On 4/20/22 11:09 AM, Juergen Gross wrote:
>> +/*
>> + * xenbus_setup_ring
>> + * @dev: xenbus device
>> + * @vaddr: pointer to starting virtual address of the ring
>> + * @nr_pages: number of pages to be granted
>> + * @grefs: grant reference array to be filled in
>> + *
>> + * Allocate physically contiguous pages for a shared ring buffer and grant it
>> + * to the peer of the given device. The ring buffer is initially filled with
>> + * zeroes. The virtual address of the ring is stored at @vaddr and the
>> + * grant references are stored in the @grefs array. In case of error @vaddr
>> + * will be set to NULL and @grefs will be filled with INVALID_GRANT_REF.
>> + */
>> +int xenbus_setup_ring(struct xenbus_device *dev, gfp_t gfp, void **vaddr,
>> + unsigned int nr_pages, grant_ref_t *grefs)
>> +{
>> + unsigned long ring_size = nr_pages * XEN_PAGE_SIZE;
>> + unsigned int i;
>> + int ret;
>> +
>> + *vaddr = alloc_pages_exact(ring_size, gfp | __GFP_ZERO);
>> + if (!*vaddr) {
>> + ret = -ENOMEM;
>> + goto err;
>> + }
>> +
>> + ret = xenbus_grant_ring(dev, *vaddr, nr_pages, grefs);
>> + if (ret)
>> + goto err;
>> +
>> + return 0;
>> +
>> + err:
>> + if (*vaddr)
>> + free_pages_exact(*vaddr, ring_size);
>> + for (i = 0; i < nr_pages; i++)
>> + grefs[i] = INVALID_GRANT_REF;
>> + *vaddr = NULL;
>> +
>> + return ret;
>> +}
>
>
> We can create a wrapper around this function that will also call
> SHARED_RING_INIT() and FRONT_RING_INIT(). A bunch of drivers do that.
This wrapper would need to be a macro, so I decided not to do that.
It would make sense to merge the call of SHARED_RING_INIT() into
FRONT_RING_INIT() (or better, have a new macro combining the two),
though, as there is no use case of FRONT_RING_INIT() without a
call of SHARED_RING_INIT() directly before it.
Juergen