Netdev List
 help / color / mirror / Atom feed
* Re: loopback IP alias breaks tftp?
From: Eric Dumazet @ 2011-10-10 15:22 UTC (permalink / raw)
  To: Olaf van der Spek
  Cc: Josh Boyer, Joel Sing, Julian Anastasov, netdev, francis.souyri
In-Reply-To: <CAGVGHmsF3JBqpqzKa_Fp6oOcVKX5BKgJUG=UJvPZcNgKiSsrRA@mail.gmail.com>

Le lundi 10 octobre 2011 à 17:15 +0200, Olaf van der Spek a écrit :
> > On Fri, Oct 07, 2011 at 02:23:21PM +0200, Eric Dumazet wrote:
> >> By the way, there is no need for tftp change :
> >>
> >> Just launch several tftpd instances, and bind each them to one
> >> particular IP.
> >>
> >> If started from xinetd.d :
> 
> Isn't that a bad way to work around this issue?
> It'd require you to duplicate your IP config for every daemon that
> listens on UDP interfaces.
> What about IP addresses that are added/deleted after the daemon is launchad?
> 
> Olaf

Thats a pretty common problem, even prior to discussed commit.

If you take a look at common UDP daemons, they have to setup a listener
for each IP address, OR use the correct API ( setsockopt(fd, IPPROTO_IP,
&on, sizeof(on)) and handle IP_PKTINFO ancillary message)

^ permalink raw reply

* Re: loopback IP alias breaks tftp?
From: Olaf van der Spek @ 2011-10-10 15:15 UTC (permalink / raw)
  To: Josh Boyer
  Cc: Eric Dumazet, Joel Sing, Julian Anastasov, netdev, francis.souyri
In-Reply-To: <20111010151058.GD1165@zod.bos.redhat.com>

> On Fri, Oct 07, 2011 at 02:23:21PM +0200, Eric Dumazet wrote:
>> By the way, there is no need for tftp change :
>>
>> Just launch several tftpd instances, and bind each them to one
>> particular IP.
>>
>> If started from xinetd.d :

Isn't that a bad way to work around this issue?
It'd require you to duplicate your IP config for every daemon that
listens on UDP interfaces.
What about IP addresses that are added/deleted after the daemon is launchad?

Olaf

^ permalink raw reply

* Re: [PATCH 9/9] net: add opaque struct around skb frag page
From: Ian Campbell @ 2011-10-10 15:13 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: netdev@vger.kernel.org
In-Reply-To: <1318259375.3227.1.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC>

On Mon, 2011-10-10 at 16:09 +0100, Eric Dumazet wrote:
> Le lundi 10 octobre 2011 à 12:11 +0100, Ian Campbell a écrit :
> > I've split this bit out of the skb frag destructor patch since it helps enforce
> > the use of the fragment API.
> > 
> > Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
> > ---
> >  include/linux/skbuff.h |   10 ++++++----
> >  net/core/skbuff.c      |    6 +++---
> >  2 files changed, 9 insertions(+), 7 deletions(-)
> > 
> > diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
> > index ac6b05a..f881d75 100644
> > --- a/include/linux/skbuff.h
> > +++ b/include/linux/skbuff.h
> > @@ -135,7 +135,9 @@ struct sk_buff;
> >  typedef struct skb_frag_struct skb_frag_t;
> >  
> >  struct skb_frag_struct {
> > -	struct page *page;
> > +	struct {
> > +		struct page *p;
> > +	} page;
> 
> Oh well, why dont you rename page to something else, say frag_page ?

I looked at renaming this field and the impact was far larger than this
(already huge) set of series.

Keeping the name for the outer struct also has the nice property that
when the struct becomes something like:

	struct {
		struct page *p;
		struct skb_frag_destructor *destr;
	} page;

existing code which does
	fraga->page = fragb->page
will carry the destructor along magically without needing modification.

Ian.

> 
> 
> 

^ permalink raw reply

* Re: e100 + VLANs?
From: David Lamparter @ 2011-10-10 15:13 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: Michael Tokarev, David Lamparter, jeffrey.t.kirsher, netdev
In-Reply-To: <1318259152.3227.0.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC>

On Mon, Oct 10, 2011 at 05:05:52PM +0200, Eric Dumazet wrote:
> > When pinging this NIC from another machine over VLAN5, I see
> > ARP packets coming to it, gets recognized and replies going
> > back, all on vlan 5.  But on the other side, replies comes
> > WITHOUT a VLAN tag!
> > 
> > From this NIC's point of view, capturing on whole ethX:
> > 
> > 00:1f:c6:ef:e5:1b > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 60: vlan 5, p 0, ethertype ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 10.48.11.2 tell 10.48.11.1, length 42
> > 00:90:27:30:6d:1c > 00:1f:c6:ef:e5:1b, ethertype 802.1Q (0x8100), length 46: vlan 5, p 0, ethertype ARP, Ethernet (len 6), IPv4 (len 4), Reply 10.48.11.2 is-at 00:90:27:30:6d:1c, length 28
> > 
> > From the partner point of view, also on whole ethX:
> > 
> > 00:1f:c6:ef:e5:1b > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 46: vlan 5, p 0, ethertype ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 10.48.11.2 tell 10.48.11.1, length 28
> > 00:90:27:30:6d:1c > 00:1f:c6:ef:e5:1b, ethertype ARP (0x0806), length 60: Ethernet (len 6), IPv4 (len 4), Reply 10.48.11.2 is-at 00:90:27:30:6d:1c, length 46
> > 
> > So, the tag gets eaten somewhere along the way... ;)

Hmm. Looks like broken VLAN TX offload, but the driver doesn't even
implement VLAN offload. Maybe it's broken in its non-implementation...

Your "partner" is a known-good setup and can be assumed to be working
correctly? This is over a crossover cable, no evil switches involved?

> > And I can't really recreate the situation which I had - I know
> > some packets were flowing, so at least ARP worked.  Now it
> > does not work anymore.
> 
> What the 'partner' setup looks like ?
> 
> ip link
> ip addr
> ip ro

'local' setup too please :)


-David

^ permalink raw reply

* Re: loopback IP alias breaks tftp?
From: Josh Boyer @ 2011-10-10 15:10 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: Joel Sing, Julian Anastasov, netdev, francis.souyri
In-Reply-To: <1317990201.3207.15.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC>

On Fri, Oct 07, 2011 at 02:23:21PM +0200, Eric Dumazet wrote:
> Le vendredi 07 octobre 2011 à 14:04 +0200, Eric Dumazet a écrit :
> 
> > Its a completely different problem IMHO : You describe a tftp server
> > bug.
> > 
> > Say your tftp server is multihomed with 3 different IPS : 
> > 
> > 192.168.20.21, 192.168.20.22, 192.168.20.23
> > 
> > And tftp server listens to any address (UDP port 69) : 0.0.0.0:69
> > 
> > When receiving a request on 192.168.20.22, it should use same source
> > address, not let the system chose a "random or whatever policy" one.
> > 
> > 
> > 
> > So I would suggest to check/fix if TFTP server uses the correct socket
> > API to get both the client IP and its own IP in each UDP datagram
> > 
> > -> setsockopt(fd, IPPROTO_IP, &on, sizeof(on))
> 
> > This permits tftp server to use the same "struct in_pktinfo" for replies, forcing a correct source address.
> > 
> 
> By the way, there is no need for tftp change :
> 
> Just launch several tftpd instances, and bind each them to one
> particular IP.
> 
> If started from xinetd.d :
> 
> $ cat /etc/xinetd.d/tftp1
> service tftp
> {
> 	socket_type		= dgram
> 	protocol		= udp
> 	wait			= yes
> 	user			= root
> 	server			= /usr/sbin/in.tftpd
> 	server_args		= -s /tftpboot
> 	disable			= no
> 	bind		= 192.168.20.21
> 	per_source		= 11
> 	cps			= 100 2
> 	flags			= IPv4
> }

(I've CC'd the original bug reporter now.)

I did this locally and it still timed out.  So the bind alone is not
enough to fix the problem.  At least not on lo:0 127.0.0.2.

Changing the source address in the routing table as Joel suggested does
work around the problem.

So, in summary,  either the TFTP server needs to be changed per your
original suggestion, or the routing table needs to be altered for every
alias?  Is that correct?

josh

^ permalink raw reply

* Re: [PATCH 9/9] net: add opaque struct around skb frag page
From: Eric Dumazet @ 2011-10-10 15:09 UTC (permalink / raw)
  To: Ian Campbell; +Cc: netdev
In-Reply-To: <1318245101-16890-9-git-send-email-ian.campbell@citrix.com>

Le lundi 10 octobre 2011 à 12:11 +0100, Ian Campbell a écrit :
> I've split this bit out of the skb frag destructor patch since it helps enforce
> the use of the fragment API.
> 
> Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
> ---
>  include/linux/skbuff.h |   10 ++++++----
>  net/core/skbuff.c      |    6 +++---
>  2 files changed, 9 insertions(+), 7 deletions(-)
> 
> diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
> index ac6b05a..f881d75 100644
> --- a/include/linux/skbuff.h
> +++ b/include/linux/skbuff.h
> @@ -135,7 +135,9 @@ struct sk_buff;
>  typedef struct skb_frag_struct skb_frag_t;
>  
>  struct skb_frag_struct {
> -	struct page *page;
> +	struct {
> +		struct page *p;
> +	} page;

Oh well, why dont you rename page to something else, say frag_page ?

^ permalink raw reply

* Re: e100 + VLANs?
From: Eric Dumazet @ 2011-10-10 15:05 UTC (permalink / raw)
  To: Michael Tokarev; +Cc: David Lamparter, jeffrey.t.kirsher, netdev
In-Reply-To: <4E9307CB.4050704@msgid.tls.msk.ru>

Le lundi 10 octobre 2011 à 18:57 +0400, Michael Tokarev a écrit :
> 10.10.2011 14:19, David Lamparter wrote:
> > On Sat, Oct 08, 2011 at 11:34:40AM -0700, Jeff Kirsher wrote:
> >> On 10/08/2011 09:24 AM, Eric Dumazet wrote:
> >>> Le samedi 08 octobre 2011 à 14:08 +0400, Michael Tokarev a écrit :
> >>>>> Yesterday I tried to use 802.1Q VLAN tagging with an (oldish)
> >>>>> e100-driven network card, identified by lspci like this:
> >>>>>
> >>>>>  00:12.0 Ethernet controller: Intel Corporation 82557/8/9/0/1 Ethernet Pro 100 (rev 02)
> >>>>>
> >>>>> Just to discover that it does not quite work: packets of
> >>>>> size 1497+ bytes gets lost.
> > [...]
> >>> e100 driver seems VLAN enabled at a first glance.
> >> Eric is correct, that e100 does support VLANs.
> >>
> >> In addition to Eric's suggestion, can you also provide all the output of
> >> lspci -vvv for the network card?
> > 
> > I'm opening the lore box here, but early e100 cards AFAIK have a 
> > hardware limit at 1500 (+18 src/dst/proto) bytes. At least, Juniper's
> > JUNOS does not support full-sized .1Q on their e100 control plane
> > interfaces...
> 
> Thank you all for the suggestions and feedback.
> 
> The card may indeed be quite old, I don't know where it come from and
> when.  Here's lspci -vvv for it:
> 
> 00:12.0 Ethernet controller: Intel Corporation 82557/8/9/0/1 Ethernet Pro 100 (rev 02)
> 	Subsystem: Intel Corporation EtherExpress PRO/100B (TX)
> 	Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR+ FastB2B- DisINTx-
> 	Status: Cap- 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
> 	Latency: 66 (2000ns min, 14000ns max)
> 	Interrupt: pin A routed to IRQ 11
> 	Region 0: Memory at fe200000 (32-bit, prefetchable) [size=4K]
> 	Region 1: I/O ports at 2400 [size=32]
> 	Region 2: Memory at fc000000 (32-bit, non-prefetchable) [size=1M]
> 	[virtual] Expansion ROM at 30100000 [disabled] [size=1M]
> 	Kernel driver in use: e100
> 
> 
> I tried to set it up to talk to another machine in order to find
> out where the packets gets lost.  But had another complication
> on the way: it does not "want" to work with 802.1Q VLANs anymore
> at all... ;)
> 
> When pinging this NIC from another machine over VLAN5, I see
> ARP packets coming to it, gets recognized and replies going
> back, all on vlan 5.  But on the other side, replies comes
> WITHOUT a VLAN tag!
> 
> From this NIC's point of view, capturing on whole ethX:
> 
> 00:1f:c6:ef:e5:1b > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 60: vlan 5, p 0, ethertype ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 10.48.11.2 tell 10.48.11.1, length 42
> 00:90:27:30:6d:1c > 00:1f:c6:ef:e5:1b, ethertype 802.1Q (0x8100), length 46: vlan 5, p 0, ethertype ARP, Ethernet (len 6), IPv4 (len 4), Reply 10.48.11.2 is-at 00:90:27:30:6d:1c, length 28
> 
> From the partner point of view, also on whole ethX:
> 
> 00:1f:c6:ef:e5:1b > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 46: vlan 5, p 0, ethertype ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 10.48.11.2 tell 10.48.11.1, length 28
> 00:90:27:30:6d:1c > 00:1f:c6:ef:e5:1b, ethertype ARP (0x0806), length 60: Ethernet (len 6), IPv4 (len 4), Reply 10.48.11.2 is-at 00:90:27:30:6d:1c, length 46
> 
> So, the tag gets eaten somewhere along the way... ;)
> 
> And I can't really recreate the situation which I had - I know
> some packets were flowing, so at least ARP worked.  Now it
> does not work anymore.

What the 'partner' setup looks like ?

ip link
ip addr
ip ro

^ permalink raw reply

* Re: e100 + VLANs?
From: Michael Tokarev @ 2011-10-10 14:57 UTC (permalink / raw)
  To: David Lamparter; +Cc: jeffrey.t.kirsher, Eric Dumazet, netdev
In-Reply-To: <20111010101954.GB2840382@jupiter.n2.diac24.net>

10.10.2011 14:19, David Lamparter wrote:
> On Sat, Oct 08, 2011 at 11:34:40AM -0700, Jeff Kirsher wrote:
>> On 10/08/2011 09:24 AM, Eric Dumazet wrote:
>>> Le samedi 08 octobre 2011 à 14:08 +0400, Michael Tokarev a écrit :
>>>>> Yesterday I tried to use 802.1Q VLAN tagging with an (oldish)
>>>>> e100-driven network card, identified by lspci like this:
>>>>>
>>>>>  00:12.0 Ethernet controller: Intel Corporation 82557/8/9/0/1 Ethernet Pro 100 (rev 02)
>>>>>
>>>>> Just to discover that it does not quite work: packets of
>>>>> size 1497+ bytes gets lost.
> [...]
>>> e100 driver seems VLAN enabled at a first glance.
>> Eric is correct, that e100 does support VLANs.
>>
>> In addition to Eric's suggestion, can you also provide all the output of
>> lspci -vvv for the network card?
> 
> I'm opening the lore box here, but early e100 cards AFAIK have a 
> hardware limit at 1500 (+18 src/dst/proto) bytes. At least, Juniper's
> JUNOS does not support full-sized .1Q on their e100 control plane
> interfaces...

Thank you all for the suggestions and feedback.

The card may indeed be quite old, I don't know where it come from and
when.  Here's lspci -vvv for it:

00:12.0 Ethernet controller: Intel Corporation 82557/8/9/0/1 Ethernet Pro 100 (rev 02)
	Subsystem: Intel Corporation EtherExpress PRO/100B (TX)
	Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR+ FastB2B- DisINTx-
	Status: Cap- 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
	Latency: 66 (2000ns min, 14000ns max)
	Interrupt: pin A routed to IRQ 11
	Region 0: Memory at fe200000 (32-bit, prefetchable) [size=4K]
	Region 1: I/O ports at 2400 [size=32]
	Region 2: Memory at fc000000 (32-bit, non-prefetchable) [size=1M]
	[virtual] Expansion ROM at 30100000 [disabled] [size=1M]
	Kernel driver in use: e100


I tried to set it up to talk to another machine in order to find
out where the packets gets lost.  But had another complication
on the way: it does not "want" to work with 802.1Q VLANs anymore
at all... ;)

When pinging this NIC from another machine over VLAN5, I see
ARP packets coming to it, gets recognized and replies going
back, all on vlan 5.  But on the other side, replies comes
WITHOUT a VLAN tag!

From this NIC's point of view, capturing on whole ethX:

00:1f:c6:ef:e5:1b > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 60: vlan 5, p 0, ethertype ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 10.48.11.2 tell 10.48.11.1, length 42
00:90:27:30:6d:1c > 00:1f:c6:ef:e5:1b, ethertype 802.1Q (0x8100), length 46: vlan 5, p 0, ethertype ARP, Ethernet (len 6), IPv4 (len 4), Reply 10.48.11.2 is-at 00:90:27:30:6d:1c, length 28

From the partner point of view, also on whole ethX:

00:1f:c6:ef:e5:1b > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 46: vlan 5, p 0, ethertype ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 10.48.11.2 tell 10.48.11.1, length 28
00:90:27:30:6d:1c > 00:1f:c6:ef:e5:1b, ethertype ARP (0x0806), length 60: Ethernet (len 6), IPv4 (len 4), Reply 10.48.11.2 is-at 00:90:27:30:6d:1c, length 46

So, the tag gets eaten somewhere along the way... ;)

And I can't really recreate the situation which I had - I know
some packets were flowing, so at least ARP worked.  Now it
does not work anymore.

Hmm.... ;)

Thank you!

/mjt

^ permalink raw reply

* Re: net/fec on i.MX28: failure after network cable unplug or device down
From: Lothar Waßmann @ 2011-10-10 13:52 UTC (permalink / raw)
  To: Uwe Kleine-König; +Cc: netdev, Shawn Guo, Wolfram Sang
In-Reply-To: <20111010131705.GA25293@pengutronix.de>

[-- Attachment #1: message body and .signature --]
[-- Type: text/plain, Size: 846 bytes --]

Hi,

Uwe Kleine-König writes:
> Hello,
> 
> I currently see the problem on two different i.MX28 based system
> (Freescale's mx28evk and a Karo TX28) that after unplugging and
> reconnection of the network cable or ifconfig down; ifconfig up; the
> network is dead. That means nothing is sent or received anymore.
> 
I already solved this problem (and some others too), but wasn't able
to send any patch yet.

The FEC of the i.MX28 requires the ETHER_EN bit in the ECR to be set
for the MII interface to work. Resetting the interface upon shutdown
is required though, because otherwise the receiver will remain active
and use the stale DMA descriptors in memory to store received packets!

Furthermore the (R)MII mode must be configured correctly in the RCR
register.

The current state of my patch is appended for reference.


Lothar Waßmann
-- 

[-- Attachment #2: fec-cleanup --]
[-- Type: application/octet-stream, Size: 3610 bytes --]

Index: linux/drivers/net/fec.c
===================================================================
--- linux.orig/drivers/net/fec.c	2011-09-13 09:58:38.000000000 +0200
+++ linux/drivers/net/fec.c	2011-09-13 09:58:41.000000000 +0200
@@ -486,10 +486,16 @@
 	writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
 }
 
+/* prevent the FEC from transmitting/receiving packets, but leave
+ * the MII interface active to detect link change
+ */
 static void
 fec_stop(struct net_device *ndev)
 {
 	struct fec_enet_private *fep = netdev_priv(ndev);
+	const struct platform_device_id *id_entry =
+				platform_get_device_id(fep->pdev);
+	u32 rmii_mode = readl(fep->hwp + FEC_R_CNTRL) & (1 << 8);
 
 	/* We cannot expect a graceful transmit stop without link !!! */
 	if (fep->link) {
@@ -504,8 +510,33 @@
 	udelay(10);
 	writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
 	writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
+
+	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
+		/* i.MX28 requires ETHER_EN enabled to be able to
+		 * access the PHY registers and the RMII mode properly set to
+		 * be able to detect link changes
+		 */
+		writel(2, fep->hwp + FEC_ECNTRL);
+		writel(rmii_mode, fep->hwp + FEC_R_CNTRL);
+	}
 }
 
+/* shutdown the FEC and the MII interface */
+static void
+fec_shutdown(struct net_device *ndev)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+
+	/* We cannot expect a graceful transmit stop without link !!! */
+	if (fep->link) {
+		writel(1, fep->hwp + FEC_X_CNTRL); /* Graceful transmit stop */
+		udelay(10);
+		if (!(readl(fep->hwp + FEC_IEVENT) & FEC_ENET_GRA))
+			printk("fec_stop : Graceful transmit stop did not complete !\n");
+	}
+
+	writel(0, fep->hwp + FEC_ECNTRL);
+}
 
 static void
 fec_timeout(struct net_device *ndev)
@@ -789,7 +820,7 @@
 			iap = (unsigned char *)FEC_FLASHMAC;
 #else
 		if (pdata)
-			memcpy(iap, pdata->mac, ETH_ALEN);
+			iap = (unsigned char *)&pdata->mac;
 #endif
 	}
 
@@ -836,6 +867,8 @@
 	if (phy_dev->link) {
 		if (fep->full_duplex != phy_dev->duplex) {
 			fec_restart(ndev, phy_dev->duplex);
+			/* prevent unnecessary second fec_restart() below */
+			fep->link = phy_dev->link;
 			status_change = 1;
 		}
 	}
@@ -1052,8 +1085,6 @@
 
 static void fec_enet_mii_remove(struct fec_enet_private *fep)
 {
-	if (fep->phy_dev)
-		phy_disconnect(fep->phy_dev);
 	mdiobus_unregister(fep->mii_bus);
 	kfree(fep->mii_bus->irq);
 	mdiobus_free(fep->mii_bus);
@@ -1184,6 +1215,8 @@
 fec_enet_open(struct net_device *ndev)
 {
 	struct fec_enet_private *fep = netdev_priv(ndev);
+	const struct platform_device_id *id_entry =
+				platform_get_device_id(fep->pdev);
 	int ret;
 
 	/* I should reset the ring buffers here, but I don't yet know
@@ -1214,7 +1247,7 @@
 	/* Don't know what to do yet. */
 	fep->opened = 0;
 	netif_stop_queue(ndev);
-	fec_stop(ndev);
+	fec_shutdown(ndev);
 
 	if (fep->phy_dev) {
 		phy_stop(fep->phy_dev);
@@ -1518,7 +1551,7 @@
 		}
 	}
 
-	fep->clk = clk_get(&pdev->dev, "fec_clk");
+	fep->clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(fep->clk)) {
 		ret = PTR_ERR(fep->clk);
 		goto failed_clk;
@@ -1570,13 +1603,18 @@
 	struct net_device *ndev = platform_get_drvdata(pdev);
 	struct fec_enet_private *fep = netdev_priv(ndev);
 	struct resource *r;
+	int i;
 
-	fec_stop(ndev);
+	unregister_netdev(ndev);
 	fec_enet_mii_remove(fep);
+	for (i = 0; i < 3; i++) {
+		int irq = platform_get_irq(pdev, i);
+		if (irq > 0)
+			free_irq(irq, ndev);
+	}
 	clk_disable(fep->clk);
 	clk_put(fep->clk);
 	iounmap(fep->hwp);
-	unregister_netdev(ndev);
 	free_netdev(ndev);
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);

[-- Attachment #3: message body text --]
[-- Type: text/plain, Size: 367 bytes --]

___________________________________________________________

Ka-Ro electronics GmbH | Pascalstraße 22 | D - 52076 Aachen
Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10
Geschäftsführer: Matthias Kaussen
Handelsregistereintrag: Amtsgericht Aachen, HRB 4996

www.karo-electronics.de | info@karo-electronics.de
___________________________________________________________

^ permalink raw reply

* Re:await your response
From: Chang @ 2011-10-10 10:15 UTC (permalink / raw)


My name is Mr Young Chang, Head of operation Mevas Bank here in Hong Kong. I have a business proposal that i will like you to handle with me from my bank worth 19.7m USD 

^ permalink raw reply

* net/fec on i.MX28: failure after network cable unplug or device down
From: Uwe Kleine-König @ 2011-10-10 13:17 UTC (permalink / raw)
  To: netdev; +Cc: Shawn Guo, Wolfram Sang, Lothar Waßmann

Hello,

I currently see the problem on two different i.MX28 based system
(Freescale's mx28evk and a Karo TX28) that after unplugging and
reconnection of the network cable or ifconfig down; ifconfig up; the
network is dead. That means nothing is sent or received anymore.

ifconfig up dies with:

	[   32.120000] FEC: MDIO read timeout
	[   32.120000] eth0: could not attach to PHY
	ifconfig: SIOCSIFFLAGS: Connection timed out

after unplugging the network cable I get:

	[   25.520000] PHY: 1:00 - Link is Down
	[   26.530000] FEC: MDIO read timeout

In both cases the mdio read operation doesn't fire the mii irq, though
the FEC_MII_DATA contains data that looks right and the interrupt
register (FEC_IEVENT) has the mii bit set and according to the mask
register (FEC_IMASK) the irq isn't masked.

When commenting out

	writel(1, fep->hwp + FEC_ECNTRL);

(i.e. don't reset the network unit) in fec_stop it works (but Wolfram
seems to remember that doing so breaks e.g. i.MX35. We have not checked
yet).

Strange enough with the reset commented out in fec_stop, fec_restart
resets the fec (when the cable is reconnected) but without breaking it.

I tried to restore more registers in fec_stop (most notably FEC_R_CNTRL
that has some mii fields) but without success.

Do you see this problem, too? Maybe do you have an idea to fix it?
Currently I use the following patch:

diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 5b631fe..8c1330f 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -458,6 +458,8 @@ static void
 fec_stop(struct net_device *ndev)
 {
 	struct fec_enet_private *fep = netdev_priv(ndev);
+	const struct platform_device_id *id_entry =
+				platform_get_device_id(fep->pdev);
 
 	/* We cannot expect a graceful transmit stop without link !!! */
 	if (fep->link) {
@@ -467,11 +469,13 @@ fec_stop(struct net_device *ndev)
 			printk("fec_stop : Graceful transmit stop did not complete !\n");
 	}
 
-	/* Whack a reset.  We should wait for this. */
-	writel(1, fep->hwp + FEC_ECNTRL);
-	udelay(10);
-	writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
-	writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
+	if (!(id_entry->driver_data & FEC_QUIRK_ENET_MAC)) {
+		/* Whack a reset.  We should wait for this. */
+		writel(1, fep->hwp + FEC_ECNTRL);
+		udelay(10);
+		writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
+		writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
+	}
 }
 
but this feels wrong because sending and receiving isn't disabled in
hardware without link then.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply related

* Re: [PATCH 1/9] mm: add a "struct subpage" type containing a page, offset and length
From: Ian Campbell @ 2011-10-10 12:27 UTC (permalink / raw)
  To: linux-mm@kvack.org; +Cc: netdev@vger.kernel.org
In-Reply-To: <1318245101-16890-1-git-send-email-ian.campbell@citrix.com>

On Mon, 2011-10-10 at 12:11 +0100, Ian Campbell wrote:

> Cc: linux-mm@kvack.org
> ---
>  include/linux/mm_types.h |   11 +++++++++++
>  1 files changed, 11 insertions(+), 0 deletions(-)

get_maintainers.pl didn't pick up on this CC. Since mm_types.h was split
out of mm.h does the following make sense? Not sure if mm_*.h (or just
mm_inline.hm?) also makes sense.

8<--------------------------

Subject: MAINTAINER: mm subsystem includes mm_types.h

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>

diff --git a/MAINTAINERS b/MAINTAINERS
index ae8820e..f10a7ea 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4212,6 +4212,7 @@ L:	linux-mm@kvack.org
 W:	http://www.linux-mm.org
 S:	Maintained
 F:	include/linux/mm.h
+F:	include/linux/mm_types.h
 F:	mm/
 
 MEMORY RESOURCE CONTROLLER


> 
> diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
> index 774b895..dc1d103 100644
> --- a/include/linux/mm_types.h
> +++ b/include/linux/mm_types.h
> @@ -135,6 +135,17 @@ struct page {
>  #endif
>  ;
>  
> +struct subpage {
> +	struct page *page;
> +#if (BITS_PER_LONG > 32) || (PAGE_SIZE >= 65536)
> +	__u32 page_offset;
> +	__u32 size;
> +#else
> +	__u16 page_offset;
> +	__u16 size;
> +#endif
> +};
> +
>  typedef unsigned long __nocast vm_flags_t;
>  
>  /*


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related

* [PATCH 9/9] net: add opaque struct around skb frag page
From: Ian Campbell @ 2011-10-10 11:11 UTC (permalink / raw)
  To: netdev; +Cc: Ian Campbell
In-Reply-To: <1318245076.21903.408.camel@zakaz.uk.xensource.com>

I've split this bit out of the skb frag destructor patch since it helps enforce
the use of the fragment API.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
---
 include/linux/skbuff.h |   10 ++++++----
 net/core/skbuff.c      |    6 +++---
 2 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index ac6b05a..f881d75 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -135,7 +135,9 @@ struct sk_buff;
 typedef struct skb_frag_struct skb_frag_t;
 
 struct skb_frag_struct {
-	struct page *page;
+	struct {
+		struct page *p;
+	} page;
 #if (BITS_PER_LONG > 32) || (PAGE_SIZE >= 65536)
 	__u32 page_offset;
 	__u32 size;
@@ -1149,7 +1151,7 @@ static inline void __skb_fill_page_desc(struct sk_buff *skb, int i,
 {
 	skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
 
-	frag->page		  = page;
+	frag->page.p		  = page;
 	frag->page_offset	  = off;
 	frag->size		  = size;
 }
@@ -1673,7 +1675,7 @@ static inline void netdev_free_page(struct net_device *dev, struct page *page)
  */
 static inline struct page *skb_frag_page(const skb_frag_t *frag)
 {
-	return frag->page;
+	return frag->page.p;
 }
 
 /**
@@ -1759,7 +1761,7 @@ static inline void *skb_frag_address_safe(const skb_frag_t *frag)
  */
 static inline void __skb_frag_set_page(skb_frag_t *frag, struct page *page)
 {
-	frag->page = page;
+	frag->page.p = page;
 	__skb_frag_ref(frag);
 }
 
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 5b2c5f1..6305076 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -657,14 +657,14 @@ int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask)
 
 	/* skb frags release userspace buffers */
 	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
-		put_page(skb_shinfo(skb)->frags[i].page);
+		skb_frag_unref(skb, i);
 
 	uarg->callback(uarg);
 
 	/* skb frags point to kernel buffers */
 	for (i = skb_shinfo(skb)->nr_frags; i > 0; i--) {
-		skb_shinfo(skb)->frags[i - 1].page_offset = 0;
-		skb_shinfo(skb)->frags[i - 1].page = head;
+		__skb_fill_page_desc(skb, i-1, head, 0,
+				     skb_shinfo(skb)->frags[i - 1].size);
 		head = (struct page *)head->private;
 	}
 
-- 
1.7.2.5

^ permalink raw reply related

* [PATCH 8/9] ll_temac: convert to SKB paged frag API.
From: Ian Campbell @ 2011-10-10 11:11 UTC (permalink / raw)
  To: netdev; +Cc: Ian Campbell
In-Reply-To: <1318245076.21903.408.camel@zakaz.uk.xensource.com>

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Cc: netdev@vger.kernel.org
---
 drivers/net/ethernet/xilinx/ll_temac_main.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c
index 570776e..66e3c36 100644
--- a/drivers/net/ethernet/xilinx/ll_temac_main.c
+++ b/drivers/net/ethernet/xilinx/ll_temac_main.c
@@ -715,8 +715,7 @@ static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 
 		cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
 		cur_p->phys = dma_map_single(ndev->dev.parent,
-					     (void *)page_address(frag->page) +
-					          frag->page_offset,
+					     skb_frag_address(frag),
 					     frag->size, DMA_TO_DEVICE);
 		cur_p->len = frag->size;
 		cur_p->app0 = 0;
-- 
1.7.2.5

^ permalink raw reply related

* [PATCH 7/9] emac: convert to SKB paged frag API.
From: Ian Campbell @ 2011-10-10 11:11 UTC (permalink / raw)
  To: netdev; +Cc: Ian Campbell
In-Reply-To: <1318245076.21903.408.camel@zakaz.uk.xensource.com>

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Cc: netdev@vger.kernel.org
---
 drivers/net/ethernet/ibm/emac/core.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c
index a573df1..6b3a033 100644
--- a/drivers/net/ethernet/ibm/emac/core.c
+++ b/drivers/net/ethernet/ibm/emac/core.c
@@ -1458,8 +1458,8 @@ static int emac_start_xmit_sg(struct sk_buff *skb, struct net_device *ndev)
 		if (unlikely(dev->tx_cnt + mal_tx_chunks(len) >= NUM_TX_BUFF))
 			goto undo_frame;
 
-		pd = dma_map_page(&dev->ofdev->dev, frag->page, frag->page_offset, len,
-				  DMA_TO_DEVICE);
+		pd = skb_frag_dma_map(&dev->ofdev->dev, frag, 0, len,
+				      DMA_TO_DEVICE);
 
 		slot = emac_xmit_split(dev, slot, pd, len, i == nr_frags - 1,
 				       ctrl);
-- 
1.7.2.5

^ permalink raw reply related

* [PATCH 6/9] ehea: convert to SKB paged frag API
From: Ian Campbell @ 2011-10-10 11:11 UTC (permalink / raw)
  To: netdev; +Cc: Ian Campbell, Breno Leitao
In-Reply-To: <1318245076.21903.408.camel@zakaz.uk.xensource.com>

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Cc: Breno Leitao <leitao@linux.vnet.ibm.com>
Cc: netdev@vger.kernel.org
---
 drivers/net/ethernet/ibm/ehea/ehea_main.c |   11 +++--------
 1 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c
index c821cb6..dfefe80 100644
--- a/drivers/net/ethernet/ibm/ehea/ehea_main.c
+++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c
@@ -1817,8 +1817,7 @@ static inline void write_swqe2_data(struct sk_buff *skb, struct net_device *dev,
 			sg1entry->l_key = lkey;
 			sg1entry->len = frag->size;
 			sg1entry->vaddr =
-				ehea_map_vaddr(page_address(frag->page)
-					       + frag->page_offset);
+				ehea_map_vaddr(skb_frag_address(frag));
 			swqe->descriptors++;
 			sg1entry_contains_frag_data = 1;
 		}
@@ -1830,9 +1829,7 @@ static inline void write_swqe2_data(struct sk_buff *skb, struct net_device *dev,
 
 			sgentry->l_key = lkey;
 			sgentry->len = frag->size;
-			sgentry->vaddr =
-				ehea_map_vaddr(page_address(frag->page)
-					       + frag->page_offset);
+			sgentry->vaddr = ehea_map_vaddr(skb_frag_address(frag));
 			swqe->descriptors++;
 		}
 	}
@@ -2222,9 +2219,7 @@ static void ehea_xmit3(struct sk_buff *skb, struct net_device *dev,
 		/* ... then copy data from the fragments */
 		for (i = 0; i < nfrags; i++) {
 			frag = &skb_shinfo(skb)->frags[i];
-			memcpy(imm_data,
-			       page_address(frag->page) + frag->page_offset,
-			       frag->size);
+			memcpy(imm_data, skb_frag_address(frag), frag->size);
 			imm_data += frag->size;
 		}
 	}
-- 
1.7.2.5

^ permalink raw reply related

* [PATCH 5/9] cxgbi: convert to SKB paged frag API.
From: Ian Campbell @ 2011-10-10 11:11 UTC (permalink / raw)
  To: netdev
  Cc: Ian Campbell, James E.J. Bottomley, David S. Miller,
	Mike Christie, James Bottomley, Karen Xie, linux-scsi
In-Reply-To: <1318245076.21903.408.camel@zakaz.uk.xensource.com>

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Cc: "James E.J. Bottomley" <JBottomley@parallels.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: James Bottomley <James.Bottomley@suse.de>
Cc: Karen Xie <kxie@chelsio.com>
Cc: linux-scsi@vger.kernel.org
Cc: netdev@vger.kernel.org
---
 drivers/scsi/cxgbi/libcxgbi.c |   16 +++++++++-------
 drivers/scsi/cxgbi/libcxgbi.h |    2 +-
 2 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c
index 77ac217..628b23d 100644
--- a/drivers/scsi/cxgbi/libcxgbi.c
+++ b/drivers/scsi/cxgbi/libcxgbi.c
@@ -1787,7 +1787,7 @@ static int sgl_seek_offset(struct scatterlist *sgl, unsigned int sgcnt,
 }
 
 static int sgl_read_to_frags(struct scatterlist *sg, unsigned int sgoffset,
-				unsigned int dlen, skb_frag_t *frags,
+				unsigned int dlen, struct subpage *frags,
 				int frag_max)
 {
 	unsigned int datalen = dlen;
@@ -1944,7 +1944,7 @@ int cxgbi_conn_init_pdu(struct iscsi_task *task, unsigned int offset,
 		if (tdata->nr_frags > MAX_SKB_FRAGS ||
 		    (padlen && tdata->nr_frags == MAX_SKB_FRAGS)) {
 			char *dst = skb->data + task->hdr_len;
-			skb_frag_t *frag = tdata->frags;
+			struct subpage *frag = tdata->frags;
 
 			/* data fits in the skb's headroom */
 			for (i = 0; i < tdata->nr_frags; i++, frag++) {
@@ -1962,11 +1962,13 @@ int cxgbi_conn_init_pdu(struct iscsi_task *task, unsigned int offset,
 			skb_put(skb, count + padlen);
 		} else {
 			/* data fit into frag_list */
-			for (i = 0; i < tdata->nr_frags; i++)
-				get_page(tdata->frags[i].page);
-
-			memcpy(skb_shinfo(skb)->frags, tdata->frags,
-				sizeof(skb_frag_t) * tdata->nr_frags);
+			for (i = 0; i < tdata->nr_frags; i++) {
+				__skb_fill_page_desc(skb, i,
+						tdata->frags[i].page,
+						tdata->frags[i].page_offset,
+						tdata->frags[i].size);
+				skb_frag_ref(skb, i);
+			}
 			skb_shinfo(skb)->nr_frags = tdata->nr_frags;
 			skb->len += count;
 			skb->data_len += count;
diff --git a/drivers/scsi/cxgbi/libcxgbi.h b/drivers/scsi/cxgbi/libcxgbi.h
index 9267844..9406759 100644
--- a/drivers/scsi/cxgbi/libcxgbi.h
+++ b/drivers/scsi/cxgbi/libcxgbi.h
@@ -574,7 +574,7 @@ struct cxgbi_endpoint {
 #define MAX_PDU_FRAGS	((ULP2_MAX_PDU_PAYLOAD + 512 - 1) / 512)
 struct cxgbi_task_data {
 	unsigned short nr_frags;
-	skb_frag_t frags[MAX_PDU_FRAGS];
+	struct subpage frags[MAX_PDU_FRAGS];
 	struct sk_buff *skb;
 	unsigned int offset;
 	unsigned int count;
-- 
1.7.2.5

^ permalink raw reply related

* [PATCH 4/9] cxgb4vf: convert to SKB paged frag API.
From: Ian Campbell @ 2011-10-10 11:11 UTC (permalink / raw)
  To: netdev; +Cc: Ian Campbell, Casey Leedom
In-Reply-To: <1318245076.21903.408.camel@zakaz.uk.xensource.com>

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Cc: Casey Leedom <leedom@chelsio.com>
Cc: netdev@vger.kernel.org
---
 drivers/net/ethernet/chelsio/cxgb4vf/adapter.h |    2 +-
 drivers/net/ethernet/chelsio/cxgb4vf/sge.c     |   80 ++++++++++--------------
 2 files changed, 35 insertions(+), 47 deletions(-)

diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h b/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h
index 594334d..a9f2e34 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h
@@ -144,7 +144,7 @@ struct sge_fl {
  * An ingress packet gather list.
  */
 struct pkt_gl {
-	skb_frag_t frags[MAX_SKB_FRAGS];
+	struct subpage frags[MAX_SKB_FRAGS];
 	void *va;			/* virtual address of first byte */
 	unsigned int nfrags;		/* # of fragments */
 	unsigned int tot_len;		/* total length of fragments */
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c
index cffb328..27f3134 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c
@@ -296,8 +296,8 @@ static int map_skb(struct device *dev, const struct sk_buff *skb,
 	si = skb_shinfo(skb);
 	end = &si->frags[si->nr_frags];
 	for (fp = si->frags; fp < end; fp++) {
-		*++addr = dma_map_page(dev, fp->page, fp->page_offset, fp->size,
-				       DMA_TO_DEVICE);
+		*++addr = skb_frag_dma_map(dev, fp, 0, fp->size,
+					   DMA_TO_DEVICE);
 		if (dma_mapping_error(dev, *addr))
 			goto unwind;
 	}
@@ -1357,6 +1357,35 @@ out_free:
 }
 
 /**
+ *	copy_frags - copy fragments from gather list into skb_shared_info
+ *	@si: destination skb shared info structure
+ *	@gl: source internal packet gather list
+ *	@offset: packet start offset in first page
+ *
+ *	Copy an internal packet gather list into a Linux skb_shared_info
+ *	structure.
+ */
+static inline void copy_frags(struct sk_buff *skb,
+			      const struct pkt_gl *gl,
+			      unsigned int offset)
+{
+	int i;
+
+	/* usually there's just one frag */
+	__skb_fill_page_desc(skb, 0, gl->frags[0].page,
+			     gl->frags[0].page_offset + offset,
+			     gl->frags[0].size - offset);
+	skb_shinfo(skb)->nr_frags = gl->nfrags;
+	for (i = 1; i < gl->nfrags; i++)
+		__skb_fill_page_desc(skb, i, gl->frags[i].page,
+				     gl->frags[i].page_offset,
+				     gl->frags[i].size);
+
+	/* get a reference to the last page, we don't own it */
+	get_page(gl->frags[gl->nfrags - 1].page);
+}
+
+/**
  *	t4vf_pktgl_to_skb - build an sk_buff from a packet gather list
  *	@gl: the gather list
  *	@skb_len: size of sk_buff main body if it carries fragments
@@ -1369,7 +1398,6 @@ struct sk_buff *t4vf_pktgl_to_skb(const struct pkt_gl *gl,
 				  unsigned int skb_len, unsigned int pull_len)
 {
 	struct sk_buff *skb;
-	struct skb_shared_info *ssi;
 
 	/*
 	 * If the ingress packet is small enough, allocate an skb large enough
@@ -1396,21 +1424,10 @@ struct sk_buff *t4vf_pktgl_to_skb(const struct pkt_gl *gl,
 		__skb_put(skb, pull_len);
 		skb_copy_to_linear_data(skb, gl->va, pull_len);
 
-		ssi = skb_shinfo(skb);
-		ssi->frags[0].page = gl->frags[0].page;
-		ssi->frags[0].page_offset = gl->frags[0].page_offset + pull_len;
-		ssi->frags[0].size = gl->frags[0].size - pull_len;
-		if (gl->nfrags > 1)
-			memcpy(&ssi->frags[1], &gl->frags[1],
-			       (gl->nfrags-1) * sizeof(skb_frag_t));
-		ssi->nr_frags = gl->nfrags;
-
+		copy_frags(skb, gl, pull_len);
 		skb->len = gl->tot_len;
 		skb->data_len = skb->len - pull_len;
 		skb->truesize += skb->data_len;
-
-		/* Get a reference for the last page, we don't own it */
-		get_page(gl->frags[gl->nfrags - 1].page);
 	}
 
 out:
@@ -1434,35 +1451,6 @@ void t4vf_pktgl_free(const struct pkt_gl *gl)
 }
 
 /**
- *	copy_frags - copy fragments from gather list into skb_shared_info
- *	@si: destination skb shared info structure
- *	@gl: source internal packet gather list
- *	@offset: packet start offset in first page
- *
- *	Copy an internal packet gather list into a Linux skb_shared_info
- *	structure.
- */
-static inline void copy_frags(struct skb_shared_info *si,
-			      const struct pkt_gl *gl,
-			      unsigned int offset)
-{
-	unsigned int n;
-
-	/* usually there's just one frag */
-	si->frags[0].page = gl->frags[0].page;
-	si->frags[0].page_offset = gl->frags[0].page_offset + offset;
-	si->frags[0].size = gl->frags[0].size - offset;
-	si->nr_frags = gl->nfrags;
-
-	n = gl->nfrags - 1;
-	if (n)
-		memcpy(&si->frags[1], &gl->frags[1], n * sizeof(skb_frag_t));
-
-	/* get a reference to the last page, we don't own it */
-	get_page(gl->frags[n].page);
-}
-
-/**
  *	do_gro - perform Generic Receive Offload ingress packet processing
  *	@rxq: ingress RX Ethernet Queue
  *	@gl: gather list for ingress packet
@@ -1484,7 +1472,7 @@ static void do_gro(struct sge_eth_rxq *rxq, const struct pkt_gl *gl,
 		return;
 	}
 
-	copy_frags(skb_shinfo(skb), gl, PKTSHIFT);
+	copy_frags(skb, gl, PKTSHIFT);
 	skb->len = gl->tot_len - PKTSHIFT;
 	skb->data_len = skb->len;
 	skb->truesize += skb->data_len;
@@ -1667,7 +1655,7 @@ int process_responses(struct sge_rspq *rspq, int budget)
 		rmb();
 		rsp_type = RSPD_TYPE(rc->type_gen);
 		if (likely(rsp_type == RSP_TYPE_FLBUF)) {
-			skb_frag_t *fp;
+			struct subpage *fp;
 			struct pkt_gl gl;
 			const struct rx_sw_desc *sdesc;
 			u32 bufsz, frag;
-- 
1.7.2.5

^ permalink raw reply related

* [PATCH 3/9] cxgb4: convert to SKB paged frag API.
From: Ian Campbell @ 2011-10-10 11:11 UTC (permalink / raw)
  To: netdev; +Cc: Ian Campbell, Dimitris Michailidis
In-Reply-To: <1318245076.21903.408.camel@zakaz.uk.xensource.com>

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Cc: Dimitris Michailidis <dm@chelsio.com>
Cc: netdev@vger.kernel.org
---
 drivers/net/ethernet/chelsio/cxgb4/cxgb4.h |    2 +-
 drivers/net/ethernet/chelsio/cxgb4/sge.c   |   33 ++++++++++++++-------------
 2 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index 223a7f7..209cd69 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -326,7 +326,7 @@ struct sge_fl {                     /* SGE free-buffer queue state */
 
 /* A packet gather list */
 struct pkt_gl {
-	skb_frag_t frags[MAX_SKB_FRAGS];
+	struct subpage frags[MAX_SKB_FRAGS];
 	void *va;                         /* virtual address of first byte */
 	unsigned int nfrags;              /* # of fragments */
 	unsigned int tot_len;             /* total length of fragments */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c
index 56adf44..0100c4c 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
@@ -215,8 +215,8 @@ static int map_skb(struct device *dev, const struct sk_buff *skb,
 	end = &si->frags[si->nr_frags];
 
 	for (fp = si->frags; fp < end; fp++) {
-		*++addr = dma_map_page(dev, fp->page, fp->page_offset, fp->size,
-				       DMA_TO_DEVICE);
+		*++addr = skb_frag_dma_map(dev, fp, 0, fp->size,
+					   DMA_TO_DEVICE);
 		if (dma_mapping_error(dev, *addr))
 			goto unwind;
 	}
@@ -1409,22 +1409,23 @@ int cxgb4_ofld_send(struct net_device *dev, struct sk_buff *skb)
 }
 EXPORT_SYMBOL(cxgb4_ofld_send);
 
-static inline void copy_frags(struct skb_shared_info *ssi,
+static inline void copy_frags(struct sk_buff *skb,
 			      const struct pkt_gl *gl, unsigned int offset)
 {
-	unsigned int n;
+	int i;
 
 	/* usually there's just one frag */
-	ssi->frags[0].page = gl->frags[0].page;
-	ssi->frags[0].page_offset = gl->frags[0].page_offset + offset;
-	ssi->frags[0].size = gl->frags[0].size - offset;
-	ssi->nr_frags = gl->nfrags;
-	n = gl->nfrags - 1;
-	if (n)
-		memcpy(&ssi->frags[1], &gl->frags[1], n * sizeof(skb_frag_t));
+	__skb_fill_page_desc(skb, 0, gl->frags[0].page,
+			     gl->frags[0].page_offset + offset,
+			     gl->frags[0].size - offset);
+	skb_shinfo(skb)->nr_frags = gl->nfrags;
+	for (i = 1; i < gl->nfrags; i++)
+		__skb_fill_page_desc(skb, i, gl->frags[i].page,
+				     gl->frags[i].page_offset,
+				     gl->frags[i].size);
 
 	/* get a reference to the last page, we don't own it */
-	get_page(gl->frags[n].page);
+	get_page(gl->frags[gl->nfrags - 1].page);
 }
 
 /**
@@ -1459,7 +1460,7 @@ struct sk_buff *cxgb4_pktgl_to_skb(const struct pkt_gl *gl,
 		__skb_put(skb, pull_len);
 		skb_copy_to_linear_data(skb, gl->va, pull_len);
 
-		copy_frags(skb_shinfo(skb), gl, pull_len);
+		copy_frags(skb, gl, pull_len);
 		skb->len = gl->tot_len;
 		skb->data_len = skb->len - pull_len;
 		skb->truesize += skb->data_len;
@@ -1478,7 +1479,7 @@ EXPORT_SYMBOL(cxgb4_pktgl_to_skb);
 static void t4_pktgl_free(const struct pkt_gl *gl)
 {
 	int n;
-	const skb_frag_t *p;
+	const struct subpage *p;
 
 	for (p = gl->frags, n = gl->nfrags - 1; n--; p++)
 		put_page(p->page);
@@ -1522,7 +1523,7 @@ static void do_gro(struct sge_eth_rxq *rxq, const struct pkt_gl *gl,
 		return;
 	}
 
-	copy_frags(skb_shinfo(skb), gl, RX_PKT_PAD);
+	copy_frags(skb, gl, RX_PKT_PAD);
 	skb->len = gl->tot_len - RX_PKT_PAD;
 	skb->data_len = skb->len;
 	skb->truesize += skb->data_len;
@@ -1698,7 +1699,7 @@ static int process_responses(struct sge_rspq *q, int budget)
 		rmb();
 		rsp_type = RSPD_TYPE(rc->type_gen);
 		if (likely(rsp_type == RSP_TYPE_FLBUF)) {
-			skb_frag_t *fp;
+			struct subpage *fp;
 			struct pkt_gl si;
 			const struct rx_sw_desc *rsd;
 			u32 len = ntohl(rc->pldbuflen_qid), bufsz, frags;
-- 
1.7.2.5

^ permalink raw reply related

* [PATCH 2/9] mlx4: convert to SKB paged frag API.
From: Ian Campbell @ 2011-10-10 11:11 UTC (permalink / raw)
  To: netdev; +Cc: Ian Campbell
In-Reply-To: <1318245076.21903.408.camel@zakaz.uk.xensource.com>

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Cc: netdev@vger.kernel.org
---
 drivers/net/ethernet/mellanox/mlx4/en_rx.c |   34 ++++++++++++++--------------
 drivers/net/ethernet/mellanox/mlx4/en_tx.c |   20 +++-------------
 2 files changed, 21 insertions(+), 33 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index 37cc9e5..12e0bee 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -44,7 +44,7 @@
 
 static int mlx4_en_alloc_frag(struct mlx4_en_priv *priv,
 			      struct mlx4_en_rx_desc *rx_desc,
-			      struct skb_frag_struct *skb_frags,
+			      struct subpage *skb_frags,
 			      struct mlx4_en_rx_alloc *ring_alloc,
 			      int i)
 {
@@ -157,8 +157,8 @@ static int mlx4_en_prepare_rx_desc(struct mlx4_en_priv *priv,
 				   struct mlx4_en_rx_ring *ring, int index)
 {
 	struct mlx4_en_rx_desc *rx_desc = ring->buf + (index * ring->stride);
-	struct skb_frag_struct *skb_frags = ring->rx_info +
-					    (index << priv->log_rx_info);
+	struct subpage *skb_frags = ring->rx_info +
+				    (index << priv->log_rx_info);
 	int i;
 
 	for (i = 0; i < priv->num_frags; i++)
@@ -183,7 +183,7 @@ static void mlx4_en_free_rx_desc(struct mlx4_en_priv *priv,
 				 int index)
 {
 	struct mlx4_en_dev *mdev = priv->mdev;
-	struct skb_frag_struct *skb_frags;
+	struct subpage *skb_frags;
 	struct mlx4_en_rx_desc *rx_desc = ring->buf + (index << ring->log_stride);
 	dma_addr_t dma;
 	int nr;
@@ -403,8 +403,8 @@ void mlx4_en_deactivate_rx_ring(struct mlx4_en_priv *priv,
 /* Unmap a completed descriptor and free unused pages */
 static int mlx4_en_complete_rx_desc(struct mlx4_en_priv *priv,
 				    struct mlx4_en_rx_desc *rx_desc,
-				    struct skb_frag_struct *skb_frags,
-				    struct skb_frag_struct *skb_frags_rx,
+				    struct subpage *skb_frags,
+				    struct sk_buff *skb,
 				    struct mlx4_en_rx_alloc *page_alloc,
 				    int length)
 {
@@ -420,9 +420,10 @@ static int mlx4_en_complete_rx_desc(struct mlx4_en_priv *priv,
 			break;
 
 		/* Save page reference in skb */
-		skb_frags_rx[nr].page = skb_frags[nr].page;
-		skb_frags_rx[nr].size = skb_frags[nr].size;
-		skb_frags_rx[nr].page_offset = skb_frags[nr].page_offset;
+		__skb_fill_page_desc(skb, nr,
+				     skb_frags[nr].page,
+				     skb_frags[nr].size,
+				     skb_frags[nr].page_offset);
 		dma = be64_to_cpu(rx_desc->data[nr].addr);
 
 		/* Allocate a replacement page */
@@ -430,12 +431,12 @@ static int mlx4_en_complete_rx_desc(struct mlx4_en_priv *priv,
 			goto fail;
 
 		/* Unmap buffer */
-		pci_unmap_single(mdev->pdev, dma, skb_frags_rx[nr].size,
+		pci_unmap_single(mdev->pdev, dma, skb_shinfo(skb)->frags[nr].size,
 				 PCI_DMA_FROMDEVICE);
 	}
 	/* Adjust size of last fragment to match actual length */
 	if (nr > 0)
-		skb_frags_rx[nr - 1].size = length -
+		skb_shinfo(skb)->frags[nr - 1].size = length -
 			priv->frag_info[nr - 1].frag_prefix_size;
 	return nr;
 
@@ -444,7 +445,7 @@ fail:
 	 * the descriptor) of this packet; remaining fragments are reused... */
 	while (nr > 0) {
 		nr--;
-		put_page(skb_frags_rx[nr].page);
+		skb_frag_unref(skb, nr);
 	}
 	return 0;
 }
@@ -452,7 +453,7 @@ fail:
 
 static struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv,
 				      struct mlx4_en_rx_desc *rx_desc,
-				      struct skb_frag_struct *skb_frags,
+				      struct subpage *skb_frags,
 				      struct mlx4_en_rx_alloc *page_alloc,
 				      unsigned int length)
 {
@@ -490,8 +491,7 @@ static struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv,
 
 		/* Move relevant fragments to skb */
 		used_frags = mlx4_en_complete_rx_desc(priv, rx_desc, skb_frags,
-						      skb_shinfo(skb)->frags,
-						      page_alloc, length);
+						      skb, page_alloc, length);
 		if (unlikely(!used_frags)) {
 			kfree_skb(skb);
 			return NULL;
@@ -533,7 +533,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
 	struct mlx4_en_priv *priv = netdev_priv(dev);
 	struct mlx4_cqe *cqe;
 	struct mlx4_en_rx_ring *ring = &priv->rx_ring[cq->ring];
-	struct skb_frag_struct *skb_frags;
+	struct subpage *skb_frags;
 	struct mlx4_en_rx_desc *rx_desc;
 	struct sk_buff *skb;
 	int index;
@@ -600,7 +600,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
 
 					nr = mlx4_en_complete_rx_desc(
 						priv, rx_desc,
-						skb_frags, skb_shinfo(gro_skb)->frags,
+						skb_frags, gro_skb,
 						ring->page_alloc, length);
 					if (!nr)
 						goto next;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
index 6e03de0..e8cc987 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
@@ -460,26 +460,13 @@ static inline void mlx4_en_xmit_poll(struct mlx4_en_priv *priv, int tx_ind)
 		}
 }
 
-static void *get_frag_ptr(struct sk_buff *skb)
-{
-	struct skb_frag_struct *frag =  &skb_shinfo(skb)->frags[0];
-	struct page *page = frag->page;
-	void *ptr;
-
-	ptr = page_address(page);
-	if (unlikely(!ptr))
-		return NULL;
-
-	return ptr + frag->page_offset;
-}
-
 static int is_inline(struct sk_buff *skb, void **pfrag)
 {
 	void *ptr;
 
 	if (inline_thold && !skb_is_gso(skb) && skb->len <= inline_thold) {
 		if (skb_shinfo(skb)->nr_frags == 1) {
-			ptr = get_frag_ptr(skb);
+			ptr = skb_frag_address_safe(&skb_shinfo(skb)->frags[0]);
 			if (unlikely(!ptr))
 				return 0;
 
@@ -756,8 +743,9 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
 		/* Map fragments */
 		for (i = skb_shinfo(skb)->nr_frags - 1; i >= 0; i--) {
 			frag = &skb_shinfo(skb)->frags[i];
-			dma = pci_map_page(mdev->dev->pdev, frag->page, frag->page_offset,
-					   frag->size, PCI_DMA_TODEVICE);
+			dma = skb_frag_dma_map(&mdev->dev->pdev->dev, frag,
+					       0, frag->size,
+					       DMA_TO_DEVICE);
 			data->addr = cpu_to_be64(dma);
 			data->lkey = cpu_to_be32(mdev->mr.key);
 			wmb();
-- 
1.7.2.5

^ permalink raw reply related

* [PATCH 1/9] mm: add a "struct subpage" type containing a page, offset and length
From: Ian Campbell @ 2011-10-10 11:11 UTC (permalink / raw)
  To: netdev; +Cc: Ian Campbell, linux-mm
In-Reply-To: <1318245076.21903.408.camel@zakaz.uk.xensource.com>

A few network drivers currently use skb_frag_struct for this purpose but I have
patches which add additional fields and semantics there which these other uses
do not want.

A structure for reference sub-page regions seems like a generally useful thing
so do so instead of adding a network subsystem specific structure.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Cc: linux-mm@kvack.org
---
 include/linux/mm_types.h |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 774b895..dc1d103 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -135,6 +135,17 @@ struct page {
 #endif
 ;
 
+struct subpage {
+	struct page *page;
+#if (BITS_PER_LONG > 32) || (PAGE_SIZE >= 65536)
+	__u32 page_offset;
+	__u32 size;
+#else
+	__u16 page_offset;
+	__u16 size;
+#endif
+};
+
 typedef unsigned long __nocast vm_flags_t;
 
 /*
-- 
1.7.2.5

^ permalink raw reply related

* [PATCH 0/9] skb fragment API: convert network drivers (part V)
From: Ian Campbell @ 2011-10-10 11:11 UTC (permalink / raw)
  To: netdev@vger.kernel.org; +Cc: linux-scsi, linux-mm

The following series converts a fifth (and hopefully final) batch of
network drivers to the SKB pages fragment API introduced in
131ea6675c76.

There are four drivers here (mlx4, cxgb4, cxgb4vf and cxgbi) which used
skb_frag_t as part of their internal datastructures which meant that
they are impacted by changes to that type more than most drivers. To
break this dependency I added a "struct subpage" (struct page + offset +
len) and converted them to use it. These conversions are a little less
trivial than most of the preceding ones and I have only been able to
compile test them.

I think "struct subpage" is a generally useful tuple I added to a
central location (mm_types.h) rather than somewhere networking or driver
specific but I can trivially move if preferred.

The remaining three drivers in the series (ehea, emac, ll_temac) are
normal conversions which I either missed in my first pass or which have
had direct uses of the fragment pages added since then.

The final patch here wraps the page member of skb_frag_t in a structure,
this is a precursor to adding the destructor here (those patches need a
little more work, arising from comments made at LPC, I'll post regarding
those shortly). This should help ensure that no direct uses of the page
get introduced in the meantime.

I have run an allmodconfig build on a boatload architectures[2] on a
baseline of current net-next/master (88c5100c28b0) and with this series.
Although the baseline didn't build for most architectures I used "make
-k" and confirmed that this series added no new warnings or errors.

This is part of my series to enable visibility into SKB paged fragment's
lifecycles, [0] contains some more background and rationale but
basically the completed series will allow entities which inject pages
into the networking stack to receive a notification when the stack has
really finished with those pages (i.e. including retransmissions,
clones, pull-ups etc) and not just when the original skb is finished
with, which is beneficial to many subsystems which wish to inject pages
into the network stack without giving up full ownership of those page's
lifecycle. It implements something broadly along the lines of what was
described in [1].

Cheers,
Ian.

[0] http://marc.info/?l=linux-netdev&m=131072801125521&w=2
[1] http://marc.info/?l=linux-netdev&m=130925719513084&w=2
[2] arm amd64 blackfin cris i386 ia64 m68k mips64 mips powerpc64 powerpc
s390x sh4 sparc64 sparc xtensa 



^ permalink raw reply

* [PATCH] isdn: add missing cast operator in drivers/isdn/sc/init.c
From: Il Han @ 2011-10-10 11:02 UTC (permalink / raw)
  To: Karsten Keil; +Cc: netdev, Il Han

Add (void __iomem *) to convert the value to the proper type before passing it to readl().

Signed-off-by: Il Han <corone.il.han@gmail.com>
---
 drivers/isdn/sc/init.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c
index ca710ab..79bde78 100644
--- a/drivers/isdn/sc/init.c
+++ b/drivers/isdn/sc/init.c
@@ -484,7 +484,7 @@ static int identify_board(unsigned long rambase, unsigned int iobase)
 	 */
 	outb(PRI_BASEPG_VAL, pgport);
 	msleep_interruptible(1000);
-	sig = readl(rambase + SIG_OFFSET);
+	sig = readl((void __iomem *)rambase + SIG_OFFSET);
 	pr_debug("Looking for a signature, got 0x%lx\n", sig);
 	if(sig == SIGNATURE)
 		return PRI_BOARD;
@@ -494,7 +494,7 @@ static int identify_board(unsigned long rambase, unsigned int iobase)
 	 */
 	outb(BRI_BASEPG_VAL, pgport);
 	msleep_interruptible(1000);
-	sig = readl(rambase + SIG_OFFSET);
+	sig = readl((void __iomem *)rambase + SIG_OFFSET);
 	pr_debug("Looking for a signature, got 0x%lx\n", sig);
 	if(sig == SIGNATURE)
 		return BRI_BOARD;
@@ -504,7 +504,7 @@ static int identify_board(unsigned long rambase, unsigned int iobase)
 	/*
 	 * Try to spot a card
 	 */
-	sig = readl(rambase + SIG_OFFSET);
+	sig = readl((void __iomem *)rambase + SIG_OFFSET);
 	pr_debug("Looking for a signature, got 0x%lx\n", sig);
 	if(sig != SIGNATURE)
 		return -1;
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH v6 8/8] Disable task moving when using kernel memory accounting
From: Glauber Costa @ 2011-10-10 10:24 UTC (permalink / raw)
  To: linux-kernel
  Cc: paul, lizf, kamezawa.hiroyu, ebiederm, davem, gthelen, netdev,
	linux-mm, kirill, avagin, devel, Glauber Costa
In-Reply-To: <1318242268-2234-1-git-send-email-glommer@parallels.com>

Since this code is still experimental, we are leaving the exact
details of how to move tasks between cgroups when kernel memory
accounting is used as future work.

For now, we simply disallow movement if there are any pending
accounted memory.

Signed-off-by: Glauber Costa <glommer@parallels.com>
CC: Hiroyouki Kamezawa <kamezawa.hiroyu@jp.fujitsu.com>
---
 mm/memcontrol.c |   31 ++++++++++++++++++-------------
 1 files changed, 18 insertions(+), 13 deletions(-)

diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index ca08be2..8d1beeb 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -408,23 +408,11 @@ void sock_update_memcg(struct sock *sk)
 
 	rcu_read_lock();
 	sk->sk_cgrp = mem_cgroup_from_task(current);
-
-	/*
-	 * We don't need to protect against anything task-related, because
-	 * we are basically stuck with the sock pointer that won't change,
-	 * even if the task that originated the socket changes cgroups.
-	 *
-	 * What we do have to guarantee, is that the chain leading us to
-	 * the top level won't change under our noses. Incrementing the
-	 * reference count via cgroup_exclude_rmdir guarantees that.
-	 */
-	cgroup_exclude_rmdir(mem_cgroup_css(sk->sk_cgrp));
 	rcu_read_unlock();
 }
 
 void sock_release_memcg(struct sock *sk)
 {
-	cgroup_release_and_wakeup_rmdir(mem_cgroup_css(sk->sk_cgrp));
 }
 
 void memcg_sockets_allocated_dec(struct mem_cgroup *memcg, struct proto *prot)
@@ -5636,10 +5624,17 @@ static int mem_cgroup_can_attach(struct cgroup_subsys *ss,
 {
 	int ret = 0;
 	struct mem_cgroup *mem = mem_cgroup_from_cont(cgroup);
+	struct mem_cgroup *from = mem_cgroup_from_task(p);
+
+	if (from != mem &&
+	    res_counter_read_u64(&mem->tcp.tcp_memory_allocated, RES_USAGE)) {
+		printk(KERN_WARNING "Can't move tasks between cgroups: "
+			"Kernel memory held. task: %s\n", p->comm);
+		return 1;
+	}
 
 	if (mem->move_charge_at_immigrate) {
 		struct mm_struct *mm;
-		struct mem_cgroup *from = mem_cgroup_from_task(p);
 
 		VM_BUG_ON(from == mem);
 
@@ -5807,6 +5802,16 @@ static int mem_cgroup_can_attach(struct cgroup_subsys *ss,
 				struct cgroup *cgroup,
 				struct task_struct *p)
 {
+	struct mem_cgroup *mem = mem_cgroup_from_cont(cgroup);
+	struct mem_cgroup *from = mem_cgroup_from_task(p);
+
+	if (from != mem &&
+	    res_counter_read_u64(&mem->tcp.tcp_memory_allocated, RES_USAGE)) {
+		printk(KERN_WARNING "Can't move tasks between cgroups: "
+			"Kernel memory held. task: %s\n", p->comm);
+		return 1;
+	}
+
 	return 0;
 }
 static void mem_cgroup_cancel_attach(struct cgroup_subsys *ss,
-- 
1.7.6.4

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related

* [PATCH v6 7/8] Display current tcp memory allocation in kmem cgroup
From: Glauber Costa @ 2011-10-10 10:24 UTC (permalink / raw)
  To: linux-kernel
  Cc: paul, lizf, kamezawa.hiroyu, ebiederm, davem, gthelen, netdev,
	linux-mm, kirill, avagin, devel, Glauber Costa
In-Reply-To: <1318242268-2234-1-git-send-email-glommer@parallels.com>

This patch introduces kmem.tcp_current_memory file, living in the
kmem_cgroup filesystem. It is a simple read-only file that displays the
amount of kernel memory currently consumed by the cgroup.

Signed-off-by: Glauber Costa <glommer@parallels.com>
CC: David S. Miller <davem@davemloft.net>
CC: Hiroyouki Kamezawa <kamezawa.hiroyu@jp.fujitsu.com>
CC: Eric W. Biederman <ebiederm@xmission.com>
---
 Documentation/cgroups/memory.txt |    1 +
 mm/memcontrol.c                  |    5 +++++
 2 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt
index c1db134..00f1a88 100644
--- a/Documentation/cgroups/memory.txt
+++ b/Documentation/cgroups/memory.txt
@@ -79,6 +79,7 @@ Brief summary of control files.
  memory.independent_kmem_limit	 # select whether or not kernel memory limits are
 				   independent of user limits
  memory.kmem.tcp.limit_in_bytes  # set/show hard limit for tcp buf memory
+ memory.kmem.tcp.usage_in_bytes  # show current tcp buf memory allocation
 
 1. History
 
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 60e0ec0..ca08be2 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -543,6 +543,11 @@ static struct cftype tcp_files[] = {
 		.read_u64 = mem_cgroup_read,
 		.private = MEMFILE_PRIVATE(_KMEM_TCP, RES_LIMIT),
 	},
+	{
+		.name = "kmem.tcp.usage_in_bytes",
+		.read_u64 = mem_cgroup_read,
+		.private = MEMFILE_PRIVATE(_KMEM_TCP, RES_USAGE),
+	},
 };
 
 static void tcp_create_cgroup(struct mem_cgroup *cg, struct cgroup_subsys *ss)
-- 
1.7.6.4

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ 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