Commit 5206a79d authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6: (25 commits)
  [Bluetooth] Use work queue to trigger URB submission
  [Bluetooth] Add locking for bt_proto array manipulation
  [Bluetooth] Check if DLC is still attached to the TTY
  [Bluetooth] Fix reference count when connection lookup fails
  [Bluetooth] Disconnect HID interrupt channel first
  [Bluetooth] Support concurrent connect requests
  [Bluetooth] Make use of virtual devices tree
  [Bluetooth] Handle return values from driver core functions
  [Bluetooth] Fix compat ioctl for BNEP, CMTP and HIDP
  [IPV6] sit: Add missing MODULE_LICENSE
  [IPV6]: Remove bogus WARN_ON in Proxy-NA handling.
  [IPv6] rules: Use RT6_LOOKUP_F_HAS_SADDR and fix source based selectors
  [XFRM]: Fix xfrm_state_num going negative.
  [NET]: reduce sizeof(struct inet_peer), cleanup, change in peer_check_expire()
  NetLabel: the CIPSOv4 passthrough mapping does not pass categories correctly
  NetLabel: better error handling involving mls_export_cat()
  NetLabel: only deref the CIPSOv4 standard map fields when using standard mapping
  [BRIDGE]: flush forwarding table when device carrier off
  [NETFILTER]: ctnetlink: Remove debugging messages
  [NETFILTER]: Update MAINTAINERS entry
  ...
parents 29da7eb0 3f530692
......@@ -2049,11 +2049,13 @@ P: Marc Boucher
P: James Morris
P: Harald Welte
P: Jozsef Kadlecsik
M: coreteam@netfilter.org
P: Patrick McHardy
M: kaber@trash.net
L: netfilter-devel@lists.netfilter.org
L: netfilter@lists.netfilter.org
L: coreteam@netfilter.org
W: http://www.netfilter.org/
W: http://www.iptables.org/
L: netfilter@lists.netfilter.org
L: netfilter-devel@lists.netfilter.org
S: Supported
NETLABEL
......
......@@ -29,7 +29,6 @@
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/timer.h>
#include <linux/device.h>
#include <linux/firmware.h>
......@@ -43,7 +42,7 @@
#define BT_DBG(D...)
#endif
#define VERSION "1.0"
#define VERSION "1.1"
static int ignore = 0;
......@@ -72,7 +71,7 @@ struct bcm203x_data {
unsigned long state;
struct timer_list timer;
struct work_struct work;
struct urb *urb;
unsigned char *buffer;
......@@ -105,7 +104,7 @@ static void bcm203x_complete(struct urb *urb)
data->state = BCM203X_SELECT_MEMORY;
mod_timer(&data->timer, jiffies + (HZ / 10));
schedule_work(&data->work);
break;
case BCM203X_SELECT_MEMORY:
......@@ -158,9 +157,9 @@ static void bcm203x_complete(struct urb *urb)
}
}
static void bcm203x_timer(unsigned long user_data)
static void bcm203x_work(void *user_data)
{
struct bcm203x_data *data = (struct bcm203x_data *) user_data;
struct bcm203x_data *data = user_data;
if (usb_submit_urb(data->urb, GFP_ATOMIC) < 0)
BT_ERR("Can't submit URB");
......@@ -247,13 +246,11 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
release_firmware(firmware);
init_timer(&data->timer);
data->timer.function = bcm203x_timer;
data->timer.data = (unsigned long) data;
INIT_WORK(&data->work, bcm203x_work, (void *) data);
usb_set_intfdata(intf, data);
mod_timer(&data->timer, jiffies + HZ);
schedule_work(&data->work);
return 0;
}
......
......@@ -153,6 +153,7 @@ struct hci_conn {
__u8 mode;
__u8 type;
__u8 out;
__u8 attempt;
__u8 dev_class[3];
__u8 features[8];
__u16 interval;
......@@ -289,6 +290,22 @@ static inline struct hci_conn *hci_conn_hash_lookup_ba(struct hci_dev *hdev,
return NULL;
}
static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev,
__u8 type, __u16 state)
{
struct hci_conn_hash *h = &hdev->conn_hash;
struct list_head *p;
struct hci_conn *c;
list_for_each(p, &h->list) {
c = list_entry(p, struct hci_conn, list);
if (c->type == type && c->state == state)
return c;
}
return NULL;
}
void hci_acl_connect(struct hci_conn *conn);
void hci_acl_disconn(struct hci_conn *conn, __u8 reason);
void hci_add_sco(struct hci_conn *conn, __u16 handle);
......
......@@ -19,7 +19,7 @@ struct inet_peer
{
struct inet_peer *avl_left, *avl_right;
struct inet_peer *unused_next, **unused_prevp;
unsigned long dtime; /* the time of last use of not
__u32 dtime; /* the time of last use of not
* referenced entries */
atomic_t refcnt;
__be32 v4daddr; /* peer's address */
......@@ -35,21 +35,8 @@ void inet_initpeers(void) __init;
/* can be called with or without local BH being disabled */
struct inet_peer *inet_getpeer(__be32 daddr, int create);
extern spinlock_t inet_peer_unused_lock;
extern struct inet_peer **inet_peer_unused_tailp;
/* can be called from BH context or outside */
static inline void inet_putpeer(struct inet_peer *p)
{
spin_lock_bh(&inet_peer_unused_lock);
if (atomic_dec_and_test(&p->refcnt)) {
p->unused_prevp = inet_peer_unused_tailp;
p->unused_next = NULL;
*inet_peer_unused_tailp = p;
inet_peer_unused_tailp = &p->unused_next;
p->dtime = jiffies;
}
spin_unlock_bh(&inet_peer_unused_lock);
}
extern void inet_putpeer(struct inet_peer *p);
extern spinlock_t inet_peer_idlock;
/* can be called with or without local BH being disabled */
......
......@@ -48,41 +48,56 @@
#define BT_DBG(D...)
#endif
#define VERSION "2.10"
#define VERSION "2.11"
/* Bluetooth sockets */
#define BT_MAX_PROTO 8
static struct net_proto_family *bt_proto[BT_MAX_PROTO];
static DEFINE_RWLOCK(bt_proto_lock);
int bt_sock_register(int proto, struct net_proto_family *ops)
{
int err = 0;
if (proto < 0 || proto >= BT_MAX_PROTO)
return -EINVAL;
write_lock(&bt_proto_lock);
if (bt_proto[proto])
return -EEXIST;
err = -EEXIST;
else
bt_proto[proto] = ops;
bt_proto[proto] = ops;
return 0;
write_unlock(&bt_proto_lock);
return err;
}
EXPORT_SYMBOL(bt_sock_register);
int bt_sock_unregister(int proto)
{
int err = 0;
if (proto < 0 || proto >= BT_MAX_PROTO)
return -EINVAL;
write_lock(&bt_proto_lock);
if (!bt_proto[proto])
return -ENOENT;
err = -ENOENT;
else
bt_proto[proto] = NULL;
bt_proto[proto] = NULL;
return 0;
write_unlock(&bt_proto_lock);
return err;
}
EXPORT_SYMBOL(bt_sock_unregister);
static int bt_sock_create(struct socket *sock, int proto)
{
int err = 0;
int err;
if (proto < 0 || proto >= BT_MAX_PROTO)
return -EINVAL;
......@@ -92,11 +107,18 @@ static int bt_sock_create(struct socket *sock, int proto)
request_module("bt-proto-%d", proto);
}
#endif
err = -EPROTONOSUPPORT;
read_lock(&bt_proto_lock);
if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) {
err = bt_proto[proto]->create(sock, proto);
module_put(bt_proto[proto]->owner);
}
read_unlock(&bt_proto_lock);
return err;
}
......
......@@ -528,12 +528,10 @@ static struct device *bnep_get_device(struct bnep_session *session)
return NULL;
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
if (!conn)
return NULL;
hci_dev_put(hdev);
return &conn->dev;
return conn ? &conn->dev : NULL;
}
int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
......
......@@ -43,6 +43,7 @@
#include <linux/ioctl.h>
#include <linux/file.h>
#include <linux/init.h>
#include <linux/compat.h>
#include <net/sock.h>
#include <asm/system.h>
......@@ -146,24 +147,56 @@ static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
return 0;
}
#ifdef CONFIG_COMPAT
static int bnep_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
if (cmd == BNEPGETCONNLIST) {
struct bnep_connlist_req cl;
uint32_t uci;
int err;
if (get_user(cl.cnum, (uint32_t __user *) arg) ||
get_user(uci, (u32 __user *) (arg + 4)))
return -EFAULT;
cl.ci = compat_ptr(uci);
if (cl.cnum <= 0)
return -EINVAL;
err = bnep_get_connlist(&cl);
if (!err && put_user(cl.cnum, (uint32_t __user *) arg))
err = -EFAULT;
return err;
}
return bnep_sock_ioctl(sock, cmd, arg);
}
#endif
static const struct proto_ops bnep_sock_ops = {
.family = PF_BLUETOOTH,
.owner = THIS_MODULE,
.release = bnep_sock_release,
.ioctl = bnep_sock_ioctl,
.bind = sock_no_bind,
.getname = sock_no_getname,
.sendmsg = sock_no_sendmsg,
.recvmsg = sock_no_recvmsg,
.poll = sock_no_poll,
.listen = sock_no_listen,
.shutdown = sock_no_shutdown,
.setsockopt = sock_no_setsockopt,
.getsockopt = sock_no_getsockopt,
.connect = sock_no_connect,
.socketpair = sock_no_socketpair,
.accept = sock_no_accept,
.mmap = sock_no_mmap
.family = PF_BLUETOOTH,
.owner = THIS_MODULE,
.release = bnep_sock_release,
.ioctl = bnep_sock_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = bnep_sock_compat_ioctl,
#endif
.bind = sock_no_bind,
.getname = sock_no_getname,
.sendmsg = sock_no_sendmsg,
.recvmsg = sock_no_recvmsg,
.poll = sock_no_poll,
.listen = sock_no_listen,
.shutdown = sock_no_shutdown,
.setsockopt = sock_no_setsockopt,
.getsockopt = sock_no_getsockopt,
.connect = sock_no_connect,
.socketpair = sock_no_socketpair,
.accept = sock_no_accept,
.mmap = sock_no_mmap
};
static struct proto bnep_proto = {
......@@ -181,7 +214,7 @@ static int bnep_sock_create(struct socket *sock, int protocol)
if (sock->type != SOCK_RAW)
return -ESOCKTNOSUPPORT;
sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &bnep_proto, 1);
sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &bnep_proto, 1);
if (!sk)
return -ENOMEM;
......
......@@ -34,6 +34,7 @@
#include <linux/socket.h>
#include <linux/ioctl.h>
#include <linux/file.h>
#include <linux/compat.h>
#include <net/sock.h>
#include <linux/isdn/capilli.h>
......@@ -137,11 +138,43 @@ static int cmtp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
return -EINVAL;
}
#ifdef CONFIG_COMPAT
static int cmtp_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
if (cmd == CMTPGETCONNLIST) {
struct cmtp_connlist_req cl;
uint32_t uci;
int err;
if (get_user(cl.cnum, (uint32_t __user *) arg) ||
get_user(uci, (u32 __user *) (arg + 4)))
return -EFAULT;
cl.ci = compat_ptr(uci);
if (cl.cnum <= 0)
return -EINVAL;
err = cmtp_get_connlist(&cl);
if (!err && put_user(cl.cnum, (uint32_t __user *) arg))
err = -EFAULT;
return err;
}
return cmtp_sock_ioctl(sock, cmd, arg);
}
#endif
static const struct proto_ops cmtp_sock_ops = {
.family = PF_BLUETOOTH,
.owner = THIS_MODULE,
.release = cmtp_sock_release,
.ioctl = cmtp_sock_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = cmtp_sock_compat_ioctl,
#endif
.bind = sock_no_bind,
.getname = sock_no_getname,
.sendmsg = sock_no_sendmsg,
......@@ -172,7 +205,7 @@ static int cmtp_sock_create(struct socket *sock, int protocol)
if (sock->type != SOCK_RAW)
return -ESOCKTNOSUPPORT;
sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &cmtp_proto, 1);
sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &cmtp_proto, 1);
if (!sk)
return -ENOMEM;
......
......@@ -51,7 +51,7 @@
#define BT_DBG(D...)
#endif
static void hci_acl_connect(struct hci_conn *conn)
void hci_acl_connect(struct hci_conn *conn)
{
struct hci_dev *hdev = conn->hdev;
struct inquiry_entry *ie;
......@@ -63,6 +63,8 @@ static void hci_acl_connect(struct hci_conn *conn)
conn->out = 1;
conn->link_mode = HCI_LM_MASTER;
conn->attempt++;
memset(&cp, 0, sizeof(cp));
bacpy(&cp.bdaddr, &conn->dst);
cp.pscan_rep_mode = 0x02;
......@@ -80,7 +82,7 @@ static void hci_acl_connect(struct hci_conn *conn)
cp.role_switch = 0x01;
else
cp.role_switch = 0x00;
hci_send_cmd(hdev, OGF_LINK_CTL, OCF_CREATE_CONN, sizeof(cp), &cp);
}
......
......@@ -414,9 +414,12 @@ static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
if (status) {
if (conn && conn->state == BT_CONNECT) {
conn->state = BT_CLOSED;
hci_proto_connect_cfm(conn, status);
hci_conn_del(conn);
if (status != 0x0c || conn->attempt > 2) {
conn->state = BT_CLOSED;
hci_proto_connect_cfm(conn, status);
hci_conn_del(conn);
} else
conn->state = BT_CONNECT2;
}
} else {
if (!conn) {
......@@ -728,7 +731,7 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk
static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_conn_complete *ev = (struct hci_ev_conn_complete *) skb->data;
struct hci_conn *conn;
struct hci_conn *conn, *pend;
BT_DBG("%s", hdev->name);
......@@ -801,6 +804,10 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
if (ev->status)
hci_conn_del(conn);
pend = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
if (pend)
hci_acl_connect(pend);
hci_dev_unlock(hdev);
}
......
......@@ -618,7 +618,7 @@ static int hci_sock_create(struct socket *sock, int protocol)
sock->ops = &hci_sock_ops;
sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &hci_sk_proto, 1);
sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto, 1);
if (!sk)
return -ENOMEM;
......
......@@ -242,10 +242,14 @@ static void add_conn(void *data)
struct hci_conn *conn = data;
int i;
device_register(&conn->dev);
if (device_register(&conn->dev) < 0) {
BT_ERR("Failed to register connection device");
return;
}
for (i = 0; conn_attrs[i]; i++)
device_create_file(&conn->dev, conn_attrs[i]);
if (device_create_file(&conn->dev, conn_attrs[i]) < 0)
BT_ERR("Failed to create connection attribute");
}
void hci_conn_add_sysfs(struct hci_conn *conn)
......@@ -295,11 +299,7 @@ int hci_register_sysfs(struct hci_dev *hdev)
BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type);
dev->class = bt_class;
if (hdev->parent)
dev->parent = hdev->parent;
else
dev->parent = &bt_platform->dev;
dev->parent = hdev->parent;
strlcpy(dev->bus_id, hdev->name, BUS_ID_SIZE);
......@@ -312,7 +312,8 @@ int hci_register_sysfs(struct hci_dev *hdev)
return err;
for (i = 0; bt_attrs[i]; i++)
device_create_file(dev, bt_attrs[i]);
if (device_create_file(dev, bt_attrs[i]) < 0)
BT_ERR("Failed to create device attribute");
return 0;
}
......
......@@ -510,11 +510,11 @@ static int hidp_session(void *arg)
if (intr_sk->sk_state != BT_CONNECTED)
wait_event_timeout(*(ctrl_sk->sk_sleep), (ctrl_sk->sk_state == BT_CLOSED), HZ);
fput(session->ctrl_sock->file);
fput(session->intr_sock->file);
wait_event_timeout(*(intr_sk->sk_sleep), (intr_sk->sk_state == BT_CLOSED), HZ);
fput(session->intr_sock->file);
fput(session->ctrl_sock->file);
__hidp_unlink_session(session);
......@@ -541,12 +541,10 @@ static struct device *hidp_get_device(struct hidp_session *session)
return NULL;
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
if (!conn)
return NULL;
hci_dev_put(hdev);
return &conn->dev;
return conn ? &conn->dev : NULL;
}
static inline void hidp_setup_input(struct hidp_session *session, struct hidp_connadd_req *req)
......
......@@ -35,6 +35,7 @@
#include <linux/ioctl.h>
#include <linux/file.h>
#include <linux/init.h>
#include <linux/compat.h>
#include <net/sock.h>
#include "hidp.h"
......@@ -143,11 +144,88 @@ static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
return -EINVAL;
}
#ifdef CONFIG_COMPAT
struct compat_hidp_connadd_req {
int ctrl_sock; // Connected control socket
int intr_sock; // Connteted interrupt socket
__u16 parser;
__u16 rd_size;
compat_uptr_t rd_data;
__u8 country;
__u8 subclass;
__u16 vendor;
__u16 product;
__u16 version;
__u32 flags;
__u32 idle_to;
char name[128];
};
static int hidp_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
if (cmd == HIDPGETCONNLIST) {
struct hidp_connlist_req cl;
uint32_t uci;
int err;
if (get_user(cl.cnum, (uint32_t __user *) arg) ||
get_user(uci, (u32 __user *) (arg + 4)))
return -EFAULT;
cl.ci = compat_ptr(uci);
if (cl.cnum <= 0)
return -EINVAL;
err = hidp_get_connlist(&cl);
if (!err && put_user(cl.cnum, (uint32_t __user *) arg))
err = -EFAULT;
return err;
} else if (cmd == HIDPCONNADD) {
struct compat_hidp_connadd_req ca;
struct hidp_connadd_req __user *uca;
uca = compat_alloc_user_space(sizeof(*uca));
if (copy_from_user(&ca, (void *) arg, sizeof(ca)))
return -EFAULT;
if (put_user(ca.ctrl_sock, &uca->ctrl_sock) ||
put_user(ca.intr_sock, &uca->intr_sock) ||
put_user(ca.parser, &uca->parser) ||
put_user(ca.rd_size, &uca->parser) ||
put_user(compat_ptr(ca.rd_data), &uca->rd_data) ||
put_user(ca.country, &uca->country) ||
put_user(ca.subclass, &uca->subclass) ||
put_user(ca.vendor, &uca->vendor) ||
put_user(ca.product, &uca->product) ||
put_user(ca.version, &uca->version) ||
put_user(ca.flags, &uca->flags) ||
put_user(ca.idle_to, &uca->idle_to) ||
copy_to_user(&uca->name[0], &ca.name[0], 128))
return -EFAULT;
arg = (unsigned long) uca;
/* Fall through. We don't actually write back any _changes_
to the structure anyway, so there's no need to copy back
into the original compat version */
}
return hidp_sock_ioctl(sock, cmd, arg);