Commit c3dfa985 authored by Maksim Krasnyanskiy's avatar Maksim Krasnyanskiy

[Bluetooth] Convert BNEP protocol to dynamic allocation of network devices.

This will allow fixing races with rmmod and sysfs access.

Patch from Stephen Hemminger <shemminger@osdl.org>
parent 6e21ae5b
......@@ -168,11 +168,11 @@ struct bnep_session {
u64 mc_filter;
struct socket *sock;
struct net_device dev;
struct net_device *dev;
struct net_device_stats stats;
};
int bnep_net_init(struct net_device *dev);
void bnep_net_setup(struct net_device *dev);
int bnep_sock_init(void);
int bnep_sock_cleanup(void);
......
......@@ -180,7 +180,7 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len)
s->mc_filter = 0;
/* Always send broadcast */
set_bit(bnep_mc_hash(s->dev.broadcast), (ulong *) &s->mc_filter);
set_bit(bnep_mc_hash(s->dev->broadcast), (ulong *) &s->mc_filter);
/* Add address ranges to the multicast hash */
for (; n > 0; n--) {
......@@ -293,7 +293,7 @@ static u8 __bnep_rx_hlen[] = {
static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
{
struct net_device *dev = &s->dev;
struct net_device *dev = s->dev;
struct sk_buff *nskb;
u8 type;
......@@ -451,7 +451,7 @@ static inline int bnep_tx_frame(struct bnep_session *s, struct sk_buff *skb)
static int bnep_session(void *arg)
{
struct bnep_session *s = arg;
struct net_device *dev = &s->dev;
struct net_device *dev = s->dev;
struct sock *sk = s->sock->sk;
struct sk_buff *skb;
wait_queue_t wait;
......@@ -501,7 +501,7 @@ static int bnep_session(void *arg)
__bnep_unlink_session(s);
up_write(&bnep_session_sem);
kfree(s);
kfree(dev);
return 0;
}
......@@ -517,10 +517,13 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
baswap((void *) dst, &bt_sk(sock->sk)->dst);
baswap((void *) src, &bt_sk(sock->sk)->src);
s = kmalloc(sizeof(struct bnep_session), GFP_KERNEL);
if (!s)
return -ENOMEM;
memset(s, 0, sizeof(struct bnep_session));
/* session struct allocated as private part of net_device */
dev = alloc_netdev(sizeof(struct bnep_session),
(*req->device) ? req->device : "bnep%d",
bnep_net_setup);
if (!dev)
return ENOMEM;
down_write(&bnep_session_sem);
......@@ -530,20 +533,15 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
goto failed;
}
dev = &s->dev;
if (*req->device)
strcpy(dev->name, req->device);
else
strcpy(dev->name, "bnep%d");
s = dev->priv;
memset(dev->broadcast, 0xff, ETH_ALEN);
/* This is rx header therefore addresses are swapped.
* ie eh.h_dest is our local address. */
memcpy(s->eh.h_dest, &src, ETH_ALEN);
memcpy(s->eh.h_source, &dst, ETH_ALEN);
memcpy(dev->dev_addr, s->eh.h_dest, ETH_ALEN);
s->dev = dev;
s->sock = sock;
s->role = req->role;
s->state = BT_CONNECTED;
......@@ -569,8 +567,6 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
s->proto_filter[2].end = htons(0x86DD);
#endif
dev->init = bnep_net_init;
dev->priv = s;
err = register_netdev(dev);
if (err) {
goto failed;
......@@ -592,7 +588,7 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
failed:
up_write(&bnep_session_sem);
kfree(s);
kfree(dev);
return err;
}
......@@ -624,7 +620,7 @@ int bnep_del_connection(struct bnep_conndel_req *req)
static void __bnep_copy_ci(struct bnep_conninfo *ci, struct bnep_session *s)
{
memcpy(ci->dst, s->eh.h_source, ETH_ALEN);
strcpy(ci->device, s->dev.name);
strcpy(ci->device, s->dev->name);
ci->flags = s->flags;
ci->state = s->state;
ci->role = s->role;
......
......@@ -226,11 +226,10 @@ static int bnep_net_xmit(struct sk_buff *skb, struct net_device *dev)
return 0;
}
int bnep_net_init(struct net_device *dev)
void bnep_net_setup(struct net_device *dev)
{
struct bnep_session *s = dev->priv;
memcpy(dev->dev_addr, s->eh.h_dest, ETH_ALEN);
memset(dev->broadcast, 0xff, ETH_ALEN);
dev->addr_len = ETH_ALEN;
ether_setup(dev);
......@@ -245,6 +244,4 @@ int bnep_net_init(struct net_device *dev)
dev->watchdog_timeo = HZ * 2;
dev->tx_timeout = bnep_net_timeout;
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment