msm: kgsl: change timestamp frees to use kgsl_event
The timestamp memqueue was unsorted, which could cause memory to not be freed soon enough. The kgsl_event list is sorted and does almost exactly the same thing as the memqueue did, so freememontimestamp is now implemented using the kgsl_event list.
This commit is contained in:
		| @@ -1000,15 +1000,6 @@ struct kgsl_memdesc *adreno_find_region(struct kgsl_device *device, | ||||
| 	} | ||||
| 	mutex_unlock(&kgsl_driver.process_mutex); | ||||
|  | ||||
| 	BUG_ON(!mutex_is_locked(&device->mutex)); | ||||
| 	list_for_each_entry(entry, &device->memqueue, list) { | ||||
| 		if (kgsl_gpuaddr_in_memdesc(&entry->memdesc, gpuaddr, size)) { | ||||
| 			result = &entry->memdesc; | ||||
| 			return result; | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	while (1) { | ||||
| 		struct adreno_context *adreno_context = NULL; | ||||
| 		context = idr_get_next(&device->context_idr, &next); | ||||
|   | ||||
| @@ -47,8 +47,6 @@ MODULE_PARM_DESC(ksgl_mmu_type, | ||||
|  | ||||
| static struct ion_client *kgsl_ion_client; | ||||
|  | ||||
| #ifdef CONFIG_GENLOCK | ||||
|  | ||||
| /** | ||||
|  * kgsl_add_event - Add a new timstamp event for the KGSL device | ||||
|  * @device - KGSL device for the new event | ||||
| @@ -106,7 +104,6 @@ static int kgsl_add_event(struct kgsl_device *device, u32 ts, | ||||
| 	queue_work(device->work_queue, &device->ts_expired_ws); | ||||
| 	return 0; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| /** | ||||
|  * kgsl_cancel_events - Cancel all events for a process | ||||
| @@ -258,44 +255,10 @@ kgsl_destroy_context(struct kgsl_device_private *dev_priv, | ||||
| 	idr_remove(&dev_priv->device->context_idr, id); | ||||
| } | ||||
|  | ||||
| /* to be called when a process is destroyed, this walks the memqueue and | ||||
|  * frees any entryies that belong to the dying process | ||||
|  */ | ||||
| static void kgsl_memqueue_cleanup(struct kgsl_device *device, | ||||
| 				     struct kgsl_process_private *private) | ||||
| { | ||||
| 	struct kgsl_mem_entry *entry, *entry_tmp; | ||||
|  | ||||
| 	if (!private) | ||||
| 		return; | ||||
|  | ||||
| 	BUG_ON(!mutex_is_locked(&device->mutex)); | ||||
|  | ||||
| 	list_for_each_entry_safe(entry, entry_tmp, &device->memqueue, list) { | ||||
| 		if (entry->priv == private) { | ||||
| 			list_del(&entry->list); | ||||
| 			kgsl_mem_entry_put(entry); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void kgsl_memqueue_freememontimestamp(struct kgsl_device *device, | ||||
| 				  struct kgsl_mem_entry *entry, | ||||
| 				  uint32_t timestamp, | ||||
| 				  enum kgsl_timestamp_type type) | ||||
| { | ||||
| 	BUG_ON(!mutex_is_locked(&device->mutex)); | ||||
|  | ||||
| 	entry->free_timestamp = timestamp; | ||||
|  | ||||
| 	list_add_tail(&entry->list, &device->memqueue); | ||||
| } | ||||
|  | ||||
| static void kgsl_timestamp_expired(struct work_struct *work) | ||||
| { | ||||
| 	struct kgsl_device *device = container_of(work, struct kgsl_device, | ||||
| 		ts_expired_ws); | ||||
| 	struct kgsl_mem_entry *entry, *entry_tmp; | ||||
| 	struct kgsl_event *event, *event_tmp; | ||||
| 	uint32_t ts_processed; | ||||
|  | ||||
| @@ -305,15 +268,6 @@ static void kgsl_timestamp_expired(struct work_struct *work) | ||||
| 	ts_processed = device->ftbl->readtimestamp(device, | ||||
| 		KGSL_TIMESTAMP_RETIRED); | ||||
|  | ||||
| 	/* Flush the freememontimestamp queue */ | ||||
| 	list_for_each_entry_safe(entry, entry_tmp, &device->memqueue, list) { | ||||
| 		if (timestamp_cmp(ts_processed, entry->free_timestamp) < 0) | ||||
| 			break; | ||||
|  | ||||
| 		list_del(&entry->list); | ||||
| 		kgsl_mem_entry_put(entry); | ||||
| 	} | ||||
|  | ||||
| 	/* Process expired events */ | ||||
| 	list_for_each_entry_safe(event, event_tmp, &device->events, list) { | ||||
| 		if (timestamp_cmp(ts_processed, event->timestamp) < 0) | ||||
| @@ -688,7 +642,6 @@ static int kgsl_release(struct inode *inodep, struct file *filep) | ||||
| 	/* clean up any to-be-freed entries that belong to this | ||||
| 	 * process and this device | ||||
| 	 */ | ||||
| 	kgsl_memqueue_cleanup(device, private); | ||||
| 	kgsl_cancel_events(device, dev_priv); | ||||
|  | ||||
| 	mutex_unlock(&device->mutex); | ||||
| @@ -1062,6 +1015,16 @@ static long kgsl_ioctl_cmdstream_readtimestamp(struct kgsl_device_private | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static void kgsl_freemem_event_cb(struct kgsl_device *device, | ||||
| 	void *priv, u32 timestamp) | ||||
| { | ||||
| 	struct kgsl_mem_entry *entry = priv; | ||||
| 	spin_lock(&entry->priv->mem_lock); | ||||
| 	list_del(&entry->list); | ||||
| 	spin_unlock(&entry->priv->mem_lock); | ||||
| 	kgsl_mem_entry_put(entry); | ||||
| } | ||||
|  | ||||
| static long kgsl_ioctl_cmdstream_freememontimestamp(struct kgsl_device_private | ||||
| 						    *dev_priv, unsigned int cmd, | ||||
| 						    void *data) | ||||
| @@ -1072,13 +1035,11 @@ static long kgsl_ioctl_cmdstream_freememontimestamp(struct kgsl_device_private | ||||
|  | ||||
| 	spin_lock(&dev_priv->process_priv->mem_lock); | ||||
| 	entry = kgsl_sharedmem_find(dev_priv->process_priv, param->gpuaddr); | ||||
| 	if (entry) | ||||
| 		list_del(&entry->list); | ||||
| 	spin_unlock(&dev_priv->process_priv->mem_lock); | ||||
|  | ||||
| 	if (entry) { | ||||
| 		kgsl_memqueue_freememontimestamp(dev_priv->device, entry, | ||||
| 					param->timestamp, param->type); | ||||
| 		result = kgsl_add_event(dev_priv->device, param->timestamp, | ||||
| 					kgsl_freemem_event_cb, entry, dev_priv); | ||||
| 	} else { | ||||
| 		KGSL_DRV_ERR(dev_priv->device, | ||||
| 			"invalid gpuaddr %08x\n", param->gpuaddr); | ||||
| @@ -2253,7 +2214,6 @@ kgsl_register_device(struct kgsl_device *device) | ||||
| 	INIT_WORK(&device->idle_check_ws, kgsl_idle_check); | ||||
| 	INIT_WORK(&device->ts_expired_ws, kgsl_timestamp_expired); | ||||
|  | ||||
| 	INIT_LIST_HEAD(&device->memqueue); | ||||
| 	INIT_LIST_HEAD(&device->events); | ||||
|  | ||||
| 	ret = kgsl_mmu_init(device); | ||||
|   | ||||
| @@ -153,7 +153,6 @@ struct kgsl_device { | ||||
| 	uint32_t state; | ||||
| 	uint32_t requested_state; | ||||
|  | ||||
| 	struct list_head memqueue; | ||||
| 	unsigned int active_cnt; | ||||
| 	struct completion suspend_gate; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user