Netdev List
 help / color / mirror / Atom feed
* Re: ICMP packets - ll_temac with Microblaze
From: Eric Dumazet @ 2011-12-21 15:59 UTC (permalink / raw)
  To: monstr; +Cc: David Miller, John Williams, netdev
In-Reply-To: <4EF1EC28.90008@monstr.eu>

Le mercredi 21 décembre 2011 à 15:24 +0100, Michal Simek a écrit :
> Eric Dumazet wrote:
> > Le mercredi 21 décembre 2011 à 14:28 +0100, Michal Simek a écrit :
> > 
> >> ok. Can you provide me any background why size should be setup by
> >> size = SKB_WITH_OVERHEAD(ksize(data));
> >> and not to use size which is passed to kmalloc in __alloc_skb.
> > 
> > Its all about memory accounting (based on skb->truesize)
> > 
> > Prior to the patch, we could fool memory accounting because skbs claimed
> > to use less memory than what they really used.
> > 
> > And crash machines eventually.
> > 
> > Now memory accouting is fixed, we probably need to change some points in
> > the kernel, where we previously accepted a small skb, but not a very
> > large one.
> > 
> > Since "ping" probably uses SOCK_RAW sockets, I'll try this one :
> > 
> > (We dont care of _this_ skb truesize, only on the count of previously
> > queued packets)
> > 
> > 
> > diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
> > index 0da505c..a809a48 100644
> > --- a/net/packet/af_packet.c
> > +++ b/net/packet/af_packet.c
> > @@ -1631,8 +1631,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev,
> >  	if (snaplen > res)
> >  		snaplen = res;
> >  
> > -	if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
> > -	    (unsigned)sk->sk_rcvbuf)
> > +	if (atomic_read(&sk->sk_rmem_alloc) >= (unsigned)sk->sk_rcvbuf)
> >  		goto drop_n_acct;
> >  
> >  	if (skb_shared(skb)) {
> > @@ -1763,7 +1762,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
> >  	if (po->tp_version <= TPACKET_V2) {
> >  		if (macoff + snaplen > po->rx_ring.frame_size) {
> >  			if (po->copy_thresh &&
> > -				atomic_read(&sk->sk_rmem_alloc) + skb->truesize
> > +				atomic_read(&sk->sk_rmem_alloc)
> >  				< (unsigned)sk->sk_rcvbuf) {
> >  				if (skb_shared(skb)) {
> >  					copy_skb = skb_clone(skb, GFP_ATOMIC);
> > 
> > 
> > 
> > 
> 
> It doesn't work too.
> It is possible to see this behavior on qemu. What about if I prepare you package with cross toolchain, rootfs
> and you can add debug message where you want?
> 
> I have also tried ll_temac driver with ppc440 and behavior is the same.
> 
> Max FRAME_SIZE pass to netdev_alloc_skb_ip_align is 7966. For this value ping works.
> (For ll_temac driver it is #define XTE_JUMBO_MTU 7948 from ll_temac.h)
> 

I wonder if you applied/tested my patch correctly, since it really
should had help in your case  (allowing first received packet to be
queued, even if very big)

Given the way NIC drivers work (pre-allocating big buffers before
hardware fill frames in them), SO_RCVBUF limits are difficult to
respect.

We should allow at least one frame, even with a very small SO_RCVBUF
setting, or silently cap a minimum sane value.

^ permalink raw reply

* Re: ICMP packets - ll_temac with Microblaze
From: Eric Dumazet @ 2011-12-21 15:44 UTC (permalink / raw)
  To: monstr; +Cc: David Miller, John Williams, netdev
In-Reply-To: <1324481439.2301.7.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC>

Le mercredi 21 décembre 2011 à 16:30 +0100, Eric Dumazet a écrit :
> Le mercredi 21 décembre 2011 à 15:24 +0100, Michal Simek a écrit :
> > Eric Dumazet wrote:
> > > Le mercredi 21 décembre 2011 à 14:28 +0100, Michal Simek a écrit :
> > > 
> > >> ok. Can you provide me any background why size should be setup by
> > >> size = SKB_WITH_OVERHEAD(ksize(data));
> > >> and not to use size which is passed to kmalloc in __alloc_skb.
> > > 
> > > Its all about memory accounting (based on skb->truesize)
> > > 
> > > Prior to the patch, we could fool memory accounting because skbs claimed
> > > to use less memory than what they really used.
> > > 
> > > And crash machines eventually.
> > > 
> > > Now memory accouting is fixed, we probably need to change some points in
> > > the kernel, where we previously accepted a small skb, but not a very
> > > large one.
> > > 
> > > Since "ping" probably uses SOCK_RAW sockets, I'll try this one :
> > > 
> > > (We dont care of _this_ skb truesize, only on the count of previously
> > > queued packets)
> > > 
> > > 
> > > diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
> > > index 0da505c..a809a48 100644
> > > --- a/net/packet/af_packet.c
> > > +++ b/net/packet/af_packet.c
> > > @@ -1631,8 +1631,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev,
> > >  	if (snaplen > res)
> > >  		snaplen = res;
> > >  
> > > -	if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
> > > -	    (unsigned)sk->sk_rcvbuf)
> > > +	if (atomic_read(&sk->sk_rmem_alloc) >= (unsigned)sk->sk_rcvbuf)
> > >  		goto drop_n_acct;
> > >  
> > >  	if (skb_shared(skb)) {
> > > @@ -1763,7 +1762,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
> > >  	if (po->tp_version <= TPACKET_V2) {
> > >  		if (macoff + snaplen > po->rx_ring.frame_size) {
> > >  			if (po->copy_thresh &&
> > > -				atomic_read(&sk->sk_rmem_alloc) + skb->truesize
> > > +				atomic_read(&sk->sk_rmem_alloc)
> > >  				< (unsigned)sk->sk_rcvbuf) {
> > >  				if (skb_shared(skb)) {
> > >  					copy_skb = skb_clone(skb, GFP_ATOMIC);
> > > 
> > > 
> > > 
> > > 
> > 
> > It doesn't work too.
> > It is possible to see this behavior on qemu. What about if I prepare you package with cross toolchain, rootfs
> > and you can add debug message where you want?
> > 
> > I have also tried ll_temac driver with ppc440 and behavior is the same.
> > 
> > Max FRAME_SIZE pass to netdev_alloc_skb_ip_align is 7966. For this value ping works.
> > (For ll_temac driver it is #define XTE_JUMBO_MTU 7948 from ll_temac.h)
> 
> I did several tests with MTU 9000 on my machines and it works well.
> 
> It seems my pings (iputils-sss20071127 or iputils-sss20101006) uses a
> big enough RCVBUF
> 
> setsockopt(3, SOL_SOCKET, SO_RCVBUF, [65536], 4) = 0
> getsockopt(3, SOL_SOCKET, SO_RCVBUF, [131072], [4]) = 0
> 
> Could you check with "strace ping..." what is doing busybox ?

I found it : Its too small for jumbo frames.

setsockopt(3, SOL_SOCKET, SO_RCVBUF, [7280], 4) = 0

networking/ping.c


        /* set recv buf (needed if we can get lots of responses: flood ping,
         * broadcast ping etc) */
        sockopt = (datalen * 2) + 7 * 1024; /* giving it a bit of extra room */
        setsockopt(pingsock, SOL_SOCKET, SO_RCVBUF, &sockopt, sizeof(sockopt));

^ permalink raw reply

* Re: [PATCH 3/4] net: use cgroup_attach method to migrate socket priotiy and classid
From: Al Viro @ 2011-12-21 15:40 UTC (permalink / raw)
  To: Neil Horman; +Cc: netdev, Thomas Graf, David S. Miller
In-Reply-To: <1324478390-22036-4-git-send-email-nhorman@tuxdriver.com>

On Wed, Dec 21, 2011 at 09:39:49AM -0500, Neil Horman wrote:
> +static void cgrp_attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
> +			struct cgroup *old_cgrp, struct task_struct *tsk)
> +{
> +	int fd, err;
> +	struct files_struct *files;
> +	struct file *file;
> +	struct socket *sock;
> +	struct cgroup_netprio_state *old, *new;
> +	pid_t task_pid;
> + 
> +	files = get_files_struct(tsk);
> +	task_pid = task_pid_nr(tsk);
> + 
> +	old = cgrp_netprio_state(old_cgrp);
> +	new = cgrp_netprio_state(cgrp);
> + 
> +	spin_lock(&files->file_lock);
> +	for (fd=0; fd < files_fdtable(files)->max_fds; fd++) {
> +		file = fcheck_files(files, fd);
> +		if (!file)
> +			continue;
> +		sock = sock_from_file(file, &err);
> +		if (!sock)
> +			continue;
> +		if (!sock->sk)
> +			continue;
> +		if (sock->sk->sk_cgrp_owner == task_pid)
> +			sock->sk->sk_cgrp_prioidx = new->prioidx;

This looks bogus *and* racy; what about e.g. files currently in SCM_RIGHTS
datagrams?

^ permalink raw reply

* Re: [PATCH 2/4] vfs: Export some file manipulation functions
From: Christoph Hellwig @ 2011-12-21 15:30 UTC (permalink / raw)
  To: Neil Horman; +Cc: netdev, Thomas Graf, David S. Miller, linux-fsdevel
In-Reply-To: <1324478390-22036-3-git-send-email-nhorman@tuxdriver.com>

On Wed, Dec 21, 2011 at 09:39:48AM -0500, Neil Horman wrote:
> the networking cgroups can use the fd table of a task to make adjustments to the
> sockets that they own, helping us set owners for various resources. Export
> get_files_struct, put_files_struct and sock_from_file, so we can walk a tasks
> fdarray easily.

No, no one has any business using these lowlevel routines form modules.

Please find a way to do this in core code, or find more highlevel
primitives to export.

And not even Ccing linux-fsdevel on a change like this is one of the few
things I'd consider extremely offensive.


^ permalink raw reply

* Re: ICMP packets - ll_temac with Microblaze
From: Eric Dumazet @ 2011-12-21 15:30 UTC (permalink / raw)
  To: monstr; +Cc: David Miller, John Williams, netdev
In-Reply-To: <4EF1EC28.90008@monstr.eu>

Le mercredi 21 décembre 2011 à 15:24 +0100, Michal Simek a écrit :
> Eric Dumazet wrote:
> > Le mercredi 21 décembre 2011 à 14:28 +0100, Michal Simek a écrit :
> > 
> >> ok. Can you provide me any background why size should be setup by
> >> size = SKB_WITH_OVERHEAD(ksize(data));
> >> and not to use size which is passed to kmalloc in __alloc_skb.
> > 
> > Its all about memory accounting (based on skb->truesize)
> > 
> > Prior to the patch, we could fool memory accounting because skbs claimed
> > to use less memory than what they really used.
> > 
> > And crash machines eventually.
> > 
> > Now memory accouting is fixed, we probably need to change some points in
> > the kernel, where we previously accepted a small skb, but not a very
> > large one.
> > 
> > Since "ping" probably uses SOCK_RAW sockets, I'll try this one :
> > 
> > (We dont care of _this_ skb truesize, only on the count of previously
> > queued packets)
> > 
> > 
> > diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
> > index 0da505c..a809a48 100644
> > --- a/net/packet/af_packet.c
> > +++ b/net/packet/af_packet.c
> > @@ -1631,8 +1631,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev,
> >  	if (snaplen > res)
> >  		snaplen = res;
> >  
> > -	if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
> > -	    (unsigned)sk->sk_rcvbuf)
> > +	if (atomic_read(&sk->sk_rmem_alloc) >= (unsigned)sk->sk_rcvbuf)
> >  		goto drop_n_acct;
> >  
> >  	if (skb_shared(skb)) {
> > @@ -1763,7 +1762,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
> >  	if (po->tp_version <= TPACKET_V2) {
> >  		if (macoff + snaplen > po->rx_ring.frame_size) {
> >  			if (po->copy_thresh &&
> > -				atomic_read(&sk->sk_rmem_alloc) + skb->truesize
> > +				atomic_read(&sk->sk_rmem_alloc)
> >  				< (unsigned)sk->sk_rcvbuf) {
> >  				if (skb_shared(skb)) {
> >  					copy_skb = skb_clone(skb, GFP_ATOMIC);
> > 
> > 
> > 
> > 
> 
> It doesn't work too.
> It is possible to see this behavior on qemu. What about if I prepare you package with cross toolchain, rootfs
> and you can add debug message where you want?
> 
> I have also tried ll_temac driver with ppc440 and behavior is the same.
> 
> Max FRAME_SIZE pass to netdev_alloc_skb_ip_align is 7966. For this value ping works.
> (For ll_temac driver it is #define XTE_JUMBO_MTU 7948 from ll_temac.h)

I did several tests with MTU 9000 on my machines and it works well.

It seems my pings (iputils-sss20071127 or iputils-sss20101006) uses a
big enough RCVBUF

setsockopt(3, SOL_SOCKET, SO_RCVBUF, [65536], 4) = 0
getsockopt(3, SOL_SOCKET, SO_RCVBUF, [131072], [4]) = 0

Could you check with "strace ping..." what is doing busybox ?

^ permalink raw reply

* [PATCH net-next] igb: Add support for byte queue limits.
From: Eric Dumazet @ 2011-12-21 15:18 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Jeff Kirsher, Alexander Duyck

This adds support for byte queue limits (BQL)

Since this driver collects bytes count in 'bytecount' field, use it also
in igb_tx_map()

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
CC: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
CC: Alexander Duyck <alexander.h.duyck@intel.com>
---
 drivers/net/ethernet/intel/igb/igb.h      |    5 +++++
 drivers/net/ethernet/intel/igb/igb_main.c |    5 +++++
 2 files changed, 10 insertions(+)

diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
index c69feeb..3d12e67 100644
--- a/drivers/net/ethernet/intel/igb/igb.h
+++ b/drivers/net/ethernet/intel/igb/igb.h
@@ -447,4 +447,9 @@ static inline s32 igb_get_phy_info(struct e1000_hw *hw)
 	return 0;
 }
 
+static inline struct netdev_queue *txring_txq(const struct igb_ring *tx_ring)
+{
+	return netdev_get_tx_queue(tx_ring->netdev, tx_ring->queue_index);
+}
+
 #endif /* _IGB_H_ */
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 89d576c..dcc68cc 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -3201,6 +3201,7 @@ static void igb_clean_tx_ring(struct igb_ring *tx_ring)
 		buffer_info = &tx_ring->tx_buffer_info[i];
 		igb_unmap_and_free_tx_resource(tx_ring, buffer_info);
 	}
+	netdev_tx_reset_queue(txring_txq(tx_ring));
 
 	size = sizeof(struct igb_tx_buffer) * tx_ring->count;
 	memset(tx_ring->tx_buffer_info, 0, size);
@@ -4238,6 +4239,8 @@ static void igb_tx_map(struct igb_ring *tx_ring,
 		frag++;
 	}
 
+	netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount);
+
 	/* write last descriptor with RS and EOP bits */
 	cmd_type |= cpu_to_le32(size) | cpu_to_le32(IGB_TXD_DCMD);
 	tx_desc->read.cmd_type_len = cmd_type;
@@ -5777,6 +5780,8 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector)
 		}
 	}
 
+	netdev_tx_completed_queue(txring_txq(tx_ring),
+				  total_packets, total_bytes);
 	i += tx_ring->count;
 	tx_ring->next_to_clean = i;
 	u64_stats_update_begin(&tx_ring->tx_syncp);

^ permalink raw reply related

* Re: [PATCH] ARM: net: JIT compiler for packet filters
From: Nicolas Pitre @ 2011-12-21 15:07 UTC (permalink / raw)
  To: Mircea Gherzan; +Cc: linux-arm-kernel, netdev, linux
In-Reply-To: <20111221144346.GB3229@swarm.cs.pub.ro>

On Wed, 21 Dec 2011, Mircea Gherzan wrote:

> On Mon, Dec 19, 2011 at 12:42:49PM -0500, Nicolas Pitre wrote:
> > On Mon, 19 Dec 2011, Mircea Gherzan wrote:
> > 
> > > +static inline void _emit(int cond, u32 inst, struct jit_ctx *ctx)
> > > +{
> > > +	if (ctx->target != NULL)
> > > +		ctx->target[ctx->idx] = inst | (cond << 28);
> > > +
> > > +	ctx->idx++;
> > > +}
> > 
> > You might consider the patch titled "ARM: Add generic instruction opcode 
> > manipulation helpers" that Dave Martin just posted and rely on it to 
> > make your code compatible with BE8 mode as well.
> 
> That patch is not in devel-stable and I don't want to introduce further
> dependencies for the time being. Once both patches are in mainline, I
> will take a look.

Fair enough.


Nicolas

^ permalink raw reply

* Re: [PATCH v2] ARM: net: JIT compiler for packet filters
From: Mircea Gherzan @ 2011-12-21 14:59 UTC (permalink / raw)
  To: Dave Martin; +Cc: linux-arm-kernel, netdev, linux
In-Reply-To: <20111219182908.GA2027@linaro.org>

On Mon, Dec 19, 2011 at 06:29:08PM +0000, Dave Martin wrote:
> On Mon, Dec 19, 2011 at 06:18:39PM +0000, Dave Martin wrote:
> > On Mon, Dec 19, 2011 at 06:45:13PM +0200, Mircea Gherzan wrote:
> 
> [...]
> 
> > > The JITed code calls back to the kernel for the load helpers. So setting
> > > bit 0 is required.
> > 
> > When you take the address of a link-time external function symbol,
> > bit[0] in the address will automatically be set appropriately by the
> > linker to indicate the target instruction set -- you already use BX/BLX
> > to jump to such symbols, so you should switch correctly when calling
> > _to_ the kernel.
> > 
> > Returns should also work, except for old-style "mov pc,lr" returns made
> > in Thumb code (from ARM code, this magically works for >= v7).  Such returns
> > only happen in hand-written assembler: for C code, the compiler always
> > generates proper AEABI-compliant return sequences.
> > 
> > So, for calling load_func[], jit_get_skb_b etc. (which are C functions),
> > there should be no problem.
> > 
> > I think the only code which you call from the JIT output but which does
> > not return compliantly is __aeabi_uidiv() in arch/arm/lib/lib1funcs.S.
> > 
> > 
> > I have a quick hacked-up patch (below) which attempts to fix this;
> > I'd be interested if this works for you  -- but finalising your ARM-only
> > version of the patch should still be the priority.
> > 
> > If this fix does work, I'll turn it into a proper patch, as we can maybe
> > use it more widely.
> 
> Oops, I forgot to paste in my patch ... here it is.
> 
> Cheers
> ---Dave
> 
> diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
> index b6e65de..013bfaf 100644
> --- a/arch/arm/include/asm/assembler.h
> +++ b/arch/arm/include/asm/assembler.h
> @@ -313,4 +313,39 @@
>  	.size \name , . - \name
>  	.endm
>  
> +/*
> + * Helper macro to abstract a function return, where the return address is
> + * held in a register:
> + */
> +.macro __def_bret cc
> +	.macro bret\cc Rm:req
> +#if __LINUX_ARM_ARCH__ < 7
> +		mov\cc	pc, \Rm
> +#else
> +		bx\cc	\Rm
> +#endif

This patch worked for me, because I'm using ARMv7 exclusively. But I'm
inclined to think that your patch will fail on ARMv6T (for example) with
a Thumb2 kernel, because the "mov pc, Rm" is a simple branch on pre-v7
cores.

Note however that v3 of my patch no longer requires any changes to the
assembly code: the C trampoline/wrapper for integer division ensures a
proper return. And this one is used only for the DIV_X BPF opcode, which
appears also quite rarely.

[...]

Cheers,
Mircea

^ permalink raw reply

* Re: [PATCH] net/sched: sch_plug - Queue traffic until an explicit release command
From: Jamal Hadi Salim @ 2011-12-21 14:54 UTC (permalink / raw)
  To: rshriram; +Cc: netdev, Brendan Cully
In-Reply-To: <CAP8mzPNmqPjmYZHT5d21D1yjz293wF+EF0BwoMAu+M=7VtHHSg@mail.gmail.com>

On Tue, 2011-12-20 at 11:05 -0600, Shriram Rajagopalan wrote:

> In dom0. Basically the setup is like this:
>  Guest (veth0)
>  dom0 (vif0.0 --> eth0)
> 
>    packets coming out of veth0 appear as incoming packets in vif0.0
>  Once Remus (or any other output commit style system is started)
>  the following commands could be executed in dom0, to activate this qdisc
>  ip link set ifb0 up
>  tc qdisc add dev vif0.0 ingress
>  tc filter add dev vif0.0 parent ffff: proto ip pref 10 u32 match u32
> 0 0 action mirred egress redirect dev eth0

Ok. To fill in the blank there, I believe the qdisc will be attached to
ifb0? Nobody cares about latency? You have > 20K packets being
accumulated here ...

Also assuming that this is a setup thing that happens for every 
guest that needs checkpointing 

> 
> Oh yes. But throttle functionality doesnt seem to be implemented
> in the qdisc code base. there is a throttle flag but looking at the
> qdisc scheduler, I could see no references to this flag or related actions.
> That is why in the dequeue function, I return NULL until the release pointer
> is set.

Thats along the lines i was thinking of. If you could set the throttle
flag (more work involved than i am suggesting), then you solve the
problem with any qdisc.
Your qdisc is essentially a bfifo with throttling.
 
> And we need a couple of netlink api calls (PLUG/UNPLUG) to manipulate
> the qdisc from userspace

Right - needed to "set the throttle flag" part.

> I have done better. When Remus is activated for a Guest VM, I pull the
> plug from the primary physical host and the ssh connection to the domU,
> with top command running (and/or xeyes) continues to run seamlessly. ;)

I dont think that kind of traffic will fill up your humongous queue.
You need some bulk transfers going on filling the link bandwidth to see
the futility of the queue.

> When the guest VM recovers on another physical host, it is restored to the
> most recent checkpoint. With a checkpoint frequency of 25ms, in the worst case
> on failover, one checkpoint worth of execution could be lost.

Out of curiosity: how much traffic do you end up generating for just
checkpointing? Is this using a separate link?

I am also a little lost: Are you going to plug/unplug every time you
checkpoint? i.e we are going to have 2 netlink messages every 25ms
for above?

>  With the loss of
> the physical machine and its output buffer, the packets (tcp,udp, etc)
> are also lost.
> 
> But that does not affect the "consistency" of the state of Guest and
> client connections,
> as the client (say TCP clients) only think that there was some packet
> loss and "resend"
> the packets. The resuming Guest VM on the backup host would pickup the
> connection
> from where it left off.

Yes, this is what i was trying to get to. If you dont buffer,
the end hosts will recover anyways. The value being no code
changes needed. Not just that, I am pointing that buffering
in itself is not very useful when the link is being used to its
full capacity. 

[Sorry, I feel I am treading on questioning the utility of what
you are doing but i cant help myself, it is just my nature to 
question;-> In a past life i may have been a relative of some ancient
Greek philospher.]

> OTOH, if the packets were released before the checkpoint was done,
> then we have the
> classic orphaned messages problem. If the client and the Guest VM
> exchange a bunch of packets, the TCP window moves. 
> When the Guest VM resumes on the backup host,
> it is basically rolled back in time (by 25ms or so), i.e. it does not
> know about the shift
> in the tcp window. Hence, the client and Guest's tcp sequence numbers
> would be out of
> sync and the connection would hang. 

So this part is interesting - but i wonder if the issue is not so
much the window moved but some other bug or misfeature or i am missing
something. Shouldnt the sender just get an ACK with signifying the
correct sequence number? Also, if you have access to the receivers(new
guest) sequence number could you not "adjust it" based on the checkpoint
messages?

> Which we dont want. I want to buffer the packets and then release them
> once the checkpoint is committed at the backup host.

And whose value is still unclear to me.

> One could do this with any qdisc but the catch here is that the qdisc
> stops releasing packets only when it hits the stop pointer (ie start of
> the next checkpoint buffer). Simply putting a qdisc to sleep would
> prevent it from releasing packets from the current buffer (whose checkpoint
> has been acked).

I meant putting it to sleep when you plug and waking it when you
unplug. By sleep i meant blackholing for the checkpointing + 
recovery period. I understand that dropping is not what you want to
achieve because you see value in buffering.

> I agree. Its more sensible to configure it via the tc command. I would
> probably have to end up issuing patches for the tc code base too.

I think you MUST do this. We dont believe in hardcoding anything. You 
are playing in policy management territory. Let the control side worry
about policies. Ex: I think if you knew the bandwidth of the link and
the checkpointing frequency, you could come up with a reasonable buffer
size.

> > Look at the other feedback given to you (Stephen and Dave responded).
> >
> > If a qdisc is needed, should it not be a classful qdisc?
> >
> 
> I dont understand. why ?

I was coming from the same reasoning i used earlier, i.e
this sounds like a generic problem.
You are treading into policy management and deciding what is best
for the guest user. We have an infrastructure that allows the admin 
to setup policies based on traffic characteristics. You are limiting
this feature to be only used by folks who have no choice but to use
your qdisc. I cant isolate latency sensitive traffic like an slogin
sitting behind 20K scp packets etc. If you make it classful, that
isolation can be added etc. Not sure if i made sense.

Alternatively, this seems to me like a bfifo qdisc that needs to have
throttle support that can be controlled from user space.

cheers,
jamal

^ permalink raw reply

* Re: [PATCH] ARM: net: JIT compiler for packet filters
From: Mircea Gherzan @ 2011-12-21 14:43 UTC (permalink / raw)
  To: Nicolas Pitre; +Cc: linux-arm-kernel, netdev, linux
In-Reply-To: <alpine.LFD.2.02.1112191231520.2907@xanadu.home>

On Mon, Dec 19, 2011 at 12:42:49PM -0500, Nicolas Pitre wrote:
> On Mon, 19 Dec 2011, Mircea Gherzan wrote:
> 
> > +static inline void _emit(int cond, u32 inst, struct jit_ctx *ctx)
> > +{
> > +	if (ctx->target != NULL)
> > +		ctx->target[ctx->idx] = inst | (cond << 28);
> > +
> > +	ctx->idx++;
> > +}
> 
> You might consider the patch titled "ARM: Add generic instruction opcode 
> manipulation helpers" that Dave Martin just posted and rely on it to 
> make your code compatible with BE8 mode as well.

That patch is not in devel-stable and I don't want to introduce further
dependencies for the time being. Once both patches are in mainline, I
will take a look.

> Also it seems that you are making the distinction between pre-ARMv7 and 
> ARMv7+ while in most cases it should be pre-ARMv6 and ARMv6+

Has been fixed in v2 of the patch.

Mircea

^ permalink raw reply

* [PATCH 4/4] net: remove no-longer needed calls to sock_update_[classid|netprioix]
From: Neil Horman @ 2011-12-21 14:39 UTC (permalink / raw)
  To: netdev; +Cc: Neil Horman, Thomas Graf, David S. Miller
In-Reply-To: <1324478390-22036-1-git-send-email-nhorman@tuxdriver.com>

Now that we can use cgroups to re-write individual sockets classid and priroity,
we no longer have to update them on each send/recieve

Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
CC: Thomas Graf <tgraf@infradead.org>
CC: "David S. Miller" <davem@davemloft.net>
---
 drivers/net/tun.c            |    2 --
 include/net/netprio_cgroup.h |    6 ------
 include/net/sock.h           |    8 --------
 net/core/sock.c              |    9 +++++----
 net/socket.c                 |   10 ----------
 5 files changed, 5 insertions(+), 30 deletions(-)

diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 93c5d72..cf70336 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -582,8 +582,6 @@ static struct sk_buff *tun_alloc_skb(struct tun_struct *tun,
 	struct sk_buff *skb;
 	int err;
 
-	sock_update_classid(sk);
-
 	/* Under a page?  Don't bother with paged skb. */
 	if (prepad + len < PAGE_SIZE || !linear)
 		linear = len;
diff --git a/include/net/netprio_cgroup.h b/include/net/netprio_cgroup.h
index e503b87..9c794ab 100644
--- a/include/net/netprio_cgroup.h
+++ b/include/net/netprio_cgroup.h
@@ -36,8 +36,6 @@ struct cgroup_netprio_state {
 extern int net_prio_subsys_id;
 #endif
 
-extern void sock_update_netprioidx(struct sock *sk);
-
 static inline struct cgroup_netprio_state
 		*task_netprio_state(struct task_struct *p)
 {
@@ -48,10 +46,6 @@ static inline struct cgroup_netprio_state
 	return NULL;
 #endif
 }
-
-#else
-
-#define sock_update_netprioidx(sk)
 #endif
 
 #endif  /* _NET_CLS_CGROUP_H */
diff --git a/include/net/sock.h b/include/net/sock.h
index cdb03c2..df30db0 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1367,14 +1367,6 @@ extern void *sock_kmalloc(struct sock *sk, int size,
 extern void sock_kfree_s(struct sock *sk, void *mem, int size);
 extern void sk_send_sigurg(struct sock *sk);
 
-#ifdef CONFIG_CGROUPS
-extern void sock_update_classid(struct sock *sk);
-#else
-static inline void sock_update_classid(struct sock *sk)
-{
-}
-#endif
-
 /*
  * Functions to fill in entries in struct proto_ops when a protocol
  * does not implement a particular function.
diff --git a/net/core/sock.c b/net/core/sock.c
index b922fb5..cfc2d10 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1160,7 +1160,7 @@ static void sk_prot_free(struct proto *prot, struct sock *sk)
 }
 
 #ifdef CONFIG_CGROUPS
-void sock_update_classid(struct sock *sk)
+static void sock_update_classid(struct sock *sk)
 {
 	pid_t tpid;
 	u32 classid;
@@ -1174,9 +1174,8 @@ void sock_update_classid(struct sock *sk)
 	    (classid && classid != sk->sk_classid))
 		sk->sk_classid = classid;
 }
-EXPORT_SYMBOL(sock_update_classid);
 
-void sock_update_netprioidx(struct sock *sk)
+static void sock_update_netprioidx(struct sock *sk)
 {
 	pid_t tpid;
 	struct cgroup_netprio_state *state;
@@ -1189,7 +1188,9 @@ void sock_update_netprioidx(struct sock *sk)
 		sk->sk_cgrp_prioidx = state ? state->prioidx : 0;
 	rcu_read_unlock();
 }
-EXPORT_SYMBOL_GPL(sock_update_netprioidx);
+#else
+#define sock_update_classid(sk)
+#define sock_update_netprioidx(sk)
 #endif
 
 /**
diff --git a/net/socket.c b/net/socket.c
index eab8db1..3c6693a 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -550,10 +550,6 @@ static inline int __sock_sendmsg_nosec(struct kiocb *iocb, struct socket *sock,
 {
 	struct sock_iocb *si = kiocb_to_siocb(iocb);
 
-	sock_update_classid(sock->sk);
-
-	sock_update_netprioidx(sock->sk);
-
 	si->sock = sock;
 	si->scm = NULL;
 	si->msg = msg;
@@ -716,8 +712,6 @@ static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock,
 {
 	struct sock_iocb *si = kiocb_to_siocb(iocb);
 
-	sock_update_classid(sock->sk);
-
 	si->sock = sock;
 	si->scm = NULL;
 	si->msg = msg;
@@ -828,8 +822,6 @@ static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
 	if (unlikely(!sock->ops->splice_read))
 		return -EINVAL;
 
-	sock_update_classid(sock->sk);
-
 	return sock->ops->splice_read(sock, ppos, pipe, len, flags);
 }
 
@@ -3376,8 +3368,6 @@ EXPORT_SYMBOL(kernel_setsockopt);
 int kernel_sendpage(struct socket *sock, struct page *page, int offset,
 		    size_t size, int flags)
 {
-	sock_update_classid(sock->sk);
-
 	if (sock->ops->sendpage)
 		return sock->ops->sendpage(sock, page, offset, size, flags);
 
-- 
1.7.6.4

^ permalink raw reply related

* [PATCH 3/4] net: use cgroup_attach method to migrate socket priotiy and classid
From: Neil Horman @ 2011-12-21 14:39 UTC (permalink / raw)
  To: netdev; +Cc: Neil Horman, Thomas Graf, David S. Miller
In-Reply-To: <1324478390-22036-1-git-send-email-nhorman@tuxdriver.com>

Now that we have an owner identified for each socket, we can use the
cgroup_attach method to migrate sockets owned by migrating tasks to their new
cgroup instances.

Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
CC: Thomas Graf <tgraf@infradead.org>
CC: "David S. Miller" <davem@davemloft.net>
---
 net/core/netprio_cgroup.c |   40 +++++++++++++++++++++++++++++++++++++++-
 net/sched/cls_cgroup.c    |   39 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 78 insertions(+), 1 deletions(-)

diff --git a/net/core/netprio_cgroup.c b/net/core/netprio_cgroup.c
index 3a9fd48..32eef0f 100644
--- a/net/core/netprio_cgroup.c
+++ b/net/core/netprio_cgroup.c
@@ -18,6 +18,7 @@
 #include <linux/cgroup.h>
 #include <linux/rcupdate.h>
 #include <linux/atomic.h>
+#include <linux/fdtable.h>
 #include <net/rtnetlink.h>
 #include <net/pkt_cls.h>
 #include <net/sock.h>
@@ -27,12 +28,14 @@ static struct cgroup_subsys_state *cgrp_create(struct cgroup_subsys *ss,
 					       struct cgroup *cgrp);
 static void cgrp_destroy(struct cgroup_subsys *ss, struct cgroup *cgrp);
 static int cgrp_populate(struct cgroup_subsys *ss, struct cgroup *cgrp);
-
+static void cgrp_attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
+			struct cgroup *old_cgrp, struct task_struct *tsk);
 struct cgroup_subsys net_prio_subsys = {
 	.name		= "net_prio",
 	.create		= cgrp_create,
 	.destroy	= cgrp_destroy,
 	.populate	= cgrp_populate,
+	.attach		= cgrp_attach,
 #ifdef CONFIG_NETPRIO_CGROUP
 	.subsys_id	= net_prio_subsys_id,
 #endif
@@ -265,6 +268,41 @@ static int cgrp_populate(struct cgroup_subsys *ss, struct cgroup *cgrp)
 	return cgroup_add_files(cgrp, ss, ss_files, ARRAY_SIZE(ss_files));
 }
 
+static void cgrp_attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
+			struct cgroup *old_cgrp, struct task_struct *tsk)
+{
+	int fd, err;
+	struct files_struct *files;
+	struct file *file;
+	struct socket *sock;
+	struct cgroup_netprio_state *old, *new;
+	pid_t task_pid;
+ 
+	files = get_files_struct(tsk);
+	task_pid = task_pid_nr(tsk);
+ 
+	old = cgrp_netprio_state(old_cgrp);
+	new = cgrp_netprio_state(cgrp);
+ 
+	spin_lock(&files->file_lock);
+	for (fd=0; fd < files_fdtable(files)->max_fds; fd++) {
+		file = fcheck_files(files, fd);
+		if (!file)
+			continue;
+		sock = sock_from_file(file, &err);
+		if (!sock)
+			continue;
+		if (!sock->sk)
+			continue;
+		if (sock->sk->sk_cgrp_owner == task_pid)
+			sock->sk->sk_cgrp_prioidx = new->prioidx;
+	}
+	spin_unlock(&files->file_lock);
+ 
+	put_files_struct(files);
+}
+ 
+
 static int netprio_device_event(struct notifier_block *unused,
 				unsigned long event, void *ptr)
 {
diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c
index f84fdc3..7020cda 100644
--- a/net/sched/cls_cgroup.c
+++ b/net/sched/cls_cgroup.c
@@ -17,6 +17,7 @@
 #include <linux/skbuff.h>
 #include <linux/cgroup.h>
 #include <linux/rcupdate.h>
+#include <linux/fdtable.h>
 #include <net/rtnetlink.h>
 #include <net/pkt_cls.h>
 #include <net/sock.h>
@@ -26,12 +27,15 @@ static struct cgroup_subsys_state *cgrp_create(struct cgroup_subsys *ss,
 					       struct cgroup *cgrp);
 static void cgrp_destroy(struct cgroup_subsys *ss, struct cgroup *cgrp);
 static int cgrp_populate(struct cgroup_subsys *ss, struct cgroup *cgrp);
+static void cgrp_attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
+			struct cgroup *old_cgrp, struct task_struct *tsk);
 
 struct cgroup_subsys net_cls_subsys = {
 	.name		= "net_cls",
 	.create		= cgrp_create,
 	.destroy	= cgrp_destroy,
 	.populate	= cgrp_populate,
+	.attach		= cgrp_attach,
 #ifdef CONFIG_NET_CLS_CGROUP
 	.subsys_id	= net_cls_subsys_id,
 #endif
@@ -95,6 +99,41 @@ static int cgrp_populate(struct cgroup_subsys *ss, struct cgroup *cgrp)
 	return cgroup_add_files(cgrp, ss, ss_files, ARRAY_SIZE(ss_files));
 }
 
+static void cgrp_attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
+			struct cgroup *old_cgrp, struct task_struct *tsk)
+{
+	int fd, err;
+	struct files_struct *files;
+	struct file *file;
+	struct socket *sock;
+	struct cgroup_cls_state *old, *new;
+	pid_t task_pid;
+ 
+	files = get_files_struct(tsk);
+	task_pid = task_pid_nr(tsk);
+ 
+	old = cgrp_cls_state(old_cgrp);
+	new = cgrp_cls_state(cgrp);
+ 
+	spin_lock(&files->file_lock);
+	for (fd=0; fd < files_fdtable(files)->max_fds; fd++) {
+		file = fcheck_files(files, fd);
+		if (!file)
+			continue;
+		sock = sock_from_file(file, &err);
+		if (!sock)
+			continue;
+		if (!sock->sk)
+			continue;
+		if (sock->sk->sk_cgrp_owner == task_pid)
+			sock->sk->sk_classid = new->classid;
+	}
+	spin_unlock(&files->file_lock);
+ 
+	put_files_struct(files);
+}
+ 
+
 struct cls_cgroup_head {
 	u32			handle;
 	struct tcf_exts		exts;
-- 
1.7.6.4

^ permalink raw reply related

* [PATCH 2/4] vfs: Export some file manipulation functions
From: Neil Horman @ 2011-12-21 14:39 UTC (permalink / raw)
  To: netdev; +Cc: Neil Horman, Thomas Graf, David S. Miller
In-Reply-To: <1324478390-22036-1-git-send-email-nhorman@tuxdriver.com>

the networking cgroups can use the fd table of a task to make adjustments to the
sockets that they own, helping us set owners for various resources. Export
get_files_struct, put_files_struct and sock_from_file, so we can walk a tasks
fdarray easily.

Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
CC: Thomas Graf <tgraf@infradead.org>
CC: "David S. Miller" <davem@davemloft.net>
---
 include/linux/fdtable.h |    4 ++--
 include/linux/net.h     |    1 +
 kernel/exit.c           |    2 ++
 net/socket.c            |    3 ++-
 4 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h
index 82163c4..1d06352 100644
--- a/include/linux/fdtable.h
+++ b/include/linux/fdtable.h
@@ -97,8 +97,8 @@ static inline struct file * fcheck_files(struct files_struct *files, unsigned in
 
 struct task_struct;
 
-struct files_struct *get_files_struct(struct task_struct *);
-void put_files_struct(struct files_struct *fs);
+extern struct files_struct *get_files_struct(struct task_struct *);
+extern void put_files_struct(struct files_struct *fs);
 void reset_files_struct(struct files_struct *);
 int unshare_files(struct files_struct **);
 struct files_struct *dup_fd(struct files_struct *, int *);
diff --git a/include/linux/net.h b/include/linux/net.h
index b299230..eea9912 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -245,6 +245,7 @@ extern int   	     sock_sendmsg(struct socket *sock, struct msghdr *msg,
 extern int	     sock_recvmsg(struct socket *sock, struct msghdr *msg,
 				  size_t size, int flags);
 extern int 	     sock_map_fd(struct socket *sock, int flags);
+extern struct socket *sock_from_file(struct file *file, int *err);
 extern struct socket *sockfd_lookup(int fd, int *err);
 #define		     sockfd_put(sock) fput(sock->file)
 extern int	     net_ratelimit(void);
diff --git a/kernel/exit.c b/kernel/exit.c
index d0b7d98..2f48b95 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -499,6 +499,7 @@ struct files_struct *get_files_struct(struct task_struct *task)
 
 	return files;
 }
+EXPORT_SYMBOL(get_files_struct);
 
 void put_files_struct(struct files_struct *files)
 {
@@ -520,6 +521,7 @@ void put_files_struct(struct files_struct *files)
 		rcu_read_unlock();
 	}
 }
+EXPORT_SYMBOL(put_files_struct);
 
 void reset_files_struct(struct files_struct *files)
 {
diff --git a/net/socket.c b/net/socket.c
index e62b4f0..eab8db1 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -398,7 +398,7 @@ int sock_map_fd(struct socket *sock, int flags)
 }
 EXPORT_SYMBOL(sock_map_fd);
 
-static struct socket *sock_from_file(struct file *file, int *err)
+struct socket *sock_from_file(struct file *file, int *err)
 {
 	if (file->f_op == &socket_file_ops)
 		return file->private_data;	/* set in sock_map_fd */
@@ -406,6 +406,7 @@ static struct socket *sock_from_file(struct file *file, int *err)
 	*err = -ENOTSOCK;
 	return NULL;
 }
+EXPORT_SYMBOL(sock_from_file);
 
 /**
  *	sockfd_lookup - Go from a file number to its socket slot
-- 
1.7.6.4

^ permalink raw reply related

* [PATCH 1/4] net_prio/classid: add cgroup process ownership filter
From: Neil Horman @ 2011-12-21 14:39 UTC (permalink / raw)
  To: netdev; +Cc: Neil Horman, Thomas Graf, David S. Miller
In-Reply-To: <1324478390-22036-1-git-send-email-nhorman@tuxdriver.com>

To prevent multiple processes that share a socket from fighting over the cgroup
instance said socket belongs to, add a sk_cgrp_owner flag so that calls to
sk_update_[classid/prioidx] only do something in the event that its the owning
process updating them.  This way only one pid is responsible for updating the
sockets cgroup information.  When that process releases the socket, set the
owner pid to zero so as to prevent a future task that reuses the same pid from
inheriting the socket erroneously

Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
CC: Thomas Graf <tgraf@infradead.org>
CC: "David S. Miller" <davem@davemloft.net>
---
 include/net/sock.h |    4 ++++
 net/core/sock.c    |   15 ++++++++++++---
 2 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/include/net/sock.h b/include/net/sock.h
index 18ecc99..cdb03c2 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -327,6 +327,7 @@ struct sock {
 	unsigned short		sk_max_ack_backlog;
 	__u32			sk_priority;
 #ifdef CONFIG_CGROUPS
+	pid_t			sk_cgrp_owner;
 	__u32			sk_cgrp_prioidx;
 #endif
 	struct pid		*sk_peer_pid;
@@ -1537,6 +1538,9 @@ static inline void sock_orphan(struct sock *sk)
 	sock_set_flag(sk, SOCK_DEAD);
 	sk_set_socket(sk, NULL);
 	sk->sk_wq  = NULL;
+#ifdef CONFIG_CGROUPS
+	sk->sk_cgrp_owner = 0;
+#endif
 	write_unlock_bh(&sk->sk_callback_lock);
 }
 
diff --git a/net/core/sock.c b/net/core/sock.c
index 5a6a906..b922fb5 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1162,24 +1162,31 @@ static void sk_prot_free(struct proto *prot, struct sock *sk)
 #ifdef CONFIG_CGROUPS
 void sock_update_classid(struct sock *sk)
 {
+	pid_t tpid;
 	u32 classid;
 
 	rcu_read_lock();  /* doing current task, which cannot vanish. */
 	classid = task_cls_classid(current);
+	tpid = task_pid_nr(current);
 	rcu_read_unlock();
-	if (classid && classid != sk->sk_classid)
+
+	if ((tpid == sk->sk_cgrp_owner) &&
+	    (classid && classid != sk->sk_classid))
 		sk->sk_classid = classid;
 }
 EXPORT_SYMBOL(sock_update_classid);
 
 void sock_update_netprioidx(struct sock *sk)
 {
+	pid_t tpid;
 	struct cgroup_netprio_state *state;
 	if (in_interrupt())
 		return;
 	rcu_read_lock();
+	tpid = task_pid_nr(current);
 	state = task_netprio_state(current);
-	sk->sk_cgrp_prioidx = state ? state->prioidx : 0;
+	if (tpid == sk->sk_cgrp_owner)
+		sk->sk_cgrp_prioidx = state ? state->prioidx : 0;
 	rcu_read_unlock();
 }
 EXPORT_SYMBOL_GPL(sock_update_netprioidx);
@@ -1208,7 +1215,9 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority,
 		sock_lock_init(sk);
 		sock_net_set(sk, get_net(net));
 		atomic_set(&sk->sk_wmem_alloc, 1);
-
+#ifdef CONFIG_CGROUPS
+		sk->sk_cgrp_owner = task_pid_nr(current);
+#endif
 		sock_update_classid(sk);
 		sock_update_netprioidx(sk);
 	}
-- 
1.7.6.4

^ permalink raw reply related

* [PATCH 0/4] net: Improve socket sharing between multiple cgroups
From: Neil Horman @ 2011-12-21 14:39 UTC (permalink / raw)
  To: netdev; +Cc: Neil Horman, Thomas Graf, David S. Miller

Currently, the network centric cgroups for priority and classification don't 
share resources properly.  Since socket priority and classification are
assigned based on the socket through which the data was sent, an anomaly arises
when multiple processes share a given socket.  As the priority index and class-id
are updated when a skb is sent at the top of the stack, but interrogated and
used at the bottom of the stack, multiple process living in separate cgroups but
sharing a socket can result in skbs being sent at multiple separate priorities
and classifications.  Aside from the user confusion this may cause, additional
problems can arise if the socket is tcp, and the fluctuation in class or
priority causes network re-ordering that results in serious performance
degradation.

The problem is further compounded by processes that use network resources
unknowingly.  For instance,the CIFS file system creates a network socket to a
cifs server in the context of whatever process is writing to that mount point,
and the same socket will subsequently be used by any other processes writing to
that mount.  This socket sharing will almost certainly lead to classification
and priority changes on a single data stream that will degrade file system
throughput.

This patch series is meant to solve the first of these two problems.  It changes
the way in which the priority and net_cls cgroup implementations migrate the
priority and class-id of the sockets each task owns.  specifically this series:

1) adds an cgroup owner pid field to the sock structure
2) assigns the pid of the creating process at the time of sock allocation
3) zeros the owning pid at the time of sk_common_release (to prevent future pid
aliasing
4) adds a cgroup_attach method to each cgroup subsystem which identifies sockets
owned by that task (based on matching the task pid and the pid provided in (2)
to update the priority and class-id appropriately.

This does not solve the anonymous socket use problem (I plan to address that in
a future patch series), but it does allow for a sockets priority and
classification to be controlled by a single pid for the purposes of cgroup
assignment.

Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
CC: Thomas Graf <tgraf@infradead.org>
CC: "David S. Miller" <davem@davemloft.net>

^ permalink raw reply

* Re: [PATCH] ARM: net: JIT compiler for packet filters
From: Mircea Gherzan @ 2011-12-21 14:36 UTC (permalink / raw)
  To: Nicolas Pitre; +Cc: Rob Herring, netdev, linux-arm-kernel, linux
In-Reply-To: <alpine.LFD.2.02.1112191226160.2907@xanadu.home>

On Mon, Dec 19, 2011 at 12:31:19PM -0500, Nicolas Pitre wrote:
> On Sun, 18 Dec 2011, Rob Herring wrote:
> 
> > On 12/18/2011 05:49 PM, Mircea Gherzan wrote:
> > > +	select HAVE_BPF_JIT if (!THUMB2_KERNEL && AEABI)
> > 
> > No thumb2. That's a shame...
> 
> I think this would be more sensible to make a Thumb2 kernel properly 
> interoperate with this and keep the JIT code simple rather than having 
> to duplicate all this for Thumb2.

The JITed code interoperates properly with a Thumb2 kernel as of v3 of
the patch.

> > BLX is v5+ only. It probably fine to make the JIT v5+ only. There's
> > probably not much v4 h/w that would use this.
> 
> While you might be right, I don't think it is that big a cost to make 
> this support ARMv4 too.  In fact, if slow ARMv4 systems are still 
> routing packets out there, they are likely to see a huge benefit from 
> this.

This has also been addressed in v3.

Mircea

^ permalink raw reply

* [PATCH 4/4] microblaze: Remove NO_IRQ from architecture
From: Michal Simek @ 2011-12-21 14:32 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Ryan Mallon, netdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
In-Reply-To: <1324477932-19262-3-git-send-email-monstr-pSz03upnqPeHXe+LvDLADg@public.gmane.org>

NO_IRQ shouldn't be used by any driver. All Microblaze
drivers are fixed that's why NO_IRQ can be removed.

Signed-off-by: Michal Simek <monstr-pSz03upnqPeHXe+LvDLADg@public.gmane.org>
CC: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
CC: Benjamin Herrenschmidt <benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org>
CC: Ryan Mallon <rmallon-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 arch/microblaze/include/asm/irq.h |    2 --
 arch/microblaze/pci/pci-common.c  |    4 ++--
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/arch/microblaze/include/asm/irq.h b/arch/microblaze/include/asm/irq.h
index b116a82..a175132 100644
--- a/arch/microblaze/include/asm/irq.h
+++ b/arch/microblaze/include/asm/irq.h
@@ -27,8 +27,6 @@ typedef unsigned long irq_hw_number_t;
 
 extern unsigned int nr_irq;
 
-#define NO_IRQ 0
-
 struct pt_regs;
 extern void do_IRQ(struct pt_regs *regs);
 
diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
index db841c7..0d71b2e 100644
--- a/arch/microblaze/pci/pci-common.c
+++ b/arch/microblaze/pci/pci-common.c
@@ -242,7 +242,7 @@ int pci_read_irq_line(struct pci_dev *pci_dev)
 			 line, pin);
 
 		virq = irq_create_mapping(NULL, line);
-		if (virq != NO_IRQ)
+		if (virq)
 			irq_set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
 	} else {
 		pr_debug(" Got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
@@ -253,7 +253,7 @@ int pci_read_irq_line(struct pci_dev *pci_dev)
 		virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
 					     oirq.size);
 	}
-	if (virq == NO_IRQ) {
+	if (!virq) {
 		pr_debug(" Failed to map !\n");
 		return -1;
 	}
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH 3/4] input: xilinx_ps2: Don't use NO_IRQ
From: Michal Simek @ 2011-12-21 14:32 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Ryan Mallon, netdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Rob Herring
In-Reply-To: <1324477932-19262-2-git-send-email-monstr-pSz03upnqPeHXe+LvDLADg@public.gmane.org>

Drivers shouldn't use NO_IRQ. Microblaze and PPC
define NO_IRQ as 0 and this reference will be removed
in near future.

Signed-off-by: Michal Simek <monstr-pSz03upnqPeHXe+LvDLADg@public.gmane.org>
CC: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
CC: Rob Herring <rob.herring-bsGFqQB8/DxBDgjK7y7TUQ@public.gmane.org>
CC: Ryan Mallon <rmallon-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 drivers/input/serio/xilinx_ps2.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c
index d64c5a4..f3e54b9 100644
--- a/drivers/input/serio/xilinx_ps2.c
+++ b/drivers/input/serio/xilinx_ps2.c
@@ -253,7 +253,7 @@ static int __devinit xps2_of_probe(struct platform_device *ofdev)
 	}
 
 	/* Get IRQ for the device */
-	if (of_irq_to_resource(ofdev->dev.of_node, 0, &r_irq) == NO_IRQ) {
+	if (!of_irq_to_resource(ofdev->dev.of_node, 0, &r_irq)) {
 		dev_err(dev, "no IRQ found\n");
 		return -ENODEV;
 	}
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH 2/4] net: ethernet: xilinx: Don't use NO_IRQ in xilinx
From: Michal Simek @ 2011-12-21 14:32 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Stephen Rothwell, Ryan Mallon, netdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, David S. Miller
In-Reply-To: <1324477932-19262-1-git-send-email-monstr-pSz03upnqPeHXe+LvDLADg@public.gmane.org>

Fix ll_temac and emaclite drivers. Only Microblaze and Xilinx PPC
use then and both use NO_IRQ as 0. It will be removed in near future.

Signed-off-by: Michal Simek <monstr-pSz03upnqPeHXe+LvDLADg@public.gmane.org>
CC: "David S. Miller" <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org> (commit_signer:7/10=70%)
CC: Stephen Rothwell <sfr-3FnU+UHB4dNDw9hX6IcOSA@public.gmane.org> (commit_signer:1/10=10%)
CC: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
CC: Ryan Mallon <rmallon-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 drivers/net/ethernet/xilinx/ll_temac_main.c   |    2 +-
 drivers/net/ethernet/xilinx/xilinx_emaclite.c |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c
index 2681b53..87775d7 100644
--- a/drivers/net/ethernet/xilinx/ll_temac_main.c
+++ b/drivers/net/ethernet/xilinx/ll_temac_main.c
@@ -1077,7 +1077,7 @@ static int __devinit temac_of_probe(struct platform_device *op)
 
 	of_node_put(np); /* Finished with the DMA node; drop the reference */
 
-	if ((lp->rx_irq == NO_IRQ) || (lp->tx_irq == NO_IRQ)) {
+	if (!lp->rx_irq || !lp->tx_irq) {
 		dev_err(&op->dev, "could not determine irqs\n");
 		rc = -ENOMEM;
 		goto err_iounmap_2;
diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
index 8018d7d..252edf7 100644
--- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c
+++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
@@ -1129,7 +1129,7 @@ static int __devinit xemaclite_of_probe(struct platform_device *ofdev)
 
 	/* Get IRQ for the device */
 	rc = of_irq_to_resource(ofdev->dev.of_node, 0, &r_irq);
-	if (rc == NO_IRQ) {
+	if (!rc) {
 		dev_err(dev, "no IRQ found\n");
 		return rc;
 	}
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH 1/4] block: xsysace: Don't use NO_IRQ
From: Michal Simek @ 2011-12-21 14:32 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Ryan Mallon, netdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Rob Herring

Drivers shouldn't use NO_IRQ. Microblaze and PPC
define NO_IRQ as 0 and this reference will be removed
in near future.

Signed-off-by: Michal Simek <monstr-pSz03upnqPeHXe+LvDLADg@public.gmane.org>
CC: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
CC: Rob Herring <rob.herring-bsGFqQB8/DxBDgjK7y7TUQ@public.gmane.org>
CC: Ryan Mallon <rmallon-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 drivers/block/xsysace.c |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c
index fb1975d..1a17e33 100644
--- a/drivers/block/xsysace.c
+++ b/drivers/block/xsysace.c
@@ -456,7 +456,7 @@ static inline void ace_fsm_yieldirq(struct ace_device *ace)
 {
 	dev_dbg(ace->dev, "ace_fsm_yieldirq()\n");
 
-	if (ace->irq == NO_IRQ)
+	if (!ace->irq)
 		/* No IRQ assigned, so need to poll */
 		tasklet_schedule(&ace->fsm_tasklet);
 	ace->fsm_continue_flag = 0;
@@ -1034,12 +1034,12 @@ static int __devinit ace_setup(struct ace_device *ace)
 		ACE_CTRL_DATABUFRDYIRQ | ACE_CTRL_ERRORIRQ);
 
 	/* Now we can hook up the irq handler */
-	if (ace->irq != NO_IRQ) {
+	if (ace->irq) {
 		rc = request_irq(ace->irq, ace_interrupt, 0, "systemace", ace);
 		if (rc) {
 			/* Failure - fall back to polled mode */
 			dev_err(ace->dev, "request_irq failed\n");
-			ace->irq = NO_IRQ;
+			ace->irq = 0;
 		}
 	}
 
@@ -1086,7 +1086,7 @@ static void __devexit ace_teardown(struct ace_device *ace)
 
 	tasklet_kill(&ace->fsm_tasklet);
 
-	if (ace->irq != NO_IRQ)
+	if (ace->irq)
 		free_irq(ace->irq, ace);
 
 	iounmap(ace->baseaddr);
@@ -1156,7 +1156,7 @@ static int __devinit ace_probe(struct platform_device *dev)
 	resource_size_t physaddr = 0;
 	int bus_width = ACE_BUS_WIDTH_16; /* FIXME: should not be hard coded */
 	u32 id = dev->id;
-	int irq = NO_IRQ;
+	int irq = 0;
 	int i;
 
 	dev_dbg(&dev->dev, "ace_probe(%p)\n", dev);
-- 
1.7.5.4

^ permalink raw reply related

* Re: ICMP packets - ll_temac with Microblaze
From: Michal Simek @ 2011-12-21 14:24 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: David Miller, John Williams, netdev
In-Reply-To: <1324474811.2728.61.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC>

Eric Dumazet wrote:
> Le mercredi 21 décembre 2011 à 14:28 +0100, Michal Simek a écrit :
> 
>> ok. Can you provide me any background why size should be setup by
>> size = SKB_WITH_OVERHEAD(ksize(data));
>> and not to use size which is passed to kmalloc in __alloc_skb.
> 
> Its all about memory accounting (based on skb->truesize)
> 
> Prior to the patch, we could fool memory accounting because skbs claimed
> to use less memory than what they really used.
> 
> And crash machines eventually.
> 
> Now memory accouting is fixed, we probably need to change some points in
> the kernel, where we previously accepted a small skb, but not a very
> large one.
> 
> Since "ping" probably uses SOCK_RAW sockets, I'll try this one :
> 
> (We dont care of _this_ skb truesize, only on the count of previously
> queued packets)
> 
> 
> diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
> index 0da505c..a809a48 100644
> --- a/net/packet/af_packet.c
> +++ b/net/packet/af_packet.c
> @@ -1631,8 +1631,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev,
>  	if (snaplen > res)
>  		snaplen = res;
>  
> -	if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
> -	    (unsigned)sk->sk_rcvbuf)
> +	if (atomic_read(&sk->sk_rmem_alloc) >= (unsigned)sk->sk_rcvbuf)
>  		goto drop_n_acct;
>  
>  	if (skb_shared(skb)) {
> @@ -1763,7 +1762,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
>  	if (po->tp_version <= TPACKET_V2) {
>  		if (macoff + snaplen > po->rx_ring.frame_size) {
>  			if (po->copy_thresh &&
> -				atomic_read(&sk->sk_rmem_alloc) + skb->truesize
> +				atomic_read(&sk->sk_rmem_alloc)
>  				< (unsigned)sk->sk_rcvbuf) {
>  				if (skb_shared(skb)) {
>  					copy_skb = skb_clone(skb, GFP_ATOMIC);
> 
> 
> 
> 

It doesn't work too.
It is possible to see this behavior on qemu. What about if I prepare you package with cross toolchain, rootfs
and you can add debug message where you want?

I have also tried ll_temac driver with ppc440 and behavior is the same.

Max FRAME_SIZE pass to netdev_alloc_skb_ip_align is 7966. For this value ping works.
(For ll_temac driver it is #define XTE_JUMBO_MTU 7948 from ll_temac.h)

Thanks,
Michal

-- 
Michal Simek, Ing. (M.Eng)
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel 2.6 Microblaze Linux - http://www.monstr.eu/fdt/
Microblaze U-BOOT custodian

^ permalink raw reply

* Re: [PATCH 0/4] skb paged fragment destructors
From: Eric Dumazet @ 2011-12-21 14:02 UTC (permalink / raw)
  To: Ian Campbell
  Cc: David Miller, jesse.brandeburg@intel.com, netdev@vger.kernel.org
In-Reply-To: <1324475280.7877.33.camel@zakaz.uk.xensource.com>

Le mercredi 21 décembre 2011 à 13:48 +0000, Ian Campbell a écrit :
> On Wed, 2011-12-21 at 12:30 +0000, Eric Dumazet wrote:
> > Le mercredi 21 décembre 2011 à 11:18 +0000, Ian Campbell a écrit :
> > 
> > > 
> > > An order 1 allocation is in multiples of PAGE_SIZE, isn't it, even
> > > though they happen to be contiguous?
> > 
> > Really an order-1 allocation allocates one page, a compound one.
> 
> Oh, right, I see what you mean.
> 
> You snipped the question about the + 2, I take it you have no idea what
> it is all about either?
> 

No idea on this +2 point.

I know some hardwares have limits on a fragment length (for example IGB
uses IGB_MAX_DATA_PER_TXD limit), but I dont know why we add extra frags
in generic skb.

^ permalink raw reply

* [net-next 2/2] stmmac: update the driver's documentation (Dec-2011)
From: Giuseppe CAVALLARO @ 2011-12-21 13:58 UTC (permalink / raw)
  To: netdev; +Cc: davem, rayagond, Giuseppe Cavallaro
In-Reply-To: <1324475900-1470-1-git-send-email-peppe.cavallaro@st.com>

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
 Documentation/networking/stmmac.txt |   16 +++++++++-------
 1 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/Documentation/networking/stmmac.txt b/Documentation/networking/stmmac.txt
index 8d67980..d0aeead 100644
--- a/Documentation/networking/stmmac.txt
+++ b/Documentation/networking/stmmac.txt
@@ -4,14 +4,16 @@ Copyright (C) 2007-2010  STMicroelectronics Ltd
 Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
 
 This is the driver for the MAC 10/100/1000 on-chip Ethernet controllers
-(Synopsys IP blocks); it has been fully tested on STLinux platforms.
+(Synopsys IP blocks).
 
 Currently this network device driver is for all STM embedded MAC/GMAC
-(i.e. 7xxx/5xxx SoCs) and it's known working on other platforms i.e. ARM SPEAr.
+(i.e. 7xxx/5xxx SoCs), SPEAr (arm), Loongson1B (mips) and XLINX XC2V3000
+FF1152AMT0221 D1215994A VIRTEX FPGA board.
 
-DWC Ether MAC 10/100/1000 Universal version 3.41a and DWC Ether MAC 10/100
-Universal version 4.0 have been used for developing the first code
-implementation.
+DWC Ether MAC 10/100/1000 Universal version 3.60a (and older) and DWC Ether MAC 10/100
+Universal version 4.0 have been used for developing this driver.
+
+This driver supports both the platform bus and PCI.
 
 Please, for more information also visit: www.stlinux.com
 
@@ -277,5 +279,5 @@ In fact, these can generate an huge amount of debug messages.
 
 6) TODO:
  o XGMAC is not supported.
- o Review the timer optimisation code to use an embedded device that will be
-  available in new chip generations.
+ o Add the EEE - Energy Efficient Ethernet
+ o Add the PTP - precision time protocol
-- 
1.7.4.4

^ permalink raw reply related

* [net-next 1/2] stmmac: add the experimental PCI support
From: Giuseppe CAVALLARO @ 2011-12-21 13:58 UTC (permalink / raw)
  To: netdev; +Cc: davem, rayagond, Giuseppe Cavallaro
In-Reply-To: <1324475900-1470-1-git-send-email-peppe.cavallaro@st.com>

This patch adds the PCI support (as EXPERIMENTAL)
this has been also tested on XLINX XC2V3000 FF1152AMT0221
D1215994A VIRTEX FPGA board.
To support the PCI bus the main part has been reworked
and both the platform and the PCI specific parts have
been moved into different files.

Signed-off-by: Rayagond Kokatanur <rayagond@vayavyalabs.com>
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
 drivers/net/ethernet/stmicro/stmmac/Kconfig        |   27 ++-
 drivers/net/ethernet/stmicro/stmmac/Makefile       |    2 +
 drivers/net/ethernet/stmicro/stmmac/common.h       |    7 +
 drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c    |   13 +
 drivers/net/ethernet/stmicro/stmmac/stmmac.h       |   13 +-
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  |  418 ++++++--------------
 drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c  |    3 +-
 drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c   |  221 +++++++++++
 .../net/ethernet/stmicro/stmmac/stmmac_platform.c  |  198 +++++++++
 9 files changed, 612 insertions(+), 290 deletions(-)
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c

diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index 22745d7..0364283 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -12,11 +12,36 @@ config STMMAC_ETH
 
 if STMMAC_ETH
 
+config STMMAC_PLATFORM
+	tristate "STMMAC platform bus support"
+	depends on STMMAC_ETH
+	default y
+	---help---
+	  This selects the platform specific bus support for
+	  the stmmac device driver. This is the driver used
+	  on many embedded STM platforms based on ARM and SuperH
+	  processors.
+	  If you have a controller with this interface, say Y or M here.
+
+	  If unsure, say N.
+
+config STMMAC_PCI
+	tristate "STMMAC support on PCI bus (EXPERIMENTAL)"
+	depends on STMMAC_ETH && PCI && EXPERIMENTAL
+	---help---
+	  This is to select the Synopsys DWMAC available on PCI devices,
+	  if you have a controller with this interface, say Y or M here.
+
+	  This PCI support is tested on XLINX XC2V3000 FF1152AMT0221
+	  D1215994A VIRTEX FPGA board.
+
+	  If unsure, say N.
+
 config STMMAC_DEBUG_FS
 	bool "Enable monitoring via sysFS "
 	default n
 	depends on STMMAC_ETH && DEBUG_FS
-	-- help
+	---help---
 	  The stmmac entry in /sys reports DMA TX/RX rings
 	  or (if supported) the HW cap register.
 
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index d7c4516..bc965ac 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -2,6 +2,8 @@ obj-$(CONFIG_STMMAC_ETH) += stmmac.o
 stmmac-$(CONFIG_STMMAC_TIMER) += stmmac_timer.o
 stmmac-$(CONFIG_STMMAC_RING) += ring_mode.o
 stmmac-$(CONFIG_STMMAC_CHAINED) += chain_mode.o
+stmmac-$(CONFIG_STMMAC_PLATFORM) += stmmac_platform.o
+stmmac-$(CONFIG_STMMAC_PCI) += stmmac_pci.o
 stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o	\
 	      dwmac_lib.o dwmac1000_core.o  dwmac1000_dma.o	\
 	      dwmac100_core.o dwmac100_dma.o enh_desc.o  norm_desc.o \
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 2cc1192..d0b814e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -22,7 +22,11 @@
   Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
 *******************************************************************************/
 
+#include <linux/etherdevice.h>
 #include <linux/netdevice.h>
+#include <linux/phy.h>
+#include <linux/module.h>
+#include <linux/init.h>
 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
 #define STMMAC_VLAN_TAG_USED
 #include <linux/if_vlan.h>
@@ -315,5 +319,8 @@ extern void stmmac_set_mac_addr(void __iomem *ioaddr, u8 addr[6],
 				unsigned int high, unsigned int low);
 extern void stmmac_get_mac_addr(void __iomem *ioaddr, unsigned char *addr,
 				unsigned int high, unsigned int low);
+
+extern void stmmac_set_mac(void __iomem *ioaddr, bool enable);
+
 extern void dwmac_dma_flush_tx_fifo(void __iomem *ioaddr);
 extern const struct stmmac_ring_mode_ops ring_mode_ops;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
index e250935..f20aa12 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
@@ -238,6 +238,19 @@ void stmmac_set_mac_addr(void __iomem *ioaddr, u8 addr[6],
 	writel(data, ioaddr + low);
 }
 
+/* Enable disable MAC RX/TX */
+void stmmac_set_mac(void __iomem *ioaddr, bool enable)
+{
+	u32 value = readl(ioaddr + MAC_CTRL_REG);
+
+	if (enable)
+		value |= MAC_RNABLE_RX | MAC_ENABLE_TX;
+	else
+		value &= ~(MAC_ENABLE_TX | MAC_RNABLE_RX);
+
+	writel(value, ioaddr + MAC_CTRL_REG);
+}
+
 void stmmac_get_mac_addr(void __iomem *ioaddr, unsigned char *addr,
 			 unsigned int high, unsigned int low)
 {
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index a140a8f..1207400 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -20,7 +20,8 @@
   Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
 *******************************************************************************/
 
-#define DRV_MODULE_VERSION	"Oct_2011"
+#define STMMAC_RESOURCE_NAME   "stmmaceth"
+#define DRV_MODULE_VERSION	"Dec_2011"
 #include <linux/stmmac.h>
 #include <linux/phy.h>
 #include "common.h"
@@ -82,8 +83,18 @@ struct stmmac_priv {
 	int hw_cap_support;
 };
 
+extern int phyaddr;
+
 extern int stmmac_mdio_unregister(struct net_device *ndev);
 extern int stmmac_mdio_register(struct net_device *ndev);
 extern void stmmac_set_ethtool_ops(struct net_device *netdev);
 extern const struct stmmac_desc_ops enh_desc_ops;
 extern const struct stmmac_desc_ops ndesc_ops;
+
+int stmmac_freeze(struct net_device *ndev);
+int stmmac_restore(struct net_device *ndev);
+int stmmac_resume(struct net_device *ndev);
+int stmmac_suspend(struct net_device *ndev);
+int stmmac_dvr_remove(struct net_device *ndev);
+struct stmmac_priv *stmmac_dvr_probe(struct device *device,
+				struct plat_stmmacenet_data *plat_dat);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 24c2bf6..b314592 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -28,12 +28,8 @@
 	https://bugzilla.stlinux.com/
 *******************************************************************************/
 
-#include <linux/module.h>
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
-#include <linux/etherdevice.h>
-#include <linux/platform_device.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>
 #include <linux/skbuff.h>
@@ -52,8 +48,6 @@
 #endif
 #include "stmmac.h"
 
-#define STMMAC_RESOURCE_NAME	"stmmaceth"
-
 #undef STMMAC_DEBUG
 /*#define STMMAC_DEBUG*/
 #ifdef STMMAC_DEBUG
@@ -93,7 +87,7 @@ static int debug = -1;		/* -1: default, 0: no output, 16:  all */
 module_param(debug, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Message Level (0: no output, 16: all)");
 
-static int phyaddr = -1;
+int phyaddr = -1;
 module_param(phyaddr, int, S_IRUGO);
 MODULE_PARM_DESC(phyaddr, "Physical device address");
 
@@ -141,6 +135,11 @@ static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE |
 
 static irqreturn_t stmmac_interrupt(int irq, void *dev_id);
 
+#ifdef CONFIG_STMMAC_DEBUG_FS
+static int stmmac_init_fs(struct net_device *dev);
+static void stmmac_exit_fs(void);
+#endif
+
 /**
  * stmmac_verify_args - verify the driver parameters.
  * Description: it verifies if some wrong parameter is passed to the driver.
@@ -345,22 +344,6 @@ static int stmmac_init_phy(struct net_device *dev)
 	return 0;
 }
 
-static inline void stmmac_enable_mac(void __iomem *ioaddr)
-{
-	u32 value = readl(ioaddr + MAC_CTRL_REG);
-
-	value |= MAC_RNABLE_RX | MAC_ENABLE_TX;
-	writel(value, ioaddr + MAC_CTRL_REG);
-}
-
-static inline void stmmac_disable_mac(void __iomem *ioaddr)
-{
-	u32 value = readl(ioaddr + MAC_CTRL_REG);
-
-	value &= ~(MAC_ENABLE_TX | MAC_RNABLE_RX);
-	writel(value, ioaddr + MAC_CTRL_REG);
-}
-
 /**
  * display_ring
  * @p: pointer to the ring.
@@ -887,6 +870,53 @@ static int stmmac_get_hw_features(struct stmmac_priv *priv)
 }
 
 /**
+ * stmmac_mac_device_setup
+ * @dev : device pointer
+ * Description: this is to attach the GMAC or MAC 10/100
+ * main core structures that will be completed during the
+ * open step.
+ */
+static int stmmac_mac_device_setup(struct net_device *dev)
+{
+	struct stmmac_priv *priv = netdev_priv(dev);
+
+	struct mac_device_info *device;
+
+	if (priv->plat->has_gmac)
+		device = dwmac1000_setup(priv->ioaddr);
+	else
+		device = dwmac100_setup(priv->ioaddr);
+
+	if (!device)
+		return -ENOMEM;
+
+	priv->hw = device;
+	priv->hw->ring = &ring_mode_ops;
+
+	if (device_can_wakeup(priv->device)) {
+		priv->wolopts = WAKE_MAGIC; /* Magic Frame as default */
+		enable_irq_wake(priv->wol_irq);
+	}
+
+	return 0;
+}
+
+static void stmmac_check_ether_addr(struct stmmac_priv *priv)
+{
+	/* verify if the MAC address is valid, in case of failures it
+	 * generates a random MAC address */
+	if (!is_valid_ether_addr(priv->dev->dev_addr)) {
+		priv->hw->mac->get_umac_addr((void __iomem *)
+					     priv->dev->base_addr,
+					     priv->dev->dev_addr, 0);
+		if  (!is_valid_ether_addr(priv->dev->dev_addr))
+			random_ether_addr(priv->dev->dev_addr);
+	}
+	pr_warning("%s: device MAC address %pM\n", priv->dev->name,
+						   priv->dev->dev_addr);
+}
+
+/**
  *  stmmac_open - open entry point of the driver
  *  @dev : pointer to the device structure.
  *  Description:
@@ -900,18 +930,28 @@ static int stmmac_open(struct net_device *dev)
 	struct stmmac_priv *priv = netdev_priv(dev);
 	int ret;
 
-	/* Check that the MAC address is valid.  If its not, refuse
-	 * to bring the device up. The user must specify an
-	 * address using the following linux command:
-	 *      ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx  */
-	if (!is_valid_ether_addr(dev->dev_addr)) {
-		random_ether_addr(dev->dev_addr);
-		pr_warning("%s: generated random MAC address %pM\n", dev->name,
-			dev->dev_addr);
-	}
+	/* MAC HW device setup */
+	ret = stmmac_mac_device_setup(dev);
+	if (ret < 0)
+		return ret;
+
+	stmmac_check_ether_addr(priv);
 
 	stmmac_verify_args();
 
+	/* Override with kernel parameters if supplied XXX CRS XXX
+	 * this needs to have multiple instances */
+	if ((phyaddr >= 0) && (phyaddr <= 31))
+		priv->plat->phy_addr = phyaddr;
+
+	/* MDIO bus Registration */
+	ret = stmmac_mdio_register(dev);
+	if (ret < 0) {
+		pr_debug("%s: MDIO bus (id: %d) registration failed",
+			 __func__, priv->plat->bus_id);
+		return ret;
+	}
+
 #ifdef CONFIG_STMMAC_TIMER
 	priv->tm = kzalloc(sizeof(struct stmmac_timer *), GFP_KERNEL);
 	if (unlikely(priv->tm == NULL)) {
@@ -1008,7 +1048,7 @@ static int stmmac_open(struct net_device *dev)
 	}
 
 	/* Enable the MAC Rx/Tx */
-	stmmac_enable_mac(priv->ioaddr);
+	stmmac_set_mac(priv->ioaddr, true);
 
 	/* Set the HW DMA mode and the COE */
 	stmmac_dma_operation_mode(priv);
@@ -1019,6 +1059,11 @@ static int stmmac_open(struct net_device *dev)
 
 	stmmac_mmc_setup(priv);
 
+#ifdef CONFIG_STMMAC_DEBUG_FS
+	ret = stmmac_init_fs(dev);
+	if (ret < 0)
+		pr_warning("\tFailed debugFS registration");
+#endif
 	/* Start the ball rolling... */
 	DBG(probe, DEBUG, "%s: DMA RX/TX processes started...\n", dev->name);
 	priv->hw->dma->start_tx(priv->ioaddr);
@@ -1091,10 +1136,15 @@ static int stmmac_release(struct net_device *dev)
 	free_dma_desc_resources(priv);
 
 	/* Disable the MAC Rx/Tx */
-	stmmac_disable_mac(priv->ioaddr);
+	stmmac_set_mac(priv->ioaddr, false);
 
 	netif_carrier_off(dev);
 
+#ifdef CONFIG_STMMAC_DEBUG_FS
+	stmmac_exit_fs();
+#endif
+	stmmac_mdio_unregister(dev);
+
 	return 0;
 }
 
@@ -1739,28 +1789,41 @@ static const struct net_device_ops stmmac_netdev_ops = {
 };
 
 /**
- * stmmac_probe - Initialization of the adapter .
- * @dev : device pointer
- * Description: The function initializes the network device structure for
- * the STMMAC driver. It also calls the low level routines
- * in order to init the HW (i.e. the DMA engine)
+ * stmmac_dvr_probe
+ * @device: device pointer
+ * Description: this is the main probe function used to
+ * call the alloc_etherdev, allocate the priv structure.
  */
-static int stmmac_probe(struct net_device *dev)
+struct stmmac_priv *stmmac_dvr_probe(struct device *device,
+					struct plat_stmmacenet_data *plat_dat)
 {
 	int ret = 0;
-	struct stmmac_priv *priv = netdev_priv(dev);
+	struct net_device *ndev = NULL;
+	struct stmmac_priv *priv;
 
-	ether_setup(dev);
+	ndev = alloc_etherdev(sizeof(struct stmmac_priv));
+	if (!ndev) {
+		pr_err("%s: ERROR: allocating the device\n", __func__);
+		return NULL;
+	}
+
+	SET_NETDEV_DEV(ndev, device);
+
+	priv = netdev_priv(ndev);
+	priv->device = device;
+	priv->dev = ndev;
 
-	dev->netdev_ops = &stmmac_netdev_ops;
-	stmmac_set_ethtool_ops(dev);
+	ether_setup(ndev);
 
-	dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
-	dev->features |= dev->hw_features | NETIF_F_HIGHDMA;
-	dev->watchdog_timeo = msecs_to_jiffies(watchdog);
+	ndev->netdev_ops = &stmmac_netdev_ops;
+	stmmac_set_ethtool_ops(ndev);
+
+	ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+	ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA;
+	ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
 #ifdef STMMAC_VLAN_TAG_USED
 	/* Both mac100 and gmac support receive VLAN tag detection */
-	dev->features |= NETIF_F_HW_VLAN_RX;
+	ndev->features |= NETIF_F_HW_VLAN_RX;
 #endif
 	priv->msg_enable = netif_msg_init(debug, default_msg_level);
 
@@ -1768,248 +1831,60 @@ static int stmmac_probe(struct net_device *dev)
 		priv->flow_ctrl = FLOW_AUTO;	/* RX/TX pause on */
 
 	priv->pause = pause;
-	netif_napi_add(dev, &priv->napi, stmmac_poll, 64);
-
-	/* Get the MAC address */
-	priv->hw->mac->get_umac_addr((void __iomem *) dev->base_addr,
-				     dev->dev_addr, 0);
-
-	if (!is_valid_ether_addr(dev->dev_addr))
-		pr_warning("\tno valid MAC address;"
-			"please, use ifconfig or nwhwconfig!\n");
+	priv->plat = plat_dat;
+	netif_napi_add(ndev, &priv->napi, stmmac_poll, 64);
 
 	spin_lock_init(&priv->lock);
 	spin_lock_init(&priv->tx_lock);
 
-	ret = register_netdev(dev);
+	ret = register_netdev(ndev);
 	if (ret) {
 		pr_err("%s: ERROR %i registering the device\n",
 		       __func__, ret);
-		return -ENODEV;
+		goto error;
 	}
 
 	DBG(probe, DEBUG, "%s: Scatter/Gather: %s - HW checksums: %s\n",
-	    dev->name, (dev->features & NETIF_F_SG) ? "on" : "off",
-	    (dev->features & NETIF_F_IP_CSUM) ? "on" : "off");
+	    ndev->name, (ndev->features & NETIF_F_SG) ? "on" : "off",
+	    (ndev->features & NETIF_F_IP_CSUM) ? "on" : "off");
 
-	return ret;
-}
+	return priv;
 
-/**
- * stmmac_mac_device_setup
- * @dev : device pointer
- * Description: select and initialise the mac device (mac100 or Gmac).
- */
-static int stmmac_mac_device_setup(struct net_device *dev)
-{
-	struct stmmac_priv *priv = netdev_priv(dev);
+error:
+	netif_napi_del(&priv->napi);
 
-	struct mac_device_info *device;
-
-	if (priv->plat->has_gmac) {
-		dev->priv_flags |= IFF_UNICAST_FLT;
-		device = dwmac1000_setup(priv->ioaddr);
-	} else {
-		device = dwmac100_setup(priv->ioaddr);
-	}
-
-	if (!device)
-		return -ENOMEM;
-
-	priv->hw = device;
-	priv->hw->ring = &ring_mode_ops;
-
-	if (device_can_wakeup(priv->device)) {
-		priv->wolopts = WAKE_MAGIC; /* Magic Frame as default */
-		enable_irq_wake(priv->wol_irq);
-	}
-
-	return 0;
-}
-
-/**
- * stmmac_dvr_probe
- * @pdev: platform device pointer
- * Description: the driver is initialized through platform_device.
- */
-static int stmmac_dvr_probe(struct platform_device *pdev)
-{
-	int ret = 0;
-	struct resource *res;
-	void __iomem *addr = NULL;
-	struct net_device *ndev = NULL;
-	struct stmmac_priv *priv = NULL;
-	struct plat_stmmacenet_data *plat_dat;
-
-	pr_info("STMMAC driver:\n\tplatform registration... ");
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -ENODEV;
-	pr_info("\tdone!\n");
-
-	if (!request_mem_region(res->start, resource_size(res),
-				pdev->name)) {
-		pr_err("%s: ERROR: memory allocation failed"
-		       "cannot get the I/O addr 0x%x\n",
-		       __func__, (unsigned int)res->start);
-		return -EBUSY;
-	}
-
-	addr = ioremap(res->start, resource_size(res));
-	if (!addr) {
-		pr_err("%s: ERROR: memory mapping failed\n", __func__);
-		ret = -ENOMEM;
-		goto out_release_region;
-	}
-
-	ndev = alloc_etherdev(sizeof(struct stmmac_priv));
-	if (!ndev) {
-		pr_err("%s: ERROR: allocating the device\n", __func__);
-		ret = -ENOMEM;
-		goto out_unmap;
-	}
-
-	SET_NETDEV_DEV(ndev, &pdev->dev);
-
-	/* Get the MAC information */
-	ndev->irq = platform_get_irq_byname(pdev, "macirq");
-	if (ndev->irq == -ENXIO) {
-		pr_err("%s: ERROR: MAC IRQ configuration "
-		       "information not found\n", __func__);
-		ret = -ENXIO;
-		goto out_free_ndev;
-	}
-
-	priv = netdev_priv(ndev);
-	priv->device = &(pdev->dev);
-	priv->dev = ndev;
-	plat_dat = pdev->dev.platform_data;
-
-	priv->plat = plat_dat;
-
-	priv->ioaddr = addr;
-
-	/*
-	 * On some platforms e.g. SPEAr the wake up irq differs from the mac irq
-	 * The external wake up irq can be passed through the platform code
-	 * named as "eth_wake_irq"
-	 *
-	 * In case the wake up interrupt is not passed from the platform
-	 * so the driver will continue to use the mac irq (ndev->irq)
-	 */
-	priv->wol_irq = platform_get_irq_byname(pdev, "eth_wake_irq");
-	if (priv->wol_irq == -ENXIO)
-		priv->wol_irq = ndev->irq;
-
-	platform_set_drvdata(pdev, ndev);
-
-	/* Set the I/O base addr */
-	ndev->base_addr = (unsigned long)addr;
-
-	/* Custom initialisation */
-	if (priv->plat->init) {
-		ret = priv->plat->init(pdev);
-		if (unlikely(ret))
-			goto out_free_ndev;
-	}
-
-	/* MAC HW device detection */
-	ret = stmmac_mac_device_setup(ndev);
-	if (ret < 0)
-		goto out_plat_exit;
-
-	/* Network Device Registration */
-	ret = stmmac_probe(ndev);
-	if (ret < 0)
-		goto out_plat_exit;
-
-	/* Override with kernel parameters if supplied XXX CRS XXX
-	 * this needs to have multiple instances */
-	if ((phyaddr >= 0) && (phyaddr <= 31))
-		priv->plat->phy_addr = phyaddr;
-
-	pr_info("\t%s - (dev. name: %s - id: %d, IRQ #%d\n"
-	       "\tIO base addr: 0x%p)\n", ndev->name, pdev->name,
-	       pdev->id, ndev->irq, addr);
-
-	/* MDIO bus Registration */
-	pr_debug("\tMDIO bus (id: %d)...", priv->plat->bus_id);
-	ret = stmmac_mdio_register(ndev);
-	if (ret < 0)
-		goto out_unregister;
-	pr_debug("registered!\n");
-
-#ifdef CONFIG_STMMAC_DEBUG_FS
-	ret = stmmac_init_fs(ndev);
-	if (ret < 0)
-		pr_warning("\tFailed debugFS registration");
-#endif
-
-	return 0;
-
-out_unregister:
 	unregister_netdev(ndev);
-out_plat_exit:
-	if (priv->plat->exit)
-		priv->plat->exit(pdev);
-out_free_ndev:
 	free_netdev(ndev);
-	platform_set_drvdata(pdev, NULL);
-out_unmap:
-	iounmap(addr);
-out_release_region:
-	release_mem_region(res->start, resource_size(res));
 
-	return ret;
+	return NULL;
 }
 
 /**
  * stmmac_dvr_remove
- * @pdev: platform device pointer
+ * @ndev: net device pointer
  * Description: this function resets the TX/RX processes, disables the MAC RX/TX
- * changes the link status, releases the DMA descriptor rings,
- * unregisters the MDIO bus and unmaps the allocated memory.
+ * changes the link status, releases the DMA descriptor rings.
  */
-static int stmmac_dvr_remove(struct platform_device *pdev)
+int stmmac_dvr_remove(struct net_device *ndev)
 {
-	struct net_device *ndev = platform_get_drvdata(pdev);
 	struct stmmac_priv *priv = netdev_priv(ndev);
-	struct resource *res;
 
 	pr_info("%s:\n\tremoving driver", __func__);
 
 	priv->hw->dma->stop_rx(priv->ioaddr);
 	priv->hw->dma->stop_tx(priv->ioaddr);
 
-	stmmac_disable_mac(priv->ioaddr);
-
+	stmmac_set_mac(priv->ioaddr, false);
 	netif_carrier_off(ndev);
-
-	stmmac_mdio_unregister(ndev);
-
-	if (priv->plat->exit)
-		priv->plat->exit(pdev);
-
-	platform_set_drvdata(pdev, NULL);
 	unregister_netdev(ndev);
-
-	iounmap((void *)priv->ioaddr);
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(res->start, resource_size(res));
-
-#ifdef CONFIG_STMMAC_DEBUG_FS
-	stmmac_exit_fs();
-#endif
-
 	free_netdev(ndev);
 
 	return 0;
 }
 
 #ifdef CONFIG_PM
-static int stmmac_suspend(struct device *dev)
+int stmmac_suspend(struct net_device *ndev)
 {
-	struct net_device *ndev = dev_get_drvdata(dev);
 	struct stmmac_priv *priv = netdev_priv(ndev);
 	int dis_ic = 0;
 
@@ -2043,15 +1918,14 @@ static int stmmac_suspend(struct device *dev)
 	if (device_may_wakeup(priv->device))
 		priv->hw->mac->pmt(priv->ioaddr, priv->wolopts);
 	else
-		stmmac_disable_mac(priv->ioaddr);
+		stmmac_set_mac(priv->ioaddr, false);
 
 	spin_unlock(&priv->lock);
 	return 0;
 }
 
-static int stmmac_resume(struct device *dev)
+int stmmac_resume(struct net_device *ndev)
 {
-	struct net_device *ndev = dev_get_drvdata(dev);
 	struct stmmac_priv *priv = netdev_priv(ndev);
 
 	if (!netif_running(ndev))
@@ -2070,7 +1944,7 @@ static int stmmac_resume(struct device *dev)
 	netif_device_attach(ndev);
 
 	/* Enable the MAC and DMA */
-	stmmac_enable_mac(priv->ioaddr);
+	stmmac_set_mac(priv->ioaddr, true);
 	priv->hw->dma->start_tx(priv->ioaddr);
 	priv->hw->dma->start_rx(priv->ioaddr);
 
@@ -2090,47 +1964,23 @@ static int stmmac_resume(struct device *dev)
 	return 0;
 }
 
-static int stmmac_freeze(struct device *dev)
+int stmmac_freeze(struct net_device *ndev)
 {
-	struct net_device *ndev = dev_get_drvdata(dev);
-
 	if (!ndev || !netif_running(ndev))
 		return 0;
 
 	return stmmac_release(ndev);
 }
 
-static int stmmac_restore(struct device *dev)
+int stmmac_restore(struct net_device *ndev)
 {
-	struct net_device *ndev = dev_get_drvdata(dev);
-
 	if (!ndev || !netif_running(ndev))
 		return 0;
 
 	return stmmac_open(ndev);
 }
-
-static const struct dev_pm_ops stmmac_pm_ops = {
-	.suspend = stmmac_suspend,
-	.resume = stmmac_resume,
-	.freeze = stmmac_freeze,
-	.thaw = stmmac_restore,
-	.restore = stmmac_restore,
-};
-#else
-static const struct dev_pm_ops stmmac_pm_ops;
 #endif /* CONFIG_PM */
 
-static struct platform_driver stmmac_driver = {
-	.probe = stmmac_dvr_probe,
-	.remove = stmmac_dvr_remove,
-	.driver = {
-		.name = STMMAC_RESOURCE_NAME,
-		.owner = THIS_MODULE,
-		.pm = &stmmac_pm_ops,
-	},
-};
-
 #ifndef MODULE
 static int __init stmmac_cmdline_opt(char *str)
 {
@@ -2189,9 +2039,3 @@ err:
 
 __setup("stmmaceth=", stmmac_cmdline_opt);
 #endif
-
-module_platform_driver(stmmac_driver);
-
-MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet driver");
-MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
index 9c3b9d5..51f4412 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
@@ -109,6 +109,7 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
  */
 static int stmmac_mdio_reset(struct mii_bus *bus)
 {
+#if defined(CONFIG_STMMAC_PLATFORM)
 	struct net_device *ndev = bus->priv;
 	struct stmmac_priv *priv = netdev_priv(ndev);
 	unsigned int mii_address = priv->hw->mii.addr;
@@ -123,7 +124,7 @@ static int stmmac_mdio_reset(struct mii_bus *bus)
 	 * on MDC, so perform a dummy mdio read.
 	 */
 	writel(0, priv->ioaddr + mii_address);
-
+#endif
 	return 0;
 }
 
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
new file mode 100644
index 0000000..54a819a
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
@@ -0,0 +1,221 @@
+/*******************************************************************************
+  This contains the functions to handle the pci driver.
+
+  Copyright (C) 2011-2012  Vayavya Labs Pvt Ltd
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms and conditions of the GNU General Public License,
+  version 2, as published by the Free Software Foundation.
+
+  This program is distributed in the hope it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+  more details.
+
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+  The full GNU General Public License is included in this distribution in
+  the file called "COPYING".
+
+  Author: Rayagond Kokatanur <rayagond@vayavyalabs.com>
+  Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+*******************************************************************************/
+
+#include <linux/pci.h>
+#include "stmmac.h"
+
+struct plat_stmmacenet_data plat_dat;
+struct stmmac_mdio_bus_data mdio_data;
+
+static void stmmac_default_data(void)
+{
+	memset(&plat_dat, 0, sizeof(struct plat_stmmacenet_data));
+	plat_dat.bus_id = 1;
+	plat_dat.phy_addr = 0;
+	plat_dat.interface = PHY_INTERFACE_MODE_GMII;
+	plat_dat.pbl = 32;
+	plat_dat.clk_csr = 2;	/* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
+	plat_dat.has_gmac = 1;
+	plat_dat.force_sf_dma_mode = 1;
+
+	mdio_data.bus_id = 1;
+	mdio_data.phy_reset = NULL;
+	mdio_data.phy_mask = 0;
+	plat_dat.mdio_bus_data = &mdio_data;
+}
+
+/**
+ * stmmac_pci_probe
+ *
+ * @pdev: pci device pointer
+ * @id: pointer to table of device id/id's.
+ *
+ * Description: This probing function gets called for all PCI devices which
+ * match the ID table and are not "owned" by other driver yet. This function
+ * gets passed a "struct pci_dev *" for each device whose entry in the ID table
+ * matches the device. The probe functions returns zero when the driver choose
+ * to take "ownership" of the device or an error code(-ve no) otherwise.
+ */
+static int __devinit stmmac_pci_probe(struct pci_dev *pdev,
+				      const struct pci_device_id *id)
+{
+	int ret = 0;
+	void __iomem *addr = NULL;
+	struct stmmac_priv *priv = NULL;
+	int i;
+
+	/* Enable pci device */
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		pr_err("%s : ERROR: failed to enable %s device\n", __func__,
+		       pci_name(pdev));
+		return ret;
+	}
+	if (pci_request_regions(pdev, STMMAC_RESOURCE_NAME)) {
+		pr_err("%s: ERROR: failed to get PCI region\n", __func__);
+		ret = -ENODEV;
+		goto err_out_req_reg_failed;
+	}
+
+	/* Get the base address of device */
+	for (i = 0; i <= 5; i++) {
+		if (pci_resource_len(pdev, i) == 0)
+			continue;
+		addr = pci_iomap(pdev, i, 0);
+		if (addr == NULL) {
+			pr_err("%s: ERROR: cannot map regiser memory, aborting",
+			       __func__);
+			ret = -EIO;
+			goto err_out_map_failed;
+		}
+		break;
+	}
+	pci_set_master(pdev);
+
+	stmmac_default_data();
+
+	priv = stmmac_dvr_probe(&(pdev->dev), &plat_dat);
+	if (!priv) {
+		pr_err("%s: main drivr probe failed", __func__);
+		goto err_out;
+	}
+	priv->ioaddr = addr;
+	priv->dev->base_addr = (unsigned long)addr;
+	priv->dev->irq = pdev->irq;
+	priv->wol_irq = pdev->irq;
+
+	pci_set_drvdata(pdev, priv->dev);
+
+	pr_debug("STMMAC platform driver registration completed");
+
+	return 0;
+
+err_out:
+	pci_clear_master(pdev);
+err_out_map_failed:
+	pci_release_regions(pdev);
+err_out_req_reg_failed:
+	pci_disable_device(pdev);
+
+	return ret;
+}
+
+/**
+ * stmmac_dvr_remove
+ *
+ * @pdev: platform device pointer
+ * Description: this function calls the main to free the net resources
+ * and releases the PCI resources.
+ */
+static void __devexit stmmac_pci_remove(struct pci_dev *pdev)
+{
+	struct net_device *ndev = pci_get_drvdata(pdev);
+	struct stmmac_priv *priv = netdev_priv(ndev);
+
+	stmmac_dvr_remove(ndev);
+
+	pci_set_drvdata(pdev, NULL);
+	pci_iounmap(pdev, priv->ioaddr);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+}
+
+#ifdef CONFIG_PM
+static int stmmac_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct net_device *ndev = pci_get_drvdata(pdev);
+	int ret;
+
+	ret = stmmac_suspend(ndev);
+	pci_save_state(pdev);
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+	return ret;
+}
+
+static int stmmac_pci_resume(struct pci_dev *pdev)
+{
+	struct net_device *ndev = pci_get_drvdata(pdev);
+
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+
+	return stmmac_resume(ndev);
+}
+#endif
+
+#define STMMAC_VENDOR_ID 0x700
+#define STMMAC_DEVICE_ID 0x1108
+
+static DEFINE_PCI_DEVICE_TABLE(stmmac_id_table) = {
+	{
+	PCI_DEVICE(STMMAC_VENDOR_ID, STMMAC_DEVICE_ID)}, {
+	}
+};
+
+MODULE_DEVICE_TABLE(pci, stmmac_id_table);
+
+static struct pci_driver stmmac_driver = {
+	.name = STMMAC_RESOURCE_NAME,
+	.id_table = stmmac_id_table,
+	.probe = stmmac_pci_probe,
+	.remove = __devexit_p(stmmac_pci_remove),
+#ifdef CONFIG_PM
+	.suspend = stmmac_pci_suspend,
+	.resume = stmmac_pci_resume,
+#endif
+};
+
+/**
+ * stmmac_init_module - Entry point for the driver
+ * Description: This function is the entry point for the driver.
+ */
+static int __init stmmac_init_module(void)
+{
+	int ret;
+
+	ret = pci_register_driver(&stmmac_driver);
+	if (ret < 0)
+		pr_err("%s: ERROR: driver registration failed\n", __func__);
+
+	return ret;
+}
+
+/**
+ * stmmac_cleanup_module - Cleanup routine for the driver
+ * Description: This function is the cleanup routine for the driver.
+ */
+static void __exit stmmac_cleanup_module(void)
+{
+	pci_unregister_driver(&stmmac_driver);
+}
+
+module_init(stmmac_init_module);
+module_exit(stmmac_cleanup_module);
+
+MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet PCI driver");
+MODULE_AUTHOR("Rayagond Kokatanur <rayagond.kokatanur@vayavyalabs.com>");
+MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
new file mode 100644
index 0000000..7b1594f
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -0,0 +1,198 @@
+/*******************************************************************************
+  This contains the functions to handle the platform driver.
+
+  Copyright (C) 2007-2011  STMicroelectronics Ltd
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms and conditions of the GNU General Public License,
+  version 2, as published by the Free Software Foundation.
+
+  This program is distributed in the hope it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+  more details.
+
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+  The full GNU General Public License is included in this distribution in
+  the file called "COPYING".
+
+  Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+*******************************************************************************/
+
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include "stmmac.h"
+
+/**
+ * stmmac_pltfr_probe
+ * @pdev: platform device pointer
+ * Description: platform_device probe function. It allocates
+ * the necessary resources and invokes the main to init
+ * the net device, register the mdio bus etc.
+ */
+static int stmmac_pltfr_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct resource *res;
+	void __iomem *addr = NULL;
+	struct stmmac_priv *priv = NULL;
+	struct plat_stmmacenet_data *plat_dat;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
+		pr_err("%s: ERROR: memory allocation failed"
+		       "cannot get the I/O addr 0x%x\n",
+		       __func__, (unsigned int)res->start);
+		return -EBUSY;
+	}
+
+	addr = ioremap(res->start, resource_size(res));
+	if (!addr) {
+		pr_err("%s: ERROR: memory mapping failed", __func__);
+		ret = -ENOMEM;
+		goto out_release_region;
+	}
+	plat_dat = pdev->dev.platform_data;
+	priv = stmmac_dvr_probe(&(pdev->dev), plat_dat);
+	if (!priv) {
+		pr_err("%s: main drivr probe failed", __func__);
+		goto out_release_region;
+	}
+
+	priv->ioaddr = addr;
+	/* Set the I/O base addr */
+	priv->dev->base_addr = (unsigned long)addr;
+
+	/* Get the MAC information */
+	priv->dev->irq = platform_get_irq_byname(pdev, "macirq");
+	if (priv->dev->irq == -ENXIO) {
+		pr_err("%s: ERROR: MAC IRQ configuration "
+		       "information not found\n", __func__);
+		ret = -ENXIO;
+		goto out_unmap;
+	}
+
+	/*
+	 * On some platforms e.g. SPEAr the wake up irq differs from the mac irq
+	 * The external wake up irq can be passed through the platform code
+	 * named as "eth_wake_irq"
+	 *
+	 * In case the wake up interrupt is not passed from the platform
+	 * so the driver will continue to use the mac irq (ndev->irq)
+	 */
+	priv->wol_irq = platform_get_irq_byname(pdev, "eth_wake_irq");
+	if (priv->wol_irq == -ENXIO)
+		priv->wol_irq = priv->dev->irq;
+
+	platform_set_drvdata(pdev, priv->dev);
+
+	/* Custom initialisation */
+	if (priv->plat->init) {
+		ret = priv->plat->init(pdev);
+		if (unlikely(ret))
+			goto out_unmap;
+	}
+
+	pr_debug("STMMAC platform driver registration completed");
+
+	return 0;
+
+out_unmap:
+	iounmap(addr);
+	platform_set_drvdata(pdev, NULL);
+
+out_release_region:
+	release_mem_region(res->start, resource_size(res));
+
+	return ret;
+}
+
+/**
+ * stmmac_pltfr_remove
+ * @pdev: platform device pointer
+ * Description: this function calls the main to free the net resources
+ * and calls the platforms hook and release the resources (e.g. mem).
+ */
+static int stmmac_pltfr_remove(struct platform_device *pdev)
+{
+	struct net_device *ndev = platform_get_drvdata(pdev);
+	struct stmmac_priv *priv = netdev_priv(ndev);
+	struct resource *res;
+	int ret = stmmac_dvr_remove(ndev);
+
+	if (priv->plat->exit)
+		priv->plat->exit(pdev);
+
+	if (priv->plat->exit)
+		priv->plat->exit(pdev);
+
+	platform_set_drvdata(pdev, NULL);
+
+	iounmap((void *)priv->ioaddr);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(res->start, resource_size(res));
+
+	return ret;
+}
+
+#ifdef CONFIG_PM
+static int stmmac_pltfr_suspend(struct device *dev)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+
+	return stmmac_suspend(ndev);
+}
+
+static int stmmac_pltfr_resume(struct device *dev)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+
+	return stmmac_resume(ndev);
+}
+
+int stmmac_pltfr_freeze(struct device *dev)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+
+	return stmmac_freeze(ndev);
+}
+
+int stmmac_pltfr_restore(struct device *dev)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+
+	return stmmac_restore(ndev);
+}
+
+static const struct dev_pm_ops stmmac_pltfr_pm_ops = {
+	.suspend = stmmac_pltfr_suspend,
+	.resume = stmmac_pltfr_resume,
+	.freeze = stmmac_pltfr_freeze,
+	.thaw = stmmac_pltfr_restore,
+	.restore = stmmac_pltfr_restore,
+};
+#else
+static const struct dev_pm_ops stmmac_pltfr_pm_ops;
+#endif /* CONFIG_PM */
+
+static struct platform_driver stmmac_driver = {
+	.probe = stmmac_pltfr_probe,
+	.remove = stmmac_pltfr_remove,
+	.driver = {
+		   .name = STMMAC_RESOURCE_NAME,
+		   .owner = THIS_MODULE,
+		   .pm = &stmmac_pltfr_pm_ops,
+		   },
+};
+
+module_platform_driver(stmmac_driver);
+
+MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet PLATFORM driver");
+MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
+MODULE_LICENSE("GPL");
-- 
1.7.4.4

^ permalink raw reply related

* [PATCH 2/2 (net.git)] stmmac: update the driver's documentation (Dec-2011)
From: Giuseppe CAVALLARO @ 2011-12-21 13:58 UTC (permalink / raw)
  To: netdev; +Cc: davem, rayagond, Giuseppe Cavallaro
In-Reply-To: <1324475900-1470-1-git-send-email-peppe.cavallaro@st.com>

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
---
 Documentation/networking/stmmac.txt |   16 +++++++++-------
 1 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/Documentation/networking/stmmac.txt b/Documentation/networking/stmmac.txt
index 8d67980..d0aeead 100644
--- a/Documentation/networking/stmmac.txt
+++ b/Documentation/networking/stmmac.txt
@@ -4,14 +4,16 @@ Copyright (C) 2007-2010  STMicroelectronics Ltd
 Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
 
 This is the driver for the MAC 10/100/1000 on-chip Ethernet controllers
-(Synopsys IP blocks); it has been fully tested on STLinux platforms.
+(Synopsys IP blocks).
 
 Currently this network device driver is for all STM embedded MAC/GMAC
-(i.e. 7xxx/5xxx SoCs) and it's known working on other platforms i.e. ARM SPEAr.
+(i.e. 7xxx/5xxx SoCs), SPEAr (arm), Loongson1B (mips) and XLINX XC2V3000
+FF1152AMT0221 D1215994A VIRTEX FPGA board.
 
-DWC Ether MAC 10/100/1000 Universal version 3.41a and DWC Ether MAC 10/100
-Universal version 4.0 have been used for developing the first code
-implementation.
+DWC Ether MAC 10/100/1000 Universal version 3.60a (and older) and DWC Ether MAC 10/100
+Universal version 4.0 have been used for developing this driver.
+
+This driver supports both the platform bus and PCI.
 
 Please, for more information also visit: www.stlinux.com
 
@@ -277,5 +279,5 @@ In fact, these can generate an huge amount of debug messages.
 
 6) TODO:
  o XGMAC is not supported.
- o Review the timer optimisation code to use an embedded device that will be
-  available in new chip generations.
+ o Add the EEE - Energy Efficient Ethernet
+ o Add the PTP - precision time protocol
-- 
1.7.4.4

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox