diff options
author | Johan Hedberg <johan.hedberg@intel.com> | 2011-12-14 17:47:39 -0500 |
---|---|---|
committer | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-12-18 14:41:04 -0500 |
commit | 7d78525dcf5c6fe5e6e73d22776ed5f960e3153e (patch) | |
tree | be4ab2f2c9b140733a685e6ac6da2c7e409b3618 /net | |
parent | ef5803729c2323204f7372617ad97e55e94153b9 (diff) |
Bluetooth: Add timer for automatically disabling the service cache
We do not want the service cache to be enabled indefinitely after
mgmt_read_info is called. To solve this a timer is added which will
automatically disable the cache if mgmt_set_dev_class isn't called
within 5 seconds of calling mgmt_read_info.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net')
-rw-r--r-- | net/bluetooth/hci_core.c | 3 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 40 |
2 files changed, 38 insertions, 5 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 82d1d9e6b7c6..b5ba42db0561 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -598,6 +598,9 @@ static int hci_dev_do_close(struct hci_dev *hdev) | |||
598 | if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->flags)) | 598 | if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->flags)) |
599 | cancel_delayed_work(&hdev->power_off); | 599 | cancel_delayed_work(&hdev->power_off); |
600 | 600 | ||
601 | if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->flags)) | ||
602 | cancel_delayed_work(&hdev->service_cache); | ||
603 | |||
601 | hci_dev_lock(hdev); | 604 | hci_dev_lock(hdev); |
602 | inquiry_cache_flush(hdev); | 605 | inquiry_cache_flush(hdev); |
603 | hci_conn_hash_flush(hdev); | 606 | hci_conn_hash_flush(hdev); |
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index cc4ea392ac6a..6cb8c7f708b5 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -35,6 +35,8 @@ | |||
35 | 35 | ||
36 | #define INQUIRY_LEN_BREDR 0x08 /* TGAP(100) */ | 36 | #define INQUIRY_LEN_BREDR 0x08 /* TGAP(100) */ |
37 | 37 | ||
38 | #define SERVICE_CACHE_TIMEOUT (5 * 1000) | ||
39 | |||
38 | struct pending_cmd { | 40 | struct pending_cmd { |
39 | struct list_head list; | 41 | struct list_head list; |
40 | u16 opcode; | 42 | u16 opcode; |
@@ -472,6 +474,32 @@ static int update_class(struct hci_dev *hdev) | |||
472 | return hci_send_cmd(hdev, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod); | 474 | return hci_send_cmd(hdev, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod); |
473 | } | 475 | } |
474 | 476 | ||
477 | static void service_cache_off(struct work_struct *work) | ||
478 | { | ||
479 | struct hci_dev *hdev = container_of(work, struct hci_dev, | ||
480 | service_cache.work); | ||
481 | |||
482 | if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->flags)) | ||
483 | return; | ||
484 | |||
485 | hci_dev_lock(hdev); | ||
486 | |||
487 | update_eir(hdev); | ||
488 | update_class(hdev); | ||
489 | |||
490 | hci_dev_unlock(hdev); | ||
491 | } | ||
492 | |||
493 | static void mgmt_init_hdev(struct hci_dev *hdev) | ||
494 | { | ||
495 | if (!test_and_set_bit(HCI_MGMT, &hdev->flags)) | ||
496 | INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off); | ||
497 | |||
498 | if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->flags)) | ||
499 | schedule_delayed_work(&hdev->service_cache, | ||
500 | msecs_to_jiffies(SERVICE_CACHE_TIMEOUT)); | ||
501 | } | ||
502 | |||
475 | static int read_controller_info(struct sock *sk, u16 index) | 503 | static int read_controller_info(struct sock *sk, u16 index) |
476 | { | 504 | { |
477 | struct mgmt_rp_read_info rp; | 505 | struct mgmt_rp_read_info rp; |
@@ -489,10 +517,8 @@ static int read_controller_info(struct sock *sk, u16 index) | |||
489 | 517 | ||
490 | hci_dev_lock(hdev); | 518 | hci_dev_lock(hdev); |
491 | 519 | ||
492 | if (test_and_clear_bit(HCI_PI_MGMT_INIT, &hci_pi(sk)->flags)) { | 520 | if (test_and_clear_bit(HCI_PI_MGMT_INIT, &hci_pi(sk)->flags)) |
493 | set_bit(HCI_MGMT, &hdev->flags); | 521 | mgmt_init_hdev(hdev); |
494 | set_bit(HCI_SERVICE_CACHE, &hdev->flags); | ||
495 | } | ||
496 | 522 | ||
497 | memset(&rp, 0, sizeof(rp)); | 523 | memset(&rp, 0, sizeof(rp)); |
498 | 524 | ||
@@ -992,8 +1018,12 @@ static int set_dev_class(struct sock *sk, u16 index, unsigned char *data, | |||
992 | hdev->major_class = cp->major; | 1018 | hdev->major_class = cp->major; |
993 | hdev->minor_class = cp->minor; | 1019 | hdev->minor_class = cp->minor; |
994 | 1020 | ||
995 | if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->flags)) | 1021 | if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->flags)) { |
1022 | hci_dev_unlock(hdev); | ||
1023 | cancel_delayed_work_sync(&hdev->service_cache); | ||
1024 | hci_dev_lock(hdev); | ||
996 | update_eir(hdev); | 1025 | update_eir(hdev); |
1026 | } | ||
997 | 1027 | ||
998 | err = update_class(hdev); | 1028 | err = update_class(hdev); |
999 | 1029 | ||