patch-2.4.20 linux-2.4.20/net/bluetooth/hci_core.c
Next file: linux-2.4.20/net/bluetooth/hci_event.c
Previous file: linux-2.4.20/net/bluetooth/hci_conn.c
Back to the patch index
Back to the overall index
- Lines: 185
- Date:
Thu Nov 28 15:53:15 2002
- Orig file:
linux-2.4.19/net/bluetooth/hci_core.c
- Orig date:
Fri Aug 2 17:39:46 2002
diff -urN linux-2.4.19/net/bluetooth/hci_core.c linux-2.4.20/net/bluetooth/hci_core.c
@@ -25,11 +25,12 @@
/*
* BlueZ HCI Core.
*
- * $Id: hci_core.c,v 1.7 2002/06/25 22:03:39 maxk Exp $
+ * $Id: hci_core.c,v 1.14 2002/08/26 16:57:57 maxk Exp $
*/
#include <linux/config.h>
#include <linux/module.h>
+#include <linux/kmod.h>
#include <linux/types.h>
#include <linux/errno.h>
@@ -66,7 +67,7 @@
/* HCI device list */
LIST_HEAD(hdev_list);
-spinlock_t hdev_list_lock;
+rwlock_t hdev_list_lock = RW_LOCK_UNLOCKED;
/* HCI protocols */
#define HCI_MAX_PROTO 2
@@ -93,6 +94,32 @@
notifier_call_chain(&hci_notifier, event, hdev);
}
+/* ---- HCI hotplug support ---- */
+
+#ifdef CONFIG_HOTPLUG
+
+static int hci_run_hotplug(char *dev, char *action)
+{
+ char *argv[3], *envp[5], dstr[20], astr[32];
+
+ sprintf(dstr, "DEVICE=%s", dev);
+ sprintf(astr, "ACTION=%s", action);
+
+ argv[0] = hotplug_path;
+ argv[1] = "bluetooth";
+ argv[2] = NULL;
+
+ envp[0] = "HOME=/";
+ envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+ envp[2] = dstr;
+ envp[3] = astr;
+ envp[4] = NULL;
+
+ return call_usermodehelper(argv[0], argv, envp);
+}
+#else
+#define hci_run_hotplug(A...)
+#endif
/* ---- HCI requests ---- */
@@ -270,7 +297,7 @@
if (index < 0)
return NULL;
- spin_lock(&hdev_list_lock);
+ read_lock(&hdev_list_lock);
list_for_each(p, &hdev_list) {
hdev = list_entry(p, struct hci_dev, list);
if (hdev->id == index) {
@@ -280,7 +307,7 @@
}
hdev = NULL;
done:
- spin_unlock(&hdev_list_lock);
+ read_unlock(&hdev_list_lock);
return hdev;
}
@@ -699,7 +726,7 @@
return -ENOMEM;
dr = dl->dev_req;
- spin_lock_bh(&hdev_list_lock);
+ read_lock_bh(&hdev_list_lock);
list_for_each(p, &hdev_list) {
struct hci_dev *hdev;
hdev = list_entry(p, struct hci_dev, list);
@@ -708,7 +735,7 @@
if (++n >= dev_num)
break;
}
- spin_unlock_bh(&hdev_list_lock);
+ read_unlock_bh(&hdev_list_lock);
dl->dev_num = n;
size = n * sizeof(struct hci_dev_req) + sizeof(__u16);
@@ -768,7 +795,7 @@
if (!hdev->open || !hdev->close || !hdev->destruct)
return -EINVAL;
- spin_lock_bh(&hdev_list_lock);
+ write_lock_bh(&hdev_list_lock);
/* Find first available device id */
list_for_each(p, &hdev_list) {
@@ -806,12 +833,13 @@
memset(&hdev->stat, 0, sizeof(struct hci_dev_stats));
atomic_set(&hdev->promisc, 0);
-
- hci_notify(hdev, HCI_DEV_REG);
MOD_INC_USE_COUNT;
- spin_unlock_bh(&hdev_list_lock);
+ write_unlock_bh(&hdev_list_lock);
+
+ hci_notify(hdev, HCI_DEV_REG);
+ hci_run_hotplug(hdev->name, "register");
return id;
}
@@ -821,13 +849,15 @@
{
BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type);
- spin_lock_bh(&hdev_list_lock);
+ write_lock_bh(&hdev_list_lock);
list_del(&hdev->list);
- spin_unlock_bh(&hdev_list_lock);
+ write_unlock_bh(&hdev_list_lock);
hci_dev_do_close(hdev);
hci_notify(hdev, HCI_DEV_UNREG);
+ hci_run_hotplug(hdev->name, "unregister");
+
hci_dev_put(hdev);
MOD_DEC_USE_COUNT;
@@ -1134,6 +1164,25 @@
return conn;
}
+static inline void hci_acl_tx_to(struct hci_dev *hdev)
+{
+ struct conn_hash *h = &hdev->conn_hash;
+ struct list_head *p;
+ struct hci_conn *c;
+
+ BT_ERR("%s ACL tx timeout", hdev->name);
+
+ /* Kill stalled connections */
+ list_for_each(p, &h->list) {
+ c = list_entry(p, struct hci_conn, list);
+ if (c->type == ACL_LINK && c->sent) {
+ BT_ERR("%s killing stalled ACL connection %s",
+ hdev->name, batostr(&c->dst));
+ hci_acl_disconn(c, 0x13);
+ }
+ }
+}
+
static inline void hci_sched_acl(struct hci_dev *hdev)
{
struct hci_conn *conn;
@@ -1144,10 +1193,8 @@
/* ACL tx timeout must be longer than maximum
* link supervision timeout (40.9 seconds) */
- if (!hdev->acl_cnt && (jiffies - hdev->acl_last_tx) > (HZ * 45)) {
- BT_ERR("%s ACL tx timeout", hdev->name);
- hdev->acl_cnt++;
- }
+ if (!hdev->acl_cnt && (jiffies - hdev->acl_last_tx) > (HZ * 45))
+ hci_acl_tx_to(hdev);
while (hdev->acl_cnt && (conn = hci_low_sent(hdev, ACL_LINK, "e))) {
while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
@@ -1366,9 +1413,6 @@
int hci_core_init(void)
{
- /* Init locks */
- spin_lock_init(&hdev_list_lock);
-
return 0;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)