diff options
Diffstat (limited to 'backport/compat/backport-3.18.c')
-rw-r--r-- | backport/compat/backport-3.18.c | 332 |
1 files changed, 0 insertions, 332 deletions
diff --git a/backport/compat/backport-3.18.c b/backport/compat/backport-3.18.c deleted file mode 100644 index d2eceef7..00000000 --- a/backport/compat/backport-3.18.c +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright (c) 2014 Hauke Mehrtens <hauke@hauke-m.de> - * - * Backport functionality introduced in Linux 3.18. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include <linux/if_ether.h> -#include <linux/if_vlan.h> -#include <linux/ip.h> -#include <linux/ipv6.h> -#include <scsi/fc/fc_fcoe.h> -#include <linux/skbuff.h> -#include <linux/errqueue.h> -#include <linux/wait.h> -#include <linux/of.h> -#include <linux/string.h> - -/** - * eth_get_headlen - determine the the length of header for an ethernet frame - * @data: pointer to start of frame - * @len: total length of frame - * - * Make a best effort attempt to pull the length for all of the headers for - * a given frame in a linear buffer. - */ -int eth_get_headlen(unsigned char *data, unsigned int max_len) -{ - union { - unsigned char *network; - /* l2 headers */ - struct ethhdr *eth; - struct vlan_hdr *vlan; - /* l3 headers */ - struct iphdr *ipv4; - struct ipv6hdr *ipv6; - } hdr; - __be16 protocol; - u8 nexthdr = 0; /* default to not TCP */ - u8 hlen; - - /* this should never happen, but better safe than sorry */ - if (max_len < ETH_HLEN) - return max_len; - - /* initialize network frame pointer */ - hdr.network = data; - - /* set first protocol and move network header forward */ - protocol = hdr.eth->h_proto; - hdr.network += ETH_HLEN; - - /* handle any vlan tag if present */ - if (protocol == htons(ETH_P_8021Q)) { - if ((hdr.network - data) > (max_len - VLAN_HLEN)) - return max_len; - - protocol = hdr.vlan->h_vlan_encapsulated_proto; - hdr.network += VLAN_HLEN; - } - - /* handle L3 protocols */ - if (protocol == htons(ETH_P_IP)) { - if ((hdr.network - data) > (max_len - sizeof(struct iphdr))) - return max_len; - - /* access ihl as a u8 to avoid unaligned access on ia64 */ - hlen = (hdr.network[0] & 0x0F) << 2; - - /* verify hlen meets minimum size requirements */ - if (hlen < sizeof(struct iphdr)) - return hdr.network - data; - - /* record next protocol if header is present */ - if (!(hdr.ipv4->frag_off & htons(IP_OFFSET))) - nexthdr = hdr.ipv4->protocol; - } else if (protocol == htons(ETH_P_IPV6)) { - if ((hdr.network - data) > (max_len - sizeof(struct ipv6hdr))) - return max_len; - - /* record next protocol */ - nexthdr = hdr.ipv6->nexthdr; - hlen = sizeof(struct ipv6hdr); - } else if (protocol == htons(ETH_P_FCOE)) { - if ((hdr.network - data) > (max_len - FCOE_HEADER_LEN)) - return max_len; - hlen = FCOE_HEADER_LEN; - } else { - return hdr.network - data; - } - - /* relocate pointer to start of L4 header */ - hdr.network += hlen; - - /* finally sort out TCP/UDP */ - if (nexthdr == IPPROTO_TCP) { - if ((hdr.network - data) > (max_len - sizeof(struct tcphdr))) - return max_len; - - /* access doff as a u8 to avoid unaligned access on ia64 */ - hlen = (hdr.network[12] & 0xF0) >> 2; - - /* verify hlen meets minimum size requirements */ - if (hlen < sizeof(struct tcphdr)) - return hdr.network - data; - - hdr.network += hlen; - } else if (nexthdr == IPPROTO_UDP) { - if ((hdr.network - data) > (max_len - sizeof(struct udphdr))) - return max_len; - - hdr.network += sizeof(struct udphdr); - } - - /* - * If everything has gone correctly hdr.network should be the - * data section of the packet and will be the end of the header. - * If not then it probably represents the end of the last recognized - * header. - */ - if ((hdr.network - data) < max_len) - return hdr.network - data; - else - return max_len; -} -EXPORT_SYMBOL_GPL(eth_get_headlen); - -#define sock_efree LINUX_BACKPORT(sock_efree) -static void sock_efree(struct sk_buff *skb) -{ - sock_put(skb->sk); -} - -/** - * skb_clone_sk - create clone of skb, and take reference to socket - * @skb: the skb to clone - * - * This function creates a clone of a buffer that holds a reference on - * sk_refcnt. Buffers created via this function are meant to be - * returned using sock_queue_err_skb, or free via kfree_skb. - * - * When passing buffers allocated with this function to sock_queue_err_skb - * it is necessary to wrap the call with sock_hold/sock_put in order to - * prevent the socket from being released prior to being enqueued on - * the sk_error_queue. - */ -struct sk_buff *skb_clone_sk(struct sk_buff *skb) -{ - struct sock *sk = skb->sk; - struct sk_buff *clone; - - if (!sk || !atomic_inc_not_zero(&sk->sk_refcnt)) - return NULL; - - clone = skb_clone(skb, GFP_ATOMIC); - if (!clone) { - sock_put(sk); - return NULL; - } - - clone->sk = sk; - clone->destructor = sock_efree; - - return clone; -} -EXPORT_SYMBOL_GPL(skb_clone_sk); - -#if LINUX_VERSION_IS_GEQ(3,3,0) -/* - * skb_complete_wifi_ack() needs to get backported, because the version from - * 3.18 added the sock_hold() and sock_put() calles missing in older versions. - */ -void skb_complete_wifi_ack(struct sk_buff *skb, bool acked) -{ - struct sock *sk = skb->sk; - struct sock_exterr_skb *serr; - int err; - - skb->wifi_acked_valid = 1; - skb->wifi_acked = acked; - - serr = SKB_EXT_ERR(skb); - memset(serr, 0, sizeof(*serr)); - serr->ee.ee_errno = ENOMSG; - serr->ee.ee_origin = SO_EE_ORIGIN_TXSTATUS; - - /* take a reference to prevent skb_orphan() from freeing the socket */ - sock_hold(sk); - - err = sock_queue_err_skb(sk, skb); - if (err) - kfree_skb(skb); - - sock_put(sk); -} -EXPORT_SYMBOL_GPL(skb_complete_wifi_ack); -#endif - -#if LINUX_VERSION_IS_GEQ(3,17,0) -int __sched out_of_line_wait_on_bit_timeout( - void *word, int bit, wait_bit_action_f *action, - unsigned mode, unsigned long timeout) -{ - wait_queue_head_t *wq = bit_waitqueue(word, bit); - DEFINE_WAIT_BIT(wait, word, bit); - - wait.key.private = jiffies + timeout; - return __wait_on_bit(wq, &wait, action, mode); -} -EXPORT_SYMBOL_GPL(out_of_line_wait_on_bit_timeout); - -__sched int bit_wait_timeout(struct wait_bit_key *word) -{ - unsigned long now = ACCESS_ONCE(jiffies); - if (signal_pending_state(current->state, current)) - return 1; - if (time_after_eq(now, word->private)) - return -EAGAIN; - schedule_timeout(word->private - now); - return 0; -} -EXPORT_SYMBOL_GPL(bit_wait_timeout); -#endif - -#ifdef CONFIG_OF -/** - * of_find_property_value_of_size - * - * @np: device node from which the property value is to be read. - * @propname: name of the property to be searched. - * @len: requested length of property value - * - * Search for a property in a device node and valid the requested size. - * Returns the property value on success, -EINVAL if the property does not - * exist, -ENODATA if property does not have a value, and -EOVERFLOW if the - * property data isn't large enough. - * - */ -void *of_find_property_value_of_size(const struct device_node *np, - const char *propname, u32 len) -{ - struct property *prop = of_find_property(np, propname, NULL); - - if (!prop) - return ERR_PTR(-EINVAL); - if (!prop->value) - return ERR_PTR(-ENODATA); - if (len > prop->length) - return ERR_PTR(-EOVERFLOW); - - return prop->value; -} - -/** - * of_property_read_u64_array - Find and read an array of 64 bit integers - * from a property. - * - * @np: device node from which the property value is to be read. - * @propname: name of the property to be searched. - * @out_values: pointer to return value, modified only if return value is 0. - * @sz: number of array elements to read - * - * Search for a property in a device node and read 64-bit value(s) from - * it. Returns 0 on success, -EINVAL if the property does not exist, - * -ENODATA if property does not have a value, and -EOVERFLOW if the - * property data isn't large enough. - * - * The out_values is modified only if a valid u64 value can be decoded. - */ -int of_property_read_u64_array(const struct device_node *np, - const char *propname, u64 *out_values, - size_t sz) -{ - const __be32 *val = of_find_property_value_of_size(np, propname, - (sz * sizeof(*out_values))); - - if (IS_ERR(val)) - return PTR_ERR(val); - - while (sz--) { - *out_values++ = of_read_number(val, 2); - val += 2; - } - return 0; -} -EXPORT_SYMBOL_GPL(of_property_read_u64_array); -#endif /* CONFIG_OF */ - -#if !(LINUX_VERSION_IS_GEQ(3,17,3) || \ - (LINUX_VERSION_IS_GEQ(3,14,24) && \ - LINUX_VERSION_IS_LESS(3,15,0)) || \ - (LINUX_VERSION_IS_GEQ(3,12,33) && \ - LINUX_VERSION_IS_LESS(3,13,0)) || \ - (LINUX_VERSION_IS_GEQ(3,10,60) && \ - LINUX_VERSION_IS_LESS(3,11,0)) || \ - (LINUX_VERSION_IS_GEQ(3,4,106) && \ - LINUX_VERSION_IS_LESS(3,5,0)) || \ - (LINUX_VERSION_IS_GEQ(3,2,65) && \ - LINUX_VERSION_IS_LESS(3,3,0))) -/** - * memzero_explicit - Fill a region of memory (e.g. sensitive - * keying data) with 0s. - * @s: Pointer to the start of the area. - * @count: The size of the area. - * - * Note: usually using memset() is just fine (!), but in cases - * where clearing out _local_ data at the end of a scope is - * necessary, memzero_explicit() should be used instead in - * order to prevent the compiler from optimising away zeroing. - * - * memzero_explicit() doesn't need an arch-specific version as - * it just invokes the one of memset() implicitly. - */ -void memzero_explicit(void *s, size_t count) -{ - memset(s, 0, count); - barrier_data(s); -} -EXPORT_SYMBOL_GPL(memzero_explicit); -#endif - -char *bin2hex(char *dst, const void *src, size_t count) -{ - const unsigned char *_src = src; - - while (count--) - dst = hex_byte_pack(dst, *_src++); - return dst; -} -EXPORT_SYMBOL(bin2hex); |