*
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/spinlock.h>
#include <linux/rcupdate.h>
#include <linux/bitops.h>
-#include <linux/mutex.h>
#include <asm/uaccess.h>
#include <asm/system.h>
static const struct proto_ops econet_ops;
static struct hlist_head econet_sklist;
static DEFINE_RWLOCK(econet_lock);
-static DEFINE_MUTEX(econet_mutex);
/* Since there are only 256 possible network numbers (or fewer, depends
how you count) it makes sense to use a simple lookup table. */
msg->msg_namelen = sizeof(struct sockaddr_ec);
- mutex_lock(&econet_mutex);
-
/*
* Call the generic datagram receiver. This handles all sorts
* of horrible races and re-entrancy so we can forget about it
out_free:
skb_free_datagram(sk, skb);
out:
- mutex_unlock(&econet_mutex);
return err;
}
static int econet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
{
struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr;
- struct sock *sk;
- struct econet_sock *eo;
+ struct sock *sk=sock->sk;
+ struct econet_sock *eo = ec_sk(sk);
/*
* Check legality
sec->sec_family != AF_ECONET)
return -EINVAL;
- mutex_lock(&econet_mutex);
-
- sk = sock->sk;
- eo = ec_sk(sk);
-
eo->cb = sec->cb;
eo->port = sec->port;
eo->station = sec->addr.station;
eo->net = sec->addr.net;
- mutex_unlock(&econet_mutex);
-
return 0;
}
* Get and verify the address.
*/
- mutex_lock(&econet_mutex);
-
if (saddr == NULL) {
struct econet_sock *eo = ec_sk(sk);
port = eo->port;
cb = eo->cb;
} else {
- if (msg->msg_namelen < sizeof(struct sockaddr_ec)) {
- mutex_unlock(&econet_mutex);
+ if (msg->msg_namelen < sizeof(struct sockaddr_ec))
return -EINVAL;
- }
addr.station = saddr->addr.station;
addr.net = saddr->addr.net;
port = saddr->port;
dev = net2dev_map[addr.net];
/* If not directly reachable, use some default */
- if (dev == NULL) {
+ if (dev == NULL)
+ {
dev = net2dev_map[0];
/* No interfaces at all? */
- if (dev == NULL) {
- mutex_unlock(&econet_mutex);
+ if (dev == NULL)
return -ENETDOWN;
- }
}
- if (len + 15 > dev->mtu) {
- mutex_unlock(&econet_mutex);
+ if (len + 15 > dev->mtu)
return -EMSGSIZE;
- }
- if (dev->type == ARPHRD_ECONET) {
+ if (dev->type == ARPHRD_ECONET)
+ {
/* Real hardware Econet. We're not worthy etc. */
#ifdef CONFIG_ECONET_NATIVE
unsigned short proto = 0;
dev_queue_xmit(skb);
dev_put(dev);
- mutex_unlock(&econet_mutex);
return(len);
out_free:
#else
err = -EPROTOTYPE;
#endif
- mutex_unlock(&econet_mutex);
-
return err;
}
#ifdef CONFIG_ECONET_AUNUDP
/* AUN virtual Econet. */
- if (udpsock == NULL) {
- mutex_unlock(&econet_mutex);
+ if (udpsock == NULL)
return -ENETDOWN; /* No socket - can't send */
- }
/* Make up a UDP datagram and hand it off to some higher intellect. */
void __user *base = msg->msg_iov[i].iov_base;
size_t len = msg->msg_iov[i].iov_len;
/* Check it now since we switch to KERNEL_DS later. */
- if (!access_ok(VERIFY_READ, base, len)) {
- mutex_unlock(&econet_mutex);
+ if (!access_ok(VERIFY_READ, base, len))
return -EFAULT;
- }
iov[i+1].iov_base = base;
iov[i+1].iov_len = len;
size += len;
/* Get a skbuff (no data, just holds our cb information) */
if ((skb = sock_alloc_send_skb(sk, 0,
- msg->msg_flags & MSG_DONTWAIT,
- &err)) == NULL) {
- mutex_unlock(&econet_mutex);
+ msg->msg_flags & MSG_DONTWAIT, &err)) == NULL)
return err;
- }
eb = (struct ec_cb *)&skb->cb;
#else
err = -EPROTOTYPE;
#endif
- mutex_unlock(&econet_mutex);
-
return err;
}
static int econet_getname(struct socket *sock, struct sockaddr *uaddr,
int *uaddr_len, int peer)
{
- struct sock *sk;
- struct econet_sock *eo;
+ struct sock *sk = sock->sk;
+ struct econet_sock *eo = ec_sk(sk);
struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr;
if (peer)
return -EOPNOTSUPP;
- mutex_lock(&econet_mutex);
-
- sk = sock->sk;
- eo = ec_sk(sk);
-
sec->sec_family = AF_ECONET;
sec->port = eo->port;
sec->addr.station = eo->station;
sec->addr.net = eo->net;
- mutex_unlock(&econet_mutex);
-
*uaddr_len = sizeof(*sec);
return 0;
}
static int econet_release(struct socket *sock)
{
- struct sock *sk;
-
- mutex_lock(&econet_mutex);
+ struct sock *sk = sock->sk;
- sk = sock->sk;
if (!sk)
- goto out_unlock;
+ return 0;
econet_remove_socket(&econet_sklist, sk);
sk->sk_timer.expires = jiffies + HZ;
sk->sk_timer.function = econet_destroy_timer;
add_timer(&sk->sk_timer);
-
- goto out_unlock;
+ return 0;
}
sk_free(sk);
-
-out_unlock:
- mutex_unlock(&econet_mutex);
return 0;
}
struct ec_device *edev;
struct net_device *dev;
struct sockaddr_ec *sec;
- int err;
/*
* Fetch the caller's info block into kernel space
sec = (struct sockaddr_ec *)&ifr.ifr_addr;
- mutex_lock(&econet_mutex);
-
- err = 0;
- switch (cmd) {
+ switch (cmd)
+ {
case SIOCSIFADDR:
edev = dev->ec_ptr;
- if (edev == NULL) {
+ if (edev == NULL)
+ {
/* Magic up a new one. */
- edev = kzalloc(sizeof(struct ec_device), GFP_KERNEL);
+ edev = kmalloc(sizeof(struct ec_device), GFP_KERNEL);
if (edev == NULL) {
- err = -ENOMEM;
- break;
+ printk("af_ec: memory squeeze.\n");
+ dev_put(dev);
+ return -ENOMEM;
}
+ memset(edev, 0, sizeof(struct ec_device));
dev->ec_ptr = edev;
- } else
+ }
+ else
net2dev_map[edev->net] = NULL;
edev->station = sec->addr.station;
edev->net = sec->addr.net;
net2dev_map[sec->addr.net] = dev;
if (!net2dev_map[0])
net2dev_map[0] = dev;
- break;
+ dev_put(dev);
+ return 0;
case SIOCGIFADDR:
edev = dev->ec_ptr;
- if (edev == NULL) {
- err = -ENODEV;
- break;
+ if (edev == NULL)
+ {
+ dev_put(dev);
+ return -ENODEV;
}
memset(sec, 0, sizeof(struct sockaddr_ec));
sec->addr.station = edev->station;
sec->sec_family = AF_ECONET;
dev_put(dev);
if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))
- err = -EFAULT;
- break;
-
- default:
- err = -EINVAL;
- break;
+ return -EFAULT;
+ return 0;
}
- mutex_unlock(&econet_mutex);
-
dev_put(dev);
-
- return err;
+ return -EINVAL;
}
/*
.owner = THIS_MODULE,
};
-static const struct proto_ops econet_ops = {
+static const struct proto_ops SOCKOPS_WRAPPED(econet_ops) = {
.family = PF_ECONET,
.owner = THIS_MODULE,
.release = econet_release,
.sendpage = sock_no_sendpage,
};
+#include <linux/smp_lock.h>
+SOCKOPS_WRAP(econet, PF_ECONET);
+
#if defined(CONFIG_ECONET_AUNUDP) || defined(CONFIG_ECONET_NATIVE)
/*
* Find the listening socket, if any, for the given data.