Merge commit 'v3.3-rc6' into android-3.3
Colin Cross [Mon, 5 Mar 2012 22:17:12 +0000 (14:17 -0800)]
1  2 
include/net/bluetooth/hci_core.h
kernel/sched/core.c
net/bluetooth/af_bluetooth.c
net/bluetooth/l2cap_core.c
net/bluetooth/rfcomm/core.c

@@@ -515,8 -515,7 +515,8 @@@ void hci_add_sco(struct hci_conn *conn
  void hci_setup_sync(struct hci_conn *conn, __u16 handle);
  void hci_sco_setup(struct hci_conn *conn, __u8 status);
  
 -struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst);
 +struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type,
 +                                      __u16 pkt_type, bdaddr_t *dst);
  int hci_conn_del(struct hci_conn *conn);
  void hci_conn_hash_flush(struct hci_dev *hdev);
  void hci_conn_check_pending(struct hci_dev *hdev);
@@@ -525,9 -524,8 +525,9 @@@ struct hci_chan *hci_chan_create(struc
  int hci_chan_del(struct hci_chan *chan);
  void hci_chan_list_flush(struct hci_conn *conn);
  
 -struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
 -                                              __u8 sec_level, __u8 auth_type);
 +struct hci_conn *hci_connect(struct hci_dev *hdev, int type,
 +                                      __u16 pkt_type, bdaddr_t *dst,
 +                                      __u8 sec_level, __u8 auth_type);
  int hci_conn_check_link_mode(struct hci_conn *conn);
  int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level);
  int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type);
@@@ -542,7 -540,7 +542,7 @@@ void hci_conn_put_device(struct hci_con
  static inline void hci_conn_hold(struct hci_conn *conn)
  {
        atomic_inc(&conn->refcnt);
-       cancel_delayed_work_sync(&conn->disc_work);
+       cancel_delayed_work(&conn->disc_work);
  }
  
  static inline void hci_conn_put(struct hci_conn *conn)
                        if (conn->state == BT_CONNECTED) {
                                timeo = msecs_to_jiffies(conn->disc_timeout);
                                if (!conn->out)
 -                                      timeo *= 2;
 +                                      timeo *= 20;
                        } else {
                                timeo = msecs_to_jiffies(10);
                        }
                } else {
                        timeo = msecs_to_jiffies(10);
                }
-               cancel_delayed_work_sync(&conn->disc_work);
+               cancel_delayed_work(&conn->disc_work);
                queue_delayed_work(conn->hdev->workqueue,
-                                       &conn->disc_work, jiffies + timeo);
+                                       &conn->disc_work, timeo);
        }
  }
  
diff --combined kernel/sched/core.c
@@@ -1932,7 -1932,6 +1932,6 @@@ static void finish_task_switch(struct r
        local_irq_enable();
  #endif /* __ARCH_WANT_INTERRUPTS_ON_CTXSW */
        finish_lock_switch(rq, prev);
-       trace_sched_stat_sleeptime(current, rq->clock);
  
        fire_sched_in_preempt_notifiers(current);
        if (mm)
@@@ -6729,7 -6728,7 +6728,7 @@@ int __init sched_create_sysfs_power_sav
  static int cpuset_cpu_active(struct notifier_block *nfb, unsigned long action,
                             void *hcpu)
  {
-       switch (action & ~CPU_TASKS_FROZEN) {
+       switch (action) {
        case CPU_ONLINE:
        case CPU_DOWN_FAILED:
                cpuset_update_active_cpus();
  static int cpuset_cpu_inactive(struct notifier_block *nfb, unsigned long action,
                               void *hcpu)
  {
-       switch (action & ~CPU_TASKS_FROZEN) {
+       switch (action) {
        case CPU_DOWN_PREPARE:
                cpuset_update_active_cpus();
                return NOTIFY_OK;
@@@ -6990,24 -6989,13 +6989,24 @@@ static inline int preempt_count_equals(
        return (nested == preempt_offset);
  }
  
 +static int __might_sleep_init_called;
 +int __init __might_sleep_init(void)
 +{
 +      __might_sleep_init_called = 1;
 +      return 0;
 +}
 +early_initcall(__might_sleep_init);
 +
  void __might_sleep(const char *file, int line, int preempt_offset)
  {
        static unsigned long prev_jiffy;        /* ratelimiting */
  
        rcu_sleep_check(); /* WARN_ON_ONCE() by default, no rate limit reqd. */
        if ((preempt_count_equals(preempt_offset) && !irqs_disabled()) ||
 -          system_state != SYSTEM_RUNNING || oops_in_progress)
 +          oops_in_progress)
 +              return;
 +      if (system_state != SYSTEM_RUNNING &&
 +          (!__might_sleep_init_called || system_state != SYSTEM_BOOTING))
                return;
        if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy)
                return;
@@@ -7562,23 -7550,6 +7561,23 @@@ cpu_cgroup_destroy(struct cgroup_subsy
        sched_destroy_group(tg);
  }
  
 +static int
 +cpu_cgroup_allow_attach(struct cgroup *cgrp, struct cgroup_taskset *tset)
 +{
 +      const struct cred *cred = current_cred(), *tcred;
 +      struct task_struct *task;
 +
 +      cgroup_taskset_for_each(task, cgrp, tset) {
 +              tcred = __task_cred(task);
 +
 +              if ((current != task) && !capable(CAP_SYS_NICE) &&
 +                  cred->euid != tcred->uid && cred->euid != tcred->suid)
 +                      return -EACCES;
 +      }
 +
 +      return 0;
 +}
 +
  static int cpu_cgroup_can_attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
                                 struct cgroup_taskset *tset)
  {
@@@ -7940,7 -7911,6 +7939,7 @@@ struct cgroup_subsys cpu_cgroup_subsys 
        .destroy        = cpu_cgroup_destroy,
        .can_attach     = cpu_cgroup_can_attach,
        .attach         = cpu_cgroup_attach,
 +      .allow_attach   = cpu_cgroup_allow_attach,
        .exit           = cpu_cgroup_exit,
        .populate       = cpu_cgroup_populate,
        .subsys_id      = cpu_cgroup_subsys_id,
  
  #include <net/bluetooth/bluetooth.h>
  
 +#ifdef CONFIG_ANDROID_PARANOID_NETWORK
 +#include <linux/android_aid.h>
 +#endif
 +
 +#ifndef CONFIG_BT_SOCK_DEBUG
 +#undef  BT_DBG
 +#define BT_DBG(D...)
 +#endif
 +
  #define VERSION "2.16"
  
  /* Bluetooth sockets */
@@@ -80,19 -71,16 +80,16 @@@ static const char *const bt_slock_key_s
        "slock-AF_BLUETOOTH-BTPROTO_AVDTP",
  };
  
- static inline void bt_sock_reclassify_lock(struct socket *sock, int proto)
+ void bt_sock_reclassify_lock(struct sock *sk, int proto)
  {
-       struct sock *sk = sock->sk;
-       if (!sk)
-               return;
+       BUG_ON(!sk);
        BUG_ON(sock_owned_by_user(sk));
  
        sock_lock_init_class_and_name(sk,
                        bt_slock_key_strings[proto], &bt_slock_key[proto],
                                bt_key_strings[proto], &bt_lock_key[proto]);
  }
+ EXPORT_SYMBOL(bt_sock_reclassify_lock);
  
  int bt_sock_register(int proto, const struct net_proto_family *ops)
  {
@@@ -134,40 -122,11 +131,40 @@@ int bt_sock_unregister(int proto
  }
  EXPORT_SYMBOL(bt_sock_unregister);
  
 +#ifdef CONFIG_ANDROID_PARANOID_NETWORK
 +static inline int current_has_bt_admin(void)
 +{
 +      return (!current_euid() || in_egroup_p(AID_NET_BT_ADMIN));
 +}
 +
 +static inline int current_has_bt(void)
 +{
 +      return (current_has_bt_admin() || in_egroup_p(AID_NET_BT));
 +}
 +# else
 +static inline int current_has_bt_admin(void)
 +{
 +      return 1;
 +}
 +
 +static inline int current_has_bt(void)
 +{
 +      return 1;
 +}
 +#endif
 +
  static int bt_sock_create(struct net *net, struct socket *sock, int proto,
                          int kern)
  {
        int err;
  
 +      if (proto == BTPROTO_RFCOMM || proto == BTPROTO_SCO ||
 +                      proto == BTPROTO_L2CAP) {
 +              if (!current_has_bt())
 +                      return -EPERM;
 +      } else if (!current_has_bt_admin())
 +              return -EPERM;
 +
        if (net != &init_net)
                return -EAFNOSUPPORT;
  
  
        if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) {
                err = bt_proto[proto]->create(net, sock, proto, kern);
-               bt_sock_reclassify_lock(sock, proto);
+               if (!err)
+                       bt_sock_reclassify_lock(sock->sk, proto);
                module_put(bt_proto[proto]->owner);
        }
  
@@@ -1018,10 -1018,10 +1018,10 @@@ static void l2cap_conn_del(struct hci_c
        hci_chan_del(conn->hchan);
  
        if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
-               __cancel_delayed_work(&conn->info_timer);
+               cancel_delayed_work_sync(&conn->info_timer);
  
        if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) {
-               __cancel_delayed_work(&conn->security_timer);
+               cancel_delayed_work_sync(&conn->security_timer);
                smp_chan_destroy(conn);
        }
  
@@@ -1120,7 -1120,7 +1120,7 @@@ static struct l2cap_chan *l2cap_global_
        return c1;
  }
  
- inline int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *dst)
+ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *dst)
  {
        struct sock *sk = chan->sk;
        bdaddr_t *src = &bt_sk(sk)->src;
        auth_type = l2cap_get_auth_type(chan);
  
        if (chan->dcid == L2CAP_CID_LE_DATA)
 -              hcon = hci_connect(hdev, LE_LINK, dst,
 +              hcon = hci_connect(hdev, LE_LINK, 0, dst,
                                        chan->sec_level, auth_type);
        else
 -              hcon = hci_connect(hdev, ACL_LINK, dst,
 +              hcon = hci_connect(hdev, ACL_LINK, 0, dst,
                                        chan->sec_level, auth_type);
  
        if (IS_ERR(hcon)) {
@@@ -2574,7 -2574,7 +2574,7 @@@ static inline int l2cap_command_rej(str
  
        if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
                                        cmd->ident == conn->info_ident) {
-               __cancel_delayed_work(&conn->info_timer);
+               cancel_delayed_work(&conn->info_timer);
  
                conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
                conn->info_ident = 0;
@@@ -2970,7 -2970,8 +2970,8 @@@ static inline int l2cap_config_rsp(stru
  
        default:
                sk->sk_err = ECONNRESET;
-               __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
+               __set_chan_timer(chan,
+                               msecs_to_jiffies(L2CAP_DISC_REJ_TIMEOUT));
                l2cap_send_disconn_req(conn, chan, ECONNRESET);
                goto done;
        }
@@@ -3120,7 -3121,7 +3121,7 @@@ static inline int l2cap_information_rsp
                        conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
                return 0;
  
-       __cancel_delayed_work(&conn->info_timer);
+       cancel_delayed_work(&conn->info_timer);
  
        if (result != L2CAP_IR_SUCCESS) {
                conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
@@@ -4478,7 -4479,8 +4479,8 @@@ static inline void l2cap_check_encrypti
        if (encrypt == 0x00) {
                if (chan->sec_level == BT_SECURITY_MEDIUM) {
                        __clear_chan_timer(chan);
-                       __set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
+                       __set_chan_timer(chan,
+                                       msecs_to_jiffies(L2CAP_ENC_TIMEOUT));
                } else if (chan->sec_level == BT_SECURITY_HIGH)
                        l2cap_chan_close(chan, ECONNREFUSED);
        } else {
@@@ -4499,7 -4501,7 +4501,7 @@@ int l2cap_security_cfm(struct hci_conn 
  
        if (hcon->type == LE_LINK) {
                smp_distribute_keys(conn, 0);
-               __cancel_delayed_work(&conn->security_timer);
+               cancel_delayed_work(&conn->security_timer);
        }
  
        rcu_read_lock();
                                        L2CAP_CONN_REQ, sizeof(req), &req);
                        } else {
                                __clear_chan_timer(chan);
-                               __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
+                               __set_chan_timer(chan,
+                                       msecs_to_jiffies(L2CAP_DISC_TIMEOUT));
                        }
                } else if (chan->state == BT_CONNECT2) {
                        struct l2cap_conn_rsp rsp;
                                }
                        } else {
                                l2cap_state_change(chan, BT_DISCONN);
-                               __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
+                               __set_chan_timer(chan,
+                                       msecs_to_jiffies(L2CAP_DISC_TIMEOUT));
                                res = L2CAP_CR_SEC_BLOCK;
                                stat = L2CAP_CS_NO_INFO;
                        }
@@@ -462,6 -462,7 +462,6 @@@ static int __rfcomm_dlc_close(struct rf
  
        switch (d->state) {
        case BT_CONNECT:
 -      case BT_CONFIG:
                if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) {
                        set_bit(RFCOMM_AUTH_REJECT, &d->flags);
                        rfcomm_schedule();
@@@ -1163,12 -1164,18 +1163,18 @@@ static int rfcomm_recv_ua(struct rfcomm
                        break;
  
                case BT_DISCONN:
-                       /* When socket is closed and we are not RFCOMM
-                        * initiator rfcomm_process_rx already calls
-                        * rfcomm_session_put() */
-                       if (s->sock->sk->sk_state != BT_CLOSED)
-                               if (list_empty(&s->dlcs))
-                                       rfcomm_session_put(s);
+                       /* rfcomm_session_put is called later so don't do
+                        * anything here otherwise we will mess up the session
+                        * reference counter:
+                        *
+                        * (a) when we are the initiator dlc_unlink will drive
+                        * the reference counter to 0 (there is no initial put
+                        * after session_add)
+                        *
+                        * (b) when we are not the initiator rfcomm_rx_process
+                        * will explicitly call put to balance the initial hold
+                        * done after session add.
+                        */
                        break;
                }
        }