Loading drivers/gpu/msm/adreno.c +8 −19 Original line number Diff line number Diff line Loading @@ -652,7 +652,7 @@ void adreno_cp_callback(struct adreno_device *adreno_dev, int bit) { struct kgsl_device *device = &adreno_dev->dev; queue_work(device->work_queue, &device->event_work); kgsl_schedule_work(&device->event_work); adreno_dispatcher_schedule(device); } Loading Loading @@ -1315,24 +1315,13 @@ static int _adreno_start(struct adreno_device *adreno_dev) adreno_writereg(adreno_dev, ADRENO_REG_RBBM_SECVID_TSB_CONTROL, 0x0); if (ADRENO_FEATURE(adreno_dev, ADRENO_64BIT) && MMU_FEATURE(&device->mmu, KGSL_MMU_64BIT)) { adreno_writereg64(adreno_dev, ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_BASE, ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_BASE_HI, KGSL_IOMMU_SECURE_BASE64); KGSL_IOMMU_SECURE_BASE); adreno_writereg(adreno_dev, ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_SIZE, KGSL_IOMMU_SECURE_SIZE64); } else { adreno_writereg64(adreno_dev, ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_BASE, ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_BASE_HI, KGSL_IOMMU_SECURE_BASE32); adreno_writereg(adreno_dev, ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_SIZE, KGSL_IOMMU_SECURE_SIZE32); } KGSL_IOMMU_SECURE_SIZE); } status = adreno_ocmem_malloc(adreno_dev); Loading drivers/gpu/msm/adreno_a5xx.c +1 −1 Original line number Diff line number Diff line Loading @@ -2767,7 +2767,7 @@ static void a5xx_gpmu_int_callback(struct adreno_device *adreno_dev, int bit) /* Stop GPMU */ kgsl_regwrite(device, A5XX_GPMU_CM3_SYSRESET, 1); queue_work(device->work_queue, &adreno_dev->gpmu_work); kgsl_schedule_work(&adreno_dev->gpmu_work); KGSL_DRV_CRIT_RATELIMIT(device, "GPMU: Watchdog bite\n"); Loading drivers/gpu/msm/adreno_dispatch.c +3 −3 Original line number Diff line number Diff line Loading @@ -2135,7 +2135,7 @@ static void adreno_dispatcher_work(struct work_struct *work) * stragglers */ if (dispatcher->inflight == 0 && count) queue_work(device->work_queue, &device->event_work); kgsl_schedule_work(&device->event_work); /* Try to dispatch new commands */ _adreno_dispatcher_issuecmds(adreno_dev); Loading Loading @@ -2188,7 +2188,7 @@ void adreno_dispatcher_schedule(struct kgsl_device *device) struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher; queue_work(device->work_queue, &dispatcher->work); kgsl_schedule_work(&dispatcher->work); } /** Loading Loading @@ -2577,7 +2577,7 @@ void adreno_preempt_process_dispatch_queue(struct adreno_device *adreno_dev, cmdbatch->expires = jiffies + msecs_to_jiffies(adreno_cmdbatch_timeout); } queue_work(device->work_queue, &device->event_work); kgsl_schedule_work(&device->event_work); } /** Loading drivers/gpu/msm/kgsl.c +45 −34 Original line number Diff line number Diff line Loading @@ -228,13 +228,24 @@ int kgsl_readtimestamp(struct kgsl_device *device, void *priv, } EXPORT_SYMBOL(kgsl_readtimestamp); /* Scheduled by kgsl_mem_entry_put_deferred() */ static void _deferred_put(struct work_struct *work) { struct kgsl_mem_entry *entry = container_of(work, struct kgsl_mem_entry, work); kgsl_mem_entry_put(entry); } static inline struct kgsl_mem_entry * kgsl_mem_entry_create(void) { struct kgsl_mem_entry *entry = kzalloc(sizeof(*entry), GFP_KERNEL); if (entry) if (entry != NULL) { kref_init(&entry->refcount); INIT_WORK(&entry->work, _deferred_put); } return entry; } Loading Loading @@ -1256,6 +1267,8 @@ kgsl_sharedmem_find_id(struct kgsl_process_private *process, unsigned int id) int result = 0; struct kgsl_mem_entry *entry; drain_workqueue(kgsl_driver.mem_workqueue); spin_lock(&process->mem_lock); entry = idr_find(&process->mem_idr, id); if (entry) Loading Loading @@ -1833,8 +1846,7 @@ static long gpuobj_free_on_timestamp(struct kgsl_device_private *dev_priv, static void gpuobj_free_fence_func(void *priv) { struct kgsl_mem_entry *entry = priv; kgsl_mem_entry_put(entry); kgsl_mem_entry_put_deferred((struct kgsl_mem_entry *) priv); } static long gpuobj_free_on_fence(struct kgsl_device_private *dev_priv, Loading @@ -1844,15 +1856,22 @@ static long gpuobj_free_on_fence(struct kgsl_device_private *dev_priv, struct kgsl_gpu_event_fence event; long ret; if (!kgsl_mem_entry_set_pend(entry)) return -EBUSY; memset(&event, 0, sizeof(event)); ret = _copy_from_user(&event, to_user_ptr(param->priv), sizeof(event), param->len); if (ret) if (ret) { kgsl_mem_entry_unset_pend(entry); return ret; } if (event.fd < 0) if (event.fd < 0) { kgsl_mem_entry_unset_pend(entry); return -EINVAL; } handle = kgsl_sync_fence_async_wait(event.fd, gpuobj_free_fence_func, entry); Loading @@ -1861,7 +1880,12 @@ static long gpuobj_free_on_fence(struct kgsl_device_private *dev_priv, if (handle == NULL) return gpumem_free_entry(entry); return IS_ERR(handle) ? PTR_ERR(handle) : 0; if (IS_ERR(handle)) { kgsl_mem_entry_unset_pend(entry); return PTR_ERR(handle); } return 0; } long kgsl_ioctl_gpuobj_free(struct kgsl_device_private *dev_priv, Loading Loading @@ -2386,7 +2410,7 @@ static int kgsl_setup_dma_buf(struct kgsl_device *device, entry->memdesc.size = 0; entry->memdesc.mmapsize = 0; /* USE_CPU_MAP is not impemented for ION. */ entry->memdesc.flags &= ~KGSL_MEMFLAGS_USE_CPU_MAP; entry->memdesc.flags &= ~((uint64_t) KGSL_MEMFLAGS_USE_CPU_MAP); entry->memdesc.flags |= KGSL_MEMFLAGS_USERMEM_ION; sg_table = dma_buf_map_attachment(attach, DMA_TO_DEVICE); Loading Loading @@ -2483,10 +2507,11 @@ long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv, | KGSL_MEMALIGN_MASK | KGSL_MEMFLAGS_USE_CPU_MAP | KGSL_MEMFLAGS_SECURE; entry->memdesc.flags = param->flags | KGSL_MEMFLAGS_FORCE_32BIT; entry->memdesc.flags = ((uint64_t) param->flags) | KGSL_MEMFLAGS_FORCE_32BIT; if (!kgsl_mmu_use_cpu_map(&dev_priv->device->mmu)) entry->memdesc.flags &= ~KGSL_MEMFLAGS_USE_CPU_MAP; entry->memdesc.flags &= ~((uint64_t) KGSL_MEMFLAGS_USE_CPU_MAP); if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_IOMMU) entry->memdesc.priv |= KGSL_MEMDESC_GUARD_PAGE; Loading Loading @@ -2865,7 +2890,7 @@ static uint64_t kgsl_filter_cachemode(uint64_t flags) */ if ((flags & KGSL_CACHEMODE_MASK) >> KGSL_CACHEMODE_SHIFT == KGSL_CACHEMODE_WRITETHROUGH) { flags &= ~KGSL_CACHEMODE_MASK; flags &= ~((uint64_t) KGSL_CACHEMODE_MASK); flags |= (KGSL_CACHEMODE_WRITEBACK << KGSL_CACHEMODE_SHIFT) & KGSL_CACHEMODE_MASK; } Loading Loading @@ -2900,7 +2925,7 @@ static struct kgsl_mem_entry *gpumem_alloc_entry( /* Turn off SVM if the system doesn't support it */ if (!kgsl_mmu_use_cpu_map(&dev_priv->device->mmu)) flags &= ~KGSL_MEMFLAGS_USE_CPU_MAP; flags &= ~((uint64_t) KGSL_MEMFLAGS_USE_CPU_MAP); /* Return not supported error if secure memory isn't enabled */ if (!kgsl_mmu_is_secured(&dev_priv->device->mmu) && Loading @@ -2912,8 +2937,7 @@ static struct kgsl_mem_entry *gpumem_alloc_entry( /* Secure memory disables advanced addressing modes */ if (flags & KGSL_MEMFLAGS_SECURE) flags &= ~(KGSL_MEMFLAGS_USE_CPU_MAP | KGSL_MEMFLAGS_FORCE_32BIT); flags &= ~((uint64_t) KGSL_MEMFLAGS_USE_CPU_MAP); /* Cap the alignment bits to the highest number we can handle */ align = MEMFLAGS(flags, KGSL_MEMALIGN_MASK, KGSL_MEMALIGN_SHIFT); Loading @@ -2921,7 +2945,7 @@ static struct kgsl_mem_entry *gpumem_alloc_entry( KGSL_CORE_ERR("Alignment too large; restricting to %dK\n", KGSL_MAX_ALIGN >> 10); flags &= ~KGSL_MEMALIGN_MASK; flags &= ~((uint64_t) KGSL_MEMALIGN_MASK); flags |= (ilog2(KGSL_MAX_ALIGN) << KGSL_MEMALIGN_SHIFT) & KGSL_MEMALIGN_MASK; } Loading Loading @@ -3023,7 +3047,7 @@ long kgsl_ioctl_gpumem_alloc(struct kgsl_device_private *dev_priv, uint64_t flags = param->flags; /* Legacy functions doesn't support these advanced features */ flags &= ~KGSL_MEMFLAGS_USE_CPU_MAP; flags &= ~((uint64_t) KGSL_MEMFLAGS_USE_CPU_MAP); flags |= KGSL_MEMFLAGS_FORCE_32BIT; entry = gpumem_alloc_entry(dev_priv, (uint64_t) param->size, Loading Loading @@ -3145,7 +3169,7 @@ long kgsl_ioctl_gpuobj_set_info(struct kgsl_device_private *dev_priv, copy_metadata(entry, param->metadata, param->metadata_len); if (param->flags & KGSL_GPUOBJ_SET_INFO_TYPE) { entry->memdesc.flags &= ~KGSL_MEMTYPE_MASK; entry->memdesc.flags &= ~((uint64_t) KGSL_MEMTYPE_MASK); entry->memdesc.flags |= param->type << KGSL_MEMTYPE_SHIFT; } Loading Loading @@ -3882,20 +3906,10 @@ int kgsl_device_platform_probe(struct kgsl_device *device) setup_timer(&device->idle_timer, kgsl_timer, (unsigned long) device); /* Create our primary workqueue for events and power */ device->work_queue = create_singlethread_workqueue(device->name); if (device->work_queue == NULL) { status = -ENODEV; KGSL_DRV_ERR(device, "create_singelthreaded_workqueue(%s) failed\n", device->name); goto error_pwrctrl_close; } status = kgsl_mmu_init(device); if (status != 0) { KGSL_DRV_ERR(device, "kgsl_mmu_init failed %d\n", status); goto error_dest_work_q; goto error_pwrctrl_close; } /* Check to see if our device can perform DMA correctly */ Loading Loading @@ -3946,9 +3960,6 @@ int kgsl_device_platform_probe(struct kgsl_device *device) error_close_mmu: kgsl_mmu_close(device); error_dest_work_q: destroy_workqueue(device->work_queue); device->work_queue = NULL; error_pwrctrl_close: kgsl_pwrctrl_close(device); error: Loading @@ -3973,10 +3984,6 @@ void kgsl_device_platform_remove(struct kgsl_device *device) kgsl_mmu_close(device); if (device->work_queue) { destroy_workqueue(device->work_queue); device->work_queue = NULL; } kgsl_pwrctrl_close(device); _unregister_device(device); Loading Loading @@ -4073,6 +4080,10 @@ static int __init kgsl_core_init(void) INIT_LIST_HEAD(&kgsl_driver.pagetable_list); kgsl_driver.workqueue = create_singlethread_workqueue("kgsl-workqueue"); kgsl_driver.mem_workqueue = create_singlethread_workqueue("kgsl-mementry"); kgsl_mmu_set_mmutype(ksgl_mmu_type); kgsl_events_init(); Loading drivers/gpu/msm/kgsl.h +47 −10 Original line number Diff line number Diff line Loading @@ -58,29 +58,38 @@ static inline void KGSL_STATS_ADD(uint64_t size, atomic_long_t *stat, struct kgsl_device; struct kgsl_context; /** * struct kgsl_driver - main container for global KGSL things * @cdev: Character device struct * @major: Major ID for the KGSL device * @class: Pointer to the class struct for the core KGSL sysfs entries * @virtdev: Virtual device for managing the core * @ptkobj: kobject for storing the pagetable statistics * @prockobj: kobject for storing the process statistics * @devp: Array of pointers to the individual KGSL device structs * @process_list: List of open processes * @pagetable_list: LIst of open pagetables * @ptlock: Lock for accessing the pagetable list * @process_mutex: Mutex for accessing the process list * @devlock: Mutex protecting the device list * @stats: Struct containing atomic memory statistics * @full_cache_threshold: the threshold that triggers a full cache flush * @workqueue: Pointer to a single threaded workqueue * @mem_workqueue: Pointer to a workqueue for deferring memory entries */ struct kgsl_driver { struct cdev cdev; dev_t major; struct class *class; /* Virtual device for managing the core */ struct device virtdev; /* Kobjects for storing pagetable and process statistics */ struct kobject *ptkobj; struct kobject *prockobj; struct kgsl_device *devp[KGSL_DEVICE_MAX]; /* Global lilst of open processes */ struct list_head process_list; /* Global list of pagetables */ struct list_head pagetable_list; /* Spinlock for accessing the pagetable list */ spinlock_t ptlock; /* Mutex for accessing the process list */ struct mutex process_mutex; /* Mutex for protecting the device list */ struct mutex devlock; struct { atomic_long_t vmalloc; atomic_long_t vmalloc_max; Loading @@ -94,6 +103,8 @@ struct kgsl_driver { atomic_long_t mapped_max; } stats; unsigned int full_cache_threshold; struct workqueue_struct *workqueue; struct workqueue_struct *mem_workqueue; }; extern struct kgsl_driver kgsl_driver; Loading Loading @@ -190,6 +201,7 @@ struct kgsl_memdesc { * are still references to it. * @dev_priv: back pointer to the device file that created this entry. * @metadata: String containing user specified metadata for the entry * @work: Work struct used to schedule a kgsl_mem_entry_put in atomic contexts */ struct kgsl_mem_entry { struct kref refcount; Loading @@ -200,6 +212,7 @@ struct kgsl_mem_entry { struct kgsl_process_private *priv; int pending_free; char metadata[KGSL_GPUOBJ_ALLOC_METADATA_MAX + 1]; struct work_struct work; }; struct kgsl_device_private; Loading Loading @@ -410,6 +423,15 @@ static inline int timestamp_cmp(unsigned int a, unsigned int b) return ((a > b) && (a - b <= KGSL_TIMESTAMP_WINDOW)) ? 1 : -1; } /** * kgsl_schedule_work() - Schedule a work item on the KGSL workqueue * @work: work item to schedule */ static inline void kgsl_schedule_work(struct work_struct *work) { queue_work(kgsl_driver.workqueue, work); } static inline int kgsl_mem_entry_get(struct kgsl_mem_entry *entry) { Loading @@ -422,6 +444,21 @@ kgsl_mem_entry_put(struct kgsl_mem_entry *entry) kref_put(&entry->refcount, kgsl_mem_entry_destroy); } /** * kgsl_mem_entry_put_deferred() - Schedule a task to put the memory entry * @entry: Mem entry to put * * This function is for atomic contexts where a normal kgsl_mem_entry_put() * would result in the memory entry getting destroyed and possibly taking * mutexes along the way. Schedule the work to happen outside of the atomic * context. */ static inline void kgsl_mem_entry_put_deferred(struct kgsl_mem_entry *entry) { if (entry != NULL) queue_work(kgsl_driver.mem_workqueue, &entry->work); } /* * kgsl_addr_range_overlap() - Checks if 2 ranges overlap * @gpuaddr1: Start of first address range Loading Loading
drivers/gpu/msm/adreno.c +8 −19 Original line number Diff line number Diff line Loading @@ -652,7 +652,7 @@ void adreno_cp_callback(struct adreno_device *adreno_dev, int bit) { struct kgsl_device *device = &adreno_dev->dev; queue_work(device->work_queue, &device->event_work); kgsl_schedule_work(&device->event_work); adreno_dispatcher_schedule(device); } Loading Loading @@ -1315,24 +1315,13 @@ static int _adreno_start(struct adreno_device *adreno_dev) adreno_writereg(adreno_dev, ADRENO_REG_RBBM_SECVID_TSB_CONTROL, 0x0); if (ADRENO_FEATURE(adreno_dev, ADRENO_64BIT) && MMU_FEATURE(&device->mmu, KGSL_MMU_64BIT)) { adreno_writereg64(adreno_dev, ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_BASE, ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_BASE_HI, KGSL_IOMMU_SECURE_BASE64); KGSL_IOMMU_SECURE_BASE); adreno_writereg(adreno_dev, ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_SIZE, KGSL_IOMMU_SECURE_SIZE64); } else { adreno_writereg64(adreno_dev, ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_BASE, ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_BASE_HI, KGSL_IOMMU_SECURE_BASE32); adreno_writereg(adreno_dev, ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_SIZE, KGSL_IOMMU_SECURE_SIZE32); } KGSL_IOMMU_SECURE_SIZE); } status = adreno_ocmem_malloc(adreno_dev); Loading
drivers/gpu/msm/adreno_a5xx.c +1 −1 Original line number Diff line number Diff line Loading @@ -2767,7 +2767,7 @@ static void a5xx_gpmu_int_callback(struct adreno_device *adreno_dev, int bit) /* Stop GPMU */ kgsl_regwrite(device, A5XX_GPMU_CM3_SYSRESET, 1); queue_work(device->work_queue, &adreno_dev->gpmu_work); kgsl_schedule_work(&adreno_dev->gpmu_work); KGSL_DRV_CRIT_RATELIMIT(device, "GPMU: Watchdog bite\n"); Loading
drivers/gpu/msm/adreno_dispatch.c +3 −3 Original line number Diff line number Diff line Loading @@ -2135,7 +2135,7 @@ static void adreno_dispatcher_work(struct work_struct *work) * stragglers */ if (dispatcher->inflight == 0 && count) queue_work(device->work_queue, &device->event_work); kgsl_schedule_work(&device->event_work); /* Try to dispatch new commands */ _adreno_dispatcher_issuecmds(adreno_dev); Loading Loading @@ -2188,7 +2188,7 @@ void adreno_dispatcher_schedule(struct kgsl_device *device) struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher; queue_work(device->work_queue, &dispatcher->work); kgsl_schedule_work(&dispatcher->work); } /** Loading Loading @@ -2577,7 +2577,7 @@ void adreno_preempt_process_dispatch_queue(struct adreno_device *adreno_dev, cmdbatch->expires = jiffies + msecs_to_jiffies(adreno_cmdbatch_timeout); } queue_work(device->work_queue, &device->event_work); kgsl_schedule_work(&device->event_work); } /** Loading
drivers/gpu/msm/kgsl.c +45 −34 Original line number Diff line number Diff line Loading @@ -228,13 +228,24 @@ int kgsl_readtimestamp(struct kgsl_device *device, void *priv, } EXPORT_SYMBOL(kgsl_readtimestamp); /* Scheduled by kgsl_mem_entry_put_deferred() */ static void _deferred_put(struct work_struct *work) { struct kgsl_mem_entry *entry = container_of(work, struct kgsl_mem_entry, work); kgsl_mem_entry_put(entry); } static inline struct kgsl_mem_entry * kgsl_mem_entry_create(void) { struct kgsl_mem_entry *entry = kzalloc(sizeof(*entry), GFP_KERNEL); if (entry) if (entry != NULL) { kref_init(&entry->refcount); INIT_WORK(&entry->work, _deferred_put); } return entry; } Loading Loading @@ -1256,6 +1267,8 @@ kgsl_sharedmem_find_id(struct kgsl_process_private *process, unsigned int id) int result = 0; struct kgsl_mem_entry *entry; drain_workqueue(kgsl_driver.mem_workqueue); spin_lock(&process->mem_lock); entry = idr_find(&process->mem_idr, id); if (entry) Loading Loading @@ -1833,8 +1846,7 @@ static long gpuobj_free_on_timestamp(struct kgsl_device_private *dev_priv, static void gpuobj_free_fence_func(void *priv) { struct kgsl_mem_entry *entry = priv; kgsl_mem_entry_put(entry); kgsl_mem_entry_put_deferred((struct kgsl_mem_entry *) priv); } static long gpuobj_free_on_fence(struct kgsl_device_private *dev_priv, Loading @@ -1844,15 +1856,22 @@ static long gpuobj_free_on_fence(struct kgsl_device_private *dev_priv, struct kgsl_gpu_event_fence event; long ret; if (!kgsl_mem_entry_set_pend(entry)) return -EBUSY; memset(&event, 0, sizeof(event)); ret = _copy_from_user(&event, to_user_ptr(param->priv), sizeof(event), param->len); if (ret) if (ret) { kgsl_mem_entry_unset_pend(entry); return ret; } if (event.fd < 0) if (event.fd < 0) { kgsl_mem_entry_unset_pend(entry); return -EINVAL; } handle = kgsl_sync_fence_async_wait(event.fd, gpuobj_free_fence_func, entry); Loading @@ -1861,7 +1880,12 @@ static long gpuobj_free_on_fence(struct kgsl_device_private *dev_priv, if (handle == NULL) return gpumem_free_entry(entry); return IS_ERR(handle) ? PTR_ERR(handle) : 0; if (IS_ERR(handle)) { kgsl_mem_entry_unset_pend(entry); return PTR_ERR(handle); } return 0; } long kgsl_ioctl_gpuobj_free(struct kgsl_device_private *dev_priv, Loading Loading @@ -2386,7 +2410,7 @@ static int kgsl_setup_dma_buf(struct kgsl_device *device, entry->memdesc.size = 0; entry->memdesc.mmapsize = 0; /* USE_CPU_MAP is not impemented for ION. */ entry->memdesc.flags &= ~KGSL_MEMFLAGS_USE_CPU_MAP; entry->memdesc.flags &= ~((uint64_t) KGSL_MEMFLAGS_USE_CPU_MAP); entry->memdesc.flags |= KGSL_MEMFLAGS_USERMEM_ION; sg_table = dma_buf_map_attachment(attach, DMA_TO_DEVICE); Loading Loading @@ -2483,10 +2507,11 @@ long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv, | KGSL_MEMALIGN_MASK | KGSL_MEMFLAGS_USE_CPU_MAP | KGSL_MEMFLAGS_SECURE; entry->memdesc.flags = param->flags | KGSL_MEMFLAGS_FORCE_32BIT; entry->memdesc.flags = ((uint64_t) param->flags) | KGSL_MEMFLAGS_FORCE_32BIT; if (!kgsl_mmu_use_cpu_map(&dev_priv->device->mmu)) entry->memdesc.flags &= ~KGSL_MEMFLAGS_USE_CPU_MAP; entry->memdesc.flags &= ~((uint64_t) KGSL_MEMFLAGS_USE_CPU_MAP); if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_IOMMU) entry->memdesc.priv |= KGSL_MEMDESC_GUARD_PAGE; Loading Loading @@ -2865,7 +2890,7 @@ static uint64_t kgsl_filter_cachemode(uint64_t flags) */ if ((flags & KGSL_CACHEMODE_MASK) >> KGSL_CACHEMODE_SHIFT == KGSL_CACHEMODE_WRITETHROUGH) { flags &= ~KGSL_CACHEMODE_MASK; flags &= ~((uint64_t) KGSL_CACHEMODE_MASK); flags |= (KGSL_CACHEMODE_WRITEBACK << KGSL_CACHEMODE_SHIFT) & KGSL_CACHEMODE_MASK; } Loading Loading @@ -2900,7 +2925,7 @@ static struct kgsl_mem_entry *gpumem_alloc_entry( /* Turn off SVM if the system doesn't support it */ if (!kgsl_mmu_use_cpu_map(&dev_priv->device->mmu)) flags &= ~KGSL_MEMFLAGS_USE_CPU_MAP; flags &= ~((uint64_t) KGSL_MEMFLAGS_USE_CPU_MAP); /* Return not supported error if secure memory isn't enabled */ if (!kgsl_mmu_is_secured(&dev_priv->device->mmu) && Loading @@ -2912,8 +2937,7 @@ static struct kgsl_mem_entry *gpumem_alloc_entry( /* Secure memory disables advanced addressing modes */ if (flags & KGSL_MEMFLAGS_SECURE) flags &= ~(KGSL_MEMFLAGS_USE_CPU_MAP | KGSL_MEMFLAGS_FORCE_32BIT); flags &= ~((uint64_t) KGSL_MEMFLAGS_USE_CPU_MAP); /* Cap the alignment bits to the highest number we can handle */ align = MEMFLAGS(flags, KGSL_MEMALIGN_MASK, KGSL_MEMALIGN_SHIFT); Loading @@ -2921,7 +2945,7 @@ static struct kgsl_mem_entry *gpumem_alloc_entry( KGSL_CORE_ERR("Alignment too large; restricting to %dK\n", KGSL_MAX_ALIGN >> 10); flags &= ~KGSL_MEMALIGN_MASK; flags &= ~((uint64_t) KGSL_MEMALIGN_MASK); flags |= (ilog2(KGSL_MAX_ALIGN) << KGSL_MEMALIGN_SHIFT) & KGSL_MEMALIGN_MASK; } Loading Loading @@ -3023,7 +3047,7 @@ long kgsl_ioctl_gpumem_alloc(struct kgsl_device_private *dev_priv, uint64_t flags = param->flags; /* Legacy functions doesn't support these advanced features */ flags &= ~KGSL_MEMFLAGS_USE_CPU_MAP; flags &= ~((uint64_t) KGSL_MEMFLAGS_USE_CPU_MAP); flags |= KGSL_MEMFLAGS_FORCE_32BIT; entry = gpumem_alloc_entry(dev_priv, (uint64_t) param->size, Loading Loading @@ -3145,7 +3169,7 @@ long kgsl_ioctl_gpuobj_set_info(struct kgsl_device_private *dev_priv, copy_metadata(entry, param->metadata, param->metadata_len); if (param->flags & KGSL_GPUOBJ_SET_INFO_TYPE) { entry->memdesc.flags &= ~KGSL_MEMTYPE_MASK; entry->memdesc.flags &= ~((uint64_t) KGSL_MEMTYPE_MASK); entry->memdesc.flags |= param->type << KGSL_MEMTYPE_SHIFT; } Loading Loading @@ -3882,20 +3906,10 @@ int kgsl_device_platform_probe(struct kgsl_device *device) setup_timer(&device->idle_timer, kgsl_timer, (unsigned long) device); /* Create our primary workqueue for events and power */ device->work_queue = create_singlethread_workqueue(device->name); if (device->work_queue == NULL) { status = -ENODEV; KGSL_DRV_ERR(device, "create_singelthreaded_workqueue(%s) failed\n", device->name); goto error_pwrctrl_close; } status = kgsl_mmu_init(device); if (status != 0) { KGSL_DRV_ERR(device, "kgsl_mmu_init failed %d\n", status); goto error_dest_work_q; goto error_pwrctrl_close; } /* Check to see if our device can perform DMA correctly */ Loading Loading @@ -3946,9 +3960,6 @@ int kgsl_device_platform_probe(struct kgsl_device *device) error_close_mmu: kgsl_mmu_close(device); error_dest_work_q: destroy_workqueue(device->work_queue); device->work_queue = NULL; error_pwrctrl_close: kgsl_pwrctrl_close(device); error: Loading @@ -3973,10 +3984,6 @@ void kgsl_device_platform_remove(struct kgsl_device *device) kgsl_mmu_close(device); if (device->work_queue) { destroy_workqueue(device->work_queue); device->work_queue = NULL; } kgsl_pwrctrl_close(device); _unregister_device(device); Loading Loading @@ -4073,6 +4080,10 @@ static int __init kgsl_core_init(void) INIT_LIST_HEAD(&kgsl_driver.pagetable_list); kgsl_driver.workqueue = create_singlethread_workqueue("kgsl-workqueue"); kgsl_driver.mem_workqueue = create_singlethread_workqueue("kgsl-mementry"); kgsl_mmu_set_mmutype(ksgl_mmu_type); kgsl_events_init(); Loading
drivers/gpu/msm/kgsl.h +47 −10 Original line number Diff line number Diff line Loading @@ -58,29 +58,38 @@ static inline void KGSL_STATS_ADD(uint64_t size, atomic_long_t *stat, struct kgsl_device; struct kgsl_context; /** * struct kgsl_driver - main container for global KGSL things * @cdev: Character device struct * @major: Major ID for the KGSL device * @class: Pointer to the class struct for the core KGSL sysfs entries * @virtdev: Virtual device for managing the core * @ptkobj: kobject for storing the pagetable statistics * @prockobj: kobject for storing the process statistics * @devp: Array of pointers to the individual KGSL device structs * @process_list: List of open processes * @pagetable_list: LIst of open pagetables * @ptlock: Lock for accessing the pagetable list * @process_mutex: Mutex for accessing the process list * @devlock: Mutex protecting the device list * @stats: Struct containing atomic memory statistics * @full_cache_threshold: the threshold that triggers a full cache flush * @workqueue: Pointer to a single threaded workqueue * @mem_workqueue: Pointer to a workqueue for deferring memory entries */ struct kgsl_driver { struct cdev cdev; dev_t major; struct class *class; /* Virtual device for managing the core */ struct device virtdev; /* Kobjects for storing pagetable and process statistics */ struct kobject *ptkobj; struct kobject *prockobj; struct kgsl_device *devp[KGSL_DEVICE_MAX]; /* Global lilst of open processes */ struct list_head process_list; /* Global list of pagetables */ struct list_head pagetable_list; /* Spinlock for accessing the pagetable list */ spinlock_t ptlock; /* Mutex for accessing the process list */ struct mutex process_mutex; /* Mutex for protecting the device list */ struct mutex devlock; struct { atomic_long_t vmalloc; atomic_long_t vmalloc_max; Loading @@ -94,6 +103,8 @@ struct kgsl_driver { atomic_long_t mapped_max; } stats; unsigned int full_cache_threshold; struct workqueue_struct *workqueue; struct workqueue_struct *mem_workqueue; }; extern struct kgsl_driver kgsl_driver; Loading Loading @@ -190,6 +201,7 @@ struct kgsl_memdesc { * are still references to it. * @dev_priv: back pointer to the device file that created this entry. * @metadata: String containing user specified metadata for the entry * @work: Work struct used to schedule a kgsl_mem_entry_put in atomic contexts */ struct kgsl_mem_entry { struct kref refcount; Loading @@ -200,6 +212,7 @@ struct kgsl_mem_entry { struct kgsl_process_private *priv; int pending_free; char metadata[KGSL_GPUOBJ_ALLOC_METADATA_MAX + 1]; struct work_struct work; }; struct kgsl_device_private; Loading Loading @@ -410,6 +423,15 @@ static inline int timestamp_cmp(unsigned int a, unsigned int b) return ((a > b) && (a - b <= KGSL_TIMESTAMP_WINDOW)) ? 1 : -1; } /** * kgsl_schedule_work() - Schedule a work item on the KGSL workqueue * @work: work item to schedule */ static inline void kgsl_schedule_work(struct work_struct *work) { queue_work(kgsl_driver.workqueue, work); } static inline int kgsl_mem_entry_get(struct kgsl_mem_entry *entry) { Loading @@ -422,6 +444,21 @@ kgsl_mem_entry_put(struct kgsl_mem_entry *entry) kref_put(&entry->refcount, kgsl_mem_entry_destroy); } /** * kgsl_mem_entry_put_deferred() - Schedule a task to put the memory entry * @entry: Mem entry to put * * This function is for atomic contexts where a normal kgsl_mem_entry_put() * would result in the memory entry getting destroyed and possibly taking * mutexes along the way. Schedule the work to happen outside of the atomic * context. */ static inline void kgsl_mem_entry_put_deferred(struct kgsl_mem_entry *entry) { if (entry != NULL) queue_work(kgsl_driver.mem_workqueue, &entry->work); } /* * kgsl_addr_range_overlap() - Checks if 2 ranges overlap * @gpuaddr1: Start of first address range Loading