diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-24 20:54:29 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-24 20:54:29 +0200 |
commit | 28f3d717618156c0dcd2f497d791b578a7931d87 (patch) | |
tree | 37b11581b51929b5473541e53bd242b3e1a9f666 /drivers/bluetooth/btmrvl_sdio.c | |
parent | Merge branch 'perf-uprobes-for-linus' of git://git.kernel.org/pub/scm/linux/k... (diff) | |
parent | tcp: take care of overlaps in tcp_try_coalesce() (diff) | |
download | linux-28f3d717618156c0dcd2f497d791b578a7931d87.tar.xz linux-28f3d717618156c0dcd2f497d791b578a7931d87.zip |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull more networking updates from David Miller:
"Ok, everything from here on out will be bug fixes."
1) One final sync of wireless and bluetooth stuff from John Linville.
These changes have all been in his tree for more than a week, and
therefore have had the necessary -next exposure. John was just away
on a trip and didn't have a change to send the pull request until a
day or two ago.
2) Put back some defines in user exposed header file areas that were
removed during the tokenring purge. From Stephen Hemminger and Paul
Gortmaker.
3) A bug fix for UDP hash table allocation got lost in the pile due to
one of those "you got it.. no I've got it.." situations. :-)
From Tim Bird.
4) SKB coalescing in TCP needs to have stricter checks, otherwise we'll
try to coalesce overlapping frags and crash. Fix from Eric Dumazet.
5) RCU routing table lookups can race with free_fib_info(), causing
crashes when we deref the device pointers in the route. Fix by
releasing the net device in the RCU callback. From Yanmin Zhang.
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (293 commits)
tcp: take care of overlaps in tcp_try_coalesce()
ipv4: fix the rcu race between free_fib_info and ip_route_output_slow
mm: add a low limit to alloc_large_system_hash
ipx: restore token ring define to include/linux/ipx.h
if: restore token ring ARP type to header
xen: do not disable netfront in dom0
phy/micrel: Fix ID of KSZ9021
mISDN: Add X-Tensions USB ISDN TA XC-525
gianfar:don't add FCB length to hard_header_len
Bluetooth: Report proper error number in disconnection
Bluetooth: Create flags for bt_sk()
Bluetooth: report the right security level in getsockopt
Bluetooth: Lock the L2CAP channel when sending
Bluetooth: Restore locking semantics when looking up L2CAP channels
Bluetooth: Fix a redundant and problematic incoming MTU check
Bluetooth: Add support for Foxconn/Hon Hai AR5BBU22 0489:E03C
Bluetooth: Fix EIR data generation for mgmt_device_found
Bluetooth: Fix Inquiry with RSSI event mask
Bluetooth: improve readability of l2cap_seq_list code
Bluetooth: Fix skb length calculation
...
Diffstat (limited to 'drivers/bluetooth/btmrvl_sdio.c')
-rw-r--r-- | drivers/bluetooth/btmrvl_sdio.c | 112 |
1 files changed, 105 insertions, 7 deletions
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index 27b74b0d547b..a853244e7fd7 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c @@ -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); - + release_firmware(fw_helper); return ret; } @@ -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); - + release_firmware(fw_firmware); return ret; } @@ -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: @@ -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) |