Netdev List
 help / color / mirror / Atom feed
* routing table error in 2.6.39 ..
From: ratheesh kannoth @ 2011-09-22 15:55 UTC (permalink / raw)
  To: user-mode-linux-user, user-mode-linux-devel, netdev

I built UML  (user mode linux ) for 2.6.38 and 2.6.39 kernels.

in 2.6.38 routing  table is  correct. But in 2.6.39 default gw appears
on top of the routing table. same problem persist in 3.0.0 also.

is it a known problem or fixed in higher versions ?

-Ratheesh

^ permalink raw reply

* Re: [PATCH v2 net-next] af_unix: dont send SCM_CREDENTIALS by default
From: tim @ 2011-09-22 16:15 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Valdis.Kletnieks, Tim Chen, David Miller, zheng.z.yan, yanzheng,
	netdev, sfr, jirislaby, sedat.dilek, alex.shi
In-Reply-To: <1316492170.2455.43.camel@edumazet-laptop>

On Tue, 2011-09-20 at 06:16 +0200, Eric Dumazet wrote:
> Le lundi 19 septembre 2011 à 22:10 -0400, Valdis.Kletnieks@vt.edu a
> écrit :
> > On Mon, 19 Sep 2011 14:39:58 PDT, Tim Chen said:
> > > Do we have to worry about the case where peer socket changes its flag
> > > to SOCK_PASSCRED while packets are in flight?  If there isn't such
> > > pathological use case, the patch looks fine to me.
> > 
> > I wouldn't think so - if you're sending a packet, and retroactively trying to
> > change the flag and expect it to work, your program is too ugly to live.  After
> > all, if the scheduler had cut off your timeslice and scheduledthe receiving
> > process before you set the flag, that packet would be delivered and done with
> > anyhow, and no amount of wishing will set that flag on an already-delivered
> > packet.
> > 
> > What *is* worth checking is that we DTRT if a process/thread is doing a send on
> > one CPU, and another process/thread with a shared file descriptor for that
> > socket is diddling the flag.  But if we just define it as "atomic op to change
> > the flag and other observers get whatever value their CPU sees at that
> > instant", I'm OK with that too.. ;)
> > 
> 
> Note : The man page does states :
> 
> "To receive a struct ucred message the SO_PASSCRED option  must  be
> enabled  on  the socket."
> 
> But it doesnt say if the SO_PASSCRED option must be enabled before the
> sender sends its message, or before receiver attempts to read it.
> 
> Once a message is queued on an unix socket, flipping SO_PASSCRED cant
> change its content (adding or removing credentials), since sender might
> already have disappeared.
> 
> So current code includes credentials in all sent messages, just in case
> receiver actually fetch credentials.
> 
> There are probably programs that assume they can set SO_PASSCRED right
> before calling recvmsg(). Are we taking risk to break them, or are we
> gentle and provide a sysctl option to ease the transition, I dont
> know...
> 

Should we reconsider the original approach of reducing the
pid/credential references, with your fixes to correct its flaws in the
streaming msg case?

Tim

^ permalink raw reply

* Re: [PATCH net-next v2] candev: allow SJW user setting for bittiming calculation
From: Oliver Hartkopp @ 2011-09-22 16:26 UTC (permalink / raw)
  To: Wolfgang Grandegger
  Cc: SocketCAN Core Mailing List, Linux Netdev List, David Miller
In-Reply-To: <4E7B331F.3070801-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>

On 09/22/11 15:07, Wolfgang Grandegger wrote:

> Hi Oliver,
> 
> On 09/22/2011 12:28 PM, Oliver Hartkopp wrote:
>> This patch adds support for SJW user settings to not set the synchronization
>> jump width (SJW) to 1 in any case when using the in-kernel bittiming
>> calculation.
>>
>> The ip-tool from iproute2 already supports to pass the user defined SJW
>> value. The given SJW value is sanitized with the controller specific sjw_max
>> and the calculated tseg2 value. As the SJW can have values up to 4 providing
>> this value will lead to the maximum possible SJW automatically. A higher SJW
>> allows higher controller oscillator tolerances.

(..)


> As I already said, I expected "bt->sjw" to be always 0 when
> can_calc_bittiming() is called. But the software somehow allows to
> preset "bt->sjw", which is not intended as the help of the ip utility shows:


What was the technical reason for this 'not intended' that time?

> I actually hesitate to extend can_calc_bittiming(). I suggest using an
> external tool to calculate proper bit-timing parameters and set them
> with "ip link set DEVICE type can tq ...".


Yes, i know the possibility to specify the bittiming via time-quanta (tq).

But i think the in-kernel bittiming calculation is pretty good and solves most
usual cases. For me it's just an additional requirement to specify SJW as
MIN(tseg2, max_sjw) to extend the clock source tolerance - which can be
provided as an additional option to the bittiming calculation without pain
(IMO). If i can 'tune' the sample point, why should i not have any influence
to the synchronization jump width generation then?

And btw. a help text can really be changed easily ;-)

-        [ bitrate BITRATE [ sample-point SAMPLE-POINT] ] |
+        [ bitrate BITRATE [ sample-point SAMPLE-POINT] [sjw SJW] ] |

Regards,
Oliver

^ permalink raw reply

* RE: [Pv-drivers] [PATCH 14/14] vmxnet3: convert to SKB paged frag API.
From: Bhavesh Davda @ 2011-09-22 16:30 UTC (permalink / raw)
  To: Ian Campbell, netdev@vger.kernel.org; +Cc: VMware, Inc.
In-Reply-To: <1316678008-16842-14-git-send-email-ian.campbell@citrix.com>

These changes look sane. What about frag->page_offset and frag->size, are there APIs to access those as well?

[sorry can't pull from git.kernel.org at the moment to answer my own quesion]

- Bhavesh
 
Bhavesh P. Davda

> -----Original Message-----
> From: pv-drivers-bounces@vmware.com [mailto:pv-drivers-bounces@vmware.com] On
> Behalf Of Ian Campbell
> Sent: Thursday, September 22, 2011 12:53 AM
> To: netdev@vger.kernel.org
> Cc: VMware, Inc.; Ian Campbell
> Subject: [Pv-drivers] [PATCH 14/14] vmxnet3: convert to SKB paged frag API.
> 
> Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
> Cc: Shreyas Bhatewara <sbhatewara@vmware.com>
> Cc: "VMware, Inc." <pv-drivers@vmware.com>
> Cc: netdev@vger.kernel.org
> ---
>  drivers/net/vmxnet3/vmxnet3_drv.c |    8 ++++----
>  1 files changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c
> b/drivers/net/vmxnet3/vmxnet3_drv.c
> index 759c1a4..57e7c66 100644
> --- a/drivers/net/vmxnet3/vmxnet3_drv.c
> +++ b/drivers/net/vmxnet3/vmxnet3_drv.c
> @@ -654,7 +654,7 @@ vmxnet3_append_frag(struct sk_buff *skb, struct
> Vmxnet3_RxCompDesc *rcd,
> 
>  	BUG_ON(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS);
> 
> -	frag->page = rbi->page;
> +	__skb_frag_set_page(frag, rbi->page);
>  	frag->page_offset = 0;
>  	frag->size = rcd->len;
>  	skb->data_len += frag->size;
> @@ -748,9 +748,9 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx
> *ctx,
> 
>  		tbi = tq->buf_info + tq->tx_ring.next2fill;
>  		tbi->map_type = VMXNET3_MAP_PAGE;
> -		tbi->dma_addr = pci_map_page(adapter->pdev, frag->page,
> -					     frag->page_offset, frag->size,
> -					     PCI_DMA_TODEVICE);
> +		tbi->dma_addr = skb_frag_dma_map(&adapter->pdev->dev, frag,
> +						 0, frag->size,
> +						 PCI_DMA_TODEVICE);
> 
>  		tbi->len = frag->size;
> 
> --
> 1.7.2.5
> 
> _______________________________________________
> Pv-drivers mailing list
> Pv-drivers@vmware.com
> http://mailman2.vmware.com/mailman/listinfo/pv-drivers

^ permalink raw reply

* Re: Introducing open source MSTP daemon
From: David Lamparter @ 2011-09-22 16:39 UTC (permalink / raw)
  To: Vitalii Demianets
  Cc: bridge, netdev, Srinivas M.A., Stephen Hemminger, Alex Rozin,
	Michael Rozhavsky
In-Reply-To: <201109221727.33010.vitas@nppfactor.kiev.ua>

On Thu, Sep 22, 2011 at 05:27:32PM +0300, Vitalii Demianets wrote:
> Good day!
> I am happy to introduce open source MSTP daemon:
> http://sourceforge.net/p/mstpd
> 
> Of course due to current limitations of the Linux bridge code, namely:
>  - no integration with VLAN code
>  - no support of different FIDs (independent learning)
>  - no support of the per-MSTI port states

Yes... Linux kernel bridging code only implements 802.1D, even the mac
table is one-for-all-VLANs.

> this daemon is not very useful for the bare Linux box. It can work only with 
> support of specialized driver which talks to the MSTP-aware hardware (most of 
> the today ethernet switching parts are MSTP-aware and support FIDs and 
> per-MSTI port states).
> Nevertheless I hope to find some interest in my work. Maybe it will stimulate 
> in some way the integration of the Linux bridge and VLAN code, who knows? 
> From the IEEE point of view they are already merged, see 802.1Q-2005 which 
> incorporates previous editions of 802.1q and 802.1d and 802.1w/s.
> 
> Once again, all interested are welcome. Please review, criticize, test, 
> modify, patch, deploy and do other things :) Any kind of feedback is 
> extremely welcome :)

Very cool!

The code looks quite good to me (i've only looked at 2 files though ;).
Minor nitpicks:
 - hmac_md5 & epoll could maybe come from an external library. you're
   the 3810583th person to have code for that... libevent?
   OpenSSL/gnutls?
 - libnetlink.c is a copy from iproute2? since it is a fresh clean SVN,
   it's not easy to know whether you made changes. Can you put a note
   which version this is? Or maybe you can link it externally?
 - the "assign" macro and "boolFalse" in mstp.c are weird. I understand
   you want stricter type checking, but this makes the code somewhat
   odd to read. Maybe external tools can be used to do this checking
   (sparse, cppcheck, llvm's static analysis, ...)
 - what coding style is it? it's neither Linux kernel nor GNU :) - maybe
   reformat to Linux kernel style while it is still new.

I assume it works with current Linux kernel bridge code on a RSTP level?
The code looks considerably more maintainable than rstpd :) - I will try
running it later!


-David

^ permalink raw reply

* Re: Introducing open source MSTP daemon
From: David Lamparter @ 2011-09-22 16:45 UTC (permalink / raw)
  To: David Lamparter
  Cc: Vitalii Demianets, bridge, netdev, Srinivas M.A.,
	Stephen Hemminger, Alex Rozin, Michael Rozhavsky
In-Reply-To: <20110922163939.GB1012103@jupiter.n2.diac24.net>

On Thu, Sep 22, 2011 at 06:39:40PM +0200, David Lamparter wrote:
>  - what coding style is it? it's neither Linux kernel nor GNU :) - maybe
>    reformat to Linux kernel style while it is still new.

Oh, it's GNU. I shouldn't look at source code in a web browser, stupid
me - Sorry, forget I asked.

-David

^ permalink raw reply

* RE: [Pv-drivers] [PATCH 14/14] vmxnet3: convert to SKB paged frag API.
From: Ian Campbell @ 2011-09-22 16:46 UTC (permalink / raw)
  To: Bhavesh Davda; +Cc: netdev@vger.kernel.org, VMware, Inc.
In-Reply-To: <B07832953588294D802727FF264E276A13EB817FBD@exch-mbx-112.vmware.com>

On Thu, 2011-09-22 at 17:30 +0100, Bhavesh Davda wrote:
> These changes look sane. What about frag->page_offset and frag->size, are there APIs to access those as well?

You can go at those directly.

The important part here is to abstract away the access to the ->page
variable so we can change how the reference counting works.

So unless people think there is a compelling reason to hide away size
and offset I wasn't planning on doing anything like that.

Ian.

> 
> [sorry can't pull from git.kernel.org at the moment to answer my own quesion]
> 
> - Bhavesh
>  
> Bhavesh P. Davda
> 
> > -----Original Message-----
> > From: pv-drivers-bounces@vmware.com [mailto:pv-drivers-bounces@vmware.com] On
> > Behalf Of Ian Campbell
> > Sent: Thursday, September 22, 2011 12:53 AM
> > To: netdev@vger.kernel.org
> > Cc: VMware, Inc.; Ian Campbell
> > Subject: [Pv-drivers] [PATCH 14/14] vmxnet3: convert to SKB paged frag API.
> > 
> > Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
> > Cc: Shreyas Bhatewara <sbhatewara@vmware.com>
> > Cc: "VMware, Inc." <pv-drivers@vmware.com>
> > Cc: netdev@vger.kernel.org
> > ---
> >  drivers/net/vmxnet3/vmxnet3_drv.c |    8 ++++----
> >  1 files changed, 4 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c
> > b/drivers/net/vmxnet3/vmxnet3_drv.c
> > index 759c1a4..57e7c66 100644
> > --- a/drivers/net/vmxnet3/vmxnet3_drv.c
> > +++ b/drivers/net/vmxnet3/vmxnet3_drv.c
> > @@ -654,7 +654,7 @@ vmxnet3_append_frag(struct sk_buff *skb, struct
> > Vmxnet3_RxCompDesc *rcd,
> > 
> >  	BUG_ON(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS);
> > 
> > -	frag->page = rbi->page;
> > +	__skb_frag_set_page(frag, rbi->page);
> >  	frag->page_offset = 0;
> >  	frag->size = rcd->len;
> >  	skb->data_len += frag->size;
> > @@ -748,9 +748,9 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx
> > *ctx,
> > 
> >  		tbi = tq->buf_info + tq->tx_ring.next2fill;
> >  		tbi->map_type = VMXNET3_MAP_PAGE;
> > -		tbi->dma_addr = pci_map_page(adapter->pdev, frag->page,
> > -					     frag->page_offset, frag->size,
> > -					     PCI_DMA_TODEVICE);
> > +		tbi->dma_addr = skb_frag_dma_map(&adapter->pdev->dev, frag,
> > +						 0, frag->size,
> > +						 PCI_DMA_TODEVICE);
> > 
> >  		tbi->len = frag->size;
> > 
> > --
> > 1.7.2.5
> > 
> > _______________________________________________
> > Pv-drivers mailing list
> > Pv-drivers@vmware.com
> > http://mailman2.vmware.com/mailman/listinfo/pv-drivers

^ permalink raw reply

* RE: [Pv-drivers] [PATCH 14/14] vmxnet3: convert to SKB paged frag API.
From: Bhavesh Davda @ 2011-09-22 16:49 UTC (permalink / raw)
  To: Ian Campbell; +Cc: netdev@vger.kernel.org, VMware, Inc.
In-Reply-To: <1316709993.23371.81.camel@zakaz.uk.xensource.com>

Okay.

Signed-off-by: Bhavesh Davda <bhavesh@vmware.com>

- Bhavesh
 
Bhavesh P. Davda

> -----Original Message-----
> From: Ian Campbell [mailto:Ian.Campbell@eu.citrix.com]
> Sent: Thursday, September 22, 2011 9:47 AM
> To: Bhavesh Davda
> Cc: netdev@vger.kernel.org; VMware, Inc.
> Subject: RE: [Pv-drivers] [PATCH 14/14] vmxnet3: convert to SKB paged frag
> API.
> 
> On Thu, 2011-09-22 at 17:30 +0100, Bhavesh Davda wrote:
> > These changes look sane. What about frag->page_offset and frag->size, are
> there APIs to access those as well?
> 
> You can go at those directly.
> 
> The important part here is to abstract away the access to the ->page
> variable so we can change how the reference counting works.
> 
> So unless people think there is a compelling reason to hide away size
> and offset I wasn't planning on doing anything like that.
> 
> Ian.
> 
> >
> > [sorry can't pull from git.kernel.org at the moment to answer my own
> quesion]
> >
> > - Bhavesh
> >
> > Bhavesh P. Davda
> >
> > > -----Original Message-----
> > > From: pv-drivers-bounces@vmware.com [mailto:pv-drivers-bounces@vmware.com]
> On
> > > Behalf Of Ian Campbell
> > > Sent: Thursday, September 22, 2011 12:53 AM
> > > To: netdev@vger.kernel.org
> > > Cc: VMware, Inc.; Ian Campbell
> > > Subject: [Pv-drivers] [PATCH 14/14] vmxnet3: convert to SKB paged frag
> API.
> > >
> > > Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
> > > Cc: Shreyas Bhatewara <sbhatewara@vmware.com>
> > > Cc: "VMware, Inc." <pv-drivers@vmware.com>
> > > Cc: netdev@vger.kernel.org
> > > ---
> > >  drivers/net/vmxnet3/vmxnet3_drv.c |    8 ++++----
> > >  1 files changed, 4 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c
> > > b/drivers/net/vmxnet3/vmxnet3_drv.c
> > > index 759c1a4..57e7c66 100644
> > > --- a/drivers/net/vmxnet3/vmxnet3_drv.c
> > > +++ b/drivers/net/vmxnet3/vmxnet3_drv.c
> > > @@ -654,7 +654,7 @@ vmxnet3_append_frag(struct sk_buff *skb, struct
> > > Vmxnet3_RxCompDesc *rcd,
> > >
> > >  	BUG_ON(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS);
> > >
> > > -	frag->page = rbi->page;
> > > +	__skb_frag_set_page(frag, rbi->page);
> > >  	frag->page_offset = 0;
> > >  	frag->size = rcd->len;
> > >  	skb->data_len += frag->size;
> > > @@ -748,9 +748,9 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct
> vmxnet3_tx_ctx
> > > *ctx,
> > >
> > >  		tbi = tq->buf_info + tq->tx_ring.next2fill;
> > >  		tbi->map_type = VMXNET3_MAP_PAGE;
> > > -		tbi->dma_addr = pci_map_page(adapter->pdev, frag->page,
> > > -					     frag->page_offset, frag->size,
> > > -					     PCI_DMA_TODEVICE);
> > > +		tbi->dma_addr = skb_frag_dma_map(&adapter->pdev->dev, frag,
> > > +						 0, frag->size,
> > > +						 PCI_DMA_TODEVICE);
> > >
> > >  		tbi->len = frag->size;
> > >
> > > --
> > > 1.7.2.5
> > >
> > > _______________________________________________
> > > Pv-drivers mailing list
> > > Pv-drivers@vmware.com
> > > http://mailman2.vmware.com/mailman/listinfo/pv-drivers
> 


^ permalink raw reply

* Re: [PATCH net-next v2] candev: allow SJW user setting for bittiming calculation
From: Wolfgang Grandegger @ 2011-09-22 18:10 UTC (permalink / raw)
  To: Oliver Hartkopp
  Cc: SocketCAN Core Mailing List, Linux Netdev List, David Miller
In-Reply-To: <4E7B61C8.8020506-fJ+pQTUTwRTk1uMJSBkQmQ@public.gmane.org>

On 09/22/2011 06:26 PM, Oliver Hartkopp wrote:
> On 09/22/11 15:07, Wolfgang Grandegger wrote:
> 
>> Hi Oliver,
>>
>> On 09/22/2011 12:28 PM, Oliver Hartkopp wrote:
>>> This patch adds support for SJW user settings to not set the synchronization
>>> jump width (SJW) to 1 in any case when using the in-kernel bittiming
>>> calculation.
>>>
>>> The ip-tool from iproute2 already supports to pass the user defined SJW
>>> value. The given SJW value is sanitized with the controller specific sjw_max
>>> and the calculated tseg2 value. As the SJW can have values up to 4 providing
>>> this value will lead to the maximum possible SJW automatically. A higher SJW
>>> allows higher controller oscillator tolerances.
> 
> (..)
> 
> 
>> As I already said, I expected "bt->sjw" to be always 0 when
>> can_calc_bittiming() is called. But the software somehow allows to
>> preset "bt->sjw", which is not intended as the help of the ip utility shows:
> 
> 
> What was the technical reason for this 'not intended' that time?

Fiddling with SJW is something for *expert* only. You need to know
what's going on the bus (electrically). To be clear, I'm not such an expert.

>> I actually hesitate to extend can_calc_bittiming(). I suggest using an
>> external tool to calculate proper bit-timing parameters and set them
>> with "ip link set DEVICE type can tq ...".
> 
> 
> Yes, i know the possibility to specify the bittiming via time-quanta (tq).

This is what we called the "expert mode".

> But i think the in-kernel bittiming calculation is pretty good and solves most
> usual cases. For me it's just an additional requirement to specify SJW as

What's your reason to increase SJW? Likely because you get bus errors
with the standard settings. How should it be set? Likely you need to
fiddle with other parameters as well. For sure, no business for a normal
CAN user.

> MIN(tseg2, max_sjw) to extend the clock source tolerance - which can be
> provided as an additional option to the bittiming calculation without pain
> (IMO). If i can 'tune' the sample point, why should i not have any influence
> to the synchronization jump width generation then?

Bitrate and sample point is something obvious for normal users.

> And btw. a help text can really be changed easily ;-)
> 
> -        [ bitrate BITRATE [ sample-point SAMPLE-POINT] ] |
> +        [ bitrate BITRATE [ sample-point SAMPLE-POINT] [sjw SJW] ] |

Well, I have stronger arguments against it ;-).

Any other opinions or suggestions?

Wolfgang.

^ permalink raw reply

* Re: routing table error in 2.6.39 ..
From: David Miller @ 2011-09-22 18:21 UTC (permalink / raw)
  To: ratheesh.ksz; +Cc: user-mode-linux-user, user-mode-linux-devel, netdev
In-Reply-To: <CAGZFCEHtyE1MutMmhKefFm9Xx5rri1j7DR7L=cFU3KUg7ejs4g@mail.gmail.com>

From: ratheesh kannoth <ratheesh.ksz@gmail.com>
Date: Thu, 22 Sep 2011 21:25:47 +0530

> in 2.6.38 routing  table is  correct. But in 2.6.39 default gw appears
> on top of the routing table. same problem persist in 3.0.0 also.

You cannot depend upon the order in which routing table entries
are listed by the kernel.

The table internally is correct, and lookups will match using the
proper longest-matching-prefix algorithm.

^ permalink raw reply

* pull request: batman-adv 2011-09-22 (regression fix)
From: Marek Lindner @ 2011-09-22 18:57 UTC (permalink / raw)
  To: davem; +Cc: netdev, b.a.t.m.a.n

Hi David,

our testers have discovered a regression in the current linux-3.1
code base. It increases latency of payload traffic by a factor of
4-5. Therefore we propose a patch that hopefully can be included 
before linux 3.1 final has been released. We kept it as short as 
possible to avoid introducing last minute bugs.

Once you pulled the patch you will run into a merge conflict
with net-next:
++<<<<<<< HEAD
 + orig_node = transtable_search(bat_priv, ethhdr->h_source,
 +                               ethhdr->h_dest);
 + if (is_multicast_ether_addr(ethhdr->h_dest) ||
 + (orig_node && orig_node->gw_flags)) {
++=======
+ orig_node = transtable_search(bat_priv, ethhdr->h_dest);
+ do_bcast = is_multicast_ether_addr(ethhdr->h_dest);
+ if (do_bcast || (orig_node && orig_node->gw_flags)) {
++>>>>>>> batman-adv/maint

The correct merge result would be:
+======
orig_node = transtable_search(bat_priv, ethhdr->h_source,
                              ethhdr->h_dest);
do_bcast = is_multicast_ether_addr(ethhdr->h_dest);
if (do_bcast || (orig_node && orig_node->gw_flags)) {
+======

Let me know if there is a better way to address the merge conflict.

Thanks,
Marek

The following changes since commit 322a8b034003c0d46d39af85bf24fee27b902f48:

  Linux 3.1-rc1 (2011-08-07 18:23:30 -0700)

are available in the git repository at:
  git://git.open-mesh.org/linux-merge.git batman-adv/maint

Antonio Quartulli (1):
      batman-adv: do_bcast has to be true for broadcast packets only

 net/batman-adv/soft-interface.c |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)

^ permalink raw reply

* [PATCH] batman-adv: do_bcast has to be true for broadcast packets only
From: Marek Lindner @ 2011-09-22 18:57 UTC (permalink / raw)
  To: davem; +Cc: netdev, b.a.t.m.a.n, Antonio Quartulli, Marek Lindner
In-Reply-To: <1316717836-19374-1-git-send-email-lindner_marek@yahoo.de>

From: Antonio Quartulli <ordex@autistici.org>

corrects a critical bug of the GW feature. This bug made all the unicast
packets destined to a GW to be sent as broadcast. This bug is present even if
the sender GW feature is configured as OFF. It's an urgent bug fix and should
be committed as soon as possible.

This was a regression introduced by 43676ab590c3f8686fd047d34c3e33803eef71f0

Signed-off-by: Antonio Quartulli <ordex@autistici.org>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
---
 net/batman-adv/soft-interface.c |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 3e2f91f..05dd351 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -565,7 +565,7 @@ static int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
 	struct orig_node *orig_node = NULL;
 	int data_len = skb->len, ret;
 	short vid = -1;
-	bool do_bcast = false;
+	bool do_bcast;
 
 	if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE)
 		goto dropped;
@@ -598,15 +598,15 @@ static int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
 	tt_local_add(soft_iface, ethhdr->h_source);
 
 	orig_node = transtable_search(bat_priv, ethhdr->h_dest);
-	if (is_multicast_ether_addr(ethhdr->h_dest) ||
-				(orig_node && orig_node->gw_flags)) {
+	do_bcast = is_multicast_ether_addr(ethhdr->h_dest);
+	if (do_bcast ||	(orig_node && orig_node->gw_flags)) {
 		ret = gw_is_target(bat_priv, skb, orig_node);
 
 		if (ret < 0)
 			goto dropped;
 
-		if (ret == 0)
-			do_bcast = true;
+		if (ret)
+			do_bcast = false;
 	}
 
 	/* ethernet packet should be broadcasted */
-- 
1.7.5.4

^ permalink raw reply related

* Re: [PATCH net-next v2] candev: allow SJW user setting for bittiming calculation
From: Oliver Hartkopp @ 2011-09-22 19:41 UTC (permalink / raw)
  To: Wolfgang Grandegger; +Cc: SocketCAN Core Mailing List, Linux Netdev List
In-Reply-To: <4E7B7A30.4030707-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>

Hi Wolfgang,

i put Pavel and Andrey into CC, maybe they also have an opinion about this.
I just talked to a specialist who told me, that a higher SJW is better - if
possible. And if an expert told me so and i had a simple config interface to
fullfill it, it would be great for me ;-)

Here is a link to the patch and this discussion:

http://patchwork.ozlabs.org/patch/115932/

Regards,
Oliver

On 09/22/11 20:10, Wolfgang Grandegger wrote:

> On 09/22/2011 06:26 PM, Oliver Hartkopp wrote:
>> On 09/22/11 15:07, Wolfgang Grandegger wrote:
>>
>>> Hi Oliver,
>>>
>>> On 09/22/2011 12:28 PM, Oliver Hartkopp wrote:
>>>> This patch adds support for SJW user settings to not set the synchronization
>>>> jump width (SJW) to 1 in any case when using the in-kernel bittiming
>>>> calculation.
>>>>
>>>> The ip-tool from iproute2 already supports to pass the user defined SJW
>>>> value. The given SJW value is sanitized with the controller specific sjw_max
>>>> and the calculated tseg2 value. As the SJW can have values up to 4 providing
>>>> this value will lead to the maximum possible SJW automatically. A higher SJW
>>>> allows higher controller oscillator tolerances.
>>
>> (..)
>>
>>
>>> As I already said, I expected "bt->sjw" to be always 0 when
>>> can_calc_bittiming() is called. But the software somehow allows to
>>> preset "bt->sjw", which is not intended as the help of the ip utility shows:
>>
>>
>> What was the technical reason for this 'not intended' that time?
> 
> Fiddling with SJW is something for *expert* only. You need to know
> what's going on the bus (electrically). To be clear, I'm not such an expert.
> 
>>> I actually hesitate to extend can_calc_bittiming(). I suggest using an
>>> external tool to calculate proper bit-timing parameters and set them
>>> with "ip link set DEVICE type can tq ...".
>>
>>
>> Yes, i know the possibility to specify the bittiming via time-quanta (tq).
> 
> This is what we called the "expert mode".
> 
>> But i think the in-kernel bittiming calculation is pretty good and solves most
>> usual cases. For me it's just an additional requirement to specify SJW as
> 
> What's your reason to increase SJW? Likely because you get bus errors
> with the standard settings. How should it be set? Likely you need to
> fiddle with other parameters as well. For sure, no business for a normal
> CAN user.
> 
>> MIN(tseg2, max_sjw) to extend the clock source tolerance - which can be
>> provided as an additional option to the bittiming calculation without pain
>> (IMO). If i can 'tune' the sample point, why should i not have any influence
>> to the synchronization jump width generation then?
> 
> Bitrate and sample point is something obvious for normal users.
> 
>> And btw. a help text can really be changed easily ;-)
>>
>> -        [ bitrate BITRATE [ sample-point SAMPLE-POINT] ] |
>> +        [ bitrate BITRATE [ sample-point SAMPLE-POINT] [sjw SJW] ] |
> 
> Well, I have stronger arguments against it ;-).
> 
> Any other opinions or suggestions?
> 
> Wolfgang.
> 
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 0/14] skb fragment API: convert network drivers (part III)
From: David Miller @ 2011-09-22 20:05 UTC (permalink / raw)
  To: Ian.Campbell; +Cc: netdev
In-Reply-To: <1316677996.23371.10.camel@zakaz.uk.xensource.com>

From: Ian Campbell <Ian.Campbell@citrix.com>
Date: Thu, 22 Sep 2011 08:53:16 +0100

> The following series converts the third batch of network drivers to the
> SKB pages fragment API introduced in 131ea6675c76. I expect there will
> be ~4 similarly sized batches to convert all the drivers over.
> 
> 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].

ALl applied, thanks Ian.

^ permalink raw reply

* [PATCH next 0/4] Pull request for 'davem-next.r8169' branch
From: Francois Romieu @ 2011-09-22 21:02 UTC (permalink / raw)
  To: davem; +Cc: netdev, Realtek linux nic maintainers, Hayes Wang

Please pull from branch 'davem-next.r8169' in repository

git://violet.fr.zoreil.com/romieu/linux davem-next.r8169

to get the changes below.

The series includes the remaining part of Hayes's recent patches as
well as some jumbo frames changes.

The pci_write_config_byte(pdev, 0x79, ... should be replaced with some
rtl_tx_performance_tweak variant. Feel free to peel the top-most patch
if you want me to respin it with the jumbo changes patch.

Distance from 'davem-next' (8decf868790b48a727d7e7ca164f2bcd3c1389c0)
---------------------------------------------------------------------

d58d46b5d85139d18eb939aa7279c160bab70484
deb9d93c89d311714a60809b28160e538e1cbb43
c2218925f3a653ac6c39e62eb0e10232d2b44dab
3090bd9a3102331ed981280ef05ee5433ce978d7

Diffstat
--------

 drivers/net/ethernet/realtek/r8169.c |  487 ++++++++++++++++++++++++++++++----
 1 files changed, 430 insertions(+), 57 deletions(-)

Shortlog
--------

Francois Romieu (2):
      r8169: expand received packet length indication.
      r8169: jumbo fixes.

Hayes Wang (2):
      r8169: define the early size for 8111evl
      r8169: support new chips of RTL8111F

Patch
-----

diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index 6eb9f4e..2ce6070 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -42,6 +42,8 @@
 #define FIRMWARE_8168E_1	"rtl_nic/rtl8168e-1.fw"
 #define FIRMWARE_8168E_2	"rtl_nic/rtl8168e-2.fw"
 #define FIRMWARE_8168E_3	"rtl_nic/rtl8168e-3.fw"
+#define FIRMWARE_8168F_1	"rtl_nic/rtl8168f-1.fw"
+#define FIRMWARE_8168F_2	"rtl_nic/rtl8168f-2.fw"
 #define FIRMWARE_8105E_1	"rtl_nic/rtl8105e-1.fw"
 
 #ifdef RTL8169_DEBUG
@@ -133,6 +135,8 @@ enum mac_version {
 	RTL_GIGA_MAC_VER_32,
 	RTL_GIGA_MAC_VER_33,
 	RTL_GIGA_MAC_VER_34,
+	RTL_GIGA_MAC_VER_35,
+	RTL_GIGA_MAC_VER_36,
 	RTL_GIGA_MAC_NONE   = 0xff,
 };
 
@@ -141,84 +145,110 @@ enum rtl_tx_desc_version {
 	RTL_TD_1	= 1,
 };
 
-#define _R(NAME,TD,FW) \
-	{ .name = NAME, .txd_version = TD, .fw_name = FW }
+#define JUMBO_1K	ETH_DATA_LEN
+#define JUMBO_4K	(4*1024 - ETH_HLEN - 2)
+#define JUMBO_6K	(6*1024 - ETH_HLEN - 2)
+#define JUMBO_7K	(7*1024 - ETH_HLEN - 2)
+#define JUMBO_9K	(9*1024 - ETH_HLEN - 2)
+
+#define _R(NAME,TD,FW,SZ,B) {	\
+	.name = NAME,		\
+	.txd_version = TD,	\
+	.fw_name = FW,		\
+	.jumbo_max = SZ,	\
+	.jumbo_tx_csum = B	\
+}
 
 static const struct {
 	const char *name;
 	enum rtl_tx_desc_version txd_version;
 	const char *fw_name;
+	u16 jumbo_max;
+	bool jumbo_tx_csum;
 } rtl_chip_infos[] = {
 	/* PCI devices. */
 	[RTL_GIGA_MAC_VER_01] =
-		_R("RTL8169",		RTL_TD_0, NULL),
+		_R("RTL8169",		RTL_TD_0, NULL, JUMBO_7K, true),
 	[RTL_GIGA_MAC_VER_02] =
-		_R("RTL8169s",		RTL_TD_0, NULL),
+		_R("RTL8169s",		RTL_TD_0, NULL, JUMBO_7K, true),
 	[RTL_GIGA_MAC_VER_03] =
-		_R("RTL8110s",		RTL_TD_0, NULL),
+		_R("RTL8110s",		RTL_TD_0, NULL, JUMBO_7K, true),
 	[RTL_GIGA_MAC_VER_04] =
-		_R("RTL8169sb/8110sb",	RTL_TD_0, NULL),
+		_R("RTL8169sb/8110sb",	RTL_TD_0, NULL, JUMBO_7K, true),
 	[RTL_GIGA_MAC_VER_05] =
-		_R("RTL8169sc/8110sc",	RTL_TD_0, NULL),
+		_R("RTL8169sc/8110sc",	RTL_TD_0, NULL, JUMBO_7K, true),
 	[RTL_GIGA_MAC_VER_06] =
-		_R("RTL8169sc/8110sc",	RTL_TD_0, NULL),
+		_R("RTL8169sc/8110sc",	RTL_TD_0, NULL, JUMBO_7K, true),
 	/* PCI-E devices. */
 	[RTL_GIGA_MAC_VER_07] =
-		_R("RTL8102e",		RTL_TD_1, NULL),
+		_R("RTL8102e",		RTL_TD_1, NULL, JUMBO_1K, true),
 	[RTL_GIGA_MAC_VER_08] =
-		_R("RTL8102e",		RTL_TD_1, NULL),
+		_R("RTL8102e",		RTL_TD_1, NULL, JUMBO_1K, true),
 	[RTL_GIGA_MAC_VER_09] =
-		_R("RTL8102e",		RTL_TD_1, NULL),
+		_R("RTL8102e",		RTL_TD_1, NULL, JUMBO_1K, true),
 	[RTL_GIGA_MAC_VER_10] =
-		_R("RTL8101e",		RTL_TD_0, NULL),
+		_R("RTL8101e",		RTL_TD_0, NULL, JUMBO_1K, true),
 	[RTL_GIGA_MAC_VER_11] =
-		_R("RTL8168b/8111b",	RTL_TD_0, NULL),
+		_R("RTL8168b/8111b",	RTL_TD_0, NULL, JUMBO_4K, false),
 	[RTL_GIGA_MAC_VER_12] =
-		_R("RTL8168b/8111b",	RTL_TD_0, NULL),
+		_R("RTL8168b/8111b",	RTL_TD_0, NULL, JUMBO_4K, false),
 	[RTL_GIGA_MAC_VER_13] =
-		_R("RTL8101e",		RTL_TD_0, NULL),
+		_R("RTL8101e",		RTL_TD_0, NULL, JUMBO_1K, true),
 	[RTL_GIGA_MAC_VER_14] =
-		_R("RTL8100e",		RTL_TD_0, NULL),
+		_R("RTL8100e",		RTL_TD_0, NULL, JUMBO_1K, true),
 	[RTL_GIGA_MAC_VER_15] =
-		_R("RTL8100e",		RTL_TD_0, NULL),
+		_R("RTL8100e",		RTL_TD_0, NULL, JUMBO_1K, true),
 	[RTL_GIGA_MAC_VER_16] =
-		_R("RTL8101e",		RTL_TD_0, NULL),
+		_R("RTL8101e",		RTL_TD_0, NULL, JUMBO_1K, true),
 	[RTL_GIGA_MAC_VER_17] =
-		_R("RTL8168b/8111b",	RTL_TD_0, NULL),
+		_R("RTL8168b/8111b",	RTL_TD_1, NULL, JUMBO_4K, false),
 	[RTL_GIGA_MAC_VER_18] =
-		_R("RTL8168cp/8111cp",	RTL_TD_1, NULL),
+		_R("RTL8168cp/8111cp",	RTL_TD_1, NULL, JUMBO_6K, false),
 	[RTL_GIGA_MAC_VER_19] =
-		_R("RTL8168c/8111c",	RTL_TD_1, NULL),
+		_R("RTL8168c/8111c",	RTL_TD_1, NULL, JUMBO_6K, false),
 	[RTL_GIGA_MAC_VER_20] =
-		_R("RTL8168c/8111c",	RTL_TD_1, NULL),
+		_R("RTL8168c/8111c",	RTL_TD_1, NULL, JUMBO_6K, false),
 	[RTL_GIGA_MAC_VER_21] =
-		_R("RTL8168c/8111c",	RTL_TD_1, NULL),
+		_R("RTL8168c/8111c",	RTL_TD_1, NULL, JUMBO_6K, false),
 	[RTL_GIGA_MAC_VER_22] =
-		_R("RTL8168c/8111c",	RTL_TD_1, NULL),
+		_R("RTL8168c/8111c",	RTL_TD_1, NULL, JUMBO_6K, false),
 	[RTL_GIGA_MAC_VER_23] =
-		_R("RTL8168cp/8111cp",	RTL_TD_1, NULL),
+		_R("RTL8168cp/8111cp",	RTL_TD_1, NULL, JUMBO_6K, false),
 	[RTL_GIGA_MAC_VER_24] =
-		_R("RTL8168cp/8111cp",	RTL_TD_1, NULL),
+		_R("RTL8168cp/8111cp",	RTL_TD_1, NULL, JUMBO_6K, false),
 	[RTL_GIGA_MAC_VER_25] =
-		_R("RTL8168d/8111d",	RTL_TD_1, FIRMWARE_8168D_1),
+		_R("RTL8168d/8111d",	RTL_TD_1, FIRMWARE_8168D_1,
+							JUMBO_9K, false),
 	[RTL_GIGA_MAC_VER_26] =
-		_R("RTL8168d/8111d",	RTL_TD_1, FIRMWARE_8168D_2),
+		_R("RTL8168d/8111d",	RTL_TD_1, FIRMWARE_8168D_2,
+							JUMBO_9K, false),
 	[RTL_GIGA_MAC_VER_27] =
-		_R("RTL8168dp/8111dp",	RTL_TD_1, NULL),
+		_R("RTL8168dp/8111dp",	RTL_TD_1, NULL, JUMBO_9K, false),
 	[RTL_GIGA_MAC_VER_28] =
-		_R("RTL8168dp/8111dp",	RTL_TD_1, NULL),
+		_R("RTL8168dp/8111dp",	RTL_TD_1, NULL, JUMBO_9K, false),
 	[RTL_GIGA_MAC_VER_29] =
-		_R("RTL8105e",		RTL_TD_1, FIRMWARE_8105E_1),
+		_R("RTL8105e",		RTL_TD_1, FIRMWARE_8105E_1,
+							JUMBO_1K, true),
 	[RTL_GIGA_MAC_VER_30] =
-		_R("RTL8105e",		RTL_TD_1, FIRMWARE_8105E_1),
+		_R("RTL8105e",		RTL_TD_1, FIRMWARE_8105E_1,
+							JUMBO_1K, true),
 	[RTL_GIGA_MAC_VER_31] =
-		_R("RTL8168dp/8111dp",	RTL_TD_1, NULL),
+		_R("RTL8168dp/8111dp",	RTL_TD_1, NULL, JUMBO_9K, false),
 	[RTL_GIGA_MAC_VER_32] =
-		_R("RTL8168e/8111e",	RTL_TD_1, FIRMWARE_8168E_1),
+		_R("RTL8168e/8111e",	RTL_TD_1, FIRMWARE_8168E_1,
+							JUMBO_9K, false),
 	[RTL_GIGA_MAC_VER_33] =
-		_R("RTL8168e/8111e",	RTL_TD_1, FIRMWARE_8168E_2),
+		_R("RTL8168e/8111e",	RTL_TD_1, FIRMWARE_8168E_2,
+							JUMBO_9K, false),
 	[RTL_GIGA_MAC_VER_34] =
-		_R("RTL8168evl/8111evl",RTL_TD_1, FIRMWARE_8168E_3)
+		_R("RTL8168evl/8111evl",RTL_TD_1, FIRMWARE_8168E_3,
+							JUMBO_9K, false),
+	[RTL_GIGA_MAC_VER_35] =
+		_R("RTL8168f/8111f",	RTL_TD_1, FIRMWARE_8168F_1,
+							JUMBO_9K, false),
+	[RTL_GIGA_MAC_VER_36] =
+		_R("RTL8168f/8111f",	RTL_TD_1, FIRMWARE_8168F_2,
+							JUMBO_9K, false),
 };
 #undef _R
 
@@ -311,6 +341,7 @@ enum rtl_registers {
 	MaxTxPacketSize	= 0xec,	/* 8101/8168. Unit of 128 bytes. */
 
 #define TxPacketMax	(8064 >> 7)
+#define EarlySize	0x27
 
 	FuncEvent	= 0xf0,
 	FuncEventMask	= 0xf4,
@@ -460,8 +491,12 @@ enum rtl_register_content {
 	/* Config3 register p.25 */
 	MagicPacket	= (1 << 5),	/* Wake up when receives a Magic Packet */
 	LinkUp		= (1 << 4),	/* Wake up when the cable connection is re-established */
+	Jumbo_En0	= (1 << 2),	/* 8168 only. Reserved in the 8168b */
 	Beacon_en	= (1 << 0),	/* 8168 only. Reserved in the 8168b */
 
+	/* Config4 register */
+	Jumbo_En1	= (1 << 1),	/* 8168 only. Reserved in the 8168b */
+
 	/* Config5 register p.27 */
 	BWF		= (1 << 6),	/* Accept Broadcast wakeup frame */
 	MWF		= (1 << 5),	/* Accept Multicast wakeup frame */
@@ -670,6 +705,11 @@ struct rtl8169_private {
 		void (*up)(struct rtl8169_private *);
 	} pll_power_ops;
 
+	struct jumbo_ops {
+		void (*enable)(struct rtl8169_private *);
+		void (*disable)(struct rtl8169_private *);
+	} jumbo_ops;
+
 	int (*set_speed)(struct net_device *, u8 aneg, u16 sp, u8 dpx, u32 adv);
 	int (*get_settings)(struct net_device *, struct ethtool_cmd *);
 	void (*phy_reset_enable)(struct rtl8169_private *tp);
@@ -714,6 +754,8 @@ MODULE_FIRMWARE(FIRMWARE_8168E_1);
 MODULE_FIRMWARE(FIRMWARE_8168E_2);
 MODULE_FIRMWARE(FIRMWARE_8168E_3);
 MODULE_FIRMWARE(FIRMWARE_8105E_1);
+MODULE_FIRMWARE(FIRMWARE_8168F_1);
+MODULE_FIRMWARE(FIRMWARE_8168F_2);
 
 static int rtl8169_open(struct net_device *dev);
 static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
@@ -732,6 +774,19 @@ static void rtl8169_down(struct net_device *dev);
 static void rtl8169_rx_clear(struct rtl8169_private *tp);
 static int rtl8169_poll(struct napi_struct *napi, int budget);
 
+static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force)
+{
+	int cap = pci_pcie_cap(pdev);
+
+	if (cap) {
+		u16 ctl;
+
+		pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl);
+		ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force;
+		pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl);
+	}
+}
+
 static u32 ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg)
 {
 	void __iomem *ioaddr = tp->mmio_addr;
@@ -1202,6 +1257,19 @@ static void rtl_link_chg_patch(struct rtl8169_private *tp)
 			     ERIAR_EXGMAC);
 		rtl_w1w0_eri(ioaddr, 0xdc, ERIAR_MASK_0001, 0x01, 0x00,
 			     ERIAR_EXGMAC);
+	} else if (tp->mac_version == RTL_GIGA_MAC_VER_35 ||
+		   tp->mac_version == RTL_GIGA_MAC_VER_36) {
+		if (RTL_R8(PHYstatus) & _1000bpsF) {
+			rtl_eri_write(ioaddr, 0x1bc, ERIAR_MASK_1111,
+				      0x00000011, ERIAR_EXGMAC);
+			rtl_eri_write(ioaddr, 0x1dc, ERIAR_MASK_1111,
+				      0x00000005, ERIAR_EXGMAC);
+		} else {
+			rtl_eri_write(ioaddr, 0x1bc, ERIAR_MASK_1111,
+				      0x0000001f, ERIAR_EXGMAC);
+			rtl_eri_write(ioaddr, 0x1dc, ERIAR_MASK_1111,
+				      0x0000003f, ERIAR_EXGMAC);
+		}
 	}
 }
 
@@ -1487,9 +1555,15 @@ static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 
 static u32 rtl8169_fix_features(struct net_device *dev, u32 features)
 {
+	struct rtl8169_private *tp = netdev_priv(dev);
+
 	if (dev->mtu > TD_MSS_MAX)
 		features &= ~NETIF_F_ALL_TSO;
 
+	if (dev->mtu > JUMBO_1K &&
+	    !rtl_chip_infos[tp->mac_version].jumbo_tx_csum)
+		features &= ~NETIF_F_IP_CSUM;
+
 	return features;
 }
 
@@ -1741,6 +1815,10 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp,
 		u32 val;
 		int mac_version;
 	} mac_info[] = {
+		/* 8168F family. */
+		{ 0x7cf00000, 0x48100000,	RTL_GIGA_MAC_VER_36 },
+		{ 0x7cf00000, 0x48000000,	RTL_GIGA_MAC_VER_35 },
+
 		/* 8168E family. */
 		{ 0x7c800000, 0x2c800000,	RTL_GIGA_MAC_VER_34 },
 		{ 0x7cf00000, 0x2c200000,	RTL_GIGA_MAC_VER_33 },
@@ -2875,6 +2953,97 @@ static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp)
 	rtl_writephy(tp, 0x1f, 0x0000);
 }
 
+static void rtl8168f_1_hw_phy_config(struct rtl8169_private *tp)
+{
+	static const struct phy_reg phy_reg_init[] = {
+		/* Channel estimation fine tune */
+		{ 0x1f, 0x0003 },
+		{ 0x09, 0xa20f },
+		{ 0x1f, 0x0000 },
+
+		/* Modify green table for giga & fnet */
+		{ 0x1f, 0x0005 },
+		{ 0x05, 0x8b55 },
+		{ 0x06, 0x0000 },
+		{ 0x05, 0x8b5e },
+		{ 0x06, 0x0000 },
+		{ 0x05, 0x8b67 },
+		{ 0x06, 0x0000 },
+		{ 0x05, 0x8b70 },
+		{ 0x06, 0x0000 },
+		{ 0x1f, 0x0000 },
+		{ 0x1f, 0x0007 },
+		{ 0x1e, 0x0078 },
+		{ 0x17, 0x0000 },
+		{ 0x19, 0x00fb },
+		{ 0x1f, 0x0000 },
+
+		/* Modify green table for 10M */
+		{ 0x1f, 0x0005 },
+		{ 0x05, 0x8b79 },
+		{ 0x06, 0xaa00 },
+		{ 0x1f, 0x0000 },
+
+		/* Disable hiimpedance detection (RTCT) */
+		{ 0x1f, 0x0003 },
+		{ 0x01, 0x328a },
+		{ 0x1f, 0x0000 }
+	};
+
+	rtl_apply_firmware(tp);
+
+	rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+
+	/* For 4-corner performance improve */
+	rtl_writephy(tp, 0x1f, 0x0005);
+	rtl_writephy(tp, 0x05, 0x8b80);
+	rtl_w1w0_phy(tp, 0x06, 0x0006, 0x0000);
+	rtl_writephy(tp, 0x1f, 0x0000);
+
+	/* PHY auto speed down */
+	rtl_writephy(tp, 0x1f, 0x0007);
+	rtl_writephy(tp, 0x1e, 0x002d);
+	rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000);
+	rtl_writephy(tp, 0x1f, 0x0000);
+	rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
+
+	/* Improve 10M EEE waveform */
+	rtl_writephy(tp, 0x1f, 0x0005);
+	rtl_writephy(tp, 0x05, 0x8b86);
+	rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
+	rtl_writephy(tp, 0x1f, 0x0000);
+
+	/* Improve 2-pair detection performance */
+	rtl_writephy(tp, 0x1f, 0x0005);
+	rtl_writephy(tp, 0x05, 0x8b85);
+	rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
+	rtl_writephy(tp, 0x1f, 0x0000);
+}
+
+static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp)
+{
+	rtl_apply_firmware(tp);
+
+	/* For 4-corner performance improve */
+	rtl_writephy(tp, 0x1f, 0x0005);
+	rtl_writephy(tp, 0x05, 0x8b80);
+	rtl_w1w0_phy(tp, 0x06, 0x0006, 0x0000);
+	rtl_writephy(tp, 0x1f, 0x0000);
+
+	/* PHY auto speed down */
+	rtl_writephy(tp, 0x1f, 0x0007);
+	rtl_writephy(tp, 0x1e, 0x002d);
+	rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000);
+	rtl_writephy(tp, 0x1f, 0x0000);
+	rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
+
+	/* Improve 10M EEE waveform */
+	rtl_writephy(tp, 0x1f, 0x0005);
+	rtl_writephy(tp, 0x05, 0x8b86);
+	rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
+	rtl_writephy(tp, 0x1f, 0x0000);
+}
+
 static void rtl8102e_hw_phy_config(struct rtl8169_private *tp)
 {
 	static const struct phy_reg phy_reg_init[] = {
@@ -2999,6 +3168,12 @@ static void rtl_hw_phy_config(struct net_device *dev)
 	case RTL_GIGA_MAC_VER_34:
 		rtl8168e_2_hw_phy_config(tp);
 		break;
+	case RTL_GIGA_MAC_VER_35:
+		rtl8168f_1_hw_phy_config(tp);
+		break;
+	case RTL_GIGA_MAC_VER_36:
+		rtl8168f_2_hw_phy_config(tp);
+		break;
 
 	default:
 		break;
@@ -3483,8 +3658,8 @@ static void r8168_pll_power_up(struct rtl8169_private *tp)
 	r8168_phy_power_up(tp);
 }
 
-static void rtl_pll_power_op(struct rtl8169_private *tp,
-			     void (*op)(struct rtl8169_private *))
+static void rtl_generic_op(struct rtl8169_private *tp,
+			   void (*op)(struct rtl8169_private *))
 {
 	if (op)
 		op(tp);
@@ -3492,12 +3667,12 @@ static void rtl_pll_power_op(struct rtl8169_private *tp,
 
 static void rtl_pll_power_down(struct rtl8169_private *tp)
 {
-	rtl_pll_power_op(tp, tp->pll_power_ops.down);
+	rtl_generic_op(tp, tp->pll_power_ops.down);
 }
 
 static void rtl_pll_power_up(struct rtl8169_private *tp)
 {
-	rtl_pll_power_op(tp, tp->pll_power_ops.up);
+	rtl_generic_op(tp, tp->pll_power_ops.up);
 }
 
 static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp)
@@ -3534,6 +3709,8 @@ static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp)
 	case RTL_GIGA_MAC_VER_32:
 	case RTL_GIGA_MAC_VER_33:
 	case RTL_GIGA_MAC_VER_34:
+	case RTL_GIGA_MAC_VER_35:
+	case RTL_GIGA_MAC_VER_36:
 		ops->down	= r8168_pll_power_down;
 		ops->up		= r8168_pll_power_up;
 		break;
@@ -3586,6 +3763,150 @@ static void rtl8169_init_ring_indexes(struct rtl8169_private *tp)
 	tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0;
 }
 
+static void rtl_hw_jumbo_enable(struct rtl8169_private *tp)
+{
+	rtl_generic_op(tp, tp->jumbo_ops.enable);
+}
+
+static void rtl_hw_jumbo_disable(struct rtl8169_private *tp)
+{
+	rtl_generic_op(tp, tp->jumbo_ops.disable);
+}
+
+static void r8168c_hw_jumbo_enable(struct rtl8169_private *tp)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+
+	RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
+	RTL_W8(Config4, RTL_R8(Config4) | Jumbo_En1);
+	rtl_tx_performance_tweak(tp->pci_dev, 0x2 << MAX_READ_REQUEST_SHIFT);
+}
+
+static void r8168c_hw_jumbo_disable(struct rtl8169_private *tp)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+
+	RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
+	RTL_W8(Config4, RTL_R8(Config4) & ~Jumbo_En1);
+	rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT);
+}
+
+static void r8168dp_hw_jumbo_enable(struct rtl8169_private *tp)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+
+	RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
+}
+
+static void r8168dp_hw_jumbo_disable(struct rtl8169_private *tp)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+
+	RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
+}
+
+static void r8168e_hw_jumbo_enable(struct rtl8169_private *tp)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+	struct pci_dev *pdev = tp->pci_dev;
+
+	RTL_W8(MaxTxPacketSize, 0x3f);
+	RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
+	RTL_W8(Config4, RTL_R8(Config4) | 0x01);
+	pci_write_config_byte(pdev, 0x79, 0x20);
+}
+
+static void r8168e_hw_jumbo_disable(struct rtl8169_private *tp)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+	struct pci_dev *pdev = tp->pci_dev;
+
+	RTL_W8(MaxTxPacketSize, 0x0c);
+	RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
+	RTL_W8(Config4, RTL_R8(Config4) & ~0x01);
+	pci_write_config_byte(pdev, 0x79, 0x50);
+}
+
+static void r8168b_0_hw_jumbo_enable(struct rtl8169_private *tp)
+{
+	rtl_tx_performance_tweak(tp->pci_dev,
+		(0x2 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
+}
+
+static void r8168b_0_hw_jumbo_disable(struct rtl8169_private *tp)
+{
+	rtl_tx_performance_tweak(tp->pci_dev,
+		(0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
+}
+
+static void r8168b_1_hw_jumbo_enable(struct rtl8169_private *tp)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+
+	r8168b_0_hw_jumbo_enable(tp);
+
+	RTL_W8(Config4, RTL_R8(Config4) | (1 << 0));
+}
+
+static void r8168b_1_hw_jumbo_disable(struct rtl8169_private *tp)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+
+	r8168b_0_hw_jumbo_disable(tp);
+
+	RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0));
+}
+
+static void __devinit rtl_init_jumbo_ops(struct rtl8169_private *tp)
+{
+	struct jumbo_ops *ops = &tp->jumbo_ops;
+
+	switch (tp->mac_version) {
+	case RTL_GIGA_MAC_VER_11:
+		ops->disable	= r8168b_0_hw_jumbo_disable;
+		ops->enable	= r8168b_0_hw_jumbo_enable;
+		break;
+	case RTL_GIGA_MAC_VER_12:
+	case RTL_GIGA_MAC_VER_17:
+		ops->disable	= r8168b_1_hw_jumbo_disable;
+		ops->enable	= r8168b_1_hw_jumbo_enable;
+		break;
+	case RTL_GIGA_MAC_VER_18: /* Wild guess. Needs info from Realtek. */
+	case RTL_GIGA_MAC_VER_19:
+	case RTL_GIGA_MAC_VER_20:
+	case RTL_GIGA_MAC_VER_21: /* Wild guess. Needs info from Realtek. */
+	case RTL_GIGA_MAC_VER_22:
+	case RTL_GIGA_MAC_VER_23:
+	case RTL_GIGA_MAC_VER_24:
+	case RTL_GIGA_MAC_VER_25:
+	case RTL_GIGA_MAC_VER_26:
+		ops->disable	= r8168c_hw_jumbo_disable;
+		ops->enable	= r8168c_hw_jumbo_enable;
+		break;
+	case RTL_GIGA_MAC_VER_27:
+	case RTL_GIGA_MAC_VER_28:
+		ops->disable	= r8168dp_hw_jumbo_disable;
+		ops->enable	= r8168dp_hw_jumbo_enable;
+		break;
+	case RTL_GIGA_MAC_VER_31: /* Wild guess. Needs info from Realtek. */
+	case RTL_GIGA_MAC_VER_32:
+	case RTL_GIGA_MAC_VER_33:
+	case RTL_GIGA_MAC_VER_34:
+		ops->disable	= r8168e_hw_jumbo_disable;
+		ops->enable	= r8168e_hw_jumbo_enable;
+		break;
+
+	/*
+	 * No action needed for jumbo frames with 8169.
+	 * No jumbo for 810x at all.
+	 */
+	default:
+		ops->disable	= NULL;
+		ops->enable	= NULL;
+		break;
+	}
+}
+
 static void rtl_hw_reset(struct rtl8169_private *tp)
 {
 	void __iomem *ioaddr = tp->mmio_addr;
@@ -3730,6 +4051,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	rtl_init_mdio_ops(tp);
 	rtl_init_pll_power_ops(tp);
+	rtl_init_jumbo_ops(tp);
 
 	rtl8169_print_mac_version(tp);
 
@@ -3813,6 +4135,12 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netif_info(tp, probe, dev, "%s at 0x%lx, %pM, XID %08x IRQ %d\n",
 		   rtl_chip_infos[chipset].name, dev->base_addr, dev->dev_addr,
 		   (u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), dev->irq);
+	if (rtl_chip_infos[chipset].jumbo_max != JUMBO_1K) {
+		netif_info(tp, probe, dev, "jumbo features [frames: %d bytes, "
+			   "tx checksumming: %s]\n",
+			   rtl_chip_infos[chipset].jumbo_max,
+			   rtl_chip_infos[chipset].jumbo_tx_csum ? "ok" : "ko");
+	}
 
 	if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
 	    tp->mac_version == RTL_GIGA_MAC_VER_28 ||
@@ -4008,7 +4336,9 @@ static void rtl8169_hw_reset(struct rtl8169_private *tp)
 	    tp->mac_version == RTL_GIGA_MAC_VER_31) {
 		while (RTL_R8(TxPoll) & NPQ)
 			udelay(20);
-	} else if (tp->mac_version == RTL_GIGA_MAC_VER_34) {
+	} else if (tp->mac_version == RTL_GIGA_MAC_VER_34 ||
+	           tp->mac_version == RTL_GIGA_MAC_VER_35 ||
+	           tp->mac_version == RTL_GIGA_MAC_VER_36) {
 		RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq);
 		while (!(RTL_R32(TxConfig) & TXCFG_EMPTY))
 			udelay(100);
@@ -4167,19 +4497,6 @@ static void rtl_hw_start_8169(struct net_device *dev)
 	RTL_W16(IntrMask, tp->intr_event);
 }
 
-static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force)
-{
-	int cap = pci_pcie_cap(pdev);
-
-	if (cap) {
-		u16 ctl;
-
-		pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl);
-		ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force;
-		pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl);
-	}
-}
-
 static void rtl_csi_access_enable(void __iomem *ioaddr, u32 bits)
 {
 	u32 csi;
@@ -4479,7 +4796,50 @@ static void rtl_hw_start_8168e_2(void __iomem *ioaddr, struct pci_dev *pdev)
 	rtl_w1w0_eri(ioaddr, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00,
 		     ERIAR_EXGMAC);
 
-	RTL_W8(MaxTxPacketSize, 0x27);
+	RTL_W8(MaxTxPacketSize, EarlySize);
+
+	rtl_disable_clock_request(pdev);
+
+	RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
+	RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
+
+	/* Adjust EEE LED frequency */
+	RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
+
+	RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
+	RTL_W32(MISC, RTL_R32(MISC) | PWM_EN);
+	RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
+}
+
+static void rtl_hw_start_8168f_1(void __iomem *ioaddr, struct pci_dev *pdev)
+{
+	static const struct ephy_info e_info_8168f_1[] = {
+		{ 0x06, 0x00c0,	0x0020 },
+		{ 0x08, 0x0001,	0x0002 },
+		{ 0x09, 0x0000,	0x0080 },
+		{ 0x19, 0x0000,	0x0224 }
+	};
+
+	rtl_csi_access_enable_1(ioaddr);
+
+	rtl_ephy_init(ioaddr, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1));
+
+	rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
+
+	rtl_eri_write(ioaddr, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
+	rtl_eri_write(ioaddr, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
+	rtl_eri_write(ioaddr, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC);
+	rtl_eri_write(ioaddr, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
+	rtl_w1w0_eri(ioaddr, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
+	rtl_w1w0_eri(ioaddr, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
+	rtl_w1w0_eri(ioaddr, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
+	rtl_w1w0_eri(ioaddr, 0x1d0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
+	rtl_eri_write(ioaddr, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC);
+	rtl_eri_write(ioaddr, 0xd0, ERIAR_MASK_1111, 0x00000060, ERIAR_EXGMAC);
+	rtl_w1w0_eri(ioaddr, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00,
+		     ERIAR_EXGMAC);
+
+	RTL_W8(MaxTxPacketSize, EarlySize);
 
 	rtl_disable_clock_request(pdev);
 
@@ -4588,6 +4948,11 @@ static void rtl_hw_start_8168(struct net_device *dev)
 		rtl_hw_start_8168e_2(ioaddr, pdev);
 		break;
 
+	case RTL_GIGA_MAC_VER_35:
+	case RTL_GIGA_MAC_VER_36:
+		rtl_hw_start_8168f_1(ioaddr, pdev);
+		break;
+
 	default:
 		printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n",
 			dev->name, tp->mac_version);
@@ -4759,9 +5124,17 @@ static void rtl_hw_start_8101(struct net_device *dev)
 
 static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
 {
-	if (new_mtu < ETH_ZLEN || new_mtu > SafeMtu)
+	struct rtl8169_private *tp = netdev_priv(dev);
+
+	if (new_mtu < ETH_ZLEN ||
+	    new_mtu > rtl_chip_infos[tp->mac_version].jumbo_max)
 		return -EINVAL;
 
+	if (new_mtu > ETH_DATA_LEN)
+		rtl_hw_jumbo_enable(tp);
+	else
+		rtl_hw_jumbo_disable(tp);
+
 	dev->mtu = new_mtu;
 	netdev_update_features(dev);
 
@@ -5356,7 +5729,7 @@ static int rtl8169_rx_interrupt(struct net_device *dev,
 		} else {
 			struct sk_buff *skb;
 			dma_addr_t addr = le64_to_cpu(desc->addr);
-			int pkt_size = (status & 0x00001FFF) - 4;
+			int pkt_size = (status & 0x00003fff) - 4;
 
 			/*
 			 * The driver does not support incoming fragmented
-- 
Ueimor

^ permalink raw reply related

* [PATCH next 1/4] r8169: define the early size for 8111evl
From: Francois Romieu @ 2011-09-22 21:03 UTC (permalink / raw)
  To: davem; +Cc: netdev, Realtek linux nic maintainers, Hayes Wang
In-Reply-To: <20110922210202.GA16362@electric-eye.fr.zoreil.com>

For RTL8111EVL, the register of MaxTxPacketSize doesn't acctually
limit the tx size. It influnces the feature of early tx.

Signed-off-by: Hayes Wang <hayeswang@realtek.com>
---
 drivers/net/ethernet/realtek/r8169.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index 6eb9f4e..44b40ea 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -311,6 +311,7 @@ enum rtl_registers {
 	MaxTxPacketSize	= 0xec,	/* 8101/8168. Unit of 128 bytes. */
 
 #define TxPacketMax	(8064 >> 7)
+#define EarlySize	0x27
 
 	FuncEvent	= 0xf0,
 	FuncEventMask	= 0xf4,
@@ -4479,7 +4480,7 @@ static void rtl_hw_start_8168e_2(void __iomem *ioaddr, struct pci_dev *pdev)
 	rtl_w1w0_eri(ioaddr, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00,
 		     ERIAR_EXGMAC);
 
-	RTL_W8(MaxTxPacketSize, 0x27);
+	RTL_W8(MaxTxPacketSize, EarlySize);
 
 	rtl_disable_clock_request(pdev);
 
-- 
1.7.6

^ permalink raw reply related

* [PATCH next 2/4] r8169: support new chips of RTL8111F
From: Francois Romieu @ 2011-09-22 21:03 UTC (permalink / raw)
  To: davem; +Cc: netdev, Realtek linux nic maintainers, Hayes Wang
In-Reply-To: <20110922210202.GA16362@electric-eye.fr.zoreil.com>

Support new chips of RTL8111F.

Signed-off-by: Hayes Wang <hayeswang@realtek.com>
---
 drivers/net/ethernet/realtek/r8169.c |  180 +++++++++++++++++++++++++++++++++-
 1 files changed, 178 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index 44b40ea..9a5965e 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -42,6 +42,8 @@
 #define FIRMWARE_8168E_1	"rtl_nic/rtl8168e-1.fw"
 #define FIRMWARE_8168E_2	"rtl_nic/rtl8168e-2.fw"
 #define FIRMWARE_8168E_3	"rtl_nic/rtl8168e-3.fw"
+#define FIRMWARE_8168F_1	"rtl_nic/rtl8168f-1.fw"
+#define FIRMWARE_8168F_2	"rtl_nic/rtl8168f-2.fw"
 #define FIRMWARE_8105E_1	"rtl_nic/rtl8105e-1.fw"
 
 #ifdef RTL8169_DEBUG
@@ -133,6 +135,8 @@ enum mac_version {
 	RTL_GIGA_MAC_VER_32,
 	RTL_GIGA_MAC_VER_33,
 	RTL_GIGA_MAC_VER_34,
+	RTL_GIGA_MAC_VER_35,
+	RTL_GIGA_MAC_VER_36,
 	RTL_GIGA_MAC_NONE   = 0xff,
 };
 
@@ -218,7 +222,11 @@ static const struct {
 	[RTL_GIGA_MAC_VER_33] =
 		_R("RTL8168e/8111e",	RTL_TD_1, FIRMWARE_8168E_2),
 	[RTL_GIGA_MAC_VER_34] =
-		_R("RTL8168evl/8111evl",RTL_TD_1, FIRMWARE_8168E_3)
+		_R("RTL8168evl/8111evl",RTL_TD_1, FIRMWARE_8168E_3),
+	[RTL_GIGA_MAC_VER_35] =
+		_R("RTL8168f/8111f",	RTL_TD_1, FIRMWARE_8168F_1),
+	[RTL_GIGA_MAC_VER_36] =
+		_R("RTL8168f/8111f",	RTL_TD_1, FIRMWARE_8168F_2)
 };
 #undef _R
 
@@ -715,6 +723,8 @@ MODULE_FIRMWARE(FIRMWARE_8168E_1);
 MODULE_FIRMWARE(FIRMWARE_8168E_2);
 MODULE_FIRMWARE(FIRMWARE_8168E_3);
 MODULE_FIRMWARE(FIRMWARE_8105E_1);
+MODULE_FIRMWARE(FIRMWARE_8168F_1);
+MODULE_FIRMWARE(FIRMWARE_8168F_2);
 
 static int rtl8169_open(struct net_device *dev);
 static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
@@ -1203,6 +1213,19 @@ static void rtl_link_chg_patch(struct rtl8169_private *tp)
 			     ERIAR_EXGMAC);
 		rtl_w1w0_eri(ioaddr, 0xdc, ERIAR_MASK_0001, 0x01, 0x00,
 			     ERIAR_EXGMAC);
+	} else if (tp->mac_version == RTL_GIGA_MAC_VER_35 ||
+		   tp->mac_version == RTL_GIGA_MAC_VER_36) {
+		if (RTL_R8(PHYstatus) & _1000bpsF) {
+			rtl_eri_write(ioaddr, 0x1bc, ERIAR_MASK_1111,
+				      0x00000011, ERIAR_EXGMAC);
+			rtl_eri_write(ioaddr, 0x1dc, ERIAR_MASK_1111,
+				      0x00000005, ERIAR_EXGMAC);
+		} else {
+			rtl_eri_write(ioaddr, 0x1bc, ERIAR_MASK_1111,
+				      0x0000001f, ERIAR_EXGMAC);
+			rtl_eri_write(ioaddr, 0x1dc, ERIAR_MASK_1111,
+				      0x0000003f, ERIAR_EXGMAC);
+		}
 	}
 }
 
@@ -1742,6 +1765,10 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp,
 		u32 val;
 		int mac_version;
 	} mac_info[] = {
+		/* 8168F family. */
+		{ 0x7cf00000, 0x48100000,	RTL_GIGA_MAC_VER_36 },
+		{ 0x7cf00000, 0x48000000,	RTL_GIGA_MAC_VER_35 },
+
 		/* 8168E family. */
 		{ 0x7c800000, 0x2c800000,	RTL_GIGA_MAC_VER_34 },
 		{ 0x7cf00000, 0x2c200000,	RTL_GIGA_MAC_VER_33 },
@@ -2876,6 +2903,97 @@ static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp)
 	rtl_writephy(tp, 0x1f, 0x0000);
 }
 
+static void rtl8168f_1_hw_phy_config(struct rtl8169_private *tp)
+{
+	static const struct phy_reg phy_reg_init[] = {
+		/* Channel estimation fine tune */
+		{ 0x1f, 0x0003 },
+		{ 0x09, 0xa20f },
+		{ 0x1f, 0x0000 },
+
+		/* Modify green table for giga & fnet */
+		{ 0x1f, 0x0005 },
+		{ 0x05, 0x8b55 },
+		{ 0x06, 0x0000 },
+		{ 0x05, 0x8b5e },
+		{ 0x06, 0x0000 },
+		{ 0x05, 0x8b67 },
+		{ 0x06, 0x0000 },
+		{ 0x05, 0x8b70 },
+		{ 0x06, 0x0000 },
+		{ 0x1f, 0x0000 },
+		{ 0x1f, 0x0007 },
+		{ 0x1e, 0x0078 },
+		{ 0x17, 0x0000 },
+		{ 0x19, 0x00fb },
+		{ 0x1f, 0x0000 },
+
+		/* Modify green table for 10M */
+		{ 0x1f, 0x0005 },
+		{ 0x05, 0x8b79 },
+		{ 0x06, 0xaa00 },
+		{ 0x1f, 0x0000 },
+
+		/* Disable hiimpedance detection (RTCT) */
+		{ 0x1f, 0x0003 },
+		{ 0x01, 0x328a },
+		{ 0x1f, 0x0000 }
+	};
+
+	rtl_apply_firmware(tp);
+
+	rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+
+	/* For 4-corner performance improve */
+	rtl_writephy(tp, 0x1f, 0x0005);
+	rtl_writephy(tp, 0x05, 0x8b80);
+	rtl_w1w0_phy(tp, 0x06, 0x0006, 0x0000);
+	rtl_writephy(tp, 0x1f, 0x0000);
+
+	/* PHY auto speed down */
+	rtl_writephy(tp, 0x1f, 0x0007);
+	rtl_writephy(tp, 0x1e, 0x002d);
+	rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000);
+	rtl_writephy(tp, 0x1f, 0x0000);
+	rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
+
+	/* Improve 10M EEE waveform */
+	rtl_writephy(tp, 0x1f, 0x0005);
+	rtl_writephy(tp, 0x05, 0x8b86);
+	rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
+	rtl_writephy(tp, 0x1f, 0x0000);
+
+	/* Improve 2-pair detection performance */
+	rtl_writephy(tp, 0x1f, 0x0005);
+	rtl_writephy(tp, 0x05, 0x8b85);
+	rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
+	rtl_writephy(tp, 0x1f, 0x0000);
+}
+
+static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp)
+{
+	rtl_apply_firmware(tp);
+
+	/* For 4-corner performance improve */
+	rtl_writephy(tp, 0x1f, 0x0005);
+	rtl_writephy(tp, 0x05, 0x8b80);
+	rtl_w1w0_phy(tp, 0x06, 0x0006, 0x0000);
+	rtl_writephy(tp, 0x1f, 0x0000);
+
+	/* PHY auto speed down */
+	rtl_writephy(tp, 0x1f, 0x0007);
+	rtl_writephy(tp, 0x1e, 0x002d);
+	rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000);
+	rtl_writephy(tp, 0x1f, 0x0000);
+	rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
+
+	/* Improve 10M EEE waveform */
+	rtl_writephy(tp, 0x1f, 0x0005);
+	rtl_writephy(tp, 0x05, 0x8b86);
+	rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
+	rtl_writephy(tp, 0x1f, 0x0000);
+}
+
 static void rtl8102e_hw_phy_config(struct rtl8169_private *tp)
 {
 	static const struct phy_reg phy_reg_init[] = {
@@ -3000,6 +3118,12 @@ static void rtl_hw_phy_config(struct net_device *dev)
 	case RTL_GIGA_MAC_VER_34:
 		rtl8168e_2_hw_phy_config(tp);
 		break;
+	case RTL_GIGA_MAC_VER_35:
+		rtl8168f_1_hw_phy_config(tp);
+		break;
+	case RTL_GIGA_MAC_VER_36:
+		rtl8168f_2_hw_phy_config(tp);
+		break;
 
 	default:
 		break;
@@ -3535,6 +3659,8 @@ static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp)
 	case RTL_GIGA_MAC_VER_32:
 	case RTL_GIGA_MAC_VER_33:
 	case RTL_GIGA_MAC_VER_34:
+	case RTL_GIGA_MAC_VER_35:
+	case RTL_GIGA_MAC_VER_36:
 		ops->down	= r8168_pll_power_down;
 		ops->up		= r8168_pll_power_up;
 		break;
@@ -4009,7 +4135,9 @@ static void rtl8169_hw_reset(struct rtl8169_private *tp)
 	    tp->mac_version == RTL_GIGA_MAC_VER_31) {
 		while (RTL_R8(TxPoll) & NPQ)
 			udelay(20);
-	} else if (tp->mac_version == RTL_GIGA_MAC_VER_34) {
+	} else if (tp->mac_version == RTL_GIGA_MAC_VER_34 ||
+	           tp->mac_version == RTL_GIGA_MAC_VER_35 ||
+	           tp->mac_version == RTL_GIGA_MAC_VER_36) {
 		RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq);
 		while (!(RTL_R32(TxConfig) & TXCFG_EMPTY))
 			udelay(100);
@@ -4495,6 +4623,49 @@ static void rtl_hw_start_8168e_2(void __iomem *ioaddr, struct pci_dev *pdev)
 	RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
 }
 
+static void rtl_hw_start_8168f_1(void __iomem *ioaddr, struct pci_dev *pdev)
+{
+	static const struct ephy_info e_info_8168f_1[] = {
+		{ 0x06, 0x00c0,	0x0020 },
+		{ 0x08, 0x0001,	0x0002 },
+		{ 0x09, 0x0000,	0x0080 },
+		{ 0x19, 0x0000,	0x0224 }
+	};
+
+	rtl_csi_access_enable_1(ioaddr);
+
+	rtl_ephy_init(ioaddr, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1));
+
+	rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
+
+	rtl_eri_write(ioaddr, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
+	rtl_eri_write(ioaddr, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
+	rtl_eri_write(ioaddr, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC);
+	rtl_eri_write(ioaddr, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
+	rtl_w1w0_eri(ioaddr, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
+	rtl_w1w0_eri(ioaddr, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
+	rtl_w1w0_eri(ioaddr, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
+	rtl_w1w0_eri(ioaddr, 0x1d0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
+	rtl_eri_write(ioaddr, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC);
+	rtl_eri_write(ioaddr, 0xd0, ERIAR_MASK_1111, 0x00000060, ERIAR_EXGMAC);
+	rtl_w1w0_eri(ioaddr, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00,
+		     ERIAR_EXGMAC);
+
+	RTL_W8(MaxTxPacketSize, EarlySize);
+
+	rtl_disable_clock_request(pdev);
+
+	RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
+	RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
+
+	/* Adjust EEE LED frequency */
+	RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
+
+	RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
+	RTL_W32(MISC, RTL_R32(MISC) | PWM_EN);
+	RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
+}
+
 static void rtl_hw_start_8168(struct net_device *dev)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
@@ -4589,6 +4760,11 @@ static void rtl_hw_start_8168(struct net_device *dev)
 		rtl_hw_start_8168e_2(ioaddr, pdev);
 		break;
 
+	case RTL_GIGA_MAC_VER_35:
+	case RTL_GIGA_MAC_VER_36:
+		rtl_hw_start_8168f_1(ioaddr, pdev);
+		break;
+
 	default:
 		printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n",
 			dev->name, tp->mac_version);
-- 
1.7.6

^ permalink raw reply related

* [PATCH next 3/4] r8169: expand received packet length indication.
From: Francois Romieu @ 2011-09-22 21:04 UTC (permalink / raw)
  To: davem; +Cc: netdev, Realtek linux nic maintainers, Hayes Wang
In-Reply-To: <20110922210202.GA16362@electric-eye.fr.zoreil.com>

8168d and above allow jumbo frames beyond 8k. Bump the received
packet length check before enabling jumbo frames on these chipsets.

Frame length indication covers bits 0..13 of the first Rx descriptor
32 bits for the 8169 and 8168. I only have authoritative documentation
for the allowed use of the extra (13) bit with the 8169 and 8168c.
Realtek's drivers use the same mask for the 816x and the fast ethernet
only 810x.

Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
---
 drivers/net/ethernet/realtek/r8169.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index 9a5965e..30bba23 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -5533,7 +5533,7 @@ static int rtl8169_rx_interrupt(struct net_device *dev,
 		} else {
 			struct sk_buff *skb;
 			dma_addr_t addr = le64_to_cpu(desc->addr);
-			int pkt_size = (status & 0x00001FFF) - 4;
+			int pkt_size = (status & 0x00003fff) - 4;
 
 			/*
 			 * The driver does not support incoming fragmented
-- 
1.7.6

^ permalink raw reply related

* [PATCH next 4/4] r8169: jumbo fixes.
From: Francois Romieu @ 2011-09-22 21:06 UTC (permalink / raw)
  To: davem; +Cc: netdev, Realtek linux nic maintainers, Hayes Wang
In-Reply-To: <20110922210202.GA16362@electric-eye.fr.zoreil.com>

- fix features : jumbo frames and checksumming can not be used at the
  same time.

- introduce hw_jumbo_{enable / disable} helpers. Their content has been
  creatively extracted from Realtek's own drivers. As an illustration,
  it would be nice to know how/if the MaxTxPacketSize register operates
  when the device can work with a 9k jumbo frame as its documentation
  (8168c) can not be applied beyond ~7k.

- rtl_tx_performance_tweak is moved forward. No change.

Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
---
 drivers/net/ethernet/realtek/r8169.c |  308 +++++++++++++++++++++++++++------
 1 files changed, 252 insertions(+), 56 deletions(-)

diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index 30bba23..2ce6070 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -145,88 +145,110 @@ enum rtl_tx_desc_version {
 	RTL_TD_1	= 1,
 };
 
-#define _R(NAME,TD,FW) \
-	{ .name = NAME, .txd_version = TD, .fw_name = FW }
+#define JUMBO_1K	ETH_DATA_LEN
+#define JUMBO_4K	(4*1024 - ETH_HLEN - 2)
+#define JUMBO_6K	(6*1024 - ETH_HLEN - 2)
+#define JUMBO_7K	(7*1024 - ETH_HLEN - 2)
+#define JUMBO_9K	(9*1024 - ETH_HLEN - 2)
+
+#define _R(NAME,TD,FW,SZ,B) {	\
+	.name = NAME,		\
+	.txd_version = TD,	\
+	.fw_name = FW,		\
+	.jumbo_max = SZ,	\
+	.jumbo_tx_csum = B	\
+}
 
 static const struct {
 	const char *name;
 	enum rtl_tx_desc_version txd_version;
 	const char *fw_name;
+	u16 jumbo_max;
+	bool jumbo_tx_csum;
 } rtl_chip_infos[] = {
 	/* PCI devices. */
 	[RTL_GIGA_MAC_VER_01] =
-		_R("RTL8169",		RTL_TD_0, NULL),
+		_R("RTL8169",		RTL_TD_0, NULL, JUMBO_7K, true),
 	[RTL_GIGA_MAC_VER_02] =
-		_R("RTL8169s",		RTL_TD_0, NULL),
+		_R("RTL8169s",		RTL_TD_0, NULL, JUMBO_7K, true),
 	[RTL_GIGA_MAC_VER_03] =
-		_R("RTL8110s",		RTL_TD_0, NULL),
+		_R("RTL8110s",		RTL_TD_0, NULL, JUMBO_7K, true),
 	[RTL_GIGA_MAC_VER_04] =
-		_R("RTL8169sb/8110sb",	RTL_TD_0, NULL),
+		_R("RTL8169sb/8110sb",	RTL_TD_0, NULL, JUMBO_7K, true),
 	[RTL_GIGA_MAC_VER_05] =
-		_R("RTL8169sc/8110sc",	RTL_TD_0, NULL),
+		_R("RTL8169sc/8110sc",	RTL_TD_0, NULL, JUMBO_7K, true),
 	[RTL_GIGA_MAC_VER_06] =
-		_R("RTL8169sc/8110sc",	RTL_TD_0, NULL),
+		_R("RTL8169sc/8110sc",	RTL_TD_0, NULL, JUMBO_7K, true),
 	/* PCI-E devices. */
 	[RTL_GIGA_MAC_VER_07] =
-		_R("RTL8102e",		RTL_TD_1, NULL),
+		_R("RTL8102e",		RTL_TD_1, NULL, JUMBO_1K, true),
 	[RTL_GIGA_MAC_VER_08] =
-		_R("RTL8102e",		RTL_TD_1, NULL),
+		_R("RTL8102e",		RTL_TD_1, NULL, JUMBO_1K, true),
 	[RTL_GIGA_MAC_VER_09] =
-		_R("RTL8102e",		RTL_TD_1, NULL),
+		_R("RTL8102e",		RTL_TD_1, NULL, JUMBO_1K, true),
 	[RTL_GIGA_MAC_VER_10] =
-		_R("RTL8101e",		RTL_TD_0, NULL),
+		_R("RTL8101e",		RTL_TD_0, NULL, JUMBO_1K, true),
 	[RTL_GIGA_MAC_VER_11] =
-		_R("RTL8168b/8111b",	RTL_TD_0, NULL),
+		_R("RTL8168b/8111b",	RTL_TD_0, NULL, JUMBO_4K, false),
 	[RTL_GIGA_MAC_VER_12] =
-		_R("RTL8168b/8111b",	RTL_TD_0, NULL),
+		_R("RTL8168b/8111b",	RTL_TD_0, NULL, JUMBO_4K, false),
 	[RTL_GIGA_MAC_VER_13] =
-		_R("RTL8101e",		RTL_TD_0, NULL),
+		_R("RTL8101e",		RTL_TD_0, NULL, JUMBO_1K, true),
 	[RTL_GIGA_MAC_VER_14] =
-		_R("RTL8100e",		RTL_TD_0, NULL),
+		_R("RTL8100e",		RTL_TD_0, NULL, JUMBO_1K, true),
 	[RTL_GIGA_MAC_VER_15] =
-		_R("RTL8100e",		RTL_TD_0, NULL),
+		_R("RTL8100e",		RTL_TD_0, NULL, JUMBO_1K, true),
 	[RTL_GIGA_MAC_VER_16] =
-		_R("RTL8101e",		RTL_TD_0, NULL),
+		_R("RTL8101e",		RTL_TD_0, NULL, JUMBO_1K, true),
 	[RTL_GIGA_MAC_VER_17] =
-		_R("RTL8168b/8111b",	RTL_TD_0, NULL),
+		_R("RTL8168b/8111b",	RTL_TD_1, NULL, JUMBO_4K, false),
 	[RTL_GIGA_MAC_VER_18] =
-		_R("RTL8168cp/8111cp",	RTL_TD_1, NULL),
+		_R("RTL8168cp/8111cp",	RTL_TD_1, NULL, JUMBO_6K, false),
 	[RTL_GIGA_MAC_VER_19] =
-		_R("RTL8168c/8111c",	RTL_TD_1, NULL),
+		_R("RTL8168c/8111c",	RTL_TD_1, NULL, JUMBO_6K, false),
 	[RTL_GIGA_MAC_VER_20] =
-		_R("RTL8168c/8111c",	RTL_TD_1, NULL),
+		_R("RTL8168c/8111c",	RTL_TD_1, NULL, JUMBO_6K, false),
 	[RTL_GIGA_MAC_VER_21] =
-		_R("RTL8168c/8111c",	RTL_TD_1, NULL),
+		_R("RTL8168c/8111c",	RTL_TD_1, NULL, JUMBO_6K, false),
 	[RTL_GIGA_MAC_VER_22] =
-		_R("RTL8168c/8111c",	RTL_TD_1, NULL),
+		_R("RTL8168c/8111c",	RTL_TD_1, NULL, JUMBO_6K, false),
 	[RTL_GIGA_MAC_VER_23] =
-		_R("RTL8168cp/8111cp",	RTL_TD_1, NULL),
+		_R("RTL8168cp/8111cp",	RTL_TD_1, NULL, JUMBO_6K, false),
 	[RTL_GIGA_MAC_VER_24] =
-		_R("RTL8168cp/8111cp",	RTL_TD_1, NULL),
+		_R("RTL8168cp/8111cp",	RTL_TD_1, NULL, JUMBO_6K, false),
 	[RTL_GIGA_MAC_VER_25] =
-		_R("RTL8168d/8111d",	RTL_TD_1, FIRMWARE_8168D_1),
+		_R("RTL8168d/8111d",	RTL_TD_1, FIRMWARE_8168D_1,
+							JUMBO_9K, false),
 	[RTL_GIGA_MAC_VER_26] =
-		_R("RTL8168d/8111d",	RTL_TD_1, FIRMWARE_8168D_2),
+		_R("RTL8168d/8111d",	RTL_TD_1, FIRMWARE_8168D_2,
+							JUMBO_9K, false),
 	[RTL_GIGA_MAC_VER_27] =
-		_R("RTL8168dp/8111dp",	RTL_TD_1, NULL),
+		_R("RTL8168dp/8111dp",	RTL_TD_1, NULL, JUMBO_9K, false),
 	[RTL_GIGA_MAC_VER_28] =
-		_R("RTL8168dp/8111dp",	RTL_TD_1, NULL),
+		_R("RTL8168dp/8111dp",	RTL_TD_1, NULL, JUMBO_9K, false),
 	[RTL_GIGA_MAC_VER_29] =
-		_R("RTL8105e",		RTL_TD_1, FIRMWARE_8105E_1),
+		_R("RTL8105e",		RTL_TD_1, FIRMWARE_8105E_1,
+							JUMBO_1K, true),
 	[RTL_GIGA_MAC_VER_30] =
-		_R("RTL8105e",		RTL_TD_1, FIRMWARE_8105E_1),
+		_R("RTL8105e",		RTL_TD_1, FIRMWARE_8105E_1,
+							JUMBO_1K, true),
 	[RTL_GIGA_MAC_VER_31] =
-		_R("RTL8168dp/8111dp",	RTL_TD_1, NULL),
+		_R("RTL8168dp/8111dp",	RTL_TD_1, NULL, JUMBO_9K, false),
 	[RTL_GIGA_MAC_VER_32] =
-		_R("RTL8168e/8111e",	RTL_TD_1, FIRMWARE_8168E_1),
+		_R("RTL8168e/8111e",	RTL_TD_1, FIRMWARE_8168E_1,
+							JUMBO_9K, false),
 	[RTL_GIGA_MAC_VER_33] =
-		_R("RTL8168e/8111e",	RTL_TD_1, FIRMWARE_8168E_2),
+		_R("RTL8168e/8111e",	RTL_TD_1, FIRMWARE_8168E_2,
+							JUMBO_9K, false),
 	[RTL_GIGA_MAC_VER_34] =
-		_R("RTL8168evl/8111evl",RTL_TD_1, FIRMWARE_8168E_3),
+		_R("RTL8168evl/8111evl",RTL_TD_1, FIRMWARE_8168E_3,
+							JUMBO_9K, false),
 	[RTL_GIGA_MAC_VER_35] =
-		_R("RTL8168f/8111f",	RTL_TD_1, FIRMWARE_8168F_1),
+		_R("RTL8168f/8111f",	RTL_TD_1, FIRMWARE_8168F_1,
+							JUMBO_9K, false),
 	[RTL_GIGA_MAC_VER_36] =
-		_R("RTL8168f/8111f",	RTL_TD_1, FIRMWARE_8168F_2)
+		_R("RTL8168f/8111f",	RTL_TD_1, FIRMWARE_8168F_2,
+							JUMBO_9K, false),
 };
 #undef _R
 
@@ -469,8 +491,12 @@ enum rtl_register_content {
 	/* Config3 register p.25 */
 	MagicPacket	= (1 << 5),	/* Wake up when receives a Magic Packet */
 	LinkUp		= (1 << 4),	/* Wake up when the cable connection is re-established */
+	Jumbo_En0	= (1 << 2),	/* 8168 only. Reserved in the 8168b */
 	Beacon_en	= (1 << 0),	/* 8168 only. Reserved in the 8168b */
 
+	/* Config4 register */
+	Jumbo_En1	= (1 << 1),	/* 8168 only. Reserved in the 8168b */
+
 	/* Config5 register p.27 */
 	BWF		= (1 << 6),	/* Accept Broadcast wakeup frame */
 	MWF		= (1 << 5),	/* Accept Multicast wakeup frame */
@@ -679,6 +705,11 @@ struct rtl8169_private {
 		void (*up)(struct rtl8169_private *);
 	} pll_power_ops;
 
+	struct jumbo_ops {
+		void (*enable)(struct rtl8169_private *);
+		void (*disable)(struct rtl8169_private *);
+	} jumbo_ops;
+
 	int (*set_speed)(struct net_device *, u8 aneg, u16 sp, u8 dpx, u32 adv);
 	int (*get_settings)(struct net_device *, struct ethtool_cmd *);
 	void (*phy_reset_enable)(struct rtl8169_private *tp);
@@ -743,6 +774,19 @@ static void rtl8169_down(struct net_device *dev);
 static void rtl8169_rx_clear(struct rtl8169_private *tp);
 static int rtl8169_poll(struct napi_struct *napi, int budget);
 
+static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force)
+{
+	int cap = pci_pcie_cap(pdev);
+
+	if (cap) {
+		u16 ctl;
+
+		pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl);
+		ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force;
+		pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl);
+	}
+}
+
 static u32 ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg)
 {
 	void __iomem *ioaddr = tp->mmio_addr;
@@ -1511,9 +1555,15 @@ static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 
 static u32 rtl8169_fix_features(struct net_device *dev, u32 features)
 {
+	struct rtl8169_private *tp = netdev_priv(dev);
+
 	if (dev->mtu > TD_MSS_MAX)
 		features &= ~NETIF_F_ALL_TSO;
 
+	if (dev->mtu > JUMBO_1K &&
+	    !rtl_chip_infos[tp->mac_version].jumbo_tx_csum)
+		features &= ~NETIF_F_IP_CSUM;
+
 	return features;
 }
 
@@ -3608,8 +3658,8 @@ static void r8168_pll_power_up(struct rtl8169_private *tp)
 	r8168_phy_power_up(tp);
 }
 
-static void rtl_pll_power_op(struct rtl8169_private *tp,
-			     void (*op)(struct rtl8169_private *))
+static void rtl_generic_op(struct rtl8169_private *tp,
+			   void (*op)(struct rtl8169_private *))
 {
 	if (op)
 		op(tp);
@@ -3617,12 +3667,12 @@ static void rtl_pll_power_op(struct rtl8169_private *tp,
 
 static void rtl_pll_power_down(struct rtl8169_private *tp)
 {
-	rtl_pll_power_op(tp, tp->pll_power_ops.down);
+	rtl_generic_op(tp, tp->pll_power_ops.down);
 }
 
 static void rtl_pll_power_up(struct rtl8169_private *tp)
 {
-	rtl_pll_power_op(tp, tp->pll_power_ops.up);
+	rtl_generic_op(tp, tp->pll_power_ops.up);
 }
 
 static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp)
@@ -3713,6 +3763,150 @@ static void rtl8169_init_ring_indexes(struct rtl8169_private *tp)
 	tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0;
 }
 
+static void rtl_hw_jumbo_enable(struct rtl8169_private *tp)
+{
+	rtl_generic_op(tp, tp->jumbo_ops.enable);
+}
+
+static void rtl_hw_jumbo_disable(struct rtl8169_private *tp)
+{
+	rtl_generic_op(tp, tp->jumbo_ops.disable);
+}
+
+static void r8168c_hw_jumbo_enable(struct rtl8169_private *tp)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+
+	RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
+	RTL_W8(Config4, RTL_R8(Config4) | Jumbo_En1);
+	rtl_tx_performance_tweak(tp->pci_dev, 0x2 << MAX_READ_REQUEST_SHIFT);
+}
+
+static void r8168c_hw_jumbo_disable(struct rtl8169_private *tp)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+
+	RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
+	RTL_W8(Config4, RTL_R8(Config4) & ~Jumbo_En1);
+	rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT);
+}
+
+static void r8168dp_hw_jumbo_enable(struct rtl8169_private *tp)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+
+	RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
+}
+
+static void r8168dp_hw_jumbo_disable(struct rtl8169_private *tp)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+
+	RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
+}
+
+static void r8168e_hw_jumbo_enable(struct rtl8169_private *tp)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+	struct pci_dev *pdev = tp->pci_dev;
+
+	RTL_W8(MaxTxPacketSize, 0x3f);
+	RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
+	RTL_W8(Config4, RTL_R8(Config4) | 0x01);
+	pci_write_config_byte(pdev, 0x79, 0x20);
+}
+
+static void r8168e_hw_jumbo_disable(struct rtl8169_private *tp)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+	struct pci_dev *pdev = tp->pci_dev;
+
+	RTL_W8(MaxTxPacketSize, 0x0c);
+	RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
+	RTL_W8(Config4, RTL_R8(Config4) & ~0x01);
+	pci_write_config_byte(pdev, 0x79, 0x50);
+}
+
+static void r8168b_0_hw_jumbo_enable(struct rtl8169_private *tp)
+{
+	rtl_tx_performance_tweak(tp->pci_dev,
+		(0x2 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
+}
+
+static void r8168b_0_hw_jumbo_disable(struct rtl8169_private *tp)
+{
+	rtl_tx_performance_tweak(tp->pci_dev,
+		(0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
+}
+
+static void r8168b_1_hw_jumbo_enable(struct rtl8169_private *tp)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+
+	r8168b_0_hw_jumbo_enable(tp);
+
+	RTL_W8(Config4, RTL_R8(Config4) | (1 << 0));
+}
+
+static void r8168b_1_hw_jumbo_disable(struct rtl8169_private *tp)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+
+	r8168b_0_hw_jumbo_disable(tp);
+
+	RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0));
+}
+
+static void __devinit rtl_init_jumbo_ops(struct rtl8169_private *tp)
+{
+	struct jumbo_ops *ops = &tp->jumbo_ops;
+
+	switch (tp->mac_version) {
+	case RTL_GIGA_MAC_VER_11:
+		ops->disable	= r8168b_0_hw_jumbo_disable;
+		ops->enable	= r8168b_0_hw_jumbo_enable;
+		break;
+	case RTL_GIGA_MAC_VER_12:
+	case RTL_GIGA_MAC_VER_17:
+		ops->disable	= r8168b_1_hw_jumbo_disable;
+		ops->enable	= r8168b_1_hw_jumbo_enable;
+		break;
+	case RTL_GIGA_MAC_VER_18: /* Wild guess. Needs info from Realtek. */
+	case RTL_GIGA_MAC_VER_19:
+	case RTL_GIGA_MAC_VER_20:
+	case RTL_GIGA_MAC_VER_21: /* Wild guess. Needs info from Realtek. */
+	case RTL_GIGA_MAC_VER_22:
+	case RTL_GIGA_MAC_VER_23:
+	case RTL_GIGA_MAC_VER_24:
+	case RTL_GIGA_MAC_VER_25:
+	case RTL_GIGA_MAC_VER_26:
+		ops->disable	= r8168c_hw_jumbo_disable;
+		ops->enable	= r8168c_hw_jumbo_enable;
+		break;
+	case RTL_GIGA_MAC_VER_27:
+	case RTL_GIGA_MAC_VER_28:
+		ops->disable	= r8168dp_hw_jumbo_disable;
+		ops->enable	= r8168dp_hw_jumbo_enable;
+		break;
+	case RTL_GIGA_MAC_VER_31: /* Wild guess. Needs info from Realtek. */
+	case RTL_GIGA_MAC_VER_32:
+	case RTL_GIGA_MAC_VER_33:
+	case RTL_GIGA_MAC_VER_34:
+		ops->disable	= r8168e_hw_jumbo_disable;
+		ops->enable	= r8168e_hw_jumbo_enable;
+		break;
+
+	/*
+	 * No action needed for jumbo frames with 8169.
+	 * No jumbo for 810x at all.
+	 */
+	default:
+		ops->disable	= NULL;
+		ops->enable	= NULL;
+		break;
+	}
+}
+
 static void rtl_hw_reset(struct rtl8169_private *tp)
 {
 	void __iomem *ioaddr = tp->mmio_addr;
@@ -3857,6 +4051,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	rtl_init_mdio_ops(tp);
 	rtl_init_pll_power_ops(tp);
+	rtl_init_jumbo_ops(tp);
 
 	rtl8169_print_mac_version(tp);
 
@@ -3940,6 +4135,12 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netif_info(tp, probe, dev, "%s at 0x%lx, %pM, XID %08x IRQ %d\n",
 		   rtl_chip_infos[chipset].name, dev->base_addr, dev->dev_addr,
 		   (u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), dev->irq);
+	if (rtl_chip_infos[chipset].jumbo_max != JUMBO_1K) {
+		netif_info(tp, probe, dev, "jumbo features [frames: %d bytes, "
+			   "tx checksumming: %s]\n",
+			   rtl_chip_infos[chipset].jumbo_max,
+			   rtl_chip_infos[chipset].jumbo_tx_csum ? "ok" : "ko");
+	}
 
 	if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
 	    tp->mac_version == RTL_GIGA_MAC_VER_28 ||
@@ -4296,19 +4497,6 @@ static void rtl_hw_start_8169(struct net_device *dev)
 	RTL_W16(IntrMask, tp->intr_event);
 }
 
-static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force)
-{
-	int cap = pci_pcie_cap(pdev);
-
-	if (cap) {
-		u16 ctl;
-
-		pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl);
-		ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force;
-		pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl);
-	}
-}
-
 static void rtl_csi_access_enable(void __iomem *ioaddr, u32 bits)
 {
 	u32 csi;
@@ -4936,9 +5124,17 @@ static void rtl_hw_start_8101(struct net_device *dev)
 
 static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
 {
-	if (new_mtu < ETH_ZLEN || new_mtu > SafeMtu)
+	struct rtl8169_private *tp = netdev_priv(dev);
+
+	if (new_mtu < ETH_ZLEN ||
+	    new_mtu > rtl_chip_infos[tp->mac_version].jumbo_max)
 		return -EINVAL;
 
+	if (new_mtu > ETH_DATA_LEN)
+		rtl_hw_jumbo_enable(tp);
+	else
+		rtl_hw_jumbo_disable(tp);
+
 	dev->mtu = new_mtu;
 	netdev_update_features(dev);
 
-- 
1.7.6

^ permalink raw reply related

* [RFC PATCH V2 1/2] net/core/ethtool: New Commands to Configure IOV features
From: Greg Rose @ 2011-09-22 21:35 UTC (permalink / raw)
  To: netdev

The only currently supported method of configuring the number of VFs
is through the max_vfs module parameter.  This method is inadequate to
support scenarios in which the user might wish to have varying numbers
of VFs per PF.  There is additional support for drivers that want to
partition some driver resources to additional net devices and for
configuring the number of Tx/Rx queue pairs per VF.

Signed-off-by: Greg Rose <gregory.v.rose@intel.com>
---

 include/linux/ethtool.h |   30 +++++++++++++++++++++++++++++-
 net/core/ethtool.c      |   38 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 67 insertions(+), 1 deletions(-)

diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 45f00b6..448730f 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -720,6 +720,27 @@ enum ethtool_sfeatures_retval_bits {
 #define ETHTOOL_F_WISH          (1 << ETHTOOL_F_WISH__BIT)
 #define ETHTOOL_F_COMPAT        (1 << ETHTOOL_F_COMPAT__BIT)
 
+enum ethtool_iov_modes {
+	ETHTOOL_IOV_MODE_NONE,
+	ETHTOOL_IOV_MODE_SRIOV,
+	ETHTOOL_IOV_MODE_NETDEVS,
+};
+
+#define	ETHTOOL_IOV_CMD_CONFIGURE_SRIOV		1
+#define	ETHTOOL_IOV_CMD_CONFIGURE_NETDEVS	2
+#define	ETHTOOL_IOV_CMD_CONFIGURE_VF_QUEUES	3
+
+struct ethtool_iov_set_cmd {
+	__u32 cmd;
+	__u32 set_cmd;
+	__u32 cmd_param;
+};
+
+struct ethtool_iov_get_cmd {
+	__u32 cmd;
+	__u32 mode;
+};
+
 #ifdef __KERNEL__
 
 #include <linux/rculist.h>
@@ -879,6 +900,8 @@ bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported);
  * 		   and flag of the device.
  * @get_dump_data: Get dump data.
  * @set_dump: Set dump specific flags to the device.
+ * @iov_set_cmd: Set IOV parameters - number of VFs or VM Queues
+ * @iov_get_cmd: Get current IOV parameters and configuration
  *
  * All operations are optional (i.e. the function pointer may be set
  * to %NULL) and callers must take this into account.  Callers must
@@ -956,7 +979,10 @@ struct ethtool_ops {
 	int	(*get_dump_data)(struct net_device *,
 				 struct ethtool_dump *, void *);
 	int	(*set_dump)(struct net_device *, struct ethtool_dump *);
-
+	int	(*iov_set_cmd)(struct net_device *,
+			struct ethtool_iov_set_cmd *);
+	int	(*iov_get_cmd)(struct net_device *,
+			struct ethtool_iov_get_cmd *);
 };
 #endif /* __KERNEL__ */
 
@@ -1030,6 +1056,8 @@ struct ethtool_ops {
 #define ETHTOOL_SET_DUMP	0x0000003e /* Set dump settings */
 #define ETHTOOL_GET_DUMP_FLAG	0x0000003f /* Get dump settings */
 #define ETHTOOL_GET_DUMP_DATA	0x00000040 /* Get dump data */
+#define ETHTOOL_IOV_SET_CMD	0x00000041 /* Set IOV parameters */
+#define ETHTOOL_IOV_GET_CMD	0x00000042 /* Get IOV parameters */
 
 /* compatibility with older code */
 #define SPARC_ETH_GSET		ETHTOOL_GSET
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index f444817..a469e40 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -1633,6 +1633,38 @@ out:
 	return ret;
 }
 
+static int ethtool_iov_set_command(struct net_device *dev,
+				  void __user *useraddr)
+{
+	struct ethtool_iov_set_cmd iov_cmd;
+
+	if (!dev->ethtool_ops->iov_set_cmd)
+		return -EOPNOTSUPP;
+	if (copy_from_user(&iov_cmd, useraddr, sizeof(iov_cmd)))
+		return -EFAULT;
+
+	return dev->ethtool_ops->iov_set_cmd(dev, &iov_cmd);
+}
+
+static int ethtool_iov_get_command(struct net_device *dev,
+				  void __user *useraddr)
+{
+	int ret;
+	struct ethtool_iov_get_cmd iov_cmd;
+
+	if (!dev->ethtool_ops->iov_get_cmd)
+		return -EOPNOTSUPP;
+	if (copy_from_user(&iov_cmd, useraddr, sizeof(iov_cmd)))
+		return -EFAULT;
+
+	ret = dev->ethtool_ops->iov_get_cmd(dev, &iov_cmd);
+	if (!ret)
+		ret = copy_to_user(useraddr, &iov_cmd, sizeof(iov_cmd));
+
+	return ret;
+}
+
+
 /* The main entry point in this file.  Called from net/core/dev.c */
 
 int dev_ethtool(struct net *net, struct ifreq *ifr)
@@ -1855,6 +1887,12 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
 	case ETHTOOL_GET_DUMP_DATA:
 		rc = ethtool_get_dump_data(dev, useraddr);
 		break;
+	case ETHTOOL_IOV_SET_CMD:
+		rc = ethtool_iov_set_command(dev, useraddr);
+		break;
+	case ETHTOOL_IOV_GET_CMD:
+		rc = ethtool_iov_get_command(dev, useraddr);
+		break;
 	default:
 		rc = -EOPNOTSUPP;
 	}

^ permalink raw reply related

* [RFC PATCH V2 2/2] ixgbe: Add support for new ethtool IOV configuration commands
From: Greg Rose @ 2011-09-22 21:35 UTC (permalink / raw)
  To: netdev
In-Reply-To: <20110922213522.26654.59301.stgit@gitlad.jf.intel.com>

Implement driver support for the new ethtool command to configure
the number of VFs per PF independently.  The framework is in place
for support of two other features that allow the user to partition
some of the I/O resources of the device to additional semi-independent
net devices and to set the number of queues per VF.

Signed-off-by: Greg Rose <gregory.v.rose@intel.com>
---

 drivers/net/ethernet/intel/ixgbe/ixgbe.h         |    1 
 drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c |  110 ++++++++++++++++++++++
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c    |    3 +
 3 files changed, 113 insertions(+), 1 deletions(-)

diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index 8fab322..cea2323 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -528,6 +528,7 @@ struct ixgbe_adapter {
 	int fdir_filter_count;
 	u32 timer_event_accumulator;
 	u32 vferr_refcount;
+	const struct ixgbe_info *saved_ii;
 };
 
 struct ixgbe_fdir_filter {
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
index 08c9994..c695362 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
@@ -38,7 +38,7 @@
 #include <linux/uaccess.h>
 
 #include "ixgbe.h"
-
+#include "ixgbe_sriov.h"
 
 #define IXGBE_ALL_RAR_ENTRIES 16
 
@@ -2577,6 +2577,112 @@ static int ixgbe_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
 	return ret;
 }
 
+static int ixgbe_reinit_sriov(struct net_device *netdev, int new_vfs)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	struct pci_dev *pdev = adapter->pdev;
+	int err;
+	int i;
+
+	if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) {
+		if (ixgbe_check_vf_assignment(adapter)) {
+			netdev_warn(netdev, "%s ",
+				    "reconfigure of SR-IOV VFs "
+				    "not supported while VFs are "
+				    "assigned to guest VMs\n");
+			return -EBUSY;
+		}
+	}
+	if (netif_running(netdev)) {
+		netdev_warn(netdev, "%s",
+			    "Cannot reconfigure SR-IOV "
+			    "while interface is up\n"
+			    "Please bring the interface "
+			    "down first\n");
+		 return -EBUSY;
+	}
+
+	ixgbe_clear_interrupt_scheme(adapter);
+
+	if (adapter->num_vfs)
+		ixgbe_disable_sriov(adapter);
+
+	adapter->num_vfs = (new_vfs > 63) ? 63 : new_vfs;
+
+	if (adapter->num_vfs) {
+		ixgbe_enable_sriov(adapter, adapter->saved_ii);
+		for (i = 0; i < adapter->num_vfs; i++)
+			ixgbe_vf_configuration(pdev, (i | 0x10000000));
+	}
+
+	if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) {
+		adapter->flags &= ~(IXGBE_FLAG_RSS_ENABLED |
+				    IXGBE_FLAG_DCB_ENABLED);
+		netdev->features &= ~NETIF_F_RXHASH;
+	} else {
+		adapter->flags |= IXGBE_FLAG_RSS_ENABLED;
+		netdev->features |= NETIF_F_RXHASH;
+	}
+
+	err = ixgbe_init_interrupt_scheme(adapter);
+	/*
+	 * If we can't init some sort of interrupt scheme then the device
+	 * is hosed - just print a warning and bail.  Nothing will work
+	 * but at least we've put a message in the system log telling why.
+	 */
+	if (err)
+		e_dev_err("Cannot initialize interrupts for device\n");
+	else
+		ixgbe_reset(adapter);
+
+	return err;
+}
+
+static int ixgbe_iov_set_cmd(struct net_device *dev,
+			     struct ethtool_iov_set_cmd *iov_cmd)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(dev);
+	struct ixgbe_hw *hw = &adapter->hw;
+	int err = 0;
+
+	if (iov_cmd->set_cmd == ETHTOOL_IOV_CMD_CONFIGURE_SRIOV &&
+	    hw->mac.type == ixgbe_mac_82598EB)
+		return -EOPNOTSUPP;
+
+	switch (iov_cmd->set_cmd) {
+	case ETHTOOL_IOV_CMD_CONFIGURE_SRIOV:
+		if (iov_cmd->cmd_param != adapter->num_vfs &&
+		    !(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
+			err = ixgbe_reinit_sriov(dev, iov_cmd->cmd_param);
+		else
+			err = -EINVAL;
+		break;
+	case ETHTOOL_IOV_CMD_CONFIGURE_NETDEVS:
+		err = -ENOTSUPP;
+		break;
+	case ETHTOOL_IOV_CMD_CONFIGURE_VF_QUEUES:
+		err = -ENOTSUPP;
+		break;
+	default:
+		err = -EINVAL;
+		break;
+	}
+
+	return err;
+}
+
+static int ixgbe_iov_get_cmd(struct net_device *dev,
+			     struct ethtool_iov_get_cmd *iov_cmd)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(dev);
+
+	iov_cmd->mode = ETHTOOL_IOV_MODE_NONE;
+	if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
+		iov_cmd->mode = ETHTOOL_IOV_MODE_SRIOV;
+
+	return 0;
+}
+
 static const struct ethtool_ops ixgbe_ethtool_ops = {
 	.get_settings           = ixgbe_get_settings,
 	.set_settings           = ixgbe_set_settings,
@@ -2605,6 +2711,8 @@ static const struct ethtool_ops ixgbe_ethtool_ops = {
 	.set_coalesce           = ixgbe_set_coalesce,
 	.get_rxnfc		= ixgbe_get_rxnfc,
 	.set_rxnfc		= ixgbe_set_rxnfc,
+	.iov_set_cmd		= ixgbe_iov_set_cmd,
+	.iov_get_cmd		= ixgbe_iov_get_cmd,
 };
 
 void ixgbe_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 99ff8b2..546f3ba 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -7591,6 +7591,9 @@ static void __devinit ixgbe_probe_vf(struct ixgbe_adapter *adapter,
 	if (hw->mac.type == ixgbe_mac_82598EB)
 		return;
 
+	/* need to save this away in case SR-IOV is reconfigured */
+	adapter->saved_ii = ii;
+
 	/* The 82599 supports up to 64 VFs per physical function
 	 * but this implementation limits allocation to 63 so that
 	 * basic networking resources are still available to the

^ permalink raw reply related

* [RFC PATCH V2] ethtool:  Add command to configure IOV features
From: Greg Rose @ 2011-09-22 21:35 UTC (permalink / raw)
  To: netdev

New command to allow configuration of IOV features such as the number of
Virtual Functions to allocate for a given Physical Function interface,
the number of semi-independent net devices to allocate from partitioned
I/O resources in the PF and to set the number of queues per VF.

Signed-off-by: Greg Rose <gregory.v.rose@intel.com>
---

 ethtool.c |   94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 93 insertions(+), 1 deletions(-)

diff --git a/ethtool.c b/ethtool.c
index 35c3733..1ebf6f3 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -99,6 +99,8 @@ static int do_flash(int fd, struct ifreq *ifr);
 static int do_permaddr(int fd, struct ifreq *ifr);
 static int do_getfwdump(int fd, struct ifreq *ifr);
 static int do_setfwdump(int fd, struct ifreq *ifr);
+static int do_get_iov(int fd, struct ifreq *ifr);
+static int do_set_iov(int fd, struct ifreq *ifr);
 
 static int send_ioctl(int fd, struct ifreq *ifr);
 
@@ -133,6 +135,8 @@ static enum {
 	MODE_PERMADDR,
 	MODE_SET_DUMP,
 	MODE_GET_DUMP,
+	MODE_GET_IOV,
+	MODE_SET_IOV,
 } mode = MODE_GSET;
 
 static struct option {
@@ -266,6 +270,8 @@ static struct option {
     { "-W", "--set-dump", MODE_SET_DUMP,
 		"Set dump flag of the device",
 		"		N\n"},
+    { "-v", "--get-iov", MODE_GET_IOV, "Get IOV parameters", "\n" },
+    { "-V", "--set_iov", MODE_SET_IOV, "Set IOV parameters", "[ N ]\n" },
     { "-h", "--help", MODE_HELP, "Show this help" },
     { NULL, "--version", MODE_VERSION, "Show version number" },
     {}
@@ -392,6 +398,10 @@ static char **rxfhindir_weight = NULL;
 static char *flash_file = NULL;
 static int flash = -1;
 static int flash_region = -1;
+static int iov_changed = 0;
+static int iov_numvfs_wanted = -1;
+static int iov_numnetdevs_wanted = -1;
+static int iov_numvqueues_wanted = -1;
 
 static int msglvl_changed;
 static u32 msglvl_wanted = 0;
@@ -549,6 +559,12 @@ static struct cmdline_info cmdline_msglvl[] = {
 	  NETIF_MSG_WOL, &msglvl_mask },
 };
 
+static struct cmdline_info cmdline_iov[] = {
+	{ "vfs", CMDL_S32, &iov_numvfs_wanted, NULL },
+	{ "netdevs", CMDL_S32, &iov_numnetdevs_wanted, NULL },
+	{ "vqueues", CMDL_S32, &iov_numvqueues_wanted, NULL },
+};
+
 static long long
 get_int_range(char *str, int base, long long min, long long max)
 {
@@ -792,7 +808,9 @@ static void parse_cmdline(int argc, char **argp)
 			    (mode == MODE_FLASHDEV) ||
 			    (mode == MODE_PERMADDR) ||
 			    (mode == MODE_SET_DUMP) ||
-			    (mode == MODE_GET_DUMP)) {
+			    (mode == MODE_GET_DUMP) ||
+			    (mode == MODE_GET_IOV) ||
+			    (mode == MODE_SET_IOV)) {
 				devname = argp[i];
 				break;
 			}
@@ -1007,6 +1025,14 @@ static void parse_cmdline(int argc, char **argp)
 				i = argc;
 				break;
 			}
+			if (mode == MODE_SET_IOV) {
+				parse_generic_cmdline(argc, argp, i,
+					&iov_changed,
+					cmdline_iov,
+					ARRAY_SIZE(cmdline_iov));
+				i = argc;
+				break;
+			}
 			if (mode != MODE_SSET)
 				exit_bad_args();
 			if (!strcmp(argp[i], "speed")) {
@@ -1949,6 +1975,10 @@ static int doit(void)
 		return do_getfwdump(fd, &ifr);
 	} else if (mode == MODE_SET_DUMP) {
 		return do_setfwdump(fd, &ifr);
+	} else if (mode == MODE_GET_IOV) {
+		return do_get_iov(fd, &ifr);
+	} else if (mode == MODE_SET_IOV) {
+		return do_set_iov(fd, &ifr);
 	}
 
 	return 69;
@@ -3338,6 +3368,68 @@ static int do_setfwdump(int fd, struct ifreq *ifr)
 	return 0;
 }
 
+static int do_get_iov(int fd, struct ifreq *ifr)
+{
+	int err;
+	struct ethtool_iov_get_cmd iov_cmd;
+
+	iov_cmd.cmd = ETHTOOL_IOV_GET_CMD;
+	ifr->ifr_data = (caddr_t)&iov_cmd;
+	err = send_ioctl(fd, ifr);
+	if (err < 0) {
+		perror("Can not get current IOV mode\n");
+		return 1;
+	}
+
+	memcpy(&iov_cmd, ifr->ifr_data, sizeof(iov_cmd));
+
+	switch(iov_cmd.mode) {
+	case ETHTOOL_IOV_MODE_SRIOV:
+		printf("Device %s is configured for SR-IOV mode\n", devname);
+		break;
+	case ETHTOOL_IOV_MODE_VM_QUEUES:
+		printf("Device %s is configured for VM Queues mode\n", devname);
+		break;
+	case ETHTOOL_IOV_MODE_NONE:
+	default:
+		printf("Device %s is not configured for IO Virtualization\n",
+				devname);
+		break;
+	}
+
+	return 0;
+}
+
+static int do_set_iov(int fd, struct ifreq *ifr)
+{
+	int err;
+	struct ethtool_iov_set_cmd iov_cmd;
+
+	if (iov_changed) {
+		iov_cmd.cmd = ETHTOOL_IOV_SET_CMD;
+		if (iov_numvfs_wanted >= 0) {
+			iov_cmd.set_cmd = ETHTOOL_IOV_CMD_CONFIGURE_SRIOV;
+			iov_cmd.cmd_param = iov_numvfs_wanted;
+		} else if (iov_numnetdevs_wanted >= 0) {
+			iov_cmd.set_cmd = ETHTOOL_IOV_CMD_CONFIGURE_NETDEVS;
+			iov_cmd.cmd_param = iov_numnetdevs_wanted;
+		} else if (iov_numvqueues_wanted >= 0) {
+			iov_cmd.set_cmd = ETHTOOL_IOV_CMD_CONFIGURE_VF_QUEUES;
+			iov_cmd.cmd_param = iov_numvqueues_wanted;
+		} else {
+			return -EINVAL;
+		}
+		ifr->ifr_data = (caddr_t)&iov_cmd;
+		err = send_ioctl(fd, ifr);
+		if (err < 0) {
+			perror("Can not set new IOV mode\n");
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
 static int send_ioctl(int fd, struct ifreq *ifr)
 {
 	return ioctl(fd, SIOCETHTOOL, ifr);

^ permalink raw reply related

* Re: [PATCH v3 6/7] tcp buffer limitation: per-cgroup limit
From: Balbir Singh @ 2011-09-22 23:08 UTC (permalink / raw)
  To: Glauber Costa
  Cc: linux-kernel, paul, lizf, kamezawa.hiroyu, ebiederm, davem,
	gthelen, netdev, linux-mm, kirill
In-Reply-To: <1316393805-3005-7-git-send-email-glommer@parallels.com>

On Mon, Sep 19, 2011 at 6:26 AM, Glauber Costa <glommer@parallels.com> wrote:
> This patch uses the "tcp_max_mem" field of the kmem_cgroup to
> effectively control the amount of kernel memory pinned by a cgroup.
>
> We have to make sure that none of the memory pressure thresholds
> specified in the namespace are bigger than the current 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 +
>  include/linux/memcontrol.h       |   10 ++++
>  mm/memcontrol.c                  |   89 +++++++++++++++++++++++++++++++++++---
>  net/ipv4/sysctl_net_ipv4.c       |   20 ++++++++
>  4 files changed, 113 insertions(+), 7 deletions(-)
>
> diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt
> index 6f1954a..1ffde3e 100644
> --- a/Documentation/cgroups/memory.txt
> +++ b/Documentation/cgroups/memory.txt
> @@ -78,6 +78,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.max_memory      # set/show hard limit for tcp buf memory
>
>  1. History
>
> diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
> index 6b8c0c0..2df6db8 100644
> --- a/include/linux/memcontrol.h
> +++ b/include/linux/memcontrol.h
> @@ -416,6 +416,9 @@ int tcp_init_cgroup_fill(struct proto *prot, struct cgroup *cgrp,
>                         struct cgroup_subsys *ss);
>  void tcp_destroy_cgroup(struct proto *prot, struct cgroup *cgrp,
>                        struct cgroup_subsys *ss);
> +
> +unsigned long tcp_max_memory(struct mem_cgroup *cg);
> +void tcp_prot_mem(struct mem_cgroup *cg, long val, int idx);
>  #else
>  /* memcontrol includes sockets.h, that includes memcontrol.h ... */
>  static inline void memcg_sock_mem_alloc(struct mem_cgroup *mem,
> @@ -441,6 +444,13 @@ static inline void sock_update_memcg(struct sock *sk)
>  static inline void sock_release_memcg(struct sock *sk)
>  {
>  }
> +static inline unsigned long tcp_max_memory(struct mem_cgroup *cg)
> +{
> +       return 0;
> +}
> +static inline void tcp_prot_mem(struct mem_cgroup *cg, long val, int idx)
> +{
> +}
>  #endif /* CONFIG_CGROUP_MEM_RES_CTLR_KMEM */
>  #endif /* CONFIG_INET */
>  #endif /* _LINUX_MEMCONTROL_H */
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index 5e9b2c7..be5ab89 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -345,6 +345,7 @@ struct mem_cgroup {
>        spinlock_t pcp_counter_lock;
>
>        /* per-cgroup tcp memory pressure knobs */
> +       int tcp_max_memory;

Aren't we better of abstracting this in a different structure?
Including all the tcp parameters in that abstraction and adding that
structure here?

>        atomic_long_t tcp_memory_allocated;
>        struct percpu_counter tcp_sockets_allocated;
>        /* those two are read-mostly, leave them at the end */
> @@ -352,6 +353,11 @@ struct mem_cgroup {
>        int tcp_memory_pressure;
>  };
>
> +static inline bool mem_cgroup_is_root(struct mem_cgroup *mem)
> +{
> +       return (mem == root_mem_cgroup);
> +}
> +
>  static struct mem_cgroup *parent_mem_cgroup(struct mem_cgroup *mem);
>  /* Writing them here to avoid exposing memcg's inner layout */
>  #ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
> @@ -466,6 +472,56 @@ struct percpu_counter *sockets_allocated_tcp(struct mem_cgroup *sg)
>        return &sg->tcp_sockets_allocated;
>  }
>
> +static int tcp_write_maxmem(struct cgroup *cgrp, struct cftype *cft, u64 val)
> +{
> +       struct mem_cgroup *sg = mem_cgroup_from_cont(cgrp);

sg, I'd prefer memcg, does sg stand for socket group?

> +       struct mem_cgroup *parent = parent_mem_cgroup(sg);
> +       struct net *net = current->nsproxy->net_ns;
> +       int i;
> +
> +       if (!cgroup_lock_live_group(cgrp))
> +               return -ENODEV;
> +
> +       /*
> +        * We can't allow more memory than our parents. Since this
> +        * will be tested for all calls, by induction, there is no need
> +        * to test any parent other than our own
> +        * */
> +       if (parent && (val > parent->tcp_max_memory))
> +               val = parent->tcp_max_memory;
> +
> +       sg->tcp_max_memory = val;
> +
> +       for (i = 0; i < 3; i++)
> +               sg->tcp_prot_mem[i]  = min_t(long, val,
> +                                            net->ipv4.sysctl_tcp_mem[i]);
> +
> +       cgroup_unlock();
> +
> +       return 0;
> +}
> +
> +static u64 tcp_read_maxmem(struct cgroup *cgrp, struct cftype *cft)
> +{
> +       struct mem_cgroup *sg = mem_cgroup_from_cont(cgrp);

sg? We generally use memcg as a convention

> +       u64 ret;
> +
> +       if (!cgroup_lock_live_group(cgrp))
> +               return -ENODEV;
> +       ret = sg->tcp_max_memory;
> +
> +       cgroup_unlock();
> +       return ret;
> +}
> +
> +static struct cftype tcp_files[] = {
> +       {
> +               .name = "kmem.tcp.max_memory",
> +               .write_u64 = tcp_write_maxmem,
> +               .read_u64 = tcp_read_maxmem,
> +       },
> +};
> +
>  /*
>  * For ipv6, we only need to fill in the function pointers (can't initialize
>  * things twice). So keep it separated
> @@ -487,8 +543,10 @@ int tcp_init_cgroup(struct proto *prot, struct cgroup *cgrp,
>                    struct cgroup_subsys *ss)
>  {
>        struct mem_cgroup *cg = mem_cgroup_from_cont(cgrp);
> +       struct mem_cgroup *parent = parent_mem_cgroup(cg);
>        unsigned long limit;
>        struct net *net = current->nsproxy->net_ns;
> +       int ret = 0;
>
>        cg->tcp_memory_pressure = 0;
>        atomic_long_set(&cg->tcp_memory_allocated, 0);
> @@ -497,12 +555,25 @@ int tcp_init_cgroup(struct proto *prot, struct cgroup *cgrp,
>        limit = nr_free_buffer_pages() / 8;
>        limit = max(limit, 128UL);
>
> +       if (parent)
> +               cg->tcp_max_memory = parent->tcp_max_memory;
> +       else
> +               cg->tcp_max_memory = limit * 2;
> +
>        cg->tcp_prot_mem[0] = net->ipv4.sysctl_tcp_mem[0];
>        cg->tcp_prot_mem[1] = net->ipv4.sysctl_tcp_mem[1];
>        cg->tcp_prot_mem[2] = net->ipv4.sysctl_tcp_mem[2];
>
>        tcp_init_cgroup_fill(prot, cgrp, ss);
> -       return 0;
> +       /*
> +        * For non-root cgroup, we need to set up all tcp-related variables,
> +        * but to be consistent with the rest of kmem management, we don't
> +        * expose any of the controls
> +        */
> +       if (!mem_cgroup_is_root(cg))
> +               ret = cgroup_add_files(cgrp, ss, tcp_files,
> +                                      ARRAY_SIZE(tcp_files));
> +       return ret;
>  }
>  EXPORT_SYMBOL(tcp_init_cgroup);
>
> @@ -514,6 +585,16 @@ void tcp_destroy_cgroup(struct proto *prot, struct cgroup *cgrp,
>        percpu_counter_destroy(&cg->tcp_sockets_allocated);
>  }
>  EXPORT_SYMBOL(tcp_destroy_cgroup);
> +
> +unsigned long tcp_max_memory(struct mem_cgroup *cg)
> +{
> +       return cg->tcp_max_memory;
> +}
> +
> +void tcp_prot_mem(struct mem_cgroup *cg, long val, int idx)
> +{
> +       cg->tcp_prot_mem[idx] = val;
> +}
>  #endif /* CONFIG_INET */
>  #endif /* CONFIG_CGROUP_MEM_RES_CTLR_KMEM */
>
> @@ -1092,12 +1173,6 @@ static struct mem_cgroup *mem_cgroup_get_next(struct mem_cgroup *iter,
>  #define for_each_mem_cgroup_all(iter) \
>        for_each_mem_cgroup_tree_cond(iter, NULL, true)
>
> -
> -static inline bool mem_cgroup_is_root(struct mem_cgroup *mem)
> -{
> -       return (mem == root_mem_cgroup);
> -}
> -
>  void mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx)
>  {
>        struct mem_cgroup *mem;
> diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
> index bbd67ab..cdc35f6 100644
> --- a/net/ipv4/sysctl_net_ipv4.c
> +++ b/net/ipv4/sysctl_net_ipv4.c
> @@ -14,6 +14,7 @@
>  #include <linux/init.h>
>  #include <linux/slab.h>
>  #include <linux/nsproxy.h>
> +#include <linux/memcontrol.h>
>  #include <linux/swap.h>
>  #include <net/snmp.h>
>  #include <net/icmp.h>
> @@ -182,6 +183,10 @@ static int ipv4_tcp_mem(ctl_table *ctl, int write,
>        int ret;
>        unsigned long vec[3];
>        struct net *net = current->nsproxy->net_ns;
> +#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
> +       int i;
> +       struct mem_cgroup *cg;
> +#endif
>
>        ctl_table tmp = {
>                .data = &vec,
> @@ -198,6 +203,21 @@ static int ipv4_tcp_mem(ctl_table *ctl, int write,
>        if (ret)
>                return ret;
>
> +#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
> +       rcu_read_lock();
> +       cg = mem_cgroup_from_task(current);
> +       for (i = 0; i < 3; i++)
> +               if (vec[i] > tcp_max_memory(cg)) {
> +                       rcu_read_unlock();
> +                       return -EINVAL;
> +               }
> +
> +       tcp_prot_mem(cg, vec[0], 0);
> +       tcp_prot_mem(cg, vec[1], 1);
> +       tcp_prot_mem(cg, vec[2], 2);
> +       rcu_read_unlock();
> +#endif
> +
>        net->ipv4.sysctl_tcp_mem[0] = vec[0];
>        net->ipv4.sysctl_tcp_mem[1] = vec[1];
>        net->ipv4.sysctl_tcp_mem[2] = vec[2];

Balbir Singh

--
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

* [PATCH] net: change capability used by socket options IP{,V6}_TRANSPARENT
From: Maciej Żenczykowski @ 2011-09-22 23:29 UTC (permalink / raw)
  To: Maciej Żenczykowski
  Cc: netdev, linux-security-module, James Morris,
	Maciej Żenczykowski
In-Reply-To: <1315927629.5851.4.camel@bzorp>

From: Maciej Żenczykowski <maze@google.com>

Up till now the IP{,V6}_TRANSPARENT socket options (which actually set
the same bit in the socket struct) have required CAP_NET_ADMIN
privileges to set or clear the option.

- we make clearing the bit not require any privileges.
- we deprecate using CAP_NET_ADMIN for this purpose.
- we introduce a new capability CAP_NET_TRANSPARENT,
  which is tailored to allow setting just this bit.
- we allow either one of CAP_NET_TRANSPARENT or CAP_NET_RAW
  to set this bit, because raw sockets already effectively
  allow you to emulate socket transparency, and make the
  transition easier for apps not desiring to use a brand
  new capability (because of header file or glibc support)
- we print a warning (but allow it) if you try to set
  the socket option with CAP_NET_ADMIN privs, but without
  either one of CAP_NET_TRANSPARENT or CAP_NET_RAW.

The reason for introducing a new capability is that while
transparent sockets are potentially dangerous (and can let you
spoof your source IP on traffic), they don't normally give you
the full 'freedom' of eavesdropping and/or spoofing that raw sockets
give you.

Signed-off-by: Maciej Żenczykowski <maze@google.com>
Acked-by: Balazs Scheidler <bazsi@balabit.hu>
Acked-by: David Miller <davem@redhat.com>
---
 include/linux/capability.h |   13 +++++++++----
 net/ipv4/ip_sockglue.c     |   26 ++++++++++++++++++++++----
 net/ipv6/ipv6_sockglue.c   |   29 ++++++++++++++++++++++++-----
 3 files changed, 55 insertions(+), 13 deletions(-)

diff --git a/include/linux/capability.h b/include/linux/capability.h
index c421123..a115ed4 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -198,7 +198,7 @@ struct cpu_vfs_cap_data {
 /* Allow modification of routing tables */
 /* Allow setting arbitrary process / process group ownership on
    sockets */
-/* Allow binding to any address for transparent proxying */
+/* Allow binding to any address for transparent proxying (deprecated) */
 /* Allow setting TOS (type of service) */
 /* Allow setting promiscuous mode */
 /* Allow clearing driver statistics */
@@ -210,6 +210,7 @@ struct cpu_vfs_cap_data {
 
 /* Allow use of RAW sockets */
 /* Allow use of PACKET sockets */
+/* Allow binding to any address for transparent proxying */
 
 #define CAP_NET_RAW          13
 
@@ -332,7 +333,7 @@ struct cpu_vfs_cap_data {
 
 #define CAP_AUDIT_CONTROL    30
 
-#define CAP_SETFCAP	     31
+#define CAP_SETFCAP          31
 
 /* Override MAC access.
    The base kernel enforces no MAC policy.
@@ -357,10 +358,14 @@ struct cpu_vfs_cap_data {
 
 /* Allow triggering something that will wake the system */
 
-#define CAP_WAKE_ALARM            35
+#define CAP_WAKE_ALARM       35
+
+/* Allow binding to any address for transparent proxying */
+
+#define CAP_NET_TRANSPARENT  36
 
 
-#define CAP_LAST_CAP         CAP_WAKE_ALARM
+#define CAP_LAST_CAP         CAP_NET_TRANSPARENT
 
 #define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP)
 
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 8905e92..44efa39 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -961,12 +961,30 @@ mc_msf_out:
 		break;
 
 	case IP_TRANSPARENT:
-		if (!capable(CAP_NET_ADMIN)) {
-			err = -EPERM;
-			break;
-		}
 		if (optlen < 1)
 			goto e_inval;
+		/* Always allow clearing the transparent proxy socket option.
+		 * The pre-3.2 permission for setting this was CAP_NET_ADMIN,
+		 * and this is still supported - but deprecated.  As of Linux
+		 * 3.2 the proper permission is one of CAP_NET_TRANSPARENT
+		 * (preferred, a new capability) or CAP_NET_RAW.  The latter
+		 * is supported to make the transition easier (and because
+		 * raw sockets already effectively allow one to emulate
+		 * socket transparency).
+		 */
+		if (!!val && !capable(CAP_NET_TRANSPARENT)
+		          && !capable(CAP_NET_RAW)) {
+			if (!capable(CAP_NET_ADMIN)) {
+				err = -EPERM;
+				break;
+			}
+			printk_once(KERN_WARNING "%s (%d): "
+				 "deprecated: attempt to set socket option "
+				 "IP_TRANSPARENT with CAP_NET_ADMIN but "
+				 "without either one of CAP_NET_TRANSPARENT "
+				 "or CAP_NET_RAW.\n",
+				 current->comm, task_pid_nr(current));
+		}
 		inet->transparent = !!val;
 		break;
 
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 2fbda5f..b8315c8 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -343,13 +343,32 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
 		break;
 
 	case IPV6_TRANSPARENT:
-		if (!capable(CAP_NET_ADMIN)) {
-			retv = -EPERM;
-			break;
-		}
 		if (optlen < sizeof(int))
 			goto e_inval;
-		/* we don't have a separate transparent bit for IPV6 we use the one in the IPv4 socket */
+		/* Always allow clearing the transparent proxy socket option.
+		 * The pre-3.2 permission for setting this was CAP_NET_ADMIN,
+		 * and this is still supported - but deprecated.  As of Linux
+		 * 3.2 the proper permission is one of CAP_NET_TRANSPARENT
+		 * (preferred, a new capability) or CAP_NET_RAW.  The latter
+		 * is supported to make the transition easier (and because
+		 * raw sockets already effectively allow one to emulate
+		 * socket transparency).
+		 */
+		if (valbool && !capable(CAP_NET_TRANSPARENT)
+		            && !capable(CAP_NET_RAW)) {
+			if (!capable(CAP_NET_ADMIN)) {
+				retv = -EPERM;
+				break;
+			}
+			printk_once(KERN_WARNING "%s (%d): "
+				 "deprecated: attempt to set socket option "
+				 "IPV6_TRANSPARENT with CAP_NET_ADMIN but "
+				 "without either one of CAP_NET_TRANSPARENT "
+				 "or CAP_NET_RAW.\n",
+				 current->comm, task_pid_nr(current));
+		}
+		/* we don't have a separate transparent bit for IPV6 we use the
+		 * one in the IPv4 socket */
 		inet_sk(sk)->transparent = valbool;
 		retv = 0;
 		break;
-- 
1.7.3.1

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* Re: [net-next 1/8] pci: Add flag indicating device has been assigned by KVM
From: Jeff Kirsher @ 2011-09-23  4:16 UTC (permalink / raw)
  To: davem, konrad.wilk@oracle.com, ijc@hellion.org.uk, Jesse Barnes
  Cc: Greg Rose, netdev, gospo, Jeff Kirsher, linux-pci
In-Reply-To: <1316599974-23205-2-git-send-email-jeffrey.t.kirsher@intel.com>

On Wed, Sep 21, 2011 at 03:12, Jeff Kirsher <jeffrey.t.kirsher@intel.com> wrote:
> From: Greg Rose <gregory.v.rose@intel.com>
>
> Device drivers that create and destroy SR-IOV virtual functions via
> calls to pci_enable_sriov() and pci_disable_sriov can cause catastrophic
> failures if they attempt to destroy VFs while they are assigned to
> guest virtual machines.  By adding a flag for use by the KVM module
> to indicate that a device is assigned a device driver can check that
> flag and avoid destroying VFs while they are assigned and avoid system
> failures.
>
> Signed-off-by: Greg Rose <gregory.v.rose@intel.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
> ---
>  include/linux/pci.h     |    2 ++
>  virt/kvm/assigned-dev.c |    2 ++
>  virt/kvm/iommu.c        |    4 ++++
>  3 files changed, 8 insertions(+), 0 deletions(-)
>
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index f27893b..4f511da 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -174,6 +174,8 @@ enum pci_dev_flags {
>        PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG = (__force pci_dev_flags_t) 1,
>        /* Device configuration is irrevocably lost if disabled into D3 */
>        PCI_DEV_FLAGS_NO_D3 = (__force pci_dev_flags_t) 2,
> +       /* Provide indication device is assigned by KVM */
> +       PCI_DEV_FLAGS_ASSIGNED = (__force pci_dev_flags_t) 4,
>  };
>
>  enum pci_irq_reroute_variant {
> diff --git a/virt/kvm/assigned-dev.c b/virt/kvm/assigned-dev.c
> index 4e9eaeb..eaf3a50 100644
> --- a/virt/kvm/assigned-dev.c
> +++ b/virt/kvm/assigned-dev.c
> @@ -205,6 +205,8 @@ static void kvm_free_assigned_device(struct kvm *kvm,
>        else
>                pci_restore_state(assigned_dev->dev);
>
> +       assigned_dev->dev->dev_flags &= ~PCI_DEV_FLAGS_ASSIGNED;
> +
>        pci_release_regions(assigned_dev->dev);
>        pci_disable_device(assigned_dev->dev);
>        pci_dev_put(assigned_dev->dev);
> diff --git a/virt/kvm/iommu.c b/virt/kvm/iommu.c
> index 78c80f6..967aba1 100644
> --- a/virt/kvm/iommu.c
> +++ b/virt/kvm/iommu.c
> @@ -187,6 +187,8 @@ int kvm_assign_device(struct kvm *kvm,
>                        goto out_unmap;
>        }
>
> +       pdev->dev_flags |= PCI_DEV_FLAGS_ASSIGNED;
> +
>        printk(KERN_DEBUG "assign device %x:%x:%x.%x\n",
>                assigned_dev->host_segnr,
>                assigned_dev->host_busnr,
> @@ -215,6 +217,8 @@ int kvm_deassign_device(struct kvm *kvm,
>
>        iommu_detach_device(domain, &pdev->dev);
>
> +       pdev->dev_flags &= ~PCI_DEV_FLAGS_ASSIGNED;
> +
>        printk(KERN_DEBUG "deassign device %x:%x:%x.%x\n",
>                assigned_dev->host_segnr,
>                assigned_dev->host_busnr,
> --
> 1.7.6.2

Jesse/Konrad/Ian-

I sent this patch out as part of a pull request for David Miller's
net-next tree.  I know that Greg sent this originally out to the
linux-pci mailing list as a RFC. Since Greg also has a patch against
ixgbe which implemented this flag, I sent both patches for inclusion
into David Miller's net-next.

Dave is wanting to ensure that the PCI maintainers have reviewed this
and are ok with it before pulls my series of patches.

-- 
Cheers,
Jeff

^ permalink raw reply


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