Loading drivers/bluetooth/ath3k.c +6 −0 Original line number Diff line number Diff line Loading @@ -81,6 +81,9 @@ static struct usb_device_id ath3k_table[] = { /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xE02C) }, /* Atheros AR5BBU22 with sflash firmware */ { USB_DEVICE(0x0489, 0xE03C) }, { } /* Terminating entry */ }; Loading @@ -99,6 +102,9 @@ static struct usb_device_id ath3k_blist_tbl[] = { { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, /* Atheros AR5BBU22 with sflash firmware */ { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 }, { } /* Terminating entry */ }; Loading drivers/bluetooth/btmrvl_drv.h +3 −0 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ struct btmrvl_adapter { u8 wakeup_tries; wait_queue_head_t cmd_wait_q; u8 cmd_complete; bool is_suspended; }; struct btmrvl_private { Loading Loading @@ -139,8 +140,10 @@ void btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb); int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb); int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd); int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv); int btmrvl_enable_ps(struct btmrvl_private *priv); int btmrvl_prepare_command(struct btmrvl_private *priv); int btmrvl_enable_hs(struct btmrvl_private *priv); #ifdef CONFIG_DEBUG_FS void btmrvl_debugfs_init(struct hci_dev *hdev); Loading drivers/bluetooth/btmrvl_main.c +33 −23 Original line number Diff line number Diff line Loading @@ -200,6 +200,36 @@ int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd) } EXPORT_SYMBOL_GPL(btmrvl_send_module_cfg_cmd); int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv) { struct sk_buff *skb; struct btmrvl_cmd *cmd; skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC); if (!skb) { BT_ERR("No free skb"); return -ENOMEM; } cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd)); cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_HOST_SLEEP_CONFIG)); cmd->length = 2; cmd->data[0] = (priv->btmrvl_dev.gpio_gap & 0xff00) >> 8; cmd->data[1] = (u8) (priv->btmrvl_dev.gpio_gap & 0x00ff); bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT; skb->dev = (void *) priv->btmrvl_dev.hcidev; skb_queue_head(&priv->adapter->tx_queue, skb); BT_DBG("Queue HSCFG Command, gpio=0x%x, gap=0x%x", cmd->data[0], cmd->data[1]); return 0; } EXPORT_SYMBOL_GPL(btmrvl_send_hscfg_cmd); int btmrvl_enable_ps(struct btmrvl_private *priv) { struct sk_buff *skb; Loading Loading @@ -232,7 +262,7 @@ int btmrvl_enable_ps(struct btmrvl_private *priv) } EXPORT_SYMBOL_GPL(btmrvl_enable_ps); static int btmrvl_enable_hs(struct btmrvl_private *priv) int btmrvl_enable_hs(struct btmrvl_private *priv) { struct sk_buff *skb; struct btmrvl_cmd *cmd; Loading Loading @@ -268,35 +298,15 @@ static int btmrvl_enable_hs(struct btmrvl_private *priv) return ret; } EXPORT_SYMBOL_GPL(btmrvl_enable_hs); int btmrvl_prepare_command(struct btmrvl_private *priv) { struct sk_buff *skb = NULL; struct btmrvl_cmd *cmd; int ret = 0; if (priv->btmrvl_dev.hscfgcmd) { priv->btmrvl_dev.hscfgcmd = 0; skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC); if (skb == NULL) { BT_ERR("No free skb"); return -ENOMEM; } cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd)); cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_HOST_SLEEP_CONFIG)); cmd->length = 2; cmd->data[0] = (priv->btmrvl_dev.gpio_gap & 0xff00) >> 8; cmd->data[1] = (u8) (priv->btmrvl_dev.gpio_gap & 0x00ff); bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT; skb->dev = (void *) priv->btmrvl_dev.hcidev; skb_queue_head(&priv->adapter->tx_queue, skb); BT_DBG("Queue HSCFG Command, gpio=0x%x, gap=0x%x", cmd->data[0], cmd->data[1]); btmrvl_send_hscfg_cmd(priv); } if (priv->btmrvl_dev.pscmd) { Loading drivers/bluetooth/btmrvl_sdio.c +105 −7 Original line number Diff line number Diff line Loading @@ -339,9 +339,7 @@ static int btmrvl_sdio_download_helper(struct btmrvl_sdio_card *card) done: kfree(tmphlprbuf); if (fw_helper) release_firmware(fw_helper); return ret; } Loading Loading @@ -484,10 +482,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card) done: kfree(tmpfwbuf); if (fw_firmware) release_firmware(fw_firmware); return ret; } Loading Loading @@ -1013,6 +1008,9 @@ static int btmrvl_sdio_probe(struct sdio_func *func, priv->btmrvl_dev.psmode = 1; btmrvl_enable_ps(priv); priv->btmrvl_dev.gpio_gap = 0xffff; btmrvl_send_hscfg_cmd(priv); return 0; disable_host_int: Loading Loading @@ -1048,11 +1046,111 @@ static void btmrvl_sdio_remove(struct sdio_func *func) } } static int btmrvl_sdio_suspend(struct device *dev) { struct sdio_func *func = dev_to_sdio_func(dev); struct btmrvl_sdio_card *card; struct btmrvl_private *priv; mmc_pm_flag_t pm_flags; struct hci_dev *hcidev; if (func) { pm_flags = sdio_get_host_pm_caps(func); BT_DBG("%s: suspend: PM flags = 0x%x", sdio_func_id(func), pm_flags); if (!(pm_flags & MMC_PM_KEEP_POWER)) { BT_ERR("%s: cannot remain alive while suspended", sdio_func_id(func)); return -ENOSYS; } card = sdio_get_drvdata(func); if (!card || !card->priv) { BT_ERR("card or priv structure is not valid"); return 0; } } else { BT_ERR("sdio_func is not specified"); return 0; } priv = card->priv; if (priv->adapter->hs_state != HS_ACTIVATED) { if (btmrvl_enable_hs(priv)) { BT_ERR("HS not actived, suspend failed!"); return -EBUSY; } } hcidev = priv->btmrvl_dev.hcidev; BT_DBG("%s: SDIO suspend", hcidev->name); hci_suspend_dev(hcidev); skb_queue_purge(&priv->adapter->tx_queue); priv->adapter->is_suspended = true; /* We will keep the power when hs enabled successfully */ if (priv->adapter->hs_state == HS_ACTIVATED) { BT_DBG("suspend with MMC_PM_KEEP_POWER"); return sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); } else { BT_DBG("suspend without MMC_PM_KEEP_POWER"); return 0; } } static int btmrvl_sdio_resume(struct device *dev) { struct sdio_func *func = dev_to_sdio_func(dev); struct btmrvl_sdio_card *card; struct btmrvl_private *priv; mmc_pm_flag_t pm_flags; struct hci_dev *hcidev; if (func) { pm_flags = sdio_get_host_pm_caps(func); BT_DBG("%s: resume: PM flags = 0x%x", sdio_func_id(func), pm_flags); card = sdio_get_drvdata(func); if (!card || !card->priv) { BT_ERR("card or priv structure is not valid"); return 0; } } else { BT_ERR("sdio_func is not specified"); return 0; } priv = card->priv; if (!priv->adapter->is_suspended) { BT_DBG("device already resumed"); return 0; } priv->adapter->is_suspended = false; hcidev = priv->btmrvl_dev.hcidev; BT_DBG("%s: SDIO resume", hcidev->name); hci_resume_dev(hcidev); priv->hw_wakeup_firmware(priv); priv->adapter->hs_state = HS_DEACTIVATED; BT_DBG("%s: HS DEACTIVATED in resume!", hcidev->name); return 0; } static const struct dev_pm_ops btmrvl_sdio_pm_ops = { .suspend = btmrvl_sdio_suspend, .resume = btmrvl_sdio_resume, }; static struct sdio_driver bt_mrvl_sdio = { .name = "btmrvl_sdio", .id_table = btmrvl_sdio_ids, .probe = btmrvl_sdio_probe, .remove = btmrvl_sdio_remove, .drv = { .owner = THIS_MODULE, .pm = &btmrvl_sdio_pm_ops, } }; static int __init btmrvl_sdio_init_module(void) Loading drivers/bluetooth/btusb.c +14 −2 Original line number Diff line number Diff line Loading @@ -143,6 +143,9 @@ static struct usb_device_id blacklist_table[] = { /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 }, /* Broadcom BCM2035 */ { USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU }, { USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU }, Loading Loading @@ -855,6 +858,7 @@ static void btusb_work(struct work_struct *work) { struct btusb_data *data = container_of(work, struct btusb_data, work); struct hci_dev *hdev = data->hdev; int new_alts; int err; if (hdev->conn_hash.sco_num > 0) { Loading @@ -868,11 +872,19 @@ static void btusb_work(struct work_struct *work) set_bit(BTUSB_DID_ISO_RESUME, &data->flags); } if (data->isoc_altsetting != 2) { if (hdev->voice_setting & 0x0020) { static const int alts[3] = { 2, 4, 5 }; new_alts = alts[hdev->conn_hash.sco_num - 1]; } else { new_alts = hdev->conn_hash.sco_num; } if (data->isoc_altsetting != new_alts) { clear_bit(BTUSB_ISOC_RUNNING, &data->flags); usb_kill_anchored_urbs(&data->isoc_anchor); if (__set_isoc_interface(hdev, 2) < 0) if (__set_isoc_interface(hdev, new_alts) < 0) return; } Loading Loading
drivers/bluetooth/ath3k.c +6 −0 Original line number Diff line number Diff line Loading @@ -81,6 +81,9 @@ static struct usb_device_id ath3k_table[] = { /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xE02C) }, /* Atheros AR5BBU22 with sflash firmware */ { USB_DEVICE(0x0489, 0xE03C) }, { } /* Terminating entry */ }; Loading @@ -99,6 +102,9 @@ static struct usb_device_id ath3k_blist_tbl[] = { { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, /* Atheros AR5BBU22 with sflash firmware */ { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 }, { } /* Terminating entry */ }; Loading
drivers/bluetooth/btmrvl_drv.h +3 −0 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ struct btmrvl_adapter { u8 wakeup_tries; wait_queue_head_t cmd_wait_q; u8 cmd_complete; bool is_suspended; }; struct btmrvl_private { Loading Loading @@ -139,8 +140,10 @@ void btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb); int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb); int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd); int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv); int btmrvl_enable_ps(struct btmrvl_private *priv); int btmrvl_prepare_command(struct btmrvl_private *priv); int btmrvl_enable_hs(struct btmrvl_private *priv); #ifdef CONFIG_DEBUG_FS void btmrvl_debugfs_init(struct hci_dev *hdev); Loading
drivers/bluetooth/btmrvl_main.c +33 −23 Original line number Diff line number Diff line Loading @@ -200,6 +200,36 @@ int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd) } EXPORT_SYMBOL_GPL(btmrvl_send_module_cfg_cmd); int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv) { struct sk_buff *skb; struct btmrvl_cmd *cmd; skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC); if (!skb) { BT_ERR("No free skb"); return -ENOMEM; } cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd)); cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_HOST_SLEEP_CONFIG)); cmd->length = 2; cmd->data[0] = (priv->btmrvl_dev.gpio_gap & 0xff00) >> 8; cmd->data[1] = (u8) (priv->btmrvl_dev.gpio_gap & 0x00ff); bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT; skb->dev = (void *) priv->btmrvl_dev.hcidev; skb_queue_head(&priv->adapter->tx_queue, skb); BT_DBG("Queue HSCFG Command, gpio=0x%x, gap=0x%x", cmd->data[0], cmd->data[1]); return 0; } EXPORT_SYMBOL_GPL(btmrvl_send_hscfg_cmd); int btmrvl_enable_ps(struct btmrvl_private *priv) { struct sk_buff *skb; Loading Loading @@ -232,7 +262,7 @@ int btmrvl_enable_ps(struct btmrvl_private *priv) } EXPORT_SYMBOL_GPL(btmrvl_enable_ps); static int btmrvl_enable_hs(struct btmrvl_private *priv) int btmrvl_enable_hs(struct btmrvl_private *priv) { struct sk_buff *skb; struct btmrvl_cmd *cmd; Loading Loading @@ -268,35 +298,15 @@ static int btmrvl_enable_hs(struct btmrvl_private *priv) return ret; } EXPORT_SYMBOL_GPL(btmrvl_enable_hs); int btmrvl_prepare_command(struct btmrvl_private *priv) { struct sk_buff *skb = NULL; struct btmrvl_cmd *cmd; int ret = 0; if (priv->btmrvl_dev.hscfgcmd) { priv->btmrvl_dev.hscfgcmd = 0; skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC); if (skb == NULL) { BT_ERR("No free skb"); return -ENOMEM; } cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd)); cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_HOST_SLEEP_CONFIG)); cmd->length = 2; cmd->data[0] = (priv->btmrvl_dev.gpio_gap & 0xff00) >> 8; cmd->data[1] = (u8) (priv->btmrvl_dev.gpio_gap & 0x00ff); bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT; skb->dev = (void *) priv->btmrvl_dev.hcidev; skb_queue_head(&priv->adapter->tx_queue, skb); BT_DBG("Queue HSCFG Command, gpio=0x%x, gap=0x%x", cmd->data[0], cmd->data[1]); btmrvl_send_hscfg_cmd(priv); } if (priv->btmrvl_dev.pscmd) { Loading
drivers/bluetooth/btmrvl_sdio.c +105 −7 Original line number Diff line number Diff line Loading @@ -339,9 +339,7 @@ static int btmrvl_sdio_download_helper(struct btmrvl_sdio_card *card) done: kfree(tmphlprbuf); if (fw_helper) release_firmware(fw_helper); return ret; } Loading Loading @@ -484,10 +482,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card) done: kfree(tmpfwbuf); if (fw_firmware) release_firmware(fw_firmware); return ret; } Loading Loading @@ -1013,6 +1008,9 @@ static int btmrvl_sdio_probe(struct sdio_func *func, priv->btmrvl_dev.psmode = 1; btmrvl_enable_ps(priv); priv->btmrvl_dev.gpio_gap = 0xffff; btmrvl_send_hscfg_cmd(priv); return 0; disable_host_int: Loading Loading @@ -1048,11 +1046,111 @@ static void btmrvl_sdio_remove(struct sdio_func *func) } } static int btmrvl_sdio_suspend(struct device *dev) { struct sdio_func *func = dev_to_sdio_func(dev); struct btmrvl_sdio_card *card; struct btmrvl_private *priv; mmc_pm_flag_t pm_flags; struct hci_dev *hcidev; if (func) { pm_flags = sdio_get_host_pm_caps(func); BT_DBG("%s: suspend: PM flags = 0x%x", sdio_func_id(func), pm_flags); if (!(pm_flags & MMC_PM_KEEP_POWER)) { BT_ERR("%s: cannot remain alive while suspended", sdio_func_id(func)); return -ENOSYS; } card = sdio_get_drvdata(func); if (!card || !card->priv) { BT_ERR("card or priv structure is not valid"); return 0; } } else { BT_ERR("sdio_func is not specified"); return 0; } priv = card->priv; if (priv->adapter->hs_state != HS_ACTIVATED) { if (btmrvl_enable_hs(priv)) { BT_ERR("HS not actived, suspend failed!"); return -EBUSY; } } hcidev = priv->btmrvl_dev.hcidev; BT_DBG("%s: SDIO suspend", hcidev->name); hci_suspend_dev(hcidev); skb_queue_purge(&priv->adapter->tx_queue); priv->adapter->is_suspended = true; /* We will keep the power when hs enabled successfully */ if (priv->adapter->hs_state == HS_ACTIVATED) { BT_DBG("suspend with MMC_PM_KEEP_POWER"); return sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); } else { BT_DBG("suspend without MMC_PM_KEEP_POWER"); return 0; } } static int btmrvl_sdio_resume(struct device *dev) { struct sdio_func *func = dev_to_sdio_func(dev); struct btmrvl_sdio_card *card; struct btmrvl_private *priv; mmc_pm_flag_t pm_flags; struct hci_dev *hcidev; if (func) { pm_flags = sdio_get_host_pm_caps(func); BT_DBG("%s: resume: PM flags = 0x%x", sdio_func_id(func), pm_flags); card = sdio_get_drvdata(func); if (!card || !card->priv) { BT_ERR("card or priv structure is not valid"); return 0; } } else { BT_ERR("sdio_func is not specified"); return 0; } priv = card->priv; if (!priv->adapter->is_suspended) { BT_DBG("device already resumed"); return 0; } priv->adapter->is_suspended = false; hcidev = priv->btmrvl_dev.hcidev; BT_DBG("%s: SDIO resume", hcidev->name); hci_resume_dev(hcidev); priv->hw_wakeup_firmware(priv); priv->adapter->hs_state = HS_DEACTIVATED; BT_DBG("%s: HS DEACTIVATED in resume!", hcidev->name); return 0; } static const struct dev_pm_ops btmrvl_sdio_pm_ops = { .suspend = btmrvl_sdio_suspend, .resume = btmrvl_sdio_resume, }; static struct sdio_driver bt_mrvl_sdio = { .name = "btmrvl_sdio", .id_table = btmrvl_sdio_ids, .probe = btmrvl_sdio_probe, .remove = btmrvl_sdio_remove, .drv = { .owner = THIS_MODULE, .pm = &btmrvl_sdio_pm_ops, } }; static int __init btmrvl_sdio_init_module(void) Loading
drivers/bluetooth/btusb.c +14 −2 Original line number Diff line number Diff line Loading @@ -143,6 +143,9 @@ static struct usb_device_id blacklist_table[] = { /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 }, /* Broadcom BCM2035 */ { USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU }, { USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU }, Loading Loading @@ -855,6 +858,7 @@ static void btusb_work(struct work_struct *work) { struct btusb_data *data = container_of(work, struct btusb_data, work); struct hci_dev *hdev = data->hdev; int new_alts; int err; if (hdev->conn_hash.sco_num > 0) { Loading @@ -868,11 +872,19 @@ static void btusb_work(struct work_struct *work) set_bit(BTUSB_DID_ISO_RESUME, &data->flags); } if (data->isoc_altsetting != 2) { if (hdev->voice_setting & 0x0020) { static const int alts[3] = { 2, 4, 5 }; new_alts = alts[hdev->conn_hash.sco_num - 1]; } else { new_alts = hdev->conn_hash.sco_num; } if (data->isoc_altsetting != new_alts) { clear_bit(BTUSB_ISOC_RUNNING, &data->flags); usb_kill_anchored_urbs(&data->isoc_anchor); if (__set_isoc_interface(hdev, 2) < 0) if (__set_isoc_interface(hdev, new_alts) < 0) return; } Loading