From 0d348b26aee707b366e20d8f9914cb2e2dc47ed0 Mon Sep 17 00:00:00 2001 From: Matt Sealey Date: Sun, 2 Dec 2012 14:40:57 -0600 Subject: [PATCH] amd-gpu: annotate and refine kmod/ioctl functionality also clean up coding style on open, release, mmap functions --- drivers/mxc/amd-gpu/kgsl_kmod.c | 201 +++++++++++++++++--------------- 1 file changed, 110 insertions(+), 91 deletions(-) diff --git a/drivers/mxc/amd-gpu/kgsl_kmod.c b/drivers/mxc/amd-gpu/kgsl_kmod.c index 6e64043569b..01f6009a337 100644 --- a/drivers/mxc/amd-gpu/kgsl_kmod.c +++ b/drivers/mxc/amd-gpu/kgsl_kmod.c @@ -92,6 +92,7 @@ static const struct file_operations kgsl_fops = //.write = kgsl_write, }; +/* qcom: doesn't do this */ static struct vm_operations_struct kgsl_vmops = { .fault = kgsl_fault, @@ -162,7 +163,7 @@ static int kgsl_ioctl_device_getproperty(struct file *fd, void __user *arg) * - call yamato_getproperty or g12_getproperty * - those functions allocate return value on stack * - copy_to_user the result - * - no idea how FSL code is even meant to work here!? + * - no idea how FSL code is even meant to work here!? does hwaccess_memread do it? */ result = kgsl_device_getproperty(param.device_id, param.type, tmp, param.sizebytes); @@ -174,17 +175,18 @@ done: static int kgsl_ioctl_device_setproperty(struct file *fd, void __user *arg) { - int status; + int result; struct kgsl_device_setproperty param; if (copy_from_user(¶m, arg, sizeof(param))) { - status = GSL_FAILURE; // -EFAULT + result = GSL_FAILURE; // -EFAULT goto done; } - status = kgsl_device_setproperty(param.device_id, param.type, param.value, param.sizebytes); + + result = kgsl_device_setproperty(param.device_id, param.type, param.value, param.sizebytes); done: - return status; + return result; } static int kgsl_ioctl_device_regread(struct file *fd, void __user *arg) @@ -203,6 +205,8 @@ static int kgsl_ioctl_device_regread(struct file *fd, void __user *arg) status = kgsl_device_regread(param.device_id, param.offsetwords, &tmp); if (status == GSL_SUCCESS) { + /* qcom: arg, ¶m, sizeof(param) */ + /* fsl code should never work? */ if (copy_to_user(param.value, &tmp, sizeof(unsigned int))) { pr_err("%s: copy_to_user error\n", __func__); status = GSL_FAILURE; @@ -239,6 +243,7 @@ static int kgsl_ioctl_cmdstream_waittimestamp(struct file *fd, void __user *arg) return GSL_FAILURE; } + /* qcom: per-device waittimestamp, driver lock around function, runpending to finish */ result = kgsl_cmdstream_waittimestamp(param.device_id, param.timestamp, param.timeout); return result; @@ -256,10 +261,13 @@ static int kgsl_ioctl_cmdstream_issueibcmds(struct file *fd, void __user *arg) return GSL_FAILURE; } + /* qcom: per-device opencoded */ status = kgsl_cmdstream_issueibcmds(param.device_id, param.drawctxt_index, param.ibaddr, param.sizedwords, &tmp, param.flags); if (status == GSL_SUCCESS) { + /* don't understand how copying it to param.timestamp gets it back into userspace... + this is not how the newer drivers work or how any driver does it for real..? */ if (copy_to_user(param.timestamp, &tmp, sizeof(unsigned int))) { pr_err("%s: copy_to_user error\n", __func__); status = GSL_FAILURE; @@ -314,6 +322,7 @@ static int kgsl_ioctl_sharedmem_free(struct file *fd, void __user *arg) return GSL_FAILURE; } + /* qcom: kgsl_sharedmem_find => kgsl_remove_mem_entry */ status = del_memblock_from_allocated_list(fd, &tmp); if (status) { pr_err("%s: tried to free memdesc that was not allocated!\n", __func__); @@ -483,6 +492,7 @@ static int kgsl_ioctl_cmdstream_readtimestamp(struct file *fd, void __user *arg) return GSL_FAILURE; } + /* qcom: per device here */ tmp = kgsl_cmdstream_readtimestamp(param.device_id, param.type); if (copy_to_user(param.timestamp, &tmp, sizeof(unsigned int))) { pr_err("%s: copy_to_user error\n", __func__); @@ -501,6 +511,7 @@ static int kgsl_ioctl_cmdstream_freememontimestamp(struct file *fd, void __user return GSL_FAILURE; } + /* qcom: per device */ status = del_memblock_from_allocated_list(fd, param.memdesc); if (status) { /* tried to remove a block of memory that is not allocated! @@ -513,6 +524,7 @@ static int kgsl_ioctl_cmdstream_freememontimestamp(struct file *fd, void __user param.memdesc, param.timestamp, param.type); + /* qcom: runpending here */ } return status; } @@ -529,6 +541,7 @@ static int kgsl_ioctl_context_create(struct file *fd, void __user *arg) return GSL_FAILURE; } + /* qcom: per device */ device = &gsl_driver.device[param.device_id-1]; mutex_lock(&gsl_driver.lock); status = device->ftbl.device_drawctxt_create(device, param.type, &tmp, param.flags); @@ -565,6 +578,8 @@ static int kgsl_ioctl_context_destroy(struct file *fd, void __user *arg) status = device->ftbl.device_drawctxt_destroy(device, param.drawctxt_id); mutex_unlock(&gsl_driver.lock); + /* qcom: runpending */ + del_device_context_from_array(fd, param.device_id, param.drawctxt_id); return status; @@ -710,6 +725,7 @@ static int kgsl_ioctl(struct inode *inode, struct file *fd, unsigned int cmd, un result = kgsl_ioctl_device_setproperty(fd, (void __user *)arg); break; case IOCTL_KGSL_SHAREDMEM_ALLOC: + /* qcom: runpending on each device first */ result = kgsl_ioctl_sharedmem_alloc(fd, (void __user *)arg); break; case IOCTL_KGSL_SHAREDMEM_FREE: @@ -731,6 +747,7 @@ static int kgsl_ioctl(struct inode *inode, struct file *fd, unsigned int cmd, un result = kgsl_ioctl_sharedmem_largestfreeblock(fd, (void __user *)arg); break; case IOCTL_KGSL_SHAREDMEM_CACHEOPERATION: + /* qcom: only if cache enabled (debug option) */ result = kgsl_ioctl_sharedmem_cacheoperation(fd, (void __user *)arg); break; case IOCTL_KGSL_CMDSTREAM_ISSUEIBCMDS: @@ -785,133 +802,135 @@ static int kgsl_ioctl(struct inode *inode, struct file *fd, unsigned int cmd, un break; default: + pr_err("%s: invalid ioctl code %08x\n", __func__, cmd); result = -ENOTTY; + break; } + /* qcom: post hwaccess here (explains why none of their funcs do it..?) */ return result; } static int kgsl_mmap(struct file *fd, struct vm_area_struct *vma) { - int result; - int status = 0; - unsigned long start = vma->vm_start; - unsigned long pfn = vma->vm_pgoff; - unsigned long size = vma->vm_end - vma->vm_start; - unsigned long prot = pgprot_writecombine(vma->vm_page_prot); - unsigned long addr = vma->vm_pgoff << PAGE_SHIFT; - void *va = NULL; + int result; + int status = 0; + unsigned long start = vma->vm_start; + unsigned long pfn = vma->vm_pgoff; + unsigned long size = vma->vm_end - vma->vm_start; + unsigned long prot = pgprot_writecombine(vma->vm_page_prot); + unsigned long addr = vma->vm_pgoff << PAGE_SHIFT; + void *va = NULL; - if (gsl_driver.enable_mmu && (addr < GSL_LINUX_MAP_RANGE_END) && (addr >= GSL_LINUX_MAP_RANGE_START)) { - va = gsl_linux_map_find(addr); - while (size > 0) { - if (remap_pfn_range(vma, start, vmalloc_to_pfn(va), PAGE_SIZE, prot)) { - return -EAGAIN; - } - start += PAGE_SIZE; - va += PAGE_SIZE; - size -= PAGE_SIZE; + /* qcom: + * no difference between enable or disable mmu re remap_pfn_range usage + * mark vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot) before remap + * also holds gsl_driver.lock! + */ + + if (gsl_driver.enable_mmu && (addr < GSL_LINUX_MAP_RANGE_END) && (addr >= GSL_LINUX_MAP_RANGE_START)) { + va = gsl_linux_map_find(addr); + while (size > 0) { + if (remap_pfn_range(vma, start, vmalloc_to_pfn(va), PAGE_SIZE, prot)) + return -EAGAIN; + } + start += PAGE_SIZE; + va += PAGE_SIZE; + size -= PAGE_SIZE; + } else { + if (remap_pfn_range(vma, start, pfn, size, prot)) + status = -EAGAIN; } - } else { - if (remap_pfn_range(vma, start, pfn, size, prot)) { - status = -EAGAIN; - } - } + vma->vm_ops = &kgsl_vmops; - vma->vm_ops = &kgsl_vmops; - - return status; + return status; } static int kgsl_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { - return VM_FAULT_SIGBUS; + return VM_FAULT_SIGBUS; } -static int kgsl_open(struct inode *inode, struct file *fd) +static int kgsl_open(struct inode *inodep, struct file *filep) { - unsigned int flags = 0; - struct kgsl_file_private *datp; - int err = 0; + unsigned int flags = 0; + struct kgsl_file_private *private; + int result = 0; - if(mutex_lock_interruptible(&gsl_mutex)) - { - return -EINTR; - } + if (filep->f_flags & O_EXCL) { + return -EBUSY; + } - if (kgsl_driver_entry(flags) != GSL_SUCCESS) - { - printk(KERN_INFO "%s: kgsl_driver_entry error\n", __func__); - err = -EIO; // TODO: not sure why did it fail? - } - else - { - /* allocate per file descriptor data structure */ - datp = (struct kgsl_file_private *)kzalloc( - sizeof(struct kgsl_file_private), - GFP_KERNEL); - if(datp) - { - init_created_contexts_array(datp->created_contexts_array[0]); - INIT_LIST_HEAD(&datp->allocated_blocks_head); + private = kzalloc(sizeof(*private), GFP_KERNEL); + if (private == NULL) { + return -ENOMEM; + } - fd->private_data = (void *)datp; - } - else - { - err = -ENOMEM; - } - } + if(mutex_lock_interruptible(&gsl_mutex)) + return -EINTR; - mutex_unlock(&gsl_mutex); + /* qcom: first_open_locked? */ + if (kgsl_driver_entry(flags) != GSL_SUCCESS) { + pr_info("%s: kgsl_driver_entry error\n", __func__); + result = -EIO; // TODO: not sure why did it fail? + } - return err; + init_created_contexts_array(private->created_contexts_array[0]); + INIT_LIST_HEAD(&private->allocated_blocks_head); + + filep->private_data = (void *) private; + + mutex_unlock(&gsl_mutex); + + return result; } -static int kgsl_release(struct inode *inode, struct file *fd) +static int kgsl_release(struct inode *inodep, struct file *filep) { - struct kgsl_file_private *datp; - int err = 0; + struct kgsl_file_private *private; + int result = 0; - if(mutex_lock_interruptible(&gsl_mutex)) - { - return -EINTR; - } + /* qcom: pre_hwaccess */ - /* make sure contexts are destroyed */ - del_all_devices_contexts(fd); + if(mutex_lock_interruptible(&gsl_mutex)) + return -EINTR; - if (kgsl_driver_exit() != GSL_SUCCESS) - { - printk(KERN_INFO "%s: kgsl_driver_exit error\n", __func__); - err = -EIO; // TODO: find better error code - } - else - { - /* release per file descriptor data structure */ - datp = (struct kgsl_file_private *)fd->private_data; - del_all_memblocks_from_allocated_list(fd); - kfree(datp); - fd->private_data = 0; - } + /* make sure contexts are destroyed */ + /* qcom: walk lists manually here */ + del_all_devices_contexts(filep); - mutex_unlock(&gsl_mutex); + /* qcom: last_release_locked? */ + if (kgsl_driver_exit() != GSL_SUCCESS) { + pr_info("%s: kgsl_driver_exit error\n", __func__); + result = -EIO; // TODO: find better error code + } else { + /* release per file descriptor data structure */ + private = (struct kgsl_file_private *)filep->private_data; + /* qcom: remove_mem_entry for_each_entry_safe */ + del_all_memblocks_from_allocated_list(filep); + /* qcom: tear down mmu */ + filep->private_data = NULL; + kfree(private); + } - return err; + /* qcom: post_hwaccess */ + mutex_unlock(&gsl_mutex); + + return result; } static struct class *gsl_kmod_class; static irqreturn_t z160_irq_handler(int irq, void *dev_id) { - kgsl_intr_isr(&gsl_driver.device[KGSL_DEVICE_G12-1]); - return IRQ_HANDLED; + kgsl_intr_isr(&gsl_driver.device[KGSL_DEVICE_G12-1]); + return IRQ_HANDLED; } static irqreturn_t z430_irq_handler(int irq, void *dev_id) { - kgsl_intr_isr(&gsl_driver.device[KGSL_DEVICE_YAMATO-1]); - return IRQ_HANDLED; + kgsl_intr_isr(&gsl_driver.device[KGSL_DEVICE_YAMATO-1]); + return IRQ_HANDLED; } static int gpu_probe(struct platform_device *pdev)