* [PATCH] iproute2: ip: add wilcard support for device matching
From: Octavian Purdila @ 2010-12-10 14:58 UTC (permalink / raw)
To: netdev; +Cc: Lucian Adrian Grijincu, Vlad Dogaru, Octavian Purdila
Allow the users to specify a wildcard when selecting a device:
$ ip set link dev dummy* up
We do this by expanding the original command line in multiple lines
which we then feed via a pipe to a forked ip processed run in batch
mode.
Signed-off-by: Octavian Purdila <opurdila@ixiacom.com>
---
ip/ip.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 70 insertions(+), 0 deletions(-)
diff --git a/ip/ip.c b/ip/ip.c
index b127d57..2e26488 100644
--- a/ip/ip.c
+++ b/ip/ip.c
@@ -18,6 +18,8 @@
#include <netinet/in.h>
#include <string.h>
#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
#include "SNAPSHOT.h"
#include "utils.h"
@@ -139,10 +141,72 @@ static int batch(const char *name)
return ret;
}
+int main(int argc, char **argv);
+
+int expand_dev_pattern(int argc, char **argv, int pos)
+{
+ FILE *proc;
+ size_t n, dev_no;
+ char scanf_pattern[64], *line = NULL, *dev_base = argv[pos];
+ int p[2], i;
+ pid_t pid;
+
+ *strchr(dev_base, '*') = 0;
+ snprintf(scanf_pattern, sizeof(scanf_pattern), " %s%%d:", dev_base);
+
+ if (pipe(p) < 0) {
+ fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
+ return -1;
+ }
+
+ pid = fork();
+ switch (pid) {
+ case -1:
+ fprintf(stderr, "fork failed: %s\n", strerror(errno));
+ return -1;
+ case 0:
+ {
+ char *nargv[] = { argv[0], "-b", "-" };
+ int ret;
+
+ dup2(p[0], 0); close(p[0]); close(p[1]);
+ ret = main(3, nargv);
+ exit(ret);
+ }
+ default:
+ dup2(p[1], 1); close(p[0]); close(p[1]);
+ }
+
+ proc = fopen("/proc/net/dev", "r");
+ if (!proc) {
+ fprintf(stderr, "can't open /proc/net/dev\n");
+ return -1;
+ }
+
+ while (getline(&line, &n, proc) > 0) {
+ if (sscanf(line, scanf_pattern, &dev_no) == 1) {
+ for (i = 1; i < argc; i++)
+ if (i != pos)
+ printf("%s ", argv[i]);
+ else
+ printf("%s%d ", dev_base, dev_no);
+ printf("\n");
+ }
+ }
+ free(line);
+
+ fflush(stdout); close(1);
+
+ waitpid(pid, NULL, 0);
+
+ return 0;
+}
int main(int argc, char **argv)
{
char *basename;
+ int i = 0;
+
basename = strrchr(argv[0], '/');
if (basename == NULL)
@@ -150,6 +214,12 @@ int main(int argc, char **argv)
else
basename++;
+ for (i = 1; i < argc - 1; i++) {
+ if (matches(argv[i], "dev") == 0 && strchr(argv[i+1], '*')) {
+ return expand_dev_pattern(argc, argv, i+1);
+ }
+ }
+
while (argc > 1) {
char *opt = argv[1];
if (strcmp(opt,"--") == 0) {
--
1.7.1
^ permalink raw reply related
* [PATCH] [Bug 24472] Kernel panic - not syncing: Fatal Exception
From: Andrej Ota @ 2010-12-10 14:49 UTC (permalink / raw)
To: Jarek Poplawski
Cc: Paweł Staszewski, Andrew Morton, netdev, Paul Mackerras,
bugzilla-daemon, bugme-daemon, pstaszewski, Eric Dumazet,
David Miller
In-Reply-To: <20101210091505.GA7868@ff.dom.local>
Move kfree_skb which was causing memory corruption to new location, while still keeping appropriate return value for function __pppoe_xmit. Prevents memory corruption and consequent kernel panic when PPPoE peer terminates the link.
Signed-off-by: Andrej Ota [andrej@ota.si]
Reported-by: Pawel Staszewski [pstaszewski@artcom.pl]
---
drivers/net/pppoe.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index d72fb05..1a21dce 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -924,8 +924,10 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb)
/* Copy the data if there is no space for the header or if it's
* read-only.
*/
- if (skb_cow_head(skb, sizeof(*ph) + dev->hard_header_len))
+ if (skb_cow_head(skb, sizeof(*ph) + dev->hard_header_len)) {
+ kfree_skb(skb);
goto abort;
+ }
__skb_push(skb, sizeof(*ph));
skb_reset_network_header(skb);
@@ -947,7 +949,6 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb)
return 1;
abort:
- kfree_skb(skb);
return 0;
}
---
Andrej Ota.
^ permalink raw reply related
* Re: Adding Support for SG,GSO,GRO
From: David Lamparter @ 2010-12-10 14:31 UTC (permalink / raw)
To: Michał Mirosław; +Cc: David Miller, bhutchings, srk, netdev
In-Reply-To: <AANLkTi=7NLkHW6c88gUcyW8i0Wwmf2Cw4NdmRiGci4kE@mail.gmail.com>
On Fri, Dec 10, 2010 at 03:18:11PM +0100, Michał Mirosław wrote:
> I'm trying to understand the dependency because it looks artificial for me.
You have the data you want to send in the RAM, somewhere, possibly
scattered. The application calls sendfile(). The kernel puts the
transmission in the network card's queue, which might already have lots
of entries.
A millisecond later - an eternity for the CPU - the card decides to do
the transmission.
However, the data might have changed in the meantime.
sendfile() is defined so that it works asynchronously, that means if you
change the data while it is in the queue, you get unpredictable results.
But, what you should NOT get is packets with an invalid checksum.
Whatever data you are sending, it needs to have a correct checksum.
Now, if the card does the checksum itself, everything is fine. But what
are you supposed to do if the card can't checksum? Call back the kernel
at the point where the card does the TX? That's pointless (and racy).
Pre-calculate the Checksum at submission time? Doesn't work, you would
have to make a copy of the data, so it doesn't change anymore, so the
checksum stays correct. But not copying the data is the whole point of
sendfile().
You see why SG without HW checksum is useless here?
-David
^ permalink raw reply
* Re: Adding Support for SG,GSO,GRO
From: Michał Mirosław @ 2010-12-10 14:18 UTC (permalink / raw)
To: David Miller; +Cc: bhutchings, srk, netdev
In-Reply-To: <20101209.113806.71114756.davem@davemloft.net>
2010/12/9 David Miller <davem@davemloft.net>:
> From: Michał Mirosław <mirqus@gmail.com>
> Date: Thu, 9 Dec 2010 19:47:57 +0100
>> Isn't that condition too broad? If the data could change after packet
>> is submitted to the driver then results would be unpredictable and
>> allow sending wrong data with correct (because hw-calculated)
>> checksum.
> They are intentionally like that, without question.
>
> Otherwise we'd need to interlock with all application mapped,
> filesystem, and other page writes while sending any page over the
> network.
>
> We absolutely do not want to have to freeze every page we try to send
> via sendfile() or similar, the cost is just too high.
>
> If the application or networked filesystem needs such synchronization,
> it provides it for itself.
>
> For example, SAMBA only uses sendfile() when the file has an op-lock
> held on it.
>
> The checksum requirement for using SG is not going away, so continuing
> to discuss along the lines of removing that requirement is not a good
> use of your time I don't think.
I'm trying to understand the dependency because it looks artificial for me.
Unless I totally misunderstood, you say that we accept bogus data to
being sent using sendfile(). If yes, then we might as well allow
broken checksum (CPU calculated, before data changed and then was sent
to network).
If the splice/sendfile is taken out of the picture, are there any
other scenarios, when data pages could be changed after
ndo_start_xmit() entry and before TX DMA completion (between dma_map
.. dma_unmap)? And is it really what can happen with splice/sendfile?
Best Regards,
Michał Mirosław
^ permalink raw reply
* [PATCH v2] bridge: Fix return values of br_multicast_add_group/br_multicast_new_group
From: Tobias Klauser @ 2010-12-10 13:18 UTC (permalink / raw)
To: Stephen Hemminger, David S. Miller, bridge; +Cc: netdev
In-Reply-To: <20101209082924.6d797871@nehalam>
If br_multicast_new_group returns NULL, we would return 0 (no error) to
the caller of br_multicast_add_group, which is not what we want. Instead
br_multicast_new_group should return ERR_PTR(-ENOMEM) in this case.
Also propagate the error number returned by br_mdb_rehash properly.
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
---
net/bridge/br_multicast.c | 10 ++++++----
1 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 326e599..85a0398 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -654,11 +654,13 @@ static struct net_bridge_mdb_entry *br_multicast_new_group(
struct net_bridge_mdb_htable *mdb;
struct net_bridge_mdb_entry *mp;
int hash;
+ int err;
mdb = rcu_dereference_protected(br->mdb, 1);
if (!mdb) {
- if (br_mdb_rehash(&br->mdb, BR_HASH_SIZE, 0))
- return NULL;
+ err = br_mdb_rehash(&br->mdb, BR_HASH_SIZE, 0);
+ if (err)
+ return ERR_PTR(err);
goto rehash;
}
@@ -680,7 +682,7 @@ rehash:
mp = kzalloc(sizeof(*mp), GFP_ATOMIC);
if (unlikely(!mp))
- goto out;
+ return ERR_PTR(-ENOMEM);
mp->br = br;
mp->addr = *group;
@@ -713,7 +715,7 @@ static int br_multicast_add_group(struct net_bridge *br,
mp = br_multicast_new_group(br, port, group);
err = PTR_ERR(mp);
- if (unlikely(IS_ERR(mp) || !mp))
+ if (IS_ERR(mp))
goto err;
if (!port) {
--
1.7.0.4
^ permalink raw reply related
* Re: [PATCH] Sysctl interface to UNIX_INFLIGHT_TRIGGER_GC v.3
From: Eric Dumazet @ 2010-12-10 13:04 UTC (permalink / raw)
To: pavel; +Cc: Shan Wei, netdev
In-Reply-To: <4D0221A2.4010602@pavlinux.ru>
Le vendredi 10 décembre 2010 à 15:48 +0300, Pavel Vasilyev a écrit :
> On 10.12.2010 06:45, Shan Wei wrote:
> > Pavel Vasilyev wrote, at 12/10/2010 01:26 AM:
> >> Sysctl interface to UNIX_INFLIGHT_TRIGGER_GC.
> >> IMHO convenient for testing.
> >>
> >> +inflight_trigger_gc - INTEGER
> >> + The maximal number of inflight sockets for force garbage collect.
> >> +
> >> + Default: 16000
> >
> > 1) For lower payload and enough memory, it's not necessary to force garbage collection.
> > So set it to 0, disable gc.
>
>
> May be, set default to 2000, and zero to disable
>
zero to disable ?
Maybe you missed commit 9915672d41273f5b77 intent.
If you have no limit (like old kernels), you can freeze your machine,
even if it has terabytes of ram, running a single program, even as a non
root user.
When we discussed about the fix, we said a limit was needed, obviously.
Now you'll have to prove we need to make it a sysctl (yet
another /proc/sys/net parameter, yet another documentation to add...)
Even changing default from 16000 to 2000 must be for a valid reason (a
real use case)
^ permalink raw reply
* Re: [PATCH] Sysctl interface to UNIX_INFLIGHT_TRIGGER_GC v.3
From: Pavel Vasilyev @ 2010-12-10 12:48 UTC (permalink / raw)
To: Shan Wei; +Cc: netdev
In-Reply-To: <4D01A26C.8060608@cn.fujitsu.com>
[-- Attachment #1: Type: text/plain, Size: 641 bytes --]
On 10.12.2010 06:45, Shan Wei wrote:
> Pavel Vasilyev wrote, at 12/10/2010 01:26 AM:
>> Sysctl interface to UNIX_INFLIGHT_TRIGGER_GC.
>> IMHO convenient for testing.
>>
>> +inflight_trigger_gc - INTEGER
>> + The maximal number of inflight sockets for force garbage collect.
>> +
>> + Default: 16000
>
> 1) For lower payload and enough memory, it's not necessary to force garbage collection.
> So set it to 0, disable gc.
May be, set default to 2000, and zero to disable
> 2) Copy your patch to the mail, for other guys to review it.
Where me find other guys? :)
--
Pavel.
[-- Attachment #2: sysctl.inflight_trigger_gc.patch --]
[-- Type: text/x-patch, Size: 2897 bytes --]
Documentation/networking/ip-sysctl.txt | 6 ++++++
include/net/af_unix.h | 1 +
net/unix/garbage.c | 8 +++++---
net/unix/sysctl_net_unix.c | 9 +++++++++
4 files changed, 21 insertions(+), 3 deletions(-)
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index 3c5e465..f0c4b6b 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -1463,6 +1463,12 @@ max_dgram_qlen - INTEGER
Default: 10
+inflight_trigger_gc - INTEGER
+ The maximal number of inflight sockets for force garbage collect.
+
+ 0 - disable force garbage collection.
+
+ Default: 2000
UNDOCUMENTED:
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index 18e5c3f..ea580e4 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -15,6 +15,7 @@ extern struct sock *unix_get_socket(struct file *filp);
#define UNIX_HASH_SIZE 256
extern unsigned int unix_tot_inflight;
+extern unsigned int sysctl_inflight_trigger_gc;
struct unix_address {
atomic_t refcnt;
diff --git a/net/unix/garbage.c b/net/unix/garbage.c
index f89f83b..c2f3e98 100644
--- a/net/unix/garbage.c
+++ b/net/unix/garbage.c
@@ -94,7 +94,7 @@ static DEFINE_SPINLOCK(unix_gc_lock);
static DECLARE_WAIT_QUEUE_HEAD(unix_gc_wait);
unsigned int unix_tot_inflight;
-
+unsigned int sysctl_inflight_trigger_gc = 2000;
struct sock *unix_get_socket(struct file *filp)
{
@@ -259,7 +259,6 @@ static void inc_inflight_move_tail(struct unix_sock *u)
}
static bool gc_in_progress = false;
-#define UNIX_INFLIGHT_TRIGGER_GC 16000
void wait_for_unix_gc(void)
{
@@ -267,8 +266,11 @@ void wait_for_unix_gc(void)
* If number of inflight sockets is insane,
* force a garbage collect right now.
*/
- if (unix_tot_inflight > UNIX_INFLIGHT_TRIGGER_GC && !gc_in_progress)
+ if (!sysctl_inflight_trigger_gc &&
+ (unix_tot_inflight > sysctl_inflight_trigger_gc
+ && !gc_in_progress))
unix_gc();
+
wait_event(unix_gc_wait, gc_in_progress == false);
}
diff --git a/net/unix/sysctl_net_unix.c b/net/unix/sysctl_net_unix.c
index 397cffe..c807235 100644
--- a/net/unix/sysctl_net_unix.c
+++ b/net/unix/sysctl_net_unix.c
@@ -23,6 +23,13 @@ static ctl_table unix_table[] = {
.mode = 0644,
.proc_handler = proc_dointvec
},
+ {
+ .procname = "inflight_trigger_gc",
+ .data = &sysctl_inflight_trigger_gc,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec
+ },
{ }
};
@@ -41,6 +48,8 @@ int __net_init unix_sysctl_register(struct net *net)
goto err_alloc;
table[0].data = &net->unx.sysctl_max_dgram_qlen;
+ table[1].data = &sysctl_inflight_trigger_gc;
+
net->unx.ctl = register_net_sysctl_table(net, unix_path, table);
if (net->unx.ctl == NULL)
goto err_reg;
---
Signed-off-by: Pavel Vasilyev <pavel@pavlinux.ru>
^ permalink raw reply related
* [patch] isdn: return -EFAULT if copy_from_user() fails
From: Dan Carpenter @ 2010-12-10 12:40 UTC (permalink / raw)
To: Karsten Keil; +Cc: David S. Miller, netdev, kernel-janitors
We should be returning -EFAULT here.
Mostly this patch is to silence a smatch warning. The upper levels
of this driver turn all non-zero return values from isar_load_firmware()
into 1.
Signed-off-by: Dan Carpenter <error27@gmail.com>
diff --git a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c
index 2e72227..9cd4829 100644
--- a/drivers/isdn/hisax/isar.c
+++ b/drivers/isdn/hisax/isar.c
@@ -212,9 +212,9 @@ isar_load_firmware(struct IsdnCardState *cs, u_char __user *buf)
cs->debug &= ~(L1_DEB_HSCX | L1_DEB_HSCX_FIFO);
#endif
- if ((ret = copy_from_user(&size, p, sizeof(int)))) {
+ if (copy_from_user(&size, p, sizeof(int))) {
printk(KERN_ERR"isar_load_firmware copy_from_user ret %d\n", ret);
- return ret;
+ return -EFAULT;
}
p += sizeof(int);
printk(KERN_DEBUG"isar_load_firmware size: %d\n", size);
^ permalink raw reply related
* Re: [net-next-2.6 25/27] e1000e: static analysis tools complain of a possible null ptr p dereference
From: Joe Perches @ 2010-12-10 12:44 UTC (permalink / raw)
To: Jeff Kirsher; +Cc: davem, davem, Bruce Allan, netdev, gospo, bphilips
In-Reply-To: <1291975585-30576-2-git-send-email-jeffrey.t.kirsher@intel.com>
On Fri, 2010-12-10 at 02:06 -0800, Jeff Kirsher wrote:
> diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c
[]
> + default:
> + data[i] = 0;
> + continue;
> + break;
Using
continue;
break;
is odd and unhelpful.
Just continue; is sufficient and clear.
^ permalink raw reply
* [PATCH 1/1] dccp: remove unused macros
From: Gerrit Renker @ 2010-12-10 11:59 UTC (permalink / raw)
To: davem; +Cc: dccp, netdev, Shan Wei
In-Reply-To: <1291982371-5666-1-git-send-email-gerrit@erg.abdn.ac.uk>
From: Shan Wei <shanwei@cn.fujitsu.com>
Remove macros which have been unused since the initial implementation
(commit 7c657876b63cb1d8a2ec06f8fc6c37bb8412e66c, [DCCP]: Initial
implementation from Tue Aug 9 20:14:34 2005 -0700).
Signed-off-by: Shan Wei <shanwei@cn.fujitsu.com>
Acked-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
---
net/dccp/dccp.h | 8 --------
1 files changed, 0 insertions(+), 8 deletions(-)
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index 48ad5d9..4508705 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -93,9 +93,6 @@ extern void dccp_time_wait(struct sock *sk, int state, int timeo);
#define DCCP_FALLBACK_RTT (USEC_PER_SEC / 5)
#define DCCP_SANE_RTT_MAX (3 * USEC_PER_SEC)
-/* Maximal interval between probes for local resources. */
-#define DCCP_RESOURCE_PROBE_INTERVAL ((unsigned)(HZ / 2U))
-
/* sysctl variables for DCCP */
extern int sysctl_dccp_request_retries;
extern int sysctl_dccp_retries1;
@@ -203,12 +200,7 @@ struct dccp_mib {
DECLARE_SNMP_STAT(struct dccp_mib, dccp_statistics);
#define DCCP_INC_STATS(field) SNMP_INC_STATS(dccp_statistics, field)
#define DCCP_INC_STATS_BH(field) SNMP_INC_STATS_BH(dccp_statistics, field)
-#define DCCP_INC_STATS_USER(field) SNMP_INC_STATS_USER(dccp_statistics, field)
#define DCCP_DEC_STATS(field) SNMP_DEC_STATS(dccp_statistics, field)
-#define DCCP_ADD_STATS_BH(field, val) \
- SNMP_ADD_STATS_BH(dccp_statistics, field, val)
-#define DCCP_ADD_STATS_USER(field, val) \
- SNMP_ADD_STATS_USER(dccp_statistics, field, val)
/*
* Checksumming routines
^ permalink raw reply related
* net-next-2.6 [Patch 1/1] dccp: dead code elimination
From: Gerrit Renker @ 2010-12-10 11:59 UTC (permalink / raw)
To: davem; +Cc: dccp, netdev
In-Reply-To: <4D01FBBE.2030705@cn.fujitsu.com>
Dave,
can you please consider the attached patch - it removes indeed dead code.
I have also placed this in into a fresh (today's) copy of net-next-2.6, on
git://eden-feed.erg.abdn.ac.uk/net-next-2.6 [subtree 'dccp']
Shan,
I have edited the commit message (s/marcos/macros/). In future, please
can you cc: your patches to netdev@vger also. Thank you.
Gerrit
^ permalink raw reply
* Re: [RFC PATCH V2 5/5] Add TX zero copy in macvtap
From: Eric Dumazet @ 2010-12-10 10:27 UTC (permalink / raw)
To: Shirley Ma
Cc: Avi Kivity, Arnd Bergmann, mst, xiaohui.xin, netdev, kvm,
linux-kernel
In-Reply-To: <1291976026.2167.49.camel@localhost.localdomain>
Le vendredi 10 décembre 2010 à 02:13 -0800, Shirley Ma a écrit :
> + while (len) {
> + f = &skb_shinfo(skb)->frags[i];
> + f->page = page[i];
> + f->page_offset = base & ~PAGE_MASK;
> + f->size = min_t(int, len, PAGE_SIZE - f->page_offset);
> + skb->data_len += f->size;
> + skb->len += f->size;
> + skb->truesize += f->size;
> + skb_shinfo(skb)->nr_frags++;
> + /* increase sk_wmem_alloc */
> + atomic_add(f->size, &skb->sk->sk_wmem_alloc);
> + base += f->size;
> + len -= f->size;
> + i++;
> + }
You could make one atomic_add() outside of the loop, and factorize many
things...
atomic_add(len, &skb->sk->sk_wmem_alloc);
skb->data_len += len;
skb->len += len;
skb->truesize += len;
while (len) {
...
}
^ permalink raw reply
* Re: [RFC PATCH V2 0/5] macvtap TX zero copy between guest and host kernel
From: Shirley Ma @ 2010-12-10 10:16 UTC (permalink / raw)
To: Avi Kivity; +Cc: Arnd Bergmann, mst, xiaohui.xin, netdev, kvm, linux-kernel
In-Reply-To: <1291974691.2167.24.camel@localhost.localdomain>
This patch has built and tested against most recent linus git tree. But
I haven't done checkpatch yet. I would like to know whether this
approach is acceptable or not first.
Thanks
Shirley
^ permalink raw reply
* [RFC PATCH V2 5/5] Add TX zero copy in macvtap
From: Shirley Ma @ 2010-12-10 10:13 UTC (permalink / raw)
To: Avi Kivity, Arnd Bergmann, mst; +Cc: xiaohui.xin, netdev, kvm, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 6174 bytes --]
Only when buffer size is greater than GOODCOPY_LEN (128), macvtap enables zero-copy.
Signed-off-by: Shirley Ma <xma@us.ibm.com>
---
drivers/net/macvtap.c | 128 ++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 116 insertions(+), 12 deletions(-)
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index 4256727..2ec9692 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -60,6 +60,7 @@ static struct proto macvtap_proto = {
*/
static dev_t macvtap_major;
#define MACVTAP_NUM_DEVS 65536
+#define GOODCOPY_LEN (L1_CACHE_BYTES < 128 ? 128 : L1_CACHE_BYTES)
static struct class *macvtap_class;
static struct cdev macvtap_cdev;
@@ -338,6 +339,7 @@ static int macvtap_open(struct inode *inode, struct file *file)
{
struct net *net = current->nsproxy->net_ns;
struct net_device *dev = dev_get_by_index(net, iminor(inode));
+ struct macvlan_dev *vlan = netdev_priv(dev);
struct macvtap_queue *q;
int err;
@@ -367,6 +369,16 @@ static int macvtap_open(struct inode *inode, struct file *file)
q->flags = IFF_VNET_HDR | IFF_NO_PI | IFF_TAP;
q->vnet_hdr_sz = sizeof(struct virtio_net_hdr);
+ /*
+ * so far only VM uses macvtap, enable zero copy between guest
+ * kernel and host kernel when lower device supports high memory
+ * DMA
+ */
+ if (vlan) {
+ if (vlan->lowerdev->features & NETIF_F_ZEROCOPY)
+ sock_set_flag(&q->sk, SOCK_ZEROCOPY);
+ }
+
err = macvtap_set_queue(dev, file, q);
if (err)
sock_put(&q->sk);
@@ -431,6 +443,80 @@ static inline struct sk_buff *macvtap_alloc_skb(struct sock *sk, size_t prepad,
return skb;
}
+/* set skb frags from iovec, this can move to core network code for reuse */
+static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from,
+ int offset, size_t count)
+{
+ int len = iov_length(from, count) - offset;
+ int copy = skb_headlen(skb);
+ int size, offset1 = 0;
+ int i = 0;
+ skb_frag_t *f;
+
+ /* Skip over from offset */
+ while (offset >= from->iov_len) {
+ offset -= from->iov_len;
+ ++from;
+ --count;
+ }
+
+ /* copy up to skb headlen */
+ while (copy > 0) {
+ size = min_t(unsigned int, copy, from->iov_len - offset);
+ if (copy_from_user(skb->data + offset1, from->iov_base + offset,
+ size))
+ return -EFAULT;
+ if (copy > size) {
+ ++from;
+ --count;
+ }
+ copy -= size;
+ offset1 += size;
+ offset = 0;
+ }
+
+ if (len == offset1)
+ return 0;
+
+ while (count--) {
+ struct page *page[MAX_SKB_FRAGS];
+ int num_pages;
+ unsigned long base;
+
+ len = from->iov_len - offset1;
+ if (!len) {
+ offset1 = 0;
+ ++from;
+ continue;
+ }
+ base = (unsigned long)from->iov_base + offset1;
+ size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT;
+ num_pages = get_user_pages_fast(base, size, 0, &page[i]);
+ if ((num_pages != size) ||
+ (num_pages > MAX_SKB_FRAGS - skb_shinfo(skb)->nr_frags))
+ /* put_page is in skb free */
+ return -EFAULT;
+ while (len) {
+ f = &skb_shinfo(skb)->frags[i];
+ f->page = page[i];
+ f->page_offset = base & ~PAGE_MASK;
+ f->size = min_t(int, len, PAGE_SIZE - f->page_offset);
+ skb->data_len += f->size;
+ skb->len += f->size;
+ skb->truesize += f->size;
+ skb_shinfo(skb)->nr_frags++;
+ /* increase sk_wmem_alloc */
+ atomic_add(f->size, &skb->sk->sk_wmem_alloc);
+ base += f->size;
+ len -= f->size;
+ i++;
+ }
+ offset1 = 0;
+ ++from;
+ }
+ return 0;
+}
+
/*
* macvtap_skb_from_vnet_hdr and macvtap_skb_to_vnet_hdr should
* be shared with the tun/tap driver.
@@ -514,17 +600,19 @@ static int macvtap_skb_to_vnet_hdr(const struct sk_buff *skb,
/* Get packet from user space buffer */
-static ssize_t macvtap_get_user(struct macvtap_queue *q,
- const struct iovec *iv, size_t count,
- int noblock)
+static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
+ const struct iovec *iv, unsigned long total_len,
+ size_t count, int noblock)
{
struct sk_buff *skb;
struct macvlan_dev *vlan;
- size_t len = count;
+ unsigned long len = total_len;
int err;
struct virtio_net_hdr vnet_hdr = { 0 };
int vnet_hdr_len = 0;
+ int copylen, zerocopy;
+ zerocopy = sock_flag(&q->sk, SOCK_ZEROCOPY) && (len > GOODCOPY_LEN);
if (q->flags & IFF_VNET_HDR) {
vnet_hdr_len = q->vnet_hdr_sz;
@@ -550,12 +638,28 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q,
if (unlikely(len < ETH_HLEN))
goto err;
- skb = macvtap_alloc_skb(&q->sk, NET_IP_ALIGN, len, vnet_hdr.hdr_len,
- noblock, &err);
+ if (zerocopy)
+ copylen = vnet_hdr.hdr_len;
+ else
+ copylen = len;
+
+ skb = macvtap_alloc_skb(&q->sk, NET_IP_ALIGN, copylen,
+ vnet_hdr.hdr_len, noblock, &err);
if (!skb)
goto err;
-
- err = skb_copy_datagram_from_iovec(skb, 0, iv, vnet_hdr_len, len);
+
+ if (zerocopy)
+ err = zerocopy_sg_from_iovec(skb, iv, vnet_hdr_len, count);
+ else
+ err = skb_copy_datagram_from_iovec(skb, 0, iv, vnet_hdr_len,
+ len);
+ if (sock_flag(&q->sk, SOCK_ZEROCOPY)) {
+ struct skb_ubuf_info pend =
+ (struct skb_ubuf_info *)m->msg_control;
+
+ skb_shinfo(skb)->ubuf.callback = pend.callback;
+ skb_shinfo(skb)->ubuf.desc = pend.desc;
+ }
if (err)
goto err_kfree;
@@ -577,7 +681,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q,
kfree_skb(skb);
rcu_read_unlock_bh();
- return count;
+ return total_len;
err_kfree:
kfree_skb(skb);
@@ -599,8 +703,8 @@ static ssize_t macvtap_aio_write(struct kiocb *iocb, const struct iovec *iv,
ssize_t result = -ENOLINK;
struct macvtap_queue *q = file->private_data;
- result = macvtap_get_user(q, iv, iov_length(iv, count),
- file->f_flags & O_NONBLOCK);
+ result = macvtap_get_user(q, NULL, iv, iov_length(iv, count), count,
+ file->f_flags & O_NONBLOCK);
return result;
}
@@ -813,7 +917,7 @@ static int macvtap_sendmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *m, size_t total_len)
{
struct macvtap_queue *q = container_of(sock, struct macvtap_queue, sock);
- return macvtap_get_user(q, m->msg_iov, total_len,
+ return macvtap_get_user(q, m, m->msg_iov, total_len, m->msg_iovlen,
m->msg_flags & MSG_DONTWAIT);
}
[-- Attachment #2: macvtap-zero.patch --]
[-- Type: text/x-patch, Size: 6039 bytes --]
drivers/net/macvtap.c | 128 ++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 116 insertions(+), 12 deletions(-)
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index 4256727..2ec9692 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -60,6 +60,7 @@ static struct proto macvtap_proto = {
*/
static dev_t macvtap_major;
#define MACVTAP_NUM_DEVS 65536
+#define GOODCOPY_LEN (L1_CACHE_BYTES < 128 ? 128 : L1_CACHE_BYTES)
static struct class *macvtap_class;
static struct cdev macvtap_cdev;
@@ -338,6 +339,7 @@ static int macvtap_open(struct inode *inode, struct file *file)
{
struct net *net = current->nsproxy->net_ns;
struct net_device *dev = dev_get_by_index(net, iminor(inode));
+ struct macvlan_dev *vlan = netdev_priv(dev);
struct macvtap_queue *q;
int err;
@@ -367,6 +369,16 @@ static int macvtap_open(struct inode *inode, struct file *file)
q->flags = IFF_VNET_HDR | IFF_NO_PI | IFF_TAP;
q->vnet_hdr_sz = sizeof(struct virtio_net_hdr);
+ /*
+ * so far only VM uses macvtap, enable zero copy between guest
+ * kernel and host kernel when lower device supports high memory
+ * DMA
+ */
+ if (vlan) {
+ if (vlan->lowerdev->features & NETIF_F_ZEROCOPY)
+ sock_set_flag(&q->sk, SOCK_ZEROCOPY);
+ }
+
err = macvtap_set_queue(dev, file, q);
if (err)
sock_put(&q->sk);
@@ -431,6 +443,80 @@ static inline struct sk_buff *macvtap_alloc_skb(struct sock *sk, size_t prepad,
return skb;
}
+/* set skb frags from iovec, this can move to core network code for reuse */
+static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from,
+ int offset, size_t count)
+{
+ int len = iov_length(from, count) - offset;
+ int copy = skb_headlen(skb);
+ int size, offset1 = 0;
+ int i = 0;
+ skb_frag_t *f;
+
+ /* Skip over from offset */
+ while (offset >= from->iov_len) {
+ offset -= from->iov_len;
+ ++from;
+ --count;
+ }
+
+ /* copy up to skb headlen */
+ while (copy > 0) {
+ size = min_t(unsigned int, copy, from->iov_len - offset);
+ if (copy_from_user(skb->data + offset1, from->iov_base + offset,
+ size))
+ return -EFAULT;
+ if (copy > size) {
+ ++from;
+ --count;
+ }
+ copy -= size;
+ offset1 += size;
+ offset = 0;
+ }
+
+ if (len == offset1)
+ return 0;
+
+ while (count--) {
+ struct page *page[MAX_SKB_FRAGS];
+ int num_pages;
+ unsigned long base;
+
+ len = from->iov_len - offset1;
+ if (!len) {
+ offset1 = 0;
+ ++from;
+ continue;
+ }
+ base = (unsigned long)from->iov_base + offset1;
+ size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT;
+ num_pages = get_user_pages_fast(base, size, 0, &page[i]);
+ if ((num_pages != size) ||
+ (num_pages > MAX_SKB_FRAGS - skb_shinfo(skb)->nr_frags))
+ /* put_page is in skb free */
+ return -EFAULT;
+ while (len) {
+ f = &skb_shinfo(skb)->frags[i];
+ f->page = page[i];
+ f->page_offset = base & ~PAGE_MASK;
+ f->size = min_t(int, len, PAGE_SIZE - f->page_offset);
+ skb->data_len += f->size;
+ skb->len += f->size;
+ skb->truesize += f->size;
+ skb_shinfo(skb)->nr_frags++;
+ /* increase sk_wmem_alloc */
+ atomic_add(f->size, &skb->sk->sk_wmem_alloc);
+ base += f->size;
+ len -= f->size;
+ i++;
+ }
+ offset1 = 0;
+ ++from;
+ }
+ return 0;
+}
+
/*
* macvtap_skb_from_vnet_hdr and macvtap_skb_to_vnet_hdr should
* be shared with the tun/tap driver.
@@ -514,17 +600,19 @@ static int macvtap_skb_to_vnet_hdr(const struct sk_buff *skb,
/* Get packet from user space buffer */
-static ssize_t macvtap_get_user(struct macvtap_queue *q,
- const struct iovec *iv, size_t count,
- int noblock)
+static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
+ const struct iovec *iv, unsigned long total_len,
+ size_t count, int noblock)
{
struct sk_buff *skb;
struct macvlan_dev *vlan;
- size_t len = count;
+ unsigned long len = total_len;
int err;
struct virtio_net_hdr vnet_hdr = { 0 };
int vnet_hdr_len = 0;
+ int copylen, zerocopy;
+ zerocopy = sock_flag(&q->sk, SOCK_ZEROCOPY) && (len > GOODCOPY_LEN);
if (q->flags & IFF_VNET_HDR) {
vnet_hdr_len = q->vnet_hdr_sz;
@@ -550,12 +638,28 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q,
if (unlikely(len < ETH_HLEN))
goto err;
- skb = macvtap_alloc_skb(&q->sk, NET_IP_ALIGN, len, vnet_hdr.hdr_len,
- noblock, &err);
+ if (zerocopy)
+ copylen = vnet_hdr.hdr_len;
+ else
+ copylen = len;
+
+ skb = macvtap_alloc_skb(&q->sk, NET_IP_ALIGN, copylen,
+ vnet_hdr.hdr_len, noblock, &err);
if (!skb)
goto err;
-
- err = skb_copy_datagram_from_iovec(skb, 0, iv, vnet_hdr_len, len);
+
+ if (zerocopy)
+ err = zerocopy_sg_from_iovec(skb, iv, vnet_hdr_len, count);
+ else
+ err = skb_copy_datagram_from_iovec(skb, 0, iv, vnet_hdr_len,
+ len);
+ if (sock_flag(&q->sk, SOCK_ZEROCOPY)) {
+ struct skb_ubuf_info pend =
+ (struct skb_ubuf_info *)m->msg_control;
+
+ skb_shinfo(skb)->ubuf.callback = pend.callback;
+ skb_shinfo(skb)->ubuf.desc = pend.desc;
+ }
if (err)
goto err_kfree;
@@ -577,7 +681,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q,
kfree_skb(skb);
rcu_read_unlock_bh();
- return count;
+ return total_len;
err_kfree:
kfree_skb(skb);
@@ -599,8 +703,8 @@ static ssize_t macvtap_aio_write(struct kiocb *iocb, const struct iovec *iv,
ssize_t result = -ENOLINK;
struct macvtap_queue *q = file->private_data;
- result = macvtap_get_user(q, iv, iov_length(iv, count),
- file->f_flags & O_NONBLOCK);
+ result = macvtap_get_user(q, NULL, iv, iov_length(iv, count), count,
+ file->f_flags & O_NONBLOCK);
return result;
}
@@ -813,7 +917,7 @@ static int macvtap_sendmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *m, size_t total_len)
{
struct macvtap_queue *q = container_of(sock, struct macvtap_queue, sock);
- return macvtap_get_user(q, m->msg_iov, total_len,
+ return macvtap_get_user(q, m, m->msg_iov, total_len, m->msg_iovlen,
m->msg_flags & MSG_DONTWAIT);
}
^ permalink raw reply related
* [RFC PATCH V2 4/5] Add vhost zero copy callback to release guest kernel buffers
From: Shirley Ma @ 2010-12-10 10:08 UTC (permalink / raw)
To: Avi Kivity, Arnd Bergmann, mst; +Cc: xiaohui.xin, netdev, kvm, linux-kernel
This patch uses msg_control to pass vhost callback to macvtap (any better
idea to pass this in a simple way?). vhost doesn't notify guest to release
buffers until the underlying lower device DMA has done for these buffers.
This vq can not be reset if any outstanding reference.
Signed-off-by: Shirley Ma <xma@us.ibm.com>
---
drivers/vhost/net.c | 13 ++++++++++-
drivers/vhost/vhost.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++
drivers/vhost/vhost.h | 7 ++++++
3 files changed, 75 insertions(+), 1 deletions(-)
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index f442668..6779a1c 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -128,6 +128,7 @@ static void handle_tx(struct vhost_net *net)
int err, wmem;
size_t hdr_size;
struct socket *sock;
+ struct skb_ubuf_info pend;
/* TODO: check that we are running from vhost_worker?
* Not sure it's worth it, it's straight-forward enough. */
@@ -189,6 +190,13 @@ static void handle_tx(struct vhost_net *net)
iov_length(vq->hdr, s), hdr_size);
break;
}
+ /* use msg_control to pass vhost zerocopy ubuf info here */
+ if (sock_flag(sock->sk, SOCK_ZEROCOPY)) {
+ pend.callback = vq->callback;
+ pend.desc = head;
+ msg.msg_control = &pend;
+ msg.msg_controllen = sizeof(pend);
+ }
/* TODO: Check specific error and bomb out unless ENOBUFS? */
err = sock->ops->sendmsg(NULL, sock, &msg, len);
if (unlikely(err < 0)) {
@@ -199,7 +207,10 @@ static void handle_tx(struct vhost_net *net)
if (err != len)
pr_debug("Truncated TX packet: "
" len %d != %zd\n", err, len);
- vhost_add_used_and_signal(&net->dev, vq, head, 0);
+ if (sock_flag(sock->sk, SOCK_ZEROCOPY))
+ vhost_zerocopy_add_used_and_signal(vq);
+ else
+ vhost_add_used_and_signal(&net->dev, vq, head, 0);
total_len += len;
if (unlikely(total_len >= VHOST_NET_WEIGHT)) {
vhost_poll_queue(&vq->poll);
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 94701ff..b0074bc 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -170,6 +170,8 @@ static void vhost_vq_reset(struct vhost_dev *dev,
vq->call_ctx = NULL;
vq->call = NULL;
vq->log_ctx = NULL;
+ atomic_set(&vq->refcnt, 0);
+ vq->upend_cnt = 0;
}
static int vhost_worker(void *data)
@@ -273,6 +275,9 @@ long vhost_dev_init(struct vhost_dev *dev,
dev->vqs[i].heads = NULL;
dev->vqs[i].dev = dev;
mutex_init(&dev->vqs[i].mutex);
+ spin_lock_init(&dev->vqs[i].zerocopy_lock);
+ dev->vqs[i].upend_cnt = 0;
+ atomic_set(&dev->vqs[i].refcnt, 0);
vhost_vq_reset(dev, dev->vqs + i);
if (dev->vqs[i].handle_kick)
vhost_poll_init(&dev->vqs[i].poll,
@@ -370,10 +375,37 @@ long vhost_dev_reset_owner(struct vhost_dev *dev)
return 0;
}
+void vhost_zerocopy_add_used_and_signal(struct vhost_virtqueue *vq)
+{
+ struct vring_used_elem heads[64];
+ int count, left, mod;
+ unsigned long flags;
+
+ count = (vq->num > 64) ? 64 : vq->num;
+ mod = vq->ubuf_cnt / count;
+ /* notify guest when number of descriptors greater than count */
+ if (mod == 0)
+ return;
+ /*
+ * avoid holding spin lock by notifying guest x64 buffers first
+ */
+ vhost_add_used_and_signal_n(vq->dev, vq, vq->heads, count * mod);
+ /* reset the counter when notifying guest the rest*/
+ left = vq->ubuf_cnt - mod * count;
+ if (left > 0) {
+ spin_lock_irqsave(&vq->zerocopy_lock, flags);
+ memcpy(heads, &vq->heads[mod * count], left * sizeof *vq->heads);
+ vq->ubuf_cnt = 0;
+ spin_unlock_irqrestore(&vq->zerocopy_lock, flags);
+ vhost_add_used_and_signal_n(vq->dev, vq, heads, left);
+ }
+}
+
/* Caller should have device mutex */
void vhost_dev_cleanup(struct vhost_dev *dev)
{
int i;
+ unsigned long begin = jiffies;
for (i = 0; i < dev->nvqs; ++i) {
if (dev->vqs[i].kick && dev->vqs[i].handle_kick) {
vhost_poll_stop(&dev->vqs[i].poll);
@@ -389,6 +421,12 @@ void vhost_dev_cleanup(struct vhost_dev *dev)
eventfd_ctx_put(dev->vqs[i].call_ctx);
if (dev->vqs[i].call)
fput(dev->vqs[i].call);
+ /* wait for all lower device DMAs done, then notify guest */
+ if (atomic_read(&dev->vqs[i].refcnt)) {
+ if (time_after(jiffies, begin + 5 * HZ))
+ vhost_zerocopy_add_used_and_signal(&dev->vqs[i]);
+ }
+
vhost_vq_reset(dev, dev->vqs + i);
}
vhost_dev_free_iovecs(dev);
@@ -1389,3 +1427,21 @@ void vhost_disable_notify(struct vhost_virtqueue *vq)
vq_err(vq, "Failed to enable notification at %p: %d\n",
&vq->used->flags, r);
}
+
+void vhost_zerocopy_callback(struct sk_buff *skb)
+{
+ unsigned long flags;
+ size_t head = skb_shinfo(skb)->ubuf.desc;
+ struct vhost_virtqueue *vq;
+
+ vq = (struct vhost_virtqueue *)container_of(
+ skb_shinfo(skb)->ubuf.callback,
+ struct vhost_virtqueue, callback);
+ if (vq) {
+ spin_lock_irqsave(&vq->zerocopy_lock, flags);
+ vq->heads[vq->upend_cnt].id = head;
+ ++vq->upend_cnt;
+ spin_unlock_irqrestore(&vq->zerocopy_lock, flags);
+ atomic_dec(&vq->refcnt);
+ }
+}
diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
index 073d06a..42d283a 100644
--- a/drivers/vhost/vhost.h
+++ b/drivers/vhost/vhost.h
@@ -108,6 +108,11 @@ struct vhost_virtqueue {
/* Log write descriptors */
void __user *log_base;
struct vhost_log *log;
+ /* vhost zerocopy */
+ atomic_t refcnt; /* num of outstanding DMAs */
+ spinlock_t zerocopy_lock;
+ int upend_cnt; /* num of buffers DMA has done, not notify guest yet */
+ void (*callback)(struct sk_buff *skb); /* notify guest DMA done */
};
struct vhost_dev {
@@ -154,6 +159,8 @@ bool vhost_enable_notify(struct vhost_virtqueue *);
int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
unsigned int log_num, u64 len);
+void vhost_zerocopy_callback(struct sk_buff *skb);
+void vhost_zerocopy_add_used_and_signal(struct vhost_virtqueue *vq);
#define vq_err(vq, fmt, ...) do { \
pr_debug(pr_fmt(fmt), ##__VA_ARGS__); \
^ permalink raw reply related
* [net-next-2.6 27/27] igb: Add new function to read part number from EEPROM in string format
From: Jeff Kirsher @ 2010-12-10 10:06 UTC (permalink / raw)
To: davem, davem; +Cc: Carolyn Wyborny, netdev, gospo, bphilips, Jeff Kirsher
In-Reply-To: <1291975585-30576-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Carolyn Wyborny <carolyn.wyborny@intel.com>
New adapters will have part numbers stored in string format rather than
simple hex format. This function will read part number formats in either
hex or string.
Signed-off-by: Carolyn Wyborny <carolyn.wyborny@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/igb/e1000_defines.h | 7 +++
drivers/net/igb/e1000_nvm.c | 93 ++++++++++++++++++++++++++++++++++++---
drivers/net/igb/e1000_nvm.h | 2 +
drivers/net/igb/igb_main.c | 11 +++--
4 files changed, 102 insertions(+), 11 deletions(-)
diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h
index 6222279..6319ed9 100644
--- a/drivers/net/igb/e1000_defines.h
+++ b/drivers/net/igb/e1000_defines.h
@@ -419,6 +419,9 @@
#define E1000_ERR_SWFW_SYNC 13
#define E1000_NOT_IMPLEMENTED 14
#define E1000_ERR_MBX 15
+#define E1000_ERR_INVALID_ARGUMENT 16
+#define E1000_ERR_NO_SPACE 17
+#define E1000_ERR_NVM_PBA_SECTION 18
/* Loop limit on how long we wait for auto-negotiation to complete */
#define COPPER_LINK_UP_LIMIT 10
@@ -580,11 +583,15 @@
/* Mask bits for fields in Word 0x1a of the NVM */
+/* length of string needed to store part num */
+#define E1000_PBANUM_LENGTH 11
+
/* For checksumming, the sum of all words in the NVM should equal 0xBABA. */
#define NVM_SUM 0xBABA
#define NVM_PBA_OFFSET_0 8
#define NVM_PBA_OFFSET_1 9
+#define NVM_PBA_PTR_GUARD 0xFAFA
#define NVM_WORD_SIZE_BASE_SHIFT 6
/* NVM Commands - Microwire */
diff --git a/drivers/net/igb/e1000_nvm.c b/drivers/net/igb/e1000_nvm.c
index d83b77fa..6b5cc2c 100644
--- a/drivers/net/igb/e1000_nvm.c
+++ b/drivers/net/igb/e1000_nvm.c
@@ -445,31 +445,112 @@ out:
}
/**
- * igb_read_part_num - Read device part number
+ * igb_read_part_string - Read device part number
* @hw: pointer to the HW structure
* @part_num: pointer to device part number
+ * @part_num_size: size of part number buffer
*
* Reads the product board assembly (PBA) number from the EEPROM and stores
* the value in part_num.
**/
-s32 igb_read_part_num(struct e1000_hw *hw, u32 *part_num)
+s32 igb_read_part_string(struct e1000_hw *hw, u8 *part_num, u32 part_num_size)
{
- s32 ret_val;
+ s32 ret_val;
u16 nvm_data;
+ u16 pointer;
+ u16 offset;
+ u16 length;
+
+ if (part_num == NULL) {
+ hw_dbg("PBA string buffer was null\n");
+ ret_val = E1000_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
if (ret_val) {
hw_dbg("NVM Read Error\n");
goto out;
}
- *part_num = (u32)(nvm_data << 16);
- ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &nvm_data);
+ ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &pointer);
+ if (ret_val) {
+ hw_dbg("NVM Read Error\n");
+ goto out;
+ }
+
+ /*
+ * if nvm_data is not ptr guard the PBA must be in legacy format which
+ * means pointer is actually our second data word for the PBA number
+ * and we can decode it into an ascii string
+ */
+ if (nvm_data != NVM_PBA_PTR_GUARD) {
+ hw_dbg("NVM PBA number is not stored as string\n");
+
+ /* we will need 11 characters to store the PBA */
+ if (part_num_size < 11) {
+ hw_dbg("PBA string buffer too small\n");
+ return E1000_ERR_NO_SPACE;
+ }
+
+ /* extract hex string from data and pointer */
+ part_num[0] = (nvm_data >> 12) & 0xF;
+ part_num[1] = (nvm_data >> 8) & 0xF;
+ part_num[2] = (nvm_data >> 4) & 0xF;
+ part_num[3] = nvm_data & 0xF;
+ part_num[4] = (pointer >> 12) & 0xF;
+ part_num[5] = (pointer >> 8) & 0xF;
+ part_num[6] = '-';
+ part_num[7] = 0;
+ part_num[8] = (pointer >> 4) & 0xF;
+ part_num[9] = pointer & 0xF;
+
+ /* put a null character on the end of our string */
+ part_num[10] = '\0';
+
+ /* switch all the data but the '-' to hex char */
+ for (offset = 0; offset < 10; offset++) {
+ if (part_num[offset] < 0xA)
+ part_num[offset] += '0';
+ else if (part_num[offset] < 0x10)
+ part_num[offset] += 'A' - 0xA;
+ }
+
+ goto out;
+ }
+
+ ret_val = hw->nvm.ops.read(hw, pointer, 1, &length);
if (ret_val) {
hw_dbg("NVM Read Error\n");
goto out;
}
- *part_num |= nvm_data;
+
+ if (length == 0xFFFF || length == 0) {
+ hw_dbg("NVM PBA number section invalid length\n");
+ ret_val = E1000_ERR_NVM_PBA_SECTION;
+ goto out;
+ }
+ /* check if part_num buffer is big enough */
+ if (part_num_size < (((u32)length * 2) - 1)) {
+ hw_dbg("PBA string buffer too small\n");
+ ret_val = E1000_ERR_NO_SPACE;
+ goto out;
+ }
+
+ /* trim pba length from start of string */
+ pointer++;
+ length--;
+
+ for (offset = 0; offset < length; offset++) {
+ ret_val = hw->nvm.ops.read(hw, pointer + offset, 1, &nvm_data);
+ if (ret_val) {
+ hw_dbg("NVM Read Error\n");
+ goto out;
+ }
+ part_num[offset * 2] = (u8)(nvm_data >> 8);
+ part_num[(offset * 2) + 1] = (u8)(nvm_data & 0xFF);
+ }
+ part_num[offset * 2] = '\0';
out:
return ret_val;
diff --git a/drivers/net/igb/e1000_nvm.h b/drivers/net/igb/e1000_nvm.h
index 1041c34..29c956a 100644
--- a/drivers/net/igb/e1000_nvm.h
+++ b/drivers/net/igb/e1000_nvm.h
@@ -32,6 +32,8 @@ s32 igb_acquire_nvm(struct e1000_hw *hw);
void igb_release_nvm(struct e1000_hw *hw);
s32 igb_read_mac_addr(struct e1000_hw *hw);
s32 igb_read_part_num(struct e1000_hw *hw, u32 *part_num);
+s32 igb_read_part_string(struct e1000_hw *hw, u8 *part_num,
+ u32 part_num_size);
s32 igb_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
s32 igb_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
s32 igb_validate_nvm_checksum(struct e1000_hw *hw);
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 67ea262..041f8e6 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -1729,12 +1729,13 @@ static int __devinit igb_probe(struct pci_dev *pdev,
struct igb_adapter *adapter;
struct e1000_hw *hw;
u16 eeprom_data = 0;
+ s32 ret_val;
static int global_quad_port_a; /* global quad port a indication */
const struct e1000_info *ei = igb_info_tbl[ent->driver_data];
unsigned long mmio_start, mmio_len;
int err, pci_using_dac;
u16 eeprom_apme_mask = IGB_EEPROM_APME;
- u32 part_num;
+ u8 part_str[E1000_PBANUM_LENGTH];
/* Catch broken hardware that put the wrong VF device ID in
* the PCIe SR-IOV capability.
@@ -2000,10 +2001,10 @@ static int __devinit igb_probe(struct pci_dev *pdev,
"unknown"),
netdev->dev_addr);
- igb_read_part_num(hw, &part_num);
- dev_info(&pdev->dev, "%s: PBA No: %06x-%03x\n", netdev->name,
- (part_num >> 8), (part_num & 0xff));
-
+ ret_val = igb_read_part_string(hw, part_str, E1000_PBANUM_LENGTH);
+ if (ret_val)
+ strcpy(part_str, "Unknown");
+ dev_info(&pdev->dev, "%s: PBA No: %s\n", netdev->name, part_str);
dev_info(&pdev->dev,
"Using %s interrupts. %d rx queue(s), %d tx queue(s)\n",
adapter->msix_entries ? "MSI-X" :
--
1.7.3.2
^ permalink raw reply related
* [net-next-2.6 26/27] e1000e: increment the driver version
From: Jeff Kirsher @ 2010-12-10 10:06 UTC (permalink / raw)
To: davem, davem; +Cc: Bruce Allan, netdev, gospo, bphilips, Jeff Kirsher
In-Reply-To: <1291975585-30576-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Bruce Allan <bruce.w.allan@intel.com>
Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/e1000e/netdev.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 6e1f3a3..5530d0b 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -54,7 +54,7 @@
#define DRV_EXTRAVERSION "-k2"
-#define DRV_VERSION "1.2.7" DRV_EXTRAVERSION
+#define DRV_VERSION "1.2.20" DRV_EXTRAVERSION
char e1000e_driver_name[] = "e1000e";
const char e1000e_driver_version[] = DRV_VERSION;
--
1.7.3.2
^ permalink raw reply related
* [net-next-2.6 25/27] e1000e: static analysis tools complain of a possible null ptr p dereference
From: Jeff Kirsher @ 2010-12-10 10:06 UTC (permalink / raw)
To: davem, davem; +Cc: Bruce Allan, netdev, gospo, bphilips, Jeff Kirsher
In-Reply-To: <1291975585-30576-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Bruce Allan <bruce.w.allan@intel.com>
Adding this default case resolves the issue.
Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Tested-by: Emil Tantilov <emil.s.tantilov@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/e1000e/ethtool.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c
index 29b09113..72ce0ec 100644
--- a/drivers/net/e1000e/ethtool.c
+++ b/drivers/net/e1000e/ethtool.c
@@ -1992,6 +1992,10 @@ static void e1000_get_ethtool_stats(struct net_device *netdev,
p = (char *) adapter +
e1000_gstrings_stats[i].stat_offset;
break;
+ default:
+ data[i] = 0;
+ continue;
+ break;
}
data[i] = (e1000_gstrings_stats[i].sizeof_stat ==
--
1.7.3.2
^ permalink raw reply related
* [net-next-2.6 24/27] e1000e: minor error message corrections
From: Jeff Kirsher @ 2010-12-10 10:06 UTC (permalink / raw)
To: davem, davem; +Cc: Bruce Allan, netdev, gospo, bphilips, Jeff Kirsher
From: Bruce Allan <bruce.w.allan@intel.com>
Correct error messages when setting up Rx resources and when checking
module parameters.
Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/e1000e/netdev.c | 2 +-
drivers/net/e1000e/param.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 4bf843a..6e1f3a3 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -2130,7 +2130,7 @@ err_pages:
}
err:
vfree(rx_ring->buffer_info);
- e_err("Unable to allocate memory for the transmit descriptor ring\n");
+ e_err("Unable to allocate memory for the receive descriptor ring\n");
return err;
}
diff --git a/drivers/net/e1000e/param.c b/drivers/net/e1000e/param.c
index 3d36911..a9612b0 100644
--- a/drivers/net/e1000e/param.c
+++ b/drivers/net/e1000e/param.c
@@ -421,7 +421,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
static const struct e1000_option opt = {
.type = enable_option,
.name = "CRC Stripping",
- .err = "defaulting to enabled",
+ .err = "defaulting to Enabled",
.def = OPTION_ENABLED
};
--
1.7.3.2
^ permalink raw reply related
* [net-next-2.6 22/27] e1000e: support new PBA format from EEPROM
From: Jeff Kirsher @ 2010-12-10 10:03 UTC (permalink / raw)
To: davem, davem; +Cc: Bruce Allan, netdev, gospo, bphilips, Jeff Kirsher
In-Reply-To: <1291975414-30487-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Bruce Allan <bruce.w.allan@intel.com>
Provide support to e1000e for displaying the new format of the PBA found
in the EEPROM. The unique PBA identifier is no longer restricted to
hexadecimal numbers and must now be read and displayed as a string.
Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/e1000e/defines.h | 8 ++-
drivers/net/e1000e/e1000.h | 3 +-
drivers/net/e1000e/lib.c | 135 +++++++++++++++++++++++++++++++++++-------
drivers/net/e1000e/netdev.c | 12 +++-
4 files changed, 130 insertions(+), 28 deletions(-)
diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h
index 016ea38..7245dc2 100644
--- a/drivers/net/e1000e/defines.h
+++ b/drivers/net/e1000e/defines.h
@@ -488,6 +488,9 @@
#define E1000_BLK_PHY_RESET 12
#define E1000_ERR_SWFW_SYNC 13
#define E1000_NOT_IMPLEMENTED 14
+#define E1000_ERR_INVALID_ARGUMENT 16
+#define E1000_ERR_NO_SPACE 17
+#define E1000_ERR_NVM_PBA_SECTION 18
/* Loop limit on how long we wait for auto-negotiation to complete */
#define FIBER_LINK_UP_LIMIT 50
@@ -650,13 +653,16 @@
/* Mask bits for fields in Word 0x03 of the EEPROM */
#define NVM_COMPAT_LOM 0x0800
+/* length of string needed to store PBA number */
+#define E1000_PBANUM_LENGTH 11
+
/* For checksumming, the sum of all words in the NVM should equal 0xBABA. */
#define NVM_SUM 0xBABA
/* PBA (printed board assembly) number words */
#define NVM_PBA_OFFSET_0 8
#define NVM_PBA_OFFSET_1 9
-
+#define NVM_PBA_PTR_GUARD 0xFAFA
#define NVM_WORD_SIZE_BASE_SHIFT 6
/* NVM Commands - SPI */
diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h
index 3d9366f..2c913b8 100644
--- a/drivers/net/e1000e/e1000.h
+++ b/drivers/net/e1000e/e1000.h
@@ -514,7 +514,8 @@ extern struct e1000_info e1000_pch_info;
extern struct e1000_info e1000_pch2_info;
extern struct e1000_info e1000_es2_info;
-extern s32 e1000e_read_pba_num(struct e1000_hw *hw, u32 *pba_num);
+extern s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
+ u32 pba_num_size);
extern s32 e1000e_commit_phy(struct e1000_hw *hw);
diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c
index 0fd4eb5..8377523 100644
--- a/drivers/net/e1000e/lib.c
+++ b/drivers/net/e1000e/lib.c
@@ -2139,6 +2139,119 @@ s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
}
/**
+ * e1000_read_pba_string_generic - Read device part number
+ * @hw: pointer to the HW structure
+ * @pba_num: pointer to device part number
+ * @pba_num_size: size of part number buffer
+ *
+ * Reads the product board assembly (PBA) number from the EEPROM and stores
+ * the value in pba_num.
+ **/
+s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
+ u32 pba_num_size)
+{
+ s32 ret_val;
+ u16 nvm_data;
+ u16 pba_ptr;
+ u16 offset;
+ u16 length;
+
+ if (pba_num == NULL) {
+ e_dbg("PBA string buffer was null\n");
+ ret_val = E1000_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
+
+ ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
+ if (ret_val) {
+ e_dbg("NVM Read Error\n");
+ goto out;
+ }
+
+ ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr);
+ if (ret_val) {
+ e_dbg("NVM Read Error\n");
+ goto out;
+ }
+
+ /*
+ * if nvm_data is not ptr guard the PBA must be in legacy format which
+ * means pba_ptr is actually our second data word for the PBA number
+ * and we can decode it into an ascii string
+ */
+ if (nvm_data != NVM_PBA_PTR_GUARD) {
+ e_dbg("NVM PBA number is not stored as string\n");
+
+ /* we will need 11 characters to store the PBA */
+ if (pba_num_size < 11) {
+ e_dbg("PBA string buffer too small\n");
+ return E1000_ERR_NO_SPACE;
+ }
+
+ /* extract hex string from data and pba_ptr */
+ pba_num[0] = (nvm_data >> 12) & 0xF;
+ pba_num[1] = (nvm_data >> 8) & 0xF;
+ pba_num[2] = (nvm_data >> 4) & 0xF;
+ pba_num[3] = nvm_data & 0xF;
+ pba_num[4] = (pba_ptr >> 12) & 0xF;
+ pba_num[5] = (pba_ptr >> 8) & 0xF;
+ pba_num[6] = '-';
+ pba_num[7] = 0;
+ pba_num[8] = (pba_ptr >> 4) & 0xF;
+ pba_num[9] = pba_ptr & 0xF;
+
+ /* put a null character on the end of our string */
+ pba_num[10] = '\0';
+
+ /* switch all the data but the '-' to hex char */
+ for (offset = 0; offset < 10; offset++) {
+ if (pba_num[offset] < 0xA)
+ pba_num[offset] += '0';
+ else if (pba_num[offset] < 0x10)
+ pba_num[offset] += 'A' - 0xA;
+ }
+
+ goto out;
+ }
+
+ ret_val = e1000_read_nvm(hw, pba_ptr, 1, &length);
+ if (ret_val) {
+ e_dbg("NVM Read Error\n");
+ goto out;
+ }
+
+ if (length == 0xFFFF || length == 0) {
+ e_dbg("NVM PBA number section invalid length\n");
+ ret_val = E1000_ERR_NVM_PBA_SECTION;
+ goto out;
+ }
+ /* check if pba_num buffer is big enough */
+ if (pba_num_size < (((u32)length * 2) - 1)) {
+ e_dbg("PBA string buffer too small\n");
+ ret_val = E1000_ERR_NO_SPACE;
+ goto out;
+ }
+
+ /* trim pba length from start of string */
+ pba_ptr++;
+ length--;
+
+ for (offset = 0; offset < length; offset++) {
+ ret_val = e1000_read_nvm(hw, pba_ptr + offset, 1, &nvm_data);
+ if (ret_val) {
+ e_dbg("NVM Read Error\n");
+ goto out;
+ }
+ pba_num[offset * 2] = (u8)(nvm_data >> 8);
+ pba_num[(offset * 2) + 1] = (u8)(nvm_data & 0xFF);
+ }
+ pba_num[offset * 2] = '\0';
+
+out:
+ return ret_val;
+}
+
+/**
* e1000_read_mac_addr_generic - Read device MAC address
* @hw: pointer to the HW structure
*
@@ -2579,25 +2692,3 @@ bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw)
out:
return ret_val;
}
-
-s32 e1000e_read_pba_num(struct e1000_hw *hw, u32 *pba_num)
-{
- s32 ret_val;
- u16 nvm_data;
-
- ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
- if (ret_val) {
- e_dbg("NVM Read Error\n");
- return ret_val;
- }
- *pba_num = (u32)(nvm_data << 16);
-
- ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_1, 1, &nvm_data);
- if (ret_val) {
- e_dbg("NVM Read Error\n");
- return ret_val;
- }
- *pba_num |= nvm_data;
-
- return 0;
-}
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index f8efbbb..393b76d 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -5626,7 +5626,8 @@ static void e1000_print_device_info(struct e1000_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
- u32 pba_num;
+ u32 ret_val;
+ u8 pba_str[E1000_PBANUM_LENGTH];
/* print bus type/speed/width info */
e_info("(PCI Express:2.5GB/s:%s) %pM\n",
@@ -5637,9 +5638,12 @@ static void e1000_print_device_info(struct e1000_adapter *adapter)
netdev->dev_addr);
e_info("Intel(R) PRO/%s Network Connection\n",
(hw->phy.type == e1000_phy_ife) ? "10/100" : "1000");
- e1000e_read_pba_num(hw, &pba_num);
- e_info("MAC: %d, PHY: %d, PBA No: %06x-%03x\n",
- hw->mac.type, hw->phy.type, (pba_num >> 8), (pba_num & 0xff));
+ ret_val = e1000_read_pba_string_generic(hw, pba_str,
+ E1000_PBANUM_LENGTH);
+ if (ret_val)
+ strcpy(pba_str, "Unknown");
+ e_info("MAC: %d, PHY: %d, PBA No: %s\n",
+ hw->mac.type, hw->phy.type, pba_str);
}
static void e1000_eeprom_checks(struct e1000_adapter *adapter)
--
1.7.3.2
^ permalink raw reply related
* [net-next-2.6 21/27] e1000e: 82579 PHY incorrectly identified during init
From: Jeff Kirsher @ 2010-12-10 10:03 UTC (permalink / raw)
To: davem, davem; +Cc: Bruce Allan, netdev, gospo, bphilips, Jeff Kirsher
In-Reply-To: <1291975414-30487-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Bruce Allan <bruce.w.allan@intel.com>
During init, reading the 2 PHY ID registers back-to-back in the default
fast mode could return invalid data (all F's) and in slow mode could
return data to the second read the data from the first read. To resolve
the issue in fast mode, set to slow mode before any PHY accesses; to
resolve the issue in slow mode, put in a delay for every 82579 PHY access.
Since this PHY is currently only paired with the pch2lan MAC and the PHY
type is not known before the first PHY access which can fail this way,
check for this based on MAC-type.
Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/e1000e/ich8lan.c | 16 +++++++++++-----
drivers/net/e1000e/phy.c | 14 ++++++++++++++
2 files changed, 25 insertions(+), 5 deletions(-)
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c
index d7fc930..5080372 100644
--- a/drivers/net/e1000e/ich8lan.c
+++ b/drivers/net/e1000e/ich8lan.c
@@ -338,12 +338,17 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
}
phy->id = e1000_phy_unknown;
- ret_val = e1000e_get_phy_id(hw);
- if (ret_val)
- goto out;
- if ((phy->id == 0) || (phy->id == PHY_REVISION_MASK)) {
+ switch (hw->mac.type) {
+ default:
+ ret_val = e1000e_get_phy_id(hw);
+ if (ret_val)
+ goto out;
+ if ((phy->id != 0) && (phy->id != PHY_REVISION_MASK))
+ break;
+ /* fall-through */
+ case e1000_pch2lan:
/*
- * In case the PHY needs to be in mdio slow mode (eg. 82577),
+ * In case the PHY needs to be in mdio slow mode,
* set slow mode and try to get the PHY id again.
*/
ret_val = e1000_set_mdio_slow_mode_hv(hw);
@@ -352,6 +357,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
ret_val = e1000e_get_phy_id(hw);
if (ret_val)
goto out;
+ break;
}
phy->type = e1000e_get_phy_type_from_id(phy->id);
diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c
index 6ad90cc..95da386 100644
--- a/drivers/net/e1000e/phy.c
+++ b/drivers/net/e1000e/phy.c
@@ -226,6 +226,13 @@ s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
}
*data = (u16) mdic;
+ /*
+ * Allow some time after each MDIC transaction to avoid
+ * reading duplicate data in the next MDIC transaction.
+ */
+ if (hw->mac.type == e1000_pch2lan)
+ udelay(100);
+
return 0;
}
@@ -279,6 +286,13 @@ s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
return -E1000_ERR_PHY;
}
+ /*
+ * Allow some time after each MDIC transaction to avoid
+ * reading duplicate data in the next MDIC transaction.
+ */
+ if (hw->mac.type == e1000_pch2lan)
+ udelay(100);
+
return 0;
}
--
1.7.3.2
^ permalink raw reply related
* [net-next-2.6 20/27] e1000e: 82577/8/9 mis-configured OEM bits during S0->Sx
From: Jeff Kirsher @ 2010-12-10 10:03 UTC (permalink / raw)
To: davem, davem; +Cc: Bruce Allan, netdev, gospo, bphilips, Jeff Kirsher
In-Reply-To: <1291975414-30487-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Bruce Allan <bruce.w.allan@intel.com>
The LPLU (Low Power Link Up) and Gigabit Disable bits (a.k.a. OEM bits)
were being configured incorrectly when device goes to D3 state.
Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/e1000e/ich8lan.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c
index e3374d9..d7fc930 100644
--- a/drivers/net/e1000e/ich8lan.c
+++ b/drivers/net/e1000e/ich8lan.c
@@ -3591,7 +3591,7 @@ void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw)
ew32(PHY_CTRL, phy_ctrl);
if (hw->mac.type >= e1000_pchlan) {
- e1000_oem_bits_config_ich8lan(hw, true);
+ e1000_oem_bits_config_ich8lan(hw, false);
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
return;
--
1.7.3.2
^ permalink raw reply related
* [net-next-2.6 19/27] e1000e: 82571 Serdes can fail to get link
From: Jeff Kirsher @ 2010-12-10 10:03 UTC (permalink / raw)
To: davem, davem; +Cc: Bruce Allan, netdev, gospo, bphilips, Jeff Kirsher
In-Reply-To: <1291975414-30487-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Bruce Allan <bruce.w.allan@intel.com>
When link partner is sending continuous Config symbols, the 82571 Serdes
FIFO can overflow resulting in Invalid bit getting set. To resolve this,
if Sync and Config bits are both 1 ignore the Invalid bit and restart
auto-negotiation.
Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Tested-by: Emil Tantilov <emil.s.tantilov@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/e1000e/82571.c | 35 +++++++++++++++++++++++++++--------
1 files changed, 27 insertions(+), 8 deletions(-)
diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c
index 280d41f..e57e409 100644
--- a/drivers/net/e1000e/82571.c
+++ b/drivers/net/e1000e/82571.c
@@ -52,6 +52,7 @@
(ID_LED_DEF1_DEF2))
#define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000
+#define AN_RETRY_COUNT 5 /* Autoneg Retry Count value */
#define E1000_BASE1000T_STATUS 10
#define E1000_IDLE_ERROR_COUNT_MASK 0xFF
#define E1000_RECEIVE_ERROR_COUNTER 21
@@ -1503,6 +1504,8 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
u32 rxcw;
u32 ctrl;
u32 status;
+ u32 txcw;
+ u32 i;
s32 ret_val = 0;
ctrl = er32(CTRL);
@@ -1613,16 +1616,32 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
e_dbg("ANYSTATE -> DOWN\n");
} else {
/*
- * We have sync, and can tolerate one invalid (IV)
- * codeword before declaring link down, so reread
- * to look again.
+ * Check several times, if Sync and Config
+ * both are consistently 1 then simply ignore
+ * the Invalid bit and restart Autoneg
*/
- udelay(10);
- rxcw = er32(RXCW);
- if (rxcw & E1000_RXCW_IV) {
- mac->serdes_link_state = e1000_serdes_link_down;
+ for (i = 0; i < AN_RETRY_COUNT; i++) {
+ udelay(10);
+ rxcw = er32(RXCW);
+ if ((rxcw & E1000_RXCW_IV) &&
+ !((rxcw & E1000_RXCW_SYNCH) &&
+ (rxcw & E1000_RXCW_C))) {
+ mac->serdes_has_link = false;
+ mac->serdes_link_state =
+ e1000_serdes_link_down;
+ e_dbg("ANYSTATE -> DOWN\n");
+ break;
+ }
+ }
+
+ if (i == AN_RETRY_COUNT) {
+ txcw = er32(TXCW);
+ txcw |= E1000_TXCW_ANE;
+ ew32(TXCW, txcw);
+ mac->serdes_link_state =
+ e1000_serdes_link_autoneg_progress;
mac->serdes_has_link = false;
- e_dbg("ANYSTATE -> DOWN\n");
+ e_dbg("ANYSTATE -> AN_PROG\n");
}
}
}
--
1.7.3.2
^ permalink raw reply related
* [net-next-2.6 18/27] e1000e: 82577/8 must acquire h/w semaphore before workaround
From: Jeff Kirsher @ 2010-12-10 10:03 UTC (permalink / raw)
To: davem, davem; +Cc: Bruce Allan, netdev, gospo, bphilips, Jeff Kirsher
In-Reply-To: <1291975414-30487-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Bruce Allan <bruce.w.allan@intel.com>
The workaround function e1000_configure_k1_pchlan() assumes the h/w
semaphore is already acquired. This was originally missed when setting up
the part for the ethtool loopback test.
Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/e1000e/ethtool.c | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c
index 26d4f3b..29b09113 100644
--- a/drivers/net/e1000e/ethtool.c
+++ b/drivers/net/e1000e/ethtool.c
@@ -1263,6 +1263,7 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
u32 ctrl_reg = 0;
u32 stat_reg = 0;
u16 phy_reg = 0;
+ s32 ret_val = 0;
hw->mac.autoneg = 0;
@@ -1322,7 +1323,13 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
case e1000_phy_82577:
case e1000_phy_82578:
/* Workaround: K1 must be disabled for stable 1Gbps operation */
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val) {
+ e_err("Cannot setup 1Gbps loopback.\n");
+ return ret_val;
+ }
e1000_configure_k1_ich8lan(hw, false);
+ hw->phy.ops.release(hw);
break;
case e1000_phy_82579:
/* Disable PHY energy detect power down */
--
1.7.3.2
^ permalink raw reply related
* [PATCH] Document the kernel_recvmsg() function
From: Martin Lucina @ 2010-12-10 10:04 UTC (permalink / raw)
To: netdev; +Cc: Martin Sustrik, David S. Miller
[Updated and sent to the netdev mailing list, Eric thx for the pointer]
Hi,
so, today we spent all day figuring out how the kernel_sendmsg() function
*actually* works. This patch adds some documentation to help the next poor
sod.
-mato
>From 1a977fc0b9544c53761ba3c4c26ca1aac2018663 Mon Sep 17 00:00:00 2001
From: Martin Lucina <mato@kotelna.sk>
Date: Thu, 9 Dec 2010 17:11:18 +0100
Subject: [PATCH] Document the kernel_recvmsg() function
Signed-off-by: Martin Lucina <mato@kotelna.sk>
---
net/socket.c | 15 +++++++++++++++
1 files changed, 15 insertions(+), 0 deletions(-)
diff --git a/net/socket.c b/net/socket.c
index 3ca2fd9..088fb3f 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -732,6 +732,21 @@ static int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
return ret;
}
+/**
+ * kernel_recvmsg - Receive a message from a socket (kernel space)
+ * @sock: The socket to receive the message from
+ * @msg: Received message
+ * @vec: Input s/g array for message data
+ * @num: Size of input s/g array
+ * @size: Number of bytes to read
+ * @flags: Message flags (MSG_DONTWAIT, etc...)
+ *
+ * On return the msg structure contains the scatter/gather array passed in the
+ * vec argument. The array is modified so that it consists of the unfilled
+ * portion of the original array.
+ *
+ * The returned value is the total number of bytes received, or an error.
+ */
int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
struct kvec *vec, size_t num, size_t size, int flags)
{
--
1.7.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox