mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-17 01:04:19 +08:00
Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next
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>
This commit is contained in:
commit
b78370c021
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user