* Re: [UDP6]: Restore sk_filter optimisation
From: Herbert Xu @ 2007-10-31 14:42 UTC (permalink / raw)
To: Mitsuru Chinen; +Cc: David S. Miller, netdev, YOSHIFUJI Hideaki
In-Reply-To: <20071031230545.9be711d4.mitch@linux.vnet.ibm.com>
On Wed, Oct 31, 2007 at 11:05:45PM +0900, Mitsuru Chinen wrote:
>
> > > 1. udp6InDatagrams is incremented instead of udpInErrors
> > > 2. In userland, recvfrom() replies an error with EAGAIN.
> > > recvfrom() wasn't aware of such a packet before.
> > >
> > > Are these changes intentional?
>
> As far as I tested, this doesn't happen with the old code even if
> a filter is attached. However, this happen with the new code
> without a filter and I don't see this rather when a filter is
> attached. So, I'm afraid it's new.
Sorry, I read the patch the wrong way around :)
1) is just an accounting issue. It shouldn't be too difficult
to fix it up. In fact, I think udpInErrors will still be
incremented once we detect the error.
2) shouldn't be an issue because we've already solved the
problem by making poll/select do the checksum verification
before indiciating that the socket is readable.
> > And, we're not sure how much the "optimization"'s benefit is.
> > It is even worse when we are hand
The checksum verification is costly because we have to bring
the payload into cache. Since filters are very rare it's
worthwhile to postpone the checksum verification for the common
case.
Also as a general rule, we want to avoid divergent behaviour
between IPv4 and IPv6. So for changes like this we should
really modify both stacks in future rather than have each
stack do its own thing.
Thanks,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* Re: [PATCH 00/33] Swap over NFS -v14
From: Mike Snitzer @ 2007-10-31 14:54 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Christoph Hellwig, David Miller, nickpiggin, torvalds, akpm,
linux-kernel, linux-mm, netdev, trond.myklebust, Evgeniy Polyakov
In-Reply-To: <1193828206.27652.145.camel@twins>
On 10/31/07, Peter Zijlstra <a.p.zijlstra@chello.nl> wrote:
> On Wed, 2007-10-31 at 08:50 +0000, Christoph Hellwig wrote:
> > On Tue, Oct 30, 2007 at 09:37:53PM -0700, David Miller wrote:
> > > Don't be misled. Swapping over NFS is just a scarecrow for the
> > > seemingly real impetus behind these changes which is network storage
> > > stuff like iSCSI.
> >
> > So can we please do swap over network storage only first? All these
> > VM bits look conceptually sane to me, while the changes to the swap
> > code to support nfs are real crackpipe material.
>
> Yeah, I know how you stand on that. I just wanted to post all this
> before going off into the woods reworking it all.
...
> > So please get the VM bits for swap over network blockdevices in first,
>
> Trouble with that part is that we don't have any sane network block
> devices atm, NBD is utter crap, and iSCSI is too complex to be called
> sane.
>
> Maybe Evgeniy's Distributed storage thingy would work, will have a look
> at that.
Andrew recently asked Evgeniy if his DST was ready for merging; to
which Evgeniy basically said yes:
http://lkml.org/lkml/2007/10/27/54
It would be great if DST could be merged; whereby addressing the fact
that NBD is lacking for net-vm. If DST were scrutinized in the
context of net-vm it should help it get the review that is needed for
merging.
Mike
^ permalink raw reply
* Re: [PATCH][RFC] Add support for the RDC R6040 Fast Ethernet controller
From: Stephen Hemminger @ 2007-10-31 16:07 UTC (permalink / raw)
To: Florian Fainelli; +Cc: netdev
In-Reply-To: <200710292251.43257.florian.fainelli@telecomint.eu>
On Mon, 29 Oct 2007 22:51:42 +0100
Florian Fainelli <florian.fainelli@telecomint.eu> wrote:
> This patch adds support for the RDC R6040 MAC we can find in the RDC R-321x System-on-chips.
> This driver really needs improvements especially on the NAPI part which probably does not
> fully use the new NAPI structure.
> You will need the RDC PCI identifiers if you want to test this driver which are the following ones :
>
> RDC_PCI_VENDOR_ID = 0x17f3
> RDC_PCI_DEVICE_ID_RDC_R6040 = 0x6040
>
> Thank you very much in advance for your comments.
>
> Signed-off-by: Sten Wang <sten.wang@rdc.com.tw>
> Signed-off-by: Daniel Gimpelevich <daniel@gimpelevich.san-francisco.ca.us>
> Signed-off-by: Florian Fainelli <florian.fainelli@telecomint.eu>
**** BUG *** Don't call kfree() to free the network device; use free_netdev()
* Don't define use uppercase for variable names (NUM_MAC_TABLE)
* Use get_random_ether_addr() rather than a hardcoded table of mac addresses.
* checkpatch complains about some extra blanks, and several lines > 80 chars.
* use ethtool stubs for check_link
* add ethtool get_settings to allow use by bonding/bridging, etc.
* this is unusual coding style:
+ do {} while ((i++ < 2048) && (inw(ioaddr + 0x04) & 0x1));
* add a blank line after declarations and before code in a function
* use of global NAPI_status should be replaced by putting it in priv
* the handling of shared IRQ is wrong.
- need to check for status == 0 || status == 0xffff and return IRQ_NONE
* don't call napi_disable() with irq's disabled in r6040_close
* poll routine shouldn't call dev_kfree_skb_irq() to free Tx buffers because
that means going through TX softirq, just call dev_kfree_skb()
* the down routine calls pci_unmap_single with wrong length when handling
TX buffers.
* pci id table can be cleaned up:
static struct pci_device_id r6040_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_RDC, 0x6040) },
{ PCI_DEVICE(PCI_VENDOR_VIA, 0x3065) },
{ 0 }
};
* use netdev_priv() consistently rather than dev->priv.
Yes they are the same now, but that will be fixed in future.
* eliminate check for dev being NULL in IRQ handler.
* reorder functions to eliminate need for forward declarations
* get rid of R6040_PCI_CMD and pci_flags field it is unused.
* do you really have to have the whole chip_info at all? The only usage
seems to be to validate the pci region size. Do you have platforms with
busted BIOS that set it wrong or something??
---
WARNING: no space between function name and open parenthesis '('
#1071: FILE: drivers/net/r6040.c:958:
+static int __init r6040_init (void)
WARNING: no space between function name and open parenthesis '('
#1073: FILE: drivers/net/r6040.c:960:
+ return pci_register_driver (&r6040_driver);
WARNING: no space between function name and open parenthesis '('
#1077: FILE: drivers/net/r6040.c:964:
+static void __exit r6040_cleanup (void)
WARNING: no space between function name and open parenthesis '('
#1079: FILE: drivers/net/r6040.c:966:
+ pci_unregister_driver (&r6040_driver);
total: 0 errors, 36 warnings, 1001 lines checked
Your patch has style problems, please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
^ permalink raw reply
* Re: [PATCH 2/2] NFS: handle IPv6 addresses in nfs ctl
From: J. Bruce Fields @ 2007-10-31 16:20 UTC (permalink / raw)
To: Aurélien Charbon; +Cc: netdev ML, Brian Haley, Mailing list NFSv4
In-Reply-To: <4728458A.4040102@ext.bull.net>
On Wed, Oct 31, 2007 at 10:06:18AM +0100, Aurélien Charbon wrote:
> Thank you Brian
> Sorry, I did not see what you sent.
>
> I have tested it with an IPv4 configuration. It's OK.
> So Neil, Bruce, you can take this one for review.
Did you miss Neil's question about the nfsctl stuff? (Do we really need
that, or would the changes to the ip_map cache be sufficient?)--b.
>
> fs/nfsd/export.c | 9 ++-
> fs/nfsd/nfsctl.c | 42 ++++++++++++--
> include/linux/sunrpc/svcauth.h | 5 +
> include/net/ipv6.h | 10 +++
> net/sunrpc/svcauth_unix.c | 118
> +++++++++++++++++++++++++++--------------
> 5 files changed, 134 insertions(+), 50 deletions(-)
>
> Signed-off-by: Brian Haley <brian.haley@hp.com>
> Signed-off-by: Aurelien Charbon <aurelien.charbon@bull.net>
>
> ---
>
> diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
> index 66d0aeb..c47ba77 100644
> --- a/fs/nfsd/export.c
> +++ b/fs/nfsd/export.c
> @@ -35,6 +35,7 @@
> #include <linux/lockd/bind.h>
> #include <linux/sunrpc/msg_prot.h>
> #include <linux/sunrpc/gss_api.h>
> +#include <net/ipv6.h>
> #define NFSDDBG_FACILITY NFSDDBG_EXPORT
> @@ -1556,6 +1557,7 @@ exp_addclient(struct nfsctl_client *ncp)
> {
> struct auth_domain *dom;
> int i, err;
> + struct in6_addr in6;
> /* First, consistency check. */
> err = -EINVAL;
> @@ -1574,9 +1576,10 @@ exp_addclient(struct nfsctl_client *ncp)
> goto out_unlock;
> /* Insert client into hashtable. */
> - for (i = 0; i < ncp->cl_naddr; i++)
> - auth_unix_add_addr(ncp->cl_addrlist[i], dom);
> -
> + for (i = 0; i < ncp->cl_naddr; i++) {
> + ipv6_addr_set_v4mapped(ncp->cl_addrlist[i].s_addr, &in6);
> + auth_unix_add_addr(&in6, dom);
> + }
> auth_unix_forget_old(dom);
> auth_domain_put(dom);
> diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
> index 77dc989..5cb5f0d 100644
> --- a/fs/nfsd/nfsctl.c
> +++ b/fs/nfsd/nfsctl.c
> @@ -37,6 +37,7 @@
> #include <linux/nfsd/syscall.h>
> #include <asm/uaccess.h>
> +#include <net/ipv6.h>
> /*
> * We have a single directory with 9 nodes in it.
> @@ -219,24 +220,37 @@ static ssize_t write_getfs(struct file *file, char
> *buf, size_t size)
> {
> struct nfsctl_fsparm *data;
> struct sockaddr_in *sin;
> + struct sockaddr_in6 *sin6;
> struct auth_domain *clp;
> int err = 0;
> struct knfsd_fh *res;
> + struct in6_addr in6;
> if (size < sizeof(*data))
> return -EINVAL;
> data = (struct nfsctl_fsparm*)buf;
> err = -EPROTONOSUPPORT;
> - if (data->gd_addr.sa_family != AF_INET)
> + switch (data->gd_addr.sa_family) {
> + case AF_INET:
> + sin = (struct sockaddr_in *)&data->gd_addr;
> + ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6);
> + break;
> + case AF_INET6:
> + sin6 = (struct sockaddr_in6 *)&data->gd_addr;
> + ipv6_addr_copy(&in6, &sin6->sin6_addr);
> + break;
> + default:
> goto out;
> - sin = (struct sockaddr_in *)&data->gd_addr;
> + }
> +
> if (data->gd_maxlen > NFS3_FHSIZE)
> data->gd_maxlen = NFS3_FHSIZE;
> res = (struct knfsd_fh*)buf;
> exp_readlock();
> - if (!(clp = auth_unix_lookup(sin->sin_addr)))
> +
> + if (!(clp = auth_unix_lookup(&in6)))
> err = -EPERM;
> else {
> err = exp_rootfh(clp, data->gd_path, res, data->gd_maxlen);
> @@ -253,25 +267,41 @@ static ssize_t write_getfd(struct file *file, char
> *buf, size_t size)
> {
> struct nfsctl_fdparm *data;
> struct sockaddr_in *sin;
> + struct sockaddr_in6 *sin6;
> struct auth_domain *clp;
> int err = 0;
> struct knfsd_fh fh;
> char *res;
> + struct in6_addr in6;
> if (size < sizeof(*data))
> return -EINVAL;
> data = (struct nfsctl_fdparm*)buf;
> err = -EPROTONOSUPPORT;
> - if (data->gd_addr.sa_family != AF_INET)
> + if (data->gd_addr.sa_family != AF_INET &&
> + data->gd_addr.sa_family != AF_INET6)
> goto out;
> err = -EINVAL;
> if (data->gd_version < 2 || data->gd_version > NFSSVC_MAXVERS)
> goto out;
> res = buf;
> - sin = (struct sockaddr_in *)&data->gd_addr;
> exp_readlock();
> - if (!(clp = auth_unix_lookup(sin->sin_addr)))
> +
> + switch (data->gd_addr.sa_family) {
> + case AF_INET:
> + sin = (struct sockaddr_in *)&data->gd_addr;
> + ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6);
> + break;
> + case AF_INET6:
> + sin6 = (struct sockaddr_in6 *)&data->gd_addr;
> + ipv6_addr_copy(&in6, &sin6->sin6_addr);
> + break;
> + default:
> + goto out;
> + }
> +
> + if (!(clp = auth_unix_lookup(&in6)))
> err = -EPERM;
> else {
> err = exp_rootfh(clp, data->gd_path, &fh, NFS_FHSIZE);
> diff --git a/include/linux/sunrpc/svcauth.h
> b/include/linux/sunrpc/svcauth.h
> index 22e1ef8..64ecb93 100644
> --- a/include/linux/sunrpc/svcauth.h
> +++ b/include/linux/sunrpc/svcauth.h
> @@ -15,6 +15,7 @@
> #include <linux/sunrpc/msg_prot.h>
> #include <linux/sunrpc/cache.h>
> #include <linux/hash.h>
> +#include <net/ipv6.h>
> #define SVC_CRED_NGROUPS 32
> struct svc_cred {
> @@ -120,10 +121,10 @@ extern void svc_auth_unregister(rpc_authflavor_t
> flavor);
> extern struct auth_domain *unix_domain_find(char *name);
> extern void auth_domain_put(struct auth_domain *item);
> -extern int auth_unix_add_addr(struct in_addr addr, struct auth_domain
> *dom);
> +extern int auth_unix_add_addr(struct in6_addr *addr, struct auth_domain
> *dom);
> extern struct auth_domain *auth_domain_lookup(char *name, struct
> auth_domain *new);
> extern struct auth_domain *auth_domain_find(char *name);
> -extern struct auth_domain *auth_unix_lookup(struct in_addr addr);
> +extern struct auth_domain *auth_unix_lookup(struct in6_addr *addr);
> extern int auth_unix_forget_old(struct auth_domain *dom);
> extern void svcauth_unix_purge(void);
> extern void svcauth_unix_info_release(void *);
> diff --git a/include/net/ipv6.h b/include/net/ipv6.h
> index ae328b6..366fdca 100644
> --- a/include/net/ipv6.h
> +++ b/include/net/ipv6.h
> @@ -16,6 +16,7 @@
> #define _NET_IPV6_H
> #include <linux/ipv6.h>
> +#include <linux/in.h>
> #include <linux/hardirq.h>
> #include <net/if_inet6.h>
> #include <net/ndisc.h>
> @@ -400,6 +401,15 @@ static inline int ipv6_addr_v4mapped(const struct
> in6_addr *a)
> a->s6_addr32[2] == htonl(0x0000ffff));
> }
> +static inline void ipv6_addr_set_v4mapped(const __be32 addr,
> + struct in6_addr *v4mapped)
> +{
> + ipv6_addr_set(v4mapped,
> + 0, 0,
> + __constant_htonl(0x0000FFFF),
> + addr);
> +}
> +
> /*
> * find the first different bit between two addresses
> * length of address must be a multiple of 32bits
> diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
> index 4114794..a40d769 100644
> --- a/net/sunrpc/svcauth_unix.c
> +++ b/net/sunrpc/svcauth_unix.c
> @@ -11,6 +11,7 @@
> #include <linux/hash.h>
> #include <linux/string.h>
> #include <net/sock.h>
> +#include <net/ipv6.h>
> #define RPCDBG_FACILITY RPCDBG_AUTH
> @@ -84,7 +85,7 @@ static void svcauth_unix_domain_release(struct
> auth_domain *dom)
> struct ip_map {
> struct cache_head h;
> char m_class[8]; /* e.g. "nfsd" */
> - struct in_addr m_addr;
> + struct in6_addr m_addr;
> struct unix_domain *m_client;
> int m_add_change;
> };
> @@ -101,7 +102,6 @@ static void ip_map_put(struct kref *kref)
> kfree(im);
> }
> -#if IP_HASHBITS == 8
> /* hash_long on a 64 bit machine is currently REALLY BAD for
> * IP addresses in reverse-endian (i.e. on a little-endian machine).
> * So use a trivial but reliable hash instead
> @@ -111,13 +111,20 @@ static inline int hash_ip(__be32 ip)
> int hash = (__force u32)ip ^ ((__force u32)ip>>16);
> return (hash ^ (hash>>8)) & 0xff;
> }
> -#endif
> +
> +static inline int hash_ip6(struct in6_addr *ip6)
> +{
> + return (hash_ip(ip6->s6_addr32[0]) ^
> + hash_ip(ip6->s6_addr32[1]) ^
> + hash_ip(ip6->s6_addr32[2]) ^
> + hash_ip(ip6->s6_addr32[3]));
> +}
> static int ip_map_match(struct cache_head *corig, struct cache_head *cnew)
> {
> struct ip_map *orig = container_of(corig, struct ip_map, h);
> struct ip_map *new = container_of(cnew, struct ip_map, h);
> return strcmp(orig->m_class, new->m_class) == 0
> - && orig->m_addr.s_addr == new->m_addr.s_addr;
> + && ipv6_addr_equal(&orig->m_addr, &new->m_addr);
> }
> static void ip_map_init(struct cache_head *cnew, struct cache_head *citem)
> {
> @@ -125,7 +132,7 @@ static void ip_map_init(struct cache_head *cnew, struct
> cache_head *citem)
> struct ip_map *item = container_of(citem, struct ip_map, h);
> strcpy(new->m_class, item->m_class);
> - new->m_addr.s_addr = item->m_addr.s_addr;
> + ipv6_addr_copy(&new->m_addr, &item->m_addr);
> }
> static void update(struct cache_head *cnew, struct cache_head *citem)
> {
> @@ -149,22 +156,24 @@ static void ip_map_request(struct cache_detail *cd,
> struct cache_head *h,
> char **bpp, int *blen)
> {
> - char text_addr[20];
> + char text_addr[40];
> struct ip_map *im = container_of(h, struct ip_map, h);
> - __be32 addr = im->m_addr.s_addr;
> -
> - snprintf(text_addr, 20, "%u.%u.%u.%u",
> - ntohl(addr) >> 24 & 0xff,
> - ntohl(addr) >> 16 & 0xff,
> - ntohl(addr) >> 8 & 0xff,
> - ntohl(addr) >> 0 & 0xff);
> + if (ipv6_addr_v4mapped(&(im->m_addr))) {
> + snprintf(text_addr, 20, NIPQUAD_FMT,
> + ntohl(im->m_addr.s6_addr32[3]) >> 24 & 0xff,
> + ntohl(im->m_addr.s6_addr32[3]) >> 16 & 0xff,
> + ntohl(im->m_addr.s6_addr32[3]) >> 8 & 0xff,
> + ntohl(im->m_addr.s6_addr32[3]) >> 0 & 0xff);
> + } else {
> + snprintf(text_addr, 40, NIP6_FMT, NIP6(im->m_addr));
> + }
> qword_add(bpp, blen, im->m_class);
> qword_add(bpp, blen, text_addr);
> (*bpp)[-1] = '\n';
> }
> -static struct ip_map *ip_map_lookup(char *class, struct in_addr addr);
> +static struct ip_map *ip_map_lookup(char *class, struct in6_addr *addr);
> static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom,
> time_t expiry);
> static int ip_map_parse(struct cache_detail *cd,
> @@ -175,10 +184,10 @@ static int ip_map_parse(struct cache_detail *cd,
> * for scratch: */
> char *buf = mesg;
> int len;
> - int b1,b2,b3,b4;
> + int b1, b2, b3, b4, b5, b6, b7, b8;
> char c;
> char class[8];
> - struct in_addr addr;
> + struct in6_addr addr6;
> int err;
> struct ip_map *ipmp;
> @@ -197,7 +206,23 @@ static int ip_map_parse(struct cache_detail *cd,
> len = qword_get(&mesg, buf, mlen);
> if (len <= 0) return -EINVAL;
> - if (sscanf(buf, "%u.%u.%u.%u%c", &b1, &b2, &b3, &b4, &c) != 4)
> + if (sscanf(buf, NIPQUAD_FMT "%c", &b1, &b2, &b3, &b4, &c) == 4) {
> + addr6.s6_addr32[0] = 0;
> + addr6.s6_addr32[1] = 0;
> + addr6.s6_addr32[2] = htonl(0xffff);
> + addr6.s6_addr32[3] =
> + htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
> + } else if (sscanf(buf, NIP6_FMT "%c",
> + &b1, &b2, &b3, &b4, &b5, &b6, &b7, &b8, &c) == 8) {
> + addr6.s6_addr16[0] = htons(b1);
> + addr6.s6_addr16[1] = htons(b2);
> + addr6.s6_addr16[2] = htons(b3);
> + addr6.s6_addr16[3] = htons(b4);
> + addr6.s6_addr16[4] = htons(b5);
> + addr6.s6_addr16[5] = htons(b6);
> + addr6.s6_addr16[6] = htons(b7);
> + addr6.s6_addr16[7] = htons(b8);
> + } else
> return -EINVAL;
> expiry = get_expiry(&mesg);
> @@ -215,10 +240,7 @@ static int ip_map_parse(struct cache_detail *cd,
> } else
> dom = NULL;
> - addr.s_addr =
> - htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
> -
> - ipmp = ip_map_lookup(class,addr);
> + ipmp = ip_map_lookup(class, &addr6);
> if (ipmp) {
> err = ip_map_update(ipmp,
> container_of(dom, struct unix_domain, h),
> @@ -238,7 +260,7 @@ static int ip_map_show(struct seq_file *m,
> struct cache_head *h)
> {
> struct ip_map *im;
> - struct in_addr addr;
> + struct in6_addr addr6;
> char *dom = "-no-domain-";
> if (h == NULL) {
> @@ -247,20 +269,24 @@ static int ip_map_show(struct seq_file *m,
> }
> im = container_of(h, struct ip_map, h);
> /* class addr domain */
> - addr = im->m_addr;
> + ipv6_addr_copy(&addr6, &im->m_addr);
> if (test_bit(CACHE_VALID, &h->flags) &&
> !test_bit(CACHE_NEGATIVE, &h->flags))
> dom = im->m_client->h.name;
> - seq_printf(m, "%s %d.%d.%d.%d %s\n",
> - im->m_class,
> - ntohl(addr.s_addr) >> 24 & 0xff,
> - ntohl(addr.s_addr) >> 16 & 0xff,
> - ntohl(addr.s_addr) >> 8 & 0xff,
> - ntohl(addr.s_addr) >> 0 & 0xff,
> - dom
> - );
> + if (ipv6_addr_v4mapped(&addr6)) {
> + seq_printf(m, "%s" NIPQUAD_FMT "%s\n",
> + im->m_class,
> + ntohl(addr6.s6_addr32[3]) >> 24 & 0xff,
> + ntohl(addr6.s6_addr32[3]) >> 16 & 0xff,
> + ntohl(addr6.s6_addr32[3]) >> 8 & 0xff,
> + ntohl(addr6.s6_addr32[3]) >> 0 & 0xff,
> + dom);
> + } else {
> + seq_printf(m, "%s" NIP6_FMT "%s\n",
> + im->m_class, NIP6(addr6), dom);
> + }
> return 0;
> }
> @@ -280,16 +306,16 @@ struct cache_detail ip_map_cache = {
> .alloc = ip_map_alloc,
> };
> -static struct ip_map *ip_map_lookup(char *class, struct in_addr addr)
> +static struct ip_map *ip_map_lookup(char *class, struct in6_addr *addr)
> {
> struct ip_map ip;
> struct cache_head *ch;
> strcpy(ip.m_class, class);
> - ip.m_addr = addr;
> + ipv6_addr_copy(&ip.m_addr, addr);
> ch = sunrpc_cache_lookup(&ip_map_cache, &ip.h,
> hash_str(class, IP_HASHBITS) ^
> - hash_ip(addr.s_addr));
> + hash_ip6(addr));
> if (ch)
> return container_of(ch, struct ip_map, h);
> @@ -318,14 +344,14 @@ static int ip_map_update(struct ip_map *ipm, struct
> unix_domain *udom, time_t ex
> ch = sunrpc_cache_update(&ip_map_cache,
> &ip.h, &ipm->h,
> hash_str(ipm->m_class, IP_HASHBITS) ^
> - hash_ip(ipm->m_addr.s_addr));
> + hash_ip6(&ipm->m_addr));
> if (!ch)
> return -ENOMEM;
> cache_put(ch, &ip_map_cache);
> return 0;
> }
> -int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom)
> +int auth_unix_add_addr(struct in6_addr *addr, struct auth_domain *dom)
> {
> struct unix_domain *udom;
> struct ip_map *ipmp;
> @@ -352,7 +378,7 @@ int auth_unix_forget_old(struct auth_domain *dom)
> return 0;
> }
> -struct auth_domain *auth_unix_lookup(struct in_addr addr)
> +struct auth_domain *auth_unix_lookup(struct in6_addr *addr)
> {
> struct ip_map *ipm;
> struct auth_domain *rv;
> @@ -641,9 +667,23 @@ static int unix_gid_find(uid_t uid, struct group_info
> **gip,
> int
> svcauth_unix_set_client(struct svc_rqst *rqstp)
> {
> - struct sockaddr_in *sin = svc_addr_in(rqstp);
> + struct sockaddr_in *sin;
> + struct sockaddr_in6 *sin6, sin6_storage;
> struct ip_map *ipm;
> + switch (rqstp->rq_addr.ss_family) {
> + case AF_INET:
> + sin = svc_addr_in(rqstp);
> + sin6 = &sin6_storage;
> + ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &sin6->sin6_addr);
> + break;
> + case AF_INET6:
> + sin6 = svc_addr_in6(rqstp);
> + break;
> + default:
> + BUG();
> + }
> +
> rqstp->rq_client = NULL;
> if (rqstp->rq_proc == 0)
> return SVC_OK;
> @@ -651,7 +691,7 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
> ipm = ip_map_cached_get(rqstp);
> if (ipm == NULL)
> ipm = ip_map_lookup(rqstp->rq_server->sv_program->pg_class,
> - sin->sin_addr);
> + &sin6->sin6_addr);
> if (ipm == NULL)
> return SVC_DENIED;
>
>
> --
>
> ********************************
> Aurelien Charbon
> Linux NFSv4 team
> Bull SAS
> Echirolles - France
> http://nfsv4.bullopensource.org/
> ********************************
>
> diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
> index 66d0aeb..c47ba77 100644
> --- a/fs/nfsd/export.c
> +++ b/fs/nfsd/export.c
> @@ -35,6 +35,7 @@
> #include <linux/lockd/bind.h>
> #include <linux/sunrpc/msg_prot.h>
> #include <linux/sunrpc/gss_api.h>
> +#include <net/ipv6.h>
>
> #define NFSDDBG_FACILITY NFSDDBG_EXPORT
>
> @@ -1556,6 +1557,7 @@ exp_addclient(struct nfsctl_client *ncp)
> {
> struct auth_domain *dom;
> int i, err;
> + struct in6_addr in6;
>
> /* First, consistency check. */
> err = -EINVAL;
> @@ -1574,9 +1576,10 @@ exp_addclient(struct nfsctl_client *ncp)
> goto out_unlock;
>
> /* Insert client into hashtable. */
> - for (i = 0; i < ncp->cl_naddr; i++)
> - auth_unix_add_addr(ncp->cl_addrlist[i], dom);
> -
> + for (i = 0; i < ncp->cl_naddr; i++) {
> + ipv6_addr_set_v4mapped(ncp->cl_addrlist[i].s_addr, &in6);
> + auth_unix_add_addr(&in6, dom);
> + }
> auth_unix_forget_old(dom);
> auth_domain_put(dom);
>
> diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
> index 77dc989..5cb5f0d 100644
> --- a/fs/nfsd/nfsctl.c
> +++ b/fs/nfsd/nfsctl.c
> @@ -37,6 +37,7 @@
> #include <linux/nfsd/syscall.h>
>
> #include <asm/uaccess.h>
> +#include <net/ipv6.h>
>
> /*
> * We have a single directory with 9 nodes in it.
> @@ -219,24 +220,37 @@ static ssize_t write_getfs(struct file *file, char *buf, size_t size)
> {
> struct nfsctl_fsparm *data;
> struct sockaddr_in *sin;
> + struct sockaddr_in6 *sin6;
> struct auth_domain *clp;
> int err = 0;
> struct knfsd_fh *res;
> + struct in6_addr in6;
>
> if (size < sizeof(*data))
> return -EINVAL;
> data = (struct nfsctl_fsparm*)buf;
> err = -EPROTONOSUPPORT;
> - if (data->gd_addr.sa_family != AF_INET)
> + switch (data->gd_addr.sa_family) {
> + case AF_INET:
> + sin = (struct sockaddr_in *)&data->gd_addr;
> + ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6);
> + break;
> + case AF_INET6:
> + sin6 = (struct sockaddr_in6 *)&data->gd_addr;
> + ipv6_addr_copy(&in6, &sin6->sin6_addr);
> + break;
> + default:
> goto out;
> - sin = (struct sockaddr_in *)&data->gd_addr;
> + }
> +
> if (data->gd_maxlen > NFS3_FHSIZE)
> data->gd_maxlen = NFS3_FHSIZE;
>
> res = (struct knfsd_fh*)buf;
>
> exp_readlock();
> - if (!(clp = auth_unix_lookup(sin->sin_addr)))
> +
> + if (!(clp = auth_unix_lookup(&in6)))
> err = -EPERM;
> else {
> err = exp_rootfh(clp, data->gd_path, res, data->gd_maxlen);
> @@ -253,25 +267,41 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size)
> {
> struct nfsctl_fdparm *data;
> struct sockaddr_in *sin;
> + struct sockaddr_in6 *sin6;
> struct auth_domain *clp;
> int err = 0;
> struct knfsd_fh fh;
> char *res;
> + struct in6_addr in6;
>
> if (size < sizeof(*data))
> return -EINVAL;
> data = (struct nfsctl_fdparm*)buf;
> err = -EPROTONOSUPPORT;
> - if (data->gd_addr.sa_family != AF_INET)
> + if (data->gd_addr.sa_family != AF_INET &&
> + data->gd_addr.sa_family != AF_INET6)
> goto out;
> err = -EINVAL;
> if (data->gd_version < 2 || data->gd_version > NFSSVC_MAXVERS)
> goto out;
>
> res = buf;
> - sin = (struct sockaddr_in *)&data->gd_addr;
> exp_readlock();
> - if (!(clp = auth_unix_lookup(sin->sin_addr)))
> +
> + switch (data->gd_addr.sa_family) {
> + case AF_INET:
> + sin = (struct sockaddr_in *)&data->gd_addr;
> + ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6);
> + break;
> + case AF_INET6:
> + sin6 = (struct sockaddr_in6 *)&data->gd_addr;
> + ipv6_addr_copy(&in6, &sin6->sin6_addr);
> + break;
> + default:
> + goto out;
> + }
> +
> + if (!(clp = auth_unix_lookup(&in6)))
> err = -EPERM;
> else {
> err = exp_rootfh(clp, data->gd_path, &fh, NFS_FHSIZE);
> diff --git a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h
> index 22e1ef8..64ecb93 100644
> --- a/include/linux/sunrpc/svcauth.h
> +++ b/include/linux/sunrpc/svcauth.h
> @@ -15,6 +15,7 @@
> #include <linux/sunrpc/msg_prot.h>
> #include <linux/sunrpc/cache.h>
> #include <linux/hash.h>
> +#include <net/ipv6.h>
>
> #define SVC_CRED_NGROUPS 32
> struct svc_cred {
> @@ -120,10 +121,10 @@ extern void svc_auth_unregister(rpc_authflavor_t flavor);
>
> extern struct auth_domain *unix_domain_find(char *name);
> extern void auth_domain_put(struct auth_domain *item);
> -extern int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom);
> +extern int auth_unix_add_addr(struct in6_addr *addr, struct auth_domain *dom);
> extern struct auth_domain *auth_domain_lookup(char *name, struct auth_domain *new);
> extern struct auth_domain *auth_domain_find(char *name);
> -extern struct auth_domain *auth_unix_lookup(struct in_addr addr);
> +extern struct auth_domain *auth_unix_lookup(struct in6_addr *addr);
> extern int auth_unix_forget_old(struct auth_domain *dom);
> extern void svcauth_unix_purge(void);
> extern void svcauth_unix_info_release(void *);
> diff --git a/include/net/ipv6.h b/include/net/ipv6.h
> index ae328b6..366fdca 100644
> --- a/include/net/ipv6.h
> +++ b/include/net/ipv6.h
> @@ -16,6 +16,7 @@
> #define _NET_IPV6_H
>
> #include <linux/ipv6.h>
> +#include <linux/in.h>
> #include <linux/hardirq.h>
> #include <net/if_inet6.h>
> #include <net/ndisc.h>
> @@ -400,6 +401,15 @@ static inline int ipv6_addr_v4mapped(const struct in6_addr *a)
> a->s6_addr32[2] == htonl(0x0000ffff));
> }
>
> +static inline void ipv6_addr_set_v4mapped(const __be32 addr,
> + struct in6_addr *v4mapped)
> +{
> + ipv6_addr_set(v4mapped,
> + 0, 0,
> + __constant_htonl(0x0000FFFF),
> + addr);
> +}
> +
> /*
> * find the first different bit between two addresses
> * length of address must be a multiple of 32bits
> diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
> index 4114794..a40d769 100644
> --- a/net/sunrpc/svcauth_unix.c
> +++ b/net/sunrpc/svcauth_unix.c
> @@ -11,6 +11,7 @@
> #include <linux/hash.h>
> #include <linux/string.h>
> #include <net/sock.h>
> +#include <net/ipv6.h>
>
> #define RPCDBG_FACILITY RPCDBG_AUTH
>
> @@ -84,7 +85,7 @@ static void svcauth_unix_domain_release(struct auth_domain *dom)
> struct ip_map {
> struct cache_head h;
> char m_class[8]; /* e.g. "nfsd" */
> - struct in_addr m_addr;
> + struct in6_addr m_addr;
> struct unix_domain *m_client;
> int m_add_change;
> };
> @@ -101,7 +102,6 @@ static void ip_map_put(struct kref *kref)
> kfree(im);
> }
>
> -#if IP_HASHBITS == 8
> /* hash_long on a 64 bit machine is currently REALLY BAD for
> * IP addresses in reverse-endian (i.e. on a little-endian machine).
> * So use a trivial but reliable hash instead
> @@ -111,13 +111,20 @@ static inline int hash_ip(__be32 ip)
> int hash = (__force u32)ip ^ ((__force u32)ip>>16);
> return (hash ^ (hash>>8)) & 0xff;
> }
> -#endif
> +
> +static inline int hash_ip6(struct in6_addr *ip6)
> +{
> + return (hash_ip(ip6->s6_addr32[0]) ^
> + hash_ip(ip6->s6_addr32[1]) ^
> + hash_ip(ip6->s6_addr32[2]) ^
> + hash_ip(ip6->s6_addr32[3]));
> +}
> static int ip_map_match(struct cache_head *corig, struct cache_head *cnew)
> {
> struct ip_map *orig = container_of(corig, struct ip_map, h);
> struct ip_map *new = container_of(cnew, struct ip_map, h);
> return strcmp(orig->m_class, new->m_class) == 0
> - && orig->m_addr.s_addr == new->m_addr.s_addr;
> + && ipv6_addr_equal(&orig->m_addr, &new->m_addr);
> }
> static void ip_map_init(struct cache_head *cnew, struct cache_head *citem)
> {
> @@ -125,7 +132,7 @@ static void ip_map_init(struct cache_head *cnew, struct cache_head *citem)
> struct ip_map *item = container_of(citem, struct ip_map, h);
>
> strcpy(new->m_class, item->m_class);
> - new->m_addr.s_addr = item->m_addr.s_addr;
> + ipv6_addr_copy(&new->m_addr, &item->m_addr);
> }
> static void update(struct cache_head *cnew, struct cache_head *citem)
> {
> @@ -149,22 +156,24 @@ static void ip_map_request(struct cache_detail *cd,
> struct cache_head *h,
> char **bpp, int *blen)
> {
> - char text_addr[20];
> + char text_addr[40];
> struct ip_map *im = container_of(h, struct ip_map, h);
> - __be32 addr = im->m_addr.s_addr;
> -
> - snprintf(text_addr, 20, "%u.%u.%u.%u",
> - ntohl(addr) >> 24 & 0xff,
> - ntohl(addr) >> 16 & 0xff,
> - ntohl(addr) >> 8 & 0xff,
> - ntohl(addr) >> 0 & 0xff);
>
> + if (ipv6_addr_v4mapped(&(im->m_addr))) {
> + snprintf(text_addr, 20, NIPQUAD_FMT,
> + ntohl(im->m_addr.s6_addr32[3]) >> 24 & 0xff,
> + ntohl(im->m_addr.s6_addr32[3]) >> 16 & 0xff,
> + ntohl(im->m_addr.s6_addr32[3]) >> 8 & 0xff,
> + ntohl(im->m_addr.s6_addr32[3]) >> 0 & 0xff);
> + } else {
> + snprintf(text_addr, 40, NIP6_FMT, NIP6(im->m_addr));
> + }
> qword_add(bpp, blen, im->m_class);
> qword_add(bpp, blen, text_addr);
> (*bpp)[-1] = '\n';
> }
>
> -static struct ip_map *ip_map_lookup(char *class, struct in_addr addr);
> +static struct ip_map *ip_map_lookup(char *class, struct in6_addr *addr);
> static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t expiry);
>
> static int ip_map_parse(struct cache_detail *cd,
> @@ -175,10 +184,10 @@ static int ip_map_parse(struct cache_detail *cd,
> * for scratch: */
> char *buf = mesg;
> int len;
> - int b1,b2,b3,b4;
> + int b1, b2, b3, b4, b5, b6, b7, b8;
> char c;
> char class[8];
> - struct in_addr addr;
> + struct in6_addr addr6;
> int err;
>
> struct ip_map *ipmp;
> @@ -197,7 +206,23 @@ static int ip_map_parse(struct cache_detail *cd,
> len = qword_get(&mesg, buf, mlen);
> if (len <= 0) return -EINVAL;
>
> - if (sscanf(buf, "%u.%u.%u.%u%c", &b1, &b2, &b3, &b4, &c) != 4)
> + if (sscanf(buf, NIPQUAD_FMT "%c", &b1, &b2, &b3, &b4, &c) == 4) {
> + addr6.s6_addr32[0] = 0;
> + addr6.s6_addr32[1] = 0;
> + addr6.s6_addr32[2] = htonl(0xffff);
> + addr6.s6_addr32[3] =
> + htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
> + } else if (sscanf(buf, NIP6_FMT "%c",
> + &b1, &b2, &b3, &b4, &b5, &b6, &b7, &b8, &c) == 8) {
> + addr6.s6_addr16[0] = htons(b1);
> + addr6.s6_addr16[1] = htons(b2);
> + addr6.s6_addr16[2] = htons(b3);
> + addr6.s6_addr16[3] = htons(b4);
> + addr6.s6_addr16[4] = htons(b5);
> + addr6.s6_addr16[5] = htons(b6);
> + addr6.s6_addr16[6] = htons(b7);
> + addr6.s6_addr16[7] = htons(b8);
> + } else
> return -EINVAL;
>
> expiry = get_expiry(&mesg);
> @@ -215,10 +240,7 @@ static int ip_map_parse(struct cache_detail *cd,
> } else
> dom = NULL;
>
> - addr.s_addr =
> - htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
> -
> - ipmp = ip_map_lookup(class,addr);
> + ipmp = ip_map_lookup(class, &addr6);
> if (ipmp) {
> err = ip_map_update(ipmp,
> container_of(dom, struct unix_domain, h),
> @@ -238,7 +260,7 @@ static int ip_map_show(struct seq_file *m,
> struct cache_head *h)
> {
> struct ip_map *im;
> - struct in_addr addr;
> + struct in6_addr addr6;
> char *dom = "-no-domain-";
>
> if (h == NULL) {
> @@ -247,20 +269,24 @@ static int ip_map_show(struct seq_file *m,
> }
> im = container_of(h, struct ip_map, h);
> /* class addr domain */
> - addr = im->m_addr;
> + ipv6_addr_copy(&addr6, &im->m_addr);
>
> if (test_bit(CACHE_VALID, &h->flags) &&
> !test_bit(CACHE_NEGATIVE, &h->flags))
> dom = im->m_client->h.name;
>
> - seq_printf(m, "%s %d.%d.%d.%d %s\n",
> - im->m_class,
> - ntohl(addr.s_addr) >> 24 & 0xff,
> - ntohl(addr.s_addr) >> 16 & 0xff,
> - ntohl(addr.s_addr) >> 8 & 0xff,
> - ntohl(addr.s_addr) >> 0 & 0xff,
> - dom
> - );
> + if (ipv6_addr_v4mapped(&addr6)) {
> + seq_printf(m, "%s" NIPQUAD_FMT "%s\n",
> + im->m_class,
> + ntohl(addr6.s6_addr32[3]) >> 24 & 0xff,
> + ntohl(addr6.s6_addr32[3]) >> 16 & 0xff,
> + ntohl(addr6.s6_addr32[3]) >> 8 & 0xff,
> + ntohl(addr6.s6_addr32[3]) >> 0 & 0xff,
> + dom);
> + } else {
> + seq_printf(m, "%s" NIP6_FMT "%s\n",
> + im->m_class, NIP6(addr6), dom);
> + }
> return 0;
> }
>
> @@ -280,16 +306,16 @@ struct cache_detail ip_map_cache = {
> .alloc = ip_map_alloc,
> };
>
> -static struct ip_map *ip_map_lookup(char *class, struct in_addr addr)
> +static struct ip_map *ip_map_lookup(char *class, struct in6_addr *addr)
> {
> struct ip_map ip;
> struct cache_head *ch;
>
> strcpy(ip.m_class, class);
> - ip.m_addr = addr;
> + ipv6_addr_copy(&ip.m_addr, addr);
> ch = sunrpc_cache_lookup(&ip_map_cache, &ip.h,
> hash_str(class, IP_HASHBITS) ^
> - hash_ip(addr.s_addr));
> + hash_ip6(addr));
>
> if (ch)
> return container_of(ch, struct ip_map, h);
> @@ -318,14 +344,14 @@ static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t ex
> ch = sunrpc_cache_update(&ip_map_cache,
> &ip.h, &ipm->h,
> hash_str(ipm->m_class, IP_HASHBITS) ^
> - hash_ip(ipm->m_addr.s_addr));
> + hash_ip6(&ipm->m_addr));
> if (!ch)
> return -ENOMEM;
> cache_put(ch, &ip_map_cache);
> return 0;
> }
>
> -int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom)
> +int auth_unix_add_addr(struct in6_addr *addr, struct auth_domain *dom)
> {
> struct unix_domain *udom;
> struct ip_map *ipmp;
> @@ -352,7 +378,7 @@ int auth_unix_forget_old(struct auth_domain *dom)
> return 0;
> }
>
> -struct auth_domain *auth_unix_lookup(struct in_addr addr)
> +struct auth_domain *auth_unix_lookup(struct in6_addr *addr)
> {
> struct ip_map *ipm;
> struct auth_domain *rv;
> @@ -641,9 +667,23 @@ static int unix_gid_find(uid_t uid, struct group_info **gip,
> int
> svcauth_unix_set_client(struct svc_rqst *rqstp)
> {
> - struct sockaddr_in *sin = svc_addr_in(rqstp);
> + struct sockaddr_in *sin;
> + struct sockaddr_in6 *sin6, sin6_storage;
> struct ip_map *ipm;
>
> + switch (rqstp->rq_addr.ss_family) {
> + case AF_INET:
> + sin = svc_addr_in(rqstp);
> + sin6 = &sin6_storage;
> + ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &sin6->sin6_addr);
> + break;
> + case AF_INET6:
> + sin6 = svc_addr_in6(rqstp);
> + break;
> + default:
> + BUG();
> + }
> +
> rqstp->rq_client = NULL;
> if (rqstp->rq_proc == 0)
> return SVC_OK;
> @@ -651,7 +691,7 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
> ipm = ip_map_cached_get(rqstp);
> if (ipm == NULL)
> ipm = ip_map_lookup(rqstp->rq_server->sv_program->pg_class,
> - sin->sin_addr);
> + &sin6->sin6_addr);
>
> if (ipm == NULL)
> return SVC_DENIED;
> _______________________________________________
> NFSv4 mailing list
> NFSv4@linux-nfs.org
> http://linux-nfs.org/cgi-bin/mailman/listinfo/nfsv4
_______________________________________________
NFSv4 mailing list
NFSv4@linux-nfs.org
http://linux-nfs.org/cgi-bin/mailman/listinfo/nfsv4
^ permalink raw reply
* Re: [PATCH 00/33] Swap over NFS -v14
From: Evgeniy Polyakov @ 2007-10-31 16:31 UTC (permalink / raw)
To: Mike Snitzer
Cc: Peter Zijlstra, Christoph Hellwig, David Miller, nickpiggin,
torvalds, akpm, linux-kernel, linux-mm, netdev, trond.myklebust
In-Reply-To: <170fa0d20710310754h55d768bdgb67f30b54174e680@mail.gmail.com>
Hi.
On Wed, Oct 31, 2007 at 10:54:02AM -0400, Mike Snitzer (snitzer@gmail.com) wrote:
> > Trouble with that part is that we don't have any sane network block
> > devices atm, NBD is utter crap, and iSCSI is too complex to be called
> > sane.
> >
> > Maybe Evgeniy's Distributed storage thingy would work, will have a look
> > at that.
>
> Andrew recently asked Evgeniy if his DST was ready for merging; to
> which Evgeniy basically said yes:
> http://lkml.org/lkml/2007/10/27/54
>
> It would be great if DST could be merged; whereby addressing the fact
> that NBD is lacking for net-vm. If DST were scrutinized in the
> context of net-vm it should help it get the review that is needed for
> merging.
By popular request I'm working on adding strong checksumming of the data
transferred, so I can not say that Andrew will want to merge this during
development phase. I expect to complete it quite soon (it is in testing
stage right now) though with new release scheduled this week. It will
also include some small features for userspace (hapiness).
Memory management is not changed.
--
Evgeniy Polyakov
^ permalink raw reply
* drivers/net/tlan question
From: Gabriel C @ 2007-10-31 17:59 UTC (permalink / raw)
To: Linux Kernel Mailing List; +Cc: netdev, tlan-devel, chessman
Hi,
I noticed on current git the following warning with !CONFIG_PCI :
...
drivers/net/tlan.c: In function 'TLan_probe1':
drivers/net/tlan.c:682: warning: label 'err_out' defined but not used
...
I thought a simply #ifdef is missing but looking at TLan_probe1() I got confused about err_out_regions
...
#ifdef CONFIG_PCI
if (pdev) {
rc = pci_enable_device(pdev);
if (rc)
return rc;
rc = pci_request_regions(pdev, TLanSignature);
if (rc) {
printk(KERN_ERR "TLAN: Could not reserve IO regions\n");
goto err_out;
}
}
#endif /* CONFIG_PCI */
dev = alloc_etherdev(sizeof(TLanPrivateInfo));
if (dev == NULL) {
printk(KERN_ERR "TLAN: Could not allocate memory for device.\n");
rc = -ENOMEM;
goto err_out_regions;
}
...
...
err_out_regions:
#ifdef CONFIG_PCI
if (pdev)
pci_release_regions(pdev);
#endif
err_out:
if (pdev)
pci_disable_device(pdev);
return rc;
...
It is possible 'dev' to be NULL with !CONFIG_PCI ? If is true then err_out_regions: does nothing ?
Does this look right ?
Regards,
Gabriel
^ permalink raw reply
* [PATCH] tlan list is subscribers-only
From: Gabriel C @ 2007-10-31 18:08 UTC (permalink / raw)
To: Linux Kernel Mailing List; +Cc: netdev, chessman
In-Reply-To: <4728C266.2010600@googlemail.com>
...
Your mail to 'Tlan-devel' with the subject
drivers/net/tlan question
Is being held until the list moderator can review it for approval.
The reason it is being held:
Post by non-member to a members-only list
...
Signed-off-by: Gabriel Craciunescu <nix.or.die@googlemail.com>
---
MAINTAINERS | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 4a26f83..6a116f3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3729,7 +3729,7 @@ S: Maintained
TLAN NETWORK DRIVER
P: Samuel Chessman
M: chessman@tux.org
-L: tlan-devel@lists.sourceforge.net
+L: tlan-devel@lists.sourceforge.net (subscribers-only)
W: http://sourceforge.net/projects/tlan/
S: Maintained
^ permalink raw reply related
* [PATCH 0/5] Make nicer CONFIG_NET_NS=n case code
From: Pavel Emelyanov @ 2007-10-31 19:19 UTC (permalink / raw)
To: David Miller; +Cc: Linux Netdev List, Eric W. Biederman, devel
Currently we have the NET_NS config option, but the only change it
makes is just return ERR_PTR(-EINVAL) inside the cloning call thus
introducing a bunch of a dead code and making the reference counting
unneeded. This is not very good.
So clean the net_namespace.c to fix this.
I have sent a set of patches to Andrew to make similar thing for
other namespaces, which introduces the NAMESPACES option to turn
all the namespaces off at once (to make embedded people suffer
less). So after that stuff is in, there will be some more patches
to tie all this together.
What is to be done after this set is to make the register_pernet_xxx
stuff smaller. Currently this code weights approximately 500 bytes,
so it worths reducing it, but I haven't found a good solution yet.
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
^ permalink raw reply
* [PATCH 1/5][NETNS] Make the init/exit hooks checks outside the loop
From: Pavel Emelyanov @ 2007-10-31 19:23 UTC (permalink / raw)
To: David Miller; +Cc: Linux Netdev List, Eric W. Biederman, devel
In-Reply-To: <4728D54F.2080208@openvz.org>
When the new pernet something (subsys, device or operations) is
being registered, the init callback is to be called for each
namespace, that currently exitst in the system. During the
unregister, the same is to be done with the exit callback.
However, not every pernet something has both calls, but the
check for the appropriate pointer to be not NULL is performed
inside the for_each_net() loop.
This is (at least) strange, so tune this.
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
---
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 662e6ea..4e52921 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -187,29 +187,28 @@ static int register_pernet_operations(struct list_head *list,
struct net *net, *undo_net;
int error;
- error = 0;
list_add_tail(&ops->list, list);
- for_each_net(net) {
- if (ops->init) {
+ if (ops->init) {
+ for_each_net(net) {
error = ops->init(net);
if (error)
goto out_undo;
}
}
-out:
- return error;
+ return 0;
out_undo:
/* If I have an error cleanup all namespaces I initialized */
list_del(&ops->list);
- for_each_net(undo_net) {
- if (undo_net == net)
- goto undone;
- if (ops->exit)
+ if (ops->exit) {
+ for_each_net(undo_net) {
+ if (undo_net == net)
+ goto undone;
ops->exit(undo_net);
+ }
}
undone:
- goto out;
+ return error;
}
static void unregister_pernet_operations(struct pernet_operations *ops)
@@ -217,8 +216,8 @@ static void unregister_pernet_operations(struct pernet_operations *ops)
struct net *net;
list_del(&ops->list);
- for_each_net(net)
- if (ops->exit)
+ if (ops->exit)
+ for_each_net(net)
ops->exit(net);
}
--
1.5.3.4
^ permalink raw reply related
* [PATCH 2/5] Relax the reference counting of init_net_ns
From: Pavel Emelyanov @ 2007-10-31 19:25 UTC (permalink / raw)
To: David Miller; +Cc: Linux Netdev List, Eric W. Biederman, devel
In-Reply-To: <4728D54F.2080208@openvz.org>
When the CONFIG_NET_NS is n there's no need in refcounting
the initial net namespace. So relax this code by making a
stupid stubs for the "n" case.
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
---
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 5279466..1fd449a 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -51,13 +51,12 @@ static inline struct net *copy_net_ns(unsigned long flags, struct net *net_ns)
}
#endif
+#ifdef CONFIG_NET_NS
extern void __put_net(struct net *net);
static inline struct net *get_net(struct net *net)
{
-#ifdef CONFIG_NET
atomic_inc(&net->count);
-#endif
return net;
}
@@ -75,26 +74,44 @@ static inline struct net *maybe_get_net(struct net *net)
static inline void put_net(struct net *net)
{
-#ifdef CONFIG_NET
if (atomic_dec_and_test(&net->count))
__put_net(net);
-#endif
}
static inline struct net *hold_net(struct net *net)
{
-#ifdef CONFIG_NET
atomic_inc(&net->use_count);
-#endif
return net;
}
static inline void release_net(struct net *net)
{
-#ifdef CONFIG_NET
atomic_dec(&net->use_count);
-#endif
}
+#else
+static inline struct net *get_net(struct net *net)
+{
+ return net;
+}
+
+static inline void put_net(struct net *net)
+{
+}
+
+static inline struct net *hold_net(struct net *net)
+{
+ return net;
+}
+
+static inline void release_net(struct net *net)
+{
+}
+
+static inline struct net *maybe_get_net(struct net *net)
+{
+ return net;
+}
+#endif
#define for_each_net(VAR) \
list_for_each_entry(VAR, &net_namespace_list, list)
--
1.5.3.4
^ permalink raw reply related
* [PATCH 3/5] Hide the dead code in the net_namespace.c
From: Pavel Emelyanov @ 2007-10-31 19:28 UTC (permalink / raw)
To: David Miller; +Cc: Linux Netdev List, Eric W. Biederman, devel
In-Reply-To: <4728D54F.2080208@openvz.org>
The namespace creation/destruction code is never called
if the CONFIG_NET_NS is n, so it's OK to move it under
appropriate ifdef.
The copy_net_ns() in the "n" case checks for flags and
returns -EINVAL when new net ns is requested. In a perfect
world this stub must be in net_namespace.h, but this
function need to know the CLONE_NEWNET value and thus
requires sched.h. On the other hand this header is to be
injected into almost every .c file in the networking code,
and making all this code depend on the sched.h is a
suicidal attempt.
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
---
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 4e52921..d5bf8b2 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -22,65 +22,6 @@ static struct kmem_cache *net_cachep;
struct net init_net;
EXPORT_SYMBOL_GPL(init_net);
-static struct net *net_alloc(void)
-{
- return kmem_cache_zalloc(net_cachep, GFP_KERNEL);
-}
-
-static void net_free(struct net *net)
-{
- if (!net)
- return;
-
- if (unlikely(atomic_read(&net->use_count) != 0)) {
- printk(KERN_EMERG "network namespace not free! Usage: %d\n",
- atomic_read(&net->use_count));
- return;
- }
-
- kmem_cache_free(net_cachep, net);
-}
-
-static void cleanup_net(struct work_struct *work)
-{
- struct pernet_operations *ops;
- struct net *net;
-
- net = container_of(work, struct net, work);
-
- mutex_lock(&net_mutex);
-
- /* Don't let anyone else find us. */
- rtnl_lock();
- list_del(&net->list);
- rtnl_unlock();
-
- /* Run all of the network namespace exit methods */
- list_for_each_entry_reverse(ops, &pernet_list, list) {
- if (ops->exit)
- ops->exit(net);
- }
-
- mutex_unlock(&net_mutex);
-
- /* Ensure there are no outstanding rcu callbacks using this
- * network namespace.
- */
- rcu_barrier();
-
- /* Finally it is safe to free my network namespace structure */
- net_free(net);
-}
-
-
-void __put_net(struct net *net)
-{
- /* Cleanup the network namespace in process context */
- INIT_WORK(&net->work, cleanup_net);
- schedule_work(&net->work);
-}
-EXPORT_SYMBOL_GPL(__put_net);
-
/*
* setup_net runs the initializers for the network namespace object.
*/
@@ -117,6 +58,12 @@ out_undo:
goto out;
}
+#ifdef CONFIG_NET_NS
+static struct net *net_alloc(void)
+{
+ return kmem_cache_zalloc(net_cachep, GFP_KERNEL);
+}
+
struct net *copy_net_ns(unsigned long flags, struct net *old_net)
{
struct net *new_net = NULL;
@@ -127,10 +74,6 @@ struct net *copy_net_ns(unsigned long flags, struct net *old_net)
if (!(flags & CLONE_NEWNET))
return old_net;
-#ifndef CONFIG_NET_NS
- return ERR_PTR(-EINVAL);
-#endif
-
err = -ENOMEM;
new_net = net_alloc();
if (!new_net)
@@ -157,6 +100,68 @@ out:
return new_net;
}
+static void net_free(struct net *net)
+{
+ if (!net)
+ return;
+
+ if (unlikely(atomic_read(&net->use_count) != 0)) {
+ printk(KERN_EMERG "network namespace not free! Usage: %d\n",
+ atomic_read(&net->use_count));
+ return;
+ }
+
+ kmem_cache_free(net_cachep, net);
+}
+
+static void cleanup_net(struct work_struct *work)
+{
+ struct pernet_operations *ops;
+ struct net *net;
+
+ net = container_of(work, struct net, work);
+
+ mutex_lock(&net_mutex);
+
+ /* Don't let anyone else find us. */
+ rtnl_lock();
+ list_del(&net->list);
+ rtnl_unlock();
+
+ /* Run all of the network namespace exit methods */
+ list_for_each_entry_reverse(ops, &pernet_list, list) {
+ if (ops->exit)
+ ops->exit(net);
+ }
+
+ mutex_unlock(&net_mutex);
+
+ /* Ensure there are no outstanding rcu callbacks using this
+ * network namespace.
+ */
+ rcu_barrier();
+
+ /* Finally it is safe to free my network namespace structure */
+ net_free(net);
+}
+
+void __put_net(struct net *net)
+{
+ /* Cleanup the network namespace in process context */
+ INIT_WORK(&net->work, cleanup_net);
+ schedule_work(&net->work);
+}
+EXPORT_SYMBOL_GPL(__put_net);
+
+#else
+struct net *copy_net_ns(unsigned long flags, struct net *old_net)
+{
+ if (flags & CLONE_NEWNET)
+ return ERR_PTR(-EINVAL);
+ return old_net;
+}
+#endif
+
static int __init net_ns_init(void)
{
int err;
--
1.5.3.4
^ permalink raw reply related
* [PATCH 4/5] Mark the setup_net as __net_init
From: Pavel Emelyanov @ 2007-10-31 19:31 UTC (permalink / raw)
To: David Miller; +Cc: Linux Netdev List, Eric W. Biederman, devel
In-Reply-To: <4728D54F.2080208@openvz.org>
The setup_net is called for the init net namespace
only (int the CONFIG_NET_NS=n of course) from the __init
function, so mark it as __net_init to disappear with the
caller after the boot.
Yet again, in the perfect world this has to be under
#ifdef CONFIG_NET_NS, but it isn't guaranteed that every
subsystem is registered *after* the init_net_ns is set
up. After we are sure, that we don't start registering
them before the init net setup, we'll be able to move
this code under the ifdef.
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
---
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index d5bf8b2..a044e2d 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -25,7 +25,7 @@ EXPORT_SYMBOL_GPL(init_net);
/*
* setup_net runs the initializers for the network namespace object.
*/
-static int setup_net(struct net *net)
+static __net_init int setup_net(struct net *net)
{
/* Must be called with net_mutex held */
struct pernet_operations *ops;
--
1.5.3.4
^ permalink raw reply related
* [PATCH 5/5] Hide the net_ns kmem cache
From: Pavel Emelyanov @ 2007-10-31 19:32 UTC (permalink / raw)
To: David Miller; +Cc: Linux Netdev List, Eric W. Biederman, devel
In-Reply-To: <4728D54F.2080208@openvz.org>
This cache is only required to create new namespaces,
but we won't have them in CONFIG_NET_NS=n case.
Hide it under the appropriate ifdef.
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
---
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index a044e2d..e9f0964 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -17,8 +17,6 @@ static DEFINE_MUTEX(net_mutex);
LIST_HEAD(net_namespace_list);
-static struct kmem_cache *net_cachep;
-
struct net init_net;
EXPORT_SYMBOL_GPL(init_net);
@@ -59,6 +57,8 @@ out_undo:
}
#ifdef CONFIG_NET_NS
+static struct kmem_cache *net_cachep;
+
static struct net *net_alloc(void)
{
return kmem_cache_zalloc(net_cachep, GFP_KERNEL);
@@ -167,9 +167,11 @@ static int __init net_ns_init(void)
int err;
printk(KERN_INFO "net_namespace: %zd bytes\n", sizeof(struct net));
+#ifdef CONFIG_NET_NS
net_cachep = kmem_cache_create("net_namespace", sizeof(struct net),
SMP_CACHE_BYTES,
SLAB_PANIC, NULL);
+#endif
mutex_lock(&net_mutex);
err = setup_net(&init_net);
--
1.5.3.4
^ permalink raw reply related
* expected behavior of PF_PACKET on NETIF_F_HW_VLAN_RX device?
From: Dave Johnson @ 2007-10-31 18:43 UTC (permalink / raw)
To: linux-kernel, netdev, Bin Guo
Depending on the network driver, I'm seeing different behavior if
a .1q packet is received to an PF_PACKET, SOCK_RAW, ETH_P_ALL socket.
On devices what do not use NETIF_F_HW_VLAN_RX, the packet socket gets
the complete packet with vlan tag included as the driver simply calls
netif_receive_skb() or equivilant. packet_rcv() then gets the whole
thing vlan tag included and sends this through the socket.
vlan_skb_recv() also gets these all and will drop them because there
are no vlans configured.
Example, e100 driver gives this to tcpdump:
# ifconfig eth1 up
# tcpdump -s 2000 -e -n -i eth1
tcpdump: WARNING: eth1: no IPv4 address assigned
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 2000 bytes
14:11:03.707178 00:0b:82:05:22:0a > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 64: vlan 101, p 0, ethertype ARP, arp who-has 192.168.101.191 tell 192.168.101.131
14:11:04.215164 00:0b:82:05:22:05 > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 64: vlan 101, p 0, ethertype ARP, arp who-has 192.168.101.191 tell 192.168.101.130
14:11:04.658940 00:0b:82:05:22:0c > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 64: vlan 101, p 0, ethertype ARP, arp who-has 192.168.101.191 tell 192.168.101.135
14:11:05.706070 00:0b:82:05:22:0a > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 64: vlan 101, p 0, ethertype ARP, arp who-has 192.168.101.191 tell 192.168.101.131
14:11:05.939195 00:b0:c2:e8:d8:1c > 33:33:00:00:00:01, ethertype 802.1Q (0x8100), length 122: vlan 108, p 0, ethertype IPv6, fe80::2b0:c2ff:fee8:d81c > ff02::1: icmp6: router advertisement [class 0xe0]
14:11:07.222302 00:b0:c2:e8:d8:1c > 33:33:00:00:00:01, ethertype 802.1Q (0x8100), length 122: vlan 110, p 0, ethertype IPv6, fe80::2b0:c2ff:fee8:d81c > ff02::1: icmp6: router advertisement [class 0xe0]
14:11:08.486953 00:b0:c2:e8:d8:1c > 01:00:5e:00:00:05, ethertype 802.1Q (0x8100), length 134: vlan 110, p 0, ethertype IPv4, IP 192.168.110.20 > 224.0.0.5: OSPFv2, Hello (1), length: 80
14:11:11.528569 00:30:48:22:63:50 > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 154: vlan 208, p 0, ethertype IPv4, IP 195.180.3.200.33350 > 195.180.3.255.111: UDP, length: 108
14:11:12.642762 00:0b:82:05:22:05 > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 64: vlan 101, p 0, ethertype ARP, arp who-has 192.168.101.191 tell 192.168.101.130
14:11:12.642766 00:0b:82:05:22:05 > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 64: vlan 101, p 0, ethertype ARP, arp who-has 192.168.101.191 tell 192.168.101.130
The packet socket gets everything including the vlan tag as I'd
expect.
But on the bnx2 driver (for example) I get 2 different behaviors:
1)
If no vlan interfaces are configured, it calls netif_receive_skb()
because there isn't a vlan group registered via
bnx2_vlan_rx_register().
# ifconfig eth1 up
# tcpdump -s 2000 -e -n -i eth1
tcpdump: WARNING: eth1: no IPv4 address assigned
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 2000 bytes
14:21:27.170505 00:0b:82:05:22:05 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 60: arp who-has 192.168.101.191 tell 192.168.101.130
14:21:27.170577 00:0b:82:05:22:05 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 60: arp who-has 192.168.101.191 tell 192.168.101.130
14:21:27.495814 00:0b:82:05:22:0c > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 60: arp who-has 192.168.101.191 tell 192.168.101.135
14:21:27.495881 00:0b:82:05:22:0c > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 60: arp who-has 192.168.101.191 tell 192.168.101.135
14:21:28.151070 00:0b:82:05:22:05 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 60: arp who-has 192.168.101.191 tell 192.168.101.130
14:21:28.166780 00:b0:c2:e8:d8:1c > 33:33:00:00:00:01, ethertype IPv6 (0x86dd), length 118: fe80::2b0:c2ff:fee8:d81c > ff02::1: icmp6: router advertisement [class 0xe0]
14:21:28.476404 00:0b:82:05:22:0c > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 60: arp who-has 192.168.101.191 tell 192.168.101.135
14:21:28.492099 00:b0:c2:e8:d8:1c > 01:00:5e:00:00:05, ethertype IPv4 (0x0800), length 130: IP 192.168.110.20 > 224.0.0.5: OSPFv2, Hello (1), length: 80
14:21:28.631439 00:19:b9:e7:8a:d7 > 33:33:ff:e7:8a:d7, ethertype IPv6 (0x86dd), length 78: :: > ff02::1:ffe7:8ad7: icmp6: neighbor sol: who has fd4d:5643:2886:67:219:b9ff:fee7:8ad7
14:21:28.671611 00:0b:82:05:22:0a > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 60: arp who-has 192.168.101.191 tell 192.168.101.131
14:21:28.671684 00:0b:82:05:22:0a > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 60: arp who-has 192.168.101.191 tell 192.168.101.131
the packet handed to netif_receive_skb() does not have the vlan tag on
it. this allows all these packets to be processed by not only the
packet ptype handler, but also ip, arp, etc... this seems very wrong
as all vlan packets are stripped of their tag, then processed by the
kernel as if they didn't have a tag to begin with.
Normally vlan_skb_recv() would be the only handler to get these
packets, but ip_rcv(), arp_rcv(), ipv6_rcv() etc.. can be called
instead!
ipv6 for example will pay attention to router advertisements and add
global scope addresses to the base device even though those packets
came in on a vlan that would otherwise be ignored.
the packet socket recipient also has no idea which vlan each packet
came in on.
2)
If there is one or more vlan interfaces configured, it calls
vlan_hwaccel_receive_skb().
# ifconfig eth1 up
# vconfig add eth1 300
# ifconfig eth1.300 up
# tcpdump -s 2000 -e -n -i eth1
tcpdump: WARNING: eth1: no IPv4 address assigned
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 2000 bytes
[Nothing....]
when vlan_hwaccel_receive_skb() gets the packets it discards
everything except vid 300 that I configured above.
Shouldn't it pass these unknown vids back to the base device as tagged
packets, especially if IFF_PROMISC is set?
What is the expected behavior for these? Should
vlan_hwaccel_receive_skb() shim a vlan tag back on the packet and send
it to the base device if there is no vlan device to send to? Also, is
it up to the individual driver to have a vlan tag on the packet if it
uses netif_receive_skb() as in case 1 above?
--
Dave Johnson
Starent Networks
^ permalink raw reply
* Re: [PATCH 0/5] Make nicer CONFIG_NET_NS=n case code
From: Eric Dumazet @ 2007-10-31 18:49 UTC (permalink / raw)
To: Pavel Emelyanov; +Cc: David Miller, Linux Netdev List, Eric W. Biederman, devel
In-Reply-To: <4728D54F.2080208@openvz.org>
On Wed, 31 Oct 2007 22:19:43 +0300
Pavel Emelyanov <xemul@openvz.org> wrote:
> Currently we have the NET_NS config option, but the only change it
> makes is just return ERR_PTR(-EINVAL) inside the cloning call thus
> introducing a bunch of a dead code and making the reference counting
> unneeded. This is not very good.
>
> So clean the net_namespace.c to fix this.
>
> I have sent a set of patches to Andrew to make similar thing for
> other namespaces, which introduces the NAMESPACES option to turn
> all the namespaces off at once (to make embedded people suffer
> less). So after that stuff is in, there will be some more patches
> to tie all this together.
>
> What is to be done after this set is to make the register_pernet_xxx
> stuff smaller. Currently this code weights approximately 500 bytes,
> so it worths reducing it, but I haven't found a good solution yet.
Definitly wanted here. Thank you.
One more refcounting on each socket creation/deletion was expensive.
Maybe we can add a macro to get nd_net from a "struct net_device"
so that every instance of
if (dev->nd_net != &init_net)
goto drop;
can also be optimized away if !CONFIG_NET_NS
extern inline netdev_get_ns(struct netdevice *dev)
{
#ifdef CONFIG_NET_NS
return dev->nd_net;
#else
return &init_net;
#endif
}
...
if (netdev_get_ns(dev) != &init_net)
goto drop;
^ permalink raw reply
* Re: expected behavior of PF_PACKET on NETIF_F_HW_VLAN_RX device?
From: Stephen Hemminger @ 2007-10-31 19:33 UTC (permalink / raw)
To: Dave Johnson; +Cc: linux-kernel, netdev, Bin Guo
In-Reply-To: <18216.52455.698606.497464@zeus.sw.starentnetworks.com>
On Wed, 31 Oct 2007 14:43:51 -0400
Dave Johnson <djohnson+linux-kernel@sw.starentnetworks.com> wrote:
>
> Depending on the network driver, I'm seeing different behavior if
> a .1q packet is received to an PF_PACKET, SOCK_RAW, ETH_P_ALL socket.
>
>
> On devices what do not use NETIF_F_HW_VLAN_RX, the packet socket gets
> the complete packet with vlan tag included as the driver simply calls
> netif_receive_skb() or equivilant. packet_rcv() then gets the whole
> thing vlan tag included and sends this through the socket.
>
> vlan_skb_recv() also gets these all and will drop them because there
> are no vlans configured.
>
The VLAN acceleration grabs and hides the tag. It is a design flaw
that should be fixed, feel free to post a patch.
--
Stephen Hemminger <shemminger@linux-foundation.org>
^ permalink raw reply
* Re: [PATCH] ehea: add kexec support
From: Christoph Raisch @ 2007-10-31 19:48 UTC (permalink / raw)
To: michael
Cc: Jan-Bernd Themann, Jeff Garzik, linux-kernel, linux-ppc,
Marcus Eder, netdev, ossthema, Stefan Roscher, Thomas Q Klein
In-Reply-To: <1193784636.32504.4.camel@concordia>
Michael Ellerman <michael@ellerman.id.au> wrote on 30.10.2007 23:50:36:
>
> On Tue, 2007-10-30 at 09:39 +0100, Christoph Raisch wrote:
> >
> > Michael Ellerman <michael@ellerman.id.au> wrote on 28.10.2007 23:32:17:
> > Hope I didn't miss anything here...
>
> Perhaps. When we kdump the kernel does not call the reboot notifiers, so
> the code Jan-Bernd just added won't get called. So the eHEA resources
> won't be freed. When the kdump kernel tries to load the eHEA driver what
> will happen?
>
Good point.
If the device driver tries to allocate resources again (in the kdump
kernel),
which have been allocated before (in the crashed kernel) the hcalls will
fail because from the hypervisor view the resources are still in use.
Currently there's no method to find out the resource handles for these
HEA resources allocated by the crashed kernel within the hypervisor...
So we have to trigger a explicit deregister in the hypervisor before the
driver
is started again.
How do you recommend we should trigger this in the kdump process?
Is placing a hook into a ppc_md.machine_kexec be an option?
Gruss / Regards
Christoph R.
^ permalink raw reply
* Re: [PATCH]: Fix IP1000 config dependencies.
From: Francois Romieu @ 2007-10-31 20:04 UTC (permalink / raw)
To: David Miller; +Cc: jeff, netdev
In-Reply-To: <20071030.205905.75927379.davem@davemloft.net>
David Miller <davem@davemloft.net> :
[...]
> Noticed during some randconfig runs.
>
> [NET]: IP1000 driver needs MII.
It is fixed as of bbd82f956e0db6190b16a8a00d3ed5d979f488e8.
--
Ueimor
^ permalink raw reply
* Re: [PATCH 10/14 v2] nes: eeprom and phy routines
From: Roland Dreier @ 2007-10-31 20:26 UTC (permalink / raw)
To: ggrundstrom; +Cc: ewg, general, netdev
In-Reply-To: <200710192021.l9JKLGFU021817@neteffect.com>
> + /* TODO: deal with EEPROM endian issues */
This is pretty scary. Is the driver broken on big-endian systems now?
> +/*
> +"Everything you wanted to know about CRC algorithms, but were afraid to ask
> + for fear that errors in your understanding might be detected." Version : 3.
etc etc... can all this be replaced with what's in lib/crc32.c? (I
hope so)
- R.
^ permalink raw reply
* [ofa-general] Re: [PATCH 11/14 v2] nes: OpenFabrics kernel verbs
From: Roland Dreier @ 2007-10-31 20:56 UTC (permalink / raw)
To: ggrundstrom; +Cc: netdev, ewg, general
In-Reply-To: <200710192023.l9JKNFov021830@neteffect.com>
> +/**
> + * nes_post_send
> + */
> +static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr,
> + struct ib_send_wr **bad_wr)
> ...
> + switch (ib_wr->opcode) {
> ...
> + if (ib_wr->num_sge > nesdev->nesadapter->max_sge) {
> + err = -EINVAL;
> + break;
> + }
> ...
> + default:
> + /* error */
> + err = -EINVAL;
> + break;
looks like if you detect an error while posting a work request, you
break out of the switch statement but just continue through the while
loop going through the list of work reuqests. Which doesn't seem like
it will work very well.
^ permalink raw reply
* [PATCH] net: docbook fixes for netif_ functions
From: Stephen Hemminger @ 2007-10-31 21:08 UTC (permalink / raw)
To: David S. Miller, Randy.Dunlap; +Cc: netdev
Documentation updates for network interfaces.
1. Add doc for netif_napi_add
2. Remove doc for unused returns from netif_rx
3. Add doc for netif_receive_skb
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
--- a/include/linux/netdevice.h 2007-10-31 09:16:09.000000000 -0700
+++ b/include/linux/netdevice.h 2007-10-31 10:02:15.000000000 -0700
@@ -739,6 +739,16 @@ static inline void *netdev_priv(const st
*/
#define SET_NETDEV_DEV(net, pdev) ((net)->dev.parent = (pdev))
+/**
+ * netif_napi_add - initialize a napi context
+ * @dev: network device
+ * @napi: napi context
+ * @poll: polling function
+ * @weight: default weight
+ *
+ * netif_napi_add() must be used to initialize a napi context prior to calling
+ * *any* of the other napi related functions.
+ */
static inline void netif_napi_add(struct net_device *dev,
struct napi_struct *napi,
int (*poll)(struct napi_struct *, int),
--- a/net/core/dev.c 2007-10-31 09:16:09.000000000 -0700
+++ b/net/core/dev.c 2007-10-31 10:00:39.000000000 -0700
@@ -1751,9 +1751,6 @@ DEFINE_PER_CPU(struct netif_rx_stats, ne
*
* return values:
* NET_RX_SUCCESS (no congestion)
- * NET_RX_CN_LOW (low congestion)
- * NET_RX_CN_MOD (moderate congestion)
- * NET_RX_CN_HIGH (high congestion)
* NET_RX_DROP (packet was dropped)
*
*/
@@ -2001,6 +1998,21 @@ out:
}
#endif
+/**
+ * netif_receive_skb - process receive buffer from network
+ * @skb: buffer to process
+ *
+ * netif_receive_skb() is the main receive data processing function.
+ * It always succeeds. The buffer may be dropped during processing
+ * for congestion control or by the protocol layers.
+ *
+ * This function may only be called from softirq context and interrupts
+ * should be enabled.
+ *
+ * return values (usually ignored).
+ * NET_RX_SUCCESS (no congestion)
+ * NET_RX_DROP (packet was dropped)
+ */
int netif_receive_skb(struct sk_buff *skb)
{
struct packet_type *ptype, *pt_prev;
^ permalink raw reply
* [PATCH] - e1000_ethtool.c - convert macros to functions
From: Joe Perches @ 2007-10-31 21:18 UTC (permalink / raw)
To: netdev; +Cc: e1000-devel, Auke Kok, Jeff Garzik
Convert REG_PATTERN_TEST and REG_SET_AND_CHECK macros to functions
Reduces x86 defconfig image by about 3k
compiled, untested (no hardware)
Signed-off-by: Joe Perches <joe@perches.com>
New:
$ size vmlinux
text data bss dec hex filename
4792735 490626 606208 5889569 59de21 vmlinux
Current:
$ size vmlinux
text data bss dec hex filename
4795759 490626 606208 5892593 59e9f1 vmlinux
---
drivers/net/e1000/e1000_ethtool.c | 185 +++++++++++++++++++++++++------------
drivers/net/e1000/e1000_osdep.h | 42 +++++----
2 files changed, 149 insertions(+), 78 deletions(-)
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index 667f18b..2627395 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -728,37 +728,45 @@ err_setup:
return err;
}
-#define REG_PATTERN_TEST(R, M, W) \
-{ \
- uint32_t pat, val; \
- const uint32_t test[] = \
- {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; \
- for (pat = 0; pat < ARRAY_SIZE(test); pat++) { \
- E1000_WRITE_REG(&adapter->hw, R, (test[pat] & W)); \
- val = E1000_READ_REG(&adapter->hw, R); \
- if (val != (test[pat] & W & M)) { \
- DPRINTK(DRV, ERR, "pattern test reg %04X failed: got " \
- "0x%08X expected 0x%08X\n", \
- E1000_##R, val, (test[pat] & W & M)); \
- *data = (adapter->hw.mac_type < e1000_82543) ? \
- E1000_82542_##R : E1000_##R; \
- return 1; \
- } \
- } \
+static bool reg_pattern_test(struct e1000_adapter *adapter, uint64_t *data,
+ int reg, uint32_t mask, uint32_t write)
+{
+ static const uint32_t test[] =
+ {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};
+ uint8_t __iomem *address = adapter->hw.hw_addr + reg;
+ uint32_t read;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(test); i++) {
+ writel(write & test[i], address);
+ read = readl(address);
+ if (read != (write & test[i] & mask)) {
+ DPRINTK(DRV, ERR, "pattern test reg %04X failed: "
+ "got 0x%08X expected 0x%08X\n",
+ reg, read, (write & test[i] & mask));
+ *data = reg;
+ return true;
+ }
+ }
+ return false;
}
-#define REG_SET_AND_CHECK(R, M, W) \
-{ \
- uint32_t val; \
- E1000_WRITE_REG(&adapter->hw, R, W & M); \
- val = E1000_READ_REG(&adapter->hw, R); \
- if ((W & M) != (val & M)) { \
- DPRINTK(DRV, ERR, "set/check reg %04X test failed: got 0x%08X "\
- "expected 0x%08X\n", E1000_##R, (val & M), (W & M)); \
- *data = (adapter->hw.mac_type < e1000_82543) ? \
- E1000_82542_##R : E1000_##R; \
- return 1; \
- } \
+static bool reg_set_and_check(struct e1000_adapter *adapter, uint64_t *data,
+ int reg, uint32_t mask, uint32_t write)
+{
+ uint8_t __iomem *address = adapter->hw.hw_addr + reg;
+ uint32_t read;
+
+ writel(write & mask, address);
+ read = readl(address);
+ if ((read & mask) != (write & mask)) {
+ DPRINTK(DRV, ERR, "set/check reg %04X test failed: "
+ "got 0x%08X expected 0x%08X\n",
+ reg, (read & mask), (write & mask));
+ *data = reg;
+ return true;
+ }
+ return false;
}
static int
@@ -800,58 +808,115 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
E1000_WRITE_REG(&adapter->hw, STATUS, before);
if (adapter->hw.mac_type != e1000_ich8lan) {
- REG_PATTERN_TEST(FCAL, 0xFFFFFFFF, 0xFFFFFFFF);
- REG_PATTERN_TEST(FCAH, 0x0000FFFF, 0xFFFFFFFF);
- REG_PATTERN_TEST(FCT, 0x0000FFFF, 0xFFFFFFFF);
- REG_PATTERN_TEST(VET, 0x0000FFFF, 0xFFFFFFFF);
+ if (reg_pattern_test(adapter, data,
+ E1000_REG(&adapter->hw, FCAL),
+ 0xFFFFFFFF, 0xFFFFFFFF) ||
+ reg_pattern_test(adapter, data,
+ E1000_REG(&adapter->hw, FCAH),
+ 0x0000FFFF, 0xFFFFFFFF) ||
+ reg_pattern_test(adapter, data,
+ E1000_REG(&adapter->hw, FCT),
+ 0x0000FFFF, 0xFFFFFFFF) ||
+ reg_pattern_test(adapter, data,
+ E1000_REG(&adapter->hw, VET),
+ 0x0000FFFF, 0xFFFFFFFF))
+ return 1;
}
- REG_PATTERN_TEST(RDTR, 0x0000FFFF, 0xFFFFFFFF);
- REG_PATTERN_TEST(RDBAH, 0xFFFFFFFF, 0xFFFFFFFF);
- REG_PATTERN_TEST(RDLEN, 0x000FFF80, 0x000FFFFF);
- REG_PATTERN_TEST(RDH, 0x0000FFFF, 0x0000FFFF);
- REG_PATTERN_TEST(RDT, 0x0000FFFF, 0x0000FFFF);
- REG_PATTERN_TEST(FCRTH, 0x0000FFF8, 0x0000FFF8);
- REG_PATTERN_TEST(FCTTV, 0x0000FFFF, 0x0000FFFF);
- REG_PATTERN_TEST(TIPG, 0x3FFFFFFF, 0x3FFFFFFF);
- REG_PATTERN_TEST(TDBAH, 0xFFFFFFFF, 0xFFFFFFFF);
- REG_PATTERN_TEST(TDLEN, 0x000FFF80, 0x000FFFFF);
+ if (reg_pattern_test(adapter, data, E1000_REG(&adapter->hw, RDTR),
+ 0x0000FFFF, 0xFFFFFFFF) ||
+ reg_pattern_test(adapter, data, E1000_REG(&adapter->hw, RDBAH),
+ 0xFFFFFFFF, 0xFFFFFFFF) ||
+ reg_pattern_test(adapter, data, E1000_REG(&adapter->hw, RDLEN),
+ 0x000FFF80, 0x000FFFFF) ||
+ reg_pattern_test(adapter, data, E1000_REG(&adapter->hw, RDH),
+ 0x0000FFFF, 0x0000FFFF) ||
+ reg_pattern_test(adapter, data, E1000_REG(&adapter->hw, RDT),
+ 0x0000FFFF, 0x0000FFFF) ||
+ reg_pattern_test(adapter, data, E1000_REG(&adapter->hw, FCRTH),
+ 0x0000FFF8, 0x0000FFF8) ||
+ reg_pattern_test(adapter, data, E1000_REG(&adapter->hw, FCTTV),
+ 0x0000FFFF, 0x0000FFFF) ||
+ reg_pattern_test(adapter, data, E1000_REG(&adapter->hw, TIPG),
+ 0x3FFFFFFF, 0x3FFFFFFF) ||
+ reg_pattern_test(adapter, data, E1000_REG(&adapter->hw, TDBAH),
+ 0xFFFFFFFF, 0xFFFFFFFF) ||
+ reg_pattern_test(adapter, data, E1000_REG(&adapter->hw, TDLEN),
+ 0x000FFF80, 0x000FFFFF))
+ return 1;
- REG_SET_AND_CHECK(RCTL, 0xFFFFFFFF, 0x00000000);
+ if (reg_set_and_check(adapter, data, E1000_REG(&adapter->hw, RCTL),
+ 0xFFFFFFFF, 0x00000000))
+ return 1;
before = (adapter->hw.mac_type == e1000_ich8lan ?
0x06C3B33E : 0x06DFB3FE);
- REG_SET_AND_CHECK(RCTL, before, 0x003FFFFB);
- REG_SET_AND_CHECK(TCTL, 0xFFFFFFFF, 0x00000000);
+ if (reg_set_and_check(adapter, data, E1000_REG(&adapter->hw, RCTL),
+ before, 0x003FFFFB) ||
+ reg_set_and_check(adapter, data, E1000_REG(&adapter->hw, TCTL),
+ 0xFFFFFFFF, 0x00000000))
+ return 1;
if (adapter->hw.mac_type >= e1000_82543) {
- REG_SET_AND_CHECK(RCTL, before, 0xFFFFFFFF);
- REG_PATTERN_TEST(RDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
- if (adapter->hw.mac_type != e1000_ich8lan)
- REG_PATTERN_TEST(TXCW, 0xC000FFFF, 0x0000FFFF);
- REG_PATTERN_TEST(TDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
- REG_PATTERN_TEST(TIDV, 0x0000FFFF, 0x0000FFFF);
+ if (reg_set_and_check(adapter, data,
+ E1000_REG(&adapter->hw, RCTL),
+ before, 0xFFFFFFFF))
+ return 1;
+ if (reg_pattern_test(adapter, data,
+ E1000_REG(&adapter->hw, RDBAL),
+ 0xFFFFFFF0, 0xFFFFFFFF))
+ return 1;
+ if (adapter->hw.mac_type != e1000_ich8lan) {
+ if (reg_pattern_test(adapter, data,
+ E1000_REG(&adapter->hw, TXCW),
+ 0xC000FFFF, 0x0000FFFF))
+ return 1;
+ }
+ if (reg_pattern_test(adapter, data,
+ E1000_REG(&adapter->hw, TDBAL),
+ 0xFFFFFFF0, 0xFFFFFFFF) ||
+ reg_pattern_test(adapter, data,
+ E1000_REG(&adapter->hw, TIDV),
+ 0x0000FFFF, 0x0000FFFF))
+ return 1;
value = (adapter->hw.mac_type == e1000_ich8lan ?
E1000_RAR_ENTRIES_ICH8LAN : E1000_RAR_ENTRIES);
for (i = 0; i < value; i++) {
- REG_PATTERN_TEST(RA + (((i << 1) + 1) << 2), 0x8003FFFF,
- 0xFFFFFFFF);
+ if (reg_pattern_test(adapter, data,
+ E1000_REG(&adapter->hw, RA) +
+ (((i << 1) + 1) << 2),
+ 0x8003FFFF, 0xFFFFFFFF))
+ return 1;
}
} else {
- REG_SET_AND_CHECK(RCTL, 0xFFFFFFFF, 0x01FFFFFF);
- REG_PATTERN_TEST(RDBAL, 0xFFFFF000, 0xFFFFFFFF);
- REG_PATTERN_TEST(TXCW, 0x0000FFFF, 0x0000FFFF);
- REG_PATTERN_TEST(TDBAL, 0xFFFFF000, 0xFFFFFFFF);
+ if (reg_set_and_check(adapter, data,
+ E1000_REG(&adapter->hw, RCTL),
+ 0xFFFFFFFF, 0x01FFFFFF))
+ return 1;
+ if (reg_pattern_test(adapter, data,
+ E1000_REG(&adapter->hw, RDBAL),
+ 0xFFFFF000, 0xFFFFFFFF) ||
+ reg_pattern_test(adapter, data,
+ E1000_REG(&adapter->hw, TXCW),
+ 0x0000FFFF, 0x0000FFFF) ||
+ reg_pattern_test(adapter, data,
+ E1000_REG(&adapter->hw, TDBAL),
+ 0xFFFFF000, 0xFFFFFFFF))
+ return 1;
}
value = (adapter->hw.mac_type == e1000_ich8lan ?
E1000_MC_TBL_SIZE_ICH8LAN : E1000_MC_TBL_SIZE);
- for (i = 0; i < value; i++)
- REG_PATTERN_TEST(MTA + (i << 2), 0xFFFFFFFF, 0xFFFFFFFF);
+ for (i = 0; i < value; i++) {
+ if (reg_pattern_test(adapter, data,
+ E1000_REG(&adapter->hw, MTA) + (i << 2),
+ 0xFFFFFFFF, 0xFFFFFFFF))
+ return 1;
+ }
*data = 0;
return 0;
diff --git a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h
index 10af742..7d70eb6 100644
--- a/drivers/net/e1000/e1000_osdep.h
+++ b/drivers/net/e1000/e1000_osdep.h
@@ -61,24 +61,30 @@ typedef enum {
#define DEBUGOUT3 DEBUGOUT2
#define DEBUGOUT7 DEBUGOUT3
-
-#define E1000_WRITE_REG(a, reg, value) ( \
- writel((value), ((a)->hw_addr + \
- (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg))))
-
-#define E1000_READ_REG(a, reg) ( \
- readl((a)->hw_addr + \
- (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg)))
-
-#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \
- writel((value), ((a)->hw_addr + \
- (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
- ((offset) << 2))))
-
-#define E1000_READ_REG_ARRAY(a, reg, offset) ( \
- readl((a)->hw_addr + \
- (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
- ((offset) << 2)))
+#define E1000_REG(a, reg) \
+ (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg)
+
+#define E1000_WRITE_REG(a, reg, value) \
+ (writel((value), ((a)->hw_addr + \
+ (((a)->mac_type >= e1000_82543) \
+ ? E1000_##reg : E1000_82542_##reg))))
+
+#define E1000_READ_REG(a, reg) \
+ (readl((a)->hw_addr + \
+ (((a)->mac_type >= e1000_82543) \
+ ? E1000_##reg : E1000_82542_##reg)))
+
+#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) \
+ (writel((value), ((a)->hw_addr + \
+ (((a)->mac_type >= e1000_82543) \
+ ? E1000_##reg : E1000_82542_##reg) +\
+ ((offset) << 2))))
+
+#define E1000_READ_REG_ARRAY(a, reg, offset) \
+ (readl((a)->hw_addr + \
+ (((a)->mac_type >= e1000_82543) \
+ ? E1000_##reg : E1000_82542_##reg) + \
+ ((offset) << 2)))
#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY
#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY
^ permalink raw reply related
* Re: [PATCH] - e1000_ethtool.c - convert macros to functions
From: Kok, Auke @ 2007-10-31 21:30 UTC (permalink / raw)
To: Joe Perches; +Cc: netdev, e1000-devel, Auke Kok, Jeff Garzik
In-Reply-To: <1193865488.11020.11.camel@localhost>
Joe Perches wrote:
> Convert REG_PATTERN_TEST and REG_SET_AND_CHECK macros to functions
> Reduces x86 defconfig image by about 3k
>
> compiled, untested (no hardware)
>
> Signed-off-by: Joe Perches <joe@perches.com>
>
> New:
>
> $ size vmlinux
> text data bss dec hex filename
> 4792735 490626 606208 5889569 59de21 vmlinux
>
> Current:
>
> $ size vmlinux
> text data bss dec hex filename
> 4795759 490626 606208 5892593 59e9f1 vmlinux
>
> ---
>
> drivers/net/e1000/e1000_ethtool.c | 185 +++++++++++++++++++++++++------------
> drivers/net/e1000/e1000_osdep.h | 42 +++++----
> 2 files changed, 149 insertions(+), 78 deletions(-)
>
> diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
> index 667f18b..2627395 100644
> --- a/drivers/net/e1000/e1000_ethtool.c
> +++ b/drivers/net/e1000/e1000_ethtool.c
> @@ -728,37 +728,45 @@ err_setup:
> return err;
> }
>
> -#define REG_PATTERN_TEST(R, M, W) \
> -{ \
> - uint32_t pat, val; \
> - const uint32_t test[] = \
> - {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; \
> - for (pat = 0; pat < ARRAY_SIZE(test); pat++) { \
> - E1000_WRITE_REG(&adapter->hw, R, (test[pat] & W)); \
> - val = E1000_READ_REG(&adapter->hw, R); \
> - if (val != (test[pat] & W & M)) { \
> - DPRINTK(DRV, ERR, "pattern test reg %04X failed: got " \
> - "0x%08X expected 0x%08X\n", \
> - E1000_##R, val, (test[pat] & W & M)); \
> - *data = (adapter->hw.mac_type < e1000_82543) ? \
> - E1000_82542_##R : E1000_##R; \
> - return 1; \
> - } \
> - } \
> +static bool reg_pattern_test(struct e1000_adapter *adapter, uint64_t *data,
> + int reg, uint32_t mask, uint32_t write)
> +{
> + static const uint32_t test[] =
> + {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};
> + uint8_t __iomem *address = adapter->hw.hw_addr + reg;
> + uint32_t read;
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(test); i++) {
> + writel(write & test[i], address);
> + read = readl(address);
> + if (read != (write & test[i] & mask)) {
> + DPRINTK(DRV, ERR, "pattern test reg %04X failed: "
> + "got 0x%08X expected 0x%08X\n",
> + reg, read, (write & test[i] & mask));
> + *data = reg;
> + return true;
> + }
> + }
> + return false;
that's not a bad idea, however see below:
> }
>
> -#define REG_SET_AND_CHECK(R, M, W) \
> -{ \
> - uint32_t val; \
> - E1000_WRITE_REG(&adapter->hw, R, W & M); \
> - val = E1000_READ_REG(&adapter->hw, R); \
> - if ((W & M) != (val & M)) { \
> - DPRINTK(DRV, ERR, "set/check reg %04X test failed: got 0x%08X "\
> - "expected 0x%08X\n", E1000_##R, (val & M), (W & M)); \
> - *data = (adapter->hw.mac_type < e1000_82543) ? \
> - E1000_82542_##R : E1000_##R; \
> - return 1; \
> - } \
> +static bool reg_set_and_check(struct e1000_adapter *adapter, uint64_t *data,
> + int reg, uint32_t mask, uint32_t write)
> +{
> + uint8_t __iomem *address = adapter->hw.hw_addr + reg;
> + uint32_t read;
> +
> + writel(write & mask, address);
> + read = readl(address);
> + if ((read & mask) != (write & mask)) {
> + DPRINTK(DRV, ERR, "set/check reg %04X test failed: "
> + "got 0x%08X expected 0x%08X\n",
> + reg, (read & mask), (write & mask));
> + *data = reg;
> + return true;
> + }
> + return false;
> }
>
> static int
> @@ -800,58 +808,115 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
> E1000_WRITE_REG(&adapter->hw, STATUS, before);
>
> if (adapter->hw.mac_type != e1000_ich8lan) {
> - REG_PATTERN_TEST(FCAL, 0xFFFFFFFF, 0xFFFFFFFF);
> - REG_PATTERN_TEST(FCAH, 0x0000FFFF, 0xFFFFFFFF);
> - REG_PATTERN_TEST(FCT, 0x0000FFFF, 0xFFFFFFFF);
> - REG_PATTERN_TEST(VET, 0x0000FFFF, 0xFFFFFFFF);
> + if (reg_pattern_test(adapter, data,
> + E1000_REG(&adapter->hw, FCAL),
> + 0xFFFFFFFF, 0xFFFFFFFF) ||
> + reg_pattern_test(adapter, data,
> + E1000_REG(&adapter->hw, FCAH),
> + 0x0000FFFF, 0xFFFFFFFF) ||
> + reg_pattern_test(adapter, data,
> + E1000_REG(&adapter->hw, FCT),
> + 0x0000FFFF, 0xFFFFFFFF) ||
> + reg_pattern_test(adapter, data,
> + E1000_REG(&adapter->hw, VET),
> + 0x0000FFFF, 0xFFFFFFFF))
> + return 1;
can't we keep the macro here (and just make it call the function instead of
expanding). the resulting code is much more lenghty and contains all these logic
traps that the previous code didn't have.
just have the macro expand to `if (reg_pattern_test(...)) return 1)` and you don't
need to change any of the calling lines.
> }
>
> - REG_PATTERN_TEST(RDTR, 0x0000FFFF, 0xFFFFFFFF);
> - REG_PATTERN_TEST(RDBAH, 0xFFFFFFFF, 0xFFFFFFFF);
> - REG_PATTERN_TEST(RDLEN, 0x000FFF80, 0x000FFFFF);
> - REG_PATTERN_TEST(RDH, 0x0000FFFF, 0x0000FFFF);
> - REG_PATTERN_TEST(RDT, 0x0000FFFF, 0x0000FFFF);
> - REG_PATTERN_TEST(FCRTH, 0x0000FFF8, 0x0000FFF8);
> - REG_PATTERN_TEST(FCTTV, 0x0000FFFF, 0x0000FFFF);
> - REG_PATTERN_TEST(TIPG, 0x3FFFFFFF, 0x3FFFFFFF);
> - REG_PATTERN_TEST(TDBAH, 0xFFFFFFFF, 0xFFFFFFFF);
> - REG_PATTERN_TEST(TDLEN, 0x000FFF80, 0x000FFFFF);
> + if (reg_pattern_test(adapter, data, E1000_REG(&adapter->hw, RDTR),
> + 0x0000FFFF, 0xFFFFFFFF) ||
> + reg_pattern_test(adapter, data, E1000_REG(&adapter->hw, RDBAH),
> + 0xFFFFFFFF, 0xFFFFFFFF) ||
> + reg_pattern_test(adapter, data, E1000_REG(&adapter->hw, RDLEN),
> + 0x000FFF80, 0x000FFFFF) ||
> + reg_pattern_test(adapter, data, E1000_REG(&adapter->hw, RDH),
> + 0x0000FFFF, 0x0000FFFF) ||
> + reg_pattern_test(adapter, data, E1000_REG(&adapter->hw, RDT),
> + 0x0000FFFF, 0x0000FFFF) ||
> + reg_pattern_test(adapter, data, E1000_REG(&adapter->hw, FCRTH),
> + 0x0000FFF8, 0x0000FFF8) ||
> + reg_pattern_test(adapter, data, E1000_REG(&adapter->hw, FCTTV),
> + 0x0000FFFF, 0x0000FFFF) ||
> + reg_pattern_test(adapter, data, E1000_REG(&adapter->hw, TIPG),
> + 0x3FFFFFFF, 0x3FFFFFFF) ||
> + reg_pattern_test(adapter, data, E1000_REG(&adapter->hw, TDBAH),
> + 0xFFFFFFFF, 0xFFFFFFFF) ||
> + reg_pattern_test(adapter, data, E1000_REG(&adapter->hw, TDLEN),
> + 0x000FFF80, 0x000FFFFF))
> + return 1;
>
> - REG_SET_AND_CHECK(RCTL, 0xFFFFFFFF, 0x00000000);
> + if (reg_set_and_check(adapter, data, E1000_REG(&adapter->hw, RCTL),
> + 0xFFFFFFFF, 0x00000000))
> + return 1;
>
> before = (adapter->hw.mac_type == e1000_ich8lan ?
> 0x06C3B33E : 0x06DFB3FE);
> - REG_SET_AND_CHECK(RCTL, before, 0x003FFFFB);
> - REG_SET_AND_CHECK(TCTL, 0xFFFFFFFF, 0x00000000);
> + if (reg_set_and_check(adapter, data, E1000_REG(&adapter->hw, RCTL),
> + before, 0x003FFFFB) ||
> + reg_set_and_check(adapter, data, E1000_REG(&adapter->hw, TCTL),
> + 0xFFFFFFFF, 0x00000000))
> + return 1;
>
> if (adapter->hw.mac_type >= e1000_82543) {
>
> - REG_SET_AND_CHECK(RCTL, before, 0xFFFFFFFF);
> - REG_PATTERN_TEST(RDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
> - if (adapter->hw.mac_type != e1000_ich8lan)
> - REG_PATTERN_TEST(TXCW, 0xC000FFFF, 0x0000FFFF);
> - REG_PATTERN_TEST(TDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
> - REG_PATTERN_TEST(TIDV, 0x0000FFFF, 0x0000FFFF);
> + if (reg_set_and_check(adapter, data,
> + E1000_REG(&adapter->hw, RCTL),
> + before, 0xFFFFFFFF))
> + return 1;
> + if (reg_pattern_test(adapter, data,
> + E1000_REG(&adapter->hw, RDBAL),
> + 0xFFFFFFF0, 0xFFFFFFFF))
> + return 1;
> + if (adapter->hw.mac_type != e1000_ich8lan) {
> + if (reg_pattern_test(adapter, data,
> + E1000_REG(&adapter->hw, TXCW),
> + 0xC000FFFF, 0x0000FFFF))
> + return 1;
> + }
> + if (reg_pattern_test(adapter, data,
> + E1000_REG(&adapter->hw, TDBAL),
> + 0xFFFFFFF0, 0xFFFFFFFF) ||
> + reg_pattern_test(adapter, data,
> + E1000_REG(&adapter->hw, TIDV),
> + 0x0000FFFF, 0x0000FFFF))
> + return 1;
> value = (adapter->hw.mac_type == e1000_ich8lan ?
> E1000_RAR_ENTRIES_ICH8LAN : E1000_RAR_ENTRIES);
> for (i = 0; i < value; i++) {
> - REG_PATTERN_TEST(RA + (((i << 1) + 1) << 2), 0x8003FFFF,
> - 0xFFFFFFFF);
> + if (reg_pattern_test(adapter, data,
> + E1000_REG(&adapter->hw, RA) +
> + (((i << 1) + 1) << 2),
> + 0x8003FFFF, 0xFFFFFFFF))
> + return 1;
> }
>
> } else {
>
> - REG_SET_AND_CHECK(RCTL, 0xFFFFFFFF, 0x01FFFFFF);
> - REG_PATTERN_TEST(RDBAL, 0xFFFFF000, 0xFFFFFFFF);
> - REG_PATTERN_TEST(TXCW, 0x0000FFFF, 0x0000FFFF);
> - REG_PATTERN_TEST(TDBAL, 0xFFFFF000, 0xFFFFFFFF);
> + if (reg_set_and_check(adapter, data,
> + E1000_REG(&adapter->hw, RCTL),
> + 0xFFFFFFFF, 0x01FFFFFF))
> + return 1;
> + if (reg_pattern_test(adapter, data,
> + E1000_REG(&adapter->hw, RDBAL),
> + 0xFFFFF000, 0xFFFFFFFF) ||
> + reg_pattern_test(adapter, data,
> + E1000_REG(&adapter->hw, TXCW),
> + 0x0000FFFF, 0x0000FFFF) ||
> + reg_pattern_test(adapter, data,
> + E1000_REG(&adapter->hw, TDBAL),
> + 0xFFFFF000, 0xFFFFFFFF))
> + return 1;
>
> }
>
> value = (adapter->hw.mac_type == e1000_ich8lan ?
> E1000_MC_TBL_SIZE_ICH8LAN : E1000_MC_TBL_SIZE);
> - for (i = 0; i < value; i++)
> - REG_PATTERN_TEST(MTA + (i << 2), 0xFFFFFFFF, 0xFFFFFFFF);
> + for (i = 0; i < value; i++) {
> + if (reg_pattern_test(adapter, data,
> + E1000_REG(&adapter->hw, MTA) + (i << 2),
> + 0xFFFFFFFF, 0xFFFFFFFF))
> + return 1;
> + }
>
> *data = 0;
> return 0;
> diff --git a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h
> index 10af742..7d70eb6 100644
> --- a/drivers/net/e1000/e1000_osdep.h
> +++ b/drivers/net/e1000/e1000_osdep.h
> @@ -61,24 +61,30 @@ typedef enum {
> #define DEBUGOUT3 DEBUGOUT2
> #define DEBUGOUT7 DEBUGOUT3
>
> -
> -#define E1000_WRITE_REG(a, reg, value) ( \
> - writel((value), ((a)->hw_addr + \
> - (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg))))
> -
> -#define E1000_READ_REG(a, reg) ( \
> - readl((a)->hw_addr + \
> - (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg)))
> -
> -#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \
> - writel((value), ((a)->hw_addr + \
> - (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
> - ((offset) << 2))))
> -
> -#define E1000_READ_REG_ARRAY(a, reg, offset) ( \
> - readl((a)->hw_addr + \
> - (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
> - ((offset) << 2)))
> +#define E1000_REG(a, reg) \
> + (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg)
> +
> +#define E1000_WRITE_REG(a, reg, value) \
> + (writel((value), ((a)->hw_addr + \
> + (((a)->mac_type >= e1000_82543) \
> + ? E1000_##reg : E1000_82542_##reg))))
> +
> +#define E1000_READ_REG(a, reg) \
> + (readl((a)->hw_addr + \
> + (((a)->mac_type >= e1000_82543) \
> + ? E1000_##reg : E1000_82542_##reg)))
> +
> +#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) \
> + (writel((value), ((a)->hw_addr + \
> + (((a)->mac_type >= e1000_82543) \
> + ? E1000_##reg : E1000_82542_##reg) +\
> + ((offset) << 2))))
> +
> +#define E1000_READ_REG_ARRAY(a, reg, offset) \
> + (readl((a)->hw_addr + \
> + (((a)->mac_type >= e1000_82543) \
> + ? E1000_##reg : E1000_82542_##reg) + \
> + ((offset) << 2)))
did you have to change these macro's ?
also, I'm a bit inclined to prefer a patch for e1000e for now as we're about to
move the pci-express hardware over, but we can certainly merge something like this
in e1000 after the move as well.
Auke
^ permalink raw reply
* Re: [PATCH 0/5] Make nicer CONFIG_NET_NS=n case code
From: Daniel Lezcano @ 2007-10-31 21:35 UTC (permalink / raw)
To: Eric Dumazet
Cc: Pavel Emelyanov, David Miller, Linux Netdev List,
Eric W. Biederman, devel
In-Reply-To: <20071031194924.2436843e.dada1@cosmosbay.com>
Eric Dumazet wrote:
> On Wed, 31 Oct 2007 22:19:43 +0300
> Pavel Emelyanov <xemul@openvz.org> wrote:
>
>> Currently we have the NET_NS config option, but the only change it
>> makes is just return ERR_PTR(-EINVAL) inside the cloning call thus
>> introducing a bunch of a dead code and making the reference counting
>> unneeded. This is not very good.
>>
>> So clean the net_namespace.c to fix this.
>>
>> I have sent a set of patches to Andrew to make similar thing for
>> other namespaces, which introduces the NAMESPACES option to turn
>> all the namespaces off at once (to make embedded people suffer
>> less). So after that stuff is in, there will be some more patches
>> to tie all this together.
>>
>> What is to be done after this set is to make the register_pernet_xxx
>> stuff smaller. Currently this code weights approximately 500 bytes,
>> so it worths reducing it, but I haven't found a good solution yet.
>
> Definitly wanted here. Thank you.
> One more refcounting on each socket creation/deletion was expensive.
>
> Maybe we can add a macro to get nd_net from a "struct net_device"
> so that every instance of
>
> if (dev->nd_net != &init_net)
> goto drop;
>
> can also be optimized away if !CONFIG_NET_NS
>
> extern inline netdev_get_ns(struct netdevice *dev)
> {
> #ifdef CONFIG_NET_NS
> return dev->nd_net;
> #else
> return &init_net;
> #endif
> }
Or something like:
#ifdef CONFIG_NET_NS
static inline int init_net_dev(struct net_device *dev)
{
return dev->nd_net == &init_net;
}
#else
static inline int init_net_dev(struct net_device *dev)
{
return 1;
}
#endif
By the way, this kind of test will disappear when the network namespace
will be complete and take into account the differents protocols.
^ permalink raw reply
* [PATCH]: Fix myri10ge NAPI oops & warnings
From: Andrew Gallatin @ 2007-10-31 21:40 UTC (permalink / raw)
To: shemminger; +Cc: jeff, netdev
[-- Attachment #1: Type: text/plain, Size: 1470 bytes --]
When testing the myri10ge driver with 2.6.24-rc1, I found
that the machine crashed under heavy load:
Unable to handle kernel paging request at 0000000000100108 RIP:
[<ffffffff803cc8dd>] net_rx_action+0x11b/0x184
The address corresponds to the list_move_tail() in
netif_rx_complete():
if (unlikely(work == weight))
list_move_tail(&n->poll_list, list);
Eventually, I traced the crashes to calling netif_rx_complete() with
work_done == budget. From looking at other drivers, it appears that
one should only call netif_rx_complete() when work_done < budget.
To fix it, I changed the test in myri10ge_poll() so that it refers
to to work_done rather than looking at the rx ring status. If
work_done is < budget, then that implies we have no more packets to
process. Any races will be resolved by the NIC when the write to
irq_claim is made.
In myri10ge_clean_rx_done(), if we ever exceeded our budget, it would
report a work_done one larger than was acutally done. This is because
the increment was done in the conditional, so work_done would be
incremented regardless of whether or not the test passed or failed.
This would lead to the WARN_ON_ONCE(work > weight); warning in
net_rx_action triggering. I've moved the increment of work_done
inside the loop. Note that this would only be a problem when we had
exceeded our budget.
Signed off by: Andrew Gallatin <gallatin@myri.com>
Andrew Gallatin Myricom Inc
[-- Attachment #2: myri10ge-napi-oops.diff --]
[-- Type: text/plain, Size: 1360 bytes --]
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index 366e62a..0f306dd 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -1151,7 +1151,7 @@ static inline int myri10ge_clean_rx_done
u16 length;
__wsum checksum;
- while (rx_done->entry[idx].length != 0 && work_done++ < budget) {
+ while (rx_done->entry[idx].length != 0 && work_done < budget) {
length = ntohs(rx_done->entry[idx].length);
rx_done->entry[idx].length = 0;
checksum = csum_unfold(rx_done->entry[idx].checksum);
@@ -1167,6 +1167,7 @@ static inline int myri10ge_clean_rx_done
rx_bytes += rx_ok * (unsigned long)length;
cnt++;
idx = cnt & (myri10ge_max_intr_slots - 1);
+ work_done++;
}
rx_done->idx = idx;
rx_done->cnt = cnt;
@@ -1233,13 +1234,12 @@ static int myri10ge_poll(struct napi_str
struct myri10ge_priv *mgp =
container_of(napi, struct myri10ge_priv, napi);
struct net_device *netdev = mgp->dev;
- struct myri10ge_rx_done *rx_done = &mgp->rx_done;
int work_done;
/* process as many rx events as NAPI will allow */
work_done = myri10ge_clean_rx_done(mgp, budget);
- if (rx_done->entry[rx_done->idx].length == 0 || !netif_running(netdev)) {
+ if (work_done < budget || !netif_running(netdev)) {
netif_rx_complete(netdev, napi);
put_be32(htonl(3), mgp->irq_claim);
}
^ 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