aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/mgmt.c
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2011-12-14 17:47:39 -0500
committerGustavo F. Padovan <padovan@profusion.mobi>2011-12-18 14:41:04 -0500
commit7d78525dcf5c6fe5e6e73d22776ed5f960e3153e (patch)
treebe4ab2f2c9b140733a685e6ac6da2c7e409b3618 /net/bluetooth/mgmt.c
parentef5803729c2323204f7372617ad97e55e94153b9 (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/bluetooth/mgmt.c')
-rw-r--r--net/bluetooth/mgmt.c40
1 files changed, 35 insertions, 5 deletions
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
38struct pending_cmd { 40struct 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
477static 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
493static 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
475static int read_controller_info(struct sock *sk, u16 index) 503static 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