summaryrefslogtreecommitdiff
path: root/drivers/bluetooth/sd8797/bt/bt_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/bluetooth/sd8797/bt/bt_main.c')
-rw-r--r--drivers/bluetooth/sd8797/bt/bt_main.c556
1 files changed, 355 insertions, 201 deletions
diff --git a/drivers/bluetooth/sd8797/bt/bt_main.c b/drivers/bluetooth/sd8797/bt/bt_main.c
index 6c5f26561381..c84704a1b5c7 100644
--- a/drivers/bluetooth/sd8797/bt/bt_main.c
+++ b/drivers/bluetooth/sd8797/bt/bt_main.c
@@ -37,6 +37,8 @@
#include <linux/platform_device.h>
#include <linux/wlan_plat.h>
+#include <linux/interrupt.h>
+
#include "bt_drv.h"
#include "mbt_char.h"
#include "bt_sdio.h"
@@ -65,33 +67,33 @@ static char fw_version[32] = "0.0.0.p0";
static struct class *chardev_class;
/** Interface specific variables */
-static int mbtchar_minor = 0;
-static int fmchar_minor = 0;
-static int nfcchar_minor = 0;
-static int debugchar_minor = 0;
+static int mbtchar_minor;
+static int fmchar_minor;
+static int nfcchar_minor;
+static int debugchar_minor;
/** Default Driver mode */
static int drv_mode = (DRV_MODE_BT | DRV_MODE_FM | DRV_MODE_NFC);
/** BT interface name */
-static char *bt_name = NULL;
+static char *bt_name;
/** FM interface name */
-static char *fm_name = NULL;
+static char *fm_name;
/** NFC interface name */
-static char *nfc_name = NULL;
+static char *nfc_name;
/** BT debug interface name */
-static char *debug_name = NULL;
+static char *debug_name;
/** Firmware flag */
static int fw = 1;
/** default powermode */
static int psmode = 1;
/** Init config file (MAC address, register etc.) */
-static char *init_cfg = NULL;
+static char *init_cfg;
/** Calibration config file (MAC address, init powe etc.) */
-static char *cal_cfg = NULL;
+static char *cal_cfg;
/** Init MAC address */
-static char *bt_mac = NULL;
+static char *bt_mac;
/** Setting mbt_drvdbg value based on DEBUG level */
#ifdef DEBUG_LEVEL1
@@ -111,9 +113,17 @@ int mbt_pm_keep_power = 1;
static int debug_intf = 1;
/** Enable minicard power-up/down */
-int minicard_pwrup = 1;
+static int minicard_pwrup = 1;
/** Pointer to struct with control hooks */
-struct wifi_platform_data *bt_control_data = NULL;
+static struct wifi_platform_data *bt_control_data;
+
+#define IORESOURCE_NAME "mrvl_bt_irq"
+#define DRIVER_NAME "bt hostwake"
+
+void mdev_poweroff(struct m_dev *m_dev);
+static struct resource *bt_irqres;
+static int irq_registered;
+static void bt_register_hostwake_irq(void *handle);
/**
* @brief Alloc bt device
@@ -328,19 +338,19 @@ bt_process_event(bt_private * priv, struct sk_buff *skb)
{
u8 ret = BT_STATUS_SUCCESS;
struct m_dev *m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
- BT_EVENT *pEvent;
+ BT_EVENT *pevent;
ENTER();
- pEvent = (BT_EVENT *) skb->data;
- if (pEvent->EC != 0xff) {
- PRINTM(CMD, "BT: Not Marvell Event=0x%x\n", pEvent->EC);
+ pevent = (BT_EVENT *) skb->data;
+ if (pevent->EC != 0xff) {
+ PRINTM(CMD, "BT: Not Marvell Event=0x%x\n", pevent->EC);
ret = BT_STATUS_FAILURE;
goto exit;
}
- switch (pEvent->data[0]) {
+ switch (pevent->data[0]) {
case BT_CMD_AUTO_SLEEP_MODE:
- if (pEvent->data[2] == BT_STATUS_SUCCESS) {
- if (pEvent->data[1] == BT_PS_ENABLE)
+ if (pevent->data[2] == BT_STATUS_SUCCESS) {
+ if (pevent->data[1] == BT_PS_ENABLE)
priv->adapter->psmode = 1;
else
priv->adapter->psmode = 0;
@@ -353,16 +363,16 @@ bt_process_event(bt_private * priv, struct sk_buff *skb)
}
break;
case BT_CMD_HOST_SLEEP_CONFIG:
- if (pEvent->data[3] == BT_STATUS_SUCCESS) {
+ if (pevent->data[3] == BT_STATUS_SUCCESS) {
PRINTM(CMD, "BT: %s: gpio=0x%x, gap=0x%x\n",
- m_dev->name, pEvent->data[1], pEvent->data[2]);
+ m_dev->name, pevent->data[1], pevent->data[2]);
} else {
PRINTM(CMD, "BT: %s: HSCFG Command Fail\n",
m_dev->name);
}
break;
case BT_CMD_HOST_SLEEP_ENABLE:
- if (pEvent->data[1] == BT_STATUS_SUCCESS) {
+ if (pevent->data[1] == BT_STATUS_SUCCESS) {
priv->adapter->hs_state = HS_ACTIVATED;
if (priv->adapter->suspend_fail == FALSE) {
#ifdef SDIO_SUSPEND_RESUME
@@ -386,45 +396,44 @@ bt_process_event(bt_private * priv, struct sk_buff *skb)
break;
case BT_CMD_MODULE_CFG_REQ:
if ((priv->bt_dev.sendcmdflag == TRUE) &&
- ((pEvent->data[1] == MODULE_BRINGUP_REQ)
- || (pEvent->data[1] == MODULE_SHUTDOWN_REQ))) {
- if (pEvent->data[1] == MODULE_BRINGUP_REQ) {
+ ((pevent->data[1] == MODULE_BRINGUP_REQ)
+ || (pevent->data[1] == MODULE_SHUTDOWN_REQ))) {
+ if (pevent->data[1] == MODULE_BRINGUP_REQ) {
PRINTM(CMD, "BT: EVENT %s:%s\n", m_dev->name,
- (pEvent->data[2] && (pEvent->data[2] !=
+ (pevent->data[2] && (pevent->data[2] !=
MODULE_CFG_RESP_ALREADY_UP))
? "Bring up Fail" : "Bring up success");
- priv->bt_dev.devType = pEvent->data[3];
+ priv->bt_dev.devType = pevent->data[3];
PRINTM(CMD, "devType:%s\n",
- (pEvent->data[3] ==
+ (pevent->data[3] ==
DEV_TYPE_AMP) ? "AMP controller" :
"BR/EDR controller");
- priv->bt_dev.devFeature = pEvent->data[4];
+ priv->bt_dev.devFeature = pevent->data[4];
PRINTM(CMD,
"devFeature: %s, %s, %s, %s, %s\n",
- ((pEvent->
+ ((pevent->
data[4] & DEV_FEATURE_BT) ?
"BT Feature" : "No BT Feature"),
- ((pEvent->
+ ((pevent->
data[4] & DEV_FEATURE_BTAMP) ?
"BTAMP Feature" : "No BTAMP Feature"),
- ((pEvent->
+ ((pevent->
data[4] & DEV_FEATURE_BLE) ?
"BLE Feature" : "No BLE Feature"),
- ((pEvent->
+ ((pevent->
data[4] & DEV_FEATURE_FM) ?
"FM Feature" : "No FM Feature"),
- ((pEvent->
+ ((pevent->
data[4] & DEV_FEATURE_NFC) ?
"NFC Feature" : "No NFC Feature"));
}
- if (pEvent->data[1] == MODULE_SHUTDOWN_REQ) {
+ if (pevent->data[1] == MODULE_SHUTDOWN_REQ) {
PRINTM(CMD, "BT: EVENT %s:%s\n", m_dev->name,
- (pEvent->
- data[2]) ? "Shut down Fail" :
- "Shut down success");
+ (pevent->data[2]) ? "Shut down Fail"
+ : "Shut down success");
}
- if (pEvent->data[2]) {
+ if (pevent->data[2]) {
priv->bt_dev.sendcmdflag = FALSE;
priv->adapter->cmd_complete = TRUE;
wake_up_interruptible(&priv->adapter->
@@ -436,14 +445,14 @@ bt_process_event(bt_private * priv, struct sk_buff *skb)
}
break;
case BT_EVENT_POWER_STATE:
- if (pEvent->data[1] == BT_PS_SLEEP)
+ if (pevent->data[1] == BT_PS_SLEEP)
priv->adapter->ps_state = PS_SLEEP;
PRINTM(CMD, "BT: EVENT %s:%s\n", m_dev->name,
(priv->adapter->ps_state) ? "PS_SLEEP" : "PS_AWAKE");
break;
case BT_CMD_SDIO_PULL_CFG_REQ:
- if (pEvent->data[pEvent->length - 1] == BT_STATUS_SUCCESS)
+ if (pevent->data[pevent->length - 1] == BT_STATUS_SUCCESS)
PRINTM(CMD, "BT: %s: SDIO pull configuration success\n",
m_dev->name);
@@ -454,7 +463,7 @@ bt_process_event(bt_private * priv, struct sk_buff *skb)
}
break;
default:
- PRINTM(CMD, "BT: Unknown Event=%d %s\n", pEvent->data[0],
+ PRINTM(CMD, "BT: Unknown Event=%d %s\n", pevent->data[0],
m_dev->name);
ret = BT_STATUS_FAILURE;
break;
@@ -507,14 +516,14 @@ bt_cmd_timeout_func(bt_adapter * adapter, u16 cmd)
*
* @param priv A pointer to bt_private structure
*
- * @return BT_STATUS_SUCCESS or BT_STATUS_FAILURE
+ * @return BT_STATUS_SUCCESS or BT_STATUS_FAILURE
*/
int
bt_send_reset_command(bt_private * priv)
{
struct sk_buff *skb = NULL;
u8 ret = BT_STATUS_SUCCESS;
- BT_HCI_CMD *pCmd;
+ BT_HCI_CMD *pcmd;
ENTER();
skb = bt_skb_alloc(sizeof(BT_HCI_CMD), GFP_ATOMIC);
if (skb == NULL) {
@@ -522,10 +531,10 @@ bt_send_reset_command(bt_private * priv)
ret = BT_STATUS_FAILURE;
goto exit;
}
- pCmd = (BT_HCI_CMD *) skb->tail;
- pCmd->ocf_ogf = (RESET_OGF << 10) | BT_CMD_RESET;
- pCmd->length = 0x00;
- pCmd->cmd_type = 0x00;
+ pcmd = (BT_HCI_CMD *) skb->data;
+ pcmd->ocf_ogf = (RESET_OGF << 10) | BT_CMD_RESET;
+ pcmd->length = 0x00;
+ pcmd->cmd_type = 0x00;
bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
skb_put(skb, 3);
skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
@@ -533,7 +542,7 @@ bt_send_reset_command(bt_private * priv)
priv->bt_dev.sendcmdflag = TRUE;
priv->bt_dev.send_cmd_ocf = BT_CMD_RESET;
priv->adapter->cmd_complete = FALSE;
- PRINTM(CMD, "Queue Reset Command(0x%x)\n", pCmd->ocf_ogf);
+ PRINTM(CMD, "Queue Reset Command(0x%x)\n", pcmd->ocf_ogf);
wake_up_interruptible(&priv->MainThread.waitQ);
if (!os_wait_interruptible_timeout
(priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
@@ -568,7 +577,7 @@ bt_send_module_cfg_cmd(bt_private * priv, int subcmd)
{
struct sk_buff *skb = NULL;
u8 ret = BT_STATUS_SUCCESS;
- BT_CMD *pCmd;
+ BT_CMD *pcmd;
ENTER();
skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
if (skb == NULL) {
@@ -576,18 +585,18 @@ bt_send_module_cfg_cmd(bt_private * priv, int subcmd)
ret = BT_STATUS_FAILURE;
goto exit;
}
- pCmd = (BT_CMD *) skb->data;
- pCmd->ocf_ogf = (VENDOR_OGF << 10) | BT_CMD_MODULE_CFG_REQ;
- pCmd->length = 1;
- pCmd->data[0] = subcmd;
+ pcmd = (BT_CMD *) skb->data;
+ pcmd->ocf_ogf = (VENDOR_OGF << 10) | BT_CMD_MODULE_CFG_REQ;
+ pcmd->length = 1;
+ pcmd->data[0] = subcmd;
bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
- skb_put(skb, sizeof(BT_CMD));
+ skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
skb_queue_head(&priv->adapter->tx_queue, skb);
priv->bt_dev.sendcmdflag = TRUE;
priv->bt_dev.send_cmd_ocf = BT_CMD_MODULE_CFG_REQ;
priv->adapter->cmd_complete = FALSE;
- PRINTM(CMD, "Queue module cfg Command(0x%x)\n", pCmd->ocf_ogf);
+ PRINTM(CMD, "Queue module cfg Command(0x%x)\n", pcmd->ocf_ogf);
wake_up_interruptible(&priv->MainThread.waitQ);
/*
On some Android platforms certain delay is needed for HCI daemon to
@@ -622,7 +631,7 @@ bt_enable_ps(bt_private * priv)
{
struct sk_buff *skb = NULL;
u8 ret = BT_STATUS_SUCCESS;
- BT_CMD *pCmd;
+ BT_CMD *pcmd;
ENTER();
skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
if (skb == NULL) {
@@ -630,25 +639,25 @@ bt_enable_ps(bt_private * priv)
ret = BT_STATUS_FAILURE;
goto exit;
}
- pCmd = (BT_CMD *) skb->data;
- pCmd->ocf_ogf = (VENDOR_OGF << 10) | BT_CMD_AUTO_SLEEP_MODE;
+ pcmd = (BT_CMD *) skb->data;
+ pcmd->ocf_ogf = (VENDOR_OGF << 10) | BT_CMD_AUTO_SLEEP_MODE;
if (priv->bt_dev.psmode)
- pCmd->data[0] = BT_PS_ENABLE;
+ pcmd->data[0] = BT_PS_ENABLE;
else
- pCmd->data[0] = BT_PS_DISABLE;
+ pcmd->data[0] = BT_PS_DISABLE;
if (priv->bt_dev.idle_timeout) {
- pCmd->length = 3;
- pCmd->data[1] = (u8) (priv->bt_dev.idle_timeout & 0x00ff);
- pCmd->data[2] = (priv->bt_dev.idle_timeout & 0xff00) >> 8;
+ pcmd->length = 3;
+ pcmd->data[1] = (u8) (priv->bt_dev.idle_timeout & 0x00ff);
+ pcmd->data[2] = (priv->bt_dev.idle_timeout & 0xff00) >> 8;
} else {
- pCmd->length = 1;
+ pcmd->length = 1;
}
bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
- skb_put(skb, sizeof(BT_CMD));
+ skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
skb_queue_head(&priv->adapter->tx_queue, skb);
- PRINTM(CMD, "Queue PSMODE Command(0x%x):%d\n", pCmd->ocf_ogf,
- pCmd->data[0]);
+ PRINTM(CMD, "Queue PSMODE Command(0x%x):%d\n", pcmd->ocf_ogf,
+ pcmd->data[0]);
priv->bt_dev.sendcmdflag = TRUE;
priv->bt_dev.send_cmd_ocf = BT_CMD_AUTO_SLEEP_MODE;
priv->adapter->cmd_complete = FALSE;
@@ -676,7 +685,7 @@ bt_send_hscfg_cmd(bt_private * priv)
{
struct sk_buff *skb = NULL;
u8 ret = BT_STATUS_SUCCESS;
- BT_CMD *pCmd;
+ BT_CMD *pcmd;
ENTER();
skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
if (skb == NULL) {
@@ -684,17 +693,17 @@ bt_send_hscfg_cmd(bt_private * priv)
ret = BT_STATUS_FAILURE;
goto exit;
}
- pCmd = (BT_CMD *) skb->data;
- pCmd->ocf_ogf = (VENDOR_OGF << 10) | BT_CMD_HOST_SLEEP_CONFIG;
- pCmd->length = 2;
- pCmd->data[0] = (priv->bt_dev.gpio_gap & 0xff00) >> 8;
- pCmd->data[1] = (u8) (priv->bt_dev.gpio_gap & 0x00ff);
+ pcmd = (BT_CMD *) skb->data;
+ pcmd->ocf_ogf = (VENDOR_OGF << 10) | BT_CMD_HOST_SLEEP_CONFIG;
+ pcmd->length = 2;
+ pcmd->data[0] = (priv->bt_dev.gpio_gap & 0xff00) >> 8;
+ pcmd->data[1] = (u8) (priv->bt_dev.gpio_gap & 0x00ff);
bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
- skb_put(skb, sizeof(BT_CMD));
+ skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
skb_queue_head(&priv->adapter->tx_queue, skb);
PRINTM(CMD, "Queue HSCFG Command(0x%x),gpio=0x%x,gap=0x%x\n",
- pCmd->ocf_ogf, pCmd->data[0], pCmd->data[1]);
+ pcmd->ocf_ogf, pcmd->data[0], pcmd->data[1]);
priv->bt_dev.sendcmdflag = TRUE;
priv->bt_dev.send_cmd_ocf = BT_CMD_HOST_SLEEP_CONFIG;
priv->adapter->cmd_complete = FALSE;
@@ -722,7 +731,7 @@ bt_send_sdio_pull_ctrl_cmd(bt_private * priv)
{
struct sk_buff *skb = NULL;
u8 ret = BT_STATUS_SUCCESS;
- BT_CMD *pCmd;
+ BT_CMD *pcmd;
ENTER();
skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
if (skb == NULL) {
@@ -730,21 +739,21 @@ bt_send_sdio_pull_ctrl_cmd(bt_private * priv)
ret = BT_STATUS_FAILURE;
goto exit;
}
- pCmd = (BT_CMD *) skb->data;
- pCmd->ocf_ogf = (VENDOR_OGF << 10) | BT_CMD_SDIO_PULL_CFG_REQ;
- pCmd->length = 4;
- pCmd->data[0] = (priv->bt_dev.sdio_pull_cfg & 0x000000ff);
- pCmd->data[1] = (priv->bt_dev.sdio_pull_cfg & 0x0000ff00) >> 8;
- pCmd->data[2] = (priv->bt_dev.sdio_pull_cfg & 0x00ff0000) >> 16;
- pCmd->data[3] = (priv->bt_dev.sdio_pull_cfg & 0xff000000) >> 24;
+ pcmd = (BT_CMD *) skb->data;
+ pcmd->ocf_ogf = (VENDOR_OGF << 10) | BT_CMD_SDIO_PULL_CFG_REQ;
+ pcmd->length = 4;
+ pcmd->data[0] = (priv->bt_dev.sdio_pull_cfg & 0x000000ff);
+ pcmd->data[1] = (priv->bt_dev.sdio_pull_cfg & 0x0000ff00) >> 8;
+ pcmd->data[2] = (priv->bt_dev.sdio_pull_cfg & 0x00ff0000) >> 16;
+ pcmd->data[3] = (priv->bt_dev.sdio_pull_cfg & 0xff000000) >> 24;
bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
- skb_put(skb, sizeof(BT_CMD));
+ skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
skb_queue_head(&priv->adapter->tx_queue, skb);
PRINTM(CMD,
"Queue SDIO PULL CFG Command(0x%x), PullUp=0x%x%x,PullDown=0x%x%x\n",
- pCmd->ocf_ogf, pCmd->data[1], pCmd->data[0],
- pCmd->data[3], pCmd->data[2]);
+ pcmd->ocf_ogf, pcmd->data[1], pcmd->data[0],
+ pcmd->data[3], pcmd->data[2]);
priv->bt_dev.sendcmdflag = TRUE;
priv->bt_dev.send_cmd_ocf = BT_CMD_SDIO_PULL_CFG_REQ;
priv->adapter->cmd_complete = FALSE;
@@ -776,7 +785,7 @@ fm_set_intr_mask(bt_private * priv, u32 mask)
{
struct sk_buff *skb = NULL;
u8 ret = BT_STATUS_SUCCESS;
- BT_CMD *pCmd;
+ BT_CMD *pcmd;
ENTER();
skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
@@ -785,14 +794,14 @@ fm_set_intr_mask(bt_private * priv, u32 mask)
ret = BT_STATUS_FAILURE;
goto exit;
}
- pCmd = (BT_CMD *) skb->data;
- pCmd->ocf_ogf = (VENDOR_OGF << 10) | FM_CMD;
- pCmd->length = 0x05;
- pCmd->data[0] = FM_SET_INTR_MASK;
- memcpy(&pCmd->data[1], &mask, sizeof(mask));
+ pcmd = (BT_CMD *) skb->data;
+ pcmd->ocf_ogf = (VENDOR_OGF << 10) | FM_CMD;
+ pcmd->length = 0x05;
+ pcmd->data[0] = FM_SET_INTR_MASK;
+ memcpy(&pcmd->data[1], &mask, sizeof(mask));
PRINTM(CMD, "FM set intr mask=0x%x\n", mask);
bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
- skb_put(skb, sizeof(BT_CMD));
+ skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
skb->dev = (void *)(&(priv->bt_dev.m_dev[FM_SEQ]));
skb_queue_head(&priv->adapter->tx_queue, skb);
priv->bt_dev.sendcmdflag = TRUE;
@@ -823,7 +832,7 @@ bt_enable_hs(bt_private * priv)
{
struct sk_buff *skb = NULL;
u8 ret = BT_STATUS_SUCCESS;
- BT_CMD *pCmd;
+ BT_CMD *pcmd;
ENTER();
skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
if (skb == NULL) {
@@ -832,16 +841,16 @@ bt_enable_hs(bt_private * priv)
goto exit;
}
priv->adapter->suspend_fail = FALSE;
- pCmd = (BT_CMD *) skb->data;
- pCmd->ocf_ogf = (VENDOR_OGF << 10) | BT_CMD_HOST_SLEEP_ENABLE;
- pCmd->length = 0;
+ pcmd = (BT_CMD *) skb->data;
+ pcmd->ocf_ogf = (VENDOR_OGF << 10) | BT_CMD_HOST_SLEEP_ENABLE;
+ pcmd->length = 0;
bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
- skb_put(skb, sizeof(BT_CMD));
+ skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
skb_queue_head(&priv->adapter->tx_queue, skb);
priv->bt_dev.sendcmdflag = TRUE;
priv->bt_dev.send_cmd_ocf = BT_CMD_HOST_SLEEP_ENABLE;
- PRINTM(CMD, "Queue hs enable Command(0x%x)\n", pCmd->ocf_ogf);
+ PRINTM(CMD, "Queue hs enable Command(0x%x)\n", pcmd->ocf_ogf);
wake_up_interruptible(&priv->MainThread.waitQ);
if (!os_wait_interruptible_timeout
(priv->adapter->cmd_wait_q, priv->adapter->hs_state,
@@ -884,7 +893,7 @@ bt_set_ble_deepsleep(bt_private * priv, int mode)
{
struct sk_buff *skb = NULL;
u8 ret = BT_STATUS_SUCCESS;
- BT_BLE_CMD *pCmd;
+ BT_BLE_CMD *pcmd;
ENTER();
skb = bt_skb_alloc(sizeof(BT_BLE_CMD), GFP_ATOMIC);
if (skb == NULL) {
@@ -892,10 +901,10 @@ bt_set_ble_deepsleep(bt_private * priv, int mode)
ret = BT_STATUS_FAILURE;
goto exit;
}
- pCmd = (BT_BLE_CMD *) skb->data;
- pCmd->ocf_ogf = (VENDOR_OGF << 10) | BT_CMD_BLE_DEEP_SLEEP;
- pCmd->length = 1;
- pCmd->deepsleep = mode;
+ pcmd = (BT_BLE_CMD *) skb->data;
+ pcmd->ocf_ogf = (VENDOR_OGF << 10) | BT_CMD_BLE_DEEP_SLEEP;
+ pcmd->length = 1;
+ pcmd->deepsleep = mode;
bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
skb_put(skb, sizeof(BT_BLE_CMD));
skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
@@ -903,7 +912,7 @@ bt_set_ble_deepsleep(bt_private * priv, int mode)
priv->bt_dev.sendcmdflag = TRUE;
priv->bt_dev.send_cmd_ocf = BT_CMD_BLE_DEEP_SLEEP;
priv->adapter->cmd_complete = FALSE;
- PRINTM(CMD, "BT: Set BLE deepsleep = %d (0x%x)\n", mode, pCmd->ocf_ogf);
+ PRINTM(CMD, "BT: Set BLE deepsleep = %d (0x%x)\n", mode, pcmd->ocf_ogf);
wake_up_interruptible(&priv->MainThread.waitQ);
if (!os_wait_interruptible_timeout
(priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
@@ -929,7 +938,7 @@ bt_get_fw_version(bt_private * priv)
{
struct sk_buff *skb = NULL;
u8 ret = BT_STATUS_SUCCESS;
- BT_HCI_CMD *pCmd;
+ BT_HCI_CMD *pcmd;
ENTER();
skb = bt_skb_alloc(sizeof(BT_HCI_CMD), GFP_ATOMIC);
if (skb == NULL) {
@@ -937,10 +946,10 @@ bt_get_fw_version(bt_private * priv)
ret = BT_STATUS_FAILURE;
goto exit;
}
- pCmd = (BT_HCI_CMD *) skb->data;
- pCmd->ocf_ogf = (VENDOR_OGF << 10) | BT_CMD_GET_FW_VERSION;
- pCmd->length = 0x01;
- pCmd->cmd_type = 0x00;
+ pcmd = (BT_HCI_CMD *) skb->data;
+ pcmd->ocf_ogf = (VENDOR_OGF << 10) | BT_CMD_GET_FW_VERSION;
+ pcmd->length = 0x01;
+ pcmd->cmd_type = 0x00;
bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
skb_put(skb, 4);
skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
@@ -974,7 +983,7 @@ bt_set_mac_address(bt_private * priv, u8 * mac)
{
struct sk_buff *skb = NULL;
u8 ret = BT_STATUS_SUCCESS;
- BT_HCI_CMD *pCmd;
+ BT_HCI_CMD *pcmd;
int i = 0;
ENTER();
skb = bt_skb_alloc(sizeof(BT_HCI_CMD), GFP_ATOMIC);
@@ -983,13 +992,13 @@ bt_set_mac_address(bt_private * priv, u8 * mac)
ret = BT_STATUS_FAILURE;
goto exit;
}
- pCmd = (BT_HCI_CMD *) skb->data;
- pCmd->ocf_ogf = (VENDOR_OGF << 10) | BT_CMD_CONFIG_MAC_ADDR;
- pCmd->length = 8;
- pCmd->cmd_type = MRVL_VENDOR_PKT;
- pCmd->cmd_len = 6;
+ pcmd = (BT_HCI_CMD *) skb->data;
+ pcmd->ocf_ogf = (VENDOR_OGF << 10) | BT_CMD_CONFIG_MAC_ADDR;
+ pcmd->length = 8;
+ pcmd->cmd_type = MRVL_VENDOR_PKT;
+ pcmd->cmd_len = 6;
for (i = 0; i < 6; i++)
- pCmd->data[i] = mac[5 - i];
+ pcmd->data[i] = mac[5 - i];
bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
skb_put(skb, sizeof(BT_HCI_CMD));
skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
@@ -997,8 +1006,8 @@ bt_set_mac_address(bt_private * priv, u8 * mac)
priv->bt_dev.sendcmdflag = TRUE;
priv->bt_dev.send_cmd_ocf = BT_CMD_CONFIG_MAC_ADDR;
priv->adapter->cmd_complete = FALSE;
- PRINTM(CMD, "BT: Set mac addr %02x:%02x:%02x:%02x:%02x:%02x (0x%x)\n",
- mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], pCmd->ocf_ogf);
+ PRINTM(CMD, "BT: Set mac addr " MACSTR " (0x%x)\n", MAC2STR(mac),
+ pcmd->ocf_ogf);
wake_up_interruptible(&priv->MainThread.waitQ);
if (!os_wait_interruptible_timeout
(priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
@@ -1026,11 +1035,11 @@ bt_load_cal_data(bt_private * priv, u8 * config_data, u8 * mac)
{
struct sk_buff *skb = NULL;
u8 ret = BT_STATUS_SUCCESS;
- BT_CMD *pCmd;
+ BT_CMD *pcmd;
int i = 0;
- // u8 config_data[28] = {0x37 0x01 0x1c 0x00 0xFF 0xFF 0xFF 0xFF
- // 0x01 0x7f 0x04 0x02 0x00 0x00 0xBA 0xCE
- // 0xC0 0xC6 0x2D 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xF0};
+ /* u8 config_data[28] = {0x37 0x01 0x1c 0x00 0xFF 0xFF 0xFF 0xFF 0x01
+ 0x7f 0x04 0x02 0x00 0x00 0xBA 0xCE 0xC0 0xC6 0x2D 0x00 0x00 0x00
+ 0x00 0x00 0x00 0x00 0xF0}; */
ENTER();
skb = bt_skb_alloc(sizeof(BT_CMD), GFP_ATOMIC);
@@ -1039,31 +1048,30 @@ bt_load_cal_data(bt_private * priv, u8 * config_data, u8 * mac)
ret = BT_STATUS_FAILURE;
goto exit;
}
- pCmd = (BT_CMD *) skb->data;
- pCmd->ocf_ogf = (VENDOR_OGF << 10) | BT_CMD_LOAD_CONFIG_DATA;
- pCmd->length = 0x20;
- pCmd->data[0] = 0x00;
- pCmd->data[1] = 0x00;
- pCmd->data[2] = 0x00;
- pCmd->data[3] = 0x1C;
- // swip cal-data byte
- for (i = 4; i < 32; i++) {
- pCmd->data[i] = config_data[(i / 4) * 8 - 1 - i];
- }
+ pcmd = (BT_CMD *) skb->data;
+ pcmd->ocf_ogf = (VENDOR_OGF << 10) | BT_CMD_LOAD_CONFIG_DATA;
+ pcmd->length = 0x20;
+ pcmd->data[0] = 0x00;
+ pcmd->data[1] = 0x00;
+ pcmd->data[2] = 0x00;
+ pcmd->data[3] = 0x1C;
+ /* swip cal-data byte */
+ for (i = 4; i < 32; i++)
+ pcmd->data[i] = config_data[(i / 4) * 8 - 1 - i];
if (mac != NULL) {
- pCmd->data[2] = 0x01; // skip checksum
+ pcmd->data[2] = 0x01; /* skip checksum */
for (i = 24; i < 30; i++)
- pCmd->data[i] = mac[29 - i];
+ pcmd->data[i] = mac[29 - i];
}
bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
- skb_put(skb, sizeof(BT_CMD));
+ skb_put(skb, BT_CMD_HEADER_SIZE + pcmd->length);
skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
skb_queue_head(&priv->adapter->tx_queue, skb);
priv->bt_dev.sendcmdflag = TRUE;
priv->bt_dev.send_cmd_ocf = BT_CMD_LOAD_CONFIG_DATA;
priv->adapter->cmd_complete = FALSE;
- DBG_HEXDUMP(DAT_D, "calirate data: ", pCmd->data, 32);
+ DBG_HEXDUMP(DAT_D, "calirate data: ", pcmd->data, 32);
wake_up_interruptible(&priv->MainThread.waitQ);
if (!os_wait_interruptible_timeout
(priv->adapter->cmd_wait_q, priv->adapter->cmd_complete,
@@ -1091,7 +1099,7 @@ bt_write_reg(bt_private * priv, u8 type, u32 offset, u16 value)
{
struct sk_buff *skb = NULL;
u8 ret = BT_STATUS_SUCCESS;
- BT_CSU_CMD *pCmd;
+ BT_CSU_CMD *pcmd;
ENTER();
skb = bt_skb_alloc(sizeof(BT_CSU_CMD), GFP_ATOMIC);
if (skb == NULL) {
@@ -1099,16 +1107,16 @@ bt_write_reg(bt_private * priv, u8 type, u32 offset, u16 value)
ret = BT_STATUS_FAILURE;
goto exit;
}
- pCmd = (BT_CSU_CMD *) skb->data;
- pCmd->ocf_ogf = (VENDOR_OGF << 10) | BT_CMD_CSU_WRITE_REG;
- pCmd->length = 7;
- pCmd->type = type;
- pCmd->offset[0] = (offset & 0x000000ff);
- pCmd->offset[1] = (offset & 0x0000ff00) >> 8;
- pCmd->offset[2] = (offset & 0x00ff0000) >> 16;
- pCmd->offset[3] = (offset & 0xff000000) >> 24;
- pCmd->value[0] = (value & 0x00ff);
- pCmd->value[1] = (value & 0xff00) >> 8;
+ pcmd = (BT_CSU_CMD *) skb->data;
+ pcmd->ocf_ogf = (VENDOR_OGF << 10) | BT_CMD_CSU_WRITE_REG;
+ pcmd->length = 7;
+ pcmd->type = type;
+ pcmd->offset[0] = (offset & 0x000000ff);
+ pcmd->offset[1] = (offset & 0x0000ff00) >> 8;
+ pcmd->offset[2] = (offset & 0x00ff0000) >> 16;
+ pcmd->offset[3] = (offset & 0xff000000) >> 24;
+ pcmd->value[0] = (value & 0x00ff);
+ pcmd->value[1] = (value & 0xff00) >> 8;
bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
skb_put(skb, sizeof(BT_CSU_CMD));
skb->dev = (void *)(&(priv->bt_dev.m_dev[BT_SEQ]));
@@ -1143,7 +1151,8 @@ bt_restore_tx_queue(bt_private * priv)
struct sk_buff *skb = NULL;
while (!skb_queue_empty(&priv->adapter->pending_queue)) {
skb = skb_dequeue(&priv->adapter->pending_queue);
- skb_queue_tail(&priv->adapter->tx_queue, skb);
+ if (skb)
+ skb_queue_tail(&priv->adapter->tx_queue, skb);
}
wake_up_interruptible(&priv->MainThread.waitQ);
}
@@ -1198,7 +1207,7 @@ bt_prepare_command(bt_private * priv)
* @return BT_STATUS_SUCCESS or BT_STATUS_FAILURE
*/
static int
-SendSinglePacket(bt_private * priv, struct sk_buff *skb)
+send_single_packet(bt_private * priv, struct sk_buff *skb)
{
int ret;
ENTER();
@@ -1298,11 +1307,11 @@ done:
void
bt_free_adapter(bt_private * priv)
{
- bt_adapter *Adapter = priv->adapter;
+ bt_adapter *adapter = priv->adapter;
ENTER();
skb_queue_purge(&priv->adapter->tx_queue);
/* Free the adapter object itself */
- kfree(Adapter);
+ kfree(adapter);
priv->adapter = NULL;
LEAVE();
@@ -1382,7 +1391,7 @@ mdev_send_frame(struct m_dev *m_dev, struct sk_buff *skb)
priv->debug_device_pending = 1;
priv->debug_ocf_ogf[0] = skb->data[0];
priv->debug_ocf_ogf[1] = skb->data[1];
- PRINTM(CMD, "debug_ocf_ogf[0]=0x%x debug_ocf_ogf[1]=0x%x \n",
+ PRINTM(CMD, "debug_ocf_ogf[0]=0x%x debug_ocf_ogf[1]=0x%x\n",
priv->debug_ocf_ogf[0], priv->debug_ocf_ogf[1]);
}
@@ -1522,6 +1531,7 @@ init_m_dev(struct m_dev *m_dev)
m_dev->ioctl = mdev_ioctl;
m_dev->query = mdev_query;
m_dev->owner = THIS_MODULE;
+ m_dev->poweroff = mdev_poweroff;
}
@@ -1538,7 +1548,7 @@ bt_service_main_thread(void *data)
{
bt_thread *thread = data;
bt_private *priv = thread->priv;
- bt_adapter *Adapter = priv->adapter;
+ bt_adapter *adapter = priv->adapter;
wait_queue_t wait;
struct sk_buff *skb;
ENTER();
@@ -1558,17 +1568,17 @@ bt_service_main_thread(void *data)
}
OS_SET_THREAD_STATE(TASK_RUNNING);
remove_wait_queue(&thread->waitQ, &wait);
- if (kthread_should_stop() || Adapter->SurpriseRemoved) {
+ if (kthread_should_stop() || adapter->SurpriseRemoved) {
PRINTM(INFO, "main-thread: break from main thread: "
"SurpriseRemoved=0x%x\n",
- Adapter->SurpriseRemoved);
+ adapter->SurpriseRemoved);
break;
}
PRINTM(INFO, "Main: Thread waking up...\n");
if (priv->adapter->IntCounter) {
OS_INT_DISABLE;
- Adapter->IntCounter = 0;
+ adapter->IntCounter = 0;
OS_INT_RESTORE;
sbi_get_int_status(priv);
} else if ((priv->adapter->ps_state == PS_SLEEP) &&
@@ -1583,7 +1593,7 @@ bt_service_main_thread(void *data)
if (!skb_queue_empty(&priv->adapter->tx_queue)) {
skb = skb_dequeue(&priv->adapter->tx_queue);
if (skb) {
- if (SendSinglePacket(priv, skb))
+ if (send_single_packet(priv, skb))
((struct m_dev *)skb->dev)->
stat.err_tx++;
else
@@ -1629,6 +1639,75 @@ bt_interrupt(struct m_dev *m_dev)
LEAVE();
}
+static void
+char_dev_release_dynamic(struct kobject *kobj)
+{
+ struct char_dev *cdev = container_of(kobj, struct char_dev, kobj);
+ ENTER();
+ PRINTM(INFO, "free char_dev\n");
+ kfree(cdev);
+ LEAVE();
+}
+
+static struct kobj_type ktype_char_dev_dynamic = {
+ .release = char_dev_release_dynamic,
+};
+
+static struct char_dev *
+alloc_char_dev(void)
+{
+ struct char_dev *cdev;
+ ENTER();
+ cdev = kzalloc(sizeof(struct char_dev), GFP_KERNEL);
+ if (cdev) {
+ kobject_init(&cdev->kobj, &ktype_char_dev_dynamic);
+ PRINTM(INFO, "alloc char_dev\n");
+ }
+ return cdev;
+}
+
+static void
+bt_private_dynamic_release(struct kobject *kobj)
+{
+ bt_private *priv = container_of(kobj, bt_private, kobj);
+ ENTER();
+ PRINTM(INFO, "free bt priv\n");
+ kfree(priv);
+ LEAVE();
+}
+
+static struct kobj_type ktype_bt_private_dynamic = {
+ .release = bt_private_dynamic_release,
+};
+
+static bt_private *
+bt_alloc_priv(void)
+{
+ bt_private *priv;
+ ENTER();
+ priv = kzalloc(sizeof(bt_private), GFP_KERNEL);
+ if (priv) {
+ kobject_init(&priv->kobj, &ktype_bt_private_dynamic);
+ PRINTM(INFO, "alloc bt priv\n");
+ }
+ LEAVE();
+ return priv;
+}
+
+struct kobject *
+bt_priv_get(bt_private * priv)
+{
+ PRINTM(INFO, "bt priv get object");
+ return kobject_get(&priv->kobj);
+}
+
+void
+bt_priv_put(bt_private * priv)
+{
+ PRINTM(INFO, "bt priv put object");
+ kobject_put(&priv->kobj);
+}
+
/**
* @brief Module configuration and register device
*
@@ -1693,7 +1772,8 @@ sbi_register_conf_dpc(bt_private * priv)
}
}
#ifdef SDIO_SUSPEND_RESUME
- priv->bt_dev.gpio_gap = 0xffff;
+
+ priv->bt_dev.gpio_gap = 0x0464;
ret = bt_send_hscfg_cmd(priv);
if (ret < 0) {
PRINTM(FATAL, "Send HSCFG failed!\n");
@@ -1708,7 +1788,7 @@ sbi_register_conf_dpc(bt_private * priv)
priv->bt_dev.m_dev[BT_SEQ].dev_type = BT_AMP_TYPE;
}
/* block all the packet from bluez */
- if (init_cfg || cal_cfg)
+ if (init_cfg || cal_cfg || bt_mac)
priv->adapter->tx_lock = TRUE;
if (mbt_dev) {
@@ -1726,7 +1806,7 @@ sbi_register_conf_dpc(bt_private * priv)
atomic_set(&mbt_dev->promisc, 0);
/** alloc char dev node */
- char_dev = kzalloc(sizeof(struct char_dev), GFP_KERNEL);
+ char_dev = alloc_char_dev();
if (!char_dev) {
class_destroy(chardev_class);
ret = -ENOMEM;
@@ -1748,6 +1828,10 @@ sbi_register_conf_dpc(bt_private * priv)
mbtchar_minor++;
PRINTM(MSG, "BT: Create %s\n", dev_file);
+ /** register m_dev to BT char device */
+ priv->bt_dev.m_dev[BT_SEQ].index = char_dev->minor;
+ char_dev->m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
+
/** create BT char device node */
register_char_dev(char_dev, chardev_class, MODULE_NAME,
mbt_dev->name);
@@ -1756,10 +1840,6 @@ sbi_register_conf_dpc(bt_private * priv)
mbtchar_chown(dev_file, AID_SYSTEM, AID_BLUETOOTH);
mbtchar_chmod(dev_file, 0666);
- /** register m_dev to BT char device */
- priv->bt_dev.m_dev[BT_SEQ].index = char_dev->minor;
- char_dev->m_dev = &(priv->bt_dev.m_dev[BT_SEQ]);
-
/** create proc device */
snprintf(priv->bt_dev.m_dev[BT_SEQ].name,
sizeof(priv->bt_dev.m_dev[BT_SEQ].name),
@@ -1788,7 +1868,7 @@ sbi_register_conf_dpc(bt_private * priv)
priv->bt_dev.m_dev[FM_SEQ].read_continue_flag = 0;
/** create char device for FM */
- char_dev = kzalloc(sizeof(struct char_dev), GFP_KERNEL);
+ char_dev = alloc_char_dev();
if (!char_dev) {
class_destroy(chardev_class);
ret = -ENOMEM;
@@ -1807,6 +1887,10 @@ sbi_register_conf_dpc(bt_private * priv)
PRINTM(MSG, "BT: Create %s\n", dev_file);
fmchar_minor++;
+ /** register m_dev to FM char device */
+ priv->bt_dev.m_dev[FM_SEQ].index = char_dev->minor;
+ char_dev->m_dev = &(priv->bt_dev.m_dev[FM_SEQ]);
+
/** register char dev */
register_char_dev(char_dev, chardev_class,
MODULE_NAME, fm_dev->name);
@@ -1814,10 +1898,6 @@ sbi_register_conf_dpc(bt_private * priv)
/** chmod for FM char device */
mbtchar_chmod(dev_file, 0666);
- /** register m_dev to FM char device */
- priv->bt_dev.m_dev[FM_SEQ].index = char_dev->minor;
- char_dev->m_dev = &(priv->bt_dev.m_dev[FM_SEQ]);
-
/** create proc device */
snprintf(priv->bt_dev.m_dev[FM_SEQ].name,
sizeof(priv->bt_dev.m_dev[FM_SEQ].name), fm_dev->name);
@@ -1845,7 +1925,7 @@ sbi_register_conf_dpc(bt_private * priv)
priv->bt_dev.m_dev[NFC_SEQ].read_continue_flag = 0;
/** create char device for NFC */
- char_dev = kzalloc(sizeof(struct char_dev), GFP_KERNEL);
+ char_dev = alloc_char_dev();
if (!char_dev) {
class_destroy(chardev_class);
ret = -ENOMEM;
@@ -1863,6 +1943,10 @@ sbi_register_conf_dpc(bt_private * priv)
PRINTM(MSG, "BT: Create %s\n", dev_file);
nfcchar_minor++;
+ /** register m_dev to NFC char device */
+ priv->bt_dev.m_dev[NFC_SEQ].index = char_dev->minor;
+ char_dev->m_dev = &(priv->bt_dev.m_dev[NFC_SEQ]);
+
/** register char dev */
register_char_dev(char_dev, chardev_class, MODULE_NAME,
nfc_dev->name);
@@ -1870,10 +1954,6 @@ sbi_register_conf_dpc(bt_private * priv)
/** chmod for NFC char device */
mbtchar_chmod(dev_file, 0666);
- /** register m_dev to NFC char device */
- priv->bt_dev.m_dev[NFC_SEQ].index = char_dev->minor;
- char_dev->m_dev = &(priv->bt_dev.m_dev[NFC_SEQ]);
-
/** create proc device */
snprintf(priv->bt_dev.m_dev[NFC_SEQ].name,
sizeof(priv->bt_dev.m_dev[NFC_SEQ].name),
@@ -1900,7 +1980,7 @@ sbi_register_conf_dpc(bt_private * priv)
priv->bt_dev.m_dev[DEBUG_SEQ].driver_data = priv;
/** create char device for Debug */
- char_dev = kzalloc(sizeof(struct char_dev), GFP_KERNEL);
+ char_dev = alloc_char_dev();
if (!char_dev) {
class_destroy(chardev_class);
ret = -ENOMEM;
@@ -1919,16 +1999,14 @@ sbi_register_conf_dpc(bt_private * priv)
debugchar_minor++;
/** register char dev */
+ priv->bt_dev.m_dev[DEBUG_SEQ].index = char_dev->minor;
+ char_dev->m_dev = &(priv->bt_dev.m_dev[DEBUG_SEQ]);
register_char_dev(char_dev, chardev_class, MODULE_NAME,
debug_dev->name);
/** chmod for debug char device */
mbtchar_chmod(dev_file, 0666);
- /** register m_dev to debug char device */
- priv->bt_dev.m_dev[DEBUG_SEQ].index = char_dev->minor;
- char_dev->m_dev = &(priv->bt_dev.m_dev[DEBUG_SEQ]);
-
/** create proc device */
snprintf(priv->bt_dev.m_dev[DEBUG_SEQ].name,
sizeof(priv->bt_dev.m_dev[DEBUG_SEQ].name),
@@ -1954,7 +2032,7 @@ sbi_register_conf_dpc(bt_private * priv)
goto done;
}
- if (cal_cfg)
+ if (cal_cfg) {
if (BT_STATUS_SUCCESS != bt_cal_config(priv, cal_cfg, bt_mac)) {
PRINTM(FATAL, "BT: Set cal data failed\n");
if (mbt_dev) {
@@ -1970,11 +2048,24 @@ sbi_register_conf_dpc(bt_private * priv)
ret = BT_STATUS_FAILURE;
goto done;
}
- if (init_cfg || cal_cfg) {
+ } else if (bt_mac) {
+ PRINTM(INFO,
+ "Set BT mac_addr from insmod parametre bt_mac = %s\n",
+ bt_mac);
+ if (BT_STATUS_SUCCESS != bt_init_mac_address(priv, bt_mac)) {
+ PRINTM(FATAL,
+ "BT: Fail to set mac address from insmod parametre\n");
+ ret = BT_STATUS_FAILURE;
+ goto done;
+ }
+ }
+ if (init_cfg || cal_cfg || bt_mac) {
priv->adapter->tx_lock = FALSE;
bt_restore_tx_queue(priv);
}
+ bt_register_hostwake_irq(NULL);
+
/* Get FW version */
bt_get_fw_version(priv);
snprintf(priv->adapter->drv_ver, MAX_VER_STR_LEN,
@@ -2007,7 +2098,7 @@ bt_add_card(void *card)
ENTER();
- priv = kzalloc(sizeof(bt_private), GFP_KERNEL);
+ priv = bt_alloc_priv();
if (!priv) {
PRINTM(FATAL, "Can not allocate priv\n");
LEAVE();
@@ -2015,7 +2106,8 @@ bt_add_card(void *card)
}
/* allocate buffer for bt_adapter */
- if (!(priv->adapter = kzalloc(sizeof(bt_adapter), GFP_KERNEL))) {
+ priv->adapter = kzalloc(sizeof(bt_adapter), GFP_KERNEL);
+ if (!priv->adapter) {
PRINTM(FATAL, "Allocate buffer for bt_adapter failed!\n");
goto err_kmalloc;
}
@@ -2067,7 +2159,7 @@ err_registerdev:
err_kmalloc:
if (priv->adapter)
bt_free_adapter(priv);
- kfree(priv);
+ bt_priv_put(priv);
LEAVE();
return NULL;
}
@@ -2157,7 +2249,7 @@ bt_remove_card(void *card)
}
PRINTM(INFO, "Free Adapter\n");
bt_free_adapter(priv);
- kfree(priv);
+ bt_priv_put(priv);
LEAVE();
return BT_STATUS_SUCCESS;
@@ -2172,7 +2264,7 @@ bt_remove_card(void *card)
static int
bt_set_carddetect(int on)
{
- PRINTM(MSG, "%s = %d\n", __FUNCTION__, on);
+ PRINTM(MSG, "%s = %d\n", __func__, on);
if (bt_control_data && bt_control_data->set_carddetect)
bt_control_data->set_carddetect(on);
@@ -2188,7 +2280,7 @@ bt_set_carddetect(int on)
static int
bt_set_power(int on, unsigned long msec)
{
- PRINTM(MSG, "%s = %d\n", __FUNCTION__, on);
+ PRINTM(MSG, "%s = %d\n", __func__, on);
if (bt_control_data && bt_control_data->set_power)
bt_control_data->set_power(on);
@@ -2197,6 +2289,58 @@ bt_set_power(int on, unsigned long msec)
return 0;
}
+static irqreturn_t
+bt_hostwake_isr(int irq, void *dev_id)
+{
+ PRINTM(INTR, "Recv hostwake isr\n");
+ return IRQ_HANDLED;
+}
+
+void
+bt_enable_hostwake_irq(int flag)
+{
+ if (bt_irqres && irq_registered) {
+ PRINTM(INTR, "enable_hostwake_irq=%d\n", flag);
+ if (flag) {
+ enable_irq(bt_irqres->start);
+ enable_irq_wake(bt_irqres->start);
+ } else {
+ disable_irq_wake(bt_irqres->start);
+ disable_irq(bt_irqres->start);
+ }
+ }
+}
+
+static void
+bt_register_hostwake_irq(void *handle)
+{
+ if (bt_irqres && !irq_registered) {
+ irq_registered =
+ request_irq(bt_irqres->start, bt_hostwake_isr,
+ bt_irqres->flags, DRIVER_NAME, handle);
+ if (irq_registered < 0)
+ PRINTM(ERROR, "Couldn't acquire BT_HOST_WAKE IRQ\n");
+ else {
+ irq_registered = 1;
+ enable_irq_wake(bt_irqres->start);
+ bt_enable_hostwake_irq(FALSE);
+ }
+ }
+}
+
+void
+mdev_poweroff(struct m_dev *m_dev)
+{
+ ENTER();
+
+ if (minicard_pwrup) {
+ bt_set_power(0, 0);
+ bt_set_carddetect(0);
+ }
+
+ LEAVE();
+}
+
/**
* @brief This function probes the platform-level device
*
@@ -2211,9 +2355,14 @@ bt_probe(struct platform_device *pdev)
ENTER();
- bt_control_data = bt_ctrl;
- bt_set_power(1, 0); /* Power On */
- bt_set_carddetect(1); /* CardDetect (0->1) */
+ bt_irqres = platform_get_resource_byname(pdev,
+ IORESOURCE_IRQ,
+ IORESOURCE_NAME);
+ if (minicard_pwrup) {
+ bt_control_data = bt_ctrl;
+ bt_set_power(1, 0); /* Power On */
+ bt_set_carddetect(1); /* CardDetect (0->1) */
+ }
LEAVE();
return 0;
@@ -2233,9 +2382,16 @@ bt_remove(struct platform_device *pdev)
ENTER();
- bt_control_data = bt_ctrl;
- bt_set_power(0, 0); /* Power Off */
- bt_set_carddetect(0); /* CardDetect (1->0) */
+ if (bt_irqres && irq_registered) {
+ PRINTM(MSG, "Free hostwake IRQ wakeup\n");
+ free_irq(bt_irqres->start, NULL);
+ irq_registered = 0;
+ }
+ if (minicard_pwrup) {
+ bt_control_data = bt_ctrl;
+ bt_set_power(0, 0); /* Power Off */
+ bt_set_carddetect(0); /* CardDetect (1->0) */
+ }
LEAVE();
return 0;
@@ -2261,8 +2417,7 @@ bt_add_dev(void)
ENTER();
- if (minicard_pwrup)
- ret = platform_driver_register(&bt_device);
+ ret = platform_driver_register(&bt_device);
LEAVE();
return ret;
@@ -2278,8 +2433,7 @@ bt_del_dev(void)
{
ENTER();
- if (minicard_pwrup)
- platform_driver_unregister(&bt_device);
+ platform_driver_unregister(&bt_device);
LEAVE();
}