forked from rubenslte/android_kernel_samsung_msm8226
msm: kgsl: restructure common probe and remove
Initialization code was split between kgsl_device_probe and kgsl_register_device, which made the code unclear and error handling difficult. Now all initialization of data structures happens in probe, and kgsl_register_device only manages the /dev file. Change-Id: I85d49c305310b943ab7600762f1f230804a3b9a8 Signed-off-by: Jeremy Gebben <jgebben@codeaurora.org>
This commit is contained in:
+92
-91
@@ -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);
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
*
|
||||
*/
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <mach/msm_iomap.h>
|
||||
#include <mach/msm_bus.h>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user