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:
SecureCRT 2012-06-23 19:03:55 +08:00
parent 4520a7c383
commit b8450f4096
3 changed files with 12 additions and 62 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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;