[PATCH 1/3] gpu: host1x: Add syncpoint base support

Thierry Reding thierry.reding at gmail.com
Fri Oct 11 11:39:06 CEST 2013


On Wed, Oct 09, 2013 at 02:54:08PM +0300, Arto Merilainen wrote:
> This patch adds support for hardware syncpoint bases. This creates
> a simple mechanism for waiting an operation to complete in the middle
> of the command buffer.

Perhaps "... simple mechanism to stall the command FIFO until an
operation is completed." That's what the TRM contains and more
accurately describes the hardware functionality.

> diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h
[...]
> @@ -26,6 +26,7 @@
>  #include "cdma.h"
>  #include "job.h"
>  
> +struct host1x_base;

host1x_syncpt_base is more explicit, host1x_base sounds very generic.

> diff --git a/drivers/gpu/host1x/hw/channel_hw.c b/drivers/gpu/host1x/hw/channel_hw.c
> index ee19962..5f9f735 100644
> --- a/drivers/gpu/host1x/hw/channel_hw.c
> +++ b/drivers/gpu/host1x/hw/channel_hw.c
> @@ -67,6 +67,21 @@ static void submit_gathers(struct host1x_job *job)
>  	}
>  }
>  
> +static inline void synchronize_syncpt_base(struct host1x_job *job)
> +{
> +	struct host1x_channel *ch = job->channel;
> +	struct host1x *host = dev_get_drvdata(ch->dev->parent);
> +	struct host1x_syncpt *sp = host->syncpt + job->syncpt_id;
> +	u32 base_id = sp->base->id;
> +	u32 base_val = host1x_syncpt_read_max(sp);
> +
> +	host1x_cdma_push(&ch->cdma,
> +			 host1x_opcode_setclass(HOST1X_CLASS_HOST1X,
> +				host1x_uclass_load_syncpt_base_r(), 1),
> +			 host1x_uclass_load_syncpt_base_base_indx_f(base_id) |
> +			 host1x_uclass_load_syncpt_base_value_f(base_val));

Please use the all-caps version of the register definitions. The
lowercase variants were only introduced to allow profiling and coverage
testing, which I think nobody's been doing and I'm in fact thinking
about removing them.

> diff --git a/drivers/gpu/host1x/syncpt.c b/drivers/gpu/host1x/syncpt.c
[...]
> +static struct host1x_base *host1x_base_alloc(struct host1x *host)
> +{
> +	struct host1x_base *base = host->bases;
> +	int i;

unsigned int

> +
> +	for (i = 0; i < host->info->nb_bases && base->reserved; i++, base++)
> +		;

I'd like to see this rewritten as:

	for (i = 0; i < host->info->nb_bases; i++) {
		if (!host->bases[i].reserved)
			break;
	}

> +static void host1x_base_free(struct host1x_base *base)
> +{
> +	if (!base)
> +		return;
> +	base->reserved = false;
> +}

The following would be somewhat shorter:

	if (base)
		base->reserved = false;

>  static struct host1x_syncpt *_host1x_syncpt_alloc(struct host1x *host,
>  						  struct device *dev,
> -						  bool client_managed)
> +						  bool client_managed,
> +						  bool support_base)

I think at this point we probably want to introduce a flags argument
instead of adding all those boolean parameters. Something like:

	#define HOST1X_SYNCPT_CLIENT_MANAGED	(1 << 0)
	#define HOST1X_SYNCPT_HAS_BASE		(1 << 1)

	struct host1x_syncpt *host1x_syncpt_alloc(struct host1x *host,
						  struct device *dev,
						  unsigned long flags);

>  int host1x_syncpt_init(struct host1x *host)
>  {
>  	struct host1x_syncpt *syncpt;
> +	struct host1x_base *bases;
>  	int i;
>  
> +	bases = devm_kzalloc(host->dev, sizeof(*bases) * host->info->nb_bases,
> +		GFP_KERNEL);
>  	syncpt = devm_kzalloc(host->dev, sizeof(*syncpt) * host->info->nb_pts,
>  		GFP_KERNEL);

I'd prefer these to be checked separately. Also the argument alignment
is wrong here. Align with the first function argument. And for
consistency, allocate bases after syncpoints...

> -	if (!syncpt)
> +	if (!syncpt || !bases)
>  		return -ENOMEM;
>  
> -	for (i = 0; i < host->info->nb_pts; ++i) {
> +	for (i = 0; i < host->info->nb_bases; i++)
> +		bases[i].id = i;
> +
> +	for (i = 0; i < host->info->nb_pts; i++) {
>  		syncpt[i].id = i;
>  		syncpt[i].host = host;
>  	}

... and initialize them after the syncpoints...

>  
>  	host->syncpt = syncpt;
> +	host->bases = bases;

... to match the assignment order.

> @@ -332,7 +368,14 @@ struct host1x_syncpt *host1x_syncpt_request(struct device *dev,
>  					    bool client_managed)
>  {
>  	struct host1x *host = dev_get_drvdata(dev->parent);
> -	return _host1x_syncpt_alloc(host, dev, client_managed);
> +	return _host1x_syncpt_alloc(host, dev, client_managed, false);
> +}
> +
> +struct host1x_syncpt *host1x_syncpt_request_based(struct device *dev,
> +						  bool client_managed)
> +{
> +	struct host1x *host = dev_get_drvdata(dev->parent);
> +	return _host1x_syncpt_alloc(host, dev, client_managed, true);
>  }

If we add a flags parameter to host1x_syncpt_request() (and
host1x_syncpt_alloc()) then we don't need the separate function.

> diff --git a/drivers/gpu/host1x/syncpt.h b/drivers/gpu/host1x/syncpt.h
> index 267c0b9..852dc76 100644
> --- a/drivers/gpu/host1x/syncpt.h
> +++ b/drivers/gpu/host1x/syncpt.h
> @@ -30,6 +30,11 @@ struct host1x;
>  /* Reserved for replacing an expired wait with a NOP */
>  #define HOST1X_SYNCPT_RESERVED			0
>  
> +struct host1x_base {
> +	u8 id;
> +	bool reserved;

Perhaps name this to something like "requested". "reserved" makes it
sound like it's reserved for some special use.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20131011/e6b775cf/attachment.pgp>


More information about the dri-devel mailing list