summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilippe Langlais <philippe.langlais@linaro.org>2012-03-16 09:04:57 +0100
committerPhilippe Langlais <philippe.langlais@stericsson.com>2012-05-22 11:06:00 +0200
commit856aff154e275b826d71d16991e41b1ec72aad1f (patch)
tree25a40859821a0638f5c84dc4708673729455f120
parentc6edd75a89500109ee7a6baf929ac8748b077124 (diff)
bluetooth: Add wake locks for CG2900cg2900-android
This patch corrects some bad behavior for the CG2900 driver when system suspends. Wake locks are added to stop Android from suspending when chip should be contacted. Signed-off-by: Par-Gunnar Hjalmdahl <par-gunnar.p.hjalmdahl@stericsson.com>
-rw-r--r--drivers/staging/cg2900/bluetooth/cg2900_uart.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/drivers/staging/cg2900/bluetooth/cg2900_uart.c b/drivers/staging/cg2900/bluetooth/cg2900_uart.c
index adfc1b26e83..24d78c6c14c 100644
--- a/drivers/staging/cg2900/bluetooth/cg2900_uart.c
+++ b/drivers/staging/cg2900/bluetooth/cg2900_uart.c
@@ -34,6 +34,7 @@
#include <linux/tty.h>
#include <linux/tty_ldisc.h>
#include <linux/types.h>
+#include <linux/wakelock.h>
#include <linux/workqueue.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci.h>
@@ -324,6 +325,7 @@ struct uart_delayed_work_struct {
* @chip_dev: Chip device for current UART transport.
* @cts_irq: CTS interrupt for this UART.
* @cts_gpio: CTS GPIO for this UART.
+ * @wake_lock: Wake lock for keeping user space awake (for Android).
* @suspend_blocked: True if suspend operation is blocked in the framework.
* @pm_qos_latency: PM QoS structure.
*/
@@ -354,6 +356,7 @@ struct uart_info {
struct cg2900_chip_dev chip_dev;
int cts_irq;
int cts_gpio;
+ struct wake_lock wake_lock;
bool suspend_blocked;
struct pm_qos_request pm_qos_latency;
};
@@ -480,6 +483,10 @@ static irqreturn_t cts_interrupt(int irq, void *dev_id)
disable_irq_wake(irq);
#endif
disable_irq_nosync(irq);
+ if (!uart_info->suspend_blocked) {
+ wake_lock(&uart_info->wake_lock);
+ uart_info->suspend_blocked = true;
+ }
/* Create work and leave IRQ context. */
(void)create_work_item(uart_info, handle_cts_irq);
@@ -646,6 +653,7 @@ static void wake_up_chip(struct uart_info *uart_info)
goto finished;
if (!uart_info->suspend_blocked) {
+ wake_lock(&uart_info->wake_lock);
uart_info->suspend_blocked = true;
pm_qos_update_request(&uart_info->pm_qos_latency,
CG2900_PM_QOS_LATENCY);
@@ -770,6 +778,7 @@ static void set_chip_sleep_mode(struct work_struct *work)
dev_dbg(MAIN_DEV, "New sleep_state: CHIP_ASLEEP\n");
uart_info->sleep_state = CHIP_ASLEEP;
if (uart_info->suspend_blocked) {
+ wake_unlock(&uart_info->wake_lock);
uart_info->suspend_blocked = false;
pm_qos_update_request(&uart_info->pm_qos_latency,
PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE);
@@ -1475,6 +1484,7 @@ static void uart_set_chip_power(struct cg2900_chip_dev *dev, bool chip_on)
if (chip_on) {
if (!uart_info->suspend_blocked) {
+ wake_lock(&uart_info->wake_lock);
uart_info->suspend_blocked = true;
pm_qos_update_request(&uart_info->pm_qos_latency,
CG2900_PM_QOS_LATENCY);
@@ -1518,6 +1528,7 @@ static void uart_set_chip_power(struct cg2900_chip_dev *dev, bool chip_on)
}
if (uart_info->suspend_blocked) {
+ wake_unlock(&uart_info->wake_lock);
uart_info->suspend_blocked = false;
pm_qos_update_request(&uart_info->pm_qos_latency,
PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE);
@@ -2133,6 +2144,8 @@ static int __devinit cg2900_uart_probe(struct platform_device *pdev)
uart_info->chip_dev.pdev = pdev;
uart_info->chip_dev.dev = &pdev->dev;
uart_info->chip_dev.t_data = uart_info;
+ wake_lock_init(&uart_info->wake_lock, WAKE_LOCK_SUSPEND, NAME);
+ uart_info->suspend_blocked = false;
pm_qos_add_request(&uart_info->pm_qos_latency, PM_QOS_CPU_DMA_LATENCY,
PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE);
@@ -2233,6 +2246,7 @@ static int __devexit cg2900_uart_remove(struct platform_device *pdev)
hci_uart_unregister_proto(uart_info->hu->proto);
pm_qos_remove_request(&uart_info->pm_qos_latency);
+ wake_lock_destroy(&uart_info->wake_lock);
destroy_workqueue(uart_info->wq);
dev_info(MAIN_DEV, "CG2900 UART removed\n");