* Re: Nested function in drivers/of/of_mdio.c
From: Jérôme Pouiller @ 2009-10-08 8:45 UTC (permalink / raw)
To: linuxppc-dev, Grant Likely; +Cc: netdev, Andy Fleming, David S. Miller
In-Reply-To: <f608b67d0910070923h54c30c2doae08550b0791ed1b@mail.gmail.com>
I did some grep on codebase. I have not found any other instances of
nested functions, but my regexps are not enough to be 100% sure.
On Wednesday 07 October 2009 18:23:04 vb@vsbe.com wrote:
> Guys, are there other instances of nested C functions in the codebase
> or was this the first attempt?
>
> On Wed, Oct 7, 2009 at 9:11 AM, Grant Likely
<grant.likely@secretlab.ca> wrote:
> > On Wed, Oct 7, 2009 at 9:15 AM, Jérôme Pouiller <jezz@sysmic.org>
wrote:
> >> Dear,
> >>
> >> I have a problem with commit
> >> 8bc487d150b939e69830c39322df4ee486efe381 in file
> >> drivers/of/of_mdio.c in function of_phy_find_device.
> >>
> >> As you see, this function define match() as a nested function. My
> >> compiler (powerpc-e500-linux-gnu-gcc-3.4.1) raise an error during
> >> link due to this nested definition:
> >> drivers/built-in.o(.text+0x5e2a4): In function
> >> `of_phy_find_device':
> >> /home/jezz/linux-next/drivers/of/of_mdio.c:107: undefined
> >> reference to `__trampoline_setup'
> >>
> >> I am sure I could solve problem by rebuilding my toolchain.
> >> Nevertheless, I think nested function definition is not perfectly
> >> supported by all compilers. Also, I suggest to place function
> >> match() outside of scope of of_phy_find_device as in following
> >> patch.
> >
> > I'm okay with that, but if you're moving code out of the file
> > scope, then please rename the function to of_phy_match() to avoid
> > global namespace conflicts.
> >
> > g.
> >
> >> diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c
> >> index bacaa53..c7b2e26 100644
> >> --- a/drivers/of/of_mdio.c
> >> +++ b/drivers/of/of_mdio.c
> >> @@ -97,6 +97,10 @@ int of_mdiobus_register(struct mii_bus *mdio,
> >> struct device_node *np) }
> >> EXPORT_SYMBOL(of_mdiobus_register);
> >>
> >> +static int match(struct device *dev, void *phy_np)
> >> +{
> >> + return dev_archdata_get_node(&dev->archdata) == phy_np;
> >> +}
> >> /**
> >> * of_phy_find_device - Give a PHY node, find the phy_device
> >> * @phy_np: Pointer to the phy's device tree node
> >> @@ -106,11 +110,6 @@ EXPORT_SYMBOL(of_mdiobus_register);
> >> struct phy_device *of_phy_find_device(struct device_node *phy_np)
> >> {
> >> struct device *d;
> >> - int match(struct device *dev, void *phy_np)
> >> - {
> >> - return dev_archdata_get_node(&dev->archdata) ==
> >> phy_np; - }
> >> -
> >> if (!phy_np)
> >> return NULL;
> >>
> >>
> >> What do you think about it?
> >>
> >> Best regards,
> >>
> >> --
> >> Jérôme Pouiller (jezz AT sysmic DOT org)
> >
> > --
> > Grant Likely, B.Sc., P.Eng.
> > Secret Lab Technologies Ltd.
> > _______________________________________________
> > Linuxppc-dev mailing list
> > Linuxppc-dev@lists.ozlabs.org
> > https://lists.ozlabs.org/listinfo/linuxppc-dev
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
>
--
Jérôme Pouiller (jerome AT sysmic DOT org)
Expert Linux Embarqué
^ permalink raw reply
* [PATCH 5/5] xfrm: remove skb_icv_walk
From: Steffen Klassert @ 2009-10-08 8:50 UTC (permalink / raw)
To: David Miller, Herbert Xu; +Cc: netdev
In-Reply-To: <20091008084631.GJ15653@secunet.com>
The last users of skb_icv_walk are converted to ahash now,
so skb_icv_walk is unused and can be removed.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
include/net/xfrm.h | 3 --
net/xfrm/xfrm_algo.c | 78 --------------------------------------------------
2 files changed, 0 insertions(+), 81 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 223e90a..d9c6dbb 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1500,9 +1500,6 @@ struct scatterlist;
typedef int (icv_update_fn_t)(struct hash_desc *, struct scatterlist *,
unsigned int);
-extern int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *tfm,
- int offset, int len, icv_update_fn_t icv_update);
-
static inline int xfrm_addr_cmp(xfrm_address_t *a, xfrm_address_t *b,
int family)
{
diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c
index faf54c6..b393410 100644
--- a/net/xfrm/xfrm_algo.c
+++ b/net/xfrm/xfrm_algo.c
@@ -689,84 +689,6 @@ int xfrm_count_enc_supported(void)
}
EXPORT_SYMBOL_GPL(xfrm_count_enc_supported);
-/* Move to common area: it is shared with AH. */
-
-int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc,
- int offset, int len, icv_update_fn_t icv_update)
-{
- int start = skb_headlen(skb);
- int i, copy = start - offset;
- struct sk_buff *frag_iter;
- struct scatterlist sg;
- int err;
-
- /* Checksum header. */
- if (copy > 0) {
- if (copy > len)
- copy = len;
-
- sg_init_one(&sg, skb->data + offset, copy);
-
- err = icv_update(desc, &sg, copy);
- if (unlikely(err))
- return err;
-
- if ((len -= copy) == 0)
- return 0;
- offset += copy;
- }
-
- for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- int end;
-
- WARN_ON(start > offset + len);
-
- end = start + skb_shinfo(skb)->frags[i].size;
- if ((copy = end - offset) > 0) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-
- if (copy > len)
- copy = len;
-
- sg_init_table(&sg, 1);
- sg_set_page(&sg, frag->page, copy,
- frag->page_offset + offset-start);
-
- err = icv_update(desc, &sg, copy);
- if (unlikely(err))
- return err;
-
- if (!(len -= copy))
- return 0;
- offset += copy;
- }
- start = end;
- }
-
- skb_walk_frags(skb, frag_iter) {
- int end;
-
- WARN_ON(start > offset + len);
-
- end = start + frag_iter->len;
- if ((copy = end - offset) > 0) {
- if (copy > len)
- copy = len;
- err = skb_icv_walk(frag_iter, desc, offset-start,
- copy, icv_update);
- if (unlikely(err))
- return err;
- if ((len -= copy) == 0)
- return 0;
- offset += copy;
- }
- start = end;
- }
- BUG_ON(len);
- return 0;
-}
-EXPORT_SYMBOL_GPL(skb_icv_walk);
-
#if defined(CONFIG_INET_ESP) || defined(CONFIG_INET_ESP_MODULE) || defined(CONFIG_INET6_ESP) || defined(CONFIG_INET6_ESP_MODULE)
void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len)
--
1.5.4.2
^ permalink raw reply related
* [PATCH 4/5] ah: Remove obsolete code
From: Steffen Klassert @ 2009-10-08 8:49 UTC (permalink / raw)
To: David Miller, Herbert Xu; +Cc: netdev
In-Reply-To: <20091008084631.GJ15653@secunet.com>
ah4 and ah6 are converted to ahash now, so we can remove the
code for the obsolete hash algorithm.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
include/net/ah.h | 29 +++--------------------------
1 files changed, 3 insertions(+), 26 deletions(-)
diff --git a/include/net/ah.h b/include/net/ah.h
index 7ac5221..7573a71 100644
--- a/include/net/ah.h
+++ b/include/net/ah.h
@@ -1,44 +1,21 @@
#ifndef _NET_AH_H
#define _NET_AH_H
-#include <linux/crypto.h>
-#include <net/xfrm.h>
+#include <linux/skbuff.h>
/* This is the maximum truncated ICV length that we know of. */
#define MAX_AH_AUTH_LEN 12
+struct crypto_ahash;
+
struct ah_data
{
- u8 *work_icv;
int icv_full_len;
int icv_trunc_len;
- struct crypto_hash *tfm;
struct crypto_ahash *ahash;
};
-static inline int ah_mac_digest(struct ah_data *ahp, struct sk_buff *skb,
- u8 *auth_data)
-{
- struct hash_desc desc;
- int err;
-
- desc.tfm = ahp->tfm;
- desc.flags = 0;
-
- memset(auth_data, 0, ahp->icv_trunc_len);
- err = crypto_hash_init(&desc);
- if (unlikely(err))
- goto out;
- err = skb_icv_walk(skb, &desc, 0, skb->len, crypto_hash_update);
- if (unlikely(err))
- goto out;
- err = crypto_hash_final(&desc, ahp->work_icv);
-
-out:
- return err;
-}
-
struct ip_auth_hdr;
static inline struct ip_auth_hdr *ip_auth_hdr(const struct sk_buff *skb)
--
1.5.4.2
^ permalink raw reply related
* [PATCH 3/5] ah6: convert to ahash
From: Steffen Klassert @ 2009-10-08 8:49 UTC (permalink / raw)
To: David Miller, Herbert Xu; +Cc: netdev
In-Reply-To: <20091008084631.GJ15653@secunet.com>
This patch converts ah6 to the new ahash interface.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
net/ipv6/ah6.c | 352 +++++++++++++++++++++++++++++++++++++++++++-------------
1 files changed, 272 insertions(+), 80 deletions(-)
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index c1589e2..0f526f8 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -24,18 +24,92 @@
* This file is derived from net/ipv4/ah.c.
*/
+#include <crypto/hash.h>
#include <linux/module.h>
#include <net/ip.h>
#include <net/ah.h>
#include <linux/crypto.h>
#include <linux/pfkeyv2.h>
-#include <linux/spinlock.h>
#include <linux/string.h>
+#include <linux/scatterlist.h>
#include <net/icmp.h>
#include <net/ipv6.h>
#include <net/protocol.h>
#include <net/xfrm.h>
+#define IPV6HDR_BASELEN 8
+
+struct tmp_ext {
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+ struct in6_addr saddr;
+#endif
+ struct in6_addr daddr;
+ char hdrs[0];
+};
+
+struct ah_skb_cb {
+ struct xfrm_skb_cb xfrm;
+ void *tmp;
+};
+
+#define AH_SKB_CB(__skb) ((struct ah_skb_cb *)&((__skb)->cb[0]))
+
+static void *ah_alloc_tmp(struct crypto_ahash *ahash, int nfrags,
+ unsigned int size)
+{
+ unsigned int len;
+
+ len = size + crypto_ahash_digestsize(ahash) +
+ (crypto_ahash_alignmask(ahash) &
+ ~(crypto_tfm_ctx_alignment() - 1));
+
+ len = ALIGN(len, crypto_tfm_ctx_alignment());
+
+ len += sizeof(struct ahash_request) + crypto_ahash_reqsize(ahash);
+ len = ALIGN(len, __alignof__(struct scatterlist));
+
+ len += sizeof(struct scatterlist) * nfrags;
+
+ return kmalloc(len, GFP_ATOMIC);
+}
+
+static inline struct tmp_ext *ah_tmp_ext(void *base)
+{
+ return base + IPV6HDR_BASELEN;
+}
+
+static inline u8 *ah_tmp_auth(u8 *tmp, unsigned int offset)
+{
+ return tmp + offset;
+}
+
+static inline u8 *ah_tmp_icv(struct crypto_ahash *ahash, void *tmp,
+ unsigned int offset)
+{
+ return PTR_ALIGN((u8 *)tmp + offset, crypto_ahash_alignmask(ahash) + 1);
+}
+
+static inline struct ahash_request *ah_tmp_req(struct crypto_ahash *ahash,
+ u8 *icv)
+{
+ struct ahash_request *req;
+
+ req = (void *)PTR_ALIGN(icv + crypto_ahash_digestsize(ahash),
+ crypto_tfm_ctx_alignment());
+
+ ahash_request_set_tfm(req, ahash);
+
+ return req;
+}
+
+static inline struct scatterlist *ah_req_sg(struct crypto_ahash *ahash,
+ struct ahash_request *req)
+{
+ return (void *)ALIGN((unsigned long)(req + 1) +
+ crypto_ahash_reqsize(ahash),
+ __alignof__(struct scatterlist));
+}
+
static int zero_out_mutable_opts(struct ipv6_opt_hdr *opthdr)
{
u8 *opt = (u8 *)opthdr;
@@ -218,24 +292,85 @@ static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len, int dir)
return 0;
}
+static void ah6_output_done(struct crypto_async_request *base, int err)
+{
+ int extlen;
+ u8 *iph_base;
+ u8 *icv;
+ struct sk_buff *skb = base->data;
+ struct xfrm_state *x = skb_dst(skb)->xfrm;
+ struct ah_data *ahp = x->data;
+ struct ipv6hdr *top_iph = ipv6_hdr(skb);
+ struct ip_auth_hdr *ah = ip_auth_hdr(skb);
+ struct tmp_ext *iph_ext;
+
+ extlen = skb_network_header_len(skb) - sizeof(struct ipv6hdr);
+ if (extlen)
+ extlen += sizeof(*iph_ext);
+
+ iph_base = AH_SKB_CB(skb)->tmp;
+ iph_ext = ah_tmp_ext(iph_base);
+ icv = ah_tmp_icv(ahp->ahash, iph_ext, extlen);
+
+ memcpy(ah->auth_data, icv, ahp->icv_trunc_len);
+ memcpy(top_iph, iph_base, IPV6HDR_BASELEN);
+
+ if (extlen) {
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+ memcpy(&top_iph->saddr, iph_ext, extlen);
+#else
+ memcpy(&top_iph->daddr, iph_ext, extlen);
+#endif
+ }
+
+ err = ah->nexthdr;
+
+ kfree(AH_SKB_CB(skb)->tmp);
+ xfrm_output_resume(skb, err);
+}
+
static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
{
int err;
+ int nfrags;
int extlen;
+ u8 *iph_base;
+ u8 *icv;
+ u8 nexthdr;
+ struct sk_buff *trailer;
+ struct crypto_ahash *ahash;
+ struct ahash_request *req;
+ struct scatterlist *sg;
struct ipv6hdr *top_iph;
struct ip_auth_hdr *ah;
struct ah_data *ahp;
- u8 nexthdr;
- char tmp_base[8];
- struct {
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
- struct in6_addr saddr;
-#endif
- struct in6_addr daddr;
- char hdrs[0];
- } *tmp_ext;
+ struct tmp_ext *iph_ext;
+
+ ahp = x->data;
+ ahash = ahp->ahash;
+
+ if ((err = skb_cow_data(skb, 0, &trailer)) < 0)
+ goto out;
+ nfrags = err;
skb_push(skb, -skb_network_offset(skb));
+ extlen = skb_network_header_len(skb) - sizeof(struct ipv6hdr);
+ if (extlen)
+ extlen += sizeof(*iph_ext);
+
+ err = -ENOMEM;
+ iph_base = ah_alloc_tmp(ahash, nfrags, IPV6HDR_BASELEN + extlen);
+ if (!iph_base)
+ goto out;
+
+ iph_ext = ah_tmp_ext(iph_base);
+ icv = ah_tmp_icv(ahash, iph_ext, extlen);
+ req = ah_tmp_req(ahash, icv);
+ sg = ah_req_sg(ahash, req);
+
+ ah = ip_auth_hdr(skb);
+ memset(ah->auth_data, 0, ahp->icv_trunc_len);
+
top_iph = ipv6_hdr(skb);
top_iph->payload_len = htons(skb->len - sizeof(*top_iph));
@@ -245,31 +380,22 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
/* When there are no extension headers, we only need to save the first
* 8 bytes of the base IP header.
*/
- memcpy(tmp_base, top_iph, sizeof(tmp_base));
+ memcpy(iph_base, top_iph, IPV6HDR_BASELEN);
- tmp_ext = NULL;
- extlen = skb_transport_offset(skb) - sizeof(struct ipv6hdr);
if (extlen) {
- extlen += sizeof(*tmp_ext);
- tmp_ext = kmalloc(extlen, GFP_ATOMIC);
- if (!tmp_ext) {
- err = -ENOMEM;
- goto error;
- }
#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
- memcpy(tmp_ext, &top_iph->saddr, extlen);
+ memcpy(iph_ext, &top_iph->saddr, extlen);
#else
- memcpy(tmp_ext, &top_iph->daddr, extlen);
+ memcpy(iph_ext, &top_iph->daddr, extlen);
#endif
err = ipv6_clear_mutable_options(top_iph,
- extlen - sizeof(*tmp_ext) +
+ extlen - sizeof(*iph_ext) +
sizeof(*top_iph),
XFRM_POLICY_OUT);
if (err)
- goto error_free_iph;
+ goto out_free;
}
- ah = ip_auth_hdr(skb);
ah->nexthdr = nexthdr;
top_iph->priority = 0;
@@ -278,36 +404,80 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
top_iph->flow_lbl[2] = 0;
top_iph->hop_limit = 0;
- ahp = x->data;
ah->hdrlen = (XFRM_ALIGN8(sizeof(*ah) + ahp->icv_trunc_len) >> 2) - 2;
ah->reserved = 0;
ah->spi = x->id.spi;
ah->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output);
- spin_lock_bh(&x->lock);
- err = ah_mac_digest(ahp, skb, ah->auth_data);
- memcpy(ah->auth_data, ahp->work_icv, ahp->icv_trunc_len);
- spin_unlock_bh(&x->lock);
+ sg_init_table(sg, nfrags);
+ skb_to_sgvec(skb, sg, 0, skb->len);
- if (err)
- goto error_free_iph;
+ ahash_request_set_crypt(req, sg, icv, skb->len);
+ ahash_request_set_callback(req, 0, ah6_output_done, skb);
+
+ AH_SKB_CB(skb)->tmp = iph_base;
- memcpy(top_iph, tmp_base, sizeof(tmp_base));
- if (tmp_ext) {
+ err = crypto_ahash_digest(req);
+ if (err) {
+ if (err == -EINPROGRESS)
+ goto out;
+
+ if (err == -EBUSY)
+ err = NET_XMIT_DROP;
+ goto out_free;
+ }
+
+ memcpy(ah->auth_data, icv, ahp->icv_trunc_len);
+ memcpy(top_iph, iph_base, IPV6HDR_BASELEN);
+
+ if (extlen) {
#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
- memcpy(&top_iph->saddr, tmp_ext, extlen);
+ memcpy(&top_iph->saddr, iph_ext, extlen);
#else
- memcpy(&top_iph->daddr, tmp_ext, extlen);
+ memcpy(&top_iph->daddr, iph_ext, extlen);
#endif
-error_free_iph:
- kfree(tmp_ext);
}
-error:
+out_free:
+ kfree(iph_base);
+out:
return err;
}
+static void ah6_input_done(struct crypto_async_request *base, int err)
+{
+ u8 *auth_data;
+ u8 *icv;
+ u8 *work_iph;
+ struct sk_buff *skb = base->data;
+ struct xfrm_state *x = xfrm_input_state(skb);
+ struct ah_data *ahp = x->data;
+ struct ip_auth_hdr *ah = ip_auth_hdr(skb);
+ int hdr_len = skb_network_header_len(skb);
+ int ah_hlen = (ah->hdrlen + 2) << 2;
+
+ work_iph = AH_SKB_CB(skb)->tmp;
+ auth_data = ah_tmp_auth(work_iph, hdr_len);
+ icv = ah_tmp_icv(ahp->ahash, auth_data, ahp->icv_trunc_len);
+
+ err = memcmp(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG: 0;
+ if (err)
+ goto out;
+
+ skb->network_header += ah_hlen;
+ memcpy(skb_network_header(skb), work_iph, hdr_len);
+ __skb_pull(skb, ah_hlen + hdr_len);
+ skb_set_transport_header(skb, -hdr_len);
+
+ err = ah->nexthdr;
+out:
+ kfree(AH_SKB_CB(skb)->tmp);
+ xfrm_input_resume(skb, err);
+}
+
+
+
static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
{
/*
@@ -325,14 +495,21 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
* There is offset of AH before IPv6 header after the process.
*/
+ u8 *auth_data;
+ u8 *icv;
+ u8 *work_iph;
+ struct sk_buff *trailer;
+ struct crypto_ahash *ahash;
+ struct ahash_request *req;
+ struct scatterlist *sg;
struct ip_auth_hdr *ah;
struct ipv6hdr *ip6h;
struct ah_data *ahp;
- unsigned char *tmp_hdr = NULL;
u16 hdr_len;
u16 ah_hlen;
int nexthdr;
- int err = -EINVAL;
+ int nfrags;
+ int err = -ENOMEM;
if (!pskb_may_pull(skb, sizeof(struct ip_auth_hdr)))
goto out;
@@ -345,9 +522,11 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
skb->ip_summed = CHECKSUM_NONE;
- hdr_len = skb->data - skb_network_header(skb);
+ hdr_len = skb_network_header_len(skb);
ah = (struct ip_auth_hdr *)skb->data;
ahp = x->data;
+ ahash = ahp->ahash;
+
nexthdr = ah->nexthdr;
ah_hlen = (ah->hdrlen + 2) << 2;
@@ -358,48 +537,67 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
if (!pskb_may_pull(skb, ah_hlen))
goto out;
- tmp_hdr = kmemdup(skb_network_header(skb), hdr_len, GFP_ATOMIC);
- if (!tmp_hdr)
- goto out;
ip6h = ipv6_hdr(skb);
+
+ skb_push(skb, hdr_len);
+
+ if ((err = skb_cow_data(skb, 0, &trailer)) < 0)
+ goto out;
+ nfrags = err;
+
+ work_iph = ah_alloc_tmp(ahash, nfrags, hdr_len + ahp->icv_trunc_len);
+ if (!work_iph)
+ goto out;
+
+ auth_data = ah_tmp_auth(work_iph, hdr_len);
+ icv = ah_tmp_icv(ahash, auth_data, ahp->icv_trunc_len);
+ req = ah_tmp_req(ahash, icv);
+ sg = ah_req_sg(ahash, req);
+
+ memcpy(work_iph, ip6h, hdr_len);
+ memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
+ memset(ah->auth_data, 0, ahp->icv_trunc_len);
+
if (ipv6_clear_mutable_options(ip6h, hdr_len, XFRM_POLICY_IN))
- goto free_out;
+ goto out_free;
+
ip6h->priority = 0;
ip6h->flow_lbl[0] = 0;
ip6h->flow_lbl[1] = 0;
ip6h->flow_lbl[2] = 0;
ip6h->hop_limit = 0;
- spin_lock(&x->lock);
- {
- u8 auth_data[MAX_AH_AUTH_LEN];
+ sg_init_table(sg, nfrags);
+ skb_to_sgvec(skb, sg, 0, skb->len);
- memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
- memset(ah->auth_data, 0, ahp->icv_trunc_len);
- skb_push(skb, hdr_len);
- err = ah_mac_digest(ahp, skb, ah->auth_data);
- if (err)
- goto unlock;
- if (memcmp(ahp->work_icv, auth_data, ahp->icv_trunc_len))
- err = -EBADMSG;
+ ahash_request_set_crypt(req, sg, icv, skb->len);
+ ahash_request_set_callback(req, 0, ah6_input_done, skb);
+
+ AH_SKB_CB(skb)->tmp = work_iph;
+
+ err = crypto_ahash_digest(req);
+ if (err) {
+ if (err == -EINPROGRESS)
+ goto out;
+
+ if (err == -EBUSY)
+ err = NET_XMIT_DROP;
+ goto out_free;
}
-unlock:
- spin_unlock(&x->lock);
+ err = memcmp(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG: 0;
if (err)
- goto free_out;
+ goto out_free;
skb->network_header += ah_hlen;
- memcpy(skb_network_header(skb), tmp_hdr, hdr_len);
+ memcpy(skb_network_header(skb), work_iph, hdr_len);
skb->transport_header = skb->network_header;
__skb_pull(skb, ah_hlen + hdr_len);
- kfree(tmp_hdr);
+ err = nexthdr;
- return nexthdr;
-
-free_out:
- kfree(tmp_hdr);
+out_free:
+ kfree(work_iph);
out:
return err;
}
@@ -430,7 +628,7 @@ static int ah6_init_state(struct xfrm_state *x)
{
struct ah_data *ahp = NULL;
struct xfrm_algo_desc *aalg_desc;
- struct crypto_hash *tfm;
+ struct crypto_ahash *ahash;
if (!x->aalg)
goto error;
@@ -442,12 +640,12 @@ static int ah6_init_state(struct xfrm_state *x)
if (ahp == NULL)
return -ENOMEM;
- tfm = crypto_alloc_hash(x->aalg->alg_name, 0, CRYPTO_ALG_ASYNC);
- if (IS_ERR(tfm))
+ ahash = crypto_alloc_ahash(x->aalg->alg_name, 0, 0);
+ if (IS_ERR(ahash))
goto error;
- ahp->tfm = tfm;
- if (crypto_hash_setkey(tfm, x->aalg->alg_key,
+ ahp->ahash = ahash;
+ if (crypto_ahash_setkey(ahash, x->aalg->alg_key,
(x->aalg->alg_key_len + 7) / 8))
goto error;
@@ -461,9 +659,9 @@ static int ah6_init_state(struct xfrm_state *x)
BUG_ON(!aalg_desc);
if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
- crypto_hash_digestsize(tfm)) {
+ crypto_ahash_digestsize(ahash)) {
printk(KERN_INFO "AH: %s digestsize %u != %hu\n",
- x->aalg->alg_name, crypto_hash_digestsize(tfm),
+ x->aalg->alg_name, crypto_ahash_digestsize(ahash),
aalg_desc->uinfo.auth.icv_fullbits/8);
goto error;
}
@@ -473,10 +671,6 @@ static int ah6_init_state(struct xfrm_state *x)
BUG_ON(ahp->icv_trunc_len > MAX_AH_AUTH_LEN);
- ahp->work_icv = kmalloc(ahp->icv_full_len, GFP_KERNEL);
- if (!ahp->work_icv)
- goto error;
-
x->props.header_len = XFRM_ALIGN8(sizeof(struct ip_auth_hdr) +
ahp->icv_trunc_len);
switch (x->props.mode) {
@@ -495,8 +689,7 @@ static int ah6_init_state(struct xfrm_state *x)
error:
if (ahp) {
- kfree(ahp->work_icv);
- crypto_free_hash(ahp->tfm);
+ crypto_free_ahash(ahp->ahash);
kfree(ahp);
}
return -EINVAL;
@@ -509,8 +702,7 @@ static void ah6_destroy(struct xfrm_state *x)
if (!ahp)
return;
- kfree(ahp->work_icv);
- crypto_free_hash(ahp->tfm);
+ crypto_free_ahash(ahp->ahash);
kfree(ahp);
}
--
1.5.4.2
^ permalink raw reply related
* [PATCH 2/5] ah4: convert to ahash
From: Steffen Klassert @ 2009-10-08 8:48 UTC (permalink / raw)
To: David Miller, Herbert Xu; +Cc: netdev
In-Reply-To: <20091008084631.GJ15653@secunet.com>
This patch converts ah4 to the new ahash interface.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
net/ipv4/ah4.c | 295 ++++++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 236 insertions(+), 59 deletions(-)
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index 5c66270..d07b0c1 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -1,3 +1,4 @@
+#include <crypto/hash.h>
#include <linux/err.h>
#include <linux/module.h>
#include <net/ip.h>
@@ -5,10 +6,67 @@
#include <net/ah.h>
#include <linux/crypto.h>
#include <linux/pfkeyv2.h>
-#include <linux/spinlock.h>
+#include <linux/scatterlist.h>
#include <net/icmp.h>
#include <net/protocol.h>
+struct ah_skb_cb {
+ struct xfrm_skb_cb xfrm;
+ void *tmp;
+};
+
+#define AH_SKB_CB(__skb) ((struct ah_skb_cb *)&((__skb)->cb[0]))
+
+static void *ah_alloc_tmp(struct crypto_ahash *ahash, int nfrags,
+ unsigned int size)
+{
+ unsigned int len;
+
+ len = size + crypto_ahash_digestsize(ahash) +
+ (crypto_ahash_alignmask(ahash) &
+ ~(crypto_tfm_ctx_alignment() - 1));
+
+ len = ALIGN(len, crypto_tfm_ctx_alignment());
+
+ len += sizeof(struct ahash_request) + crypto_ahash_reqsize(ahash);
+ len = ALIGN(len, __alignof__(struct scatterlist));
+
+ len += sizeof(struct scatterlist) * nfrags;
+
+ return kmalloc(len, GFP_ATOMIC);
+}
+
+static inline u8 *ah_tmp_auth(void *tmp, unsigned int offset)
+{
+ return tmp + offset;
+}
+
+static inline u8 *ah_tmp_icv(struct crypto_ahash *ahash, void *tmp,
+ unsigned int offset)
+{
+ return PTR_ALIGN((u8 *)tmp + offset, crypto_ahash_alignmask(ahash) + 1);
+}
+
+static inline struct ahash_request *ah_tmp_req(struct crypto_ahash *ahash,
+ u8 *icv)
+{
+ struct ahash_request *req;
+
+ req = (void *)PTR_ALIGN(icv + crypto_ahash_digestsize(ahash),
+ crypto_tfm_ctx_alignment());
+
+ ahash_request_set_tfm(req, ahash);
+
+ return req;
+}
+
+static inline struct scatterlist *ah_req_sg(struct crypto_ahash *ahash,
+ struct ahash_request *req)
+{
+ return (void *)ALIGN((unsigned long)(req + 1) +
+ crypto_ahash_reqsize(ahash),
+ __alignof__(struct scatterlist));
+}
/* Clear mutable options and find final destination to substitute
* into IP header for icv calculation. Options are already checked
@@ -54,20 +112,72 @@ static int ip_clear_mutable_options(struct iphdr *iph, __be32 *daddr)
return 0;
}
+static void ah_output_done(struct crypto_async_request *base, int err)
+{
+ u8 *icv;
+ struct iphdr *iph;
+ struct sk_buff *skb = base->data;
+ struct xfrm_state *x = skb_dst(skb)->xfrm;
+ struct ah_data *ahp = x->data;
+ struct iphdr *top_iph = ip_hdr(skb);
+ struct ip_auth_hdr *ah = ip_auth_hdr(skb);
+ int ihl = ip_hdrlen(skb);
+
+ iph = AH_SKB_CB(skb)->tmp;
+ icv = ah_tmp_icv(ahp->ahash, iph, ihl);
+ memcpy(ah->auth_data, icv, ahp->icv_trunc_len);
+
+ top_iph->tos = iph->tos;
+ top_iph->ttl = iph->ttl;
+ top_iph->frag_off = iph->frag_off;
+ if (top_iph->ihl != 5) {
+ top_iph->daddr = iph->daddr;
+ memcpy(top_iph+1, iph+1, top_iph->ihl*4 - sizeof(struct iphdr));
+ }
+
+ err = ah->nexthdr;
+
+ kfree(AH_SKB_CB(skb)->tmp);
+ xfrm_output_resume(skb, err);
+}
+
static int ah_output(struct xfrm_state *x, struct sk_buff *skb)
{
int err;
+ int nfrags;
+ int ihl;
+ u8 *icv;
+ struct sk_buff *trailer;
+ struct crypto_ahash *ahash;
+ struct ahash_request *req;
+ struct scatterlist *sg;
struct iphdr *iph, *top_iph;
struct ip_auth_hdr *ah;
struct ah_data *ahp;
- union {
- struct iphdr iph;
- char buf[60];
- } tmp_iph;
+
+ ahp = x->data;
+ ahash = ahp->ahash;
+
+ if ((err = skb_cow_data(skb, 0, &trailer)) < 0)
+ goto out;
+ nfrags = err;
skb_push(skb, -skb_network_offset(skb));
+ ah = ip_auth_hdr(skb);
+ ihl = ip_hdrlen(skb);
+
+ err = -ENOMEM;
+ iph = ah_alloc_tmp(ahash, nfrags, ihl);
+ if (!iph)
+ goto out;
+
+ icv = ah_tmp_icv(ahash, iph, ihl);
+ req = ah_tmp_req(ahash, icv);
+ sg = ah_req_sg(ahash, req);
+
+ memset(ah->auth_data, 0, ahp->icv_trunc_len);
+
top_iph = ip_hdr(skb);
- iph = &tmp_iph.iph;
iph->tos = top_iph->tos;
iph->ttl = top_iph->ttl;
@@ -78,10 +188,9 @@ static int ah_output(struct xfrm_state *x, struct sk_buff *skb)
memcpy(iph+1, top_iph+1, top_iph->ihl*4 - sizeof(struct iphdr));
err = ip_clear_mutable_options(top_iph, &top_iph->daddr);
if (err)
- goto error;
+ goto out_free;
}
- ah = ip_auth_hdr(skb);
ah->nexthdr = *skb_mac_header(skb);
*skb_mac_header(skb) = IPPROTO_AH;
@@ -91,20 +200,31 @@ static int ah_output(struct xfrm_state *x, struct sk_buff *skb)
top_iph->ttl = 0;
top_iph->check = 0;
- ahp = x->data;
ah->hdrlen = (XFRM_ALIGN8(sizeof(*ah) + ahp->icv_trunc_len) >> 2) - 2;
ah->reserved = 0;
ah->spi = x->id.spi;
ah->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output);
- spin_lock_bh(&x->lock);
- err = ah_mac_digest(ahp, skb, ah->auth_data);
- memcpy(ah->auth_data, ahp->work_icv, ahp->icv_trunc_len);
- spin_unlock_bh(&x->lock);
+ sg_init_table(sg, nfrags);
+ skb_to_sgvec(skb, sg, 0, skb->len);
- if (err)
- goto error;
+ ahash_request_set_crypt(req, sg, icv, skb->len);
+ ahash_request_set_callback(req, 0, ah_output_done, skb);
+
+ AH_SKB_CB(skb)->tmp = iph;
+
+ err = crypto_ahash_digest(req);
+ if (err) {
+ if (err == -EINPROGRESS)
+ goto out;
+
+ if (err == -EBUSY)
+ err = NET_XMIT_DROP;
+ goto out_free;
+ }
+
+ memcpy(ah->auth_data, icv, ahp->icv_trunc_len);
top_iph->tos = iph->tos;
top_iph->ttl = iph->ttl;
@@ -114,28 +234,67 @@ static int ah_output(struct xfrm_state *x, struct sk_buff *skb)
memcpy(top_iph+1, iph+1, top_iph->ihl*4 - sizeof(struct iphdr));
}
- err = 0;
-
-error:
+out_free:
+ kfree(iph);
+out:
return err;
}
+static void ah_input_done(struct crypto_async_request *base, int err)
+{
+ u8 *auth_data;
+ u8 *icv;
+ struct iphdr *work_iph;
+ struct sk_buff *skb = base->data;
+ struct xfrm_state *x = xfrm_input_state(skb);
+ struct ah_data *ahp = x->data;
+ struct ip_auth_hdr *ah = ip_auth_hdr(skb);
+ int ihl = ip_hdrlen(skb);
+ int ah_hlen = (ah->hdrlen + 2) << 2;
+
+ work_iph = AH_SKB_CB(skb)->tmp;
+ auth_data = ah_tmp_auth(work_iph, ihl);
+ icv = ah_tmp_icv(ahp->ahash, auth_data, ahp->icv_trunc_len);
+
+ err = memcmp(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG: 0;
+ if (err)
+ goto out;
+
+ skb->network_header += ah_hlen;
+ memcpy(skb_network_header(skb), work_iph, ihl);
+ __skb_pull(skb, ah_hlen + ihl);
+ skb_set_transport_header(skb, -ihl);
+
+ err = ah->nexthdr;
+out:
+ kfree(AH_SKB_CB(skb)->tmp);
+ xfrm_input_resume(skb, err);
+}
+
static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
{
int ah_hlen;
int ihl;
int nexthdr;
- int err = -EINVAL;
- struct iphdr *iph;
+ int nfrags;
+ u8 *auth_data;
+ u8 *icv;
+ struct sk_buff *trailer;
+ struct crypto_ahash *ahash;
+ struct ahash_request *req;
+ struct scatterlist *sg;
+ struct iphdr *iph, *work_iph;
struct ip_auth_hdr *ah;
struct ah_data *ahp;
- char work_buf[60];
+ int err = -ENOMEM;
if (!pskb_may_pull(skb, sizeof(*ah)))
goto out;
ah = (struct ip_auth_hdr *)skb->data;
ahp = x->data;
+ ahash = ahp->ahash;
+
nexthdr = ah->nexthdr;
ah_hlen = (ah->hdrlen + 2) << 2;
@@ -156,9 +315,24 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
ah = (struct ip_auth_hdr *)skb->data;
iph = ip_hdr(skb);
+ ihl = ip_hdrlen(skb);
+
+ if ((err = skb_cow_data(skb, 0, &trailer)) < 0)
+ goto out;
+ nfrags = err;
+
+ work_iph = ah_alloc_tmp(ahash, nfrags, ihl + ahp->icv_trunc_len);
+ if (!work_iph)
+ goto out;
+
+ auth_data = ah_tmp_auth(work_iph, ihl);
+ icv = ah_tmp_icv(ahash, auth_data, ahp->icv_trunc_len);
+ req = ah_tmp_req(ahash, icv);
+ sg = ah_req_sg(ahash, req);
- ihl = skb->data - skb_network_header(skb);
- memcpy(work_buf, iph, ihl);
+ memcpy(work_iph, iph, ihl);
+ memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
+ memset(ah->auth_data, 0, ahp->icv_trunc_len);
iph->ttl = 0;
iph->tos = 0;
@@ -166,35 +340,44 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
iph->check = 0;
if (ihl > sizeof(*iph)) {
__be32 dummy;
- if (ip_clear_mutable_options(iph, &dummy))
- goto out;
+ err = ip_clear_mutable_options(iph, &dummy);
+ if (err)
+ goto out_free;
}
- spin_lock(&x->lock);
- {
- u8 auth_data[MAX_AH_AUTH_LEN];
+ skb_push(skb, ihl);
- memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
- skb_push(skb, ihl);
- err = ah_mac_digest(ahp, skb, ah->auth_data);
- if (err)
- goto unlock;
- if (memcmp(ahp->work_icv, auth_data, ahp->icv_trunc_len))
- err = -EBADMSG;
+ sg_init_table(sg, nfrags);
+ skb_to_sgvec(skb, sg, 0, skb->len);
+
+ ahash_request_set_crypt(req, sg, icv, skb->len);
+ ahash_request_set_callback(req, 0, ah_input_done, skb);
+
+ AH_SKB_CB(skb)->tmp = work_iph;
+
+ err = crypto_ahash_digest(req);
+ if (err) {
+ if (err == -EINPROGRESS)
+ goto out;
+
+ if (err == -EBUSY)
+ err = NET_XMIT_DROP;
+ goto out_free;
}
-unlock:
- spin_unlock(&x->lock);
+ err = memcmp(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG: 0;
if (err)
- goto out;
+ goto out_free;
skb->network_header += ah_hlen;
- memcpy(skb_network_header(skb), work_buf, ihl);
- skb->transport_header = skb->network_header;
+ memcpy(skb_network_header(skb), work_iph, ihl);
__skb_pull(skb, ah_hlen + ihl);
+ skb_set_transport_header(skb, -ihl);
- return nexthdr;
+ err = nexthdr;
+out_free:
+ kfree (work_iph);
out:
return err;
}
@@ -222,7 +405,7 @@ static int ah_init_state(struct xfrm_state *x)
{
struct ah_data *ahp = NULL;
struct xfrm_algo_desc *aalg_desc;
- struct crypto_hash *tfm;
+ struct crypto_ahash *ahash;
if (!x->aalg)
goto error;
@@ -231,31 +414,31 @@ static int ah_init_state(struct xfrm_state *x)
goto error;
ahp = kzalloc(sizeof(*ahp), GFP_KERNEL);
- if (ahp == NULL)
+ if (!ahp)
return -ENOMEM;
- tfm = crypto_alloc_hash(x->aalg->alg_name, 0, CRYPTO_ALG_ASYNC);
- if (IS_ERR(tfm))
+ ahash = crypto_alloc_ahash(x->aalg->alg_name, 0, 0);
+ if (IS_ERR(ahash))
goto error;
- ahp->tfm = tfm;
- if (crypto_hash_setkey(tfm, x->aalg->alg_key,
- (x->aalg->alg_key_len + 7) / 8))
+ ahp->ahash = ahash;
+ if (crypto_ahash_setkey(ahash, x->aalg->alg_key,
+ (x->aalg->alg_key_len + 7) / 8))
goto error;
/*
* Lookup the algorithm description maintained by xfrm_algo,
* verify crypto transform properties, and store information
* we need for AH processing. This lookup cannot fail here
- * after a successful crypto_alloc_hash().
+ * after a successful crypto_alloc_ahash().
*/
aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0);
BUG_ON(!aalg_desc);
if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
- crypto_hash_digestsize(tfm)) {
+ crypto_ahash_digestsize(ahash)) {
printk(KERN_INFO "AH: %s digestsize %u != %hu\n",
- x->aalg->alg_name, crypto_hash_digestsize(tfm),
+ x->aalg->alg_name, crypto_ahash_digestsize(ahash),
aalg_desc->uinfo.auth.icv_fullbits/8);
goto error;
}
@@ -265,10 +448,6 @@ static int ah_init_state(struct xfrm_state *x)
BUG_ON(ahp->icv_trunc_len > MAX_AH_AUTH_LEN);
- ahp->work_icv = kmalloc(ahp->icv_full_len, GFP_KERNEL);
- if (!ahp->work_icv)
- goto error;
-
x->props.header_len = XFRM_ALIGN8(sizeof(struct ip_auth_hdr) +
ahp->icv_trunc_len);
if (x->props.mode == XFRM_MODE_TUNNEL)
@@ -279,8 +458,7 @@ static int ah_init_state(struct xfrm_state *x)
error:
if (ahp) {
- kfree(ahp->work_icv);
- crypto_free_hash(ahp->tfm);
+ crypto_free_ahash(ahp->ahash);
kfree(ahp);
}
return -EINVAL;
@@ -293,8 +471,7 @@ static void ah_destroy(struct xfrm_state *x)
if (!ahp)
return;
- kfree(ahp->work_icv);
- crypto_free_hash(ahp->tfm);
+ crypto_free_ahash(ahp->ahash);
kfree(ahp);
}
--
1.5.4.2
^ permalink raw reply related
* [PATCH 1/5] ah: Add struct crypto_ahash to ah_data
From: Steffen Klassert @ 2009-10-08 8:47 UTC (permalink / raw)
To: David Miller, Herbert Xu; +Cc: netdev
In-Reply-To: <20091008084631.GJ15653@secunet.com>
To support for ahash algorithms, we add a pointer to a
crypto_ahash to ah_data.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
include/net/ah.h | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/include/net/ah.h b/include/net/ah.h
index ae1c322..7ac5221 100644
--- a/include/net/ah.h
+++ b/include/net/ah.h
@@ -14,6 +14,7 @@ struct ah_data
int icv_trunc_len;
struct crypto_hash *tfm;
+ struct crypto_ahash *ahash;
};
static inline int ah_mac_digest(struct ah_data *ahp, struct sk_buff *skb,
--
1.5.4.2
^ permalink raw reply related
* [PATCH 0/5] IPsec: convert to ahash
From: Steffen Klassert @ 2009-10-08 8:46 UTC (permalink / raw)
To: David Miller, Herbert Xu; +Cc: netdev
This patchset converts the authentication header (ah4/ah6) IPsec protocol
over to the new ahash interface. With this patchset IPsec is completely
converted to ahash. The esp protocol is already converted to ahash by
converting the authenc crypto algorithm.
Steffen
^ permalink raw reply
* [PATCH] Remove nested function
From: Jérôme Pouiller @ 2009-10-08 8:34 UTC (permalink / raw)
To: Grant Likely
Cc: netdev, linuxppc, Andy Fleming, Jérôme Pouiller,
David S. Miller
In-Reply-To: <fa686aa40910070911x769d7d41u908fbcf6b0980962@mail.gmail.com>
Some toolchains dislike nested function definition, so we define function match
outside of of_phy_find_device.
Signed-off-by: Jérôme Pouiller <jezz@sysmic.org>
---
drivers/of/of_mdio.c | 13 +++++++------
1 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c
index bacaa53..4b22ba5 100644
--- a/drivers/of/of_mdio.c
+++ b/drivers/of/of_mdio.c
@@ -97,6 +97,12 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
}
EXPORT_SYMBOL(of_mdiobus_register);
+/* Helper function for of_phy_find_device */
+static int of_phy_match(struct device *dev, void *phy_np)
+{
+ return dev_archdata_get_node(&dev->archdata) == phy_np;
+}
+
/**
* of_phy_find_device - Give a PHY node, find the phy_device
* @phy_np: Pointer to the phy's device tree node
@@ -106,15 +112,10 @@ EXPORT_SYMBOL(of_mdiobus_register);
struct phy_device *of_phy_find_device(struct device_node *phy_np)
{
struct device *d;
- int match(struct device *dev, void *phy_np)
- {
- return dev_archdata_get_node(&dev->archdata) == phy_np;
- }
-
if (!phy_np)
return NULL;
- d = bus_find_device(&mdio_bus_type, NULL, phy_np, match);
+ d = bus_find_device(&mdio_bus_type, NULL, phy_np, of_phy_match);
return d ? to_phy_device(d) : NULL;
}
EXPORT_SYMBOL(of_phy_find_device);
--
1.6.0.4
_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev
^ permalink raw reply related
* Re: [PATCH net-next-2.6] netlink: fix typo in initialization
From: David Miller @ 2009-10-08 8:20 UTC (permalink / raw)
To: jpirko; +Cc: netdev, kaber
In-Reply-To: <20091008080858.GC3255@psychotron.lab.eng.brq.redhat.com>
From: Jiri Pirko <jpirko@redhat.com>
Date: Thu, 8 Oct 2009 10:08:59 +0200
> Thu, Oct 08, 2009 at 09:57:43AM CEST, davem@davemloft.net wrote:
>>From: Jiri Pirko <jpirko@redhat.com>
>>Date: Thu, 8 Oct 2009 09:23:23 +0200
>>
>>Therefore, this fix probably belongs in net-2.6 and -stable instead
>>of net-next-2.6, right?
>
> Okay. The patch is applicable on net-2.6 (I presume on -stable too). Feel free
> to apply.
Great, I'll take care of this, thanks.
^ permalink raw reply
* Re: [PATCH net-next-2.6] netlink: fix typo in initialization
From: Jiri Pirko @ 2009-10-08 8:08 UTC (permalink / raw)
To: David Miller; +Cc: netdev, kaber
In-Reply-To: <20091008.005743.231834593.davem@davemloft.net>
Thu, Oct 08, 2009 at 09:57:43AM CEST, davem@davemloft.net wrote:
>From: Jiri Pirko <jpirko@redhat.com>
>Date: Thu, 8 Oct 2009 09:23:23 +0200
>
>> Commit 9ef1d4c7c7aca1cd436612b6ca785b726ffb8ed8 introduced a typo in
>> initialization. This patch fixes this.
>>
>> Signed-off-by: Jiri Pirko <jpirko@redhat.com>
>
>Doesn't this leak some uninitialized bytes to userspace?
Yes it does.
>
>Therefore, this fix probably belongs in net-2.6 and -stable instead
>of net-next-2.6, right?
Okay. The patch is applicable on net-2.6 (I presume on -stable too). Feel free
to apply.
Thanks.
Jirka
>
>> diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
>> index 6a53694..7cf6c0f 100644
>> --- a/net/sched/cls_api.c
>> +++ b/net/sched/cls_api.c
>> @@ -350,7 +350,7 @@ static int tcf_fill_node(struct sk_buff *skb, struct tcf_proto *tp,
>> tcm = NLMSG_DATA(nlh);
>> tcm->tcm_family = AF_UNSPEC;
>> tcm->tcm__pad1 = 0;
>> - tcm->tcm__pad1 = 0;
>> + tcm->tcm__pad2 = 0;
>> tcm->tcm_ifindex = qdisc_dev(tp->q)->ifindex;
>> tcm->tcm_parent = tp->classid;
>> tcm->tcm_info = TC_H_MAKE(tp->prio, tp->protocol);
^ permalink raw reply
* Re: [PATCH net-next-2.6] netlink: fix typo in initialization
From: David Miller @ 2009-10-08 7:57 UTC (permalink / raw)
To: jpirko; +Cc: netdev, kaber
In-Reply-To: <20091008072323.GA3255@psychotron.lab.eng.brq.redhat.com>
From: Jiri Pirko <jpirko@redhat.com>
Date: Thu, 8 Oct 2009 09:23:23 +0200
> Commit 9ef1d4c7c7aca1cd436612b6ca785b726ffb8ed8 introduced a typo in
> initialization. This patch fixes this.
>
> Signed-off-by: Jiri Pirko <jpirko@redhat.com>
Doesn't this leak some uninitialized bytes to userspace?
Therefore, this fix probably belongs in net-2.6 and -stable instead
of net-next-2.6, right?
> diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
> index 6a53694..7cf6c0f 100644
> --- a/net/sched/cls_api.c
> +++ b/net/sched/cls_api.c
> @@ -350,7 +350,7 @@ static int tcf_fill_node(struct sk_buff *skb, struct tcf_proto *tp,
> tcm = NLMSG_DATA(nlh);
> tcm->tcm_family = AF_UNSPEC;
> tcm->tcm__pad1 = 0;
> - tcm->tcm__pad1 = 0;
> + tcm->tcm__pad2 = 0;
> tcm->tcm_ifindex = qdisc_dev(tp->q)->ifindex;
> tcm->tcm_parent = tp->classid;
> tcm->tcm_info = TC_H_MAKE(tp->prio, tp->protocol);
^ permalink raw reply
* [PATCH net-next-2.6] netlink: fix typo in initialization
From: Jiri Pirko @ 2009-10-08 7:23 UTC (permalink / raw)
To: netdev; +Cc: davem, kaber
Commit 9ef1d4c7c7aca1cd436612b6ca785b726ffb8ed8 introduced a typo in
initialization. This patch fixes this.
Signed-off-by: Jiri Pirko <jpirko@redhat.com>
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 6a53694..7cf6c0f 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -350,7 +350,7 @@ static int tcf_fill_node(struct sk_buff *skb, struct tcf_proto *tp,
tcm = NLMSG_DATA(nlh);
tcm->tcm_family = AF_UNSPEC;
tcm->tcm__pad1 = 0;
- tcm->tcm__pad1 = 0;
+ tcm->tcm__pad2 = 0;
tcm->tcm_ifindex = qdisc_dev(tp->q)->ifindex;
tcm->tcm_parent = tp->classid;
tcm->tcm_info = TC_H_MAKE(tp->prio, tp->protocol);
^ permalink raw reply related
* [RFC] multiqueue changes
From: Eric Dumazet @ 2009-10-08 7:18 UTC (permalink / raw)
To: David S. Miller, Jarek Poplawski, Patrick McHardy; +Cc: Linux Netdev List
Say I have such non multiqueue device :
03:00.0 Ethernet controller: Broadcom Corporation NetXtreme II BCM5708S Gigabit Ethernet (rev 12)
Driver bnx2
This drivers does an alloc_etherdev_mq(sizeof(*bp), TX_MAX_RINGS),
regardless of real capabilities of the NIC.
Then, a bit later it does :
bp->dev->real_num_tx_queues = bp->num_tx_rings;
(one in my non multiqueue case)
Now I have :
# tc -s -d qdisc show dev eth0
qdisc mq 0: root
Sent 117693091 bytes 1542188 pkt (dropped 0, overlimits 0 requeues 0)
backlog 0b 0p requeues 0
# tc -s -d class show dev eth0
class mq :1 root
Sent 113935509 bytes 1492598 pkt (dropped 0, overlimits 0 requeues 0)
backlog 0b 0p requeues 0
class mq :2 root
Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
backlog 0b 0p requeues 0
class mq :3 root
Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
backlog 0b 0p requeues 0
class mq :4 root
Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
backlog 0b 0p requeues 0
class mq :5 root
Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
backlog 0b 0p requeues 0
class mq :6 root
Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
backlog 0b 0p requeues 0
class mq :7 root
Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
backlog 0b 0p requeues 0
class mq :8 root
Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
backlog 0b 0p requeues 0
While in previous kernels I had :
# tc -s -d qdisc show dev eth0
qdisc pfifo_fast 0: root bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
Sent 26292963818 bytes 347139141 pkts (dropped 0, overlimits 0 requeues 0)
# tc -s -d class show dev eth0
So I lost the default pfifo_fast classification.
Just wondering if it could hurt some people.
Anyway, should we change bnx2/tg3 drivers so that single queue devices
have same default qdisc/class than before ?
eg :
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 08cddb6..7cac205 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -6152,6 +6152,7 @@ bnx2_setup_int_mode(struct bnx2 *bp, int dis_msi)
bp->num_tx_rings = rounddown_pow_of_two(bp->irq_nvecs);
bp->dev->real_num_tx_queues = bp->num_tx_rings;
+ bp->dev->num_tx_queues = bp->dev->real_num_tx_queues;
bp->num_rx_rings = bp->irq_nvecs;
}
^ permalink raw reply related
* Re: [PATCH] net: Add netdev_alloc_skb_ip_align() helper
From: David Miller @ 2009-10-08 5:40 UTC (permalink / raw)
To: eric.dumazet; +Cc: thomas, netdev, thierry.reding, nios2-dev, linux-kernel
In-Reply-To: <4ACD585B.5080106@gmail.com>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Thu, 08 Oct 2009 05:11:23 +0200
> David, maybe we should add following helper :
>
> [PATCH] net: Add netdev_alloc_skb_ip_align() helper
>
> Instead of hardcoding NET_IP_ALIGN stuff in various network drivers, we can
> add a helper around netdev_alloc_skb()
>
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Looks ok, but I want to look at how often this exact sequence
would match. If it applies to a lot of cases, I'll add this
but I know of many exceptions in my head already :-)
^ permalink raw reply
* Re: [PATCH] Add sk_mark route lookup support for IPv4 listening sockets, and for IPv4 multicast forwarding
From: David Miller @ 2009-10-08 5:39 UTC (permalink / raw)
To: zenczykowski; +Cc: atis, netdev, panther, eric.dumazet, brian.haley
In-Reply-To: <55a4f86e0910071703i4735f1aan1ddba81eec7eef19@mail.gmail.com>
From: Maciej Żenczykowski <zenczykowski@gmail.com>
Date: Wed, 7 Oct 2009 17:03:30 -0700
> Should wrapping a packet into a tunnel clear the mark?
> Should perhaps the mark be a parameter of the tunnel (like ttl or qos,
> can be set or can be inherited)?
That's the big question.
It may be that the only logical thing we can do is only apply
the socket mark to the top-level path and that's what happens
now.
Because we really don't have any reasonable way to let the user
control where it applies. We have no way for it to say "don't
apply the mark to the top-level path, but do apply it to the
multicast tunnel' or something like that.
So, to be honest, I'd say we should skip these skb->mark cases
for now.
^ permalink raw reply
* Re: [BUG] znet.c sleeping function called from invalid context
From: David Miller @ 2009-10-08 5:15 UTC (permalink / raw)
To: vapier.adi-Re5JQEeQqe8AvxtiuMwx3w
Cc: netdev-u79uwXL29TY76Z2rM5mHXA, strakh-ufN2psIa012HXe+LvDLADg,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
michael.hennerich-OyLXuOCK7orQT0dZR+AlfA,
uclinux-dist-devel-ZG0+EudsQA8dtHy/vicBwGD2FQJk+8+b
In-Reply-To: <8bd0f97a0910071144k1d0bf30bv60656181edae8af7-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
From: Mike Frysinger <vapier.adi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Date: Wed, 7 Oct 2009 14:44:45 -0400
> On Wed, Oct 7, 2009 at 14:47, Alexander Strakh wrote:
>> KERNEL_VERSION: 2.6.31
>> DESCRIBE:
>> Driver drivers/net/znet.c might sleep in atomic context, because it calls
>> free_dma under claim_dma_lock:
>>
>> .drivers/net/znet.c:
>> 168 static int znet_request_resources (struct net_device *dev)
>> ...
>> 189 flags = claim_dma_lock();
>> 190 free_dma (znet->tx_dma);
>> 191 release_dma_lock (flags);
>> ...
>>
>> Path to might_sleep macro from znet_request_resources:
>> 1. znet_request_resources calls free_dma at
>> arch/blackfin/kernel/bfin_dma_5xx.c:181
>> 2. free_dma calls arch/blackfin/kernel/bfin_dma_5xx.c:195
>
> i dont think we need the dmalock mutex. it's only used to protect
> read/writes to .chan_status, and that should be atomic already.
> -mike
I'm checking in the obvious fix to net-2.6, thanks for the report:
znet: Don't claim DMA lock around free_dma() calls.
It's not necessary and it's illegal too.
Reported-by: Alexander Strakh <strakh-ufN2psIa012HXe+LvDLADg@public.gmane.org>
Signed-off-by: David S. Miller <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
---
drivers/net/znet.c | 8 --------
1 files changed, 0 insertions(+), 8 deletions(-)
diff --git a/drivers/net/znet.c b/drivers/net/znet.c
index a0384b6..b423473 100644
--- a/drivers/net/znet.c
+++ b/drivers/net/znet.c
@@ -169,7 +169,6 @@ static void znet_tx_timeout (struct net_device *dev);
static int znet_request_resources (struct net_device *dev)
{
struct znet_private *znet = netdev_priv(dev);
- unsigned long flags;
if (request_irq (dev->irq, &znet_interrupt, 0, "ZNet", dev))
goto failed;
@@ -187,13 +186,9 @@ static int znet_request_resources (struct net_device *dev)
free_sia:
release_region (znet->sia_base, znet->sia_size);
free_tx_dma:
- flags = claim_dma_lock();
free_dma (znet->tx_dma);
- release_dma_lock (flags);
free_rx_dma:
- flags = claim_dma_lock();
free_dma (znet->rx_dma);
- release_dma_lock (flags);
free_irq:
free_irq (dev->irq, dev);
failed:
@@ -203,14 +198,11 @@ static int znet_request_resources (struct net_device *dev)
static void znet_release_resources (struct net_device *dev)
{
struct znet_private *znet = netdev_priv(dev);
- unsigned long flags;
release_region (znet->sia_base, znet->sia_size);
release_region (dev->base_addr, znet->io_size);
- flags = claim_dma_lock();
free_dma (znet->tx_dma);
free_dma (znet->rx_dma);
- release_dma_lock (flags);
free_irq (dev->irq, dev);
}
--
1.6.4.4
^ permalink raw reply related
* Re: [net-next-2.6 PATCH V3] can: add TI CAN (HECC) driver
From: David Miller @ 2009-10-08 5:03 UTC (permalink / raw)
To: anantgole; +Cc: netdev, socketcan-core, linux-arm-kernel
In-Reply-To: <1254920387-20939-1-git-send-email-anantgole@ti.com>
From: Anant Gole <anantgole@ti.com>
Date: Wed, 7 Oct 2009 18:29:47 +0530
> TI HECC (High End CAN Controller) module is found on many TI devices. It
> has 32 hardware mailboxes with full implementation of CAN protocol 2.0B
> with bus speeds up to 1Mbps. Specifications of the module are available
> on TI web <http://www.ti.com>
>
> Signed-off-by: Anant Gole <anantgole@ti.com>
Applied, thanks.
^ permalink raw reply
* Re: [PATCH] bridge: Allow enable/disable UFO on bridge device via ethtool
From: David Miller @ 2009-10-08 5:01 UTC (permalink / raw)
To: sri; +Cc: netdev
In-Reply-To: <1254955277.31575.208.camel@w-sridhar.beaverton.ibm.com>
From: Sridhar Samudrala <sri@us.ibm.com>
Date: Wed, 07 Oct 2009 15:41:17 -0700
> Allow enable/disable UFO on bridge device via ethtool
>
> Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>
Applied.
^ permalink raw reply
* Re: [PATCH] net: Make UFO on master device independent of attached devices
From: David Miller @ 2009-10-08 5:01 UTC (permalink / raw)
To: sri; +Cc: herbert, netdev
In-Reply-To: <1254954265.31575.191.camel@w-sridhar.beaverton.ibm.com>
From: Sridhar Samudrala <sri@us.ibm.com>
Date: Wed, 07 Oct 2009 15:24:25 -0700
> Now that software UFO is supported, UFO can be enabled on master
> devices like bridge, bond even though the attached device doesn't
> support this feature in hardware.
>
> This allows UFO to be used between KVM host and guest even when a
> physical interface attached to the bridge doesn't support UFO.
>
> Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>
Applied.
^ permalink raw reply
* Re: [PATCH net-next-2.6 0/8] Get rid of net_device_stats from adapter.
From: David Miller @ 2009-10-08 5:01 UTC (permalink / raw)
To: ajitk, ajitkhaparde; +Cc: netdev
In-Reply-To: <20091007124129.GA29781@serverengines.com>
From: Ajit Khaparde <ajitkhaparde@gmail.com>
Date: Wed, 7 Oct 2009 18:11:40 +0530
> Since net_device already has an instance of net_device stats,
> its not necessary for the drivers to maintain their own copy
> in their private adapter structure.
> This patch series takes care of this for some of the drivers.
> I have compiled them all in my setup.
> And not all of them have been tested. :-)
All applied, thanks!
^ permalink raw reply
* Re: [PATCH net-next-2.6] udp: dynamically size hash tables at boot time
From: David Miller @ 2009-10-08 5:01 UTC (permalink / raw)
To: eric.dumazet; +Cc: rick.jones2, netdev
In-Reply-To: <4ACC6F87.1050306@gmail.com>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Wed, 07 Oct 2009 12:37:59 +0200
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Applied.
^ permalink raw reply
* Re: [PATCH] net: Add netdev_alloc_skb_ip_align() helper
From: Thomas Chou @ 2009-10-08 4:36 UTC (permalink / raw)
To: Eric Dumazet
Cc: netdev, thierry.reding, Nios2 development list, linux-kernel,
David S. Miller
In-Reply-To: <4ACD585B.5080106@gmail.com>
On 10/08/2009 11:11 AM, Eric Dumazet wrote:
> Thomas Chou a écrit :
> You should do :
>
> size -= 4; /* strip the CRC */
> skb = netdev_alloc_skb(dev, size + NET_IP_ALIGN);
> if (skb) {
> skb_reserve(skb, NET_IP_ALIGN);
> ...
> }
>
>
> Please check other implementations...
>
> David, maybe we should add following helper :
>
> [PATCH] net: Add netdev_alloc_skb_ip_align() helper
Hi Eric,
Thanks for the suggestion. I will follow your commit and send revised patch.
- Thomas
^ permalink raw reply
* [PATCH] net: Add netdev_alloc_skb_ip_align() helper
From: Eric Dumazet @ 2009-10-08 3:11 UTC (permalink / raw)
To: Thomas Chou
Cc: netdev, thierry.reding, Nios2 development list, linux-kernel,
David S. Miller
In-Reply-To: <1254969161-3609-1-git-send-email-thomas@wytron.com.tw>
Thomas Chou a écrit :
> As suggested by Stephen Hemminger.
>
> Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
> ---
> drivers/net/ethoc.c | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
> index ecc53d9..4a1ed81 100644
> --- a/drivers/net/ethoc.c
> +++ b/drivers/net/ethoc.c
> @@ -409,7 +409,7 @@ static int ethoc_rx(struct net_device *dev, int limit)
> struct sk_buff *skb = netdev_alloc_skb(dev, size);
>
> size -= 4; /* strip the CRC */
> - skb_reserve(skb, 2); /* align TCP/IP header */
> + skb_reserve(skb, NET_IP_ALIGN);
>
> if (likely(skb)) {
> void *src = phys_to_virt(bd.addr);
Sorry to be dense here, but this code breaks if NET_IP_ALIGN > 4.
Its also suboptimal, you alloc two bytes in excess.
You should do :
size -= 4; /* strip the CRC */
skb = netdev_alloc_skb(dev, size + NET_IP_ALIGN);
if (skb) {
skb_reserve(skb, NET_IP_ALIGN);
...
}
Please check other implementations...
David, maybe we should add following helper :
[PATCH] net: Add netdev_alloc_skb_ip_align() helper
Instead of hardcoding NET_IP_ALIGN stuff in various network drivers, we can
add a helper around netdev_alloc_skb()
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index df7b23a..fed788e 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1489,6 +1489,16 @@ static inline struct sk_buff *netdev_alloc_skb(struct net_device *dev,
return __netdev_alloc_skb(dev, length, GFP_ATOMIC);
}
+static inline struct sk_buff *netdev_alloc_skb_ip_align(struct net_device *dev,
+ unsigned int length)
+{
+ struct sk_buff *skb = netdev_alloc_skb(dev, length + NET_IP_ALIGN);
+
+ if (NET_IP_ALIGN && skb)
+ skb_reserve(skb, NET_IP_ALIGN);
+ return skb;
+}
+
extern struct page *__netdev_alloc_page(struct net_device *dev, gfp_t gfp_mask);
/**
^ permalink raw reply related
* Re: [PATCH 3/4] ethoc: align received packet to make IP header at word boundary
From: Thomas Chou @ 2009-10-08 2:42 UTC (permalink / raw)
To: David Miller; +Cc: shemminger, netdev
In-Reply-To: <20091007.135217.73491149.davem@davemloft.net>
On 10/08/2009 04:52 AM, David Miller wrote:
> From: Stephen Hemminger<shemminger@vyatta.com>
> Date: Wed, 7 Oct 2009 09:13:37 -0700
>
>> On Mon, 5 Oct 2009 17:33:19 +0800
>> Thomas Chou<thomas@wytron.com.tw> wrote:
>>
>>> diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
>>> index f92747f..0c6c7f4 100644
>>> --- a/drivers/net/ethoc.c
>>> +++ b/drivers/net/ethoc.c
>>> @@ -399,6 +399,10 @@ static int ethoc_rx(struct net_device *dev, int limit)
>>> if (ethoc_update_rx_stats(priv,&bd) == 0) {
>>> int size = bd.stat>> 16;
>>> struct sk_buff *skb = netdev_alloc_skb(dev, size);
>>> +
>>> + size -= 4; /* strip the CRC */
>>> + skb_reserve(skb, 2); /* align TCP/IP header */
>>
>> Please use NET_IP_ALIGN rather than hard coding 2 so that the value
>> can be changed on a per-cpu architecture basis if desired.
>
> Indeed.
>
> Thomas please send a patch to fix this up, thanks.
>
>
Submitted. Thanks.
- Thomas
^ permalink raw reply
* [PATCH] ethoc: use NET_IP_ALIGN in skb_reserve()
From: Thomas Chou @ 2009-10-08 2:32 UTC (permalink / raw)
To: netdev; +Cc: thierry.reding, Nios2 development list, linux-kernel, Thomas Chou
As suggested by Stephen Hemminger.
Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
---
drivers/net/ethoc.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index ecc53d9..4a1ed81 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -409,7 +409,7 @@ static int ethoc_rx(struct net_device *dev, int limit)
struct sk_buff *skb = netdev_alloc_skb(dev, size);
size -= 4; /* strip the CRC */
- skb_reserve(skb, 2); /* align TCP/IP header */
+ skb_reserve(skb, NET_IP_ALIGN);
if (likely(skb)) {
void *src = phys_to_virt(bd.addr);
--
1.6.2.5
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox