From 5b90412127abf9dfeb63680a5f6f9f2f79c69f55 Mon Sep 17 00:00:00 2001 From: Bartosz Markowski Date: Wed, 24 Aug 2011 13:40:45 +0200 Subject: cw1200: Fix release callback for PM device Release callback was missing in CW1200 PM device. Also fixed register_platfor_device which chan not be done more than once. PM device is allocating dyncmicly now. ST-Ericsson ID: 358127 Change-Id: I3a7a7a8e72433380d00c7e2781db44e2f3abdca1 Signed-off-by: Dmitry Tarnyagin Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/29386 Reviewed-by: Bartosz MARKOWSKI Tested-by: Bartosz MARKOWSKI Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/33516 Reviewed-by: Philippe LANGLAIS --- drivers/staging/cw1200/main.c | 6 +++- drivers/staging/cw1200/pm.c | 69 ++++++++++++++++++++++++++++++------------- drivers/staging/cw1200/pm.h | 3 +- 3 files changed, 56 insertions(+), 22 deletions(-) diff --git a/drivers/staging/cw1200/main.c b/drivers/staging/cw1200/main.c index 0c58b25594f..a75fa6d8c50 100644 --- a/drivers/staging/cw1200/main.c +++ b/drivers/staging/cw1200/main.c @@ -329,6 +329,11 @@ struct ieee80211_hw *cw1200_init_common(size_t priv_data_len) INIT_WORK(&priv->multicast_start_work, cw1200_multicast_start_work); INIT_WORK(&priv->multicast_stop_work, cw1200_multicast_stop_work); + if (unlikely(cw1200_pm_init(&priv->pm_state, priv))) { + ieee80211_free_hw(hw); + return NULL; + } + if (unlikely(cw1200_queue_stats_init(&priv->tx_queue_stats, CW1200_LINK_ID_AFTER_DTIM + 1))) { ieee80211_free_hw(hw); @@ -351,7 +356,6 @@ struct ieee80211_hw *cw1200_init_common(size_t priv_data_len) init_waitqueue_head(&priv->wsm_startup_done); wsm_buf_init(&priv->wsm_cmd_buf); tx_policy_init(priv); - cw1200_pm_init(&priv->pm_state, priv); return hw; } diff --git a/drivers/staging/cw1200/pm.c b/drivers/staging/cw1200/pm.c index 2e5c8085bf8..48e46e6c3f3 100644 --- a/drivers/staging/cw1200/pm.c +++ b/drivers/staging/cw1200/pm.c @@ -17,7 +17,8 @@ #include "sbus.h" static int cw1200_suspend_late(struct device *dev); -static int cw1200_pm_remove(struct platform_device *pdev); +static void cw1200_pm_release(struct device * dev); +static int cw1200_pm_probe(struct platform_device *pdev); /* private */ struct cw1200_suspend_state { @@ -30,40 +31,60 @@ struct cw1200_suspend_state { static struct dev_pm_ops cw1200_pm_ops = { .suspend_noirq = cw1200_suspend_late, }; + static struct platform_driver cw1200_power_driver = { - .remove = cw1200_pm_remove, + .probe = cw1200_pm_probe, .driver = { .name = "cw1200_power", .pm = &cw1200_pm_ops, }, }; -static struct platform_device cw1200_power_device = { - .name = "cw1200_power", -}; -static void cw1200_pm_init_common(struct cw1200_pm_state *pm, +static int cw1200_pm_init_common(struct cw1200_pm_state *pm, struct cw1200_common *priv) { + int ret; + spin_lock_init(&pm->lock); - cw1200_power_device.dev.platform_data = priv; - platform_device_register(&cw1200_power_device); - platform_driver_register(&cw1200_power_driver); + ret = platform_driver_register(&cw1200_power_driver); + if (ret) + return ret; + pm->pm_dev = platform_device_alloc("cw1200_power", 0); + if (!pm->pm_dev) { + platform_driver_unregister(&cw1200_power_driver); + return ENOMEM; + } + + pm->pm_dev->dev.platform_data = priv; + ret = platform_device_add(pm->pm_dev); + if (ret) { + kfree(pm->pm_dev); + pm->pm_dev = NULL; + } + + return ret; } static void cw1200_pm_deinit_common(struct cw1200_pm_state *pm) { platform_driver_unregister(&cw1200_power_driver); - platform_device_unregister(&cw1200_power_device); + if (pm->pm_dev) { + platform_device_unregister(pm->pm_dev); + kfree(pm->pm_dev); + pm->pm_dev = NULL; + } } #ifdef CONFIG_WAKELOCK -void cw1200_pm_init(struct cw1200_pm_state *pm, +int cw1200_pm_init(struct cw1200_pm_state *pm, struct cw1200_common *priv) { - cw1200_pm_init_common(pm, priv); - wake_lock_init(&pm->wakelock, - WAKE_LOCK_SUSPEND, "cw1200_wlan"); + int ret = cw1200_pm_init_common(pm, priv); + if (!ret) + wake_lock_init(&pm->wakelock, + WAKE_LOCK_SUSPEND, "cw1200_wlan"); + return ret; } void cw1200_pm_deinit(struct cw1200_pm_state *pm) @@ -91,12 +112,15 @@ static void cw1200_pm_stay_awake_tmo(unsigned long) { } -void cw1200_pm_init(struct cw1200_pm_state *pm) +int cw1200_pm_init(struct cw1200_pm_state *pm) { - cw1200_init_common(pm); - init_timer(&pm->stay_awake); - pm->stay_awake.data = (unsigned long)pm; - pm->stay_awake.function = cw1200_pm_stay_awake_tmo; + int ret = cw1200_pm_init_common(pm); + if (!ret) + init_timer(&pm->stay_awake); + pm->stay_awake.data = (unsigned long)pm; + pm->stay_awake.function = cw1200_pm_stay_awake_tmo; + } + return ret; } void cw1200_pm_deinit(struct cw1200_pm_state *pm) @@ -155,8 +179,13 @@ static int cw1200_suspend_late(struct device *dev) return 0; } -static int cw1200_pm_remove(struct platform_device *pdev) +static void cw1200_pm_release(struct device *dev) +{ +} + +static int cw1200_pm_probe(struct platform_device *pdev) { + pdev->dev.release = cw1200_pm_release; return 0; } diff --git a/drivers/staging/cw1200/pm.h b/drivers/staging/cw1200/pm.h index 433e5ec1139..0515f6cfb92 100644 --- a/drivers/staging/cw1200/pm.h +++ b/drivers/staging/cw1200/pm.h @@ -31,10 +31,11 @@ struct cw1200_pm_state { #else struct timer_list stay_awake; #endif + struct platform_device *pm_dev; spinlock_t lock; }; -void cw1200_pm_init(struct cw1200_pm_state *pm, +int cw1200_pm_init(struct cw1200_pm_state *pm, struct cw1200_common *priv); void cw1200_pm_deinit(struct cw1200_pm_state *pm); void cw1200_pm_stay_awake(struct cw1200_pm_state *pm, -- cgit v1.2.3