diff options
Diffstat (limited to 'drivers/gpu/host1x/hw')
| -rw-r--r-- | drivers/gpu/host1x/hw/channel_hw.c | 60 | ||||
| -rw-r--r-- | drivers/gpu/host1x/hw/hw_host1x06_uclass.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/host1x/hw/hw_host1x07_uclass.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/host1x/hw/hw_host1x08_uclass.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/host1x/hw/intr_hw.c | 74 | ||||
| -rw-r--r-- | drivers/gpu/host1x/hw/syncpt_hw.c | 3 | 
6 files changed, 55 insertions, 88 deletions
diff --git a/drivers/gpu/host1x/hw/channel_hw.c b/drivers/gpu/host1x/hw/channel_hw.c index 732abe0750ff..d44b8de890be 100644 --- a/drivers/gpu/host1x/hw/channel_hw.c +++ b/drivers/gpu/host1x/hw/channel_hw.c @@ -179,14 +179,12 @@ static inline void synchronize_syncpt_base(struct host1x_job *job)  static void host1x_channel_set_streamid(struct host1x_channel *channel)  {  #if HOST1X_HW >= 6 -	u32 sid = 0x7f; -#ifdef CONFIG_IOMMU_API -	struct iommu_fwspec *spec = dev_iommu_fwspec_get(channel->dev->parent); -	if (spec) -		sid = spec->ids[0] & 0xffff; -#endif +	u32 stream_id; + +	if (!tegra_dev_iommu_get_stream_id(channel->dev->parent, &stream_id)) +		stream_id = TEGRA_STREAM_ID_BYPASS; -	host1x_ch_writel(channel, sid, HOST1X_CHANNEL_SMMU_STREAMID); +	host1x_ch_writel(channel, stream_id, HOST1X_CHANNEL_SMMU_STREAMID);  #endif  } @@ -278,6 +276,14 @@ static void channel_program_cdma(struct host1x_job *job)  #endif  } +static void job_complete_callback(struct dma_fence *fence, struct dma_fence_cb *cb) +{ +	struct host1x_job *job = container_of(cb, struct host1x_job, fence_cb); + +	/* Schedules CDMA update. */ +	host1x_cdma_update(&job->channel->cdma); +} +  static int channel_submit(struct host1x_job *job)  {  	struct host1x_channel *ch = job->channel; @@ -285,7 +291,6 @@ static int channel_submit(struct host1x_job *job)  	u32 prev_max = 0;  	u32 syncval;  	int err; -	struct host1x_waitlist *completed_waiter = NULL;  	struct host1x *host = dev_get_drvdata(ch->dev->parent);  	trace_host1x_channel_submit(dev_name(ch->dev), @@ -298,14 +303,7 @@ static int channel_submit(struct host1x_job *job)  	/* get submit lock */  	err = mutex_lock_interruptible(&ch->submitlock);  	if (err) -		goto error; - -	completed_waiter = kzalloc(sizeof(*completed_waiter), GFP_KERNEL); -	if (!completed_waiter) { -		mutex_unlock(&ch->submitlock); -		err = -ENOMEM; -		goto error; -	} +		return err;  	host1x_channel_set_streamid(ch);  	host1x_enable_gather_filter(ch); @@ -315,31 +313,37 @@ static int channel_submit(struct host1x_job *job)  	err = host1x_cdma_begin(&ch->cdma, job);  	if (err) {  		mutex_unlock(&ch->submitlock); -		goto error; +		return err;  	}  	channel_program_cdma(job);  	syncval = host1x_syncpt_read_max(sp); +	/* +	 * Create fence before submitting job to HW to avoid job completing +	 * before the fence is set up. +	 */ +	job->fence = host1x_fence_create(sp, syncval, true); +	if (WARN(IS_ERR(job->fence), "Failed to create submit complete fence")) { +		job->fence = NULL; +	} else { +		err = dma_fence_add_callback(job->fence, &job->fence_cb, +					     job_complete_callback); +	} +  	/* end CDMA submit & stash pinned hMems into sync queue */  	host1x_cdma_end(&ch->cdma, job);  	trace_host1x_channel_submitted(dev_name(ch->dev), prev_max, syncval); -	/* schedule a submit complete interrupt */ -	err = host1x_intr_add_action(host, sp, syncval, -				     HOST1X_INTR_ACTION_SUBMIT_COMPLETE, ch, -				     completed_waiter, &job->waiter); -	completed_waiter = NULL; -	WARN(err, "Failed to set submit complete interrupt"); -  	mutex_unlock(&ch->submitlock); -	return 0; +	if (err == -ENOENT) +		host1x_cdma_update(&ch->cdma); +	else +		WARN(err, "Failed to set submit complete interrupt"); -error: -	kfree(completed_waiter); -	return err; +	return 0;  }  static int host1x_channel_init(struct host1x_channel *ch, struct host1x *dev, diff --git a/drivers/gpu/host1x/hw/hw_host1x06_uclass.h b/drivers/gpu/host1x/hw/hw_host1x06_uclass.h index 5f831438d19b..50c32de452fb 100644 --- a/drivers/gpu/host1x/hw/hw_host1x06_uclass.h +++ b/drivers/gpu/host1x/hw/hw_host1x06_uclass.h @@ -53,7 +53,7 @@ static inline u32 host1x_uclass_incr_syncpt_cond_f(u32 v)  	host1x_uclass_incr_syncpt_cond_f(v)  static inline u32 host1x_uclass_incr_syncpt_indx_f(u32 v)  { -	return (v & 0xff) << 0; +	return (v & 0x3ff) << 0;  }  #define HOST1X_UCLASS_INCR_SYNCPT_INDX_F(v) \  	host1x_uclass_incr_syncpt_indx_f(v) diff --git a/drivers/gpu/host1x/hw/hw_host1x07_uclass.h b/drivers/gpu/host1x/hw/hw_host1x07_uclass.h index 8cd2ef087d5d..887b878f92f7 100644 --- a/drivers/gpu/host1x/hw/hw_host1x07_uclass.h +++ b/drivers/gpu/host1x/hw/hw_host1x07_uclass.h @@ -53,7 +53,7 @@ static inline u32 host1x_uclass_incr_syncpt_cond_f(u32 v)  	host1x_uclass_incr_syncpt_cond_f(v)  static inline u32 host1x_uclass_incr_syncpt_indx_f(u32 v)  { -	return (v & 0xff) << 0; +	return (v & 0x3ff) << 0;  }  #define HOST1X_UCLASS_INCR_SYNCPT_INDX_F(v) \  	host1x_uclass_incr_syncpt_indx_f(v) diff --git a/drivers/gpu/host1x/hw/hw_host1x08_uclass.h b/drivers/gpu/host1x/hw/hw_host1x08_uclass.h index 724cccd71aa1..4fb1d090edae 100644 --- a/drivers/gpu/host1x/hw/hw_host1x08_uclass.h +++ b/drivers/gpu/host1x/hw/hw_host1x08_uclass.h @@ -53,7 +53,7 @@ static inline u32 host1x_uclass_incr_syncpt_cond_f(u32 v)  	host1x_uclass_incr_syncpt_cond_f(v)  static inline u32 host1x_uclass_incr_syncpt_indx_f(u32 v)  { -	return (v & 0xff) << 0; +	return (v & 0x3ff) << 0;  }  #define HOST1X_UCLASS_INCR_SYNCPT_INDX_F(v) \  	host1x_uclass_incr_syncpt_indx_f(v) diff --git a/drivers/gpu/host1x/hw/intr_hw.c b/drivers/gpu/host1x/hw/intr_hw.c index 9acccdb139e6..b915ef7d0348 100644 --- a/drivers/gpu/host1x/hw/intr_hw.c +++ b/drivers/gpu/host1x/hw/intr_hw.c @@ -13,23 +13,6 @@  #include "../intr.h"  #include "../dev.h" -/* - * Sync point threshold interrupt service function - * Handles sync point threshold triggers, in interrupt context - */ -static void host1x_intr_syncpt_handle(struct host1x_syncpt *syncpt) -{ -	unsigned int id = syncpt->id; -	struct host1x *host = syncpt->host; - -	host1x_sync_writel(host, BIT(id % 32), -		HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(id / 32)); -	host1x_sync_writel(host, BIT(id % 32), -		HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(id / 32)); - -	schedule_work(&syncpt->intr.work); -} -  static irqreturn_t syncpt_thresh_isr(int irq, void *dev_id)  {  	struct host1x *host = dev_id; @@ -39,17 +22,20 @@ static irqreturn_t syncpt_thresh_isr(int irq, void *dev_id)  	for (i = 0; i < DIV_ROUND_UP(host->info->nb_pts, 32); i++) {  		reg = host1x_sync_readl(host,  			HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(i)); -		for_each_set_bit(id, ®, 32) { -			struct host1x_syncpt *syncpt = -				host->syncpt + (i * 32 + id); -			host1x_intr_syncpt_handle(syncpt); -		} + +		host1x_sync_writel(host, reg, +			HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(i)); +		host1x_sync_writel(host, reg, +			HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(i)); + +		for_each_set_bit(id, ®, 32) +			host1x_intr_handle_interrupt(host, i * 32 + id);  	}  	return IRQ_HANDLED;  } -static void _host1x_intr_disable_all_syncpt_intrs(struct host1x *host) +static void host1x_intr_disable_all_syncpt_intrs(struct host1x *host)  {  	unsigned int i; @@ -90,45 +76,38 @@ static void intr_hw_init(struct host1x *host, u32 cpm)  }  static int -_host1x_intr_init_host_sync(struct host1x *host, u32 cpm, -			    void (*syncpt_thresh_work)(struct work_struct *)) +host1x_intr_init_host_sync(struct host1x *host, u32 cpm)  { -	unsigned int i;  	int err;  	host1x_hw_intr_disable_all_syncpt_intrs(host); -	for (i = 0; i < host->info->nb_pts; i++) -		INIT_WORK(&host->syncpt[i].intr.work, syncpt_thresh_work); - -	err = devm_request_irq(host->dev, host->intr_syncpt_irq, +	err = devm_request_irq(host->dev, host->syncpt_irq,  			       syncpt_thresh_isr, IRQF_SHARED,  			       "host1x_syncpt", host); -	if (err < 0) { -		WARN_ON(1); +	if (err < 0)  		return err; -	}  	intr_hw_init(host, cpm);  	return 0;  } -static void _host1x_intr_set_syncpt_threshold(struct host1x *host, +static void host1x_intr_set_syncpt_threshold(struct host1x *host,  					      unsigned int id,  					      u32 thresh)  {  	host1x_sync_writel(host, thresh, HOST1X_SYNC_SYNCPT_INT_THRESH(id));  } -static void _host1x_intr_enable_syncpt_intr(struct host1x *host, +static void host1x_intr_enable_syncpt_intr(struct host1x *host,  					    unsigned int id)  {  	host1x_sync_writel(host, BIT(id % 32),  		HOST1X_SYNC_SYNCPT_THRESH_INT_ENABLE_CPU0(id / 32));  } -static void _host1x_intr_disable_syncpt_intr(struct host1x *host, +static void host1x_intr_disable_syncpt_intr(struct host1x *host,  					     unsigned int id)  {  	host1x_sync_writel(host, BIT(id % 32), @@ -137,23 +116,10 @@ static void _host1x_intr_disable_syncpt_intr(struct host1x *host,  		HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(id / 32));  } -static int _host1x_free_syncpt_irq(struct host1x *host) -{ -	unsigned int i; - -	devm_free_irq(host->dev, host->intr_syncpt_irq, host); - -	for (i = 0; i < host->info->nb_pts; i++) -		cancel_work_sync(&host->syncpt[i].intr.work); - -	return 0; -} -  static const struct host1x_intr_ops host1x_intr_ops = { -	.init_host_sync = _host1x_intr_init_host_sync, -	.set_syncpt_threshold = _host1x_intr_set_syncpt_threshold, -	.enable_syncpt_intr = _host1x_intr_enable_syncpt_intr, -	.disable_syncpt_intr = _host1x_intr_disable_syncpt_intr, -	.disable_all_syncpt_intrs = _host1x_intr_disable_all_syncpt_intrs, -	.free_syncpt_irq = _host1x_free_syncpt_irq, +	.init_host_sync = host1x_intr_init_host_sync, +	.set_syncpt_threshold = host1x_intr_set_syncpt_threshold, +	.enable_syncpt_intr = host1x_intr_enable_syncpt_intr, +	.disable_syncpt_intr = host1x_intr_disable_syncpt_intr, +	.disable_all_syncpt_intrs = host1x_intr_disable_all_syncpt_intrs,  }; diff --git a/drivers/gpu/host1x/hw/syncpt_hw.c b/drivers/gpu/host1x/hw/syncpt_hw.c index dd39d67ccec3..8cf35b2eff3d 100644 --- a/drivers/gpu/host1x/hw/syncpt_hw.c +++ b/drivers/gpu/host1x/hw/syncpt_hw.c @@ -106,9 +106,6 @@ static void syncpt_assign_to_channel(struct host1x_syncpt *sp,  #if HOST1X_HW >= 6  	struct host1x *host = sp->host; -	if (!host->hv_regs) -		return; -  	host1x_sync_writel(host,  			   HOST1X_SYNC_SYNCPT_CH_APP_CH(ch ? ch->id : 0xff),  			   HOST1X_SYNC_SYNCPT_CH_APP(sp->id));  |