diff options
author | Yunhong Jiang <yunhong.jiang@intel.com> | 2015-08-04 12:17:53 -0700 |
---|---|---|
committer | Yunhong Jiang <yunhong.jiang@intel.com> | 2015-08-04 15:44:42 -0700 |
commit | 9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 (patch) | |
tree | 1c9cafbcd35f783a87880a10f85d1a060db1a563 /kernel/net/atm/addr.c | |
parent | 98260f3884f4a202f9ca5eabed40b1354c489b29 (diff) |
Add the rt linux 4.1.3-rt3 as base
Import the rt linux 4.1.3-rt3 as OPNFV kvm base.
It's from git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-rt-devel.git linux-4.1.y-rt and
the base is:
commit 0917f823c59692d751951bf5ea699a2d1e2f26a2
Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Date: Sat Jul 25 12:13:34 2015 +0200
Prepare v4.1.3-rt3
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
We lose all the git history this way and it's not good. We
should apply another opnfv project repo in future.
Change-Id: I87543d81c9df70d99c5001fbdf646b202c19f423
Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com>
Diffstat (limited to 'kernel/net/atm/addr.c')
-rw-r--r-- | kernel/net/atm/addr.c | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/kernel/net/atm/addr.c b/kernel/net/atm/addr.c new file mode 100644 index 000000000..dcda35c66 --- /dev/null +++ b/kernel/net/atm/addr.c @@ -0,0 +1,161 @@ +/* net/atm/addr.c - Local ATM address registry */ + +/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ + +#include <linux/atm.h> +#include <linux/atmdev.h> +#include <linux/slab.h> +#include <linux/uaccess.h> + +#include "signaling.h" +#include "addr.h" + +static int check_addr(const struct sockaddr_atmsvc *addr) +{ + int i; + + if (addr->sas_family != AF_ATMSVC) + return -EAFNOSUPPORT; + if (!*addr->sas_addr.pub) + return *addr->sas_addr.prv ? 0 : -EINVAL; + for (i = 1; i < ATM_E164_LEN + 1; i++) /* make sure it's \0-terminated */ + if (!addr->sas_addr.pub[i]) + return 0; + return -EINVAL; +} + +static int identical(const struct sockaddr_atmsvc *a, const struct sockaddr_atmsvc *b) +{ + if (*a->sas_addr.prv) + if (memcmp(a->sas_addr.prv, b->sas_addr.prv, ATM_ESA_LEN)) + return 0; + if (!*a->sas_addr.pub) + return !*b->sas_addr.pub; + if (!*b->sas_addr.pub) + return 0; + return !strcmp(a->sas_addr.pub, b->sas_addr.pub); +} + +static void notify_sigd(const struct atm_dev *dev) +{ + struct sockaddr_atmpvc pvc; + + pvc.sap_addr.itf = dev->number; + sigd_enq(NULL, as_itf_notify, NULL, &pvc, NULL); +} + +void atm_reset_addr(struct atm_dev *dev, enum atm_addr_type_t atype) +{ + unsigned long flags; + struct atm_dev_addr *this, *p; + struct list_head *head; + + spin_lock_irqsave(&dev->lock, flags); + if (atype == ATM_ADDR_LECS) + head = &dev->lecs; + else + head = &dev->local; + list_for_each_entry_safe(this, p, head, entry) { + list_del(&this->entry); + kfree(this); + } + spin_unlock_irqrestore(&dev->lock, flags); + if (head == &dev->local) + notify_sigd(dev); +} + +int atm_add_addr(struct atm_dev *dev, const struct sockaddr_atmsvc *addr, + enum atm_addr_type_t atype) +{ + unsigned long flags; + struct atm_dev_addr *this; + struct list_head *head; + int error; + + error = check_addr(addr); + if (error) + return error; + spin_lock_irqsave(&dev->lock, flags); + if (atype == ATM_ADDR_LECS) + head = &dev->lecs; + else + head = &dev->local; + list_for_each_entry(this, head, entry) { + if (identical(&this->addr, addr)) { + spin_unlock_irqrestore(&dev->lock, flags); + return -EEXIST; + } + } + this = kmalloc(sizeof(struct atm_dev_addr), GFP_ATOMIC); + if (!this) { + spin_unlock_irqrestore(&dev->lock, flags); + return -ENOMEM; + } + this->addr = *addr; + list_add(&this->entry, head); + spin_unlock_irqrestore(&dev->lock, flags); + if (head == &dev->local) + notify_sigd(dev); + return 0; +} + +int atm_del_addr(struct atm_dev *dev, const struct sockaddr_atmsvc *addr, + enum atm_addr_type_t atype) +{ + unsigned long flags; + struct atm_dev_addr *this; + struct list_head *head; + int error; + + error = check_addr(addr); + if (error) + return error; + spin_lock_irqsave(&dev->lock, flags); + if (atype == ATM_ADDR_LECS) + head = &dev->lecs; + else + head = &dev->local; + list_for_each_entry(this, head, entry) { + if (identical(&this->addr, addr)) { + list_del(&this->entry); + spin_unlock_irqrestore(&dev->lock, flags); + kfree(this); + if (head == &dev->local) + notify_sigd(dev); + return 0; + } + } + spin_unlock_irqrestore(&dev->lock, flags); + return -ENOENT; +} + +int atm_get_addr(struct atm_dev *dev, struct sockaddr_atmsvc __user * buf, + size_t size, enum atm_addr_type_t atype) +{ + unsigned long flags; + struct atm_dev_addr *this; + struct list_head *head; + int total = 0, error; + struct sockaddr_atmsvc *tmp_buf, *tmp_bufp; + + spin_lock_irqsave(&dev->lock, flags); + if (atype == ATM_ADDR_LECS) + head = &dev->lecs; + else + head = &dev->local; + list_for_each_entry(this, head, entry) + total += sizeof(struct sockaddr_atmsvc); + tmp_buf = tmp_bufp = kmalloc(total, GFP_ATOMIC); + if (!tmp_buf) { + spin_unlock_irqrestore(&dev->lock, flags); + return -ENOMEM; + } + list_for_each_entry(this, head, entry) + memcpy(tmp_bufp++, &this->addr, sizeof(struct sockaddr_atmsvc)); + spin_unlock_irqrestore(&dev->lock, flags); + error = total > size ? -E2BIG : total; + if (copy_to_user(buf, tmp_buf, total < size ? total : size)) + error = -EFAULT; + kfree(tmp_buf); + return error; +} |