summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve Kondik <shade@chemlab.org>2013-07-05 10:40:01 -0700
committerSteve Kondik <shade@chemlab.org>2013-07-05 10:40:01 -0700
commit6747b2697931fe6eb2b9f92b787be64f2f548690 (patch)
tree146be832f2148cb073e719101e132cd0f08b6395
parent201208b201b9dfe79d7469b73c1b48b6a3e8b21f (diff)
downloaddevice_common-6747b2697931fe6eb2b9f92b787be64f2f548690.zip
device_common-6747b2697931fe6eb2b9f92b787be64f2f548690.tar.gz
device_common-6747b2697931fe6eb2b9f92b787be64f2f548690.tar.bz2
libbt: Add btlock support
* Concurrent WiFi/BT firmware loading can cause a chip crash. * Kernel supports a btlock device which is a simple semaphore that can protect from this situation. * Add support in the Bluedroid vendor lib for this on the BT side, as WiFi is already done directly in the kernel. Change-Id: I8b9d3b1ccd06cc5d5528c7d6d685048c258d9887
-rw-r--r--libbt/include/bt_vendor_brcm.h4
-rw-r--r--libbt/src/bt_vendor_brcm.c9
-rw-r--r--libbt/src/hardware.c60
3 files changed, 72 insertions, 1 deletions
diff --git a/libbt/include/bt_vendor_brcm.h b/libbt/include/bt_vendor_brcm.h
index 858b71b..4ba62ac 100644
--- a/libbt/include/bt_vendor_brcm.h
+++ b/libbt/include/bt_vendor_brcm.h
@@ -49,6 +49,10 @@
#define VENDOR_LIB_RUNTIME_TUNING_ENABLED FALSE
#endif
+#ifndef USE_AXI_BRIDGE_LOCK
+#define USE_AXI_BRIDGE_LOCK FALSE
+#endif
+
/* Run-time configuration file */
#ifndef VENDOR_LIB_CONF_FILE
#define VENDOR_LIB_CONF_FILE "/etc/bluetooth/bt_vendor.conf"
diff --git a/libbt/src/bt_vendor_brcm.c b/libbt/src/bt_vendor_brcm.c
index 9bd8922..eb9856d 100644
--- a/libbt/src/bt_vendor_brcm.c
+++ b/libbt/src/bt_vendor_brcm.c
@@ -53,6 +53,9 @@ void hw_lpm_set_wake_state(uint8_t wake_assert);
void hw_sco_config(void);
#endif
void vnd_load_conf(const char *p_path);
+#if (USE_AXI_BRIDGE_LOCK == TRUE)
+void axi_bridge_lock(int locked);
+#endif
/******************************************************************************
** Variables
@@ -137,8 +140,12 @@ static int op(bt_vendor_opcode_t opcode, void *param)
int *state = (int *) param;
if (*state == BT_VND_PWR_OFF)
upio_set_bluetooth_power(UPIO_BT_POWER_OFF);
- else if (*state == BT_VND_PWR_ON)
+ else if (*state == BT_VND_PWR_ON) {
+#if (USE_AXI_BRIDGE_LOCK == TRUE)
+ axi_bridge_lock(1);
+#endif
upio_set_bluetooth_power(UPIO_BT_POWER_ON);
+ }
}
break;
diff --git a/libbt/src/hardware.c b/libbt/src/hardware.c
index 45008ef..759e8a8 100644
--- a/libbt/src/hardware.c
+++ b/libbt/src/hardware.c
@@ -95,6 +95,15 @@
#define UINT16_TO_STREAM(p, u16) {*(p)++ = (uint8_t)(u16); *(p)++ = (uint8_t)((u16) >> 8);}
#define UINT32_TO_STREAM(p, u32) {*(p)++ = (uint8_t)(u32); *(p)++ = (uint8_t)((u32) >> 8); *(p)++ = (uint8_t)((u32) >> 16); *(p)++ = (uint8_t)((u32) >> 24);}
+#if (USE_AXI_BRIDGE_LOCK == TRUE)
+#define BTLOCK_DEV "/dev/btlock"
+static int btlock_cookie = 'B' | 'T'<<8 | '3'<<16 | '5'<<24;
+struct btlock {
+ int lock;
+ int cookie;
+};
+#endif
+
/******************************************************************************
** Local type definitions
******************************************************************************/
@@ -568,6 +577,53 @@ static uint8_t hw_config_read_bdaddr(HC_BT_HDR *p_buf)
}
#endif // (USE_CONTROLLER_BDADDR == TRUE)
+#if (USE_AXI_BRIDGE_LOCK == TRUE)
+/*******************************************************************************
+**
+** Function axi_bridge_lock
+**
+** Description Take semaphore to prevent concurrent BT/WiFi firmware loading
+**
+*******************************************************************************/
+void axi_bridge_lock(int locked)
+{
+ int fd = -1;
+ struct btlock lock;
+ int ret = 0;
+
+ ALOGI("axi_bridge_lock: locked=%d", locked);
+
+ fd = open(BTLOCK_DEV, O_WRONLY);
+ if (fd < 0)
+ {
+ ALOGE("axi_bridge_lock open failed: %s (%d)",
+ strerror(errno), errno);
+ return;
+ }
+
+ lock.lock = locked;
+ lock.cookie = btlock_cookie;
+
+ if (locked)
+ {
+ while ((ret = write(fd, &lock, sizeof(lock))) != 0) {
+ ALOGE("axi_bridge_lock acquire: %s (%d)",
+ strerror(errno), errno);
+ usleep(10000);
+ }
+ } else {
+ if (write(fd, &lock, sizeof(lock)) < 0)
+ {
+ ALOGE("axi_bridge_lock write failed: %s (%d)",
+ strerror(errno), errno);
+ }
+ }
+
+ if (fd >= 0)
+ close(fd);
+}
+#endif // USE_AXI_BRIDGE_LOCK
+
/*******************************************************************************
**
** Function hw_config_cback
@@ -713,6 +769,10 @@ void hw_config_cback(void *p_mem)
close(hw_cfg_cb.fw_fd);
hw_cfg_cb.fw_fd = -1;
+#if (USE_AXI_BRIDGE_LOCK == TRUE)
+ axi_bridge_lock(0);
+#endif
+
/* Normally the firmware patch configuration file
* sets the new starting baud rate at 115200.
* So, we need update host's baud rate accordingly.