From 6747b2697931fe6eb2b9f92b787be64f2f548690 Mon Sep 17 00:00:00 2001 From: Steve Kondik Date: Fri, 5 Jul 2013 10:40:01 -0700 Subject: 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 --- libbt/include/bt_vendor_brcm.h | 4 +++ libbt/src/bt_vendor_brcm.c | 9 ++++++- libbt/src/hardware.c | 60 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 1 deletion(-) 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. -- cgit v1.1