Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
This commit is contained in:
@@ -43,19 +43,6 @@ config BT_L2CAP
|
||||
Say Y here to compile L2CAP support into the kernel or say M to
|
||||
compile it as module (l2cap).
|
||||
|
||||
config BT_L2CAP_EXT_FEATURES
|
||||
bool "L2CAP Extended Features support (EXPERIMENTAL)"
|
||||
depends on BT_L2CAP && EXPERIMENTAL
|
||||
help
|
||||
This option enables the L2CAP Extended Features support. These
|
||||
new features include the Enhanced Retransmission and Streaming
|
||||
Modes, the Frame Check Sequence (FCS), and Segmentation and
|
||||
Reassembly (SAR) for L2CAP packets. They are a required for the
|
||||
new Alternate MAC/PHY and the Bluetooth Medical Profile.
|
||||
|
||||
You should say N unless you know what you are doing. Note that
|
||||
this is in an experimental state yet.
|
||||
|
||||
config BT_SCO
|
||||
tristate "SCO links support"
|
||||
depends on BT
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
BlueZ - Bluetooth protocol stack for Linux
|
||||
Copyright (C) 2000-2001 Qualcomm Incorporated
|
||||
Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
|
||||
|
||||
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
|
||||
|
||||
@@ -155,6 +155,27 @@ void hci_setup_sync(struct hci_conn *conn, __u16 handle)
|
||||
hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp);
|
||||
}
|
||||
|
||||
/* Device _must_ be locked */
|
||||
void hci_sco_setup(struct hci_conn *conn, __u8 status)
|
||||
{
|
||||
struct hci_conn *sco = conn->link;
|
||||
|
||||
BT_DBG("%p", conn);
|
||||
|
||||
if (!sco)
|
||||
return;
|
||||
|
||||
if (!status) {
|
||||
if (lmp_esco_capable(conn->hdev))
|
||||
hci_setup_sync(sco, conn->handle);
|
||||
else
|
||||
hci_add_sco(sco, conn->handle);
|
||||
} else {
|
||||
hci_proto_connect_cfm(sco, status);
|
||||
hci_conn_del(sco);
|
||||
}
|
||||
}
|
||||
|
||||
static void hci_conn_timeout(unsigned long arg)
|
||||
{
|
||||
struct hci_conn *conn = (void *) arg;
|
||||
@@ -385,10 +406,13 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8
|
||||
acl->power_save = 1;
|
||||
hci_conn_enter_active_mode(acl);
|
||||
|
||||
if (lmp_esco_capable(hdev))
|
||||
hci_setup_sync(sco, acl->handle);
|
||||
else
|
||||
hci_add_sco(sco, acl->handle);
|
||||
if (test_bit(HCI_CONN_MODE_CHANGE_PEND, &acl->pend)) {
|
||||
/* defer SCO setup until mode change completed */
|
||||
set_bit(HCI_CONN_SCO_SETUP_PEND, &acl->pend);
|
||||
return sco;
|
||||
}
|
||||
|
||||
hci_sco_setup(acl, 0x00);
|
||||
}
|
||||
|
||||
return sco;
|
||||
|
@@ -562,6 +562,7 @@ static int hci_dev_do_close(struct hci_dev *hdev)
|
||||
hci_dev_lock_bh(hdev);
|
||||
inquiry_cache_flush(hdev);
|
||||
hci_conn_hash_flush(hdev);
|
||||
hci_blacklist_clear(hdev);
|
||||
hci_dev_unlock_bh(hdev);
|
||||
|
||||
hci_notify(hdev, HCI_DEV_DOWN);
|
||||
@@ -913,7 +914,7 @@ int hci_register_dev(struct hci_dev *hdev)
|
||||
skb_queue_head_init(&hdev->cmd_q);
|
||||
skb_queue_head_init(&hdev->raw_q);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
for (i = 0; i < NUM_REASSEMBLY; i++)
|
||||
hdev->reassembly[i] = NULL;
|
||||
|
||||
init_waitqueue_head(&hdev->req_wait_q);
|
||||
@@ -923,6 +924,8 @@ int hci_register_dev(struct hci_dev *hdev)
|
||||
|
||||
hci_conn_hash_init(hdev);
|
||||
|
||||
INIT_LIST_HEAD(&hdev->blacklist.list);
|
||||
|
||||
memset(&hdev->stat, 0, sizeof(struct hci_dev_stats));
|
||||
|
||||
atomic_set(&hdev->promisc, 0);
|
||||
@@ -970,7 +973,7 @@ int hci_unregister_dev(struct hci_dev *hdev)
|
||||
|
||||
hci_dev_do_close(hdev);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
for (i = 0; i < NUM_REASSEMBLY; i++)
|
||||
kfree_skb(hdev->reassembly[i]);
|
||||
|
||||
hci_notify(hdev, HCI_DEV_UNREG);
|
||||
@@ -1030,90 +1033,171 @@ int hci_recv_frame(struct sk_buff *skb)
|
||||
}
|
||||
EXPORT_SYMBOL(hci_recv_frame);
|
||||
|
||||
/* Receive packet type fragment */
|
||||
#define __reassembly(hdev, type) ((hdev)->reassembly[(type) - 2])
|
||||
|
||||
int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count)
|
||||
static int hci_reassembly(struct hci_dev *hdev, int type, void *data,
|
||||
int count, __u8 index, gfp_t gfp_mask)
|
||||
{
|
||||
if (type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT)
|
||||
int len = 0;
|
||||
int hlen = 0;
|
||||
int remain = count;
|
||||
struct sk_buff *skb;
|
||||
struct bt_skb_cb *scb;
|
||||
|
||||
if ((type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT) ||
|
||||
index >= NUM_REASSEMBLY)
|
||||
return -EILSEQ;
|
||||
|
||||
while (count) {
|
||||
struct sk_buff *skb = __reassembly(hdev, type);
|
||||
struct { int expect; } *scb;
|
||||
int len = 0;
|
||||
skb = hdev->reassembly[index];
|
||||
|
||||
if (!skb) {
|
||||
/* Start of the frame */
|
||||
|
||||
switch (type) {
|
||||
case HCI_EVENT_PKT:
|
||||
if (count >= HCI_EVENT_HDR_SIZE) {
|
||||
struct hci_event_hdr *h = data;
|
||||
len = HCI_EVENT_HDR_SIZE + h->plen;
|
||||
} else
|
||||
return -EILSEQ;
|
||||
break;
|
||||
|
||||
case HCI_ACLDATA_PKT:
|
||||
if (count >= HCI_ACL_HDR_SIZE) {
|
||||
struct hci_acl_hdr *h = data;
|
||||
len = HCI_ACL_HDR_SIZE + __le16_to_cpu(h->dlen);
|
||||
} else
|
||||
return -EILSEQ;
|
||||
break;
|
||||
|
||||
case HCI_SCODATA_PKT:
|
||||
if (count >= HCI_SCO_HDR_SIZE) {
|
||||
struct hci_sco_hdr *h = data;
|
||||
len = HCI_SCO_HDR_SIZE + h->dlen;
|
||||
} else
|
||||
return -EILSEQ;
|
||||
break;
|
||||
}
|
||||
|
||||
skb = bt_skb_alloc(len, GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
BT_ERR("%s no memory for packet", hdev->name);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
skb->dev = (void *) hdev;
|
||||
bt_cb(skb)->pkt_type = type;
|
||||
|
||||
__reassembly(hdev, type) = skb;
|
||||
|
||||
scb = (void *) skb->cb;
|
||||
scb->expect = len;
|
||||
} else {
|
||||
/* Continuation */
|
||||
|
||||
scb = (void *) skb->cb;
|
||||
len = scb->expect;
|
||||
if (!skb) {
|
||||
switch (type) {
|
||||
case HCI_ACLDATA_PKT:
|
||||
len = HCI_MAX_FRAME_SIZE;
|
||||
hlen = HCI_ACL_HDR_SIZE;
|
||||
break;
|
||||
case HCI_EVENT_PKT:
|
||||
len = HCI_MAX_EVENT_SIZE;
|
||||
hlen = HCI_EVENT_HDR_SIZE;
|
||||
break;
|
||||
case HCI_SCODATA_PKT:
|
||||
len = HCI_MAX_SCO_SIZE;
|
||||
hlen = HCI_SCO_HDR_SIZE;
|
||||
break;
|
||||
}
|
||||
|
||||
len = min(len, count);
|
||||
skb = bt_skb_alloc(len, gfp_mask);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
scb = (void *) skb->cb;
|
||||
scb->expect = hlen;
|
||||
scb->pkt_type = type;
|
||||
|
||||
skb->dev = (void *) hdev;
|
||||
hdev->reassembly[index] = skb;
|
||||
}
|
||||
|
||||
while (count) {
|
||||
scb = (void *) skb->cb;
|
||||
len = min(scb->expect, (__u16)count);
|
||||
|
||||
memcpy(skb_put(skb, len), data, len);
|
||||
|
||||
count -= len;
|
||||
data += len;
|
||||
scb->expect -= len;
|
||||
remain = count;
|
||||
|
||||
switch (type) {
|
||||
case HCI_EVENT_PKT:
|
||||
if (skb->len == HCI_EVENT_HDR_SIZE) {
|
||||
struct hci_event_hdr *h = hci_event_hdr(skb);
|
||||
scb->expect = h->plen;
|
||||
|
||||
if (skb_tailroom(skb) < scb->expect) {
|
||||
kfree_skb(skb);
|
||||
hdev->reassembly[index] = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case HCI_ACLDATA_PKT:
|
||||
if (skb->len == HCI_ACL_HDR_SIZE) {
|
||||
struct hci_acl_hdr *h = hci_acl_hdr(skb);
|
||||
scb->expect = __le16_to_cpu(h->dlen);
|
||||
|
||||
if (skb_tailroom(skb) < scb->expect) {
|
||||
kfree_skb(skb);
|
||||
hdev->reassembly[index] = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case HCI_SCODATA_PKT:
|
||||
if (skb->len == HCI_SCO_HDR_SIZE) {
|
||||
struct hci_sco_hdr *h = hci_sco_hdr(skb);
|
||||
scb->expect = h->dlen;
|
||||
|
||||
if (skb_tailroom(skb) < scb->expect) {
|
||||
kfree_skb(skb);
|
||||
hdev->reassembly[index] = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (scb->expect == 0) {
|
||||
/* Complete frame */
|
||||
|
||||
__reassembly(hdev, type) = NULL;
|
||||
|
||||
bt_cb(skb)->pkt_type = type;
|
||||
hci_recv_frame(skb);
|
||||
}
|
||||
|
||||
count -= len; data += len;
|
||||
hdev->reassembly[index] = NULL;
|
||||
return remain;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return remain;
|
||||
}
|
||||
|
||||
int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count)
|
||||
{
|
||||
int rem = 0;
|
||||
|
||||
if (type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT)
|
||||
return -EILSEQ;
|
||||
|
||||
while (count) {
|
||||
rem = hci_reassembly(hdev, type, data, count,
|
||||
type - 1, GFP_ATOMIC);
|
||||
if (rem < 0)
|
||||
return rem;
|
||||
|
||||
data += (count - rem);
|
||||
count = rem;
|
||||
};
|
||||
|
||||
return rem;
|
||||
}
|
||||
EXPORT_SYMBOL(hci_recv_fragment);
|
||||
|
||||
#define STREAM_REASSEMBLY 0
|
||||
|
||||
int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count)
|
||||
{
|
||||
int type;
|
||||
int rem = 0;
|
||||
|
||||
while (count) {
|
||||
struct sk_buff *skb = hdev->reassembly[STREAM_REASSEMBLY];
|
||||
|
||||
if (!skb) {
|
||||
struct { char type; } *pkt;
|
||||
|
||||
/* Start of the frame */
|
||||
pkt = data;
|
||||
type = pkt->type;
|
||||
|
||||
data++;
|
||||
count--;
|
||||
} else
|
||||
type = bt_cb(skb)->pkt_type;
|
||||
|
||||
rem = hci_reassembly(hdev, type, data,
|
||||
count, STREAM_REASSEMBLY, GFP_ATOMIC);
|
||||
if (rem < 0)
|
||||
return rem;
|
||||
|
||||
data += (count - rem);
|
||||
count = rem;
|
||||
};
|
||||
|
||||
return rem;
|
||||
}
|
||||
EXPORT_SYMBOL(hci_recv_stream_fragment);
|
||||
|
||||
/* ---- Interface to upper protocols ---- */
|
||||
|
||||
/* Register/Unregister protocols.
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
BlueZ - Bluetooth protocol stack for Linux
|
||||
Copyright (C) 2000-2001 Qualcomm Incorporated
|
||||
Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
|
||||
|
||||
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
|
||||
|
||||
@@ -584,7 +584,7 @@ static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
|
||||
conn->out = 1;
|
||||
conn->link_mode |= HCI_LM_MASTER;
|
||||
} else
|
||||
BT_ERR("No memmory for new connection");
|
||||
BT_ERR("No memory for new connection");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -785,9 +785,13 @@ static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
|
||||
if (conn)
|
||||
if (conn) {
|
||||
clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
|
||||
|
||||
if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
|
||||
hci_sco_setup(conn, status);
|
||||
}
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
}
|
||||
|
||||
@@ -808,9 +812,13 @@ static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
|
||||
if (conn)
|
||||
if (conn) {
|
||||
clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
|
||||
|
||||
if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
|
||||
hci_sco_setup(conn, status);
|
||||
}
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
}
|
||||
|
||||
@@ -915,20 +923,8 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
|
||||
} else
|
||||
conn->state = BT_CLOSED;
|
||||
|
||||
if (conn->type == ACL_LINK) {
|
||||
struct hci_conn *sco = conn->link;
|
||||
if (sco) {
|
||||
if (!ev->status) {
|
||||
if (lmp_esco_capable(hdev))
|
||||
hci_setup_sync(sco, conn->handle);
|
||||
else
|
||||
hci_add_sco(sco, conn->handle);
|
||||
} else {
|
||||
hci_proto_connect_cfm(sco, ev->status);
|
||||
hci_conn_del(sco);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (conn->type == ACL_LINK)
|
||||
hci_sco_setup(conn, ev->status);
|
||||
|
||||
if (ev->status) {
|
||||
hci_proto_connect_cfm(conn, ev->status);
|
||||
@@ -952,7 +948,7 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk
|
||||
|
||||
mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
|
||||
|
||||
if (mask & HCI_LM_ACCEPT) {
|
||||
if ((mask & HCI_LM_ACCEPT) && !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
|
||||
/* Connection accepted */
|
||||
struct inquiry_entry *ie;
|
||||
struct hci_conn *conn;
|
||||
@@ -965,7 +961,7 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk
|
||||
conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
|
||||
if (!conn) {
|
||||
if (!(conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr))) {
|
||||
BT_ERR("No memmory for new connection");
|
||||
BT_ERR("No memory for new connection");
|
||||
hci_dev_unlock(hdev);
|
||||
return;
|
||||
}
|
||||
@@ -1481,6 +1477,9 @@ static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb
|
||||
else
|
||||
conn->power_save = 0;
|
||||
}
|
||||
|
||||
if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
|
||||
hci_sco_setup(conn, ev->status);
|
||||
}
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
|
@@ -165,6 +165,86 @@ static int hci_sock_release(struct socket *sock)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr)
|
||||
{
|
||||
struct list_head *p;
|
||||
struct bdaddr_list *blacklist = &hdev->blacklist;
|
||||
|
||||
list_for_each(p, &blacklist->list) {
|
||||
struct bdaddr_list *b;
|
||||
|
||||
b = list_entry(p, struct bdaddr_list, list);
|
||||
|
||||
if (bacmp(bdaddr, &b->bdaddr) == 0)
|
||||
return b;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int hci_blacklist_add(struct hci_dev *hdev, void __user *arg)
|
||||
{
|
||||
bdaddr_t bdaddr;
|
||||
struct bdaddr_list *entry;
|
||||
|
||||
if (copy_from_user(&bdaddr, arg, sizeof(bdaddr)))
|
||||
return -EFAULT;
|
||||
|
||||
if (bacmp(&bdaddr, BDADDR_ANY) == 0)
|
||||
return -EBADF;
|
||||
|
||||
if (hci_blacklist_lookup(hdev, &bdaddr))
|
||||
return -EEXIST;
|
||||
|
||||
entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL);
|
||||
if (!entry)
|
||||
return -ENOMEM;
|
||||
|
||||
bacpy(&entry->bdaddr, &bdaddr);
|
||||
|
||||
list_add(&entry->list, &hdev->blacklist.list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hci_blacklist_clear(struct hci_dev *hdev)
|
||||
{
|
||||
struct list_head *p, *n;
|
||||
struct bdaddr_list *blacklist = &hdev->blacklist;
|
||||
|
||||
list_for_each_safe(p, n, &blacklist->list) {
|
||||
struct bdaddr_list *b;
|
||||
|
||||
b = list_entry(p, struct bdaddr_list, list);
|
||||
|
||||
list_del(p);
|
||||
kfree(b);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hci_blacklist_del(struct hci_dev *hdev, void __user *arg)
|
||||
{
|
||||
bdaddr_t bdaddr;
|
||||
struct bdaddr_list *entry;
|
||||
|
||||
if (copy_from_user(&bdaddr, arg, sizeof(bdaddr)))
|
||||
return -EFAULT;
|
||||
|
||||
if (bacmp(&bdaddr, BDADDR_ANY) == 0)
|
||||
return hci_blacklist_clear(hdev);
|
||||
|
||||
entry = hci_blacklist_lookup(hdev, &bdaddr);
|
||||
if (!entry)
|
||||
return -ENOENT;
|
||||
|
||||
list_del(&entry->list);
|
||||
kfree(entry);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Ioctls that require bound socket */
|
||||
static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
@@ -194,6 +274,16 @@ static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsign
|
||||
case HCIGETAUTHINFO:
|
||||
return hci_get_auth_info(hdev, (void __user *) arg);
|
||||
|
||||
case HCIBLOCKADDR:
|
||||
if (!capable(CAP_NET_ADMIN))
|
||||
return -EACCES;
|
||||
return hci_blacklist_add(hdev, (void __user *) arg);
|
||||
|
||||
case HCIUNBLOCKADDR:
|
||||
if (!capable(CAP_NET_ADMIN))
|
||||
return -EACCES;
|
||||
return hci_blacklist_del(hdev, (void __user *) arg);
|
||||
|
||||
default:
|
||||
if (hdev->ioctl)
|
||||
return hdev->ioctl(hdev, cmd, arg);
|
||||
|
@@ -436,6 +436,41 @@ static const struct file_operations inquiry_cache_fops = {
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static int blacklist_show(struct seq_file *f, void *p)
|
||||
{
|
||||
struct hci_dev *hdev = f->private;
|
||||
struct bdaddr_list *blacklist = &hdev->blacklist;
|
||||
struct list_head *l;
|
||||
|
||||
hci_dev_lock_bh(hdev);
|
||||
|
||||
list_for_each(l, &blacklist->list) {
|
||||
struct bdaddr_list *b;
|
||||
bdaddr_t bdaddr;
|
||||
|
||||
b = list_entry(l, struct bdaddr_list, list);
|
||||
|
||||
baswap(&bdaddr, &b->bdaddr);
|
||||
|
||||
seq_printf(f, "%s\n", batostr(&bdaddr));
|
||||
}
|
||||
|
||||
hci_dev_unlock_bh(hdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int blacklist_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, blacklist_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations blacklist_fops = {
|
||||
.open = blacklist_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
int hci_register_sysfs(struct hci_dev *hdev)
|
||||
{
|
||||
struct device *dev = &hdev->dev;
|
||||
@@ -465,6 +500,9 @@ int hci_register_sysfs(struct hci_dev *hdev)
|
||||
debugfs_create_file("inquiry_cache", 0444, hdev->debugfs,
|
||||
hdev, &inquiry_cache_fops);
|
||||
|
||||
debugfs_create_file("blacklist", 0444, hdev->debugfs,
|
||||
hdev, &blacklist_fops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1152,7 +1152,7 @@ error:
|
||||
return err;
|
||||
}
|
||||
|
||||
void rfcomm_cleanup_sockets(void)
|
||||
void __exit rfcomm_cleanup_sockets(void)
|
||||
{
|
||||
debugfs_remove(rfcomm_sock_debugfs);
|
||||
|
||||
|
@@ -1153,7 +1153,7 @@ static const struct tty_operations rfcomm_ops = {
|
||||
.tiocmset = rfcomm_tty_tiocmset,
|
||||
};
|
||||
|
||||
int rfcomm_init_ttys(void)
|
||||
int __init rfcomm_init_ttys(void)
|
||||
{
|
||||
rfcomm_tty_driver = alloc_tty_driver(RFCOMM_TTY_PORTS);
|
||||
if (!rfcomm_tty_driver)
|
||||
@@ -1183,7 +1183,7 @@ int rfcomm_init_ttys(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rfcomm_cleanup_ttys(void)
|
||||
void __exit rfcomm_cleanup_ttys(void)
|
||||
{
|
||||
tty_unregister_driver(rfcomm_tty_driver);
|
||||
put_tty_driver(rfcomm_tty_driver);
|
||||
|
@@ -158,7 +158,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
|
||||
if (mac_addr) {
|
||||
sta = sta_info_get_bss(sdata, mac_addr);
|
||||
if (!sta) {
|
||||
ieee80211_key_free(key);
|
||||
ieee80211_key_free(sdata->local, key);
|
||||
err = -ENOENT;
|
||||
goto out_unlock;
|
||||
}
|
||||
@@ -192,7 +192,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
|
||||
goto out_unlock;
|
||||
|
||||
if (sta->key) {
|
||||
ieee80211_key_free(sta->key);
|
||||
ieee80211_key_free(sdata->local, sta->key);
|
||||
WARN_ON(sta->key);
|
||||
ret = 0;
|
||||
}
|
||||
@@ -205,7 +205,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
ieee80211_key_free(sdata->keys[key_idx]);
|
||||
ieee80211_key_free(sdata->local, sdata->keys[key_idx]);
|
||||
WARN_ON(sdata->keys[key_idx]);
|
||||
|
||||
ret = 0;
|
||||
@@ -324,15 +324,10 @@ static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy,
|
||||
struct net_device *dev,
|
||||
u8 key_idx)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
ieee80211_set_default_mgmt_key(sdata, key_idx);
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -238,6 +238,7 @@ enum ieee80211_work_type {
|
||||
IEEE80211_WORK_ABORT,
|
||||
IEEE80211_WORK_DIRECT_PROBE,
|
||||
IEEE80211_WORK_AUTH,
|
||||
IEEE80211_WORK_ASSOC_BEACON_WAIT,
|
||||
IEEE80211_WORK_ASSOC,
|
||||
IEEE80211_WORK_REMAIN_ON_CHANNEL,
|
||||
};
|
||||
|
@@ -323,13 +323,15 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key)
|
||||
if (!key)
|
||||
return;
|
||||
|
||||
ieee80211_key_disable_hw_accel(key);
|
||||
if (key->local)
|
||||
ieee80211_key_disable_hw_accel(key);
|
||||
|
||||
if (key->conf.alg == ALG_CCMP)
|
||||
ieee80211_aes_key_free(key->u.ccmp.tfm);
|
||||
if (key->conf.alg == ALG_AES_CMAC)
|
||||
ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm);
|
||||
ieee80211_debugfs_key_remove(key);
|
||||
if (key->local)
|
||||
ieee80211_debugfs_key_remove(key);
|
||||
|
||||
kfree(key);
|
||||
}
|
||||
@@ -410,15 +412,12 @@ static void __ieee80211_key_free(struct ieee80211_key *key)
|
||||
__ieee80211_key_destroy(key);
|
||||
}
|
||||
|
||||
void ieee80211_key_free(struct ieee80211_key *key)
|
||||
void ieee80211_key_free(struct ieee80211_local *local,
|
||||
struct ieee80211_key *key)
|
||||
{
|
||||
struct ieee80211_local *local;
|
||||
|
||||
if (!key)
|
||||
return;
|
||||
|
||||
local = key->sdata->local;
|
||||
|
||||
mutex_lock(&local->key_mtx);
|
||||
__ieee80211_key_free(key);
|
||||
mutex_unlock(&local->key_mtx);
|
||||
|
@@ -135,7 +135,8 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
|
||||
void ieee80211_key_link(struct ieee80211_key *key,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
struct sta_info *sta);
|
||||
void ieee80211_key_free(struct ieee80211_key *key);
|
||||
void ieee80211_key_free(struct ieee80211_local *local,
|
||||
struct ieee80211_key *key);
|
||||
void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx);
|
||||
void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
|
||||
int idx);
|
||||
|
@@ -107,12 +107,15 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
|
||||
if (scan_chan) {
|
||||
chan = scan_chan;
|
||||
channel_type = NL80211_CHAN_NO_HT;
|
||||
local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
|
||||
} else if (local->tmp_channel) {
|
||||
chan = scan_chan = local->tmp_channel;
|
||||
channel_type = local->tmp_channel_type;
|
||||
local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
|
||||
} else {
|
||||
chan = local->oper_channel;
|
||||
channel_type = local->_oper_channel_type;
|
||||
local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL;
|
||||
}
|
||||
|
||||
if (chan != local->hw.conf.channel ||
|
||||
|
@@ -870,6 +870,11 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
ieee80211_led_assoc(local, 1);
|
||||
|
||||
if (local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD)
|
||||
bss_conf->dtim_period = bss->dtim_period;
|
||||
else
|
||||
bss_conf->dtim_period = 0;
|
||||
|
||||
bss_conf->assoc = 1;
|
||||
/*
|
||||
* For now just always ask the driver to update the basic rateset
|
||||
@@ -1751,7 +1756,8 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
|
||||
if (wk->sdata != sdata)
|
||||
continue;
|
||||
|
||||
if (wk->type != IEEE80211_WORK_ASSOC)
|
||||
if (wk->type != IEEE80211_WORK_ASSOC &&
|
||||
wk->type != IEEE80211_WORK_ASSOC_BEACON_WAIT)
|
||||
continue;
|
||||
|
||||
if (memcmp(mgmt->bssid, wk->filter_ta, ETH_ALEN))
|
||||
@@ -2086,6 +2092,8 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_mgmt *mgmt;
|
||||
struct ieee80211_rx_status *rx_status;
|
||||
struct ieee802_11_elems elems;
|
||||
u16 status;
|
||||
|
||||
if (!skb) {
|
||||
@@ -2093,6 +2101,19 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk,
|
||||
return WORK_DONE_DESTROY;
|
||||
}
|
||||
|
||||
if (wk->type == IEEE80211_WORK_ASSOC_BEACON_WAIT) {
|
||||
mutex_lock(&wk->sdata->u.mgd.mtx);
|
||||
rx_status = (void *) skb->cb;
|
||||
ieee802_11_parse_elems(skb->data + 24 + 12, skb->len - 24 - 12, &elems);
|
||||
ieee80211_rx_bss_info(wk->sdata, (void *)skb->data, skb->len, rx_status,
|
||||
&elems, true);
|
||||
mutex_unlock(&wk->sdata->u.mgd.mtx);
|
||||
|
||||
wk->type = IEEE80211_WORK_ASSOC;
|
||||
/* not really done yet */
|
||||
return WORK_DONE_REQUEUE;
|
||||
}
|
||||
|
||||
mgmt = (void *)skb->data;
|
||||
status = le16_to_cpu(mgmt->u.assoc_resp.status_code);
|
||||
|
||||
@@ -2206,10 +2227,14 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
|
||||
if (req->prev_bssid)
|
||||
memcpy(wk->assoc.prev_bssid, req->prev_bssid, ETH_ALEN);
|
||||
|
||||
wk->type = IEEE80211_WORK_ASSOC;
|
||||
wk->chan = req->bss->channel;
|
||||
wk->sdata = sdata;
|
||||
wk->done = ieee80211_assoc_done;
|
||||
if (!bss->dtim_period &&
|
||||
sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD)
|
||||
wk->type = IEEE80211_WORK_ASSOC_BEACON_WAIT;
|
||||
else
|
||||
wk->type = IEEE80211_WORK_ASSOC;
|
||||
|
||||
if (req->use_mfp) {
|
||||
ifmgd->mfp = IEEE80211_MFP_REQUIRED;
|
||||
@@ -2257,7 +2282,8 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
if (wk->type != IEEE80211_WORK_DIRECT_PROBE &&
|
||||
wk->type != IEEE80211_WORK_AUTH &&
|
||||
wk->type != IEEE80211_WORK_ASSOC)
|
||||
wk->type != IEEE80211_WORK_ASSOC &&
|
||||
wk->type != IEEE80211_WORK_ASSOC_BEACON_WAIT)
|
||||
continue;
|
||||
|
||||
if (memcmp(req->bss->bssid, wk->filter_ta, ETH_ALEN))
|
||||
|
@@ -67,7 +67,6 @@ rix_to_ndx(struct minstrel_sta_info *mi, int rix)
|
||||
for (i = rix; i >= 0; i--)
|
||||
if (mi->r[i].rix == rix)
|
||||
break;
|
||||
WARN_ON(i < 0);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
@@ -636,7 +636,7 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
|
||||
int i;
|
||||
|
||||
/* fall back to the old minstrel for legacy stations */
|
||||
if (sta && !sta->ht_cap.ht_supported) {
|
||||
if (!sta->ht_cap.ht_supported) {
|
||||
msp->is_ht = false;
|
||||
memset(&msp->legacy, 0, sizeof(msp->legacy));
|
||||
msp->legacy.r = msp->ratelist;
|
||||
@@ -748,7 +748,7 @@ minstrel_ht_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
|
||||
return msp;
|
||||
|
||||
error1:
|
||||
kfree(msp->sample_table);
|
||||
kfree(msp->ratelist);
|
||||
error:
|
||||
kfree(msp);
|
||||
return NULL;
|
||||
|
@@ -114,6 +114,10 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
|
||||
bss->dtim_period = tim_ie->dtim_period;
|
||||
}
|
||||
|
||||
/* If the beacon had no TIM IE, or it was invalid, use 1 */
|
||||
if (beacon && !bss->dtim_period)
|
||||
bss->dtim_period = 1;
|
||||
|
||||
/* replace old supported rates if we get new values */
|
||||
srlen = 0;
|
||||
if (elems->supp_rates) {
|
||||
@@ -286,8 +290,6 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
|
||||
local->scanning = 0;
|
||||
local->scan_channel = NULL;
|
||||
|
||||
drv_sw_scan_complete(local);
|
||||
|
||||
/* we only have to protect scan_req and hw/sw scan */
|
||||
mutex_unlock(&local->scan_mtx);
|
||||
|
||||
@@ -297,6 +299,8 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
|
||||
|
||||
ieee80211_configure_filter(local);
|
||||
|
||||
drv_sw_scan_complete(local);
|
||||
|
||||
ieee80211_offchannel_return(local, true);
|
||||
|
||||
done:
|
||||
|
@@ -647,7 +647,7 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
|
||||
return ret;
|
||||
|
||||
if (sta->key) {
|
||||
ieee80211_key_free(sta->key);
|
||||
ieee80211_key_free(local, sta->key);
|
||||
WARN_ON(sta->key);
|
||||
}
|
||||
|
||||
|
@@ -575,17 +575,6 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
|
||||
return TX_CONTINUE;
|
||||
}
|
||||
|
||||
static ieee80211_tx_result debug_noinline
|
||||
ieee80211_tx_h_sta(struct ieee80211_tx_data *tx)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
|
||||
|
||||
if (tx->sta && tx->sta->uploaded)
|
||||
info->control.sta = &tx->sta->sta;
|
||||
|
||||
return TX_CONTINUE;
|
||||
}
|
||||
|
||||
static ieee80211_tx_result debug_noinline
|
||||
ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
|
||||
{
|
||||
@@ -1307,6 +1296,11 @@ static int __ieee80211_tx(struct ieee80211_local *local,
|
||||
break;
|
||||
}
|
||||
|
||||
if (sta && sta->uploaded)
|
||||
info->control.sta = &sta->sta;
|
||||
else
|
||||
info->control.sta = NULL;
|
||||
|
||||
ret = drv_tx(local, skb);
|
||||
if (WARN_ON(ret != NETDEV_TX_OK && skb->len != len)) {
|
||||
dev_kfree_skb(skb);
|
||||
@@ -1346,7 +1340,6 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
|
||||
CALL_TXH(ieee80211_tx_h_check_assoc);
|
||||
CALL_TXH(ieee80211_tx_h_ps_buf);
|
||||
CALL_TXH(ieee80211_tx_h_select_key);
|
||||
CALL_TXH(ieee80211_tx_h_sta);
|
||||
if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL))
|
||||
CALL_TXH(ieee80211_tx_h_rate_ctrl);
|
||||
|
||||
@@ -1942,11 +1935,13 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
|
||||
h_pos += encaps_len;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MAC80211_MESH
|
||||
if (meshhdrlen > 0) {
|
||||
memcpy(skb_push(skb, meshhdrlen), &mesh_hdr, meshhdrlen);
|
||||
nh_pos += meshhdrlen;
|
||||
h_pos += meshhdrlen;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ieee80211_is_data_qos(fc)) {
|
||||
__le16 *qos_control;
|
||||
|
@@ -803,8 +803,12 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata)
|
||||
|
||||
/* after reinitialize QoS TX queues setting to default,
|
||||
* disable QoS at all */
|
||||
sdata->vif.bss_conf.qos = sdata->vif.type != NL80211_IFTYPE_STATION;
|
||||
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_QOS);
|
||||
|
||||
if (sdata->vif.type != NL80211_IFTYPE_MONITOR) {
|
||||
sdata->vif.bss_conf.qos =
|
||||
sdata->vif.type != NL80211_IFTYPE_STATION;
|
||||
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_QOS);
|
||||
}
|
||||
}
|
||||
|
||||
void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata,
|
||||
|
@@ -560,6 +560,22 @@ ieee80211_remain_on_channel_timeout(struct ieee80211_work *wk)
|
||||
return WORK_ACT_TIMEOUT;
|
||||
}
|
||||
|
||||
static enum work_action __must_check
|
||||
ieee80211_assoc_beacon_wait(struct ieee80211_work *wk)
|
||||
{
|
||||
if (wk->started)
|
||||
return WORK_ACT_TIMEOUT;
|
||||
|
||||
/*
|
||||
* Wait up to one beacon interval ...
|
||||
* should this be more if we miss one?
|
||||
*/
|
||||
printk(KERN_DEBUG "%s: waiting for beacon from %pM\n",
|
||||
wk->sdata->name, wk->filter_ta);
|
||||
wk->timeout = TU_TO_EXP_TIME(wk->assoc.bss->beacon_interval);
|
||||
return WORK_ACT_NONE;
|
||||
}
|
||||
|
||||
static void ieee80211_auth_challenge(struct ieee80211_work *wk,
|
||||
struct ieee80211_mgmt *mgmt,
|
||||
size_t len)
|
||||
@@ -709,6 +725,25 @@ ieee80211_rx_mgmt_probe_resp(struct ieee80211_work *wk,
|
||||
return WORK_ACT_DONE;
|
||||
}
|
||||
|
||||
static enum work_action __must_check
|
||||
ieee80211_rx_mgmt_beacon(struct ieee80211_work *wk,
|
||||
struct ieee80211_mgmt *mgmt, size_t len)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = wk->sdata;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
|
||||
ASSERT_WORK_MTX(local);
|
||||
|
||||
if (wk->type != IEEE80211_WORK_ASSOC_BEACON_WAIT)
|
||||
return WORK_ACT_MISMATCH;
|
||||
|
||||
if (len < 24 + 12)
|
||||
return WORK_ACT_NONE;
|
||||
|
||||
printk(KERN_DEBUG "%s: beacon received\n", sdata->name);
|
||||
return WORK_ACT_DONE;
|
||||
}
|
||||
|
||||
static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
@@ -731,6 +766,7 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local,
|
||||
case IEEE80211_WORK_DIRECT_PROBE:
|
||||
case IEEE80211_WORK_AUTH:
|
||||
case IEEE80211_WORK_ASSOC:
|
||||
case IEEE80211_WORK_ASSOC_BEACON_WAIT:
|
||||
bssid = wk->filter_ta;
|
||||
break;
|
||||
default:
|
||||
@@ -745,6 +781,9 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local,
|
||||
continue;
|
||||
|
||||
switch (fc & IEEE80211_FCTL_STYPE) {
|
||||
case IEEE80211_STYPE_BEACON:
|
||||
rma = ieee80211_rx_mgmt_beacon(wk, mgmt, skb->len);
|
||||
break;
|
||||
case IEEE80211_STYPE_PROBE_RESP:
|
||||
rma = ieee80211_rx_mgmt_probe_resp(wk, mgmt, skb->len,
|
||||
rx_status);
|
||||
@@ -916,6 +955,9 @@ static void ieee80211_work_work(struct work_struct *work)
|
||||
case IEEE80211_WORK_REMAIN_ON_CHANNEL:
|
||||
rma = ieee80211_remain_on_channel_timeout(wk);
|
||||
break;
|
||||
case IEEE80211_WORK_ASSOC_BEACON_WAIT:
|
||||
rma = ieee80211_assoc_beacon_wait(wk);
|
||||
break;
|
||||
}
|
||||
|
||||
wk->started = started;
|
||||
@@ -1065,6 +1107,7 @@ ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata,
|
||||
case IEEE80211_STYPE_PROBE_RESP:
|
||||
case IEEE80211_STYPE_ASSOC_RESP:
|
||||
case IEEE80211_STYPE_REASSOC_RESP:
|
||||
case IEEE80211_STYPE_BEACON:
|
||||
skb_queue_tail(&local->work_skb_queue, skb);
|
||||
ieee80211_queue_work(&local->hw, &local->work_work);
|
||||
return RX_QUEUED;
|
||||
|
@@ -907,3 +907,52 @@ static void __exit cfg80211_exit(void)
|
||||
destroy_workqueue(cfg80211_wq);
|
||||
}
|
||||
module_exit(cfg80211_exit);
|
||||
|
||||
static int ___wiphy_printk(const char *level, const struct wiphy *wiphy,
|
||||
struct va_format *vaf)
|
||||
{
|
||||
if (!wiphy)
|
||||
return printk("%s(NULL wiphy *): %pV", level, vaf);
|
||||
|
||||
return printk("%s%s: %pV", level, wiphy_name(wiphy), vaf);
|
||||
}
|
||||
|
||||
int __wiphy_printk(const char *level, const struct wiphy *wiphy,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
struct va_format vaf;
|
||||
va_list args;
|
||||
int r;
|
||||
|
||||
va_start(args, fmt);
|
||||
|
||||
vaf.fmt = fmt;
|
||||
vaf.va = &args;
|
||||
|
||||
r = ___wiphy_printk(level, wiphy, &vaf);
|
||||
va_end(args);
|
||||
|
||||
return r;
|
||||
}
|
||||
EXPORT_SYMBOL(__wiphy_printk);
|
||||
|
||||
#define define_wiphy_printk_level(func, kern_level) \
|
||||
int func(const struct wiphy *wiphy, const char *fmt, ...) \
|
||||
{ \
|
||||
struct va_format vaf; \
|
||||
va_list args; \
|
||||
int r; \
|
||||
\
|
||||
va_start(args, fmt); \
|
||||
\
|
||||
vaf.fmt = fmt; \
|
||||
vaf.va = &args; \
|
||||
\
|
||||
r = ___wiphy_printk(kern_level, wiphy, &vaf); \
|
||||
va_end(args); \
|
||||
\
|
||||
return r; \
|
||||
} \
|
||||
EXPORT_SYMBOL(func);
|
||||
|
||||
define_wiphy_printk_level(wiphy_debug, KERN_DEBUG);
|
||||
|
@@ -247,8 +247,10 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
|
||||
if (!netif_running(wdev->netdev))
|
||||
return 0;
|
||||
|
||||
if (wdev->wext.keys)
|
||||
if (wdev->wext.keys) {
|
||||
wdev->wext.keys->def = wdev->wext.default_key;
|
||||
wdev->wext.keys->defmgmt = wdev->wext.default_mgmt_key;
|
||||
}
|
||||
|
||||
wdev->wext.ibss.privacy = wdev->wext.default_key != -1;
|
||||
|
||||
|
@@ -467,7 +467,6 @@ static struct lib80211_crypto_ops lib80211_crypt_ccmp = {
|
||||
.name = "CCMP",
|
||||
.init = lib80211_ccmp_init,
|
||||
.deinit = lib80211_ccmp_deinit,
|
||||
.build_iv = lib80211_ccmp_hdr,
|
||||
.encrypt_mpdu = lib80211_ccmp_encrypt,
|
||||
.decrypt_mpdu = lib80211_ccmp_decrypt,
|
||||
.encrypt_msdu = NULL,
|
||||
|
@@ -757,7 +757,6 @@ static struct lib80211_crypto_ops lib80211_crypt_tkip = {
|
||||
.name = "TKIP",
|
||||
.init = lib80211_tkip_init,
|
||||
.deinit = lib80211_tkip_deinit,
|
||||
.build_iv = lib80211_tkip_hdr,
|
||||
.encrypt_mpdu = lib80211_tkip_encrypt,
|
||||
.decrypt_mpdu = lib80211_tkip_decrypt,
|
||||
.encrypt_msdu = lib80211_michael_mic_add,
|
||||
|
@@ -269,7 +269,6 @@ static struct lib80211_crypto_ops lib80211_crypt_wep = {
|
||||
.name = "WEP",
|
||||
.init = lib80211_wep_init,
|
||||
.deinit = lib80211_wep_deinit,
|
||||
.build_iv = lib80211_wep_build_iv,
|
||||
.encrypt_mpdu = lib80211_wep_encrypt,
|
||||
.decrypt_mpdu = lib80211_wep_decrypt,
|
||||
.encrypt_msdu = NULL,
|
||||
|
@@ -2769,6 +2769,7 @@ static int nl80211_get_mesh_params(struct sk_buff *skb,
|
||||
|
||||
nla_put_failure:
|
||||
genlmsg_cancel(msg, hdr);
|
||||
nlmsg_free(msg);
|
||||
err = -EMSGSIZE;
|
||||
out:
|
||||
/* Cleanup */
|
||||
@@ -2960,6 +2961,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
|
||||
|
||||
nla_put_failure:
|
||||
genlmsg_cancel(msg, hdr);
|
||||
nlmsg_free(msg);
|
||||
err = -EMSGSIZE;
|
||||
out:
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
|
@@ -1306,6 +1306,7 @@ static void reg_process_hint(struct regulatory_request *reg_request)
|
||||
{
|
||||
int r = 0;
|
||||
struct wiphy *wiphy = NULL;
|
||||
enum nl80211_reg_initiator initiator = reg_request->initiator;
|
||||
|
||||
BUG_ON(!reg_request->alpha2);
|
||||
|
||||
@@ -1325,7 +1326,7 @@ static void reg_process_hint(struct regulatory_request *reg_request)
|
||||
/* This is required so that the orig_* parameters are saved */
|
||||
if (r == -EALREADY && wiphy &&
|
||||
wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY)
|
||||
wiphy_update_regulatory(wiphy, reg_request->initiator);
|
||||
wiphy_update_regulatory(wiphy, initiator);
|
||||
out:
|
||||
mutex_unlock(®_mutex);
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
@@ -1492,7 +1493,6 @@ void regulatory_hint_11d(struct wiphy *wiphy,
|
||||
u8 *country_ie,
|
||||
u8 country_ie_len)
|
||||
{
|
||||
struct ieee80211_regdomain *rd = NULL;
|
||||
char alpha2[2];
|
||||
enum environment_cap env = ENVIRON_ANY;
|
||||
struct regulatory_request *request;
|
||||
@@ -1529,7 +1529,7 @@ void regulatory_hint_11d(struct wiphy *wiphy,
|
||||
|
||||
request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL);
|
||||
if (!request)
|
||||
goto free_rd_out;
|
||||
goto out;
|
||||
|
||||
request->wiphy_idx = get_wiphy_idx(wiphy);
|
||||
request->alpha2[0] = alpha2[0];
|
||||
@@ -1543,8 +1543,6 @@ void regulatory_hint_11d(struct wiphy *wiphy,
|
||||
|
||||
return;
|
||||
|
||||
free_rd_out:
|
||||
kfree(rd);
|
||||
out:
|
||||
mutex_unlock(®_mutex);
|
||||
}
|
||||
|
Reference in New Issue
Block a user