From 23705b359ecbd3a4c612f6c43021439120c4d905 Mon Sep 17 00:00:00 2001 From: Manikanta Date: Fri, 13 Dec 2013 15:30:48 +0530 Subject: Revert "Revert "net: wireless: Update SD8797/SD8897 WLAN/BT driver to 434"" This reverts commit 4408e2f3a6e266f07f4e299433cd6ac024f580f5. Bug 1424794 Change-Id: I0cc7dc84672dce7ca20a5561b53a51f13c551e93 Signed-off-by: Manikanta Reviewed-on: http://git-master/r/345280 Reviewed-by: Bitan Biswas --- drivers/bluetooth/sd8797/bt/bt_drv.h | 20 ++- drivers/bluetooth/sd8797/bt/bt_init.c | 94 +++++++++----- drivers/bluetooth/sd8797/bt/bt_main.c | 208 ++++++++++++++++++++++-------- drivers/bluetooth/sd8797/bt/bt_proc.c | 57 +++++--- drivers/bluetooth/sd8797/bt/bt_sdio.h | 3 +- drivers/bluetooth/sd8797/bt/bt_sdiommc.c | 54 ++++---- drivers/bluetooth/sd8797/bt/hci_wrapper.h | 1 + drivers/bluetooth/sd8797/bt/mbt_char.c | 57 ++++++-- drivers/bluetooth/sd8797/bt/mbt_char.h | 3 + drivers/bluetooth/sd8897/bt/bt_main.c | 16 +++ drivers/bluetooth/sd8897/bt/bt_sdio.h | 3 +- drivers/bluetooth/sd8897/bt/bt_sdiommc.c | 25 +++- drivers/bluetooth/sd8897/bt/hci_wrapper.h | 1 + drivers/bluetooth/sd8897/bt/mbt_char.c | 3 + drivers/bluetooth/sd8897/bt/mbt_char.h | 2 + 15 files changed, 394 insertions(+), 153 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/sd8797/bt/bt_drv.h b/drivers/bluetooth/sd8797/bt/bt_drv.h index 6773d34a944c..8e6f21f501cb 100644 --- a/drivers/bluetooth/sd8797/bt/bt_drv.h +++ b/drivers/bluetooth/sd8797/bt/bt_drv.h @@ -54,6 +54,16 @@ typedef u32 t_ptr; /** Define maximum number of radio func supported */ #define MAX_RADIO_FUNC 4 +/** MAC address print format */ +#ifndef MACSTR +#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" +#endif + +/** MAC address print arguments */ +#ifndef MAC2STR +#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] +#endif + /** Debug level : Message */ #define DBG_MSG BIT(0) /** Debug level : Fatal */ @@ -435,6 +445,8 @@ typedef struct _bt_private { spinlock_t driver_lock; /** Driver lock flags */ ulong driver_flags; + /** Driver reference flags */ + struct kobject kobj; int debug_device_pending; int debug_ocf_ogf[2]; @@ -566,6 +578,8 @@ int fm_set_intr_mask(bt_private * priv, u32 mask); /** default idle time */ #define DEFAULT_IDLE_TIME 1000 +#define BT_CMD_HEADER_SIZE 3 + typedef struct _BT_CMD { /** OCF OGF */ u16 ocf_ogf; @@ -588,7 +602,10 @@ typedef struct _BT_EVENT { int check_evtpkt(bt_private * priv, struct sk_buff *skb); /* Prototype of global function */ - +/** This function gets the priv reference */ +struct kobject *bt_priv_get(bt_private * priv); +/** This function release the priv reference */ +void bt_priv_put(bt_private * priv); /** This function adds the card */ bt_private *bt_add_card(void *card); /** This function removes the card */ @@ -690,6 +707,7 @@ int bt_init_config(bt_private * priv, char *cfg_file); int bt_load_cal_data(bt_private * priv, u8 * config_data, u8 * mac); /** BT set user defined calibration data */ int bt_cal_config(bt_private * priv, char *cfg_file, char *mac); +int bt_init_mac_address(bt_private * priv, char *mac); typedef struct _BT_HCI_CMD { /** OCF OGF */ diff --git a/drivers/bluetooth/sd8797/bt/bt_init.c b/drivers/bluetooth/sd8797/bt/bt_init.c index 2de8c1238429..55481d520a3d 100644 --- a/drivers/bluetooth/sd8797/bt/bt_init.c +++ b/drivers/bluetooth/sd8797/bt/bt_init.c @@ -30,7 +30,7 @@ || ('A' <= (c) && (c) <= 'F')) #define isdigit(c) (('0' <= (c) && (c) <= '9')) -#define isspace(c) (c <= ' ' && (c == ' ' || (c <= 13 && c >=9))) +#define isspace(c) (c <= ' ' && (c == ' ' || (c <= 13 && c >= 9))) /** * @brief Returns hex value of a give character * @@ -116,7 +116,7 @@ bt_strsep(char **s, char delim, char esc) * @return hex value */ static int -bt_atox(char *a) +bt_atox(const char *a) { int i = 0; ENTER(); @@ -199,35 +199,43 @@ bt_atoi(int *data, char *a) * * @return BT_STATUS_SUCCESS or BT_STATUS_FAILURE */ -static u32 -bt_parse_cal_cfg(u8 * src, u32 len, u8 * dst, u32 dst_size) +static int +bt_parse_cal_cfg(const u8 * src, u32 len, u8 * dst, u32 dst_size) { - u8 *ptr; + const u8 *ptr; u8 *dptr; + int ret = BT_STATUS_FAILURE; ENTER(); ptr = src; dptr = dst; - while (ptr - src < len) { - if (*ptr && (isspace(*ptr) || *ptr == '\t')) { + while ((ptr - src) < len) { + if (*ptr && isspace(*ptr)) { ptr++; continue; } if (isxdigit(*ptr)) { + if ((dptr - dst) >= dst_size) { + PRINTM(ERROR, "cal_file size too big!!!\n"); + goto done; + } *dptr++ = bt_atox(ptr); ptr += 2; } else { ptr++; } - if ((dptr - dst) > dst_size) { - PRINTM(ERROR, "cal_file size too big!!!\n"); - break; - } } + if (dptr == dst) { + ret = BT_STATUS_FAILURE; + goto done; + } + + ret = BT_STATUS_SUCCESS; +done: LEAVE(); - return (dptr - dst); + return ret; } /** @@ -241,7 +249,7 @@ bt_parse_cal_cfg(u8 * src, u32 len, u8 * dst, u32 dst_size) int parse_cfg_get_line(u8 * data, u32 size, u8 * line_pos) { - static s32 pos = 0; + static s32 pos; u8 *src, *dest; if (pos >= size) { /* reach the end */ @@ -330,10 +338,8 @@ bt_process_init_cfg(bt_private * priv, u8 * data, u32 size) /* Convert MAC format */ bt_mac2u8(bt_mac, bt_addr); PRINTM(CMD, - "HCI: %s new BT Address %02x:%02x:%02x:%02x:%02x:%02x\n", - dev_name, bt_mac[0], bt_mac[1], - bt_mac[2], bt_mac[3], bt_mac[4], - bt_mac[5]); + "HCI: %s new BT Address " MACSTR + "\n", dev_name, MAC2STR(bt_mac)); if (BT_STATUS_SUCCESS != bt_set_mac_address(priv, bt_mac)) { PRINTM(FATAL, @@ -490,29 +496,25 @@ bt_process_cal_cfg(bt_private * priv, u8 * data, u32 size, char *mac) { u8 bt_mac[ETH_ALEN]; u8 cal_data[32]; + u8 *mac_data = NULL; int ret = BT_STATUS_FAILURE; memset(bt_mac, 0, sizeof(bt_mac)); - bt_parse_cal_cfg(data, size, cal_data, sizeof(cal_data)); + if (BT_STATUS_SUCCESS != + bt_parse_cal_cfg(data, size, cal_data, sizeof(cal_data))) { + goto done; + } if (mac != NULL) { /* Convert MAC format */ bt_mac2u8(bt_mac, mac); - PRINTM(CMD, - "HCI: new BT Address %02x:%02x:%02x:%02x:%02x:%02x\n", - bt_mac[0], bt_mac[1], bt_mac[2], bt_mac[3], bt_mac[4], - bt_mac[5]); - if (BT_STATUS_SUCCESS != - bt_load_cal_data(priv, cal_data, bt_mac)) { - PRINTM(FATAL, "BT: Fail to load calibrate data\n"); - goto done; - } - } else { - if (BT_STATUS_SUCCESS != bt_load_cal_data(priv, cal_data, NULL)) { - PRINTM(FATAL, "BT: Fail to load calibrate data\n"); - goto done; - } + PRINTM(CMD, "HCI: new BT Address " MACSTR "\n", + MAC2STR(bt_mac)); + mac_data = bt_mac; + } + if (BT_STATUS_SUCCESS != bt_load_cal_data(priv, cal_data, mac_data)) { + PRINTM(FATAL, "BT: Fail to load calibrate data\n"); + goto done; } - ret = BT_STATUS_SUCCESS; done: @@ -551,3 +553,29 @@ done: LEAVE(); return ret; } + +/** + * @brief BT init mac address from bt_mac parametre when insmod + * + * @param priv a pointer to bt_private structure + * @param bt_mac mac address buf + * @return BT_STATUS_SUCCESS or BT_STATUS_FAILURE + */ +int +bt_init_mac_address(bt_private * priv, char *mac) +{ + u8 bt_mac[ETH_ALEN]; + int ret = BT_STATUS_FAILURE; + + ENTER(); + memset(bt_mac, 0, sizeof(bt_mac)); + bt_mac2u8(bt_mac, mac); + PRINTM(CMD, "HCI: New BT Address " MACSTR "\n", MAC2STR(bt_mac)); + ret = bt_set_mac_address(priv, bt_mac); + if (ret != BT_STATUS_SUCCESS) + PRINTM(FATAL, + "BT: Fail to set mac address from insmod parametre.\n"); + + LEAVE(); + return ret; +} diff --git a/drivers/bluetooth/sd8797/bt/bt_main.c b/drivers/bluetooth/sd8797/bt/bt_main.c index 6c5f26561381..9b5d808d837c 100644 --- a/drivers/bluetooth/sd8797/bt/bt_main.c +++ b/drivers/bluetooth/sd8797/bt/bt_main.c @@ -65,33 +65,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 +111,11 @@ 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; + +void mdev_poweroff(struct m_dev *m_dev); /** * @brief Alloc bt device @@ -522,7 +524,7 @@ bt_send_reset_command(bt_private * priv) ret = BT_STATUS_FAILURE; goto exit; } - pCmd = (BT_HCI_CMD *) skb->tail; + pCmd = (BT_HCI_CMD *) skb->data; pCmd->ocf_ogf = (RESET_OGF << 10) | BT_CMD_RESET; pCmd->length = 0x00; pCmd->cmd_type = 0x00; @@ -581,7 +583,7 @@ bt_send_module_cfg_cmd(bt_private * priv, int subcmd) 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; @@ -644,7 +646,7 @@ bt_enable_ps(bt_private * priv) 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, @@ -690,7 +692,7 @@ bt_send_hscfg_cmd(bt_private * priv) 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", @@ -738,7 +740,7 @@ bt_send_sdio_pull_ctrl_cmd(bt_private * priv) 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, @@ -792,7 +794,7 @@ fm_set_intr_mask(bt_private * priv, u32 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; @@ -836,7 +838,7 @@ bt_enable_hs(bt_private * priv) 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; @@ -997,8 +999,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, @@ -1028,9 +1030,9 @@ bt_load_cal_data(bt_private * priv, u8 * config_data, u8 * mac) u8 ret = BT_STATUS_SUCCESS; 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); @@ -1046,17 +1048,17 @@ bt_load_cal_data(bt_private * priv, u8 * config_data, u8 * mac) pCmd->data[1] = 0x00; pCmd->data[2] = 0x00; pCmd->data[3] = 0x1C; - // swip cal-data byte + /* 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]; } 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; @@ -1143,7 +1145,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); } @@ -1522,6 +1525,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; } @@ -1629,6 +1633,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 * @@ -1708,7 +1781,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 +1799,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 +1821,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 +1833,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 +1861,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 +1880,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 +1891,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 +1918,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 +1936,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 +1947,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 +1973,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 +1992,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 +2025,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,7 +2041,18 @@ 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); } @@ -2007,7 +2089,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 +2097,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 +2150,7 @@ err_registerdev: err_kmalloc: if (priv->adapter) bt_free_adapter(priv); - kfree(priv); + bt_priv_put(priv); LEAVE(); return NULL; } @@ -2157,7 +2240,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; @@ -2197,6 +2280,19 @@ bt_set_power(int on, unsigned long msec) return 0; } +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 * diff --git a/drivers/bluetooth/sd8797/bt/bt_proc.c b/drivers/bluetooth/sd8797/bt/bt_proc.c index 315598540f58..74007eb7bd1f 100644 --- a/drivers/bluetooth/sd8797/bt/bt_proc.c +++ b/drivers/bluetooth/sd8797/bt/bt_proc.c @@ -28,16 +28,16 @@ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) #define PROC_DIR NULL #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) -#define PROC_DIR &proc_root +#define PROC_DIR (&proc_root) #else #define PROC_DIR proc_net #endif /** Proc mbt directory entry */ -static struct proc_dir_entry *proc_mbt = NULL; +static struct proc_dir_entry *proc_mbt; #define CMD52_STR_LEN 50 -static bt_private *bpriv = NULL; +static bt_private *bpriv; static char cmd52_string[CMD52_STR_LEN]; struct proc_data { @@ -71,12 +71,12 @@ struct proc_data { /** Device size */ #define item_dev_size(n) (sizeof((bt_dev_t *)0)->n) /** Device address */ -#define item_dev_addr(n) ((t_ptr) &((bt_dev_t *)0)->n) +#define item_dev_addr(n) ((t_ptr) & ((bt_dev_t *)0)->n) /** Adapter size */ #define item_adapter_size(n) (sizeof((bt_adapter *)0)->n) /** Adapter address */ -#define item_adapter_addr(n) ((t_ptr) &((bt_adapter *)0)->n) +#define item_adapter_addr(n) ((t_ptr) & ((bt_adapter *)0)->n) static struct item_data config_items[] = { #ifdef DEBUG_LEVEL1 @@ -178,7 +178,7 @@ string_to_number(char *s) break; } - return (r * pn); + return r * pn; } /** @@ -348,7 +348,11 @@ proc_write(struct file *file, static void proc_on_close(struct inode *inode, struct file *file) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) struct proc_private_data *priv = PDE_DATA(inode); +#else + struct proc_private_data *priv = PDE(inode)->data; +#endif struct proc_data *pdata = file->private_data; char *line; int i; @@ -397,7 +401,11 @@ proc_on_close(struct inode *inode, struct file *file) static int proc_open(struct inode *inode, struct file *file) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) struct proc_private_data *priv = PDE_DATA(inode); +#else + struct proc_private_data *priv = PDE(inode)->data; +#endif struct proc_data *pdata; int i; char *p; @@ -405,21 +413,23 @@ proc_open(struct inode *inode, struct file *file) ENTER(); priv->pbt->adapter->skb_pending = skb_queue_len(&priv->pbt->adapter->tx_queue); - if ((file->private_data = - kzalloc(sizeof(struct proc_data), GFP_KERNEL)) == NULL) { + file->private_data = kzalloc(sizeof(struct proc_data), GFP_KERNEL); + if (file->private_data == NULL) { PRINTM(ERROR, "BT: Can not alloc mem for proc_data\n"); LEAVE(); return -ENOMEM; } pdata = (struct proc_data *)file->private_data; - if ((pdata->rdbuf = kmalloc(priv->bufsize, GFP_KERNEL)) == NULL) { + pdata->rdbuf = kmalloc(priv->bufsize, GFP_KERNEL); + if (pdata->rdbuf == NULL) { PRINTM(ERROR, "BT: Can not alloc mem for rdbuf\n"); kfree(file->private_data); LEAVE(); return -ENOMEM; } if (priv->fileflag == DEFAULT_FILE_PERM) { - if ((pdata->wrbuf = kzalloc(priv->bufsize, GFP_KERNEL)) == NULL) { + pdata->wrbuf = kzalloc(priv->bufsize, GFP_KERNEL); + if (pdata->wrbuf == NULL) { PRINTM(ERROR, "BT: Can not alloc mem for wrbuf\n"); kfree(pdata->rdbuf); kfree(file->private_data); @@ -522,8 +532,7 @@ bt_proc_init(bt_private * priv, struct m_dev *m_dev, int seq) } memcpy((u8 *) priv->dev_proc[seq].pfiles, (u8 *) proc_files, sizeof(proc_files)); - priv->dev_proc[seq].num_proc_files = - sizeof(proc_files) / sizeof(proc_files[0]); + priv->dev_proc[seq].num_proc_files = ARRAY_SIZE(proc_files); for (j = 0; j < priv->dev_proc[seq].num_proc_files; j++) priv->dev_proc[seq].pfiles[j].pdata = NULL; for (j = 0; j < priv->dev_proc[seq].num_proc_files; j++) { @@ -562,6 +571,16 @@ bt_proc_init(bt_private * priv, struct m_dev *m_dev, int seq) (t_ptr) priv->adapter; } priv->dev_proc[seq].pfiles[j].pbt = priv; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) + entry = proc_create_data(proc_files[j].name, + S_IFREG | proc_files[j]. + fileflag, + priv->dev_proc[seq].proc_entry, + proc_files[j].fops, + &priv->dev_proc[seq]. + pfiles[j]); + if (entry == NULL) +#else entry = create_proc_entry(proc_files[j].name, S_IFREG | proc_files[j]. fileflag, @@ -574,6 +593,7 @@ bt_proc_init(bt_private * priv, struct m_dev *m_dev, int seq) #endif entry->proc_fops = proc_files[j].fops; } else +#endif PRINTM(MSG, "BT: Fail to create proc %s\n", proc_files[j].name); } @@ -617,17 +637,14 @@ bt_proc_remove(bt_private * priv) for (i = 0; i < MAX_RADIO_FUNC; i++) { if (!priv->dev_proc[i].proc_entry) continue; - for (j = 0; - j < sizeof(proc_files) / sizeof(proc_files[0]); - j++) { + for (j = 0; j < ARRAY_SIZE(proc_files); j++) { remove_proc_entry(proc_files[j].name, priv->dev_proc[i].proc_entry); } - if (priv->dev_proc[i].proc_entry) { - remove_proc_entry(priv->bt_dev.m_dev[i].name, - proc_mbt); - priv->dev_proc[i].proc_entry = NULL; - } + + remove_proc_entry(priv->bt_dev.m_dev[i].name, proc_mbt); + priv->dev_proc[i].proc_entry = NULL; + if (priv->dev_proc[i].pfiles) { for (j = 0; j < priv->dev_proc[i].num_proc_files; diff --git a/drivers/bluetooth/sd8797/bt/bt_sdio.h b/drivers/bluetooth/sd8797/bt/bt_sdio.h index c8428ec56347..2c542d58b49f 100644 --- a/drivers/bluetooth/sd8797/bt/bt_sdio.h +++ b/drivers/bluetooth/sd8797/bt/bt_sdio.h @@ -70,11 +70,13 @@ typedef IRQ_RET_TYPE(*isr_notifier_fn_t) (s32 irq, void *dev_id, /** Host Control Registers : Host interrupt RSR */ #define HOST_INT_RSR_REG 0x01 + /** Host Control Registers : Upload host interrupt RSR */ #define UP_LD_HOST_INT_RSR (0x1U) /** Host Control Registers : Host interrupt mask */ #define HOST_INT_MASK_REG 0x02 + /** Host Control Registers : Upload host interrupt mask */ #define UP_LD_HOST_INT_MASK (0x1U) /** Host Control Registers : Download host interrupt mask */ @@ -84,7 +86,6 @@ typedef IRQ_RET_TYPE(*isr_notifier_fn_t) (s32 irq, void *dev_id, /** Disable Host interrupt mask */ #define HIM_DISABLE 0xff -/** Host Control Registers : Host interrupt status */ #define HOST_INTSTATUS_REG 0x03 /** Host Control Registers : Upload host interrupt status */ #define UP_LD_HOST_INT_STATUS (0x1U) diff --git a/drivers/bluetooth/sd8797/bt/bt_sdiommc.c b/drivers/bluetooth/sd8797/bt/bt_sdiommc.c index 293eacb92da8..10bda897c177 100644 --- a/drivers/bluetooth/sd8797/bt/bt_sdiommc.c +++ b/drivers/bluetooth/sd8797/bt/bt_sdiommc.c @@ -31,9 +31,9 @@ /** Max retry number of CMD53 write */ #define MAX_WRITE_IOMEM_RETRY 2 /** Firmware name */ -static char *fw_name = NULL; +static char *fw_name; /** request firmware nowait */ -static int req_fw_nowait = 0; +static int req_fw_nowait; static int multi_fn = BIT(2); /** Default firmware name */ #define DEFAULT_FW_NAME "mrvl/sd8797_uapsta.bin" @@ -57,7 +57,7 @@ MODULE_DEVICE_TABLE(sdio, bt_ids); Global Variables ********************************************************/ /** unregiser bus driver flag */ -static u8 unregister = 0; +static u8 unregister; #ifdef SDIO_SUSPEND_RESUME /** PM keep power */ extern int mbt_pm_keep_power; @@ -343,7 +343,7 @@ sd_probe_card(struct sdio_func *func, const struct sdio_device_id *id) goto done; } card->func = func; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) /* wait for chip fully wake up */ if (!func->enable_timeout) func->enable_timeout = 200; @@ -384,7 +384,7 @@ int sd_verify_fw_download(bt_private * priv, int pollnum) { int ret = BT_STATUS_FAILURE; - u16 firmwarestat; + u16 firmwarestat = 0; int tries; ENTER(); @@ -400,7 +400,10 @@ sd_verify_fw_download(bt_private * priv, int pollnum) } mdelay(100); } - + if ((pollnum > 1) && (ret != BT_STATUS_SUCCESS)) + PRINTM(ERROR, + "Fail to poll firmware status: firmwarestat=0x%x\n", + firmwarestat); LEAVE(); return ret; } @@ -443,7 +446,7 @@ sd_init_fw_dpc(bt_private * priv) tv1 = get_utimeofday(); #endif - tmpfwbufsz = ALIGN_SZ(BT_UPLD_SIZE, DMA_ALIGNMENT); + tmpfwbufsz = BT_UPLD_SIZE + DMA_ALIGNMENT; tmpfwbuf = kmalloc(tmpfwbufsz, GFP_KERNEL); if (!tmpfwbuf) { PRINTM(ERROR, @@ -655,7 +658,7 @@ sd_request_fw_dpc(const struct firmware *fw_firmware, void *context) goto done; } if (fw_firmware) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32) if (!req_fw_nowait) #endif release_firmware(fw_firmware); @@ -665,7 +668,7 @@ sd_request_fw_dpc(const struct firmware *fw_firmware, void *context) done: if (fw_firmware) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32) if (!req_fw_nowait) #endif release_firmware(fw_firmware); @@ -732,25 +735,24 @@ sd_download_firmware_w_helper(bt_private * priv) cur_fw_name = fw_name; if (req_fw_nowait) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,32) - if ((ret = - request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, - cur_fw_name, priv->hotplug_device, - GFP_KERNEL, priv, - sd_request_fw_callback)) < 0) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32) + ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, + cur_fw_name, priv->hotplug_device, + GFP_KERNEL, priv, + sd_request_fw_callback); #else - if ((ret = - request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, - cur_fw_name, priv->hotplug_device, - priv, sd_request_fw_callback)) < 0) + ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, + cur_fw_name, priv->hotplug_device, + priv, sd_request_fw_callback); #endif + if (ret < 0) PRINTM(FATAL, "BT: request_firmware_nowait() failed, error code = %#x\n", ret); } else { - if ((err = - request_firmware(&priv->firmware, cur_fw_name, - priv->hotplug_device)) < 0) { + err = request_firmware(&priv->firmware, cur_fw_name, + priv->hotplug_device); + if (err < 0) { PRINTM(FATAL, "BT: request_firmware() failed, error code = %#x\n", err); @@ -989,7 +991,7 @@ sd_card_to_host(bt_private * priv) } break; case MRVL_VENDOR_PKT: - // Just think here need to back compatible FM + /* Just think here need to back compatible FM */ bt_cb(skb)->pkt_type = HCI_VENDOR_PKT; skb_put(skb, buf_len); skb_pull(skb, BT_HEADER_LEN); @@ -1556,9 +1558,11 @@ sbi_host_to_card(bt_private * priv, u8 * payload, u16 nb) } buf = payload; + blksz = SD_BLOCK_SIZE; + buf_block_len = (nb + blksz - 1) / blksz; /* Allocate buffer and copy payload */ if ((t_ptr) payload & (DMA_ALIGNMENT - 1)) { - tmpbufsz = ALIGN_SZ(nb, DMA_ALIGNMENT); + tmpbufsz = buf_block_len * blksz + DMA_ALIGNMENT; tmpbuf = kmalloc(tmpbufsz, GFP_KERNEL); if (!tmpbuf) { LEAVE(); @@ -1569,8 +1573,6 @@ sbi_host_to_card(bt_private * priv, u8 * payload, u16 nb) buf = (u8 *) ALIGN_ADDR(tmpbuf, DMA_ALIGNMENT); memcpy(buf, payload, nb); } - blksz = SD_BLOCK_SIZE; - buf_block_len = (nb + blksz - 1) / blksz; sdio_claim_host(card->func); #define MAX_WRITE_IOMEM_RETRY 2 do { diff --git a/drivers/bluetooth/sd8797/bt/hci_wrapper.h b/drivers/bluetooth/sd8797/bt/hci_wrapper.h index 849b96e294a7..b8870359559f 100644 --- a/drivers/bluetooth/sd8797/bt/hci_wrapper.h +++ b/drivers/bluetooth/sd8797/bt/hci_wrapper.h @@ -76,6 +76,7 @@ struct m_dev { int (*ioctl) (struct m_dev * m_dev, unsigned int cmd, unsigned long arg); void (*query) (struct m_dev * m_dev, unsigned long arg); + void (*poweroff) (struct m_dev * m_dev); }; diff --git a/drivers/bluetooth/sd8797/bt/mbt_char.c b/drivers/bluetooth/sd8797/bt/mbt_char.c index 293234abf603..27afcf97774f 100644 --- a/drivers/bluetooth/sd8797/bt/mbt_char.c +++ b/drivers/bluetooth/sd8797/bt/mbt_char.c @@ -26,12 +26,40 @@ #include "bt_drv.h" #include "mbt_char.h" -LIST_HEAD(char_dev_list); +static LIST_HEAD(char_dev_list); static DEFINE_SPINLOCK(char_dev_list_lock); static int mbtchar_major = MBTCHAR_MAJOR_NUM; +struct kobject * +chardev_get(struct char_dev *dev) +{ + struct kobject *kobj; + + kobj = bt_priv_get(dev->m_dev->driver_data); + if (!kobj) + return NULL; + PRINTM(INFO, "dev get kobj\n"); + kobj = kobject_get(&dev->kobj); + if (!kobj) + bt_priv_put(dev->m_dev->driver_data); + return kobj; +} + +void +chardev_put(struct char_dev *dev) +{ + if (dev) { + struct m_dev *m_dev = dev->m_dev; + PRINTM(INFO, "dev put kobj\n"); + kobject_put(&dev->kobj); + if (m_dev) { + bt_priv_put(m_dev->driver_data); + } + } +} + /** * @brief Changes permissions of the dev * @@ -344,6 +372,9 @@ chardev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) case MBTCHAR_IOCTL_QUERY_TYPE: m_dev->query(m_dev, arg); break; + case MBTCHAR_IOCTL_POWER_OFF: + m_dev->poweroff(m_dev); + break; default: break; } @@ -367,9 +398,9 @@ chardev_open(struct inode *inode, struct file *filp) ENTER(); dev = container_of(inode->i_cdev, struct char_dev, cdev); - if (!dev->m_dev) { - ret = -ENXIO; - goto done; + if (!chardev_get(dev)) { + LEAVE(); + return -ENXIO; } filp->private_data = dev; /* for other methods */ m_dev = dev->m_dev; @@ -386,6 +417,8 @@ chardev_open(struct inode *inode, struct file *filp) done: mdev_req_unlock(m_dev); + if (ret) + chardev_put(dev); LEAVE(); return ret; } @@ -402,13 +435,17 @@ chardev_release(struct inode *inode, struct file *filp) { int ret = 0; struct char_dev *dev = (struct char_dev *)filp->private_data; + struct m_dev *m_dev = NULL; ENTER(); - if (!dev || !dev->m_dev) { + if (!dev) { LEAVE(); return -ENXIO; } - ret = dev->m_dev->close(dev->m_dev); + m_dev = dev->m_dev; + if (m_dev) + ret = dev->m_dev->close(dev->m_dev); filp->private_data = NULL; + chardev_put(dev); LEAVE(); return ret; } @@ -446,6 +483,7 @@ chardev_poll(struct file *filp, poll_table * wait) /* File ops for the Char driver */ const struct file_operations chardev_fops = { + .owner = THIS_MODULE, .read = chardev_read, .write = chardev_write, #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) @@ -493,8 +531,7 @@ register_char_dev(struct char_dev *dev, struct class *char_class, mbtchar_major = MAJOR(dev_num); } cdev_init(&dev->cdev, &chardev_fops); - dev->cdev.owner = THIS_MODULE; - dev->cdev.ops = &chardev_fops; + dev->cdev.owner = chardev_fops.owner; dev_num = MKDEV(mbtchar_major, dev->minor); if (cdev_add(&dev->cdev, dev_num, 1)) { @@ -596,7 +633,7 @@ chardev_cleanup(struct class *char_class) list_del(p); spin_unlock_irqrestore(&char_dev_list_lock, flags); unregister_char_dev(dev, char_class, dev->m_dev->name); - kfree(dev); + kobject_put(&dev->kobj); spin_lock_irqsave(&char_dev_list_lock, flags); break; } @@ -628,7 +665,7 @@ chardev_cleanup_one(struct m_dev *m_dev, struct class *char_class) spin_unlock_irqrestore(&char_dev_list_lock, flags); dev->m_dev = NULL; unregister_char_dev(dev, char_class, m_dev->name); - kfree(dev); + kobject_put(&dev->kobj); spin_lock_irqsave(&char_dev_list_lock, flags); break; } diff --git a/drivers/bluetooth/sd8797/bt/mbt_char.h b/drivers/bluetooth/sd8797/bt/mbt_char.h index 3d67202a689f..a6918f159794 100644 --- a/drivers/bluetooth/sd8797/bt/mbt_char.h +++ b/drivers/bluetooth/sd8797/bt/mbt_char.h @@ -28,6 +28,8 @@ #define MBTCHAR_IOCTL_RELEASE _IO('M', 1) #define MBTCHAR_IOCTL_QUERY_TYPE _IO('M', 2) +#define MBTCHAR_IOCTL_POWER_OFF _IO('M', 3) + #define MBTCHAR_MAJOR_NUM (0) /** Interface specific macros */ @@ -43,6 +45,7 @@ struct char_dev { int dev_type; struct cdev cdev; struct m_dev *m_dev; + struct kobject kobj; }; /** Changes permissions of the dev */ diff --git a/drivers/bluetooth/sd8897/bt/bt_main.c b/drivers/bluetooth/sd8897/bt/bt_main.c index d7ce8ec4733b..3707d8d86b41 100644 --- a/drivers/bluetooth/sd8897/bt/bt_main.c +++ b/drivers/bluetooth/sd8897/bt/bt_main.c @@ -115,6 +115,8 @@ static int minicard_pwrup = 1; /** Pointer to struct with control hooks */ static struct wifi_platform_data *bt_control_data; +void mdev_poweroff(struct m_dev *m_dev); + /** * @brief Alloc bt device * @@ -1523,6 +1525,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; } @@ -2277,6 +2280,19 @@ bt_set_power(int on, unsigned long msec) return 0; } +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 * diff --git a/drivers/bluetooth/sd8897/bt/bt_sdio.h b/drivers/bluetooth/sd8897/bt/bt_sdio.h index 30424ab7b648..c2dca34809b1 100644 --- a/drivers/bluetooth/sd8897/bt/bt_sdio.h +++ b/drivers/bluetooth/sd8897/bt/bt_sdio.h @@ -70,11 +70,13 @@ typedef IRQ_RET_TYPE(*isr_notifier_fn_t) (s32 irq, void *dev_id, /** Host Control Registers : Host interrupt RSR */ #define HOST_INT_RSR_REG 0x01 + /** Host Control Registers : Upload host interrupt RSR */ #define UP_LD_HOST_INT_RSR (0x1U) /** Host Control Registers : Host interrupt mask */ #define HOST_INT_MASK_REG 0x02 + /** Host Control Registers : Upload host interrupt mask */ #define UP_LD_HOST_INT_MASK (0x1U) /** Host Control Registers : Download host interrupt mask */ @@ -84,7 +86,6 @@ typedef IRQ_RET_TYPE(*isr_notifier_fn_t) (s32 irq, void *dev_id, /** Disable Host interrupt mask */ #define HIM_DISABLE 0xff -/** Host Control Registers : Host interrupt status */ #define HOST_INTSTATUS_REG 0x03 /** Host Control Registers : Upload host interrupt status */ #define UP_LD_HOST_INT_STATUS (0x1U) diff --git a/drivers/bluetooth/sd8897/bt/bt_sdiommc.c b/drivers/bluetooth/sd8897/bt/bt_sdiommc.c index 01f84fbc159c..44c7f253b957 100644 --- a/drivers/bluetooth/sd8897/bt/bt_sdiommc.c +++ b/drivers/bluetooth/sd8897/bt/bt_sdiommc.c @@ -35,7 +35,7 @@ static char *fw_name; /** request firmware nowait */ static int req_fw_nowait; static int multi_fn = BIT(2); -#define DEFAULT_FW_NAME "mrvl/sd8897_uapsta_a0.bin" +#define DEFAULT_FW_NAME "mrvl/sd8897_uapsta.bin" /** Function number 2 */ #define FN2 2 @@ -445,7 +445,7 @@ sd_init_fw_dpc(bt_private * priv) tv1 = get_utimeofday(); #endif - tmpfwbufsz = ALIGN_SZ(BT_UPLD_SIZE, DMA_ALIGNMENT); + tmpfwbufsz = BT_UPLD_SIZE + DMA_ALIGNMENT; tmpfwbuf = kmalloc(tmpfwbufsz, GFP_KERNEL); if (!tmpfwbuf) { PRINTM(ERROR, @@ -1427,6 +1427,21 @@ sbi_register_dev(bt_private * priv) PRINTM(INFO, ": SDIO FUNC%d IO port: 0x%x\n", priv->bt_dev.fn, priv->bt_dev.ioport); +#define SDIO_INT_MASK 0x3F + /* Set Host interrupt reset to read to clear */ + reg = sdio_readb(func, HOST_INT_RSR_REG, &ret); + if (ret < 0) + goto release_irq; + sdio_writeb(func, reg | SDIO_INT_MASK, HOST_INT_RSR_REG, &ret); + if (ret < 0) + goto release_irq; + /* Set auto re-enable */ + reg = sdio_readb(func, CARD_MISC_CFG_REG, &ret); + if (ret < 0) + goto release_irq; + sdio_writeb(func, reg | AUTO_RE_ENABLE_INT, CARD_MISC_CFG_REG, &ret); + if (ret < 0) + goto release_irq; sdio_set_drvdata(func, card); sdio_release_host(func); @@ -1551,9 +1566,11 @@ sbi_host_to_card(bt_private * priv, u8 * payload, u16 nb) } buf = payload; + blksz = SD_BLOCK_SIZE; + buf_block_len = (nb + blksz - 1) / blksz; /* Allocate buffer and copy payload */ if ((t_ptr) payload & (DMA_ALIGNMENT - 1)) { - tmpbufsz = ALIGN_SZ(nb, DMA_ALIGNMENT); + tmpbufsz = buf_block_len * blksz + DMA_ALIGNMENT; tmpbuf = kmalloc(tmpbufsz, GFP_KERNEL); if (!tmpbuf) { LEAVE(); @@ -1564,8 +1581,6 @@ sbi_host_to_card(bt_private * priv, u8 * payload, u16 nb) buf = (u8 *) ALIGN_ADDR(tmpbuf, DMA_ALIGNMENT); memcpy(buf, payload, nb); } - blksz = SD_BLOCK_SIZE; - buf_block_len = (nb + blksz - 1) / blksz; sdio_claim_host(card->func); #define MAX_WRITE_IOMEM_RETRY 2 do { diff --git a/drivers/bluetooth/sd8897/bt/hci_wrapper.h b/drivers/bluetooth/sd8897/bt/hci_wrapper.h index 849b96e294a7..b8870359559f 100644 --- a/drivers/bluetooth/sd8897/bt/hci_wrapper.h +++ b/drivers/bluetooth/sd8897/bt/hci_wrapper.h @@ -76,6 +76,7 @@ struct m_dev { int (*ioctl) (struct m_dev * m_dev, unsigned int cmd, unsigned long arg); void (*query) (struct m_dev * m_dev, unsigned long arg); + void (*poweroff) (struct m_dev * m_dev); }; diff --git a/drivers/bluetooth/sd8897/bt/mbt_char.c b/drivers/bluetooth/sd8897/bt/mbt_char.c index 279bfa0b8cce..27afcf97774f 100644 --- a/drivers/bluetooth/sd8897/bt/mbt_char.c +++ b/drivers/bluetooth/sd8897/bt/mbt_char.c @@ -372,6 +372,9 @@ chardev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) case MBTCHAR_IOCTL_QUERY_TYPE: m_dev->query(m_dev, arg); break; + case MBTCHAR_IOCTL_POWER_OFF: + m_dev->poweroff(m_dev); + break; default: break; } diff --git a/drivers/bluetooth/sd8897/bt/mbt_char.h b/drivers/bluetooth/sd8897/bt/mbt_char.h index 7ac992241cc2..a6918f159794 100644 --- a/drivers/bluetooth/sd8897/bt/mbt_char.h +++ b/drivers/bluetooth/sd8897/bt/mbt_char.h @@ -28,6 +28,8 @@ #define MBTCHAR_IOCTL_RELEASE _IO('M', 1) #define MBTCHAR_IOCTL_QUERY_TYPE _IO('M', 2) +#define MBTCHAR_IOCTL_POWER_OFF _IO('M', 3) + #define MBTCHAR_MAJOR_NUM (0) /** Interface specific macros */ -- cgit v1.2.3