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:
Jeremy Gebben
2012-05-16 09:00:22 -06:00
parent 84d75d0949
commit 4f5f0de6d9
3 changed files with 95 additions and 110 deletions
+92 -91
View File
@@ -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);
+3 -18
View File
@@ -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)
-1
View File
@@ -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;