Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH net-next] af_unix: speedup /proc/net/unix
From: David Miller @ 2012-06-08 21:28 UTC (permalink / raw)
  To: eric.dumazet; +Cc: netdev, swhiteho, xemul
In-Reply-To: <1339167801.6001.111.camel@edumazet-glaptop>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Fri, 08 Jun 2012 17:03:21 +0200

> From: Eric Dumazet <edumazet@google.com>
> 
> /proc/net/unix has quadratic behavior, and can hold unix_table_lock for
> a while if high number of unix sockets are alive. (90 ms for 200k
> sockets...)
> 
> We already have a hash table, so its quite easy to use it.
> 
> Problem is unbound sockets are still hashed in a single hash slot
> (unix_socket_table[UNIX_HASH_TABLE])
> 
> This patch also spreads unbound sockets to 256 hash slots, to speedup
> both /proc/net/unix and unix_diag.
> 
> Time to read /proc/net/unix with 200k unix sockets :
> (time dd if=/proc/net/unix of=/dev/null bs=4k)
> 
> before : 520 secs
> after : 2 secs
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>

Nice work Eric, applied.

^ permalink raw reply

* Re: [PATCH] l2tp: fix a race in l2tp_ip_sendmsg()
From: David Miller @ 2012-06-08 21:31 UTC (permalink / raw)
  To: eric.dumazet; +Cc: netdev, jchapman, denys
In-Reply-To: <1339172700.6001.128.camel@edumazet-glaptop>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Fri, 08 Jun 2012 18:25:00 +0200

> From: Eric Dumazet <edumazet@google.com>
> 
> Commit 081b1b1bb27f (l2tp: fix l2tp_ip_sendmsg() route handling) added
> a race, in case IP route cache is disabled.
> 
> In this case, we should not do the dst_release(&rt->dst), since it'll
> free the dst immediately, instead of waiting a RCU grace period.
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>

Working with a zero-ref'd object is always playing with fire even
when we "know what we are doing" :-)

Applied and queued up for -stable, thanks Eric.

^ permalink raw reply

* Re: [PATCH] be2net: fix a race in be_xmit()
From: David Miller @ 2012-06-08 21:44 UTC (permalink / raw)
  To: Sathya.Perla; +Cc: eric.dumazet, netdev
In-Reply-To: <3367B80B08154D42A3B2BC708B5D41F647C6A0B900@EXMAIL.ad.emulex.com>

From: <Sathya.Perla@Emulex.Com>
Date: Fri, 8 Jun 2012 03:06:14 -0700

> 
>>-----Original Message-----
>>From: Eric Dumazet <edumazet@google.com>
>>
>>As soon as hardware is notified of a transmit, we no longer can assume
>>skb can be dereferenced, as TX completion might have freed the packet.
>>
>>Signed-off-by: Eric Dumazet <edumazet@google.com>
>>Cc: Sathya Perla <sathya.perla@emulex.com>
> 
> Good catch. Thanks!
> Acked-by: Sathya Perla <sathya.perla@emulex.com>

Applied.

^ permalink raw reply

* Re: [PATCH net-next] ipv4: Add interface option to enable routing of 127.0.0.0/8
From: Thomas Graf @ 2012-06-08 22:22 UTC (permalink / raw)
  To: David Miller; +Cc: tgraf, netdev
In-Reply-To: <20120608.132338.892251811480644242.davem@davemloft.net>

On Fri, Jun 08, 2012 at 01:23:38PM -0700, David Miller wrote:
> 
> What's the different between this patch and the one you posted
> half a day ago?

There is no difference. I didn't see my own mail appear in
my netdev folder and assumed git send-email had failed so
I did send it again. Sorry for the double post.

^ permalink raw reply

* [PATCH] net/core: fix kernel-doc warnings
From: Randy Dunlap @ 2012-06-09  0:01 UTC (permalink / raw)
  To: netdev, David Miller

From: Randy Dunlap <rdunlap@xenotime.net>

Fix kernel-doc warnings in net/core:

Warning(net/core/skbuff.c:3368): No description found for parameter 'delta_truesize'
Warning(net/core/filter.c:628): No description found for parameter 'pfp'
Warning(net/core/filter.c:628): Excess function parameter 'sk' description in 'sk_unattached_filter_create'

Signed-off-by: Randy Dunlap <rdunlap@xenotime.net>
---
 net/core/filter.c |    4 ++--
 net/core/skbuff.c |    2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

--- lnx-35-rc1.orig/net/core/filter.c
+++ lnx-35-rc1/net/core/filter.c
@@ -616,9 +616,9 @@ static int __sk_prepare_filter(struct sk
 /**
  *	sk_unattached_filter_create - create an unattached filter
  *	@fprog: the filter program
- *	@sk: the socket to use
+ *	@pfp: the unattached filter that is created
  *
- * Create a filter independent ofr any socket. We first run some
+ * Create a filter independent of any socket. We first run some
  * sanity checks on it to make sure it does not explode on us later.
  * If an error occurs or there is insufficient memory for the filter
  * a negative errno code is returned. On success the return is zero.
--- lnx-35-rc1.orig/net/core/skbuff.c
+++ lnx-35-rc1/net/core/skbuff.c
@@ -3361,7 +3361,7 @@ EXPORT_SYMBOL(kfree_skb_partial);
  * @to: prior buffer
  * @from: buffer to add
  * @fragstolen: pointer to boolean
- *
+ * @delta_truesize: how much more was allocated than was requested
  */
 bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from,
 		      bool *fragstolen, int *delta_truesize)

^ permalink raw reply

* Re: formal way to map from pf to vfs when using VT-d?
From: Greg Rose @ 2012-06-09  0:04 UTC (permalink / raw)
  To: Chris Friesen
  Cc: netdev, e1000-devel@lists.sourceforge.net, Kirsher, Jeffrey T,
	Brandeburg, Jesse, Allan, Bruce W
In-Reply-To: <4FD26382.3050303@genband.com>

On Fri, 8 Jun 2012 14:41:38 -0600
Chris Friesen <chris.friesen@genband.com> wrote:

> On 06/08/2012 02:14 PM, Chris Friesen wrote:
> >
> > Hi,
> >
> > I'm using the igb/igbvf drivers.  If I set igb.max_vfs=7,7,7,7 it 
> > creates 7 vfs for each of my pfs.  So far so good.
> >
> > Now, how do I map from a given pf to the PCI addresses for the set
> > of vfs that are associated with it?  I don't have virsh installed,
> > so is there a way to query this with sysfs or something?
> >
> 
> I think I found it.../sys/class/net/eth0/device/ has "virtfnX"
> entries which are symlinks to the appropriate pci address.

Here's a script used by our validation team, inserted inline.

#!/usr/bin/perl
use strict;

if ($#ARGV <1)
{
        print " Usage: ./list_vfs.pl Nic_name (t for Twinville, n for niantic, k for kawela, p for powerville) port_numer( 1 for first port, 2 for second port..) \n";

        exit ;
}
my $nic_name=$ARGV[0];
#my $port_n=$ARGV[1]%4;
my $all_vfs;
my $vf_str;
my $mode = 2;
my $my_pf_str;

if ($nic_name eq 't') {
        $my_pf_str= "\"10 Gigabit\"";
	$vf_str="\"Intel Corporation Device 1515\"";
} elsif ($nic_name eq 'n') {
	$my_pf_str="\"82599EB\"";
	$vf_str="\"82599 Ethernet Controller Virtual\"";
} elsif ($nic_name eq 'k') {
	$my_pf_str="\"82576 Gigabit Network Connection\"";
	$vf_str="\"Intel Corporation 82576 Virtual Function\"";
} elsif ($nic_name eq 'p') {
	$my_pf_str= "\"I350\"";
	$vf_str="\"Intel Corporation Device 1520\"";
	$mode=4;
} else {
	print "No such virtual Function device, please check again\n";
}

my $port_n=$ARGV[1]%$mode;

my $my_pf=qx(lspci | grep $my_pf_str | awk '{print \$1}' | awk 'NR%$mode==$port_n');
print  "PF=$my_pf\n";
my $all_vfs=qx(lspci | grep $vf_str | awk '{print \$1}' | awk 'NR%$mode==$port_n');
print "VFs are:\n";
print "$all_vfs\n";

- Greg

> 
> Chris
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" 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

* [PATCH] netdev: fix drivers/net/phy/ kernel-doc warnings
From: Randy Dunlap @ 2012-06-09  0:07 UTC (permalink / raw)
  To: netdev, David Miller

From: Randy Dunlap <rdunlap@xenotime.net>

Fix kernel-doc warnings in drivers/net/phy:

Warning(drivers/net/phy/mdio_bus.c:109): No description found for parameter 'mdio_bus_np'
Warning(drivers/net/phy/mdio_bus.c:109): Excess function parameter 'mdio_np' description in 'of_mdio_find_bus'

Signed-off-by: Randy Dunlap <rdunlap@xenotime.net>
---
 drivers/net/phy/mdio_bus.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- lnx-35-rc1.orig/drivers/net/phy/mdio_bus.c
+++ lnx-35-rc1/drivers/net/phy/mdio_bus.c
@@ -96,7 +96,7 @@ static int of_mdio_bus_match(struct devi
 }
 /**
  * of_mdio_find_bus - Given an mii_bus node, find the mii_bus.
- * @mdio_np: Pointer to the mii_bus.
+ * @mdio_bus_np: Pointer to the mii_bus.
  *
  * Returns a pointer to the mii_bus, or NULL if none found.
  *

^ permalink raw reply

* solar lala shared photos with you
From: solar lala @ 2012-06-09  0:52 UTC (permalink / raw)
  To: netdev

[-- Attachment #1: Type: text/plain, Size: 326 bytes --]

dear sir

     We send an updated list (enclosed )of available Solar automatic control  
insecticidal lamps , Please contact us for more information.



Regards

    lala

Ecosol PV Tech Co., Ltd
Tel: 86-769-8279 2468
Fax: 86-769-879 2478
email:info@ecsolsolar.com
skype:solarlala
msn:solarlala@hotmail.com
www.ecsolsolar.com

[-- Attachment #2: 太阳能杀虫灯002.jpg --]
[-- Type: image/jpeg, Size: 144424 bytes --]

[-- Attachment #3: laptop charger.jpg --]
[-- Type: image/jpeg, Size: 10232 bytes --]

[-- Attachment #4: 太阳能手提箱002.jpg --]
[-- Type: image/jpeg, Size: 42070 bytes --]

[-- Attachment #5: 太阳能水泵.jpg --]
[-- Type: image/jpeg, Size: 48979 bytes --]

^ permalink raw reply

* [PATCH] inetpeer: fix build failed when IPV6 not enabled
From: Gao feng @ 2012-06-09  2:12 UTC (permalink / raw)
  To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
	wfg-VuQAYsv1563Yd54FQh9/CA

commit c8a627ed06d6d49bf65015a2185c519335c4c83f
(inetpeer: add namespace support for inetpeer)
makes kernel bulid failed when IPV6 not enabled.

fix this by adding #if IS_ENABLED(CONFIG_IPV6)

Reported-by: Fengguang Wu <wfg-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Signed-off-by: Gao feng <gaofeng-BthXqXjhjHXQFUHtdCDX3A@public.gmane.org>
---
 net/ipv4/inetpeer.c |   18 ++++++++++++------
 1 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c
index 1c85273..57f694e 100644
--- a/net/ipv4/inetpeer.c
+++ b/net/ipv4/inetpeer.c
@@ -151,18 +151,19 @@ static int __net_init inetpeer_net_init(struct net *net)
 	net->ipv4.peers->root = peer_avl_empty_rcu;
 	seqlock_init(&net->ipv4.peers->lock);
 
+#if IS_ENABLED(CONFIG_IPV6)
 	net->ipv6.peers = kzalloc(sizeof(struct inet_peer_base),
 				  GFP_KERNEL);
-	if (net->ipv6.peers == NULL)
-		goto out_ipv6;
+	if (net->ipv6.peers == NULL) {
+		kfree(net->ipv4.peers);
+		return -ENOMEM;
+	}
 
 	net->ipv6.peers->root = peer_avl_empty_rcu;
 	seqlock_init(&net->ipv6.peers->lock);
+#endif
 
 	return 0;
-out_ipv6:
-	kfree(net->ipv4.peers);
-	return -ENOMEM;
 }
 
 static void __net_exit inetpeer_net_exit(struct net *net)
@@ -170,10 +171,11 @@ static void __net_exit inetpeer_net_exit(struct net *net)
 	inetpeer_invalidate_tree(net, AF_INET);
 	kfree(net->ipv4.peers);
 	net->ipv4.peers = NULL;
-
+#if IS_ENABLED(CONFIG_IPV6)
 	inetpeer_invalidate_tree(net, AF_INET6);
 	kfree(net->ipv6.peers);
 	net->ipv6.peers = NULL;
+#endif
 }
 
 static struct pernet_operations inetpeer_ops = {
@@ -433,7 +435,11 @@ static void unlink_from_pool(struct inet_peer *p, struct inet_peer_base *base,
 static struct inet_peer_base *family_to_base(struct net *net,
 					     int family)
 {
+#if IS_ENABLED(CONFIG_IPV6)
 	return family == AF_INET ? net->ipv4.peers : net->ipv6.peers;
+#else
+	return net->ipv4.peers;
+#endif
 }
 
 /* perform garbage collect on all items stacked during a lookup */
-- 
1.7.7.6

^ permalink raw reply related

* Re: [PATCH] netdev: mv643xx_eth: Prevent build on PPC32
From: Mark Brown @ 2012-06-09  4:01 UTC (permalink / raw)
  To: Josh Boyer
  Cc: Ben Hutchings, Lennert Buytenhek, Andrew Lunn, Olof Johansson,
	netdev
In-Reply-To: <20120608010403.GL7683@zod.bos.redhat.com>

[-- Attachment #1: Type: text/plain, Size: 2013 bytes --]

On Thu, Jun 07, 2012 at 09:04:03PM -0400, Josh Boyer wrote:

> I'm not placing blame.  I'm declaring people should be cautious going
> forward.  5 arches have the clock API.  21 don't.  Whatever reasons
> there are for that, I don't care.  It should be a big warning sign.

My point here is that it's a warning sign for the API, not really for
the drivers that use it.

> It might even be beneficial to put some Kconfig dependencies on both
> CONFIG_COMMON_CLK (which is somewhat misleadingly named) and
> CONFIG_CLKDEV_LOOKUP so those are only selectable on those 5 arches.
> Something like:

>  config CLKDEV_LOOKUP
>  	bool
> +	depends on (ARM || SUPERH || MIPS || C6X || BLACKFIN)
>  	select HAVE_CLK

This is a really bad approach.  It's sending totally the wrong message
about where we want to be (we want to have the clock API available
everywhere) and more importantly it still means that drivers need to go
on carrying around ifdefery or unhelpful dependencies which is just lots
of pointless work.  A very large proportion of the drivers that use
clocks are just making sure clocks are enabled when the device is active
to integrate with system wide power optimisation and don't actually care
if there are clocks there at all, we should be making their life as easy
as possible.

A much better approach is get the stubs mentioned earlier merged
(they're already on their way) faster.  That way there are no compile
time dependencies and the problem goes away unless the driver is doing
something more active with clocks like managing the clock rate.

In the case of CLKDEV_LOOKUP the symbol should only be selected by an
architecture anyway, it's a layer on top of the architecture clock code.

> Regardless, hopefully things like this will get hit in linux-next in the
> future.  I believe the only reason that it wasn't this time is that
> none of the PPC defconfigs build in linux-next bother to build the
> driver at all.

They do generally, people do randconfig and allXconfig builds all the
time.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* Re: [PATCH torvalds/linux.git] Make linux/tcp.h C++ friendly (trivial)
From: Paul Pluzhnikov @ 2012-06-09  4:14 UTC (permalink / raw)
  To: Jiri Kosina; +Cc: netdev
In-Reply-To: <CALoOobMSXp4x_+En2gyHmpXcxq=sECQvMZN1LX_j3Yve7Ha6Aw@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 776 bytes --]

On Tue, Mar 6, 2012 at 4:14 PM, Paul Pluzhnikov <ppluzhnikov@google.com> wrote:
> Ping?
>
> I am attaching the patch again so it doesn't get mangled by quoting
> and is easier to apply.

Ping? Ping?

I thought the patch has been applied, and stopped pinging it.
But it appears that it never did get applied :-(

Thanks,

On Thu, Dec 29, 2011 at 10:30 AM, Paul Pluzhnikov
<ppluzhnikov@google.com> wrote:
>
> Using linux/tcp.h from C++ results in:
>
> cat t.cc
>
> #include <linux/tcp.h>
> int main() { }
>
> g++ -c t.cc
>
> In file included from t.cc:1:
> /usr/include/linux/tcp.h:72: error: '__u32 __fswab32(__u32)' cannot appear in a constant-expression
> /usr/include/linux/tcp.h:72: error: a function call cannot appear in a constant-expression
> ...


-- 
Paul Pluzhnikov

[-- Attachment #2: linux-tcp_h-patch-20111229.txt --]
[-- Type: text/plain, Size: 1255 bytes --]

diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 7f59ee9..63334f7 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -69,16 +69,16 @@ union tcp_word_hdr {
 #define tcp_flag_word(tp) ( ((union tcp_word_hdr *)(tp))->words [3]) 
 
 enum { 
-	TCP_FLAG_CWR = __cpu_to_be32(0x00800000),
-	TCP_FLAG_ECE = __cpu_to_be32(0x00400000),
-	TCP_FLAG_URG = __cpu_to_be32(0x00200000),
-	TCP_FLAG_ACK = __cpu_to_be32(0x00100000),
-	TCP_FLAG_PSH = __cpu_to_be32(0x00080000),
-	TCP_FLAG_RST = __cpu_to_be32(0x00040000),
-	TCP_FLAG_SYN = __cpu_to_be32(0x00020000),
-	TCP_FLAG_FIN = __cpu_to_be32(0x00010000),
-	TCP_RESERVED_BITS = __cpu_to_be32(0x0F000000),
-	TCP_DATA_OFFSET = __cpu_to_be32(0xF0000000)
+	TCP_FLAG_CWR = __constant_cpu_to_be32(0x00800000),
+	TCP_FLAG_ECE = __constant_cpu_to_be32(0x00400000),
+	TCP_FLAG_URG = __constant_cpu_to_be32(0x00200000),
+	TCP_FLAG_ACK = __constant_cpu_to_be32(0x00100000),
+	TCP_FLAG_PSH = __constant_cpu_to_be32(0x00080000),
+	TCP_FLAG_RST = __constant_cpu_to_be32(0x00040000),
+	TCP_FLAG_SYN = __constant_cpu_to_be32(0x00020000),
+	TCP_FLAG_FIN = __constant_cpu_to_be32(0x00010000),
+	TCP_RESERVED_BITS = __constant_cpu_to_be32(0x0F000000),
+	TCP_DATA_OFFSET = __constant_cpu_to_be32(0xF0000000)
 }; 
 
 /*

^ permalink raw reply related

* Re: [PATCH torvalds/linux.git] Make linux/tcp.h C++ friendly (trivial)
From: David Miller @ 2012-06-09  5:17 UTC (permalink / raw)
  To: ppluzhnikov; +Cc: jkosina, netdev
In-Reply-To: <CALoOobNbt0Kbea8gHdNkQFa0+ydpH++6ND+fOBGvy5Rmf=_QpA@mail.gmail.com>

From: Paul Pluzhnikov <ppluzhnikov@google.com>
Date: Fri, 8 Jun 2012 21:14:19 -0700

> I thought the patch has been applied, and stopped pinging it.
> But it appears that it never did get applied :-(

Your submission is not properly formed, you need to post this as a
fresh email with proper commit message and signoffs.

Please read Documentation/SubmittingPatches if you want us to
seriously consider this change.

Thanks.

^ permalink raw reply

* Re: [PATCH] inetpeer: fix build failed when IPV6 not enabled
From: David Miller @ 2012-06-09  5:20 UTC (permalink / raw)
  To: gaofeng; +Cc: netdev, containers, wfg
In-Reply-To: <1339207973-11479-1-git-send-email-gaofeng@cn.fujitsu.com>

From: Gao feng <gaofeng@cn.fujitsu.com>
Date: Sat, 9 Jun 2012 10:12:53 +0800

> fix this by adding #if IS_ENABLED(CONFIG_IPV6)

There is not a single UGLY ifdef in inetpeer.c, and I am not going to
allow you to start crapping it up with ifdefs now.

We support ipv6 just fine without ifdefs before your network namespace
changes, so you need to find a way to continue dong so afterwards.

^ permalink raw reply

* Re: [PATCH] net/core: fix kernel-doc warnings
From: David Miller @ 2012-06-09  5:21 UTC (permalink / raw)
  To: rdunlap; +Cc: netdev
In-Reply-To: <4FD29268.1010604@xenotime.net>

From: Randy Dunlap <rdunlap@xenotime.net>
Date: Fri, 08 Jun 2012 17:01:44 -0700

> From: Randy Dunlap <rdunlap@xenotime.net>
> 
> Fix kernel-doc warnings in net/core:
> 
> Warning(net/core/skbuff.c:3368): No description found for parameter 'delta_truesize'
> Warning(net/core/filter.c:628): No description found for parameter 'pfp'
> Warning(net/core/filter.c:628): Excess function parameter 'sk' description in 'sk_unattached_filter_create'
> 
> Signed-off-by: Randy Dunlap <rdunlap@xenotime.net>

Applied.

^ permalink raw reply

* Re: [PATCH] netdev: fix drivers/net/phy/ kernel-doc warnings
From: David Miller @ 2012-06-09  5:21 UTC (permalink / raw)
  To: rdunlap; +Cc: netdev
In-Reply-To: <4FD293B7.6080702@xenotime.net>

From: Randy Dunlap <rdunlap@xenotime.net>
Date: Fri, 08 Jun 2012 17:07:19 -0700

> From: Randy Dunlap <rdunlap@xenotime.net>
> 
> Fix kernel-doc warnings in drivers/net/phy:
> 
> Warning(drivers/net/phy/mdio_bus.c:109): No description found for parameter 'mdio_bus_np'
> Warning(drivers/net/phy/mdio_bus.c:109): Excess function parameter 'mdio_np' description in 'of_mdio_find_bus'
> 
> Signed-off-by: Randy Dunlap <rdunlap@xenotime.net>

Applied.

^ permalink raw reply

* Re: [PATCH net-next] af_unix: speedup /proc/net/unix
From: Michael Tokarev @ 2012-06-09  5:42 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: David Miller, netdev, Steven Whitehouse, Pavel Emelyanov
In-Reply-To: <1339167801.6001.111.camel@edumazet-glaptop>

On 08.06.2012 19:03, Eric Dumazet wrote:
> From: Eric Dumazet <edumazet@google.com>
> 
> /proc/net/unix has quadratic behavior, and can hold unix_table_lock for
> a while if high number of unix sockets are alive. (90 ms for 200k
> sockets...)

Two comments, nitpicking...

[]
>  struct unix_iter_state {
>  	struct seq_net_private p;
> -	int i;
>  };

Can't seq_net_private be used directly?

> +static struct sock *unix_next_socket(struct seq_file *seq,
> +				     struct sock *sk,
> +				     loff_t *pos)
> +{
....
>  }
>  
>  static void *unix_seq_next(struct seq_file *seq, void *v, loff_t *pos)
>  {
> +	return unix_next_socket(seq, v, pos);
>  }

Why unix_seq_next() is needed?  Can't unix_next_socket() be used directly instead?

Thanks,

/mjt

^ permalink raw reply

* Re: [PATCH torvalds/linux.git] Make linux/tcp.h C++ friendly (trivial)
From: Paul Pluzhnikov @ 2012-06-09  5:45 UTC (permalink / raw)
  To: David Miller; +Cc: jkosina, netdev
In-Reply-To: <20120608.221755.927511342271201223.davem@davemloft.net>

[-- Attachment #1: Type: text/plain, Size: 1605 bytes --]

On Fri, Jun 8, 2012 at 10:17 PM, David Miller <davem@davemloft.net> wrote:
> From: Paul Pluzhnikov <ppluzhnikov@google.com>
> Date: Fri, 8 Jun 2012 21:14:19 -0700
>
>> I thought the patch has been applied, and stopped pinging it.
>> But it appears that it never did get applied :-(
>
> Your submission is not properly formed, you need to post this as a
> fresh email with proper commit message and signoffs.
>
> Please read Documentation/SubmittingPatches if you want us to
> seriously consider this change.

Here is the original message I sent to <trivial@kernel.org> on
Thu, Dec 29, 2011 at 10:30 AM:

-----------------------------------------
Greetings,

Using linux/tcp.h from C++ results in:

cat t.cc
#include <linux/tcp.h>
int main() { }

g++ -c t.cc

In file included from t.cc:1:
/usr/include/linux/tcp.h:72: error: '__u32 __fswab32(__u32)' cannot
appear in a constant-expression
/usr/include/linux/tcp.h:72: error: a function call cannot appear in a
constant-expression
...

Attached trivial patch fixes this problem.

Tested:
- the t.cc above compiles with g++ and
- the following program generates the same output before/after
 the patch:

#include <linux/tcp.h>
#include <stdio.h>

int main ()
{
#define P(a) printf("%s: %08x\n", #a, (int)a)
 P(TCP_FLAG_CWR);
 P(TCP_FLAG_ECE);
 P(TCP_FLAG_URG);
 P(TCP_FLAG_ACK);
 P(TCP_FLAG_PSH);
 P(TCP_FLAG_RST);
 P(TCP_FLAG_SYN);
 P(TCP_FLAG_FIN);
 P(TCP_RESERVED_BITS);
 P(TCP_DATA_OFFSET);
#undef P
 return 0;
}

Signed-off-by: Paul Pluzhnikov <ppluzhnikov@google.com>


Thanks,

P.S. Google has blanket copyright assignment to FSF.
--
Paul Pluzhnikov

[-- Attachment #2: linux-tcp_h-patch-20111229.txt --]
[-- Type: text/plain, Size: 1255 bytes --]

diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 7f59ee9..63334f7 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -69,16 +69,16 @@ union tcp_word_hdr {
 #define tcp_flag_word(tp) ( ((union tcp_word_hdr *)(tp))->words [3]) 
 
 enum { 
-	TCP_FLAG_CWR = __cpu_to_be32(0x00800000),
-	TCP_FLAG_ECE = __cpu_to_be32(0x00400000),
-	TCP_FLAG_URG = __cpu_to_be32(0x00200000),
-	TCP_FLAG_ACK = __cpu_to_be32(0x00100000),
-	TCP_FLAG_PSH = __cpu_to_be32(0x00080000),
-	TCP_FLAG_RST = __cpu_to_be32(0x00040000),
-	TCP_FLAG_SYN = __cpu_to_be32(0x00020000),
-	TCP_FLAG_FIN = __cpu_to_be32(0x00010000),
-	TCP_RESERVED_BITS = __cpu_to_be32(0x0F000000),
-	TCP_DATA_OFFSET = __cpu_to_be32(0xF0000000)
+	TCP_FLAG_CWR = __constant_cpu_to_be32(0x00800000),
+	TCP_FLAG_ECE = __constant_cpu_to_be32(0x00400000),
+	TCP_FLAG_URG = __constant_cpu_to_be32(0x00200000),
+	TCP_FLAG_ACK = __constant_cpu_to_be32(0x00100000),
+	TCP_FLAG_PSH = __constant_cpu_to_be32(0x00080000),
+	TCP_FLAG_RST = __constant_cpu_to_be32(0x00040000),
+	TCP_FLAG_SYN = __constant_cpu_to_be32(0x00020000),
+	TCP_FLAG_FIN = __constant_cpu_to_be32(0x00010000),
+	TCP_RESERVED_BITS = __constant_cpu_to_be32(0x0F000000),
+	TCP_DATA_OFFSET = __constant_cpu_to_be32(0xF0000000)
 }; 
 
 /*

^ permalink raw reply related

* Re: [PATCH torvalds/linux.git] Make linux/tcp.h C++ friendly (trivial)
From: David Miller @ 2012-06-09  5:55 UTC (permalink / raw)
  To: ppluzhnikov; +Cc: jkosina, netdev
In-Reply-To: <CALoOobMCio0GtxerOpXwB-Bxf-cKnLotPBA69oPC-6CWDfyPyg@mail.gmail.com>

From: Paul Pluzhnikov <ppluzhnikov@google.com>
Date: Fri, 8 Jun 2012 22:45:20 -0700

> On Fri, Jun 8, 2012 at 10:17 PM, David Miller <davem@davemloft.net> wrote:
>> From: Paul Pluzhnikov <ppluzhnikov@google.com>
>> Date: Fri, 8 Jun 2012 21:14:19 -0700
>>
>>> I thought the patch has been applied, and stopped pinging it.
>>> But it appears that it never did get applied :-(
>>
>> Your submission is not properly formed, you need to post this as a
>> fresh email with proper commit message and signoffs.
>>
>> Please read Documentation/SubmittingPatches if you want us to
>> seriously consider this change.
> 
> Here is the original message I sent to <trivial@kernel.org> on
> Thu, Dec 29, 2011 at 10:30 AM:

Please make a new, proper submission.  I didn't ask you to reference
your original submission did I?

Thank you.

^ permalink raw reply

* [PATCH net-next] inet: Create and use rt{,6}_get_peer_create().
From: David Miller @ 2012-06-09  6:39 UTC (permalink / raw)
  To: netdev


There's a lot of places that open-code rt{,6}_get_peer() only because
they want to set 'create' to one.  So add an rt{,6}_get_peer_create()
for their sake.

There were also a few spots open-coding plain rt{,6}_get_peer() and
those are transformed here as well.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 include/net/ip6_route.h |   17 +++++++++++++----
 include/net/route.h     |   14 ++++++++++++--
 net/ipv4/icmp.c         |    5 ++---
 net/ipv4/route.c        |   35 +++++++++--------------------------
 net/ipv4/tcp_ipv4.c     |    4 +---
 net/ipv6/icmp.c         |    6 +++---
 net/ipv6/ip6_output.c   |   11 ++++-------
 net/ipv6/ndisc.c        |    6 +++---
 net/ipv6/route.c        |    5 +----
 net/ipv6/tcp_ipv6.c     |    4 +---
 10 files changed, 49 insertions(+), 58 deletions(-)

diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index 37c1a1e..73d7502 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -53,18 +53,27 @@ static inline unsigned int rt6_flags2srcprefs(int flags)
 	return (flags >> 3) & 7;
 }
 
-extern void			rt6_bind_peer(struct rt6_info *rt,
-					      int create);
+extern void rt6_bind_peer(struct rt6_info *rt, int create);
 
-static inline struct inet_peer *rt6_get_peer(struct rt6_info *rt)
+static inline struct inet_peer *__rt6_get_peer(struct rt6_info *rt, int create)
 {
 	if (rt->rt6i_peer)
 		return rt->rt6i_peer;
 
-	rt6_bind_peer(rt, 0);
+	rt6_bind_peer(rt, create);
 	return rt->rt6i_peer;
 }
 
+static inline struct inet_peer *rt6_get_peer(struct rt6_info *rt)
+{
+	return __rt6_get_peer(rt, 0);
+}
+
+static inline struct inet_peer *rt6_get_peer_create(struct rt6_info *rt)
+{
+	return __rt6_get_peer(rt, 1);
+}
+
 extern void			ip6_route_input(struct sk_buff *skb);
 
 extern struct dst_entry *	ip6_route_output(struct net *net,
diff --git a/include/net/route.h b/include/net/route.h
index ed2b78e..433fc6c 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -296,15 +296,25 @@ static inline struct rtable *ip_route_newports(struct flowi4 *fl4, struct rtable
 
 extern void rt_bind_peer(struct rtable *rt, __be32 daddr, int create);
 
-static inline struct inet_peer *rt_get_peer(struct rtable *rt, __be32 daddr)
+static inline struct inet_peer *__rt_get_peer(struct rtable *rt, __be32 daddr, int create)
 {
 	if (rt->peer)
 		return rt->peer;
 
-	rt_bind_peer(rt, daddr, 0);
+	rt_bind_peer(rt, daddr, create);
 	return rt->peer;
 }
 
+static inline struct inet_peer *rt_get_peer(struct rtable *rt, __be32 daddr)
+{
+	return __rt_get_peer(rt, daddr, 0);
+}
+
+static inline struct inet_peer *rt_get_peer_create(struct rtable *rt, __be32 daddr)
+{
+	return __rt_get_peer(rt, daddr, 1);
+}
+
 static inline int inet_iif(const struct sk_buff *skb)
 {
 	return skb_rtable(skb)->rt_iif;
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index c75efbd..0c78ef1 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -253,9 +253,8 @@ static inline bool icmpv4_xrlim_allow(struct net *net, struct rtable *rt,
 
 	/* Limit if icmp type is enabled in ratemask. */
 	if ((1 << type) & net->ipv4.sysctl_icmp_ratemask) {
-		if (!rt->peer)
-			rt_bind_peer(rt, fl4->daddr, 1);
-		rc = inet_peer_xrlim_allow(rt->peer,
+		struct inet_peer *peer = rt_get_peer_create(rt, fl4->daddr);
+		rc = inet_peer_xrlim_allow(peer,
 					   net->ipv4.sysctl_icmp_ratelimit);
 	}
 out:
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 2c9f73f..7a4d724 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -162,10 +162,7 @@ static u32 *ipv4_cow_metrics(struct dst_entry *dst, unsigned long old)
 	struct inet_peer *peer;
 	u32 *p = NULL;
 
-	if (!rt->peer)
-		rt_bind_peer(rt, rt->rt_dst, 1);
-
-	peer = rt->peer;
+	peer = rt_get_peer_create(rt, rt->rt_dst);
 	if (peer) {
 		u32 *old_p = __DST_METRICS_PTR(old);
 		unsigned long prev, new;
@@ -1364,14 +1361,13 @@ void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more)
 	struct rtable *rt = (struct rtable *) dst;
 
 	if (rt && !(rt->dst.flags & DST_NOPEER)) {
-		if (rt->peer == NULL)
-			rt_bind_peer(rt, rt->rt_dst, 1);
+		struct inet_peer *peer = rt_get_peer_create(rt, rt->rt_dst);
 
 		/* If peer is attached to destination, it is never detached,
 		   so that we need not to grab a lock to dereference it.
 		 */
-		if (rt->peer) {
-			iph->id = htons(inet_getid(rt->peer, more));
+		if (peer) {
+			iph->id = htons(inet_getid(peer, more));
 			return;
 		}
 	} else if (!rt)
@@ -1481,10 +1477,7 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
 				    rt->rt_gateway != old_gw)
 					continue;
 
-				if (!rt->peer)
-					rt_bind_peer(rt, rt->rt_dst, 1);
-
-				peer = rt->peer;
+				peer = rt_get_peer_create(rt, rt->rt_dst);
 				if (peer) {
 					if (peer->redirect_learned.a4 != new_gw) {
 						peer->redirect_learned.a4 = new_gw;
@@ -1579,9 +1572,7 @@ void ip_rt_send_redirect(struct sk_buff *skb)
 	log_martians = IN_DEV_LOG_MARTIANS(in_dev);
 	rcu_read_unlock();
 
-	if (!rt->peer)
-		rt_bind_peer(rt, rt->rt_dst, 1);
-	peer = rt->peer;
+	peer = rt_get_peer_create(rt, rt->rt_dst);
 	if (!peer) {
 		icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, rt->rt_gateway);
 		return;
@@ -1646,9 +1637,7 @@ static int ip_error(struct sk_buff *skb)
 		break;
 	}
 
-	if (!rt->peer)
-		rt_bind_peer(rt, rt->rt_dst, 1);
-	peer = rt->peer;
+	peer = rt_get_peer_create(rt, rt->rt_dst);
 
 	send = true;
 	if (peer) {
@@ -1754,9 +1743,7 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
 
 	dst_confirm(dst);
 
-	if (!rt->peer)
-		rt_bind_peer(rt, rt->rt_dst, 1);
-	peer = rt->peer;
+	peer = rt_get_peer_create(rt, rt->rt_dst);
 	if (peer) {
 		unsigned long pmtu_expires = ACCESS_ONCE(peer->pmtu_expires);
 
@@ -1782,12 +1769,8 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
 static void ipv4_validate_peer(struct rtable *rt)
 {
 	if (rt->rt_peer_genid != rt_peer_genid()) {
-		struct inet_peer *peer;
-
-		if (!rt->peer)
-			rt_bind_peer(rt, rt->rt_dst, 0);
+		struct inet_peer *peer = rt_get_peer(rt, rt->rt_dst);
 
-		peer = rt->peer;
 		if (peer) {
 			check_peer_pmtu(&rt->dst, peer);
 
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index f485b45..833e8d9 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1832,9 +1832,7 @@ struct inet_peer *tcp_v4_get_peer(struct sock *sk, bool *release_it)
 		peer = inet_getpeer_v4(net, inet->inet_daddr, 1);
 		*release_it = true;
 	} else {
-		if (!rt->peer)
-			rt_bind_peer(rt, inet->inet_daddr, 1);
-		peer = rt->peer;
+		peer = rt_get_peer_create(rt, inet->inet_daddr);
 		*release_it = false;
 	}
 
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 091a297..ed89bba 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -188,14 +188,14 @@ static inline bool icmpv6_xrlim_allow(struct sock *sk, u8 type,
 	} else {
 		struct rt6_info *rt = (struct rt6_info *)dst;
 		int tmo = net->ipv6.sysctl.icmpv6_time;
+		struct inet_peer *peer;
 
 		/* Give more bandwidth to wider prefixes. */
 		if (rt->rt6i_dst.plen < 128)
 			tmo >>= ((128 - rt->rt6i_dst.plen)>>5);
 
-		if (!rt->rt6i_peer)
-			rt6_bind_peer(rt, 1);
-		res = inet_peer_xrlim_allow(rt->rt6i_peer, tmo);
+		peer = rt6_get_peer_create(rt);
+		res = inet_peer_xrlim_allow(peer, tmo);
 	}
 	dst_release(dst);
 	return res;
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 17b8c67..62fcf3e 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -463,6 +463,7 @@ int ip6_forward(struct sk_buff *skb)
 	 */
 	if (skb->dev == dst->dev && opt->srcrt == 0 && !skb_sec_path(skb)) {
 		struct in6_addr *target = NULL;
+		struct inet_peer *peer;
 		struct rt6_info *rt;
 
 		/*
@@ -476,13 +477,12 @@ int ip6_forward(struct sk_buff *skb)
 		else
 			target = &hdr->daddr;
 
-		if (!rt->rt6i_peer)
-			rt6_bind_peer(rt, 1);
+		peer = rt6_get_peer_create(rt);
 
 		/* Limit redirects both by destination (here)
 		   and by source (inside ndisc_send_redirect)
 		 */
-		if (inet_peer_xrlim_allow(rt->rt6i_peer, 1*HZ))
+		if (inet_peer_xrlim_allow(peer, 1*HZ))
 			ndisc_send_redirect(skb, target);
 	} else {
 		int addrtype = ipv6_addr_type(&hdr->saddr);
@@ -602,11 +602,8 @@ void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
 	int old, new;
 
 	if (rt && !(rt->dst.flags & DST_NOPEER)) {
-		struct inet_peer *peer;
+		struct inet_peer *peer = rt6_get_peer_create(rt);
 
-		if (!rt->rt6i_peer)
-			rt6_bind_peer(rt, 1);
-		peer = rt->rt6i_peer;
 		if (peer) {
 			fhdr->identification = htonl(inet_getid(peer, 0));
 			return;
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 54f62d3..69a6330 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1472,6 +1472,7 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target)
 	struct net *net = dev_net(dev);
 	struct sock *sk = net->ipv6.ndisc_sk;
 	int len = sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr);
+	struct inet_peer *peer;
 	struct sk_buff *buff;
 	struct icmp6hdr *icmph;
 	struct in6_addr saddr_buf;
@@ -1518,9 +1519,8 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target)
 			  "Redirect: destination is not a neighbour\n");
 		goto release;
 	}
-	if (!rt->rt6i_peer)
-		rt6_bind_peer(rt, 1);
-	if (!inet_peer_xrlim_allow(rt->rt6i_peer, 1*HZ))
+	peer = rt6_get_peer_create(rt);
+	if (!inet_peer_xrlim_allow(peer, 1*HZ))
 		goto release;
 
 	if (dev->addr_len) {
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 4eca013..8a986be 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -99,10 +99,7 @@ static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old)
 	if (!(rt->dst.flags & DST_HOST))
 		return NULL;
 
-	if (!rt->rt6i_peer)
-		rt6_bind_peer(rt, 1);
-
-	peer = rt->rt6i_peer;
+	peer = rt6_get_peer_create(rt);
 	if (peer) {
 		u32 *old_p = __DST_METRICS_PTR(old);
 		unsigned long prev, new;
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 1a9cdd0..218433c 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1744,9 +1744,7 @@ static struct inet_peer *tcp_v6_get_peer(struct sock *sk, bool *release_it)
 		peer = inet_getpeer_v6(net, &np->daddr, 1);
 		*release_it = true;
 	} else {
-		if (!rt->rt6i_peer)
-			rt6_bind_peer(rt, 1);
-		peer = rt->rt6i_peer;
+		peer = rt6_get_peer_create(rt);
 		*release_it = false;
 	}
 
-- 
1.7.10

^ permalink raw reply related

* [2.6.32.y] Re: [PATCH] appletalk:: da.s_net not copied but assigned to itself in aarp_rcv()
From: Jonathan Nieder @ 2012-06-09  7:07 UTC (permalink / raw)
  To: stable
  Cc: acme, roel.kluin, David Miller, netdev, Mason Loring Bliss,
	Ben Hutchings
In-Reply-To: <20120302193416.GA22055@burratino>

From: Roel Kluin <roel.kluin@gmail.com>
Date: Fri, 15 Jan 2010 01:49:28 -0800
Subject: appletalk:: da.s_net not copied but assigned to itself in aarp_rcv()

commit 2a04cd4c7d41c4549764734dcf5a883d304e3229 upstream.

da.s_net was not copied but assigned to itself.

Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
Acked-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
---
(culling cc list)
Hi Willy,

Please consider

  2a04cd4c7d41 appletalk:: da.s_net not copied bu assigned to itself
               in aarp_rcv()

for application to the 2.6.32.y tree.

Without this patch, Mason (cc-ed) is not able to use appletalk[1]:

| With Linux 2.6.32 as supplied with Debian Squeeze, Netatalk is unable
| to thrive. Connections made to afpd will open, but attempting to transfer
| files will take a very long time and/or eventually time out.
|
| I've noted this with both Netatalk as supplied with Squeeze and with
| Netatalk 2.2.1 built from the Wheezy source package, which I evidently
| need for AFP 3 support.

Though this bug is very old.  Presumably no one noticed because no one
was using proxy-AARP.

The patch was merged upstream in 2.6.33-rc6.  Mason tested it against
Debian's 2.6.32.y-based kernel in March and found it to work, and the
patch has been part of Debian's stable kernel since then without
triggering any complaints.

Hope that helps,
Jonathan

[1] http://bugs.debian.org/660902

 net/appletalk/aarp.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c
index 9d4adfd22757..f2b3b56aa779 100644
--- a/net/appletalk/aarp.c
+++ b/net/appletalk/aarp.c
@@ -819,7 +819,7 @@ static int aarp_rcv(struct sk_buff *skb, struct net_device *dev,
 				ma = &ifa->address;
 			else { /* We need to make a copy of the entry. */
 				da.s_node = sa.s_node;
-				da.s_net = da.s_net;
+				da.s_net = sa.s_net;
 				ma = &da;
 			}
 
-- 
1.7.10

^ permalink raw reply related

* [PATCH rfc net] Allow the autoconfigured network interface to be renamed.
From: Scott Parlane @ 2012-06-09  7:48 UTC (permalink / raw)
  To: netdev; +Cc: Scott Parlane

From: Scott Parlane <scott.parlane@alliedtelesis.co.nz>

if IP_PNP_RENAME_DEV is set, the first interface to be configured
automatically by the kernel during boot will be renamed.

IP_PNP_DEV_NEWNAME is the name to give the autoconfigured device.

No changes will be made to any interface that is not autoconfigured.

This allows the assurance of the boot device name, without the need
for an initramfs.

Signed-off-by: Scott Parlane <scott.parlane@alliedtelesis.co.nz>
---
 net/ipv4/Kconfig    |   17 +++++++++++++++++
 net/ipv4/ipconfig.c |   35 +++++++++++++++++++++++++++++++++++
 2 files changed, 52 insertions(+), 0 deletions(-)

diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index 20f1cb5..c85c654 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -163,6 +163,23 @@ config IP_PNP_RARP
 	  operating on your network. Read
 	  <file:Documentation/filesystems/nfs/nfsroot.txt> for details.
 
+config IP_PNP_RENAME_DEV
+	bool "IP: Rename boot device"
+	depends on IP_PNP
+	help
+	 If you want to rename the network device you are booting from
+	 to something other than eth%d enable this option, and choose the name
+	 below. This is helpful if you want to use udev to keep
+	 persistent naming of your other interfaces.
+
+config IP_PNP_DEV_NEWNAME
+	string "IP: New name of boot device"
+	depends on IP_PNP_RENAME_DEV
+	default "bootnet"
+	help
+	 The name to assign to the network device you are booting from
+	 when using ip autoconfigure
+
 config NET_IPIP
 	tristate "IP: tunneling"
 	select INET_TUNNEL
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index 67e8a6b..a4b052a 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -86,6 +86,10 @@
 #if defined(IPCONFIG_BOOTP) || defined(IPCONFIG_RARP)
 #define IPCONFIG_DYNAMIC
 #endif
+#if defined(CONFIG_IP_PNP_RENAME_DEV)
+#define IPCONFIG_RENAME_DEV
+#define IPCONFIG_DEV_NEWNAME CONFIG_IP_PNP_DEV_NEWNAME
+#endif
 
 /* Define the friendly delay before and after opening net devices */
 #define CONF_POST_OPEN		10	/* After opening: 10 msecs */
@@ -360,6 +364,37 @@ static int __init ic_setup_if(void)
 
 	memset(&ir, 0, sizeof(ir));
 	strcpy(ir.ifr_ifrn.ifrn_name, ic_dev->name);
+#ifdef IPCONFIG_RENAME_DEV
+	if ((err = ic_dev_ioctl(SIOCGIFFLAGS, &ir)) < 0) {
+		pr_err("IP-Config: Unable to get interface flags (1,%d).\n",
+		       err);
+		return -1;
+	}
+	ir.ifr_flags &= ~IFF_UP;
+	if ((err = ic_dev_ioctl(SIOCSIFFLAGS, &ir)) < 0) {
+		pr_err("IP-Config: Unable to set interface flags (1,%d).\n",
+		       err);
+		return -1;
+	}
+	strcpy(ir.ifr_newname, IPCONFIG_DEV_NEWNAME);
+	if ((err = ic_dev_ioctl(SIOCSIFNAME, &ir)) < 0) {
+		pr_err("IP-Config: Unable to change boot interface name to %s (%d).\n",
+		       IPCONFIG_DEV_NEWNAME, err);
+		return -1;
+	}
+	strcpy(ir.ifr_ifrn.ifrn_name, IPCONFIG_DEV_NEWNAME);
+	if ((err = ic_dev_ioctl(SIOCGIFFLAGS, &ir)) < 0) {
+		pr_err("IP-Config: Unable to get interface flags (2,%d).\n",
+		       err);
+		return -1;
+	}
+	ir.ifr_flags |= IFF_UP;
+	if ((err = ic_dev_ioctl(SIOCSIFFLAGS, &ir)) < 0) {
+		pr_err("IP-Config: Unable to set interface flags (2,%d).\n",
+		       err);
+		return -1;
+	}
+#endif
 	set_sockaddr(sin, ic_myaddr, 0);
 	if ((err = ic_devinet_ioctl(SIOCSIFADDR, &ir)) < 0) {
 		pr_err("IP-Config: Unable to set interface address (%d)\n",
-- 
1.7.7

^ permalink raw reply related

* Re: [PATCH net-next] af_unix: speedup /proc/net/unix
From: Eric Dumazet @ 2012-06-09  8:10 UTC (permalink / raw)
  To: Michael Tokarev; +Cc: David Miller, netdev, Steven Whitehouse, Pavel Emelyanov
In-Reply-To: <4FD2E22F.9090503@msgid.tls.msk.ru>

From: Eric Dumazet <edumazet@google.com>

On Sat, 2012-06-09 at 09:42 +0400, Michael Tokarev wrote:
> On 08.06.2012 19:03, Eric Dumazet wrote:
> > From: Eric Dumazet <edumazet@google.com>
> > 
> > /proc/net/unix has quadratic behavior, and can hold unix_table_lock for
> > a while if high number of unix sockets are alive. (90 ms for 200k
> > sockets...)
> 
> Two comments, nitpicking...
> 
> []
> >  struct unix_iter_state {
> >  	struct seq_net_private p;
> > -	int i;
> >  };
> 
> Can't seq_net_private be used directly?
> 

Absolutely

> >  
> >  static void *unix_seq_next(struct seq_file *seq, void *v, loff_t *pos)
> >  {
> > +	return unix_next_socket(seq, v, pos);
> >  }
> 
> Why unix_seq_next() is needed?  Can't unix_next_socket() be used directly instead?

Nope, you missed the "++*pos;"

static void *unix_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
	++*pos;
	return unix_next_socket(seq, v, pos);
}

Thanks !

[PATCH net-next] af_unix: remove unix_iter_state

As pointed out by Michael Tokarev , struct unix_iter_state is no longer
needed.

Suggested-by: Michael Tokarev <mjt@tls.msk.ru>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Steven Whitehouse <swhiteho@redhat.com>
Cc: Pavel Emelyanov <xemul@parallels.com>
---
 net/unix/af_unix.c |    6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index cf83f6b..79981d9 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -2255,10 +2255,6 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock,
 #define get_offset(x) ((x) & ((1L << BUCKET_SPACE) - 1))
 #define set_bucket_offset(b, o) ((b) << BUCKET_SPACE | (o))
 
-struct unix_iter_state {
-	struct seq_net_private p;
-};
-
 static struct sock *unix_from_bucket(struct seq_file *seq, loff_t *pos)
 {
 	unsigned long offset = get_offset(*pos);
@@ -2383,7 +2379,7 @@ static const struct seq_operations unix_seq_ops = {
 static int unix_seq_open(struct inode *inode, struct file *file)
 {
 	return seq_open_net(inode, file, &unix_seq_ops,
-			    sizeof(struct unix_iter_state));
+			    sizeof(struct seq_net_private));
 }
 
 static const struct file_operations unix_seq_fops = {

^ permalink raw reply related

* [net-next 0/9][pull request] Intel Wired LAN Driver Updates
From: Jeff Kirsher @ 2012-06-09  8:20 UTC (permalink / raw)
  To: davem; +Cc: Jeff Kirsher, netdev, gospo, sassmann

This series contains updates to igb and ixgbe.

The following are changes since commit fbfe95a42e90b3dd079cc9019ba7d7700feee0f6:
  inet: Create and use rt{,6}_get_peer_create().
and are available in the git repository at:
  git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-next master

Carolyn Wyborny (4):
  igb: Add support functions to access thermal data.
  igb: Add hwmon interface to export thermal data.
  igb: Update firmware info output
  igb: Version bump

Emil Tantilov (1):
  ixgbe: do not compile ixgbe_sysfs.c when CONFIG_IXGBE_HWMON is not
    set

Jacob Keller (3):
  ixgbe: ptp code cleanup
  ixgbe: PTP Fix hwtstamp mode settings
  ixgbe: Check PTP Rx timestamps via BPF filter

John Fastabend (1):
  ixgbe: align flow control DV macros with datasheet

 drivers/net/ethernet/intel/Kconfig             |   10 +
 drivers/net/ethernet/intel/igb/Makefile        |    2 +-
 drivers/net/ethernet/intel/igb/e1000_82575.c   |  659 +++++++++++++++++++++++-
 drivers/net/ethernet/intel/igb/e1000_82575.h   |   31 ++
 drivers/net/ethernet/intel/igb/e1000_defines.h |   15 +-
 drivers/net/ethernet/intel/igb/e1000_hw.h      |   21 +-
 drivers/net/ethernet/intel/igb/e1000_regs.h    |   15 +
 drivers/net/ethernet/intel/igb/igb.h           |   44 ++
 drivers/net/ethernet/intel/igb/igb_ethtool.c   |   16 +-
 drivers/net/ethernet/intel/igb/igb_main.c      |   97 +++-
 drivers/net/ethernet/intel/igb/igb_sysfs.c     |  245 +++++++++
 drivers/net/ethernet/intel/ixgbe/Makefile      |    4 +-
 drivers/net/ethernet/intel/ixgbe/ixgbe.h       |    2 +
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c  |   11 +-
 drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c   |  149 ++++--
 drivers/net/ethernet/intel/ixgbe/ixgbe_sysfs.c |    2 -
 drivers/net/ethernet/intel/ixgbe/ixgbe_type.h  |   37 +-
 17 files changed, 1284 insertions(+), 76 deletions(-)
 create mode 100644 drivers/net/ethernet/intel/igb/igb_sysfs.c

-- 
1.7.10.2

^ permalink raw reply

* [net-next 1/9] igb: Add support functions to access thermal data.
From: Jeff Kirsher @ 2012-06-09  8:20 UTC (permalink / raw)
  To: davem; +Cc: Carolyn Wyborny, netdev, gospo, sassmann, Jeff Kirsher
In-Reply-To: <1339230063-12545-1-git-send-email-jeffrey.t.kirsher@intel.com>

From: Carolyn Wyborny <carolyn.wyborny@intel.com>

Some i350 devices contain thermal data that we can get to via an i2c
interface.  These functions provide support to get at that data.  A
following patch will export this data.

Signed-off-by: Carolyn Wyborny <carolyn.wyborny@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/ethernet/intel/igb/e1000_82575.c   |  655 +++++++++++++++++++++++-
 drivers/net/ethernet/intel/igb/e1000_82575.h   |   31 ++
 drivers/net/ethernet/intel/igb/e1000_defines.h |   15 +-
 drivers/net/ethernet/intel/igb/e1000_hw.h      |   16 +
 drivers/net/ethernet/intel/igb/e1000_regs.h    |   15 +
 5 files changed, 730 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c
index e650839..9623833 100644
--- a/drivers/net/ethernet/intel/igb/e1000_82575.c
+++ b/drivers/net/ethernet/intel/igb/e1000_82575.c
@@ -2256,6 +2256,660 @@ out:
 	return ret_val;
 }
 
+/**
+ *  igb_set_i2c_bb - Enable I2C bit-bang
+ *  @hw: pointer to the HW structure
+ *
+ *  Enable I2C bit-bang interface
+ *
+ **/
+s32 igb_set_i2c_bb(struct e1000_hw *hw)
+{
+	s32 ret_val = E1000_SUCCESS;
+	u32 ctrl_ext, i2cparams;
+
+	ctrl_ext = rd32(E1000_CTRL_EXT);
+	ctrl_ext |= E1000_CTRL_I2C_ENA;
+	wr32(E1000_CTRL_EXT, ctrl_ext);
+	wrfl();
+
+	i2cparams = rd32(E1000_I2CPARAMS);
+	i2cparams |= E1000_I2CBB_EN;
+	i2cparams |= E1000_I2C_DATA_OE_N;
+	i2cparams |= E1000_I2C_CLK_OE_N;
+	wr32(E1000_I2CPARAMS, i2cparams);
+	wrfl();
+
+	return ret_val;
+}
+
+/**
+ *  igb_get_i2c_data - Reads the I2C SDA data bit
+ *  @hw: pointer to hardware structure
+ *  @i2cctl: Current value of I2CCTL register
+ *
+ *  Returns the I2C data bit value
+ **/
+static bool igb_get_i2c_data(u32 *i2cctl)
+{
+	bool data;
+
+	if (*i2cctl & E1000_I2C_DATA_IN)
+		data = 1;
+	else
+		data = 0;
+
+	return data;
+}
+
+/**
+ *  igb_set_i2c_data - Sets the I2C data bit
+ *  @hw: pointer to hardware structure
+ *  @i2cctl: Current value of I2CCTL register
+ *  @data: I2C data value (0 or 1) to set
+ *
+ *  Sets the I2C data bit
+ **/
+static s32 igb_set_i2c_data(struct e1000_hw *hw, u32 *i2cctl, bool data)
+{
+	s32 status = E1000_SUCCESS;
+
+	if (data)
+		*i2cctl |= E1000_I2C_DATA_OUT;
+	else
+		*i2cctl &= ~E1000_I2C_DATA_OUT;
+
+	*i2cctl &= ~E1000_I2C_DATA_OE_N;
+	*i2cctl |= E1000_I2C_CLK_OE_N;
+	wr32(E1000_I2CPARAMS, *i2cctl);
+	wrfl();
+
+	/* Data rise/fall (1000ns/300ns) and set-up time (250ns) */
+	udelay(E1000_I2C_T_RISE + E1000_I2C_T_FALL + E1000_I2C_T_SU_DATA);
+
+	*i2cctl = rd32(E1000_I2CPARAMS);
+	if (data != igb_get_i2c_data(i2cctl)) {
+		status = E1000_ERR_I2C;
+		hw_dbg("Error - I2C data was not set to %X.\n", data);
+	}
+
+	return status;
+}
+
+/**
+ *  igb_raise_i2c_clk - Raises the I2C SCL clock
+ *  @hw: pointer to hardware structure
+ *  @i2cctl: Current value of I2CCTL register
+ *
+ *  Raises the I2C clock line '0'->'1'
+ **/
+static void igb_raise_i2c_clk(struct e1000_hw *hw, u32 *i2cctl)
+{
+	*i2cctl |= E1000_I2C_CLK_OUT;
+	*i2cctl &= ~E1000_I2C_CLK_OE_N;
+	wr32(E1000_I2CPARAMS, *i2cctl);
+	wrfl();
+
+	/* SCL rise time (1000ns) */
+	udelay(E1000_I2C_T_RISE);
+}
+
+/**
+ *  igb_lower_i2c_clk - Lowers the I2C SCL clock
+ *  @hw: pointer to hardware structure
+ *  @i2cctl: Current value of I2CCTL register
+ *
+ *  Lowers the I2C clock line '1'->'0'
+ **/
+static void igb_lower_i2c_clk(struct e1000_hw *hw, u32 *i2cctl)
+{
+
+	*i2cctl &= ~E1000_I2C_CLK_OUT;
+	*i2cctl &= ~E1000_I2C_CLK_OE_N;
+	wr32(E1000_I2CPARAMS, *i2cctl);
+	wrfl();
+
+	/* SCL fall time (300ns) */
+	udelay(E1000_I2C_T_FALL);
+}
+
+/**
+ *  igb_clock_out_i2c_bit - Clocks in/out one bit via I2C data/clock
+ *  @hw: pointer to hardware structure
+ *  @data: data value to write
+ *
+ *  Clocks out one bit via I2C data/clock
+ **/
+static s32 igb_clock_out_i2c_bit(struct e1000_hw *hw, bool data)
+{
+	s32 status;
+	u32 i2cctl = rd32(E1000_I2CPARAMS);
+
+	status = igb_set_i2c_data(hw, &i2cctl, data);
+	if (status == E1000_SUCCESS) {
+		igb_raise_i2c_clk(hw, &i2cctl);
+
+		/* Minimum high period of clock is 4us */
+		udelay(E1000_I2C_T_HIGH);
+
+		igb_lower_i2c_clk(hw, &i2cctl);
+
+		/* Minimum low period of clock is 4.7 us.
+		 * This also takes care of the data hold time.
+		 */
+		udelay(E1000_I2C_T_LOW);
+	} else {
+		status = E1000_ERR_I2C;
+		hw_dbg("I2C data was not set to %X\n", data);
+	}
+
+	return status;
+}
+
+/**
+ *  igb_clock_out_i2c_byte - Clocks out one byte via I2C
+ *  @hw: pointer to hardware structure
+ *  @data: data byte clocked out
+ *
+ *  Clocks out one byte data via I2C data/clock
+ **/
+static s32 igb_clock_out_i2c_byte(struct e1000_hw *hw, u8 data)
+{
+	s32 status = E1000_SUCCESS;
+	s32 i;
+	u32 i2cctl;
+	bool bit = 0;
+
+	for (i = 7; i >= 0; i--) {
+		bit = (data >> i) & 0x1;
+		status = igb_clock_out_i2c_bit(hw, bit);
+
+		if (status != E1000_SUCCESS)
+			break;
+	}
+
+	/* Release SDA line (set high) */
+	i2cctl = rd32(E1000_I2CPARAMS);
+
+	i2cctl |= E1000_I2C_DATA_OE_N;
+	wr32(E1000_I2CPARAMS, i2cctl);
+	wrfl();
+
+	return status;
+}
+
+/**
+ *  igb_get_i2c_ack - Polls for I2C ACK
+ *  @hw: pointer to hardware structure
+ *
+ *  Clocks in/out one bit via I2C data/clock
+ **/
+static s32 igb_get_i2c_ack(struct e1000_hw *hw)
+{
+	s32 status = E1000_SUCCESS;
+	u32 i = 0;
+	u32 i2cctl = rd32(E1000_I2CPARAMS);
+	u32 timeout = 10;
+	bool ack = true;
+
+	igb_raise_i2c_clk(hw, &i2cctl);
+
+	/* Minimum high period of clock is 4us */
+	udelay(E1000_I2C_T_HIGH);
+
+	/* Wait until SCL returns high */
+	for (i = 0; i < timeout; i++) {
+		udelay(1);
+		i2cctl = rd32(E1000_I2CPARAMS);
+		if (i2cctl & E1000_I2C_CLK_IN)
+			break;
+	}
+	if (!(i2cctl & E1000_I2C_CLK_IN))
+		return E1000_ERR_I2C;
+
+	ack = igb_get_i2c_data(&i2cctl);
+	if (ack) {
+		hw_dbg("I2C ack was not received.\n");
+		status = E1000_ERR_I2C;
+	}
+
+	igb_lower_i2c_clk(hw, &i2cctl);
+
+	/* Minimum low period of clock is 4.7 us */
+	udelay(E1000_I2C_T_LOW);
+
+	return status;
+}
+
+/**
+ *  igb_clock_in_i2c_bit - Clocks in one bit via I2C data/clock
+ *  @hw: pointer to hardware structure
+ *  @data: read data value
+ *
+ *  Clocks in one bit via I2C data/clock
+ **/
+static s32 igb_clock_in_i2c_bit(struct e1000_hw *hw, bool *data)
+{
+	u32 i2cctl = rd32(E1000_I2CPARAMS);
+
+	igb_raise_i2c_clk(hw, &i2cctl);
+
+	/* Minimum high period of clock is 4us */
+	udelay(E1000_I2C_T_HIGH);
+
+	i2cctl = rd32(E1000_I2CPARAMS);
+	*data = igb_get_i2c_data(&i2cctl);
+
+	igb_lower_i2c_clk(hw, &i2cctl);
+
+	/* Minimum low period of clock is 4.7 us */
+	udelay(E1000_I2C_T_LOW);
+
+	return E1000_SUCCESS;
+}
+
+/**
+ *  igb_clock_in_i2c_byte - Clocks in one byte via I2C
+ *  @hw: pointer to hardware structure
+ *  @data: data byte to clock in
+ *
+ *  Clocks in one byte data via I2C data/clock
+ **/
+static s32 igb_clock_in_i2c_byte(struct e1000_hw *hw, u8 *data)
+{
+	s32 i;
+	bool bit = 0;
+
+	*data = 0;
+	for (i = 7; i >= 0; i--) {
+		igb_clock_in_i2c_bit(hw, &bit);
+		*data |= bit << i;
+	}
+
+	return E1000_SUCCESS;
+}
+
+/**
+ *  igb_i2c_stop - Sets I2C stop condition
+ *  @hw: pointer to hardware structure
+ *
+ *  Sets I2C stop condition (Low -> High on SDA while SCL is High)
+ **/
+static void igb_i2c_stop(struct e1000_hw *hw)
+{
+	u32 i2cctl = rd32(E1000_I2CPARAMS);
+
+	/* Stop condition must begin with data low and clock high */
+	igb_set_i2c_data(hw, &i2cctl, 0);
+	igb_raise_i2c_clk(hw, &i2cctl);
+
+	/* Setup time for stop condition (4us) */
+	udelay(E1000_I2C_T_SU_STO);
+
+	igb_set_i2c_data(hw, &i2cctl, 1);
+
+	/* bus free time between stop and start (4.7us)*/
+	udelay(E1000_I2C_T_BUF);
+}
+
+/**
+ *  igb_i2c_start - Sets I2C start condition
+ *  @hw: pointer to hardware structure
+ *
+ *  Sets I2C start condition (High -> Low on SDA while SCL is High)
+ **/
+static void igb_i2c_start(struct e1000_hw *hw)
+{
+	u32 i2cctl = rd32(E1000_I2CPARAMS);
+
+	/* Start condition must begin with data and clock high */
+	igb_set_i2c_data(hw, &i2cctl, 1);
+	igb_raise_i2c_clk(hw, &i2cctl);
+
+	/* Setup time for start condition (4.7us) */
+	udelay(E1000_I2C_T_SU_STA);
+
+	igb_set_i2c_data(hw, &i2cctl, 0);
+
+	/* Hold time for start condition (4us) */
+	udelay(E1000_I2C_T_HD_STA);
+
+	igb_lower_i2c_clk(hw, &i2cctl);
+
+	/* Minimum low period of clock is 4.7 us */
+	udelay(E1000_I2C_T_LOW);
+
+}
+
+/**
+ *  igb_read_i2c_byte_generic - Reads 8 bit word over I2C
+ *  @hw: pointer to hardware structure
+ *  @byte_offset: byte offset to read
+ *  @dev_addr: device address
+ *  @data: value read
+ *
+ *  Performs byte read operation over I2C interface at
+ *  a specified device address.
+ **/
+s32 igb_read_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset,
+				u8 dev_addr, u8 *data)
+{
+	s32 status = E1000_SUCCESS;
+	u32 max_retry = 10;
+	u32 retry = 1;
+	u16 swfw_mask = 0;
+
+	bool nack = true;
+
+	swfw_mask = E1000_SWFW_PHY0_SM;
+
+	do {
+		if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask)
+		    != E1000_SUCCESS) {
+			status = E1000_ERR_SWFW_SYNC;
+			goto read_byte_out;
+		}
+
+		igb_i2c_start(hw);
+
+		/* Device Address and write indication */
+		status = igb_clock_out_i2c_byte(hw, dev_addr);
+		if (status != E1000_SUCCESS)
+			goto fail;
+
+		status = igb_get_i2c_ack(hw);
+		if (status != E1000_SUCCESS)
+			goto fail;
+
+		status = igb_clock_out_i2c_byte(hw, byte_offset);
+		if (status != E1000_SUCCESS)
+			goto fail;
+
+		status = igb_get_i2c_ack(hw);
+		if (status != E1000_SUCCESS)
+			goto fail;
+
+		igb_i2c_start(hw);
+
+		/* Device Address and read indication */
+		status = igb_clock_out_i2c_byte(hw, (dev_addr | 0x1));
+		if (status != E1000_SUCCESS)
+			goto fail;
+
+		status = igb_get_i2c_ack(hw);
+		if (status != E1000_SUCCESS)
+			goto fail;
+
+		status = igb_clock_in_i2c_byte(hw, data);
+		if (status != E1000_SUCCESS)
+			goto fail;
+
+		status = igb_clock_out_i2c_bit(hw, nack);
+		if (status != E1000_SUCCESS)
+			goto fail;
+
+		igb_i2c_stop(hw);
+		break;
+
+fail:
+		hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+		mdelay(100);
+		igb_i2c_bus_clear(hw);
+		retry++;
+		if (retry < max_retry)
+			hw_dbg("I2C byte read error - Retrying.\n");
+		else
+			hw_dbg("I2C byte read error.\n");
+
+	} while (retry < max_retry);
+
+	hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+
+read_byte_out:
+
+	return status;
+}
+
+/**
+ *  igb_write_i2c_byte_generic - Writes 8 bit word over I2C
+ *  @hw: pointer to hardware structure
+ *  @byte_offset: byte offset to write
+ *  @dev_addr: device address
+ *  @data: value to write
+ *
+ *  Performs byte write operation over I2C interface at
+ *  a specified device address.
+ **/
+s32 igb_write_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset,
+				 u8 dev_addr, u8 data)
+{
+	s32 status = E1000_SUCCESS;
+	u32 max_retry = 1;
+	u32 retry = 0;
+	u16 swfw_mask = 0;
+
+	swfw_mask = E1000_SWFW_PHY0_SM;
+
+	if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) != E1000_SUCCESS) {
+		status = E1000_ERR_SWFW_SYNC;
+		goto write_byte_out;
+	}
+
+	do {
+		igb_i2c_start(hw);
+
+		status = igb_clock_out_i2c_byte(hw, dev_addr);
+		if (status != E1000_SUCCESS)
+			goto fail;
+
+		status = igb_get_i2c_ack(hw);
+		if (status != E1000_SUCCESS)
+			goto fail;
+
+		status = igb_clock_out_i2c_byte(hw, byte_offset);
+		if (status != E1000_SUCCESS)
+			goto fail;
+
+		status = igb_get_i2c_ack(hw);
+		if (status != E1000_SUCCESS)
+			goto fail;
+
+		status = igb_clock_out_i2c_byte(hw, data);
+		if (status != E1000_SUCCESS)
+			goto fail;
+
+		status = igb_get_i2c_ack(hw);
+		if (status != E1000_SUCCESS)
+			goto fail;
+
+		igb_i2c_stop(hw);
+		break;
+
+fail:
+		igb_i2c_bus_clear(hw);
+		retry++;
+		if (retry < max_retry)
+			hw_dbg("I2C byte write error - Retrying.\n");
+		else
+			hw_dbg("I2C byte write error.\n");
+	} while (retry < max_retry);
+
+	hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+
+write_byte_out:
+
+	return status;
+}
+
+/**
+ *  igb_i2c_bus_clear - Clears the I2C bus
+ *  @hw: pointer to hardware structure
+ *
+ *  Clears the I2C bus by sending nine clock pulses.
+ *  Used when data line is stuck low.
+ **/
+void igb_i2c_bus_clear(struct e1000_hw *hw)
+{
+	u32 i2cctl = rd32(E1000_I2CPARAMS);
+	u32 i;
+
+	igb_i2c_start(hw);
+
+	igb_set_i2c_data(hw, &i2cctl, 1);
+
+	for (i = 0; i < 9; i++) {
+		igb_raise_i2c_clk(hw, &i2cctl);
+
+		/* Min high period of clock is 4us */
+		udelay(E1000_I2C_T_HIGH);
+
+		igb_lower_i2c_clk(hw, &i2cctl);
+
+		/* Min low period of clock is 4.7us*/
+		udelay(E1000_I2C_T_LOW);
+	}
+
+	igb_i2c_start(hw);
+
+	/* Put the i2c bus back to default state */
+	igb_i2c_stop(hw);
+}
+
+static const u8 e1000_emc_temp_data[4] = {
+	E1000_EMC_INTERNAL_DATA,
+	E1000_EMC_DIODE1_DATA,
+	E1000_EMC_DIODE2_DATA,
+	E1000_EMC_DIODE3_DATA
+};
+static const u8 e1000_emc_therm_limit[4] = {
+	E1000_EMC_INTERNAL_THERM_LIMIT,
+	E1000_EMC_DIODE1_THERM_LIMIT,
+	E1000_EMC_DIODE2_THERM_LIMIT,
+	E1000_EMC_DIODE3_THERM_LIMIT
+};
+
+/**
+ *  igb_get_thermal_sensor_data_generic - Gathers thermal sensor data
+ *  @hw: pointer to hardware structure
+ *
+ *  Updates the temperatures in mac.thermal_sensor_data
+ **/
+s32 igb_get_thermal_sensor_data_generic(struct e1000_hw *hw)
+{
+	s32 status = E1000_SUCCESS;
+	u16 ets_offset;
+	u16 ets_cfg;
+	u16 ets_sensor;
+	u8  num_sensors;
+	u8  sensor_index;
+	u8  sensor_location;
+	u8  i;
+	struct e1000_thermal_sensor_data *data = &hw->mac.thermal_sensor_data;
+
+	if ((hw->mac.type != e1000_i350) || (hw->bus.func != 0))
+		return E1000_NOT_IMPLEMENTED;
+
+	data->sensor[0].temp = (rd32(E1000_THMJT) & 0xFF);
+
+	/* Return the internal sensor only if ETS is unsupported */
+	hw->nvm.ops.read(hw, NVM_ETS_CFG, 1, &ets_offset);
+	if ((ets_offset == 0x0000) || (ets_offset == 0xFFFF))
+		return status;
+
+	hw->nvm.ops.read(hw, ets_offset, 1, &ets_cfg);
+	if (((ets_cfg & NVM_ETS_TYPE_MASK) >> NVM_ETS_TYPE_SHIFT)
+	    != NVM_ETS_TYPE_EMC)
+		return E1000_NOT_IMPLEMENTED;
+
+	num_sensors = (ets_cfg & NVM_ETS_NUM_SENSORS_MASK);
+	if (num_sensors > E1000_MAX_SENSORS)
+		num_sensors = E1000_MAX_SENSORS;
+
+	for (i = 1; i < num_sensors; i++) {
+		hw->nvm.ops.read(hw, (ets_offset + i), 1, &ets_sensor);
+		sensor_index = ((ets_sensor & NVM_ETS_DATA_INDEX_MASK) >>
+				NVM_ETS_DATA_INDEX_SHIFT);
+		sensor_location = ((ets_sensor & NVM_ETS_DATA_LOC_MASK) >>
+				   NVM_ETS_DATA_LOC_SHIFT);
+
+		if (sensor_location != 0)
+			hw->phy.ops.read_i2c_byte(hw,
+					e1000_emc_temp_data[sensor_index],
+					E1000_I2C_THERMAL_SENSOR_ADDR,
+					&data->sensor[i].temp);
+	}
+	return status;
+}
+
+/**
+ *  igb_init_thermal_sensor_thresh_generic - Sets thermal sensor thresholds
+ *  @hw: pointer to hardware structure
+ *
+ *  Sets the thermal sensor thresholds according to the NVM map
+ *  and save off the threshold and location values into mac.thermal_sensor_data
+ **/
+s32 igb_init_thermal_sensor_thresh_generic(struct e1000_hw *hw)
+{
+	s32 status = E1000_SUCCESS;
+	u16 ets_offset;
+	u16 ets_cfg;
+	u16 ets_sensor;
+	u8  low_thresh_delta;
+	u8  num_sensors;
+	u8  sensor_index;
+	u8  sensor_location;
+	u8  therm_limit;
+	u8  i;
+	struct e1000_thermal_sensor_data *data = &hw->mac.thermal_sensor_data;
+
+	if ((hw->mac.type != e1000_i350) || (hw->bus.func != 0))
+		return E1000_NOT_IMPLEMENTED;
+
+	memset(data, 0, sizeof(struct e1000_thermal_sensor_data));
+
+	data->sensor[0].location = 0x1;
+	data->sensor[0].caution_thresh =
+		(rd32(E1000_THHIGHTC) & 0xFF);
+	data->sensor[0].max_op_thresh =
+		(rd32(E1000_THLOWTC) & 0xFF);
+
+	/* Return the internal sensor only if ETS is unsupported */
+	hw->nvm.ops.read(hw, NVM_ETS_CFG, 1, &ets_offset);
+	if ((ets_offset == 0x0000) || (ets_offset == 0xFFFF))
+		return status;
+
+	hw->nvm.ops.read(hw, ets_offset, 1, &ets_cfg);
+	if (((ets_cfg & NVM_ETS_TYPE_MASK) >> NVM_ETS_TYPE_SHIFT)
+	    != NVM_ETS_TYPE_EMC)
+		return E1000_NOT_IMPLEMENTED;
+
+	low_thresh_delta = ((ets_cfg & NVM_ETS_LTHRES_DELTA_MASK) >>
+			    NVM_ETS_LTHRES_DELTA_SHIFT);
+	num_sensors = (ets_cfg & NVM_ETS_NUM_SENSORS_MASK);
+
+	for (i = 1; i <= num_sensors; i++) {
+		hw->nvm.ops.read(hw, (ets_offset + i), 1, &ets_sensor);
+		sensor_index = ((ets_sensor & NVM_ETS_DATA_INDEX_MASK) >>
+				NVM_ETS_DATA_INDEX_SHIFT);
+		sensor_location = ((ets_sensor & NVM_ETS_DATA_LOC_MASK) >>
+				   NVM_ETS_DATA_LOC_SHIFT);
+		therm_limit = ets_sensor & NVM_ETS_DATA_HTHRESH_MASK;
+
+		hw->phy.ops.write_i2c_byte(hw,
+			e1000_emc_therm_limit[sensor_index],
+			E1000_I2C_THERMAL_SENSOR_ADDR,
+			therm_limit);
+
+		if ((i < E1000_MAX_SENSORS) && (sensor_location != 0)) {
+			data->sensor[i].location = sensor_location;
+			data->sensor[i].caution_thresh = therm_limit;
+			data->sensor[i].max_op_thresh = therm_limit -
+							low_thresh_delta;
+		}
+	}
+	return status;
+}
+
 static struct e1000_mac_operations e1000_mac_ops_82575 = {
 	.init_hw              = igb_init_hw_82575,
 	.check_for_link       = igb_check_for_link_82575,
@@ -2283,4 +2937,3 @@ const struct e1000_info e1000_82575_info = {
 	.phy_ops = &e1000_phy_ops_82575,
 	.nvm_ops = &e1000_nvm_ops_82575,
 };
-
diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.h b/drivers/net/ethernet/intel/igb/e1000_82575.h
index e85c453..2e6a441 100644
--- a/drivers/net/ethernet/intel/igb/e1000_82575.h
+++ b/drivers/net/ethernet/intel/igb/e1000_82575.h
@@ -258,4 +258,35 @@ void igb_vmdq_set_replication_pf(struct e1000_hw *, bool);
 u16 igb_rxpbs_adjust_82580(u32 data);
 s32 igb_set_eee_i350(struct e1000_hw *);
 
+#define E1000_I2C_THERMAL_SENSOR_ADDR	0xF8
+#define E1000_EMC_INTERNAL_DATA		0x00
+#define E1000_EMC_INTERNAL_THERM_LIMIT	0x20
+#define E1000_EMC_DIODE1_DATA		0x01
+#define E1000_EMC_DIODE1_THERM_LIMIT	0x19
+#define E1000_EMC_DIODE2_DATA		0x23
+#define E1000_EMC_DIODE2_THERM_LIMIT	0x1A
+#define E1000_EMC_DIODE3_DATA		0x2A
+#define E1000_EMC_DIODE3_THERM_LIMIT	0x30
+
+s32 igb_get_thermal_sensor_data_generic(struct e1000_hw *hw);
+s32 igb_init_thermal_sensor_thresh_generic(struct e1000_hw *hw);
+
+/* I2C SDA and SCL timing parameters for standard mode */
+#define E1000_I2C_T_HD_STA	4
+#define E1000_I2C_T_LOW		5
+#define E1000_I2C_T_HIGH	4
+#define E1000_I2C_T_SU_STA	5
+#define E1000_I2C_T_HD_DATA	5
+#define E1000_I2C_T_SU_DATA	1
+#define E1000_I2C_T_RISE	1
+#define E1000_I2C_T_FALL	1
+#define E1000_I2C_T_SU_STO	4
+#define E1000_I2C_T_BUF		5
+
+s32 igb_set_i2c_bb(struct e1000_hw *hw);
+s32 igb_read_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset,
+				u8 dev_addr, u8 *data);
+s32 igb_write_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset,
+				 u8 dev_addr, u8 data);
+void igb_i2c_bus_clear(struct e1000_hw *hw);
 #endif
diff --git a/drivers/net/ethernet/intel/igb/e1000_defines.h b/drivers/net/ethernet/intel/igb/e1000_defines.h
index ec7e4fe..fed5746 100644
--- a/drivers/net/ethernet/intel/igb/e1000_defines.h
+++ b/drivers/net/ethernet/intel/igb/e1000_defines.h
@@ -460,7 +460,8 @@
 #define E1000_ERR_INVALID_ARGUMENT  16
 #define E1000_ERR_NO_SPACE          17
 #define E1000_ERR_NVM_PBA_SECTION   18
-#define E1000_ERR_INVM_VALUE_NOT_FOUND	19
+#define E1000_ERR_INVM_VALUE_NOT_FOUND 19
+#define E1000_ERR_I2C               20
 
 /* Loop limit on how long we wait for auto-negotiation to complete */
 #define COPPER_LINK_UP_LIMIT              10
@@ -645,6 +646,18 @@
 #define NVM_LED_1_CFG              0x001C
 #define NVM_LED_0_2_CFG            0x001F
 
+#define NVM_ETS_CFG			0x003E
+#define NVM_ETS_LTHRES_DELTA_MASK	0x07C0
+#define NVM_ETS_LTHRES_DELTA_SHIFT	6
+#define NVM_ETS_TYPE_MASK		0x0038
+#define NVM_ETS_TYPE_SHIFT		3
+#define NVM_ETS_TYPE_EMC		0x000
+#define NVM_ETS_NUM_SENSORS_MASK	0x0007
+#define NVM_ETS_DATA_LOC_MASK		0x3C00
+#define NVM_ETS_DATA_LOC_SHIFT		10
+#define NVM_ETS_DATA_INDEX_MASK		0x0300
+#define NVM_ETS_DATA_INDEX_SHIFT	8
+#define NVM_ETS_DATA_HTHRESH_MASK	0x00FF
 
 #define E1000_NVM_CFG_DONE_PORT_0  0x040000 /* MNG config cycle done */
 #define E1000_NVM_CFG_DONE_PORT_1  0x080000 /* ...for second port */
diff --git a/drivers/net/ethernet/intel/igb/e1000_hw.h b/drivers/net/ethernet/intel/igb/e1000_hw.h
index c2a51dc..837a274 100644
--- a/drivers/net/ethernet/intel/igb/e1000_hw.h
+++ b/drivers/net/ethernet/intel/igb/e1000_hw.h
@@ -342,6 +342,8 @@ struct e1000_phy_operations {
 	s32  (*set_d0_lplu_state)(struct e1000_hw *, bool);
 	s32  (*set_d3_lplu_state)(struct e1000_hw *, bool);
 	s32  (*write_reg)(struct e1000_hw *, u32, u16);
+	s32 (*read_i2c_byte)(struct e1000_hw *, u8, u8, u8 *);
+	s32 (*write_i2c_byte)(struct e1000_hw *, u8, u8, u8);
 };
 
 struct e1000_nvm_operations {
@@ -354,6 +356,19 @@ struct e1000_nvm_operations {
 	s32  (*valid_led_default)(struct e1000_hw *, u16 *);
 };
 
+#define E1000_MAX_SENSORS		3
+
+struct e1000_thermal_diode_data {
+	u8 location;
+	u8 temp;
+	u8 caution_thresh;
+	u8 max_op_thresh;
+};
+
+struct e1000_thermal_sensor_data {
+	struct e1000_thermal_diode_data sensor[E1000_MAX_SENSORS];
+};
+
 struct e1000_info {
 	s32 (*get_invariants)(struct e1000_hw *);
 	struct e1000_mac_operations *mac_ops;
@@ -399,6 +414,7 @@ struct e1000_mac_info {
 	bool report_tx_early;
 	bool serdes_has_link;
 	bool tx_pkt_filtering;
+	struct e1000_thermal_sensor_data thermal_sensor_data;
 };
 
 struct e1000_phy_info {
diff --git a/drivers/net/ethernet/intel/igb/e1000_regs.h b/drivers/net/ethernet/intel/igb/e1000_regs.h
index 35d1e4f..b446079 100644
--- a/drivers/net/ethernet/intel/igb/e1000_regs.h
+++ b/drivers/net/ethernet/intel/igb/e1000_regs.h
@@ -75,6 +75,15 @@
 #define E1000_FCRTL    0x02160  /* Flow Control Receive Threshold Low - RW */
 #define E1000_FCRTH    0x02168  /* Flow Control Receive Threshold High - RW */
 #define E1000_FCRTV    0x02460  /* Flow Control Refresh Timer Value - RW */
+#define E1000_I2CPARAMS        0x0102C /* SFPI2C Parameters Register - RW */
+#define E1000_I2CBB_EN      0x00000100  /* I2C - Bit Bang Enable */
+#define E1000_I2C_CLK_OUT   0x00000200  /* I2C- Clock */
+#define E1000_I2C_DATA_OUT  0x00000400  /* I2C- Data Out */
+#define E1000_I2C_DATA_OE_N 0x00000800  /* I2C- Data Output Enable */
+#define E1000_I2C_DATA_IN   0x00001000  /* I2C- Data In */
+#define E1000_I2C_CLK_OE_N  0x00002000  /* I2C- Clock Output Enable */
+#define E1000_I2C_CLK_IN    0x00004000  /* I2C- Clock In */
+#define E1000_I2C_CLK_STRETCH_DIS  0x00008000 /* I2C- Dis Clk Stretching */
 
 /* IEEE 1588 TIMESYNCH */
 #define E1000_TSYNCRXCTL 0x0B620 /* Rx Time Sync Control register - RW */
@@ -121,6 +130,12 @@
 
 /* Split and Replication RX Control - RW */
 #define E1000_RXPBS    0x02404  /* Rx Packet Buffer Size - RW */
+/* Thermal sensor configuration and status registers */
+#define E1000_THMJT	0x08100 /* Junction Temperature */
+#define E1000_THLOWTC	0x08104 /* Low Threshold Control */
+#define E1000_THMIDTC	0x08108 /* Mid Threshold Control */
+#define E1000_THHIGHTC	0x0810C /* High Threshold Control */
+#define E1000_THSTAT	0x08110 /* Thermal Sensor Status */
 /*
  * Convenience macros
  *
-- 
1.7.10.2

^ permalink raw reply related

* [net-next 2/9] igb: Add hwmon interface to export thermal data.
From: Jeff Kirsher @ 2012-06-09  8:20 UTC (permalink / raw)
  To: davem; +Cc: Carolyn Wyborny, netdev, gospo, sassmann, Jeff Kirsher
In-Reply-To: <1339230063-12545-1-git-send-email-jeffrey.t.kirsher@intel.com>

From: Carolyn Wyborny <carolyn.wyborny@intel.com>

Some of our adapters have thermal data available, this patch exports
this data via hwmon sysfs interface.

Signed-off-by: Carolyn Wyborny <carolyn.wyborny@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
 drivers/net/ethernet/intel/Kconfig           |   10 ++
 drivers/net/ethernet/intel/igb/Makefile      |    2 +-
 drivers/net/ethernet/intel/igb/e1000_82575.c |    4 +
 drivers/net/ethernet/intel/igb/e1000_hw.h    |    5 +-
 drivers/net/ethernet/intel/igb/igb.h         |   29 +++
 drivers/net/ethernet/intel/igb/igb_main.c    |   25 +++
 drivers/net/ethernet/intel/igb/igb_sysfs.c   |  245 ++++++++++++++++++++++++++
 7 files changed, 318 insertions(+), 2 deletions(-)
 create mode 100644 drivers/net/ethernet/intel/igb/igb_sysfs.c

diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig
index 79b07ec..fdb9280 100644
--- a/drivers/net/ethernet/intel/Kconfig
+++ b/drivers/net/ethernet/intel/Kconfig
@@ -111,6 +111,16 @@ config IGB
 	  To compile this driver as a module, choose M here. The module
 	  will be called igb.
 
+config IGB_HWMON
+	bool "Intel(R) PCI-Express Gigabit adapters HWMON support"
+	default y
+	depends on IGB && HWMON && !(IGB=y && HWMON=m)
+	---help---
+	  Say Y if you want to expose thermal sensor data on Intel devices.
+
+	  Some of our devices contain thermal sensors, both external and internal.
+	  This data is available via the hwmon sysfs interface.
+
 config IGB_DCA
 	bool "Direct Cache Access (DCA) Support"
 	default y
diff --git a/drivers/net/ethernet/intel/igb/Makefile b/drivers/net/ethernet/intel/igb/Makefile
index 97c197f..346c3de 100644
--- a/drivers/net/ethernet/intel/igb/Makefile
+++ b/drivers/net/ethernet/intel/igb/Makefile
@@ -34,6 +34,6 @@ obj-$(CONFIG_IGB) += igb.o
 
 igb-objs := igb_main.o igb_ethtool.o e1000_82575.o \
 	    e1000_mac.o e1000_nvm.o e1000_phy.o e1000_mbx.o \
-	    e1000_i210.o
+	    e1000_i210.o igb_sysfs.o
 
 igb-$(CONFIG_IGB_PTP) += igb_ptp.o
diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c
index 9623833..cd9e3e0 100644
--- a/drivers/net/ethernet/intel/igb/e1000_82575.c
+++ b/drivers/net/ethernet/intel/igb/e1000_82575.c
@@ -2916,6 +2916,10 @@ static struct e1000_mac_operations e1000_mac_ops_82575 = {
 	.rar_set              = igb_rar_set,
 	.read_mac_addr        = igb_read_mac_addr_82575,
 	.get_speed_and_duplex = igb_get_speed_and_duplex_copper,
+#ifdef CONFIG_IGB_HWMON
+	.get_thermal_sensor_data = igb_get_thermal_sensor_data_generic,
+	.init_thermal_sensor_thresh = igb_init_thermal_sensor_thresh_generic,
+#endif
 };
 
 static struct e1000_phy_operations e1000_phy_ops_82575 = {
diff --git a/drivers/net/ethernet/intel/igb/e1000_hw.h b/drivers/net/ethernet/intel/igb/e1000_hw.h
index 837a274..6dddbc6 100644
--- a/drivers/net/ethernet/intel/igb/e1000_hw.h
+++ b/drivers/net/ethernet/intel/igb/e1000_hw.h
@@ -325,7 +325,10 @@ struct e1000_mac_operations {
 	s32  (*get_speed_and_duplex)(struct e1000_hw *, u16 *, u16 *);
 	s32  (*acquire_swfw_sync)(struct e1000_hw *, u16);
 	void (*release_swfw_sync)(struct e1000_hw *, u16);
-
+#ifdef CONFIG_IGB_HWMON
+	s32 (*get_thermal_sensor_data)(struct e1000_hw *);
+	s32 (*init_thermal_sensor_thresh)(struct e1000_hw *);
+#endif
 };
 
 struct e1000_phy_operations {
diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
index ae6d3f3..4bf856f 100644
--- a/drivers/net/ethernet/intel/igb/igb.h
+++ b/drivers/net/ethernet/intel/igb/igb.h
@@ -281,6 +281,27 @@ static inline int igb_desc_unused(struct igb_ring *ring)
 	return ring->count + ring->next_to_clean - ring->next_to_use - 1;
 }
 
+#ifdef CONFIG_IGB_HWMON
+
+#define IGB_HWMON_TYPE_LOC	0
+#define IGB_HWMON_TYPE_TEMP	1
+#define IGB_HWMON_TYPE_CAUTION	2
+#define IGB_HWMON_TYPE_MAX	3
+
+struct hwmon_attr {
+	struct device_attribute dev_attr;
+	struct e1000_hw *hw;
+	struct e1000_thermal_diode_data *sensor;
+	char name[12];
+	};
+
+struct hwmon_buff {
+	struct device *device;
+	struct hwmon_attr *hwmon_list;
+	unsigned int n_hwmon;
+	};
+#endif /* CONFIG_IGB_HWMON */
+
 /* board specific private data structure */
 struct igb_adapter {
 	unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
@@ -371,6 +392,10 @@ struct igb_adapter {
 	spinlock_t tmreg_lock;
 	struct cyclecounter cc;
 	struct timecounter tc;
+#ifdef CONFIG_IGB_HWMON
+	struct hwmon_buff igb_hwmon_buff;
+	bool ets;
+#endif /* CONFIG_IGB_HWMON */
 };
 
 #define IGB_FLAG_HAS_MSI           (1 << 0)
@@ -429,6 +454,10 @@ extern void igb_systim_to_hwtstamp(struct igb_adapter *adapter,
 				   u64 systim);
 
 #endif
+#ifdef CONFIG_IGB_HWMON
+extern void igb_sysfs_exit(struct igb_adapter *adapter);
+extern int igb_sysfs_init(struct igb_adapter *adapter);
+#endif
 static inline s32 igb_reset_phy(struct e1000_hw *hw)
 {
 	if (hw->phy.ops.reset)
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index dd3bfe8..e94a99b 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -2119,6 +2119,27 @@ static int __devinit igb_probe(struct pci_dev *pdev,
 	}
 
 #endif
+#ifdef CONFIG_IGB_HWMON
+	/* Initialize the thermal sensor on i350 devices. */
+	if (hw->mac.type == e1000_i350 && hw->bus.func == 0) {
+		u16 ets_word;
+
+		/*
+		 * Read the NVM to determine if this i350 device supports an
+		 * external thermal sensor.
+		 */
+		hw->nvm.ops.read(hw, NVM_ETS_CFG, 1, &ets_word);
+		if (ets_word != 0x0000 && ets_word != 0xFFFF)
+			adapter->ets = true;
+		else
+			adapter->ets = false;
+		if (igb_sysfs_init(adapter))
+			dev_err(&pdev->dev,
+				"failed to allocate sysfs resources\n");
+	} else {
+		adapter->ets = false;
+	}
+#endif /* CONFIG_IGB_HWMON */
 #ifdef CONFIG_IGB_PTP
 	/* do hw tstamp init after resetting */
 	igb_ptp_init(adapter);
@@ -2201,6 +2222,10 @@ static void __devexit igb_remove(struct pci_dev *pdev)
 	igb_ptp_remove(adapter);
 
 #endif
+#ifdef CONFIG_IGB_HWMON
+	igb_sysfs_exit(adapter);
+
+#endif /* CONFIG_IGB_HWMON */
 	/*
 	 * The watchdog timer may be rescheduled, so explicitly
 	 * disable watchdog from being rescheduled.
diff --git a/drivers/net/ethernet/intel/igb/igb_sysfs.c b/drivers/net/ethernet/intel/igb/igb_sysfs.c
new file mode 100644
index 0000000..10ffcf7
--- /dev/null
+++ b/drivers/net/ethernet/intel/igb/igb_sysfs.c
@@ -0,0 +1,245 @@
+/*******************************************************************************
+
+  Intel(R) Gigabit Ethernet Linux driver
+  Copyright(c) 2007-2012 Intel Corporation.
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms and conditions of the GNU General Public License,
+  version 2, as published by the Free Software Foundation.
+
+  This program is distributed in the hope it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+  more details.
+
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+  The full GNU General Public License is included in this distribution in
+  the file called "COPYING".
+
+  Contact Information:
+  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+#include "igb.h"
+#include "e1000_82575.h"
+#include "e1000_hw.h"
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/sysfs.h>
+#include <linux/kobject.h>
+#include <linux/device.h>
+#include <linux/netdevice.h>
+#include <linux/hwmon.h>
+#include <linux/pci.h>
+
+#ifdef CONFIG_IGB_HWMON
+/* hwmon callback functions */
+static ssize_t igb_hwmon_show_location(struct device *dev,
+					 struct device_attribute *attr,
+					 char *buf)
+{
+	struct hwmon_attr *igb_attr = container_of(attr, struct hwmon_attr,
+						     dev_attr);
+	return sprintf(buf, "loc%u\n",
+		       igb_attr->sensor->location);
+}
+
+static ssize_t igb_hwmon_show_temp(struct device *dev,
+				     struct device_attribute *attr,
+				     char *buf)
+{
+	struct hwmon_attr *igb_attr = container_of(attr, struct hwmon_attr,
+						     dev_attr);
+	unsigned int value;
+
+	/* reset the temp field */
+	igb_attr->hw->mac.ops.get_thermal_sensor_data(igb_attr->hw);
+
+	value = igb_attr->sensor->temp;
+
+	/* display millidegree */
+	value *= 1000;
+
+	return sprintf(buf, "%u\n", value);
+}
+
+static ssize_t igb_hwmon_show_cautionthresh(struct device *dev,
+				     struct device_attribute *attr,
+				     char *buf)
+{
+	struct hwmon_attr *igb_attr = container_of(attr, struct hwmon_attr,
+						     dev_attr);
+	unsigned int value = igb_attr->sensor->caution_thresh;
+
+	/* display millidegree */
+	value *= 1000;
+
+	return sprintf(buf, "%u\n", value);
+}
+
+static ssize_t igb_hwmon_show_maxopthresh(struct device *dev,
+				     struct device_attribute *attr,
+				     char *buf)
+{
+	struct hwmon_attr *igb_attr = container_of(attr, struct hwmon_attr,
+						     dev_attr);
+	unsigned int value = igb_attr->sensor->max_op_thresh;
+
+	/* display millidegree */
+	value *= 1000;
+
+	return sprintf(buf, "%u\n", value);
+}
+
+/*
+ * igb_add_hwmon_attr - Create hwmon attr table for a hwmon sysfs file.
+ * @ adapter: pointer to the adapter structure
+ * @ offset: offset in the eeprom sensor data table
+ * @ type: type of sensor data to display
+ *
+ * For each file we want in hwmon's sysfs interface we need a device_attribute
+ * This is included in our hwmon_attr struct that contains the references to
+ * the data structures we need to get the data to display.
+ */
+static int igb_add_hwmon_attr(struct igb_adapter *adapter,
+				unsigned int offset, int type) {
+	int rc;
+	unsigned int n_attr;
+	struct hwmon_attr *igb_attr;
+
+	n_attr = adapter->igb_hwmon_buff.n_hwmon;
+	igb_attr = &adapter->igb_hwmon_buff.hwmon_list[n_attr];
+
+	switch (type) {
+	case IGB_HWMON_TYPE_LOC:
+		igb_attr->dev_attr.show = igb_hwmon_show_location;
+		snprintf(igb_attr->name, sizeof(igb_attr->name),
+			 "temp%u_label", offset);
+		break;
+	case IGB_HWMON_TYPE_TEMP:
+		igb_attr->dev_attr.show = igb_hwmon_show_temp;
+		snprintf(igb_attr->name, sizeof(igb_attr->name),
+			 "temp%u_input", offset);
+		break;
+	case IGB_HWMON_TYPE_CAUTION:
+		igb_attr->dev_attr.show = igb_hwmon_show_cautionthresh;
+		snprintf(igb_attr->name, sizeof(igb_attr->name),
+			 "temp%u_max", offset);
+		break;
+	case IGB_HWMON_TYPE_MAX:
+		igb_attr->dev_attr.show = igb_hwmon_show_maxopthresh;
+		snprintf(igb_attr->name, sizeof(igb_attr->name),
+			 "temp%u_crit", offset);
+		break;
+	default:
+		rc = -EPERM;
+		return rc;
+	}
+
+	/* These always the same regardless of type */
+	igb_attr->sensor =
+		&adapter->hw.mac.thermal_sensor_data.sensor[offset];
+	igb_attr->hw = &adapter->hw;
+	igb_attr->dev_attr.store = NULL;
+	igb_attr->dev_attr.attr.mode = S_IRUGO;
+	igb_attr->dev_attr.attr.name = igb_attr->name;
+
+	rc = device_create_file(&adapter->pdev->dev,
+				&igb_attr->dev_attr);
+
+	if (rc == 0)
+		++adapter->igb_hwmon_buff.n_hwmon;
+
+	return rc;
+}
+
+static void igb_sysfs_del_adapter(struct igb_adapter *adapter)
+{
+	int i;
+
+	if (adapter == NULL)
+		return;
+
+	for (i = 0; i < adapter->igb_hwmon_buff.n_hwmon; i++) {
+		device_remove_file(&adapter->pdev->dev,
+			   &adapter->igb_hwmon_buff.hwmon_list[i].dev_attr);
+	}
+
+	kfree(adapter->igb_hwmon_buff.hwmon_list);
+
+	if (adapter->igb_hwmon_buff.device)
+		hwmon_device_unregister(adapter->igb_hwmon_buff.device);
+}
+
+/* called from igb_main.c */
+void igb_sysfs_exit(struct igb_adapter *adapter)
+{
+	igb_sysfs_del_adapter(adapter);
+}
+
+/* called from igb_main.c */
+int igb_sysfs_init(struct igb_adapter *adapter)
+{
+	struct hwmon_buff *igb_hwmon = &adapter->igb_hwmon_buff;
+	unsigned int i;
+	int n_attrs;
+	int rc = 0;
+
+	/* If this method isn't defined we don't support thermals */
+	if (adapter->hw.mac.ops.init_thermal_sensor_thresh == NULL)
+		goto exit;
+
+	/* Don't create thermal hwmon interface if no sensors present */
+	rc = (adapter->hw.mac.ops.init_thermal_sensor_thresh(&adapter->hw));
+		if (rc)
+			goto exit;
+
+	/*
+	 * Allocation space for max attributs
+	 * max num sensors * values (loc, temp, max, caution)
+	 */
+	n_attrs = E1000_MAX_SENSORS * 4;
+	igb_hwmon->hwmon_list = kcalloc(n_attrs, sizeof(struct hwmon_attr),
+					  GFP_KERNEL);
+	if (!igb_hwmon->hwmon_list) {
+		rc = -ENOMEM;
+		goto err;
+	}
+
+	igb_hwmon->device = hwmon_device_register(&adapter->pdev->dev);
+	if (IS_ERR(igb_hwmon->device)) {
+		rc = PTR_ERR(igb_hwmon->device);
+		goto err;
+	}
+
+	for (i = 0; i < E1000_MAX_SENSORS; i++) {
+		/*
+		 * Only create hwmon sysfs entries for sensors that have
+		 * meaningful data for.
+		 */
+		if (adapter->hw.mac.thermal_sensor_data.sensor[i].location == 0)
+			continue;
+
+		/* Bail if any hwmon attr struct fails to initialize */
+		rc = igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_CAUTION);
+		rc |= igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_LOC);
+		rc |= igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_TEMP);
+		rc |= igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_MAX);
+		if (rc)
+			goto err;
+	}
+
+	goto exit;
+
+err:
+	igb_sysfs_del_adapter(adapter);
+exit:
+	return rc;
+}
+#endif /* CONFIG_IGB_HWMON */
-- 
1.7.10.2

^ permalink raw reply related


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