* Re: [PATCH] igb/e1000e/e1000/e100: make wol usable
From: Waskiewicz Jr, Peter P @ 2009-07-22 20:00 UTC (permalink / raw)
To: Andy Gospodarek
Cc: Alexander Duyck, Ronciak, John, netdev@vger.kernel.org,
Kirsher, Jeffrey T, Brandeburg, Jesse, Allan, Bruce W,
Waskiewicz Jr, Peter P, stable@kernel.org
In-Reply-To: <20090722193400.GN8515@gospo.rdu.redhat.com>
> [PATCH] ixgbe: remove unnecessary call to device_init_wakeup
>
> Calls to device_init_wakeup should not be necessary in drivers that use
> device_set_wakeup_enable since pci_pm_init will set the can_wakeup flag
> for the device when initialized.
>
> I can't test this since I don't have any of the 82599 KX4 interfaces
> (the only ones capable of WOL), but I did instrument ixgbe_probe and
> know that can_wakeup=1 when device_init_wakeup is removed.
>
> Signed-off-by: Andy Gospodarek <andy@greyhouse.net>
>
> ---
>
> ixgbe_main.c | 1 -
> 1 file changed, 1 deletion(-)
>
> diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
> index 79f60e8..2f15abf 100644
> --- a/drivers/net/ixgbe/ixgbe_main.c
> +++ b/drivers/net/ixgbe/ixgbe_main.c
> @@ -5640,7 +5640,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
> adapter->wol = 0;
> break;
> }
> - device_init_wakeup(&adapter->pdev->dev, true);
> device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
>
> /* pick up the PCI bus settings for reporting later */
I need to rebuild one of my boxes in the lab that I do WoL testing on for
ixgbe devices. That shouldn't take me long, and I'll test this. If it
works as expected, I'll send my ack.
Cheers,
-PJ Waskiewicz
^ permalink raw reply
* Question: AF-Independence of ECN (was [PATCH 0/4] inet6: minor cleanups)
From: Gerrit Renker @ 2009-07-22 20:17 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20090721.125745.210846096.davem@davemloft.net>
Thank you for reviewing the patches.
| > Patch #4: Finds that RT_TOS() redefines IPTOS_TOS().
|
| This macro probably exists so that if the ipv4 route cache entry TOS
| representation changes compared to IPTOS_TOS(), we would simply have
| to change the definition of this macro.
|
| Just because they happen to be the same now is no reason to kill off
| this macro I think.
|
| I'm not applying this either.
|
These patches are a byproduct of studying the code. I think it is better to
post the question I am trying to resolve, before discussing any more patches.
I hope that there will be some input and/or discussion.
The problem is that
* IPv4 TOS and IPv6 Traffic Class have identical semantics
- the DiffServ bits 0..5 due to RFC 2474,
- the 'CU'/ECN bits 6,7 due to RFC 3168.
* in the code this is currently handled AF-dependent:
- as inet_sk's "tos" field,
- as ipv6_pinfo's "tclass" field.
There are already three existing Linux transport protocols affected by
the AF-dependence of ECN:
* TCPv4 supports ECN, but TCPv6 currently does not;
* SCTP achieves ECN support for v4 and v6 only with difficulties:
- it uses a function pointer 'ecn_capable', which calls wrappers around
- INET_ECN_xmit (sctp_v4_ecn_capable)
- modification of inet6_sk(sk)->tclass (sctp_v6_ecn_capable)
* DCCP ECN is not supported yet, but a working patch set exists.
So the whole point is: to achieve AF-independent ECN/DiffServ support,
I was using an ugly hack to work around the existing AF-dependence:
#define IP6_ECN_flow_xmit(sk, label) do { \
- if (INET_ECN_is_capable(inet6_sk(sk)->tclass)) \
- (label) |= htonl(INET_ECN_ECT_0 << 20); \
+ IP6_ECN_flow_init(label); \
+ (label) |= htonl((inet_sk(sk)->tos & INET_ECN_MASK) << 20); \
} while (0)
Realising that
* this is so ugly that I don't want to submit it (it has been the reason for
several patches sitting idly for a couple of months), and
* finding that other transport protocols are facing a similar situation,
I am interested in solving the problem so that
(a) the DCCP code becomes usable and
(b) other transport protocols might benefit from a more generic solution.
My question:
* is there support for an AF-independent use of ECN/DiffServ field?
* what needs to be considered other than a good understanding of the code:
- are there possible breakages,
- legacy code or,
- anything else that would prevent this?
Gerrit
^ permalink raw reply
* [PATCH 5/5] c/r: Add AF_UNIX support (v6)
From: Dan Smith @ 2009-07-22 20:41 UTC (permalink / raw)
To: containers; +Cc: Oren Laaden, Alexey Dobriyan, netdev
In-Reply-To: <1248295301-30930-1-git-send-email-danms@us.ibm.com>
This patch adds basic checkpoint/restart support for AF_UNIX sockets. It
has been tested with a single and multiple processes, and with data inflight
at the time of checkpoint. It supports socketpair()s, path-based, and
abstract sockets.
Changes in v6:
- Moved the socket addresses to the per-type header
- Eliminated the HASCWD flag
- Remove use of ckpt_write_err() in restart paths
- Change the order in which buffers are read so that we can set the
socket's limit equal to the size of the image's buffers (if appropriate)
and then restore the original values afterwards.
- Use the ckpt_validate_errno() helper
- Add a check to make sure that we didn't restore a (UNIX) socket with
any skb's in the send buffer
- Fix up sock_unix_join() to not leave addr uninitialized for socketpair
- Remove inclusion of checkpoint_hdr.h in the socket files
- Make sock_unix_write_cwd() use ckpt_write_string() and use the new
ckpt_read_string() for reading the cwd
- Use the restored realcred credentials in sock_unix_join()
- Fix error path of the chdir_and_bind
- Change the algorithm for reloading the socket buffers to use sendmsg()
on the socket's peer for better accounting
- For DGRAM sockets, check the backlog value against the system max
to avoid letting a restart bypass the overloaded queue length
- Use sock_bind() instead of sock->ops->bind() to gain the security hook
- Change "restart" to "restore" in some of the function names
Changes in v5:
- Change laddr and raddr buffers in socket header to be long enough
for INET6 addresses
- Place socket.c and sock.h function definitions inside #ifdef
CONFIG_CHECKPOINT
- Add explicit check in sock_unix_makeaddr() to refuse if the
checkpoint image specifies an addr length of 0
- Split sock_unix_restart() into a few pieces to facilitate:
- Changed behavior of the unix restore code so that unlinked LISTEN
sockets don't do a bind()...unlink()
- Save the base path of a bound socket's path so that we can chdir()
to the base before bind() if it is a relative path
- Call bind() for any socket that is not established but has a
non-zero-length local address
- Enforce the current sysctl limit on socket buffer size during restart
unless the user holds CAP_NET_ADMIN
- Unlink a path-based socket before calling bind()
Changes in v4:
- Changed the signdness of rcvlowat, rcvtimeo, sndtimeo, and backlog
to match their struct sock definitions. This should avoid issues
with sign extension.
- Add a sock_cptrst_verify() function to be run at restore time to
validate several of the values in the checkpoint image against
limits, flag masks, etc.
- Write an error string with ctk_write_err() in the obscure cases
- Don't write socket buffers for listen sockets
- Sanity check address lengths before we agree to allocate memory
- Check the result of inserting the peer object in the objhash on
restart
- Check return value of sock_cptrst() on restart
- Change logic in remote getname() phase of checkpoint to not fail for
closed (et al) sockets
- Eliminate the memory copy while reading socket buffers on restart
Changes in v3:
- Move sock_file_checkpoint() above sock_file_restore()
- Change __sock_file_*() functions to do_sock_file_*()
- Adjust some of the struct cr_hdr_socket alignment
- Improve the sock_copy_buffers() algorithm to avoid locking the source
queue for the entire operation
- Fix alignment in the socket header struct(s)
- Move the per-protocol structure (ckpt_hdr_socket_un) out of the
common socket header and read/write it separately
- Fix missing call to sock_cptrst() in restore path
- Break out the socket joining into another function
- Fix failure to restore the socket address thus fixing getname()
- Check the state values on restart
- Fix case of state being TCP_CLOSE, which allows dgram sockets to be
properly connected (if appropriate) to their peer and maintain the
sockaddr for getname() operation
- Fix restoring a listening socket that has been unlink()'d
- Fix checkpointing sockets with an in-flight FD-passing SKB. Fail
with EBUSY.
- Fix checkpointing listening sockets with an unaccepted connection.
Fail with EBUSY.
- Changed 'un' to 'unix' in function and structure names
Changes in v2:
- Change GFP_KERNEL to GFP_ATOMIC in sock_copy_buffers() (this seems
to be rather common in other uses of skb_copy())
- Move the ckpt_hdr_socket structure definition to linux/socket.h
- Fix whitespace issue
- Move sock_file_checkpoint() to net/socket.c for symmetry
Cc: Oren Laaden <orenl@cs.columbia.edu>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Cc: netdev@vger.kernel.org
Signed-off-by: Dan Smith <danms@us.ibm.com>
---
checkpoint/files.c | 7 +
checkpoint/objhash.c | 27 ++
include/linux/checkpoint_hdr.h | 13 +
include/linux/socket.h | 63 ++++
include/net/sock.h | 11 +
net/Makefile | 2 +
net/checkpoint.c | 779 ++++++++++++++++++++++++++++++++++++++++
net/socket.c | 85 +++++
8 files changed, 987 insertions(+), 0 deletions(-)
create mode 100644 net/checkpoint.c
diff --git a/checkpoint/files.c b/checkpoint/files.c
index bcdc774..81e7b20 100644
--- a/checkpoint/files.c
+++ b/checkpoint/files.c
@@ -21,6 +21,7 @@
#include <linux/syscalls.h>
#include <linux/checkpoint.h>
#include <linux/checkpoint_hdr.h>
+#include <net/sock.h>
/**************************************************************************
@@ -548,6 +549,12 @@ static struct restore_file_ops restore_file_ops[] = {
.file_type = CKPT_FILE_PIPE,
.restore = pipe_file_restore,
},
+ /* socket */
+ {
+ .file_name = "SOCKET",
+ .file_type = CKPT_FILE_SOCKET,
+ .restore = sock_file_restore,
+ },
};
static struct file *do_restore_file(struct ckpt_ctx *ctx)
diff --git a/checkpoint/objhash.c b/checkpoint/objhash.c
index da43bf4..ad08ed5 100644
--- a/checkpoint/objhash.c
+++ b/checkpoint/objhash.c
@@ -20,6 +20,7 @@
#include <linux/user_namespace.h>
#include <linux/checkpoint.h>
#include <linux/checkpoint_hdr.h>
+#include <net/sock.h>
struct ckpt_obj;
struct ckpt_obj_ops;
@@ -244,6 +245,22 @@ static void obj_groupinfo_drop(void *ptr)
put_group_info((struct group_info *) ptr);
}
+static int obj_sock_grab(void *ptr)
+{
+ sock_hold((struct sock *) ptr);
+ return 0;
+}
+
+static void obj_sock_drop(void *ptr)
+{
+ sock_put((struct sock *) ptr);
+}
+
+static int obj_sock_users(void *ptr)
+{
+ return atomic_read(&((struct sock *) ptr)->sk_refcnt);
+}
+
static struct ckpt_obj_ops ckpt_obj_ops[] = {
/* ignored object */
{
@@ -367,6 +384,16 @@ static struct ckpt_obj_ops ckpt_obj_ops[] = {
.checkpoint = checkpoint_groupinfo,
.restore = restore_groupinfo,
},
+ /* sock object */
+ {
+ .obj_name = "SOCKET",
+ .obj_type = CKPT_OBJ_SOCK,
+ .ref_drop = obj_sock_drop,
+ .ref_grab = obj_sock_grab,
+ .ref_users = obj_sock_users,
+ .checkpoint = sock_file_checkpoint,
+ .restore = sock_file_restore,
+ },
};
diff --git a/include/linux/checkpoint_hdr.h b/include/linux/checkpoint_hdr.h
index 8b7ca46..e542ff5 100644
--- a/include/linux/checkpoint_hdr.h
+++ b/include/linux/checkpoint_hdr.h
@@ -88,6 +88,12 @@ enum {
CKPT_HDR_SIGHAND = 601,
+ CKPT_HDR_FD_SOCKET = 701,
+ CKPT_HDR_SOCKET,
+ CKPT_HDR_SOCKET_BUFFERS,
+ CKPT_HDR_SOCKET_BUFFER,
+ CKPT_HDR_SOCKET_UNIX,
+
CKPT_HDR_TAIL = 9001,
CKPT_HDR_ERROR = 9999,
@@ -122,6 +128,7 @@ enum obj_type {
CKPT_OBJ_CRED,
CKPT_OBJ_USER,
CKPT_OBJ_GROUPINFO,
+ CKPT_OBJ_SOCK,
CKPT_OBJ_MAX
};
@@ -326,6 +333,7 @@ enum file_type {
CKPT_FILE_IGNORE = 0,
CKPT_FILE_GENERIC,
CKPT_FILE_PIPE,
+ CKPT_FILE_SOCKET,
CKPT_FILE_MAX
};
@@ -349,6 +357,11 @@ struct ckpt_hdr_file_pipe {
__s32 pipe_objref;
} __attribute__((aligned(8)));
+struct ckpt_hdr_file_socket {
+ struct ckpt_hdr_file common;
+ __u16 family;
+} __attribute__((aligned(8)));
+
struct ckpt_hdr_file_pipe_state {
struct ckpt_hdr h;
__s32 pipe_len;
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 3b461df..cd675dd 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -23,6 +23,7 @@ struct __kernel_sockaddr_storage {
#include <linux/uio.h> /* iovec support */
#include <linux/types.h> /* pid_t */
#include <linux/compiler.h> /* __user */
+#include <linux/checkpoint.h> /* struct ckpt_hdr */
#ifdef __KERNEL__
# ifdef CONFIG_PROC_FS
@@ -328,5 +329,67 @@ extern int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr *ka
extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data);
#endif
+
+#ifdef CONFIG_CHECKPOINT
+#include <linux/un.h> /* sockaddr_un */
+
+#define CKPT_UNIX_LINKED 1
+struct ckpt_hdr_socket_unix {
+ struct ckpt_hdr h;
+ __u32 this;
+ __u32 peer;
+ __u32 flags;
+ __u32 laddr_len;
+ __u32 raddr_len;
+ struct sockaddr_un laddr;
+ struct sockaddr_un raddr;
+} __attribute__ ((aligned(8)));
+
+struct ckpt_hdr_socket {
+ struct ckpt_hdr h;
+
+ struct ckpt_socket { /* struct socket */
+ __u64 flags;
+ __u8 state;
+ } socket __attribute__ ((aligned(8)));
+
+ struct ckpt_sock_common { /* struct sock_common */
+ __u32 bound_dev_if;
+ __u16 family;
+ __u8 state;
+ __u8 reuse;
+ } sock_common __attribute__ ((aligned(8)));
+
+ struct ckpt_sock { /* struct sock */
+ __s64 rcvlowat;
+ __s64 rcvtimeo;
+ __s64 sndtimeo;
+ __u64 flags;
+ __u64 lingertime;
+
+ __u32 err;
+ __u32 err_soft;
+ __u32 priority;
+ __s32 rcvbuf;
+ __s32 sndbuf;
+ __u16 type;
+ __s16 backlog;
+
+ __u8 protocol;
+ __u8 state;
+ __u8 shutdown;
+ __u8 userlocks;
+ __u8 no_check;
+ } sock __attribute__ ((aligned(8)));
+
+} __attribute__ ((aligned(8)));
+
+struct ckpt_hdr_socket_buffer {
+ struct ckpt_hdr h;
+ __u32 skb_count;
+ __u32 total_bytes;
+} __attribute__ ((aligned(8)));
+#endif /* CONFIG_CHECKPOINT */
+
#endif /* not kernel and not glibc */
#endif /* _LINUX_SOCKET_H */
diff --git a/include/net/sock.h b/include/net/sock.h
index d435dc1..4043cd2 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1608,4 +1608,15 @@ extern int sysctl_optmem_max;
extern __u32 sysctl_wmem_default;
extern __u32 sysctl_rmem_default;
+#ifdef CONFIG_CHECKPOINT
+/* Checkpoint/Restart Functions */
+struct ckpt_ctx;
+struct ckpt_hdr_socket;
+extern int sock_file_checkpoint(struct ckpt_ctx *, void *);
+extern void *sock_file_restore(struct ckpt_ctx *);
+extern struct socket *do_sock_file_restore(struct ckpt_ctx *,
+ struct ckpt_hdr_socket *);
+extern int do_sock_file_checkpoint(struct ckpt_ctx *ctx, struct file *file);
+#endif
+
#endif /* _SOCK_H */
diff --git a/net/Makefile b/net/Makefile
index ba324ae..91d12fe 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -66,3 +66,5 @@ ifeq ($(CONFIG_NET),y)
obj-$(CONFIG_SYSCTL) += sysctl_net.o
endif
obj-$(CONFIG_WIMAX) += wimax/
+
+obj-$(CONFIG_CHECKPOINT) += checkpoint.o
diff --git a/net/checkpoint.c b/net/checkpoint.c
new file mode 100644
index 0000000..748d3aa
--- /dev/null
+++ b/net/checkpoint.c
@@ -0,0 +1,779 @@
+/*
+ * Copyright 2009 IBM Corporation
+ *
+ * Author: Dan Smith <danms@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#include <linux/socket.h>
+#include <linux/mount.h>
+#include <linux/file.h>
+#include <linux/namei.h>
+#include <linux/syscalls.h>
+#include <linux/sched.h>
+#include <linux/fs_struct.h>
+
+#include <net/af_unix.h>
+#include <net/tcp_states.h>
+
+#include <linux/checkpoint.h>
+#include <linux/checkpoint_hdr.h>
+
+#define UNIX_ADDR_EMPTY(a) (a <= sizeof(short))
+
+static inline int sock_unix_need_cwd(struct sockaddr_un *addr,
+ unsigned long len)
+{
+ return (!UNIX_ADDR_EMPTY(len)) &&
+ addr->sun_path[0] &&
+ (addr->sun_path[0] != '/');
+}
+
+static int sock_copy_buffers(struct sk_buff_head *from,
+ struct sk_buff_head *to,
+ uint32_t *total_bytes)
+{
+ int count = 0;
+ struct sk_buff *skb;
+
+ *total_bytes = 0;
+
+ skb_queue_walk(from, skb) {
+ struct sk_buff *tmp;
+
+ tmp = dev_alloc_skb(skb->len);
+ if (!tmp)
+ return -ENOMEM;
+
+ spin_lock(&from->lock);
+ skb_morph(tmp, skb);
+ spin_unlock(&from->lock);
+
+ skb_queue_tail(to, tmp);
+ count++;
+ *total_bytes += tmp->len;
+ }
+
+ return count;
+}
+
+static int __sock_write_buffers(struct ckpt_ctx *ctx,
+ struct sk_buff_head *queue)
+{
+ struct sk_buff *skb;
+ int ret = 0;
+
+ skb_queue_walk(queue, skb) {
+ if (UNIXCB(skb).fp) {
+ ckpt_write_err(ctx, "fd-passing is not supported");
+ return -EBUSY;
+ }
+
+ ret = ckpt_write_obj_type(ctx, skb->data, skb->len,
+ CKPT_HDR_SOCKET_BUFFER);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int sock_write_buffers(struct ckpt_ctx *ctx, struct sk_buff_head *queue)
+{
+ struct ckpt_hdr_socket_buffer *h;
+ struct sk_buff_head tmpq;
+ int ret = -ENOMEM;
+
+ h = ckpt_hdr_get_type(ctx, sizeof(*h), CKPT_HDR_SOCKET_BUFFERS);
+ if (!h)
+ goto out;
+
+ skb_queue_head_init(&tmpq);
+
+ h->skb_count = sock_copy_buffers(queue, &tmpq, &h->total_bytes);
+ if (h->skb_count < 0) {
+ ret = h->skb_count;
+ goto out;
+ }
+
+ ret = ckpt_write_obj(ctx, (struct ckpt_hdr *) h);
+ if (!ret)
+ ret = __sock_write_buffers(ctx, &tmpq);
+
+ out:
+ ckpt_hdr_put(ctx, h);
+ __skb_queue_purge(&tmpq);
+
+ return ret;
+}
+
+static int sock_unix_write_cwd(struct ckpt_ctx *ctx,
+ struct sock *sock,
+ const char *sockpath)
+{
+ struct path path;
+ char *buf;
+ char *fqpath;
+ int offset;
+ int ret = -ENOENT;
+
+ buf = kmalloc(PATH_MAX, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ path.dentry = unix_sk(sock)->dentry;
+ path.mnt = unix_sk(sock)->mnt;
+
+ fqpath = d_path(&path, buf, PATH_MAX);
+ if (!fqpath)
+ goto out;
+
+ offset = strlen(fqpath) - strlen(sockpath);
+ if (offset <= 0) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ fqpath[offset] = '\0';
+
+ ckpt_debug("writing socket directory: %s\n", fqpath);
+ ret = ckpt_write_string(ctx, fqpath, strlen(fqpath));
+ out:
+ kfree(buf);
+ return ret;
+}
+
+static int sock_unix_getnames(struct ckpt_ctx *ctx,
+ struct ckpt_hdr_socket_unix *un,
+ struct socket *socket)
+{
+ struct sockaddr *loc = (struct sockaddr *)&un->laddr;
+ struct sockaddr *rem = (struct sockaddr *)&un->raddr;
+
+ if (socket->ops->getname(socket, loc, &un->laddr_len, 0)) {
+ ckpt_write_err(ctx, "Unable to getname of local");
+ return -EINVAL;
+ }
+
+ if (socket->ops->getname(socket, rem, &un->raddr_len, 1)) {
+ if ((socket->sk->sk_type != SOCK_DGRAM) &&
+ (socket->sk->sk_state == TCP_ESTABLISHED)) {
+ ckpt_write_err(ctx, "Unable to getname of remote");
+ return -EINVAL;
+ }
+ un->raddr_len = 0;
+ }
+
+ return 0;
+}
+
+static int sock_unix_checkpoint(struct ckpt_ctx *ctx,
+ struct socket *socket,
+ struct ckpt_hdr_socket *h)
+{
+ struct unix_sock *sk = unix_sk(socket->sk);
+ struct unix_sock *pr = unix_sk(sk->peer);
+ struct ckpt_hdr_socket_unix *un;
+ int new;
+ int ret = -ENOMEM;
+
+ if ((socket->sk->sk_state == TCP_LISTEN) &&
+ !skb_queue_empty(&socket->sk->sk_receive_queue)) {
+ ckpt_write_err(ctx, "listening socket has unaccepted peers");
+ return -EBUSY;
+ }
+
+ un = ckpt_hdr_get_type(ctx, sizeof(*un), CKPT_HDR_SOCKET_UNIX);
+ if (!un)
+ goto out;
+
+ ret = sock_unix_getnames(ctx, un, socket);
+ if (ret)
+ goto out;
+
+ if (sk->dentry && (sk->dentry->d_inode->i_nlink > 0))
+ un->flags |= CKPT_UNIX_LINKED;
+
+ un->this = ckpt_obj_lookup_add(ctx, sk, CKPT_OBJ_SOCK, &new);
+ if (un->this < 0)
+ goto out;
+
+ if (sk->peer)
+ un->peer = ckpt_obj_lookup_add(ctx, pr, CKPT_OBJ_SOCK, &new);
+ else
+ un->peer = 0;
+
+ if (un->peer < 0) {
+ ret = un->peer;
+ goto out;
+ }
+
+ ret = ckpt_write_obj(ctx, (struct ckpt_hdr *) h);
+ if (ret < 0)
+ goto out;
+
+ ret = ckpt_write_obj(ctx, (struct ckpt_hdr *) un);
+ if (ret < 0)
+ goto out;
+
+ if (sock_unix_need_cwd(&un->laddr, un->laddr_len))
+ ret = sock_unix_write_cwd(ctx, socket->sk, un->laddr.sun_path);
+ out:
+ ckpt_hdr_put(ctx, un);
+
+ return ret;
+}
+
+static int sock_cptrst_verify(struct ckpt_hdr_socket *h)
+{
+ uint8_t userlocks_mask = SOCK_SNDBUF_LOCK | SOCK_RCVBUF_LOCK |
+ SOCK_BINDADDR_LOCK | SOCK_BINDPORT_LOCK;
+
+ if (h->sock.shutdown & ~SHUTDOWN_MASK)
+ return -EINVAL;
+ if (h->sock.userlocks & ~userlocks_mask)
+ return -EINVAL;
+ if (h->sock.sndtimeo < 0)
+ return -EINVAL;
+ if (h->sock.rcvtimeo < 0)
+ return -EINVAL;
+ if ((h->sock.userlocks & SOCK_SNDBUF_LOCK) &&
+ ((h->sock.sndbuf < SOCK_MIN_SNDBUF) ||
+ (h->sock.sndbuf > sysctl_wmem_max)))
+ return -EINVAL;
+ if ((h->sock.userlocks & SOCK_RCVBUF_LOCK) &&
+ ((h->sock.rcvbuf < SOCK_MIN_RCVBUF) ||
+ (h->sock.rcvbuf > sysctl_rmem_max)))
+ return -EINVAL;
+ if ((h->sock.flags & SOCK_LINGER) &&
+ (h->sock.lingertime > MAX_SCHEDULE_TIMEOUT))
+ return -EINVAL;
+ if (!ckpt_validate_errno(h->sock.err))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int sock_cptrst(struct ckpt_ctx *ctx,
+ struct sock *sock,
+ struct ckpt_hdr_socket *h,
+ int op)
+{
+ if (sock->sk_socket) {
+ CKPT_COPY(op, h->socket.flags, sock->sk_socket->flags);
+ CKPT_COPY(op, h->socket.state, sock->sk_socket->state);
+ }
+
+ CKPT_COPY(op, h->sock_common.reuse, sock->sk_reuse);
+ CKPT_COPY(op, h->sock_common.bound_dev_if, sock->sk_bound_dev_if);
+ CKPT_COPY(op, h->sock_common.family, sock->sk_family);
+
+ CKPT_COPY(op, h->sock.shutdown, sock->sk_shutdown);
+ CKPT_COPY(op, h->sock.userlocks, sock->sk_userlocks);
+ CKPT_COPY(op, h->sock.no_check, sock->sk_no_check);
+ CKPT_COPY(op, h->sock.protocol, sock->sk_protocol);
+ CKPT_COPY(op, h->sock.err, sock->sk_err);
+ CKPT_COPY(op, h->sock.err_soft, sock->sk_err_soft);
+ CKPT_COPY(op, h->sock.priority, sock->sk_priority);
+ CKPT_COPY(op, h->sock.rcvlowat, sock->sk_rcvlowat);
+ CKPT_COPY(op, h->sock.backlog, sock->sk_max_ack_backlog);
+ CKPT_COPY(op, h->sock.rcvtimeo, sock->sk_rcvtimeo);
+ CKPT_COPY(op, h->sock.sndtimeo, sock->sk_sndtimeo);
+ CKPT_COPY(op, h->sock.rcvbuf, sock->sk_rcvbuf);
+ CKPT_COPY(op, h->sock.sndbuf, sock->sk_sndbuf);
+ CKPT_COPY(op, h->sock.flags, sock->sk_flags);
+ CKPT_COPY(op, h->sock.lingertime, sock->sk_lingertime);
+ CKPT_COPY(op, h->sock.type, sock->sk_type);
+ CKPT_COPY(op, h->sock.state, sock->sk_state);
+
+ if ((h->socket.state == SS_CONNECTED) &&
+ (h->sock.state != TCP_ESTABLISHED)) {
+ ckpt_debug("socket/sock in inconsistent state: %i/%i",
+ h->socket.state, h->sock.state);
+ return -EINVAL;
+ } else if ((h->sock.state < TCP_ESTABLISHED) ||
+ (h->sock.state >= TCP_MAX_STATES)) {
+ ckpt_debug("sock in invalid state: %i", h->sock.state);
+ return -EINVAL;
+ } else if ((h->socket.state < SS_FREE) ||
+ (h->socket.state > SS_DISCONNECTING)) {
+ ckpt_debug("socket in invalid state: %i",
+ h->socket.state);
+ return -EINVAL;
+ }
+
+ if (op == CKPT_CPT)
+ return sock_cptrst_verify(h);
+ else
+ return 0;
+}
+
+int do_sock_file_checkpoint(struct ckpt_ctx *ctx, struct file *file)
+{
+ struct socket *socket = file->private_data;
+ struct sock *sock = socket->sk;
+ struct ckpt_hdr_socket *h;
+ int ret = 0;
+
+ h = ckpt_hdr_get_type(ctx, sizeof(*h), CKPT_HDR_SOCKET);
+ if (!h)
+ return -ENOMEM;
+
+ ret = sock_cptrst(ctx, sock, h, CKPT_CPT);
+ if (ret)
+ goto out;
+
+ if (sock->sk_family == AF_UNIX) {
+ ret = sock_unix_checkpoint(ctx, socket, h);
+ if (ret)
+ goto out;
+ } else {
+ ckpt_write_err(ctx, "unsupported socket family %i",
+ sock->sk_family);
+ ret = EINVAL;
+ goto out;
+ }
+
+ if (sock->sk_state != TCP_LISTEN) {
+ ret = sock_write_buffers(ctx, &sock->sk_receive_queue);
+ if (ret)
+ goto out;
+
+ ret = sock_write_buffers(ctx, &sock->sk_write_queue);
+ if (ret)
+ goto out;
+ }
+ out:
+ ckpt_hdr_put(ctx, h);
+
+ return ret;
+}
+
+static int sock_read_buffer(struct ckpt_ctx *ctx, struct sock *sock)
+{
+ struct ckpt_hdr h;
+ struct msghdr msg;
+ struct kvec kvec;
+ int ret = 0;
+ int len;
+
+ memset(&msg, 0, sizeof(msg));
+
+ len = _ckpt_read_hdr_type(ctx, &h, CKPT_HDR_SOCKET_BUFFER);
+ if (len < 0)
+ return len;
+
+ if (len > SKB_MAX_ALLOC) {
+ ckpt_debug("Socket buffer too big (%i > %lu)",
+ len, SKB_MAX_ALLOC);
+ return -ENOSPC;
+ }
+
+ kvec.iov_len = len;
+ kvec.iov_base = kmalloc(len, GFP_KERNEL);
+ if (!kvec.iov_base)
+ return -ENOMEM;
+
+ ret = _ckpt_read_payload(ctx, &h, kvec.iov_base);
+ if (ret < 0)
+ goto out;
+
+ ret = kernel_sendmsg(sock->sk_socket, &msg, &kvec, 1, len);
+ ckpt_debug("kernel_sendmsg(%i): %i\n", len, ret);
+ if ((ret > 0) && (ret != len))
+ ret = -ENOMEM;
+ out:
+ return ret;
+}
+
+static int sock_read_buffers(struct ckpt_ctx *ctx, struct sock *sock,
+ uint32_t *bufsize)
+{
+ struct ckpt_hdr_socket_buffer *h;
+ int ret = 0;
+ int i;
+ uint32_t total = 0;
+ uint8_t sock_shutdown;
+
+ /* If peer is shutdown, unshutdown it for this process */
+ sock_shutdown = sock->sk_shutdown;
+ sock->sk_shutdown &= ~SHUTDOWN_MASK;
+
+ h = ckpt_read_obj_type(ctx, sizeof(*h), CKPT_HDR_SOCKET_BUFFERS);
+ if (IS_ERR(h)) {
+ ret = PTR_ERR(h);
+ goto out;
+ }
+
+ if (!bufsize) {
+ if (h->total_bytes != 0) {
+ ckpt_debug("Expected empty buffer, got %u\n",
+ h->total_bytes);
+ ret = -EINVAL;
+ }
+ goto out;
+ } else if (h->total_bytes > *bufsize) {
+ if (capable(CAP_NET_ADMIN))
+ *bufsize = h->total_bytes;
+ else {
+ ckpt_debug("Buffer total %u exceeds limit %u\n",
+ h->total_bytes, *bufsize);
+ ret = -EINVAL;
+ goto out;
+ }
+ }
+
+ for (i = 0; i < h->skb_count; i++) {
+ ret = sock_read_buffer(ctx, sock);
+ ckpt_debug("read buffer %i: %i\n", i, ret);
+ if (ret < 0)
+ break;
+
+ total += ret;
+ if (total > h->total_bytes) {
+ ckpt_debug("Buffers exceeded claimed %u", total);
+ ret = -EINVAL;
+ goto out;
+ }
+ }
+
+ if (total == h->total_bytes)
+ ret = 0;
+ else {
+ ckpt_debug("Inconsistent total buffer size %u != %u\n",
+ total, h->total_bytes);
+ ret = -EINVAL;
+ }
+ out:
+ sock->sk_shutdown = sock_shutdown;
+ ckpt_hdr_put(ctx, h);
+
+ return ret;
+}
+
+static struct unix_address *sock_unix_makeaddr(struct sockaddr_un *sun_addr,
+ unsigned len)
+{
+ struct unix_address *addr;
+
+ if (len > sizeof(struct sockaddr_un))
+ return ERR_PTR(-EINVAL);
+
+ addr = kmalloc(sizeof(*addr) + len, GFP_KERNEL);
+ if (!addr)
+ return ERR_PTR(-ENOMEM);
+
+ memcpy(addr->name, sun_addr, len);
+ addr->len = len;
+ atomic_set(&addr->refcnt, 1);
+
+ return addr;
+}
+
+static int sock_unix_join(struct ckpt_ctx *ctx,
+ struct sock *a,
+ struct sock *b,
+ struct ckpt_hdr_socket_unix *un)
+{
+ struct unix_address *addr = NULL;
+
+ sock_hold(a);
+ sock_hold(b);
+
+ unix_sk(a)->peer = b;
+ unix_sk(b)->peer = a;
+
+ a->sk_peercred.pid = task_tgid_vnr(current);
+ a->sk_peercred.uid = ctx->realcred->uid;
+ a->sk_peercred.gid = ctx->realcred->gid;
+
+ b->sk_peercred.pid = a->sk_peercred.pid;
+ b->sk_peercred.uid = a->sk_peercred.uid;
+ b->sk_peercred.gid = a->sk_peercred.gid;
+
+ if (!UNIX_ADDR_EMPTY(un->raddr_len))
+ addr = sock_unix_makeaddr(&un->raddr, un->raddr_len);
+ else if (!UNIX_ADDR_EMPTY(un->laddr_len))
+ addr = sock_unix_makeaddr(&un->laddr, un->laddr_len);
+
+ if (IS_ERR(addr))
+ return PTR_ERR(addr);
+ else if (addr) {
+ atomic_inc(&addr->refcnt); /* Held by both ends */
+ unix_sk(a)->addr = unix_sk(b)->addr = addr;
+ }
+
+ return 0;
+}
+
+static int sock_unix_restore_connected(struct ckpt_ctx *ctx,
+ struct ckpt_hdr_socket *h,
+ struct ckpt_hdr_socket_unix *un,
+ struct socket *socket)
+{
+ struct sock *this = ckpt_obj_fetch(ctx, un->this, CKPT_OBJ_SOCK);
+ struct sock *peer = ckpt_obj_fetch(ctx, un->peer, CKPT_OBJ_SOCK);
+ struct socket *tmp = NULL;
+ int ret;
+
+ if (!IS_ERR(this) && !IS_ERR(peer)) {
+ /* We're last */
+ struct socket *old = this->sk_socket;
+
+ old->sk = NULL;
+ sock_release(old);
+ sock_graft(this, socket);
+
+ } else if ((PTR_ERR(this) == -EINVAL) && (PTR_ERR(peer) == -EINVAL)) {
+ /* We're first */
+ int family = socket->sk->sk_family;
+ int type = socket->sk->sk_type;
+
+ ret = sock_create(family, type, 0, &tmp);
+ ckpt_debug("sock_create: %i\n", ret);
+ if (ret)
+ goto out;
+
+ this = socket->sk;
+ peer = tmp->sk;
+
+ ret = ckpt_obj_insert(ctx, this, un->this, CKPT_OBJ_SOCK);
+ if (ret < 0)
+ goto out;
+
+ ret = ckpt_obj_insert(ctx, peer, un->peer, CKPT_OBJ_SOCK);
+ if (ret < 0)
+ goto out;
+
+ ret = sock_unix_join(ctx, this, peer, un);
+ ckpt_debug("sock_unix_join: %i\n", ret);
+ if (ret)
+ goto out;
+
+ } else {
+ ckpt_debug("Order Error\n");
+ ret = PTR_ERR(this);
+ goto out;
+ }
+
+ /* Prime the socket's buffer limit with the maximum */
+ peer->sk_userlocks |= SOCK_SNDBUF_LOCK;
+ peer->sk_sndbuf = sysctl_wmem_max;
+
+ /* Read my buffers and sendmsg() then back to me via my peer */
+ ret = sock_read_buffers(ctx, peer, &peer->sk_sndbuf);
+ ckpt_debug("sock_read_buffers: %i\n", ret);
+ if (ret)
+ goto out;
+
+ /* Read peer's buffers and expect 0 */
+ ret = sock_read_buffers(ctx, peer, NULL);
+ out:
+ if (tmp && ret)
+ sock_release(tmp);
+
+ return ret;
+}
+
+static int sock_unix_unlink(const char *name)
+{
+ struct path spath;
+ struct path ppath;
+ int ret;
+
+ ret = kern_path(name, 0, &spath);
+ if (ret)
+ return ret;
+
+ ret = kern_path(name, LOOKUP_PARENT, &ppath);
+ if (ret)
+ goto out_s;
+
+ if (!spath.dentry) {
+ ckpt_debug("No dentry found for %s\n", name);
+ ret = -ENOENT;
+ goto out_p;
+ }
+
+ if (!ppath.dentry || !ppath.dentry->d_inode) {
+ ckpt_debug("No inode for parent of %s\n", name);
+ ret = -ENOENT;
+ goto out_p;
+ }
+
+ ret = vfs_unlink(ppath.dentry->d_inode, spath.dentry);
+ out_p:
+ path_put(&ppath);
+ out_s:
+ path_put(&spath);
+
+ return ret;
+}
+
+/* Call bind() for socket, optionally changing (temporarily) to @path first
+ * if non-NULL
+ */
+static int sock_unix_chdir_and_bind(struct socket *socket,
+ const char *path,
+ struct sockaddr *addr,
+ unsigned long addrlen)
+{
+ struct sockaddr_un *un = (struct sockaddr_un *)addr;
+ int ret;
+ struct path cur;
+ struct path dir;
+
+ if (path) {
+ ckpt_debug("switching to cwd %s for unix bind", path);
+
+ ret = kern_path(path, 0, &dir);
+ if (ret)
+ return ret;
+
+ ret = inode_permission(dir.dentry->d_inode,
+ MAY_EXEC | MAY_ACCESS);
+ if (ret)
+ goto out;
+
+ write_lock(¤t->fs->lock);
+ cur = current->fs->pwd;
+ current->fs->pwd = dir;
+ write_unlock(¤t->fs->lock);
+ }
+
+ ret = sock_unix_unlink(un->sun_path);
+ ckpt_debug("unlink(%s): %i\n", un->sun_path, ret);
+ if ((ret == 0) || (ret == -ENOENT))
+ ret = sock_bind(socket, addr, addrlen);
+
+ if (path) {
+ write_lock(¤t->fs->lock);
+ current->fs->pwd = cur;
+ write_unlock(¤t->fs->lock);
+ }
+ out:
+ if (path)
+ path_put(&dir);
+
+ return ret;
+}
+
+static int sock_unix_fakebind(struct socket *socket,
+ struct sockaddr_un *addr,
+ unsigned long len)
+{
+ struct unix_address *uaddr;
+
+ uaddr = sock_unix_makeaddr(addr, len);
+ if (IS_ERR(uaddr))
+ return PTR_ERR(uaddr);
+
+ unix_sk(socket->sk)->addr = uaddr;
+
+ return 0;
+}
+
+static int sock_unix_bind(struct ckpt_hdr_socket *h,
+ struct ckpt_hdr_socket_unix *un,
+ struct socket *socket,
+ const char *path)
+{
+ struct sockaddr *addr = (struct sockaddr *)&un->laddr;
+ unsigned long len = un->laddr_len;
+
+ if (!un->laddr.sun_path[0])
+ return sock_bind(socket, addr, len);
+ else if (!(un->flags & CKPT_UNIX_LINKED))
+ return sock_unix_fakebind(socket, &un->laddr, len);
+ else
+ return sock_unix_chdir_and_bind(socket, path, addr, len);
+}
+
+static int sock_unix_restore(struct ckpt_ctx *ctx,
+ struct ckpt_hdr_socket *h,
+ struct socket *socket)
+{
+ struct ckpt_hdr_socket_unix *un;
+ int ret = -EINVAL;
+ char *cwd = NULL;
+ struct net *net = sock_net(socket->sk);
+
+ /* AF_UNIX overloads the backlog setting to define the maximum
+ * queue length for DGRAM sockets. Make sure we don't let the
+ * caller exceed that value on restart.
+ */
+ if ((h->sock.type == SOCK_DGRAM) &&
+ (h->sock.backlog > net->unx.sysctl_max_dgram_qlen)) {
+ ckpt_debug("DGRAM backlog of %i exceeds system max of %i\n",
+ h->sock.backlog, net->unx.sysctl_max_dgram_qlen);
+ return -EINVAL;
+ }
+
+ un = ckpt_read_obj_type(ctx, sizeof(*un), CKPT_HDR_SOCKET_UNIX);
+ if (IS_ERR(un))
+ return PTR_ERR(un);
+
+ if (un->peer < 0)
+ goto out;
+
+ if (sock_unix_need_cwd(&un->laddr, un->laddr_len)) {
+ ret = ckpt_read_string(ctx, &cwd, PATH_MAX);
+ ckpt_debug("read cwd(%i): %s\n", ret, cwd);
+ if (ret)
+ goto out;
+ }
+
+ if ((h->sock.state != TCP_ESTABLISHED) &&
+ !UNIX_ADDR_EMPTY(un->laddr_len)) {
+ ret = sock_unix_bind(h, un, socket, cwd);
+ if (ret)
+ goto out;
+ }
+
+ if ((h->sock.state == TCP_ESTABLISHED) || (h->sock.state == TCP_CLOSE))
+ ret = sock_unix_restore_connected(ctx, h, un, socket);
+ else if (h->sock.state == TCP_LISTEN)
+ ret = socket->ops->listen(socket, h->sock.backlog);
+ else
+ ckpt_debug("unsupported UNIX socket state %i\n", h->sock.state);
+ out:
+ ckpt_hdr_put(ctx, un);
+ kfree(cwd);
+ return ret;
+}
+
+struct socket *do_sock_file_restore(struct ckpt_ctx *ctx,
+ struct ckpt_hdr_socket *h)
+{
+ struct socket *socket;
+ int ret;
+
+ ret = sock_create(h->sock_common.family, h->sock.type, 0, &socket);
+ if (ret < 0)
+ return ERR_PTR(ret);
+
+ if (h->sock_common.family == AF_UNIX) {
+ ret = sock_unix_restore(ctx, h, socket);
+ ckpt_debug("sock_unix_restore: %i\n", ret);
+ } else {
+ ckpt_debug("unsupported family %i\n", h->sock_common.family);
+ ret = -EINVAL;
+ }
+
+ if (ret)
+ goto out;
+
+ ret = sock_cptrst(ctx, socket->sk, h, CKPT_RST);
+ out:
+ if (ret) {
+ sock_release(socket);
+ socket = ERR_PTR(ret);
+ }
+
+ return socket;
+}
+
diff --git a/net/socket.c b/net/socket.c
index 017f6e6..ff556fc 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -96,6 +96,8 @@
#include <net/sock.h>
#include <linux/netfilter.h>
+#include <linux/checkpoint.h>
+
static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t pos);
@@ -140,6 +142,9 @@ static const struct file_operations socket_file_ops = {
.sendpage = sock_sendpage,
.splice_write = generic_splice_sendpage,
.splice_read = sock_splice_read,
+#ifdef CONFIG_CHECKPOINT
+ .checkpoint = sock_file_checkpoint,
+#endif
};
/*
@@ -415,6 +420,86 @@ int sock_map_fd(struct socket *sock, int flags)
return fd;
}
+#ifdef CONFIG_CHECKPOINT
+int sock_file_checkpoint(struct ckpt_ctx *ctx, void *ptr)
+{
+ struct ckpt_hdr_file_socket *h;
+ int ret;
+ struct file *file = ptr;
+
+ h = ckpt_hdr_get_type(ctx, sizeof(*h), CKPT_HDR_FILE);
+ if (!h)
+ return -ENOMEM;
+
+ h->common.f_type = CKPT_FILE_SOCKET;
+
+ ret = checkpoint_file_common(ctx, file, &h->common);
+ if (ret < 0)
+ goto out;
+ ret = ckpt_write_obj(ctx, (struct ckpt_hdr *) h);
+ if (ret < 0)
+ goto out;
+
+ ret = do_sock_file_checkpoint(ctx, file);
+ out:
+ ckpt_hdr_put(ctx, h);
+ return ret;
+}
+
+static struct file *sock_alloc_attach_fd(struct socket *socket)
+{
+ struct file *file;
+ int err;
+
+ file = get_empty_filp();
+ if (!file)
+ return ERR_PTR(ENOMEM);
+
+ err = sock_attach_fd(socket, file, 0);
+ if (err < 0) {
+ put_filp(file);
+ file = ERR_PTR(err);
+ }
+
+ return file;
+}
+
+void *sock_file_restore(struct ckpt_ctx *ctx)
+{
+ struct ckpt_hdr_socket *h = NULL;
+ struct socket *socket = NULL;
+ struct file *file = NULL;
+ int err;
+
+ h = ckpt_read_obj_type(ctx, sizeof(*h), CKPT_HDR_SOCKET);
+ if (IS_ERR(h))
+ return h;
+
+ socket = do_sock_file_restore(ctx, h);
+ if (IS_ERR(socket)) {
+ err = PTR_ERR(socket);
+ goto err_put;
+ }
+
+ file = sock_alloc_attach_fd(socket);
+ if (IS_ERR(file)) {
+ err = PTR_ERR(file);
+ goto err_release;
+ }
+
+ ckpt_hdr_put(ctx, h);
+
+ return file;
+
+ err_release:
+ sock_release(socket);
+ err_put:
+ ckpt_hdr_put(ctx, h);
+
+ return ERR_PTR(err);
+}
+#endif /* CONFIG_CHECKPOINT */
+
static struct socket *sock_from_file(struct file *file, int *err)
{
if (file->f_op == &socket_file_ops)
--
1.6.2.5
^ permalink raw reply related
* Re: [Bugme-new] [Bug 13760] New: 2.6.30 kernel locks up with pppoe in back trace (regression)
From: Andrew Morton @ 2009-07-22 20:45 UTC (permalink / raw)
To: for.poige+bugzilla.kernel.org; +Cc: bugzilla-daemon, bugme-daemon, netdev
In-Reply-To: <bug-13760-10286@http.bugzilla.kernel.org/>
(switched to email. Please respond via emailed reply-to-all, not via the
bugzilla web interface).
On Sat, 11 Jul 2009 06:10:00 GMT
bugzilla-daemon@bugzilla.kernel.org wrote:
> http://bugzilla.kernel.org/show_bug.cgi?id=13760
>
> Summary: 2.6.30 kernel locks up with pppoe in back trace
> (regression)
> Product: Networking
> Version: 2.5
> Kernel Version: 2.6.30
> Platform: All
> OS/Version: Linux
> Tree: Mainline
> Status: NEW
> Severity: normal
> Priority: P1
> Component: Other
> AssignedTo: acme@ghostprotocols.net
> ReportedBy: for.poige+bugzilla.kernel.org@gmail.com
> Regression: Yes
>
>
> Having updated kernel to 2.6.30 (and 2.6.30.1) I've faced several lock-ups
> during boot sequence (and even during shutdown), when pppoe connection had been
> initiated (and interrupted on shutdown). The lock-ups aren't Alt_SysRq_B
> breakable.
>
> I still not have backtraces saved but as soon as pppoe connection initiation
> runs before running X-server (and after its shutdown), I have seen parts of
> dmesg's output and to my surprise it was regarding pppoe's functions.
>
This regression report is nearly two weeks old and I think there has
been a bit of ppp-related fixing going on in that time.
Can you please tell us whether the regression is still present in
2.6.30.2? If so, I expect we'll be wanting to see those traces,
please.
Thanks.
^ permalink raw reply
* [PATCH net-next-2.6] bonding: propogate vlan_features to bonding master
From: Jay Vosburgh @ 2009-07-22 21:34 UTC (permalink / raw)
To: Or Gerlitz; +Cc: David Miller, netdev
In-Reply-To: <4A642600.2010501@voltaire.com>
Propogate the vlan_features of the slave devices to the bonding
master device, using the same logic as for regular features.
Tested by Or Gerlitz <ogerlitz@voltaire.com>, who also removed
the debug logic from the original test patch.
Signed-off-by: Or Gerlitz <ogerlitz@voltaire.com>
Signed-off-by: Jay Vosburgh <fubar@us.ibm.com>
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 3bf0cc6..5a8b882 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1331,6 +1331,7 @@ static int bond_compute_features(struct bonding *bond)
struct slave *slave;
struct net_device *bond_dev = bond->dev;
unsigned long features = bond_dev->features;
+ unsigned long vlan_features;
unsigned short max_hard_header_len = max((u16)ETH_HLEN,
bond_dev->hard_header_len);
int i;
@@ -1343,10 +1344,14 @@ static int bond_compute_features(struct bonding *bond)
features &= ~NETIF_F_ONE_FOR_ALL;
+ vlan_features = bond->first_slave->dev->vlan_features;
bond_for_each_slave(bond, slave, i) {
features = netdev_increment_features(features,
slave->dev->features,
NETIF_F_ONE_FOR_ALL);
+ vlan_features = netdev_increment_features(vlan_features,
+ slave->dev->vlan_features,
+ NETIF_F_ONE_FOR_ALL);
if (slave->dev->hard_header_len > max_hard_header_len)
max_hard_header_len = slave->dev->hard_header_len;
}
@@ -1354,6 +1359,7 @@ static int bond_compute_features(struct bonding *bond)
done:
features |= (bond_dev->features & BOND_VLAN_FEATURES);
bond_dev->features = netdev_fix_features(features, NULL);
+ bond_dev->vlan_features = netdev_fix_features(vlan_features, NULL);
bond_dev->hard_header_len = max_hard_header_len;
return 0;
^ permalink raw reply related
* [PATCH] smc91x.h: add config for Nomadik evaluation kit
From: Alessandro Rubini @ 2009-07-22 22:39 UTC (permalink / raw)
To: netdev
Signed-off-by: Alessandro Rubini <rubini@unipv.it>
Acked-by: Andrea Gallo <andrea.gallo@stericsson.com>
---
Base support for the Nomadik SoC, by ST-Ericsson, is already
included in the "nomadik" branch of rmk's tree. This one-liner
enables the 16-bit-only configuration for the chip, as the
default are not working for us
drivers/net/smc91x.h | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index f1f773b..57a159f 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -186,7 +186,8 @@ static inline void SMC_outw(u16 val, void __iomem *ioaddr, int reg)
#define SMC_outsb(a, r, p, l) writesb((a) + (r), p, (l))
#define SMC_IRQ_FLAGS (-1) /* from resource */
-#elif defined(CONFIG_MACH_LOGICPD_PXA270)
+#elif defined(CONFIG_MACH_LOGICPD_PXA270) \
+ || defined(CONFIG_MACH_NOMADIK_8815NHK)
#define SMC_CAN_USE_8BIT 0
#define SMC_CAN_USE_16BIT 1
--
1.6.0.2
^ permalink raw reply related
* [PATCH v2] smc91x.h: add config for Nomadik evaluation kit
From: Alessandro Rubini @ 2009-07-22 22:49 UTC (permalink / raw)
To: netdev; +Cc: andrea.gallo, STEricsson_nomadik_linux
Signed-off-by: Alessandro Rubini <rubini@unipv.it>
Acked-by: Andrea Gallo <andrea.gallo@stericsson.com>
---
[sorry for the repost: I used a non-subscribed address and
forgot to Cc: company people, V2 is otherwise the same as V1]
Base support for the Nomadik SoC, by ST-Ericsson, is already
included in the "nomadik" branch of rmk's tree. This one-liner
enables the 16-bit-only configuration for the chip, as the
default are not working for us
drivers/net/smc91x.h | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index f1f773b..57a159f 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -186,7 +186,8 @@ static inline void SMC_outw(u16 val, void __iomem *ioaddr, int reg)
#define SMC_outsb(a, r, p, l) writesb((a) + (r), p, (l))
#define SMC_IRQ_FLAGS (-1) /* from resource */
-#elif defined(CONFIG_MACH_LOGICPD_PXA270)
+#elif defined(CONFIG_MACH_LOGICPD_PXA270) \
+ || defined(CONFIG_MACH_NOMADIK_8815NHK)
#define SMC_CAN_USE_8BIT 0
#define SMC_CAN_USE_16BIT 1
--
1.6.0.2
^ permalink raw reply related
* [net-next-2.6 PATCH 1/5] vlan: adds fcoe offload related net_device_ops and updates fcoe_ddp_xid field
From: Jeff Kirsher @ 2009-07-22 23:28 UTC (permalink / raw)
To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
Cc: linux-scsi-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
Jeff Kirsher, gospo-H+wXaHxf7aLQT0dZR+AlfA,
devel-s9riP+hp16TNLxjTenLetw
From: Vasu Dev <vasu.dev-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Adds fcoe offload related net_device_ops functions vlan_dev_fcoe_ddp_setup
and vlan_dev_fcoe_ddp_done, their implementation simply calls real eth device
net_device_ops for FCoE DDP setup and done operations.
Updates VLAN netdev field value for fcoe_ddp_xid from real eth device netdev.
Above changes are required for fcoe DDP offload working on a VLAN interface.
Signed-off-by: Vasu Dev <vasu.dev-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
net/8021q/vlan_dev.c | 39 +++++++++++++++++++++++++++++++++++++++
1 files changed, 39 insertions(+), 0 deletions(-)
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 96bad8f..6e695ac 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -561,6 +561,33 @@ static int vlan_dev_neigh_setup(struct net_device *dev, struct neigh_parms *pa)
return err;
}
+#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
+static int vlan_dev_fcoe_ddp_setup(struct net_device *dev, u16 xid,
+ struct scatterlist *sgl, unsigned int sgc)
+{
+ struct net_device *real_dev = vlan_dev_info(dev)->real_dev;
+ const struct net_device_ops *ops = real_dev->netdev_ops;
+ int rc = 0;
+
+ if (ops->ndo_fcoe_ddp_setup)
+ rc = ops->ndo_fcoe_ddp_setup(real_dev, xid, sgl, sgc);
+
+ return rc;
+}
+
+static int vlan_dev_fcoe_ddp_done(struct net_device *dev, u16 xid)
+{
+ struct net_device *real_dev = vlan_dev_info(dev)->real_dev;
+ const struct net_device_ops *ops = real_dev->netdev_ops;
+ int len = 0;
+
+ if (ops->ndo_fcoe_ddp_done)
+ len = ops->ndo_fcoe_ddp_done(real_dev, xid);
+
+ return len;
+}
+#endif
+
static void vlan_dev_change_rx_flags(struct net_device *dev, int change)
{
struct net_device *real_dev = vlan_dev_info(dev)->real_dev;
@@ -635,6 +662,10 @@ static int vlan_dev_init(struct net_device *dev)
if (is_zero_ether_addr(dev->broadcast))
memcpy(dev->broadcast, real_dev->broadcast, dev->addr_len);
+#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
+ dev->fcoe_ddp_xid = real_dev->fcoe_ddp_xid;
+#endif
+
if (real_dev->features & NETIF_F_HW_VLAN_TX) {
dev->header_ops = real_dev->header_ops;
dev->hard_header_len = real_dev->hard_header_len;
@@ -715,6 +746,10 @@ static const struct net_device_ops vlan_netdev_ops = {
.ndo_change_rx_flags = vlan_dev_change_rx_flags,
.ndo_do_ioctl = vlan_dev_ioctl,
.ndo_neigh_setup = vlan_dev_neigh_setup,
+#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
+ .ndo_fcoe_ddp_setup = vlan_dev_fcoe_ddp_setup,
+ .ndo_fcoe_ddp_done = vlan_dev_fcoe_ddp_done,
+#endif
};
static const struct net_device_ops vlan_netdev_accel_ops = {
@@ -731,6 +766,10 @@ static const struct net_device_ops vlan_netdev_accel_ops = {
.ndo_change_rx_flags = vlan_dev_change_rx_flags,
.ndo_do_ioctl = vlan_dev_ioctl,
.ndo_neigh_setup = vlan_dev_neigh_setup,
+#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
+ .ndo_fcoe_ddp_setup = vlan_dev_fcoe_ddp_setup,
+ .ndo_fcoe_ddp_done = vlan_dev_fcoe_ddp_done,
+#endif
};
void vlan_setup(struct net_device *dev)
^ permalink raw reply related
* [net-next-2.6 PATCH 2/5] ixgbe: updates vlan feature flags to enable FCoE offloads on vlan interface
From: Jeff Kirsher @ 2009-07-22 23:28 UTC (permalink / raw)
To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
Cc: Peter P Waskiewicz Jr, linux-scsi-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA, devel-s9riP+hp16TNLxjTenLetw,
gospo-H+wXaHxf7aLQT0dZR+AlfA, Jeff Kirsher
In-Reply-To: <20090722232759.26937.78765.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
From: Vasu Dev <vasu.dev-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Updates netdev->vlan_features for NETIF_F_FCOE_CRC and NETIF_F_FSO, so that
FCoE CRC and GSO offloads will get used for FCoE over ixgbe based vlan
interface.
Signed-off-by: Vasu Dev <vasu.dev-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Yi Zou <yi.zou-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Acked-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
drivers/net/ixgbe/ixgbe_main.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 79f60e8..d89c695 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -5588,6 +5588,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
if (!(device_caps & IXGBE_DEVICE_CAPS_FCOE_OFFLOADS)) {
netdev->features |= NETIF_F_FCOE_CRC;
netdev->features |= NETIF_F_FSO;
+ netdev->vlan_features |= NETIF_F_FCOE_CRC;
+ netdev->vlan_features |= NETIF_F_FSO;
netdev->fcoe_ddp_xid = IXGBE_FCOE_DDP_MAX - 1;
} else {
adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED;
^ permalink raw reply related
* [net-next-2.6 PATCH 3/5] net: Add NETIF_F_FCOE_MTU to indicate support for a different MTU for FCoE
From: Jeff Kirsher @ 2009-07-22 23:29 UTC (permalink / raw)
To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
Cc: linux-scsi-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
Jeff Kirsher, gospo-H+wXaHxf7aLQT0dZR+AlfA,
devel-s9riP+hp16TNLxjTenLetw
In-Reply-To: <20090722232759.26937.78765.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
From: Yi Zou <yi.zou-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Add NETIF_F_FCOE_MTU to indicate that the NIC can support a secondary MTU for
converged traffic of LAN and Fiber Channel over Ethernet (FCoE). The MTU for
FCoE is 2158 = 14 (FCoE header) + 24 (FC header) + 2112 (FC max payload) +
4 (FC CRC) + 4 (FCoE trailer).
Signed-off-by: Yi Zou <yi.zou-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
include/linux/netdevice.h | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 9f25ab2..9192cdf 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -701,6 +701,7 @@ struct net_device
/* the GSO_MASK reserves bits 16 through 23 */
#define NETIF_F_FCOE_CRC (1 << 24) /* FCoE CRC32 */
#define NETIF_F_SCTP_CSUM (1 << 25) /* SCTP checksum offload */
+#define NETIF_F_FCOE_MTU (1 << 26) /* Supports max FCoE MTU, 2158 bytes*/
/* Segmentation offload features */
#define NETIF_F_GSO_SHIFT 16
^ permalink raw reply related
* [net-next-2.6 PATCH 4/5] ixgbe: Add support for NETIF_F_FCOE_MTU to 82599 devices
From: Jeff Kirsher @ 2009-07-22 23:29 UTC (permalink / raw)
To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
Cc: linux-scsi-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
Peter P Waskiewicz Jr, devel-s9riP+hp16TNLxjTenLetw,
gospo-H+wXaHxf7aLQT0dZR+AlfA, Jeff Kirsher
In-Reply-To: <20090722232759.26937.78765.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
From: Yi Zou <yi.zou-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Enable netdev feature flag bit NETIF_F_FCOE_MTU for 82599 devices and enable
jumbo frame correspondingly when NETIF_F_FCOE_MTU is set.
Signed-off-by: Yi Zou <yi.zou-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Acked-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
drivers/net/ixgbe/ixgbe_main.c | 8 +++++---
1 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index d89c695..2852a17 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -2043,7 +2043,7 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
else
hlreg0 |= IXGBE_HLREG0_JUMBOEN;
#ifdef IXGBE_FCOE
- if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED)
+ if (netdev->features & NETIF_F_FCOE_MTU)
hlreg0 |= IXGBE_HLREG0_JUMBOEN;
#endif
IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
@@ -2070,7 +2070,7 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
adapter->rx_ring[i].rx_buf_len = rx_buf_len;
#ifdef IXGBE_FCOE
- if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) {
+ if (netdev->features & NETIF_F_FCOE_MTU) {
struct ixgbe_ring_feature *f;
f = &adapter->ring_feature[RING_F_FCOE];
if ((rx_buf_len < IXGBE_FCOE_JUMBO_FRAME_SIZE) &&
@@ -2619,7 +2619,7 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
#ifdef IXGBE_FCOE
/* adjust max frame to be able to do baby jumbo for FCoE */
- if ((adapter->flags & IXGBE_FLAG_FCOE_ENABLED) &&
+ if ((netdev->features & NETIF_F_FCOE_MTU) &&
(max_frame < IXGBE_FCOE_JUMBO_FRAME_SIZE))
max_frame = IXGBE_FCOE_JUMBO_FRAME_SIZE;
@@ -5588,8 +5588,10 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
if (!(device_caps & IXGBE_DEVICE_CAPS_FCOE_OFFLOADS)) {
netdev->features |= NETIF_F_FCOE_CRC;
netdev->features |= NETIF_F_FSO;
+ netdev->features |= NETIF_F_FCOE_MTU;
netdev->vlan_features |= NETIF_F_FCOE_CRC;
netdev->vlan_features |= NETIF_F_FSO;
+ netdev->vlan_features |= NETIF_F_FCOE_MTU;
netdev->fcoe_ddp_xid = IXGBE_FCOE_DDP_MAX - 1;
} else {
adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED;
^ permalink raw reply related
* [net-next-2.6 PATCH 5/5] fcoe: Use NETIF_F_FCOE_MTU flag to set up max frame size (lport->mfs)
From: Jeff Kirsher @ 2009-07-22 23:29 UTC (permalink / raw)
To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
Cc: linux-scsi-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
Jeff Kirsher, gospo-H+wXaHxf7aLQT0dZR+AlfA,
devel-s9riP+hp16TNLxjTenLetw
In-Reply-To: <20090722232759.26937.78765.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
From: Yi Zou <yi.zou-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Add a define of FCOE_MTU as 2158 bytes and use FCOE_MTU when the LLD is found
to support NETIF_F_FCOE_MTU. The lport->mfs is then calculated out of the
2158 FCOE_MTU. Otherwise, we stick with the netdev->mtu, i.e., LAN MTU. Also,
change the notification on NETDEV_CHANGEMTU event to bypass changing mfs when
LAN MTU is changed if NETIF_F_FCOE_MTU is supported.
Signed-off-by: Yi Zou <yi.zou-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
drivers/scsi/fcoe/fcoe.c | 11 +++++++++--
drivers/scsi/fcoe/fcoe.h | 4 ++++
2 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 0a5609b..e0a885c 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -291,8 +291,13 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev)
* user-configured limit. If the MFS is too low, fcoe_link_ok()
* will return 0, so do this first.
*/
- mfs = fc->real_dev->mtu - (sizeof(struct fcoe_hdr) +
- sizeof(struct fcoe_crc_eof));
+ mfs = fc->real_dev->mtu;
+ if (fc->phys_dev->features & NETIF_F_FCOE_MTU) {
+ mfs = FCOE_MTU;
+ printk(KERN_DEBUG "fcoe:%s supports FCOE_MTU of %d bytes\n",
+ netdev->name, mfs);
+ }
+ mfs -= (sizeof(struct fcoe_hdr) + sizeof(struct fcoe_crc_eof));
if (fc_set_mfs(lp, mfs))
return -EINVAL;
@@ -1420,6 +1425,8 @@ static int fcoe_device_notification(struct notifier_block *notifier,
case NETDEV_CHANGE:
break;
case NETDEV_CHANGEMTU:
+ if (fc->phys_dev->features & NETIF_F_FCOE_MTU)
+ break;
mfs = fc->real_dev->mtu -
(sizeof(struct fcoe_hdr) +
sizeof(struct fcoe_crc_eof));
diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h
index 0d724fa..be9735d 100644
--- a/drivers/scsi/fcoe/fcoe.h
+++ b/drivers/scsi/fcoe/fcoe.h
@@ -64,6 +64,10 @@ do { \
printk(KERN_INFO "fcoe: %s" fmt, \
netdev->name, ##args);)
+/* Max MTU for FCoE: 14 (FCoE header) + 24 (FC header) + 2112 (max FC payload)
+ * + 4 (FC CRC) + 4 (FCoE trailer) = 2158 bytes */
+#define FCOE_MTU 2158
+
/*
* this percpu struct for fcoe
*/
^ permalink raw reply related
* [PATCH net-next-2.6] ethtool: device independent rx_csum and get_flags routines
From: Sridhar Samudrala @ 2009-07-22 23:38 UTC (permalink / raw)
To: David Miller, netdev
[PATCH net-next-2.6] ethtool: add device independent rx_csum and get_flags routines
This helps avoid error messages with ethtool -k on devices that
don't provide device specific routines.
Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>
------------------------------------------------------------------
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index d9d5160..cf36ff4 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -30,6 +30,11 @@ u32 ethtool_op_get_link(struct net_device *dev)
return netif_carrier_ok(dev) ? 1 : 0;
}
+u32 ethtool_op_get_rx_csum(struct net_device *dev)
+{
+ return (dev->features & NETIF_F_ALL_CSUM) != 0;
+}
+
u32 ethtool_op_get_tx_csum(struct net_device *dev)
{
return (dev->features & NETIF_F_ALL_CSUM) != 0;
@@ -1004,7 +1009,9 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
break;
case ETHTOOL_GRXCSUM:
rc = ethtool_get_value(dev, useraddr, ethcmd,
- dev->ethtool_ops->get_rx_csum);
+ (dev->ethtool_ops->get_rx_csum ?
+ dev->ethtool_ops->get_rx_csum :
+ ethtool_op_get_rx_csum));
break;
case ETHTOOL_SRXCSUM:
rc = ethtool_set_rx_csum(dev, useraddr);
@@ -1068,7 +1075,9 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
break;
case ETHTOOL_GFLAGS:
rc = ethtool_get_value(dev, useraddr, ethcmd,
- dev->ethtool_ops->get_flags);
+ (dev->ethtool_ops->get_flags ?
+ dev->ethtool_ops->get_flags :
+ ethtool_op_get_flags));
break;
case ETHTOOL_SFLAGS:
rc = ethtool_set_value(dev, useraddr,
^ permalink raw reply related
* Re: [PATCH] igb/e1000e/e1000/e100: make wol usable
From: Waskiewicz Jr, Peter P @ 2009-07-22 23:43 UTC (permalink / raw)
To: Andy Gospodarek
Cc: Alexander Duyck, Ronciak, John, netdev@vger.kernel.org,
Kirsher, Jeffrey T, Brandeburg, Jesse, Allan, Bruce W,
Waskiewicz Jr, Peter P, stable@kernel.org
In-Reply-To: <20090722193400.GN8515@gospo.rdu.redhat.com>
On Wed, 22 Jul 2009, Andy Gospodarek wrote:
> On Tue, Jul 21, 2009 at 08:25:31PM -0700, Alexander Duyck wrote:
> > My understanding was that the can_wakeup was supposed to be
> > initialized by pci_pm_init or platform_pci_wakeup_init based on the
> > pci-e capabilities. Is this not the case? It seems like this is
> > where you should be looking to determine why the the can_wakeup isn't
> > being initialized correctly.
> >
> > The patch below won't solve the problem either. The problem is that
> > the can_wakeup value is being disabled when the EEPROM doesn't support
> > WOL.
>
> The lack of EEPROM support for this was not the problem at all.
> Ultimately it turns out that can_wakeup is set in pci_pm_init, so calls
> to device_init_wakeup and device_set_wakeup_capable should not be needed
> in any driver.
>
> > If you have to do this in the drivers, then my suggestion is to take a
> > look at how ixgbe is doing it. You essentially need to initialize
> > can_wakeup to true, and then set the should_wakeup attribute based on
> > the EEPROM setting or via ethtool. This way you can still toggle the
> > should_wakeup option without being blocked by the EEPROM disabling it.
>
> The first patch does exactly that (and ixgbe was part of my inspiration
> for it). Since can_wakeup and should_wakeup are both set in
> device_init_wakeup it's a suitable alternative in driver probe
> functions, but probably not ideal when drivers check for
> device_can_wakeup in their ethtool set_wol functions.
>
> Anyway, I knew I would find a bug or unnecessary code between e1000e and
> friends or ixgbe, so it looks like ixgbe has an unnecessary call to
> device_init_wakeup. Feel free to consider this patch as an alternative.
>
>
>
> [PATCH] ixgbe: remove unnecessary call to device_init_wakeup
>
> Calls to device_init_wakeup should not be necessary in drivers that use
> device_set_wakeup_enable since pci_pm_init will set the can_wakeup flag
> for the device when initialized.
>
> I can't test this since I don't have any of the 82599 KX4 interfaces
> (the only ones capable of WOL), but I did instrument ixgbe_probe and
> know that can_wakeup=1 when device_init_wakeup is removed.
>
> Signed-off-by: Andy Gospodarek <andy@greyhouse.net>
>
> ---
>
> ixgbe_main.c | 1 -
> 1 file changed, 1 deletion(-)
>
> diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
> index 79f60e8..2f15abf 100644
> --- a/drivers/net/ixgbe/ixgbe_main.c
> +++ b/drivers/net/ixgbe/ixgbe_main.c
> @@ -5640,7 +5640,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
> adapter->wol = 0;
> break;
> }
> - device_init_wakeup(&adapter->pdev->dev, true);
> device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
>
> /* pick up the PCI bus settings for reporting later */
Works just fine on two different 82599 mezz cards that support WoL.
Thanks Andy for finding and fixing.
Acked-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
^ permalink raw reply
* Re: [PATCH v3] net: Rework mdio-ofgpio driver to use of_mdioinfrastructure
From: Mark Ware @ 2009-07-23 0:02 UTC (permalink / raw)
To: davem; +Cc: netdev, linuxppc-dev
On Thu 23/07/09 2:10 AM , David Miller davem@davemloft.net sent:
> Your email client has massively corrupted this patch, I even tried
> to fix it up but it's so bad that I just gave up half-way through.
>
> Please use an attachment or whatever is necessary to get this
> patch submitted cleanly and without it getting damaged. Read:
>
> linux/Documentation/email-clients.txt for tips.
>
> Thanks.
Sorry for the waste of time. I've obviously somehow broken my thunderbird config.
Patch is attached, hopefully with correct MIME type - this webmail client is worse than Outlook.
(Incidently, I was able to apply the corrupted patch after the following two substitutions: s/^ / / and s/^$/ /)
Regards,
Mark
^ permalink raw reply
* [PATCH V2] imwc3200: move iwmc3200 SDIO ids to sdio_ids.h
From: Tomas Winkler @ 2009-07-23 0:06 UTC (permalink / raw)
To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
linux-wireless-u79uwXL29TY76Z2rM5mHXA, Tomas Winkler
1. add intel's sdio vendor id to sdio_ids.h
2. move iwmc3200 sdio devices' ids to sdio_ids.h
Cc:inaky.perez-gonzalez-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org
Cc:cindy.h.kao-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org
Cc:yi.zhu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org
Cc:drzeus-list-p3sGCRWkH8CeZLLa646FqQ@public.gmane.org
Signed-off-by: Tomas Winkler <tomas.winkler-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
V2:
1.Fixed indentation and typos
2.Added also GPS
drivers/net/wimax/i2400m/sdio.c | 12 +++++-------
drivers/net/wireless/iwmc3200wifi/sdio.c | 4 +++-
drivers/net/wireless/iwmc3200wifi/sdio.h | 3 ---
include/linux/mmc/sdio_ids.h | 6 ++++++
4 files changed, 14 insertions(+), 11 deletions(-)
diff --git a/drivers/net/wimax/i2400m/sdio.c b/drivers/net/wimax/i2400m/sdio.c
index 2538825..ea7b290 100644
--- a/drivers/net/wimax/i2400m/sdio.c
+++ b/drivers/net/wimax/i2400m/sdio.c
@@ -58,6 +58,7 @@
*/
#include <linux/debugfs.h>
+#include <linux/mmc/sdio_ids.h>
#include <linux/mmc/sdio.h>
#include <linux/mmc/sdio_func.h>
#include "i2400m-sdio.h"
@@ -501,15 +502,12 @@ void i2400ms_remove(struct sdio_func *func)
d_fnend(3, dev, "SDIO func %p\n", func);
}
-enum {
- I2400MS_INTEL_VID = 0x89,
-};
-
static
const struct sdio_device_id i2400ms_sdio_ids[] = {
- /* Intel: i2400m WiMAX over SDIO */
- { SDIO_DEVICE(I2400MS_INTEL_VID, 0x1402) },
- { }, /* end: all zeroes */
+ /* Intel: i2400m WiMAX (iwmc3200) over SDIO */
+ { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL,
+ SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX) },
+ { /* end: all zeroes */ },
};
MODULE_DEVICE_TABLE(sdio, i2400ms_sdio_ids);
diff --git a/drivers/net/wireless/iwmc3200wifi/sdio.c b/drivers/net/wireless/iwmc3200wifi/sdio.c
index b93f620..8b1de84 100644
--- a/drivers/net/wireless/iwmc3200wifi/sdio.c
+++ b/drivers/net/wireless/iwmc3200wifi/sdio.c
@@ -65,6 +65,7 @@
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/debugfs.h>
+#include <linux/mmc/sdio_ids.h>
#include <linux/mmc/sdio.h>
#include <linux/mmc/sdio_func.h>
@@ -492,7 +493,8 @@ static void iwm_sdio_remove(struct sdio_func *func)
}
static const struct sdio_device_id iwm_sdio_ids[] = {
- { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL, SDIO_DEVICE_ID_IWM) },
+ { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL,
+ SDIO_DEVICE_ID_INTEL_IWMC3200WIFI) },
{ /* end: all zeroes */ },
};
MODULE_DEVICE_TABLE(sdio, iwm_sdio_ids);
diff --git a/drivers/net/wireless/iwmc3200wifi/sdio.h b/drivers/net/wireless/iwmc3200wifi/sdio.h
index b3c156b..aab6b68 100644
--- a/drivers/net/wireless/iwmc3200wifi/sdio.h
+++ b/drivers/net/wireless/iwmc3200wifi/sdio.h
@@ -39,9 +39,6 @@
#ifndef __IWM_SDIO_H__
#define __IWM_SDIO_H__
-#define SDIO_VENDOR_ID_INTEL 0x89
-#define SDIO_DEVICE_ID_IWM 0x1403
-
#define IWM_SDIO_DATA_ADDR 0x0
#define IWM_SDIO_INTR_ENABLE_ADDR 0x14
#define IWM_SDIO_INTR_STATUS_ADDR 0x13
diff --git a/include/linux/mmc/sdio_ids.h b/include/linux/mmc/sdio_ids.h
index 39751c8..2dbfb5a 100644
--- a/include/linux/mmc/sdio_ids.h
+++ b/include/linux/mmc/sdio_ids.h
@@ -22,6 +22,12 @@
/*
* Vendors and devices. Sort key: vendor first, device next.
*/
+#define SDIO_VENDOR_ID_INTEL 0x0089
+#define SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX 0x1402
+#define SDIO_DEVICE_ID_INTEL_IWMC3200WIFI 0x1403
+#define SDIO_DEVICE_ID_INTEL_IWMC3200TOP 0x1404
+#define SDIO_DEVICE_ID_INTEL_IWMC3200GPS 0x1405
+#define SDIO_DEVICE_ID_INTEL_IWMC3200BT 0x1406
#define SDIO_VENDOR_ID_MARVELL 0x02df
#define SDIO_DEVICE_ID_MARVELL_LIBERTAS 0x9103
--
1.6.0.6
---------------------------------------------------------------------
Intel Israel (74) Limited
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [net-2.6 PATCH 1/2] ixgbe: Enable FCoE offload when DCB is enabled for 82599
From: Jeff Kirsher @ 2009-07-23 0:07 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Yi Zou, Peter P Waskiewicz Jr, Jeff Kirsher
From: Yi Zou <yi.zou@intel.com>
Currently, FCoE offload feature is turned on when the kernel config has
CONFIG_FCOE or CONFIG_FCOE_MODULE set. However, we really want to turn
FCoE offload on when there is FCoE traffic passing and turn it off when
it's just LAN traffic. Since FCoE depends on a lossless network provided
by DCB, this allows us to have FCoE turned on/off when user turns on DCB
using dcbtool.
Signed-off-by: Yi Zou <yi.zou@intel.com>
Acked-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ixgbe/ixgbe.h | 1 +
drivers/net/ixgbe/ixgbe_dcb_nl.c | 24 ++++++++++++++++++++++++
drivers/net/ixgbe/ixgbe_main.c | 16 ++++++----------
3 files changed, 31 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
index cd22323..1b12c7b 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ixgbe/ixgbe.h
@@ -327,6 +327,7 @@ struct ixgbe_adapter {
#define IXGBE_FLAG_IN_SFP_MOD_TASK (u32)(1 << 25)
#define IXGBE_FLAG_FDIR_HASH_CAPABLE (u32)(1 << 26)
#define IXGBE_FLAG_FDIR_PERFECT_CAPABLE (u32)(1 << 27)
+#define IXGBE_FLAG_FCOE_CAPABLE (u32)(1 << 28)
#define IXGBE_FLAG_FCOE_ENABLED (u32)(1 << 29)
u32 flags2;
diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c
index da2c851..1c72657 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_nl.c
+++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c
@@ -139,6 +139,18 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
}
adapter->flags |= IXGBE_FLAG_DCB_ENABLED;
+#ifdef IXGBE_FCOE
+ /* Turn on FCoE offload */
+ if ((adapter->flags & IXGBE_FLAG_FCOE_CAPABLE) &&
+ (!(adapter->flags & IXGBE_FLAG_FCOE_ENABLED))) {
+ adapter->flags |= IXGBE_FLAG_FCOE_ENABLED;
+ adapter->ring_feature[RING_F_FCOE].indices =
+ IXGBE_FCRETA_SIZE;
+ netdev->features |= NETIF_F_FCOE_CRC;
+ netdev->features |= NETIF_F_FSO;
+ netdev->fcoe_ddp_xid = IXGBE_FCOE_DDP_MAX - 1;
+ }
+#endif /* IXGBE_FCOE */
ixgbe_init_interrupt_scheme(adapter);
if (netif_running(netdev))
netdev->netdev_ops->ndo_open(netdev);
@@ -156,6 +168,18 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
adapter->flags |= IXGBE_FLAG_RSS_ENABLED;
if (adapter->hw.mac.type == ixgbe_mac_82599EB)
adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
+
+#ifdef IXGBE_FCOE
+ /* Turn off FCoE offload */
+ if (adapter->flags & (IXGBE_FLAG_FCOE_CAPABLE |
+ IXGBE_FLAG_FCOE_ENABLED)) {
+ adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED;
+ adapter->ring_feature[RING_F_FCOE].indices = 0;
+ netdev->features &= ~NETIF_F_FCOE_CRC;
+ netdev->features &= ~NETIF_F_FSO;
+ netdev->fcoe_ddp_xid = 0;
+ }
+#endif /* IXGBE_FCOE */
ixgbe_init_interrupt_scheme(adapter);
if (netif_running(netdev))
netdev->netdev_ops->ndo_open(netdev);
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index e3442f4..a2119d7 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -3806,8 +3806,9 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
adapter->atr_sample_rate = 20;
adapter->fdir_pballoc = 0;
#ifdef IXGBE_FCOE
- adapter->flags |= IXGBE_FLAG_FCOE_ENABLED;
- adapter->ring_feature[RING_F_FCOE].indices = IXGBE_FCRETA_SIZE;
+ adapter->flags |= IXGBE_FLAG_FCOE_CAPABLE;
+ adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED;
+ adapter->ring_feature[RING_F_FCOE].indices = 0;
#endif /* IXGBE_FCOE */
}
@@ -5580,16 +5581,11 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
#endif
#ifdef IXGBE_FCOE
- if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) {
+ if (adapter->flags & IXGBE_FLAG_FCOE_CAPABLE) {
if (hw->mac.ops.get_device_caps) {
hw->mac.ops.get_device_caps(hw, &device_caps);
- if (!(device_caps & IXGBE_DEVICE_CAPS_FCOE_OFFLOADS)) {
- netdev->features |= NETIF_F_FCOE_CRC;
- netdev->features |= NETIF_F_FSO;
- netdev->fcoe_ddp_xid = IXGBE_FCOE_DDP_MAX - 1;
- } else {
- adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED;
- }
+ if (device_caps & IXGBE_DEVICE_CAPS_FCOE_OFFLOADS)
+ adapter->flags &= ~IXGBE_FLAG_FCOE_CAPABLE;
}
}
#endif /* IXGBE_FCOE */
^ permalink raw reply related
* [net-2.6 PATCH 2/2] ixgbe: Don't priority tag control frames in DCB mode
From: Jeff Kirsher @ 2009-07-23 0:07 UTC (permalink / raw)
To: davem; +Cc: netdev, gospo, Lucy Liu, Peter P Waskiewicz Jr, Jeff Kirsher
In-Reply-To: <20090723000705.27299.19299.stgit@localhost.localdomain>
From: Lucy Liu <lucy.liu@intel.com>
Certain types of control packets (LLDP, LACP, etc.) are not supposed to have a
priority tag or vlan tag inserted. Ixgbe driver is currently priority
tagging everything (if packet is not on a VLAN interface).
This patch modifies DCB mode, so that packets marked with skb priority
TC_PRIO_CONTROL are not priority tagged. It also transmits these packets on
the highest priority traffic class.
Programs (like dcbd) can set the skb priority using a socket option. Or, a tc
filter can be configured to set the priority value. Using the value
TC_PRIO_CONTROL (7) has the benefit that it is already defined in the kernel,
and the bonding LACP code already sets the skb->priority field to this value.
Signed-off-by: Lucy Liu <lucy.liu@intel.com>
Acked-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ixgbe/ixgbe_main.c | 18 ++++++++++++------
1 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index a2119d7..47a3c6d 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -34,6 +34,7 @@
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/tcp.h>
+#include <linux/pkt_sched.h>
#include <linux/ipv6.h>
#include <net/checksum.h>
#include <net/ip6_checksum.h>
@@ -5126,9 +5127,6 @@ static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
int count = 0;
unsigned int f;
- r_idx = skb->queue_mapping;
- tx_ring = &adapter->tx_ring[r_idx];
-
if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
tx_flags |= vlan_tx_tag_get(skb);
if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
@@ -5138,11 +5136,19 @@ static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT;
tx_flags |= IXGBE_TX_FLAGS_VLAN;
} else if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
- tx_flags |= (skb->queue_mapping << 13);
- tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT;
- tx_flags |= IXGBE_TX_FLAGS_VLAN;
+ if (skb->priority != TC_PRIO_CONTROL) {
+ tx_flags |= (skb->queue_mapping << 13);
+ tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT;
+ tx_flags |= IXGBE_TX_FLAGS_VLAN;
+ } else {
+ skb->queue_mapping =
+ adapter->ring_feature[RING_F_DCB].indices-1;
+ }
}
+ r_idx = skb->queue_mapping;
+ tx_ring = &adapter->tx_ring[r_idx];
+
if ((adapter->flags & IXGBE_FLAG_FCOE_ENABLED) &&
(skb->protocol == htons(ETH_P_FCOE)))
tx_flags |= IXGBE_TX_FLAGS_FCOE;
^ permalink raw reply related
* Re: Re: [PATCH v3] net: Rework mdio-ofgpio driver to use of_mdio infrastructure
From: Mark Ware @ 2009-07-23 0:10 UTC (permalink / raw)
To: davem; +Cc: netdev, linuxppc-dev
On Thu 23/07/09 2:10 AM , David Miller davem@davemloft.net sent:
> Your email client has massively corrupted this patch, I even tried
> to fix it up but it's so bad that I just gave up half-way through.
>
> Please use an attachment or whatever is necessary to get this
> patch submitted cleanly and without it getting damaged. Read:
>
> linux/Documentation/email-clients.txt
>
> for tips.
>
> Thanks.
Dave,
The patch is actually attached this time. (I hope - did I mention my dislike for this webmail interface?)
Sorry for the further noise.
Regards,
Mark
^ permalink raw reply
* Re: [PATCH v3] net: Rework mdio-ofgpio driver to use of_mdioinfrastructure
From: David Miller @ 2009-07-23 0:10 UTC (permalink / raw)
To: mware; +Cc: netdev, linuxppc-dev
In-Reply-To: <16811.1248307327@internode.on.net>
From: Mark Ware <mware@elphinstone.net>
Date: Thu, 23 Jul 2009 09:02:07 +0900
> Patch is attached, hopefully with correct MIME type - this webmail
> client is worse than Outlook.
Where is it attached? :-/
^ permalink raw reply
* Re: [PATCH v3] net: Rework mdio-ofgpio driver to use of_mdio infrastructure
From: David Miller @ 2009-07-23 0:11 UTC (permalink / raw)
To: mware; +Cc: netdev, linuxppc-dev
In-Reply-To: <16861.1248307810@internode.on.net>
From: Mark Ware <mware@elphinstone.net>
Date: Thu, 23 Jul 2009 09:40:10 +0930
>
> The patch is actually attached this time. (I hope - did I mention my dislike for this webmail interface?)
No it isn't!
And anyways you have to properly provide the full commit message
and signoffs when you resubmit patches. You can't just resubmit
the patch because all of the context is lost in patchwork.
Grrr...
^ permalink raw reply
* [PATCH] sky2: remove unnecessary assignment
From: Mike McCormack @ 2009-07-23 2:53 UTC (permalink / raw)
To: netdev
Signed-off-by: Mike McCormack <mikem@ring3k.org>
Acked-by: Stephen Hemminger <shemminger@vyatta.com>
---
drivers/net/sky2.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 3550c5d..661abd0 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -4117,7 +4117,7 @@ static int sky2_debug_show(struct seq_file *seq, void *v)
seq_printf(seq, "\nRx ring hw get=%d put=%d last=%d\n",
sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_GET_IDX)),
- last = sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_PUT_IDX)),
+ sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_PUT_IDX)),
sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_LAST_IDX)));
sky2_read32(hw, B0_Y2_SP_LISR);
--
1.5.6.5
^ permalink raw reply related
* [PATCH] cnic: Fix ISCSI_KEVENT_IF_DOWN message handling.
From: Michael Chan @ 2009-07-23 3:01 UTC (permalink / raw)
To: davem, James.Bottomley, michaelc
Cc: netdev, linux-scsi, open-iscsi, Michael Chan
When a net device goes down or when the bnx2i driver is unloaded,
the code was not generating the ISCSI_KEVENT_IF_DOWN message
properly and this could cause the userspace driver to crash.
This is fixed by sending the message properly in the shutdown path.
cnic_uio_stop() is also added to send the message when bnx2i is
unregistering.
Signed-off-by: Michael Chan <mchan@broadcom.com>
---
drivers/net/cnic.c | 23 +++++++++++++++++++++--
1 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index 4d1515f..4869d77 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -227,7 +227,7 @@ static int cnic_send_nlmsg(struct cnic_local *cp, u32 type,
}
rcu_read_lock();
- ulp_ops = rcu_dereference(cp->ulp_ops[CNIC_ULP_ISCSI]);
+ ulp_ops = rcu_dereference(cnic_ulp_tbl[CNIC_ULP_ISCSI]);
if (ulp_ops)
ulp_ops->iscsi_nl_send_msg(cp->dev, msg_type, buf, len);
rcu_read_unlock();
@@ -319,6 +319,20 @@ static int cnic_abort_prep(struct cnic_sock *csk)
return 0;
}
+static void cnic_uio_stop(void)
+{
+ struct cnic_dev *dev;
+
+ read_lock(&cnic_dev_lock);
+ list_for_each_entry(dev, &cnic_dev_list, list) {
+ struct cnic_local *cp = dev->cnic_priv;
+
+ if (cp->cnic_uinfo)
+ cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL);
+ }
+ read_unlock(&cnic_dev_lock);
+}
+
int cnic_register_driver(int ulp_type, struct cnic_ulp_ops *ulp_ops)
{
struct cnic_dev *dev;
@@ -390,6 +404,9 @@ int cnic_unregister_driver(int ulp_type)
}
read_unlock(&cnic_dev_lock);
+ if (ulp_type == CNIC_ULP_ISCSI)
+ cnic_uio_stop();
+
rcu_assign_pointer(cnic_ulp_tbl[ulp_type], NULL);
mutex_unlock(&cnic_lock);
@@ -632,7 +649,6 @@ static void cnic_free_resc(struct cnic_dev *dev)
int i = 0;
if (cp->cnic_uinfo) {
- cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL);
while (cp->uio_dev != -1 && i < 15) {
msleep(100);
i++;
@@ -1057,6 +1073,9 @@ static void cnic_ulp_stop(struct cnic_dev *dev)
struct cnic_local *cp = dev->cnic_priv;
int if_type;
+ if (cp->cnic_uinfo)
+ cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL);
+
rcu_read_lock();
for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; if_type++) {
struct cnic_ulp_ops *ulp_ops;
--
1.5.6.GIT
^ permalink raw reply related
* Re: [PATCH] sky2: remove unnecessary assignment
From: David Miller @ 2009-07-23 4:04 UTC (permalink / raw)
To: mikem; +Cc: netdev
In-Reply-To: <392fb48f0907221953j77b8ea0etcad115f9b2c99c7b@mail.gmail.com>
From: Mike McCormack <mikem@ring3k.org>
Date: Thu, 23 Jul 2009 11:53:58 +0900
> Signed-off-by: Mike McCormack <mikem@ring3k.org>
> Acked-by: Stephen Hemminger <shemminger@vyatta.com>
When people ACK your patches and they are still in
"Under Review" state in patchwork, you DO NOT have
to resend the patch.
When I grab it out of patchwork and apply it to my
tree patchwork has seen all of the Acked-by and other
tags in the replies and puts it into the commit
message for me.
By resending this you're making MORE work for me, not
LESS.
^ permalink raw reply
* [PATCH] fixed up the previous mac driver for w90p910
From: Wan ZongShun @ 2009-07-23 4:18 UTC (permalink / raw)
To: David Miller, Russell King; +Cc: soni.trilok, netdev, linux-arm-kernel
In-Reply-To: <20090720.105217.236487133.davem@davemloft.net>
Dear Russell&David,
Due to having a bit busy, when David has applied this mac patch,
however,I did not fix it based on comments as pointed by Russell.
So, I have to resubmit a new patch relative to previous patch.
patch text:
According to Russell's advice, I fixed up mac driver,
which relatives to previous mac driver patch, and the
evaluation board based on w90p910.
Signed-off-by: Wan ZongShun <mcuos.com@gmail.com>
diff --git a/drivers/net/arm/w90p910_ether.c b/drivers/net/arm/w90p910_ether.c
index 7b5f315..890716f 100644
--- a/drivers/net/arm/w90p910_ether.c
+++ b/drivers/net/arm/w90p910_ether.c
@@ -143,16 +143,17 @@ struct recv_pdesc {
struct tran_pdesc {
struct w90p910_txbd desclist[TX_DESC_SIZE];
- char tran_buf[RX_DESC_SIZE][MAX_TBUFF_SZ];
+ char tran_buf[TX_DESC_SIZE][MAX_TBUFF_SZ];
};
struct w90p910_ether {
struct recv_pdesc *rdesc;
- struct recv_pdesc *rdesc_phys;
struct tran_pdesc *tdesc;
- struct tran_pdesc *tdesc_phys;
+ dma_addr_t rdesc_phys;
+ dma_addr_t tdesc_phys;
struct net_device_stats stats;
struct platform_device *pdev;
+ struct resource *res;
struct sk_buff *skb;
struct clk *clk;
struct clk *rmiiclk;
@@ -274,59 +275,75 @@ static void w90p910_write_cam(struct net_device *dev,
__raw_writel(msw, ether->reg + REG_CAMM_BASE + x * CAM_ENTRY_SIZE);
}
-static void w90p910_init_desc(struct net_device *dev)
+static int w90p910_init_desc(struct net_device *dev)
{
struct w90p910_ether *ether;
- struct w90p910_txbd *tdesc, *tdesc_phys;
- struct w90p910_rxbd *rdesc, *rdesc_phys;
- unsigned int i, j;
+ struct w90p910_txbd *tdesc;
+ struct w90p910_rxbd *rdesc;
+ struct platform_device *pdev;
+ unsigned int i;
ether = netdev_priv(dev);
+ pdev = ether->pdev;
ether->tdesc = (struct tran_pdesc *)
- dma_alloc_coherent(NULL, sizeof(struct tran_pdesc),
- (dma_addr_t *)ðer->tdesc_phys, GFP_KERNEL);
+ dma_alloc_coherent(&pdev->dev, sizeof(struct tran_pdesc),
+ ðer->tdesc_phys, GFP_KERNEL);
+
+ if (!ether->tdesc) {
+ dev_err(&pdev->dev, "Failed to allocate memory for tx desc\n");
+ return -ENOMEM;
+ }
ether->rdesc = (struct recv_pdesc *)
- dma_alloc_coherent(NULL, sizeof(struct recv_pdesc),
- (dma_addr_t *)ðer->rdesc_phys, GFP_KERNEL);
+ dma_alloc_coherent(&pdev->dev, sizeof(struct recv_pdesc),
+ ðer->rdesc_phys, GFP_KERNEL);
+
+ if (!ether->rdesc) {
+ dev_err(&pdev->dev, "Failed to allocate memory for rx desc\n");
+ dma_free_coherent(&pdev->dev, sizeof(struct tran_pdesc),
+ ether->tdesc, ether->tdesc_phys);
+ return -ENOMEM;
+ }
for (i = 0; i < TX_DESC_SIZE; i++) {
- tdesc = &(ether->tdesc->desclist[i]);
+ unsigned int offset;
- j = ((i + 1) / TX_DESC_SIZE);
+ tdesc = &(ether->tdesc->desclist[i]);
- if (j != 0) {
- tdesc_phys = &(ether->tdesc_phys->desclist[0]);
- ether->start_tx_ptr = (unsigned int)tdesc_phys;
- tdesc->next = (unsigned int)ether->start_tx_ptr;
- } else {
- tdesc_phys = &(ether->tdesc_phys->desclist[i+1]);
- tdesc->next = (unsigned int)tdesc_phys;
- }
+ if (i == TX_DESC_SIZE - 1)
+ offset = offsetof(struct tran_pdesc, desclist[0]);
+ else
+ offset = offsetof(struct tran_pdesc, desclist[i + 1]);
- tdesc->buffer = (unsigned int)ether->tdesc_phys->tran_buf[i];
+ tdesc->next = ether->tdesc_phys + offset;
+ tdesc->buffer = ether->tdesc_phys +
+ offsetof(struct tran_pdesc, tran_buf[i]);
tdesc->sl = 0;
tdesc->mode = 0;
}
+ ether->start_tx_ptr = ether->tdesc_phys;
+
for (i = 0; i < RX_DESC_SIZE; i++) {
- rdesc = &(ether->rdesc->desclist[i]);
+ unsigned int offset;
- j = ((i + 1) / RX_DESC_SIZE);
+ rdesc = &(ether->rdesc->desclist[i]);
- if (j != 0) {
- rdesc_phys = &(ether->rdesc_phys->desclist[0]);
- ether->start_rx_ptr = (unsigned int)rdesc_phys;
- rdesc->next = (unsigned int)ether->start_rx_ptr;
- } else {
- rdesc_phys = &(ether->rdesc_phys->desclist[i+1]);
- rdesc->next = (unsigned int)rdesc_phys;
- }
+ if (i == RX_DESC_SIZE - 1)
+ offset = offsetof(struct recv_pdesc, desclist[0]);
+ else
+ offset = offsetof(struct recv_pdesc, desclist[i + 1]);
+ rdesc->next = ether->rdesc_phys + offset;
rdesc->sl = RX_OWEN_DMA;
- rdesc->buffer = (unsigned int)ether->rdesc_phys->recv_buf[i];
+ rdesc->buffer = ether->rdesc_phys +
+ offsetof(struct recv_pdesc, recv_buf[i]);
}
+
+ ether->start_rx_ptr = ether->rdesc_phys;
+
+ return 0;
}
static void w90p910_set_fifo_threshold(struct net_device *dev)
@@ -552,11 +569,14 @@ static int w90p910_set_mac_address(struct net_device *dev, void *addr)
static int w90p910_ether_close(struct net_device *dev)
{
struct w90p910_ether *ether = netdev_priv(dev);
+ struct platform_device *pdev;
+
+ pdev = ether->pdev;
- dma_free_writecombine(NULL, sizeof(struct w90p910_rxbd),
- ether->rdesc, (dma_addr_t)ether->rdesc_phys);
- dma_free_writecombine(NULL, sizeof(struct w90p910_txbd),
- ether->tdesc, (dma_addr_t)ether->tdesc_phys);
+ dma_free_coherent(&pdev->dev, sizeof(struct recv_pdesc),
+ ether->rdesc, ether->rdesc_phys);
+ dma_free_coherent(&pdev->dev, sizeof(struct tran_pdesc),
+ ether->tdesc, ether->tdesc_phys);
netif_stop_queue(dev);
@@ -592,6 +612,7 @@ static int w90p910_send_frame(struct net_device *dev,
txbd = ðer->tdesc->desclist[ether->cur_tx];
buffer = ether->tdesc->tran_buf[ether->cur_tx];
+
if (length > 1514) {
dev_err(&pdev->dev, "send data %d bytes, check it\n", length);
length = 1514;
@@ -607,7 +628,9 @@ static int w90p910_send_frame(struct net_device *dev,
w90p910_trigger_tx(dev);
- ether->cur_tx = (ether->cur_tx+1) % TX_DESC_SIZE;
+ if (++ether->cur_tx >= TX_DESC_SIZE)
+ ether->cur_tx = 0;
+
txbd = ðer->tdesc->desclist[ether->cur_tx];
dev->trans_start = jiffies;
@@ -635,7 +658,6 @@ static irqreturn_t w90p910_tx_interrupt(int irq, void *dev_id)
struct w90p910_ether *ether;
struct w90p910_txbd *txbd;
struct platform_device *pdev;
- struct tran_pdesc *tran_pdesc;
struct net_device *dev;
unsigned int cur_entry, entry, status;
@@ -647,13 +669,14 @@ static irqreturn_t w90p910_tx_interrupt(int irq, void *dev_id)
cur_entry = __raw_readl(ether->reg + REG_CTXDSA);
- tran_pdesc = ether->tdesc_phys;
- entry = (unsigned int)(&tran_pdesc->desclist[ether->finish_tx]);
+ entry = ether->tdesc_phys +
+ offsetof(struct tran_pdesc, desclist[ether->finish_tx]);
while (entry != cur_entry) {
txbd = ðer->tdesc->desclist[ether->finish_tx];
- ether->finish_tx = (ether->finish_tx + 1) % TX_DESC_SIZE;
+ if (++ether->finish_tx >= TX_DESC_SIZE)
+ ether->finish_tx = 0;
if (txbd->sl & TXDS_TXCP) {
ether->stats.tx_packets++;
@@ -668,7 +691,8 @@ static irqreturn_t w90p910_tx_interrupt(int irq, void *dev_id)
if (netif_queue_stopped(dev))
netif_wake_queue(dev);
- entry = (unsigned int)(&tran_pdesc->desclist[ether->finish_tx]);
+ entry = ether->tdesc_phys +
+ offsetof(struct tran_pdesc, desclist[ether->finish_tx]);
}
if (status & MISTA_EXDEF) {
@@ -689,20 +713,20 @@ static void netdev_rx(struct net_device *dev)
struct w90p910_ether *ether;
struct w90p910_rxbd *rxbd;
struct platform_device *pdev;
- struct recv_pdesc *rdesc_phys;
struct sk_buff *skb;
unsigned char *data;
unsigned int length, status, val, entry;
ether = netdev_priv(dev);
pdev = ether->pdev;
- rdesc_phys = ether->rdesc_phys;
rxbd = ðer->rdesc->desclist[ether->cur_rx];
do {
val = __raw_readl(ether->reg + REG_CRXDSA);
- entry = (unsigned int)&rdesc_phys->desclist[ether->cur_rx];
+
+ entry = ether->rdesc_phys +
+ offsetof(struct recv_pdesc, desclist[ether->cur_rx]);
if (val == entry)
break;
@@ -747,7 +771,10 @@ static void netdev_rx(struct net_device *dev)
rxbd->sl = RX_OWEN_DMA;
rxbd->reserved = 0x0;
- ether->cur_rx = (ether->cur_rx+1) % RX_DESC_SIZE;
+
+ if (++ether->cur_rx >= RX_DESC_SIZE)
+ ether->cur_rx = 0;
+
rxbd = ðer->rdesc->desclist[ether->cur_rx];
dev->last_rx = jiffies;
@@ -955,30 +982,29 @@ static int __devinit w90p910_ether_probe(struct platform_device *pdev)
{
struct w90p910_ether *ether;
struct net_device *dev;
- struct resource *res;
int error;
dev = alloc_etherdev(sizeof(struct w90p910_ether));
if (!dev)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (res == NULL) {
+ ether = netdev_priv(dev);
+
+ ether->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (ether->res == NULL) {
dev_err(&pdev->dev, "failed to get I/O memory\n");
error = -ENXIO;
goto failed_free;
}
- res = request_mem_region(res->start, resource_size(res), pdev->name);
- if (res == NULL) {
+ if (!request_mem_region(ether->res->start,
+ resource_size(ether->res), pdev->name)) {
dev_err(&pdev->dev, "failed to request I/O memory\n");
error = -EBUSY;
goto failed_free;
}
- ether = netdev_priv(dev);
-
- ether->reg = ioremap(res->start, resource_size(res));
+ ether->reg = ioremap(ether->res->start, resource_size(ether->res));
if (ether->reg == NULL) {
dev_err(&pdev->dev, "failed to remap I/O memory\n");
error = -ENXIO;
@@ -1039,7 +1065,7 @@ failed_free_txirq:
failed_free_io:
iounmap(ether->reg);
failed_free_mem:
- release_mem_region(res->start, resource_size(res));
+ release_mem_region(ether->res->start, resource_size(ether->res));
failed_free:
free_netdev(dev);
return error;
@@ -1051,12 +1077,19 @@ static int __devexit w90p910_ether_remove(struct platform_device *pdev)
struct w90p910_ether *ether = netdev_priv(dev);
unregister_netdev(dev);
+
clk_put(ether->rmiiclk);
clk_put(ether->clk);
- del_timer_sync(ðer->check_timer);
- platform_set_drvdata(pdev, NULL);
+
+ iounmap(ether->reg);
+ release_mem_region(ether->res->start, resource_size(ether->res));
+
free_irq(ether->txirq, dev);
free_irq(ether->rxirq, dev);
+
+ del_timer_sync(ðer->check_timer);
+ platform_set_drvdata(pdev, NULL);
+
free_netdev(dev);
return 0;
}
--
1.5.6.3
> From: Trilok Soni <soni.trilok@gmail.com>
> Date: Mon, 20 Jul 2009 23:19:38 +0530
>
>> Hi David,
>>
>> On Mon, Jul 20, 2009 at 8:15 PM, David Miller<davem@davemloft.net> wrote:
>>> From: Wan ZongShun <mcuos.com@gmail.com>
>>> Date: Thu, 16 Jul 2009 20:55:05 +0800
>>>
>>>> Add mac driver support for evaluation board based on w90p910.
>>>>
>>>> Signed-off-by: Wan ZongShun <mcuos.com@gmail.com>
>>> Applied, thanks.
>> I thought Wan will send us the updated patch with fixing comments as
>> pointed by Russell.
>>
>> Wan, could you please send updated patch.
>
> Send me a relative patch as I've already pushed this driver commit
> publicly and that cannot be undone without a lot of pain.
>
^ 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