From: Gustavo Padovan <padovan@profusion.mobi>
To: Anderson Briglia <anderson.briglia@openbossa.org>
Cc: linux-bluetooth@vger.kernel.org
Subject: Re: [RFC 6/7] Bluetooth: Add RSSI Monitor timer and list lock
Date: Wed, 3 Aug 2011 15:48:26 -0300 [thread overview]
Message-ID: <20110803184826.GD28119@joana> (raw)
In-Reply-To: <1312310109-27082-7-git-send-email-anderson.briglia@openbossa.org>
Hi Briglia,
* Anderson Briglia <anderson.briglia@openbossa.org> [2011-08-02 14:35:08 -0400]:
> This is the polling mechanism to send HCI Read RSSI commands. The
> command responses are used by the RSSI Monitor to get the current RSSI
> value and calculate the current alert level for a given monitored
> connection.
>
> This patch also adds read and write locks on rssi_monitor_list in
> order to avoid race conditions.
>
> Signed-off-by: Anderson Briglia <anderson.briglia@openbossa.org>
> ---
> include/net/bluetooth/hci_core.h | 3 +
> net/bluetooth/hci_core.c | 12 +++++
> net/bluetooth/mgmt.c | 99 ++++++++++++++++++++++++++++++++++----
> 3 files changed, 104 insertions(+), 10 deletions(-)
>
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index a3cf433..8ff3448 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -211,6 +211,8 @@ struct hci_dev {
>
> struct timer_list le_scan_timer;
>
> + struct timer_list rssi_monitor_timer;
call this rssi_timer is enough.
> +
> struct hci_dev_stats stat;
>
> struct sk_buff_head driver_init;
> @@ -869,6 +871,7 @@ int mgmt_has_pending_stop_discov(u16 index);
> int mgmt_cancel_discovery(u16 index);
> int mgmt_is_interleaved_discovery(u16 index);
> int mgmt_do_interleaved_discovery(u16 index);
> +void mgmt_do_read_rssi(struct hci_dev *hdev);
>
> /* HCI info for socket */
> #define hci_pi(sk) ((struct hci_pinfo *) sk)
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index c0c46bf..eb51b94 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -1449,6 +1449,14 @@ static void hci_disable_le_scan(unsigned long arg)
> hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
> }
>
> +static void hci_do_read_rssi(unsigned long arg)
> +{
> + struct hci_dev *hdev = (void *) arg;
> +
> + if (test_bit(HCI_UP, &hdev->flags))
> + mgmt_do_read_rssi(hdev);
> +}
> +
> /* Register HCI device */
> int hci_register_dev(struct hci_dev *hdev)
> {
> @@ -1522,6 +1530,9 @@ int hci_register_dev(struct hci_dev *hdev)
> setup_timer(&hdev->le_scan_timer, hci_disable_le_scan,
> (unsigned long) hdev);
>
> + setup_timer(&hdev->rssi_monitor_timer, hci_do_read_rssi,
> + (unsigned long) hdev);
> +
> INIT_WORK(&hdev->power_on, hci_power_on);
> INIT_WORK(&hdev->power_off, hci_power_off);
> setup_timer(&hdev->off_timer, hci_auto_off, (unsigned long) hdev);
> @@ -1604,6 +1615,7 @@ int hci_unregister_dev(struct hci_dev *hdev)
> hci_del_off_timer(hdev);
> del_timer(&hdev->adv_timer);
> del_timer(&hdev->le_scan_timer);
> + del_timer(&hdev->rssi_monitor_timer);
>
> destroy_workqueue(hdev->workqueue);
>
> diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
> index 65ddbff..b034290 100644
> --- a/net/bluetooth/mgmt.c
> +++ b/net/bluetooth/mgmt.c
> @@ -48,6 +48,8 @@ enum bt_device_type {
> #define RSSI_MONITOR_ALERT_LOW 0x01
> #define RSSI_MONITOR_ALERT_HIGH 0x02
>
> +#define RSSI_MONITOR_TIMEOUT 2000
> +
> struct pending_cmd {
> struct list_head list;
> __u16 opcode;
> @@ -70,6 +72,9 @@ struct rssi_monitor {
>
> static LIST_HEAD(rssi_monitor_list);
>
> +static rwlock_t rssi_monitor_list_lock;
> +static DEFINE_RWLOCK(rssi_monitor_list_lock);
Use a normal spinlock here.
> +
> static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
> {
> struct sk_buff *skb;
> @@ -1916,21 +1921,46 @@ static struct rssi_monitor *rssi_monitor_find(u16 index, bdaddr_t *bdaddr)
> return NULL;
> }
>
> +static void rssi_monitor_start(u16 index)
> +{
> + struct hci_dev *hdev;
> +
> + if (list_empty(&rssi_monitor_list))
> + return;
> +
> + hdev = hci_dev_get(index);
> + if (!hdev)
> + return;
> +
> + mod_timer(&hdev->rssi_monitor_timer, jiffies +
> + msecs_to_jiffies(RSSI_MONITOR_TIMEOUT));
> + hci_dev_put(hdev);
> +}
> +
> static int rssi_monitor_add(u16 index, bdaddr_t *bdaddr, s8 low_trigger,
> s8 high_trigger)
> {
> struct rssi_monitor *rm;
> + int err = 0;
>
> - if (rssi_monitor_find(index, bdaddr))
> - return -EEXIST;
> + write_lock_bh(&rssi_monitor_list_lock);
> +
> + if (rssi_monitor_find(index, bdaddr)) {
> + err = -EEXIST;
> + goto out;
> + }
>
> if (low_trigger < -127 || low_trigger > 128 ||
> - high_trigger < -127 || high_trigger > 128)
> - return -EINVAL;
> + high_trigger < -127 || high_trigger > 128) {
> + err = -EINVAL;
> + goto out;
> + }
>
> rm = kzalloc(sizeof(*rm), GFP_ATOMIC);
> - if (!rm)
> - return -ENOMEM;
> + if (!rm) {
> + err = -ENOMEM;
> + goto out;
> + }
>
> rm->index = index;
> bacpy(&rm->bdaddr, bdaddr);
> @@ -1940,20 +1970,46 @@ static int rssi_monitor_add(u16 index, bdaddr_t *bdaddr, s8 low_trigger,
>
> list_add(&rm->list, &rssi_monitor_list);
>
> - return 0;
> + rssi_monitor_start(index);
> +
> +out:
> + write_unlock_bh(&rssi_monitor_list_lock);
> + return err;
> }
>
> static int rssi_monitor_remove(u16 index, bdaddr_t *bdaddr)
> {
> struct rssi_monitor *rm;
> + struct hci_dev *hdev;
> + int err = 0;
> +
> + write_lock_bh(&rssi_monitor_list_lock);
>
> rm = rssi_monitor_find(index, bdaddr);
> - if (!rm)
> - return -EINVAL;
> + if (!rm) {
> + err = -EINVAL;
> + goto out;
> + }
>
> list_del(&rm->list);
> + kfree(rm);
>
> - return 0;
> + if (!list_empty(&rssi_monitor_list))
> + goto out;
This need to be a per hdev list, otherwise we will only disable the timer if
there is no monitor for all adapters.
> +
> + hdev = hci_dev_get(index);
> + if (!hdev) {
> + err = -EINVAL;
> + goto out;
> + }
> +
> + del_timer(&hdev->rssi_monitor_timer);
> +
> + hci_dev_put(hdev);
> +
> +out:
> + write_unlock_bh(&rssi_monitor_list_lock);
> + return err;
> }
>
> static int enable_rssi_monitor(struct sock *sk, u16 index,
> @@ -1995,7 +2051,11 @@ static int rssi_monitor_send_alert(u16 index, bdaddr_t *bdaddr, s8 rssi)
> struct mgmt_ev_rssi_monitor_alert ev;
> u8 alert;
>
> + read_lock(&rssi_monitor_list_lock);
> +
> rm = rssi_monitor_find(index, bdaddr);
> +
> + read_unlock(&rssi_monitor_list_lock);
> if (!rm)
> return -EINVAL;
>
> @@ -2718,3 +2778,22 @@ void mgmt_read_rssi_complete(u16 index, bdaddr_t *bdaddr, s8 rssi, u8 status)
>
> rssi_monitor_send_alert(index, bdaddr, rssi);
> }
> +
> +void mgmt_do_read_rssi(struct hci_dev *hdev)
> +{
> + struct rssi_monitor *rm;
> +
> + read_lock(&rssi_monitor_list_lock);
> +
> + list_for_each_entry(rm, &rssi_monitor_list, list) {
> +
> + if (rm->index != hdev->id)
> + continue;
> +
> + mgmt_read_rssi(hdev, &rm->bdaddr);
> + }
Per adapter list could make this code better as well.
Gustavo
next prev parent reply other threads:[~2011-08-03 18:48 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-08-02 18:35 [RFC 0/7] RSSI Monitor Anderson Briglia
2011-08-02 18:35 ` [RFC 1/7] Bluetooth: Add RSSI Monitor commands Anderson Briglia
2011-08-03 17:58 ` Gustavo Padovan
2011-08-03 18:04 ` Anderson Briglia
2011-08-02 18:35 ` [RFC 2/7] Bluetooth: Implement Enable RSSI Monitor Anderson Briglia
2011-08-02 18:35 ` [RFC 3/7] Bluetooth: Implement Disable " Anderson Briglia
2011-08-02 18:35 ` [RFC 4/7] Bluetooth: Implement RSSI Monitor Alert event Anderson Briglia
2011-08-02 18:35 ` [RFC 5/7] Bluetooth: Implement Read RSSI command Anderson Briglia
2011-08-02 18:35 ` [RFC 6/7] Bluetooth: Add RSSI Monitor timer and list lock Anderson Briglia
2011-08-03 18:48 ` Gustavo Padovan [this message]
2011-08-03 19:09 ` Anderson Briglia
2011-08-03 19:18 ` Gustavo Padovan
2011-08-03 19:01 ` Claudio Takahasi
2011-08-03 19:10 ` Anderson Briglia
2011-08-02 18:35 ` [RFC 7/7] Bluetooth: Remove RSSI monitor on disconnection Anderson Briglia
2011-08-03 19:36 ` [RFC 0/7] RSSI Monitor Claudio Takahasi
2011-08-03 20:25 ` Gustavo Padovan
2011-08-03 20:52 ` Claudio Takahasi
2011-08-03 21:52 ` Anderson Briglia
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20110803184826.GD28119@joana \
--to=padovan@profusion.mobi \
--cc=anderson.briglia@openbossa.org \
--cc=linux-bluetooth@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox