Subject: Re: [PATCH v3 06/10] VAS: Define helpers to alloc/free windows

From: Michael Neuling <[email-masked]>
Date: Fri, 24 Mar 2017 19:59:19 +1100

On Thu, 2017-03-16 at 20:33 -0700, Sukadev Bhattiprolu wrote:
> Define helpers to allocate/free VAS window objects. These will
> be used in follow-on patches when opening/closing windows.
> 
> Signed-off-by: Sukadev Bhattiprolu <[email-masked]>
> ---
>  drivers/misc/vas/vas-window.c | 74 +++++++++++++++++++++++++++++++++++++++++-
> -
>  1 file changed, 72 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/misc/vas/vas-window.c b/drivers/misc/vas/vas-window.c
> index edf5c9f..9233bf5 100644
> --- a/drivers/misc/vas/vas-window.c
> +++ b/drivers/misc/vas/vas-window.c
> @@ -119,7 +119,7 @@ static void unmap_wc_mmio_bars(struct vas_window *window)
>   * OS/User Window Context (UWC) MMIO Base Address Region for the given
> window.
>   * Map these bus addresses and save the mapped kernel addresses in @window.
>   */
> -int map_wc_mmio_bars(struct vas_window *window)
> +static int map_wc_mmio_bars(struct vas_window *window)
>  {
>  	int len;
>  	uint64_t start;
> @@ -472,8 +472,78 @@ int init_winctx_regs(struct vas_window *window, struct
> vas_winctx *winctx)
>  	return 0;
>  }
>  
> -/* stub for now */
> +DEFINE_SPINLOCK(vas_ida_lock);
> +
> +void vas_release_window_id(struct ida *ida, int winid)
> +{
> +	spin_lock(&vas_ida_lock);
> +	ida_remove(ida, winid);
> +	spin_unlock(&vas_ida_lock);
> +}
> +
> +int vas_assign_window_id(struct ida *ida)
> +{
> +	int rc, winid;
> +
> +	rc = ida_pre_get(ida, GFP_KERNEL);
> +	if (!rc)
> +		return -EAGAIN;
> +
> +	spin_lock(&vas_ida_lock);
> +	rc = ida_get_new_above(ida, 0, &winid);
> +	spin_unlock(&vas_ida_lock);
> +
> +	if (rc)
> +		return rc;
> +
> +	if (winid > VAS_MAX_WINDOWS_PER_CHIP) {
> +		pr_err("VAS: Too many (%d) open windows\n", winid);
> +		vas_release_window_id(ida, winid);
> +		return -EAGAIN;
> +	}
> +
> +	return winid;
> +}
> +
> +static void vas_window_free(struct vas_window *window)
> +{
> +	unmap_wc_mmio_bars(window);
> +	kfree(window->paste_addr_name);
> +	kfree(window);
> +}
> +
> +static struct vas_window *vas_window_alloc(struct vas_instance *vinst, int
> id)
> +{
> +	struct vas_window *window;
> +
> +	window = kzalloc(sizeof(*window), GFP_KERNEL);
> +	if (!window)
> +		return NULL;
> +
> +	window->vinst = vinst;
> +	window->winid = id;
> +
> +	if (map_wc_mmio_bars(window))
> +		goto out_free;
> +
> +	return window;
> +
> +out_free:
> +	kfree(window);
> +	return NULL;
> +}
> +
>  int vas_window_reset(struct vas_instance *vinst, int winid)
> 

This interface seems a little weird to me. Needing an alloc in a hardware reset
path seems a bit strange.

Maybe the data structures are the issue.  A window is a hardware construct. 
Something that uses it should probably be called something else like a context. 
Something that references a window should just be the vas_instance + winid. 

You should be able to reset this hardware window by referencing structures
already allocated.  Something associated with the struct vas_instance.

Mikey

>  {
> +	struct vas_window *window;
> +
> +	window = vas_window_alloc(vinst, winid);
> +	if (!window)
> +		return -ENOMEM;
> +
> +	reset_window_regs(window);
> +
> +	vas_window_free(window);
> +
>  	return 0;
>  }