diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 25eda4303a1..9385659d6cc 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -2335,7 +2335,7 @@ struct kgsl_driver kgsl_driver = { }; EXPORT_SYMBOL(kgsl_driver); -void kgsl_unregister_device(struct kgsl_device *device) +static void _unregister_device(struct kgsl_device *device) { int minor; @@ -2344,43 +2344,15 @@ void kgsl_unregister_device(struct kgsl_device *device) if (device == kgsl_driver.devp[minor]) break; } - - mutex_unlock(&kgsl_driver.devlock); - - if (minor == KGSL_DEVICE_MAX) - return; - - kgsl_device_snapshot_close(device); - - kgsl_cffdump_close(device->id); - kgsl_pwrctrl_uninit_sysfs(device); - - wake_lock_destroy(&device->idle_wakelock); - pm_qos_remove_request(&device->pm_qos_req_dma); - - idr_destroy(&device->context_idr); - - if (device->memstore.hostptr) - kgsl_sharedmem_free(&device->memstore); - - kgsl_mmu_close(device); - - if (device->work_queue) { - destroy_workqueue(device->work_queue); - device->work_queue = NULL; + if (minor != KGSL_DEVICE_MAX) { + device_destroy(kgsl_driver.class, + MKDEV(MAJOR(kgsl_driver.major), minor)); + kgsl_driver.devp[minor] = NULL; } - - device_destroy(kgsl_driver.class, - MKDEV(MAJOR(kgsl_driver.major), minor)); - - mutex_lock(&kgsl_driver.devlock); - kgsl_driver.devp[minor] = NULL; mutex_unlock(&kgsl_driver.devlock); } -EXPORT_SYMBOL(kgsl_unregister_device); -int -kgsl_register_device(struct kgsl_device *device) +static int _register_device(struct kgsl_device *device) { int minor, ret; dev_t dev; @@ -2394,7 +2366,6 @@ kgsl_register_device(struct kgsl_device *device) break; } } - mutex_unlock(&kgsl_driver.devlock); if (minor == KGSL_DEVICE_MAX) { @@ -2410,60 +2381,17 @@ kgsl_register_device(struct kgsl_device *device) device->name); if (IS_ERR(device->dev)) { + mutex_lock(&kgsl_driver.devlock); + kgsl_driver.devp[minor] = NULL; + mutex_unlock(&kgsl_driver.devlock); ret = PTR_ERR(device->dev); KGSL_CORE_ERR("device_create(%s): %d\n", device->name, ret); - goto err_devlist; + return ret; } dev_set_drvdata(device->parentdev, device); - - /* Generic device initialization */ - kgsl_cffdump_open(device->id); - - setup_timer(&device->idle_timer, kgsl_timer, (unsigned long) device); - ret = kgsl_create_device_workqueue(device); - if (ret) - goto err_devlist; - - device->last_expired_ctxt_id = KGSL_CONTEXT_INVALID; - ret = kgsl_mmu_init(device); - if (ret != 0) - goto err_dest_work_q; - - ret = kgsl_allocate_contiguous(&device->memstore, KGSL_MEMSTORE_SIZE); - if (ret != 0) - goto err_close_mmu; - - wake_lock_init(&device->idle_wakelock, WAKE_LOCK_IDLE, device->name); - pm_qos_add_request(&device->pm_qos_req_dma, PM_QOS_CPU_DMA_LATENCY, - PM_QOS_DEFAULT_VALUE); - - /* Initalize the snapshot engine */ - kgsl_device_snapshot_init(device); - - /* sysfs and debugfs initalization - failure here is non fatal */ - - /* Initialize logging */ - kgsl_device_debugfs_init(device); - - /* Initialize common sysfs entries */ - kgsl_pwrctrl_init_sysfs(device); - return 0; - -err_close_mmu: - kgsl_mmu_close(device); -err_dest_work_q: - destroy_workqueue(device->work_queue); - device->work_queue = NULL; -err_devlist: - mutex_lock(&kgsl_driver.devlock); - kgsl_driver.devp[minor] = NULL; - mutex_unlock(&kgsl_driver.devlock); - - return ret; } -EXPORT_SYMBOL(kgsl_register_device); int kgsl_device_platform_probe(struct kgsl_device *device) { @@ -2473,7 +2401,12 @@ int kgsl_device_platform_probe(struct kgsl_device *device) struct platform_device *pdev = container_of(device->parentdev, struct platform_device, dev); - pm_runtime_enable(device->parentdev); + status = _register_device(device); + if (status) + return status; + + /* Initialize logging first, so that failures below actually print. */ + kgsl_device_debugfs_init(device); status = kgsl_pwrctrl_init(device); if (status) @@ -2512,6 +2445,16 @@ int kgsl_device_platform_probe(struct kgsl_device *device) status = -ENODEV; goto error_release_mem; } + /*acquire interrupt */ + device->pwrctrl.interrupt_num = + platform_get_irq_byname(pdev, device->pwrctrl.irq_name); + + if (device->pwrctrl.interrupt_num <= 0) { + KGSL_DRV_ERR(device, "platform_get_irq_byname failed: %d\n", + device->pwrctrl.interrupt_num); + status = -EINVAL; + goto error_iounmap; + } status = request_irq(device->pwrctrl.interrupt_num, kgsl_irq_handler, IRQF_TRIGGER_HIGH, device->name, device); @@ -2520,7 +2463,6 @@ int kgsl_device_platform_probe(struct kgsl_device *device) device->pwrctrl.interrupt_num, status); goto error_iounmap; } - device->pwrctrl.have_irq = 1; disable_irq(device->pwrctrl.interrupt_num); KGSL_DRV_INFO(device, @@ -2530,14 +2472,50 @@ int kgsl_device_platform_probe(struct kgsl_device *device) result = kgsl_drm_init(pdev); if (result) - goto error_iounmap; + goto error_irq; - status = kgsl_register_device(device); - if (!status) - return status; + kgsl_cffdump_open(device->id); + setup_timer(&device->idle_timer, kgsl_timer, (unsigned long) device); + status = kgsl_create_device_workqueue(device); + if (status) + goto error_irq; + + status = kgsl_mmu_init(device); + if (status != 0) { + KGSL_DRV_ERR(device, "kgsl_mmu_init failed %d\n", status); + goto error_dest_work_q; + } + + status = kgsl_allocate_contiguous(&device->memstore, + sizeof(struct kgsl_devmemstore)); + + if (status != 0) { + KGSL_DRV_ERR(device, "kgsl_allocate_contiguous failed %d\n", + status); + goto error_close_mmu; + } + + wake_lock_init(&device->idle_wakelock, WAKE_LOCK_IDLE, device->name); + pm_qos_add_request(&device->pm_qos_req_dma, PM_QOS_CPU_DMA_LATENCY, + PM_QOS_DEFAULT_VALUE); + + /* Initalize the snapshot engine */ + kgsl_device_snapshot_init(device); + + /* Initialize common sysfs entries */ + kgsl_pwrctrl_init_sysfs(device); + + return 0; + +error_close_mmu: + kgsl_mmu_close(device); +error_dest_work_q: + destroy_workqueue(device->work_queue); + device->work_queue = NULL; +error_irq: free_irq(device->pwrctrl.interrupt_num, NULL); - device->pwrctrl.have_irq = 0; + device->pwrctrl.interrupt_num = 0; error_iounmap: iounmap(device->reg_virt); device->reg_virt = NULL; @@ -2546,22 +2524,45 @@ error_release_mem: error_pwrctrl_close: kgsl_pwrctrl_close(device); error: + _unregister_device(device); return status; } EXPORT_SYMBOL(kgsl_device_platform_probe); void kgsl_device_platform_remove(struct kgsl_device *device) { - kgsl_unregister_device(device); + kgsl_device_snapshot_close(device); + + kgsl_cffdump_close(device->id); + kgsl_pwrctrl_uninit_sysfs(device); + + wake_lock_destroy(&device->idle_wakelock); + pm_qos_remove_request(&device->pm_qos_req_dma); + + idr_destroy(&device->context_idr); + + kgsl_sharedmem_free(&device->memstore); + + kgsl_mmu_close(device); + + if (device->work_queue) { + destroy_workqueue(device->work_queue); + device->work_queue = NULL; + } if (device->reg_virt != NULL) { iounmap(device->reg_virt); device->reg_virt = NULL; release_mem_region(device->reg_phys, device->reg_len); } + if (device->pwrctrl.interrupt_num > 0) { + free_irq(device->pwrctrl.interrupt_num, NULL); + device->pwrctrl.interrupt_num = 0; + } + kgsl_pwrctrl_close(device); - pm_runtime_disable(device->parentdev); + _unregister_device(device); } EXPORT_SYMBOL(kgsl_device_platform_remove); diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c index 93657722bf1..3a29d719154 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.c +++ b/drivers/gpu/msm/kgsl_pwrctrl.c @@ -11,6 +11,7 @@ * */ #include +#include #include #include @@ -552,17 +553,8 @@ int kgsl_pwrctrl_init(struct kgsl_device *device) } } - /*acquire interrupt */ - pwr->interrupt_num = - platform_get_irq_byname(pdev, pwr->irq_name); - - if (pwr->interrupt_num <= 0) { - KGSL_PWR_ERR(device, "platform_get_irq_byname failed: %d\n", - pwr->interrupt_num); - result = -EINVAL; - goto done; - } + pm_runtime_enable(device->parentdev); register_early_suspend(&device->display_off); return result; @@ -582,16 +574,9 @@ void kgsl_pwrctrl_close(struct kgsl_device *device) KGSL_PWR_INFO(device, "close device %d\n", device->id); + pm_runtime_disable(device->parentdev); unregister_early_suspend(&device->display_off); - if (pwr->interrupt_num > 0) { - if (pwr->have_irq) { - free_irq(pwr->interrupt_num, NULL); - pwr->have_irq = 0; - } - pwr->interrupt_num = 0; - } - clk_put(pwr->ebi1_clk); if (pwr->pcl) diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h index 6325b66b323..1e5c21c2c2f 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.h +++ b/drivers/gpu/msm/kgsl_pwrctrl.h @@ -39,7 +39,6 @@ struct kgsl_busy { struct kgsl_pwrctrl { int interrupt_num; - int have_irq; struct clk *ebi1_clk; struct clk *grp_clks[KGSL_MAX_CLKS]; unsigned long power_flags;