summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormullerf <mullerf@google.com>2021-07-20 22:10:43 -0700
committerjonerlin <jonerlin@google.com>2021-07-22 17:20:04 +0800
commitf554a2304b0a483b04a17822a3cb1f958ce80edd (patch)
treec94baa7cf25ee39eeee7d0087badb171bd7d3971
parentcbbfc2396418f529b94c771e12bbc0c3c8cd8741 (diff)
downloadbroadcom-android-gs-bluejay-5.10-android12L-d2.tar.gz
There might be a corner case where host_isr wakes the system from suspend and UART RTS goes low before nitrous_devcie_resume() gets executed (since pm_runtime_get puts a work in queue to request the device resume), but then goes low while a trnasfer is happening because SICD_STATUS_BUSY was not set yet. For that, handle SICD BUSY/IDLE through its own Rx index and move away from pm_runtime routines, as this isn't needed anymore. Test: Manual Bug: 193466272 Signed-off-by: mullerf <mullerf@google.com> Change-Id: I20ca5e865c4c100852166959abe055ddffc23075 Signed-off-by: jonerlin <jonerlin@google.com>
-rw-r--r--nitrous.c41
1 files changed, 17 insertions, 24 deletions
diff --git a/nitrous.c b/nitrous.c
index dda19b5..5926738 100644
--- a/nitrous.c
+++ b/nitrous.c
@@ -44,7 +44,7 @@ struct nitrous_bt_lpm {
int wake_polarity; /* 0: active low; 1: active high */
bool is_suspended; /* driver is in suspend state */
- bool host_irq_dev_pm_resumed;
+ bool uart_tx_dev_pm_resumed;
int irq_timesync; /* IRQ associated with TIMESYNC GPIO*/
int timesync_state;
@@ -56,7 +56,8 @@ struct nitrous_bt_lpm {
bool lpm_enabled;
struct nitrous_lpm_proc *proc;
struct logbuffer *log;
- int idle_btip_index;
+ int idle_bt_tx_ip_index;
+ int idle_bt_rx_ip_index;
};
#define PROC_BTWAKE 0
@@ -139,21 +140,10 @@ static irqreturn_t nitrous_host_wake_isr(int irq, void *data)
if (host_wake == 1) {
logbuffer_log(lpm->log, "host_wake_isr asserted");
pm_stay_awake(lpm->dev);
- /* Only resume device when needed to keep usage count synced.
- This is because some falling edges can be missed by irq. */
- if (!lpm->host_irq_dev_pm_resumed) {
- pm_runtime_get(lpm->dev);
- lpm->host_irq_dev_pm_resumed = true;
- }
+ exynos_update_ip_idle_status(lpm->idle_bt_rx_ip_index, STATUS_BUSY);
} else {
logbuffer_log(lpm->log, "host_wake_isr de-asserted");
- pm_runtime_mark_last_busy(lpm->dev);
- /* Only autosuspend device when needed to keep usage count synced.
- This is because some rising edges can be missed by irq. */
- if (lpm->host_irq_dev_pm_resumed) {
- pm_runtime_put_autosuspend(lpm->dev);
- lpm->host_irq_dev_pm_resumed = false;
- }
+ exynos_update_ip_idle_status(lpm->idle_bt_rx_ip_index, STATUS_IDLE);
pm_wakeup_dev_event(lpm->dev, NITROUS_AUTOSUSPEND_DELAY, false);
}
@@ -248,9 +238,7 @@ static void nitrous_lpm_runtime_disable(struct nitrous_bt_lpm *lpm)
pm_runtime_disable(lpm->dev);
pm_runtime_set_suspended(lpm->dev);
- /* Host IRQ has been freed, so safe to set this here */
- lpm->host_irq_dev_pm_resumed = false;
-
+ lpm->uart_tx_dev_pm_resumed = false;
lpm->lpm_enabled = false;
}
@@ -547,7 +535,8 @@ static int nitrous_rfkill_set_power(void *data, bool blocked)
dev_dbg(lpm->dev, "REG_ON: Low");
gpiod_set_value_cansleep(lpm->gpio_power, false);
msleep(30);
- exynos_update_ip_idle_status(lpm->idle_btip_index, STATUS_BUSY);
+ exynos_update_ip_idle_status(lpm->idle_bt_tx_ip_index, STATUS_BUSY);
+ exynos_update_ip_idle_status(lpm->idle_bt_rx_ip_index, STATUS_BUSY);
dev_dbg(lpm->dev, "REG_ON: High");
gpiod_set_value_cansleep(lpm->gpio_power, true);
@@ -563,7 +552,8 @@ static int nitrous_rfkill_set_power(void *data, bool blocked)
logbuffer_log(lpm->log, "Power down BT chip");
dev_dbg(lpm->dev, "REG_ON: Low");
gpiod_set_value_cansleep(lpm->gpio_power, false);
- exynos_update_ip_idle_status(lpm->idle_btip_index, STATUS_IDLE);
+ exynos_update_ip_idle_status(lpm->idle_bt_tx_ip_index, STATUS_IDLE);
+ exynos_update_ip_idle_status(lpm->idle_bt_rx_ip_index, STATUS_IDLE);
}
lpm->rfkill_blocked = blocked;
@@ -689,8 +679,11 @@ static int nitrous_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, lpm);
- lpm->idle_btip_index = exynos_get_idle_ip_index("bluetooth");
- exynos_update_ip_idle_status(lpm->idle_btip_index, STATUS_IDLE);
+ lpm->idle_bt_tx_ip_index = exynos_get_idle_ip_index("bluetooth-tx");
+ exynos_update_ip_idle_status(lpm->idle_bt_tx_ip_index, STATUS_IDLE);
+
+ lpm->idle_bt_rx_ip_index = exynos_get_idle_ip_index("bluetooth-rx");
+ exynos_update_ip_idle_status(lpm->idle_bt_rx_ip_index, STATUS_IDLE);
logbuffer_log(lpm->log, "probe: successful");
@@ -735,7 +728,7 @@ static int nitrous_suspend_device(struct device *dev)
(lpm->is_suspended ? "asleep" : "awake"));
nitrous_wake_controller(lpm, false);
- exynos_update_ip_idle_status(lpm->idle_btip_index, STATUS_IDLE);
+ exynos_update_ip_idle_status(lpm->idle_bt_tx_ip_index, STATUS_IDLE);
lpm->is_suspended = true;
return 0;
@@ -750,7 +743,7 @@ static int nitrous_resume_device(struct device *dev)
logbuffer_log(lpm->log, "resume_device from %s",
(lpm->is_suspended ? "asleep" : "awake"));
- exynos_update_ip_idle_status(lpm->idle_btip_index, STATUS_BUSY);
+ exynos_update_ip_idle_status(lpm->idle_bt_tx_ip_index, STATUS_BUSY);
nitrous_wake_controller(lpm, true);
lpm->is_suspended = false;