]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville...
authorDavid S. Miller <davem@davemloft.net>
Sun, 8 Jun 2014 21:17:39 +0000 (14:17 -0700)
committerDavid S. Miller <davem@davemloft.net>
Sun, 8 Jun 2014 21:17:39 +0000 (14:17 -0700)
John W. Linville says:

====================
pull request: wireless-next 2014-06-06

Please accept this batch of fixes intended for the 3.16 stream.

For the bluetooth bits, Gustavo says:

"Here some more patches for 3.16. We know that Linus already opened the merge
window, but this is fix only pull request, and most of the patches here are
also tagged for stable."

Along with that, Andrea Merello provides a fix for the broken scanning
in the venerable at76c50x driver...
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/bluetooth/ath3k.c
drivers/net/wireless/at76c50x-usb.c
drivers/net/wireless/at76c50x-usb.h
net/bluetooth/6lowpan.c
net/bluetooth/hci_event.c
net/bluetooth/l2cap_core.c
net/bluetooth/l2cap_sock.c
net/bluetooth/mgmt.c
net/bluetooth/smp.c

index a83b57e57b6370572d53325638355a0d94ce24bf..f98380648cb3513fe47ac19213ce0b105a0d1873 100644 (file)
@@ -193,9 +193,10 @@ static int ath3k_load_firmware(struct usb_device *udev,
        sent += 20;
        count -= 20;
 
+       pipe = usb_sndbulkpipe(udev, 0x02);
+
        while (count) {
                size = min_t(uint, count, BULK_SIZE);
-               pipe = usb_sndbulkpipe(udev, 0x02);
                memcpy(send_buf, firmware->data + sent, size);
 
                err = usb_bulk_msg(udev, pipe, send_buf, size,
index 10fd12ec85be909501bd831ba8174f03f1b5cd2e..d48776e4f343e050787510923bc01e689a2bd9cc 100644 (file)
@@ -1429,6 +1429,8 @@ static int at76_startup_device(struct at76_priv *priv)
        /* remove BSSID from previous run */
        memset(priv->bssid, 0, ETH_ALEN);
 
+       priv->scanning = false;
+
        if (at76_set_radio(priv, 1) == 1)
                at76_wait_completion(priv, CMD_RADIO_ON);
 
@@ -1502,6 +1504,52 @@ static void at76_work_submit_rx(struct work_struct *work)
        mutex_unlock(&priv->mtx);
 }
 
+/* This is a workaround to make scan working:
+ * currently mac80211 does not process frames with no frequency
+ * information.
+ * However during scan the HW performs a sweep by itself, and we
+ * are unable to know where the radio is actually tuned.
+ * This function tries to do its best to guess this information..
+ * During scan, If the current frame is a beacon or a probe response,
+ * the channel information is extracted from it.
+ * When not scanning, for other frames, or if it happens that for
+ * whatever reason we fail to parse beacons and probe responses, this
+ * function returns the priv->channel information, that should be correct
+ * at least when we are not scanning.
+ */
+static inline int at76_guess_freq(struct at76_priv *priv)
+{
+       size_t el_off;
+       const u8 *el;
+       int channel = priv->channel;
+       int len = priv->rx_skb->len;
+       struct ieee80211_hdr *hdr = (void *)priv->rx_skb->data;
+
+       if (!priv->scanning)
+               goto exit;
+
+       if (len < 24)
+               goto exit;
+
+       if (ieee80211_is_probe_resp(hdr->frame_control)) {
+               el_off = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
+               el = ((struct ieee80211_mgmt *)hdr)->u.probe_resp.variable;
+       } else if (ieee80211_is_beacon(hdr->frame_control)) {
+               el_off = offsetof(struct ieee80211_mgmt, u.beacon.variable);
+               el = ((struct ieee80211_mgmt *)hdr)->u.beacon.variable;
+       } else {
+               goto exit;
+       }
+       len -= el_off;
+
+       el = cfg80211_find_ie(WLAN_EID_DS_PARAMS, el, len);
+       if (el && el[1] > 0)
+               channel = el[2];
+
+exit:
+       return ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
+}
+
 static void at76_rx_tasklet(unsigned long param)
 {
        struct urb *urb = (struct urb *)param;
@@ -1542,6 +1590,8 @@ static void at76_rx_tasklet(unsigned long param)
        rx_status.signal = buf->rssi;
        rx_status.flag |= RX_FLAG_DECRYPTED;
        rx_status.flag |= RX_FLAG_IV_STRIPPED;
+       rx_status.band = IEEE80211_BAND_2GHZ;
+       rx_status.freq = at76_guess_freq(priv);
 
        at76_dbg(DBG_MAC80211, "calling ieee80211_rx_irqsafe(): %d/%d",
                 priv->rx_skb->len, priv->rx_skb->data_len);
@@ -1894,6 +1944,8 @@ static void at76_dwork_hw_scan(struct work_struct *work)
        if (is_valid_ether_addr(priv->bssid))
                at76_join(priv);
 
+       priv->scanning = false;
+
        mutex_unlock(&priv->mtx);
 
        ieee80211_scan_completed(priv->hw, false);
@@ -1948,6 +2000,7 @@ static int at76_hw_scan(struct ieee80211_hw *hw,
                goto exit;
        }
 
+       priv->scanning = true;
        ieee80211_queue_delayed_work(priv->hw, &priv->dwork_hw_scan,
                                     SCAN_POLL_INTERVAL);
 
index 4718aa59f0510ba04ae07cbffd73ff4e1f4f0b7e..55090a38ac9549eb546a747144b9f274ae1b2faf 100644 (file)
@@ -418,6 +418,7 @@ struct at76_priv {
        int scan_max_time;      /* scan max channel time */
        int scan_mode;          /* SCAN_TYPE_ACTIVE, SCAN_TYPE_PASSIVE */
        int scan_need_any;      /* if set, need to scan for any ESSID */
+       bool scanning;          /* if set, the scan is running */
 
        u16 assoc_id;           /* current association ID, if associated */
 
index 73492b91105ac0aba10aec738415128d0582bfc5..8796ffa08b43b4f57ae1485f4a5867c0f532807c 100644 (file)
@@ -420,12 +420,18 @@ static int conn_send(struct l2cap_conn *conn,
        return 0;
 }
 
-static void get_dest_bdaddr(struct in6_addr *ip6_daddr,
-                           bdaddr_t *addr, u8 *addr_type)
+static u8 get_addr_type_from_eui64(u8 byte)
 {
-       u8 *eui64;
+       /* Is universal(0) or local(1) bit,  */
+       if (byte & 0x02)
+               return ADDR_LE_DEV_RANDOM;
 
-       eui64 = ip6_daddr->s6_addr + 8;
+       return ADDR_LE_DEV_PUBLIC;
+}
+
+static void copy_to_bdaddr(struct in6_addr *ip6_daddr, bdaddr_t *addr)
+{
+       u8 *eui64 = ip6_daddr->s6_addr + 8;
 
        addr->b[0] = eui64[7];
        addr->b[1] = eui64[6];
@@ -433,16 +439,19 @@ static void get_dest_bdaddr(struct in6_addr *ip6_daddr,
        addr->b[3] = eui64[2];
        addr->b[4] = eui64[1];
        addr->b[5] = eui64[0];
+}
 
-       addr->b[5] ^= 2;
+static void convert_dest_bdaddr(struct in6_addr *ip6_daddr,
+                               bdaddr_t *addr, u8 *addr_type)
+{
+       copy_to_bdaddr(ip6_daddr, addr);
 
-       /* Set universal/local bit to 0 */
-       if (addr->b[5] & 1) {
-               addr->b[5] &= ~1;
-               *addr_type = ADDR_LE_DEV_PUBLIC;
-       } else {
-               *addr_type = ADDR_LE_DEV_RANDOM;
-       }
+       /* We need to toggle the U/L bit that we got from IPv6 address
+        * so that we get the proper address and type of the BD address.
+        */
+       addr->b[5] ^= 0x02;
+
+       *addr_type = get_addr_type_from_eui64(addr->b[5]);
 }
 
 static int header_create(struct sk_buff *skb, struct net_device *netdev,
@@ -473,9 +482,11 @@ static int header_create(struct sk_buff *skb, struct net_device *netdev,
                /* Get destination BT device from skb.
                 * If there is no such peer then discard the packet.
                 */
-               get_dest_bdaddr(&hdr->daddr, &addr, &addr_type);
+               convert_dest_bdaddr(&hdr->daddr, &addr, &addr_type);
 
-               BT_DBG("dest addr %pMR type %d", &addr, addr_type);
+               BT_DBG("dest addr %pMR type %s IP %pI6c", &addr,
+                      addr_type == ADDR_LE_DEV_PUBLIC ? "PUBLIC" : "RANDOM",
+                      &hdr->daddr);
 
                read_lock_irqsave(&devices_lock, flags);
                peer = peer_lookup_ba(dev, &addr, addr_type);
@@ -556,7 +567,7 @@ static netdev_tx_t bt_xmit(struct sk_buff *skb, struct net_device *netdev)
        } else {
                unsigned long flags;
 
-               get_dest_bdaddr(&lowpan_cb(skb)->addr, &addr, &addr_type);
+               convert_dest_bdaddr(&lowpan_cb(skb)->addr, &addr, &addr_type);
                eui64_addr = lowpan_cb(skb)->addr.s6_addr + 8;
                dev = lowpan_dev(netdev);
 
@@ -564,8 +575,10 @@ static netdev_tx_t bt_xmit(struct sk_buff *skb, struct net_device *netdev)
                peer = peer_lookup_ba(dev, &addr, addr_type);
                read_unlock_irqrestore(&devices_lock, flags);
 
-               BT_DBG("xmit from %s to %pMR (%pI6c) peer %p", netdev->name,
-                      &addr, &lowpan_cb(skb)->addr, peer);
+               BT_DBG("xmit %s to %pMR type %s IP %pI6c peer %p",
+                      netdev->name, &addr,
+                      addr_type == ADDR_LE_DEV_PUBLIC ? "PUBLIC" : "RANDOM",
+                      &lowpan_cb(skb)->addr, peer);
 
                if (peer && peer->conn)
                        err = send_pkt(peer->conn, netdev->dev_addr,
@@ -620,13 +633,13 @@ static void set_addr(u8 *eui, u8 *addr, u8 addr_type)
        eui[6] = addr[1];
        eui[7] = addr[0];
 
-       eui[0] ^= 2;
-
-       /* Universal/local bit set, RFC 4291 */
+       /* Universal/local bit set, BT 6lowpan draft ch. 3.2.1 */
        if (addr_type == ADDR_LE_DEV_PUBLIC)
-               eui[0] |= 1;
+               eui[0] &= ~0x02;
        else
-               eui[0] &= ~1;
+               eui[0] |= 0x02;
+
+       BT_DBG("type %d addr %*phC", addr_type, 8, eui);
 }
 
 static void set_dev_addr(struct net_device *netdev, bdaddr_t *addr,
@@ -634,7 +647,6 @@ static void set_dev_addr(struct net_device *netdev, bdaddr_t *addr,
 {
        netdev->addr_assign_type = NET_ADDR_PERM;
        set_addr(netdev->dev_addr, addr->b, addr_type);
-       netdev->dev_addr[0] ^= 2;
 }
 
 static void ifup(struct net_device *netdev)
@@ -684,13 +696,6 @@ static int add_peer_conn(struct l2cap_conn *conn, struct lowpan_dev *dev)
 
        memcpy(&peer->eui64_addr, (u8 *)&peer->peer_addr.s6_addr + 8,
               EUI64_ADDR_LEN);
-       peer->eui64_addr[0] ^= 2; /* second bit-flip (Universe/Local)
-                                  * is done according RFC2464
-                                  */
-
-       raw_dump_inline(__func__, "peer IPv6 address",
-                       (unsigned char *)&peer->peer_addr, 16);
-       raw_dump_inline(__func__, "peer EUI64 address", peer->eui64_addr, 8);
 
        write_lock_irqsave(&devices_lock, flags);
        INIT_LIST_HEAD(&peer->list);
index 3454807a40c53df7e720543e90ab4208d9e0afc2..1096e4cd12833387313c7b5da3dd7698b3faad32 100644 (file)
@@ -1453,6 +1453,7 @@ static int hci_outgoing_auth_needed(struct hci_dev *hdev,
         * is requested.
         */
        if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
+           conn->pending_sec_level != BT_SECURITY_FIPS &&
            conn->pending_sec_level != BT_SECURITY_HIGH &&
            conn->pending_sec_level != BT_SECURITY_MEDIUM)
                return 0;
@@ -3076,7 +3077,8 @@ static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
                }
 
                if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
-                   conn->pending_sec_level == BT_SECURITY_HIGH) {
+                   (conn->pending_sec_level == BT_SECURITY_HIGH ||
+                    conn->pending_sec_level == BT_SECURITY_FIPS)) {
                        BT_DBG("%s ignoring key unauthenticated for high security",
                               hdev->name);
                        goto not_found;
index dc4d301d3a728ccd0af8efe4e9648b843d598406..6eabbe05fe54fe8ecc39707a05350439d99ce830 100644 (file)
@@ -471,8 +471,14 @@ void l2cap_chan_set_defaults(struct l2cap_chan *chan)
        chan->max_tx = L2CAP_DEFAULT_MAX_TX;
        chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;
        chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
+       chan->remote_max_tx = chan->max_tx;
+       chan->remote_tx_win = chan->tx_win;
        chan->ack_win = L2CAP_DEFAULT_TX_WINDOW;
        chan->sec_level = BT_SECURITY_LOW;
+       chan->flush_to = L2CAP_DEFAULT_FLUSH_TO;
+       chan->retrans_timeout = L2CAP_DEFAULT_RETRANS_TO;
+       chan->monitor_timeout = L2CAP_DEFAULT_MONITOR_TO;
+       chan->conf_state = 0;
 
        set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
 }
index ef5e5b04f34fbd3c130c74dc2a41ffe775870b3b..ade3fb4c23bce81aa054e2bdd064f74019767dae 100644 (file)
@@ -1180,13 +1180,16 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)
        /* Check for backlog size */
        if (sk_acceptq_is_full(parent)) {
                BT_DBG("backlog full %d", parent->sk_ack_backlog);
+               release_sock(parent);
                return NULL;
        }
 
        sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP,
                              GFP_ATOMIC);
-       if (!sk)
+       if (!sk) {
+               release_sock(parent);
                return NULL;
+        }
 
        bt_sock_reclassify_lock(sk, BTPROTO_L2CAP);
 
index 5e9c21a5525f445ae7c513a9a175e6337aed3a41..0fce54412ffdc077f6d337eadc4cfbe20b51ed26 100644 (file)
@@ -4546,10 +4546,16 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
                else
                        type = HCI_SMP_LTK_SLAVE;
 
-               if (key->type == MGMT_LTK_UNAUTHENTICATED)
+               switch (key->type) {
+               case MGMT_LTK_UNAUTHENTICATED:
                        authenticated = 0x00;
-               else
+                       break;
+               case MGMT_LTK_AUTHENTICATED:
                        authenticated = 0x01;
+                       break;
+               default:
+                       continue;
+               }
 
                hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
                            authenticated, key->val, key->enc_size, key->ediv,
index 4f9662d0fd812f47ddc11e2d738de84e7360092c..3d1cc164557de1750e4768f229aaede55b03e80c 100644 (file)
@@ -909,10 +909,11 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
 
        authreq = seclevel_to_authreq(sec_level);
 
-       /* hcon->auth_type is set by pair_device in mgmt.c. If the MITM
-        * flag is set we should also set it for the SMP request.
+       /* Require MITM if IO Capability allows or the security level
+        * requires it.
         */
-       if ((hcon->auth_type & 0x01))
+       if (hcon->io_capability != HCI_IO_NO_INPUT_OUTPUT ||
+           sec_level > BT_SECURITY_MEDIUM)
                authreq |= SMP_AUTH_MITM;
 
        if (hcon->link_mode & HCI_LM_MASTER) {