Netdev List
 help / color / mirror / Atom feed
* Re: [RFC] mac80211: clean up frame receive handling
From: drago01 @ 2007-12-12 18:39 UTC (permalink / raw)
  To: Johannes Berg
  Cc: linux-wireless, netdev, Michael Wu, Tomas Winkler, Jouni Malinen
In-Reply-To: <1197483844.6558.158.camel-YfaajirXv214zXjbi5bjpg@public.gmane.org>

On Dec 12, 2007 7:24 PM, Johannes Berg <johannes-cdvu00un1VgdHxzADdlk8Q@public.gmane.org> wrote:
> [comments welcome. I really need a refresher on what the frame formats
> mean but I think I did the right thing with skb->protocol here, I also
> think we had a bug with rfc2042 header frames bigger than 15xx bytes and
> eth_type_trans()]
>
> This cleans up the frame receive handling. After this patch
>  * EAPOL frames addressed to us or the EAPOL group address are
>    always accepted regardless of whether they are encrypted or not

why? userspace (wap_supplicant) tryes to control this depending on the
network settings.
(I don't really know why thought)
maybe it should be handled like drop_unencrypted with default to accept all?

^ permalink raw reply

* [PATCH] netfilter : xt_hashlimit should use time_after_eq()
From: Eric Dumazet @ 2007-12-12 18:39 UTC (permalink / raw)
  To: David S. Miller, Patrick McHardy; +Cc: netdev

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

Hi David & Patrick

I believe this patch is needed for linux-2.6.24

Thank you

[PATCH] netfilter : xt_hashlimit should use time_after_eq()

In order to avoid jiffies wraparound and its effect, special care must 
be taken
when doing comparisons ...

Signed-off-by: Eric Dumazet <dada1@cosmosbay.com>



[-- Attachment #2: xt_hashlimit.patch --]
[-- Type: text/plain, Size: 511 bytes --]

diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index 1910367..2ef44d8 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -240,7 +240,7 @@ static bool select_all(const struct xt_hashlimit_htable *ht,
 static bool select_gc(const struct xt_hashlimit_htable *ht,
 		      const struct dsthash_ent *he)
 {
-	return jiffies >= he->expires;
+	return time_after_eq(jiffies, he->expires);
 }
 
 static void htable_selective_cleanup(struct xt_hashlimit_htable *ht,

^ permalink raw reply related

* [PATCH]: remove netif_running() check from myri10ge_poll()
From: Andrew Gallatin @ 2007-12-12 18:38 UTC (permalink / raw)
  To: David Miller; +Cc: Jeff Garzik, netdev, linux-kernel

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

Remove the bogus netif_running() check from myri10ge_poll().

This eliminates any chance that myri10ge_poll() can trigger
an oops by calling netif_rx_complete() and returning
with work_done == budget.

Signed-off-by: Andrew Gallatin <gallatin@myri.com>

[-- Attachment #2: myri10ge_remove_netif_running.diff --]
[-- Type: text/plain, Size: 515 bytes --]

diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index 8def865..c90958f 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -1239,7 +1239,7 @@ static int myri10ge_poll(struct napi_str
 	/* process as many rx events as NAPI will allow */
 	work_done = myri10ge_clean_rx_done(mgp, budget);
 
-	if (work_done < budget || !netif_running(netdev)) {
+	if (work_done < budget) {
 		netif_rx_complete(netdev, napi);
 		put_be32(htonl(3), mgp->irq_claim);
 	}

^ permalink raw reply related

* Re: "ip neigh show" not showing arp cache entries?
From: Chris Friesen @ 2007-12-12 18:25 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: netdev, linux-kernel
In-Reply-To: <47601059.8020203@cosmosbay.com>

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

Eric Dumazet wrote:
> Chris Friesen a écrit :
>> Is this expected behaviour?
> 
> Probably not... Still a 2.6.14 kernel ?

Yep.  Embedded hardware, so I'm unable to test with a more recent kernel.

> Could you send the result of :
> 
> strace ip neigh show

I've attached two strace runs, one of "ip neigh show" and one of "ip 
neigh show 10.41.18.101".

Chris

[-- Attachment #2: trace.txt --]
[-- Type: text/plain, Size: 7617 bytes --]

root@typhoon-base-unit0:/tftpboot/cnp/0-0-5-0/0-0-5-0> strace ip neigh show
execve("/sbin/ip", ["ip", "neigh", "show"], [/* 14 vars */]) = 0
uname({sys="Linux", node="typhoon-base-unit0", ...}) = 0
brk(0)                                  = 0x806b000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=58478, ...}) = 0
mmap2(NULL, 58478, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7f56000
close(3)                                = 0
open("/lib/libresolv.so.2", O_RDONLY)   = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\320\"\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=75541, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f55000
mmap2(NULL, 71816, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7f43000
mmap2(0xb7f51000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xe) = 0xb7f51000
mmap2(0xb7f53000, 6280, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7f53000
close(3)                                = 0
open("/lib/libc.so.6", O_RDONLY)        = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\216O\1"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1407983, ...}) = 0
mmap2(NULL, 1146076, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7e2b000
mmap2(0xb7f39000, 32768, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x10d) = 0xb7f39000
mmap2(0xb7f41000, 7388, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7f41000
close(3)                                = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7e2a000
mprotect(0xb7f39000, 20480, PROT_READ)  = 0
set_thread_area({entry_number:-1 -> 6, base_addr:0xb7e2a6b0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
munmap(0xb7f56000, 58478)               = 0
socket(PF_NETLINK, SOCK_RAW, 0)         = 3
setsockopt(3, SOL_SOCKET, SO_SNDBUF, [32768], 4) = 0
setsockopt(3, SOL_SOCKET, SO_RCVBUF, [32768], 4) = 0
bind(3, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 0
getsockname(3, {sa_family=AF_NETLINK, pid=6150, groups=00000000}, [12]) = 0
time(NULL)                              = 1197465643
sendto(3, "\24\0\0\0\22\0\1\3,\340_G\0\0\0\0\0\0\0\0", 20, 0, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 20
recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"\364\0\0\0\20\0\2\0,\340_G\6\30\0\0\0\0\1\0\1\0\0\0C\30"..., 16384}], msg_controllen=0, msg_flags=0}, 0) = 3544
brk(0)                                  = 0x806b000
brk(0x808c000)                          = 0x808c000
recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"\24\0\0\0\3\0\2\0,\340_G\6\30\0\0\0\0\0\0\1\0\0\0C\30\0"..., 16384}], msg_controllen=0, msg_flags=0}, 0) = 20
sendto(3, "\24\0\0\0\36\0\1\3-\340_G\0\0\0\0\0\0\0\0", 20, 0, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 20
recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"X\0\0\0\34\0\2\0-\340_G\6\30\0\0\n\0\0\0\7\0\0\0@\0\0\5"..., 16384}], msg_controllen=0, msg_flags=0}, 0) = 264
recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"\24\0\0\0\3\0\2\0-\340_G\6\30\0\0\0\0\0\0\7\0\0\0@\0\0"..., 16384}], msg_controllen=0, msg_flags=0}, 0) = 20
exit_group(0)                           = ?
Process 6150 detached






root@typhoon-base-unit0:/tftpboot/cnp/0-0-5-0/0-0-5-0> ip neigh show 10.41.18.101
10.41.18.101 dev eth6 lladdr 00:0e:0c:5e:95:bd REACHABLE
root@typhoon-base-unit0:/tftpboot/cnp/0-0-5-0/0-0-5-0> strace ip neigh show 10.41.18.101
execve("/sbin/ip", ["ip", "neigh", "show", "10.41.18.101"], [/* 14 vars */]) = 0
uname({sys="Linux", node="typhoon-base-unit0", ...}) = 0
brk(0)                                  = 0x806b000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=58478, ...}) = 0
mmap2(NULL, 58478, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7fd5000
close(3)                                = 0
open("/lib/libresolv.so.2", O_RDONLY)   = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\320\"\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=75541, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7fd4000
mmap2(NULL, 71816, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7fc2000
mmap2(0xb7fd0000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xe) = 0xb7fd0000
mmap2(0xb7fd2000, 6280, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7fd2000
close(3)                                = 0
open("/lib/libc.so.6", O_RDONLY)        = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\216O\1"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1407983, ...}) = 0
mmap2(NULL, 1146076, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7eaa000
mmap2(0xb7fb8000, 32768, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x10d) = 0xb7fb8000
mmap2(0xb7fc0000, 7388, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7fc0000
close(3)                                = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7ea9000
mprotect(0xb7fb8000, 20480, PROT_READ)  = 0
set_thread_area({entry_number:-1 -> 6, base_addr:0xb7ea96b0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
munmap(0xb7fd5000, 58478)               = 0
socket(PF_NETLINK, SOCK_RAW, 0)         = 3
setsockopt(3, SOL_SOCKET, SO_SNDBUF, [32768], 4) = 0
setsockopt(3, SOL_SOCKET, SO_RCVBUF, [32768], 4) = 0
bind(3, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 0
getsockname(3, {sa_family=AF_NETLINK, pid=7536, groups=00000000}, [12]) = 0
time(NULL)                              = 1197465790
sendto(3, "\24\0\0\0\22\0\1\3\277\340_G\0\0\0\0\0\0\0\0", 20, 0, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 20
recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"\364\0\0\0\20\0\2\0\277\340_Gp\35\0\0\0\0\1\0\1\0\0\0C"..., 16384}], msg_controllen=0, msg_flags=0}, 0) = 3544
brk(0)                                  = 0x806b000
brk(0x808c000)                          = 0x808c000
recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"\24\0\0\0\3\0\2\0\277\340_Gp\35\0\0\0\0\0\0\1\0\0\0C\30"..., 16384}], msg_controllen=0, msg_flags=0}, 0) = 20
sendto(3, "\24\0\0\0\36\0\1\3\300\340_G\0\0\0\0\2\0\0\0", 20, 0, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 20
recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"L\0\0\0\34\0\2\0\300\340_Gp\35\0\0\2\0\0\0\r\0\0\0\2\0"..., 16384}], msg_controllen=0, msg_flags=0}, 0) = 912
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 11), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7fe3000
write(1, "10.41.18.101 dev eth6 lladdr 00:"..., 5710.41.18.101 dev eth6 lladdr 00:0e:0c:5e:95:bd REACHABLE) = 57
recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"\24\0\0\0\3\0\2\0\300\340_Gp\35\0\0\0\0\0\0\r\0\0\0\2\0"..., 16384}], msg_controllen=0, msg_flags=0}, 0) = 20
munmap(0xb7fe3000, 4096)                = 0
exit_group(0)                           = ?
Process 7536 detached

^ permalink raw reply

* [RFC] mac80211: clean up frame receive handling
From: Johannes Berg @ 2007-12-12 18:24 UTC (permalink / raw)
  To: linux-wireless; +Cc: netdev, Michael Wu, Tomas Winkler, Jouni Malinen

[comments welcome. I really need a refresher on what the frame formats
mean but I think I did the right thing with skb->protocol here, I also
think we had a bug with rfc2042 header frames bigger than 15xx bytes and
eth_type_trans()]

This cleans up the frame receive handling. After this patch
 * EAPOL frames addressed to us or the EAPOL group address are
   always accepted regardless of whether they are encrypted or not
 * other frames from a station are dropped if PAE is enabled and
   the station is not authorized
 * unencrypted frames (except the EAPOL frames above) are dropped if
   drop_unencrypted is enabled
 * we no longer invoke eth_type_trans() as we've done most of the work
   already, this patch implements the rest of the work needed
 * port control is not done for injected packets

Signed-off-by: Johannes Berg <johannes-cdvu00un1VgdHxzADdlk8Q@public.gmane.org>
---
I've made a corresponding hostapd patch which is on my website
http://johannes.sipsolutions.net/patches/hostap/all/2007-12-12-17%3a18/005-eapol-on-regular-iface.patch

It works fine and is IMHO nicer than doing the eapol stuff over the
management interface.

 net/mac80211/debugfs_netdev.c  |   27 +++--------
 net/mac80211/ieee80211_i.h     |   22 +++------
 net/mac80211/ieee80211_iface.c |    1 
 net/mac80211/rx.c              |  100 ++++++++++++++++++++++-------------------
 net/mac80211/tx.c              |   10 ++--
 5 files changed, 79 insertions(+), 81 deletions(-)

--- everything.orig/net/mac80211/ieee80211_i.h	2007-12-12 16:25:05.819131294 +0100
+++ everything/net/mac80211/ieee80211_i.h	2007-12-12 16:31:58.749134385 +0100
@@ -306,11 +306,11 @@ struct ieee80211_sub_if_data {
 	unsigned int flags;
 
 	int drop_unencrypted;
-	int eapol; /* 0 = process EAPOL frames as normal data frames,
-		    * 1 = send EAPOL frames through wlan#ap to hostapd
-		    *     (default) */
-	int ieee802_1x; /* IEEE 802.1X PAE - drop packet to/from unauthorized
-			 * port */
+	/*
+	 * IEEE 802.1X Port access control in effect,
+	 * drop packets to/from unauthorized port
+	 */
+	int ieee802_1x_pac;
 
 	u16 sequence;
 
@@ -339,8 +339,7 @@ struct ieee80211_sub_if_data {
 		struct {
 			struct dentry *channel_use;
 			struct dentry *drop_unencrypted;
-			struct dentry *eapol;
-			struct dentry *ieee8021_x;
+			struct dentry *ieee802_1x_pac;
 			struct dentry *state;
 			struct dentry *bssid;
 			struct dentry *prev_bssid;
@@ -359,8 +358,7 @@ struct ieee80211_sub_if_data {
 		struct {
 			struct dentry *channel_use;
 			struct dentry *drop_unencrypted;
-			struct dentry *eapol;
-			struct dentry *ieee8021_x;
+			struct dentry *ieee802_1x_pac;
 			struct dentry *num_sta_ps;
 			struct dentry *dtim_period;
 			struct dentry *dtim_count;
@@ -374,15 +372,13 @@ struct ieee80211_sub_if_data {
 		struct {
 			struct dentry *channel_use;
 			struct dentry *drop_unencrypted;
-			struct dentry *eapol;
-			struct dentry *ieee8021_x;
+			struct dentry *ieee802_1x_pac;
 			struct dentry *peer;
 		} wds;
 		struct {
 			struct dentry *channel_use;
 			struct dentry *drop_unencrypted;
-			struct dentry *eapol;
-			struct dentry *ieee8021_x;
+			struct dentry *ieee802_1x_pac;
 		} vlan;
 		struct {
 			struct dentry *mode;
--- everything.orig/net/mac80211/rx.c	2007-12-12 16:25:05.849130805 +0100
+++ everything/net/mac80211/rx.c	2007-12-12 16:31:58.749134385 +0100
@@ -190,7 +190,7 @@ ieee80211_rx_monitor(struct ieee80211_lo
 		rthdr->antsignal = status->ssi;
 	}
 
-	skb_set_mac_header(skb, 0);
+	skb_reset_mac_header(skb);
 	skb->ip_summed = CHECKSUM_UNNECESSARY;
 	skb->pkt_type = PACKET_OTHERHOST;
 	skb->protocol = htons(ETH_P_802_2);
@@ -387,18 +387,6 @@ ieee80211_rx_h_check(struct ieee80211_tx
 		return TXRX_DROP;
 	}
 
-	if (!(rx->flags & IEEE80211_TXRXD_RXRA_MATCH))
-		rx->skb->pkt_type = PACKET_OTHERHOST;
-	else if (compare_ether_addr(rx->dev->dev_addr, hdr->addr1) == 0)
-		rx->skb->pkt_type = PACKET_HOST;
-	else if (is_multicast_ether_addr(hdr->addr1)) {
-		if (is_broadcast_ether_addr(hdr->addr1))
-			rx->skb->pkt_type = PACKET_BROADCAST;
-		else
-			rx->skb->pkt_type = PACKET_MULTICAST;
-	} else
-		rx->skb->pkt_type = PACKET_OTHERHOST;
-
 	/* Drop disallowed frame classes based on STA auth/assoc state;
 	 * IEEE 802.11, Chap 5.5.
 	 *
@@ -967,18 +955,10 @@ ieee80211_rx_h_remove_qos_control(struct
 }
 
 static int
-ieee80211_drop_802_1x_pae(struct ieee80211_txrx_data *rx, int hdrlen)
+ieee80211_802_1x_port_control(struct ieee80211_txrx_data *rx)
 {
-	if (rx->sdata->eapol && ieee80211_is_eapol(rx->skb, hdrlen) &&
-	    rx->sdata->type != IEEE80211_IF_TYPE_STA &&
-	    (rx->flags & IEEE80211_TXRXD_RXRA_MATCH))
-		return 0;
-
-	if (unlikely(rx->sdata->ieee802_1x &&
-		     (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
-		     (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_NULLFUNC &&
-		     (!rx->sta || !(rx->sta->flags & WLAN_STA_AUTHORIZED)) &&
-		     !ieee80211_is_eapol(rx->skb, hdrlen))) {
+	if (unlikely(rx->sdata->ieee802_1x_pac &&
+		     (!rx->sta || !(rx->sta->flags & WLAN_STA_AUTHORIZED)))) {
 #ifdef CONFIG_MAC80211_DEBUG
 		printk(KERN_DEBUG "%s: dropped frame "
 		       "(unauthorized port)\n", rx->dev->name);
@@ -990,7 +970,7 @@ ieee80211_drop_802_1x_pae(struct ieee802
 }
 
 static int
-ieee80211_drop_unencrypted(struct ieee80211_txrx_data *rx, int hdrlen)
+ieee80211_drop_unencrypted(struct ieee80211_txrx_data *rx)
 {
 	/*
 	 * Pass through unencrypted frames if the hardware has
@@ -1003,9 +983,7 @@ ieee80211_drop_unencrypted(struct ieee80
 	if (unlikely(!(rx->fc & IEEE80211_FCTL_PROTECTED) &&
 		     (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
 		     (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_NULLFUNC &&
-		     (rx->key || rx->sdata->drop_unencrypted) &&
-		     (rx->sdata->eapol == 0 ||
-		      !ieee80211_is_eapol(rx->skb, hdrlen)))) {
+		     (rx->key || rx->sdata->drop_unencrypted))) {
 		if (net_ratelimit())
 			printk(KERN_DEBUG "%s: RX non-WEP frame, but expected "
 			       "encryption\n", rx->dev->name);
@@ -1014,6 +992,24 @@ ieee80211_drop_unencrypted(struct ieee80
 	return 0;
 }
 
+static bool ieee80211_frame_allowed(struct ieee80211_txrx_data *rx)
+{
+	static const u8 pae_group_addr[ETH_ALEN]
+		= { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x03 };
+	struct ethhdr *ehdr = (struct ethhdr *)rx->skb->data;
+
+	if (rx->skb->protocol == htons(ETH_P_PAE) &&
+	    (compare_ether_addr(ehdr->h_dest, pae_group_addr) == 0 ||
+	     compare_ether_addr(ehdr->h_dest, rx->dev->dev_addr) == 0))
+		return true;
+
+	if (ieee80211_802_1x_port_control(rx) ||
+	    ieee80211_drop_unencrypted(rx))
+		return false;
+
+	return true;
+}
+
 static int
 ieee80211_data_to_8023(struct ieee80211_txrx_data *rx)
 {
@@ -1130,6 +1126,7 @@ ieee80211_data_to_8023(struct ieee80211_
 		skb_pull(skb, hdrlen + 6);
 		memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
 		memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
+		skb->protocol = htons(ethertype);
 	} else {
 		struct ethhdr *ehdr;
 		__be16 len;
@@ -1139,6 +1136,7 @@ ieee80211_data_to_8023(struct ieee80211_
 		memcpy(ehdr->h_dest, dst, ETH_ALEN);
 		memcpy(ehdr->h_source, src, ETH_ALEN);
 		ehdr->h_proto = len;
+		skb->protocol = htons(ETH_P_802_2);
 	}
 	return 0;
 }
@@ -1150,14 +1148,27 @@ ieee80211_deliver_skb(struct ieee80211_t
 	struct ieee80211_local *local = rx->local;
 	struct sk_buff *skb, *xmit_skb;
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	u8 *dst;
 
 	skb = rx->skb;
 	xmit_skb = NULL;
 
-	if (local->bridge_packets && (sdata->type == IEEE80211_IF_TYPE_AP
-	    || sdata->type == IEEE80211_IF_TYPE_VLAN) &&
+	dst = skb->data;
+
+	if (compare_ether_addr(dev->dev_addr, dst) == 0)
+		skb->pkt_type = PACKET_HOST;
+	else if (is_multicast_ether_addr(dst)) {
+		if (is_broadcast_ether_addr(dst))
+			skb->pkt_type = PACKET_BROADCAST;
+		else
+			skb->pkt_type = PACKET_MULTICAST;
+	} else
+		skb->pkt_type = PACKET_OTHERHOST;
+
+	if (local->bridge_packets && (sdata->type == IEEE80211_IF_TYPE_AP ||
+				      sdata->type == IEEE80211_IF_TYPE_VLAN) &&
 	    (rx->flags & IEEE80211_TXRXD_RXRA_MATCH)) {
-		if (is_multicast_ether_addr(skb->data)) {
+		if (is_multicast_ether_addr(dst)) {
 			/* send multicast frames both to higher layers in
 			 * local net stack and back to the wireless media */
 			xmit_skb = skb_copy(skb, GFP_ATOMIC);
@@ -1186,16 +1197,18 @@ ieee80211_deliver_skb(struct ieee80211_t
 
 	if (skb) {
 		/* deliver to local stack */
-		skb->protocol = eth_type_trans(skb, dev);
 		memset(skb->cb, 0, sizeof(skb->cb));
+		skb->dev = dev;
+		skb_reset_mac_header(skb);
+		skb_pull(skb, ETH_HLEN);
 		netif_rx(skb);
 	}
 
 	if (xmit_skb) {
 		/* send to wireless media */
 		xmit_skb->protocol = __constant_htons(ETH_P_802_3);
-		skb_set_network_header(xmit_skb, 0);
-		skb_set_mac_header(xmit_skb, 0);
+		skb_reset_network_header(xmit_skb);
+		skb_reset_mac_header(xmit_skb);
 		dev_queue_xmit(xmit_skb);
 	}
 }
@@ -1280,13 +1293,12 @@ ieee80211_rx_h_amsdu(struct ieee80211_tx
 			}
 		}
 
-		skb_set_network_header(frame, 0);
+		skb_reset_network_header(frame);
 		frame->dev = dev;
 		frame->priority = skb->priority;
 		rx->skb = frame;
 
-		if ((ieee80211_drop_802_1x_pae(rx, 0)) ||
-		    (ieee80211_drop_unencrypted(rx, 0))) {
+		if (!ieee80211_frame_allowed(rx)) {
 			if (skb == frame) /* last frame */
 				return TXRX_DROP;
 			dev_kfree_skb(frame);
@@ -1305,14 +1317,15 @@ ieee80211_rx_h_amsdu(struct ieee80211_tx
 			skb_pull(frame, 6);
 			memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN);
 			memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN);
+			frame->protocol = htons(ethertype);
 		} else {
 			memcpy(skb_push(frame, sizeof(__be16)), &len,
 				sizeof(__be16));
 			memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN);
 			memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN);
+			frame->protocol = htons(ETH_P_802_2);
 		}
 
-
 		ieee80211_deliver_skb(rx);
 	}
 
@@ -1324,7 +1337,7 @@ ieee80211_rx_h_data(struct ieee80211_txr
 {
 	struct net_device *dev = rx->dev;
 	u16 fc;
-	int err, hdrlen;
+	int err;
 
 	fc = rx->fc;
 	if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA))
@@ -1333,16 +1346,13 @@ ieee80211_rx_h_data(struct ieee80211_txr
 	if (unlikely(!WLAN_FC_DATA_PRESENT(fc)))
 		return TXRX_DROP;
 
-	hdrlen = ieee80211_get_hdrlen(fc);
-
-	if ((ieee80211_drop_802_1x_pae(rx, hdrlen)) ||
-	    (ieee80211_drop_unencrypted(rx, hdrlen)))
-		return TXRX_DROP;
-
 	err = ieee80211_data_to_8023(rx);
 	if (unlikely(err))
 		return TXRX_DROP;
 
+	if (!ieee80211_frame_allowed(rx))
+		return TXRX_DROP;
+
 	rx->skb->dev = dev;
 
 	dev->stats.rx_packets++;
--- everything.orig/net/mac80211/debugfs_netdev.c	2007-12-12 16:25:05.899132325 +0100
+++ everything/net/mac80211/debugfs_netdev.c	2007-12-12 16:31:58.759132161 +0100
@@ -91,8 +91,7 @@ static const struct file_operations name
 /* common attributes */
 IEEE80211_IF_FILE(channel_use, channel_use, DEC);
 IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC);
-IEEE80211_IF_FILE(eapol, eapol, DEC);
-IEEE80211_IF_FILE(ieee8021_x, ieee802_1x, DEC);
+IEEE80211_IF_FILE(ieee802_1x_pac, ieee802_1x_pac, DEC);
 
 /* STA/IBSS attributes */
 IEEE80211_IF_FILE(state, u.sta.state, DEC);
@@ -170,8 +169,7 @@ static void add_sta_files(struct ieee802
 {
 	DEBUGFS_ADD(channel_use, sta);
 	DEBUGFS_ADD(drop_unencrypted, sta);
-	DEBUGFS_ADD(eapol, sta);
-	DEBUGFS_ADD(ieee8021_x, sta);
+	DEBUGFS_ADD(ieee802_1x_pac, sta);
 	DEBUGFS_ADD(state, sta);
 	DEBUGFS_ADD(bssid, sta);
 	DEBUGFS_ADD(prev_bssid, sta);
@@ -192,8 +190,7 @@ static void add_ap_files(struct ieee8021
 {
 	DEBUGFS_ADD(channel_use, ap);
 	DEBUGFS_ADD(drop_unencrypted, ap);
-	DEBUGFS_ADD(eapol, ap);
-	DEBUGFS_ADD(ieee8021_x, ap);
+	DEBUGFS_ADD(ieee802_1x_pac, ap);
 	DEBUGFS_ADD(num_sta_ps, ap);
 	DEBUGFS_ADD(dtim_period, ap);
 	DEBUGFS_ADD(dtim_count, ap);
@@ -209,8 +206,7 @@ static void add_wds_files(struct ieee802
 {
 	DEBUGFS_ADD(channel_use, wds);
 	DEBUGFS_ADD(drop_unencrypted, wds);
-	DEBUGFS_ADD(eapol, wds);
-	DEBUGFS_ADD(ieee8021_x, wds);
+	DEBUGFS_ADD(ieee802_1x_pac, wds);
 	DEBUGFS_ADD(peer, wds);
 }
 
@@ -218,8 +214,7 @@ static void add_vlan_files(struct ieee80
 {
 	DEBUGFS_ADD(channel_use, vlan);
 	DEBUGFS_ADD(drop_unencrypted, vlan);
-	DEBUGFS_ADD(eapol, vlan);
-	DEBUGFS_ADD(ieee8021_x, vlan);
+	DEBUGFS_ADD(ieee802_1x_pac, vlan);
 }
 
 static void add_monitor_files(struct ieee80211_sub_if_data *sdata)
@@ -263,8 +258,7 @@ static void del_sta_files(struct ieee802
 {
 	DEBUGFS_DEL(channel_use, sta);
 	DEBUGFS_DEL(drop_unencrypted, sta);
-	DEBUGFS_DEL(eapol, sta);
-	DEBUGFS_DEL(ieee8021_x, sta);
+	DEBUGFS_DEL(ieee802_1x_pac, sta);
 	DEBUGFS_DEL(state, sta);
 	DEBUGFS_DEL(bssid, sta);
 	DEBUGFS_DEL(prev_bssid, sta);
@@ -285,8 +279,7 @@ static void del_ap_files(struct ieee8021
 {
 	DEBUGFS_DEL(channel_use, ap);
 	DEBUGFS_DEL(drop_unencrypted, ap);
-	DEBUGFS_DEL(eapol, ap);
-	DEBUGFS_DEL(ieee8021_x, ap);
+	DEBUGFS_DEL(ieee802_1x_pac, ap);
 	DEBUGFS_DEL(num_sta_ps, ap);
 	DEBUGFS_DEL(dtim_period, ap);
 	DEBUGFS_DEL(dtim_count, ap);
@@ -302,8 +295,7 @@ static void del_wds_files(struct ieee802
 {
 	DEBUGFS_DEL(channel_use, wds);
 	DEBUGFS_DEL(drop_unencrypted, wds);
-	DEBUGFS_DEL(eapol, wds);
-	DEBUGFS_DEL(ieee8021_x, wds);
+	DEBUGFS_DEL(ieee802_1x_pac, wds);
 	DEBUGFS_DEL(peer, wds);
 }
 
@@ -311,8 +303,7 @@ static void del_vlan_files(struct ieee80
 {
 	DEBUGFS_DEL(channel_use, vlan);
 	DEBUGFS_DEL(drop_unencrypted, vlan);
-	DEBUGFS_DEL(eapol, vlan);
-	DEBUGFS_DEL(ieee8021_x, vlan);
+	DEBUGFS_DEL(ieee802_1x_pac, vlan);
 }
 
 static void del_monitor_files(struct ieee80211_sub_if_data *sdata)
--- everything.orig/net/mac80211/ieee80211_iface.c	2007-12-12 16:25:05.939130533 +0100
+++ everything/net/mac80211/ieee80211_iface.c	2007-12-12 16:31:58.759132161 +0100
@@ -22,7 +22,6 @@ void ieee80211_if_sdata_init(struct ieee
 
 	/* Default values for sub-interface parameters */
 	sdata->drop_unencrypted = 0;
-	sdata->eapol = 1;
 	for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
 		skb_queue_head_init(&sdata->fragments[i].skb_list);
 
--- everything.orig/net/mac80211/tx.c	2007-12-12 16:25:06.039131944 +0100
+++ everything/net/mac80211/tx.c	2007-12-12 16:31:58.759132161 +0100
@@ -221,6 +221,7 @@ ieee80211_tx_h_check_assoc(struct ieee80
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
 #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
 	u32 sta_flags;
+	u16 fc = tx->fc;
 
 	if (unlikely(tx->flags & IEEE80211_TXRXD_TX_INJECTED))
 		return TXRX_CONTINUE;
@@ -261,8 +262,10 @@ ieee80211_tx_h_check_assoc(struct ieee80
 		return TXRX_CONTINUE;
 	}
 
-	if (unlikely(/* !injected && */ tx->sdata->ieee802_1x &&
-		     !(sta_flags & WLAN_STA_AUTHORIZED))) {
+	if (unlikely(!(tx->flags & IEEE80211_TXRXD_TX_INJECTED) &&
+		     tx->sdata->ieee802_1x_pac &&
+		     !(sta_flags & WLAN_STA_AUTHORIZED) &&
+		     !ieee80211_is_eapol(tx->skb, ieee80211_get_hdrlen(fc)))) {
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
 		DECLARE_MAC_BUF(mac);
 		printk(KERN_DEBUG "%s: dropped frame to %s"
@@ -449,8 +452,7 @@ ieee80211_tx_h_select_key(struct ieee802
 	else if ((key = rcu_dereference(tx->sdata->default_key)))
 		tx->key = key;
 	else if (tx->sdata->drop_unencrypted &&
-		 !(tx->sdata->eapol &&
-		   ieee80211_is_eapol(tx->skb, ieee80211_get_hdrlen(fc)))) {
+		 !ieee80211_is_eapol(tx->skb, ieee80211_get_hdrlen(fc))) {
 		I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted);
 		return TXRX_DROP;
 	} else {

^ permalink raw reply

* [PATCH 1/8][BNX2]: Add ring constants.
From: Michael Chan @ 2007-12-12 18:58 UTC (permalink / raw)
  To: davem, netdev

[BNX2]: Add ring constants.

Define the various ring constants to make the code cleaner.

Signed-off-by: Michael Chan <mchan@broadcom.com>

diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 4e7b46e..dfe50c2 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -468,8 +468,7 @@ bnx2_free_mem(struct bnx2 *bp)
 		bp->stats_blk = NULL;
 	}
 	if (bp->tx_desc_ring) {
-		pci_free_consistent(bp->pdev,
-				    sizeof(struct tx_bd) * TX_DESC_CNT,
+		pci_free_consistent(bp->pdev, TXBD_RING_SIZE,
 				    bp->tx_desc_ring, bp->tx_desc_mapping);
 		bp->tx_desc_ring = NULL;
 	}
@@ -477,8 +476,7 @@ bnx2_free_mem(struct bnx2 *bp)
 	bp->tx_buf_ring = NULL;
 	for (i = 0; i < bp->rx_max_ring; i++) {
 		if (bp->rx_desc_ring[i])
-			pci_free_consistent(bp->pdev,
-					    sizeof(struct rx_bd) * RX_DESC_CNT,
+			pci_free_consistent(bp->pdev, RXBD_RING_SIZE,
 					    bp->rx_desc_ring[i],
 					    bp->rx_desc_mapping[i]);
 		bp->rx_desc_ring[i] = NULL;
@@ -492,30 +490,24 @@ bnx2_alloc_mem(struct bnx2 *bp)
 {
 	int i, status_blk_size;
 
-	bp->tx_buf_ring = kzalloc(sizeof(struct sw_bd) * TX_DESC_CNT,
-				  GFP_KERNEL);
+	bp->tx_buf_ring = kzalloc(SW_TXBD_RING_SIZE, GFP_KERNEL);
 	if (bp->tx_buf_ring == NULL)
 		return -ENOMEM;
 
-	bp->tx_desc_ring = pci_alloc_consistent(bp->pdev,
-					        sizeof(struct tx_bd) *
-						TX_DESC_CNT,
+	bp->tx_desc_ring = pci_alloc_consistent(bp->pdev, TXBD_RING_SIZE,
 						&bp->tx_desc_mapping);
 	if (bp->tx_desc_ring == NULL)
 		goto alloc_mem_err;
 
-	bp->rx_buf_ring = vmalloc(sizeof(struct sw_bd) * RX_DESC_CNT *
-				  bp->rx_max_ring);
+	bp->rx_buf_ring = vmalloc(SW_RXBD_RING_SIZE * bp->rx_max_ring);
 	if (bp->rx_buf_ring == NULL)
 		goto alloc_mem_err;
 
-	memset(bp->rx_buf_ring, 0, sizeof(struct sw_bd) * RX_DESC_CNT *
-				   bp->rx_max_ring);
+	memset(bp->rx_buf_ring, 0, SW_RXBD_RING_SIZE * bp->rx_max_ring);
 
 	for (i = 0; i < bp->rx_max_ring; i++) {
 		bp->rx_desc_ring[i] =
-			pci_alloc_consistent(bp->pdev,
-					     sizeof(struct rx_bd) * RX_DESC_CNT,
+			pci_alloc_consistent(bp->pdev, RXBD_RING_SIZE,
 					     &bp->rx_desc_mapping[i]);
 		if (bp->rx_desc_ring[i] == NULL)
 			goto alloc_mem_err;
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index 30ba366..e6a2153 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -6408,6 +6408,11 @@ struct sw_bd {
 	DECLARE_PCI_UNMAP_ADDR(mapping)
 };
 
+#define SW_RXBD_RING_SIZE (sizeof(struct sw_bd) * RX_DESC_CNT)
+#define RXBD_RING_SIZE (sizeof(struct rx_bd) * RX_DESC_CNT)
+#define SW_TXBD_RING_SIZE (sizeof(struct sw_bd) * TX_DESC_CNT)
+#define TXBD_RING_SIZE (sizeof(struct tx_bd) * TX_DESC_CNT)
+
 /* Buffered flash (Atmel: AT45DB011B) specific information */
 #define SEEPROM_PAGE_BITS			2
 #define SEEPROM_PHY_PAGE_SIZE			(1 << SEEPROM_PAGE_BITS)



^ permalink raw reply related

* [PATCH 8/8][BNX2]: Update version to 1.6.9.
From: Michael Chan @ 2007-12-12 19:00 UTC (permalink / raw)
  To: davem, netdev

[BNX2]: Update version to 1.6.9.

Signed-off-by: Michael Chan <mchan@broadcom.com>

diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index ae081c8..469d259 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -56,8 +56,8 @@
 
 #define DRV_MODULE_NAME		"bnx2"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"1.6.9"
-#define DRV_MODULE_RELDATE	"December 8, 2007"
+#define DRV_MODULE_VERSION	"1.7.0"
+#define DRV_MODULE_RELDATE	"December 11, 2007"
 
 #define RUN_AT(x) (jiffies + (x))
 



^ permalink raw reply related

* [PATCH 7/8][BNX2]: Enable S/G for jumbo RX.
From: Michael Chan @ 2007-12-12 19:00 UTC (permalink / raw)
  To: davem, netdev

[BNX2]: Enable S/G for jumbo RX.

If the MTU requires more than 1 page for the SKB, enable the page ring
and calculate the size of the page ring.  This will guarantee order-0
allocation regardless of the MTU size.

Fixup loopback test packet size so that we don't deal with the pages
during loopback test.

Signed-off-by: Michael Chan <mchan@broadcom.com>

diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 6c0fc8a..ae081c8 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -4493,15 +4493,32 @@ static u32 bnx2_find_max_ring(u32 ring_size, u32 max_size)
 static void
 bnx2_set_rx_ring_size(struct bnx2 *bp, u32 size)
 {
-	u32 rx_size;
+	u32 rx_size, rx_space, jumbo_size;
 
 	/* 8 for CRC and VLAN */
 	rx_size = bp->dev->mtu + ETH_HLEN + bp->rx_offset + 8;
 
+	rx_space = SKB_DATA_ALIGN(rx_size + BNX2_RX_ALIGN) + NET_SKB_PAD +
+		sizeof(struct skb_shared_info);
+
 	bp->rx_copy_thresh = RX_COPY_THRESH;
 	bp->rx_pg_ring_size = 0;
 	bp->rx_max_pg_ring = 0;
 	bp->rx_max_pg_ring_idx = 0;
+	if (rx_space > PAGE_SIZE) {
+		int pages = PAGE_ALIGN(bp->dev->mtu - 40) >> PAGE_SHIFT;
+
+		jumbo_size = size * pages;
+		if (jumbo_size > MAX_TOTAL_RX_PG_DESC_CNT)
+			jumbo_size = MAX_TOTAL_RX_PG_DESC_CNT;
+
+		bp->rx_pg_ring_size = jumbo_size;
+		bp->rx_max_pg_ring = bnx2_find_max_ring(jumbo_size,
+							MAX_RX_PG_RINGS);
+		bp->rx_max_pg_ring_idx = (bp->rx_max_pg_ring * RX_DESC_CNT) - 1;
+		rx_size = RX_COPY_THRESH + bp->rx_offset;
+		bp->rx_copy_thresh = 0;
+	}
 
 	bp->rx_buf_use_size = rx_size;
 	/* hw alignment */
@@ -4881,7 +4898,7 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
 	else
 		return -EINVAL;
 
-	pkt_size = 1514;
+	pkt_size = min(bp->dev->mtu + ETH_HLEN, bp->rx_jumbo_thresh - 4);
 	skb = netdev_alloc_skb(bp->dev, pkt_size);
 	if (!skb)
 		return -ENOMEM;



^ permalink raw reply related

* [PATCH 6/8][BNX2]: Add fast path code to handle RX pages.
From: Michael Chan @ 2007-12-12 19:00 UTC (permalink / raw)
  To: davem, netdev

[BNX2]: Add fast path code to handle RX pages.

Add function to reuse a page in case of allocation or other errors.
Add code to construct the completed SKB with the additional data in
the pages.

Signed-off-by: Michael Chan <mchan@broadcom.com>

diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 38e8e31..6c0fc8a 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -2411,6 +2411,55 @@ bnx2_tx_int(struct bnx2 *bp)
 	}
 }
 
+static void
+bnx2_reuse_rx_skb_pages(struct bnx2 *bp, struct sk_buff *skb, int count)
+{
+	struct sw_pg *cons_rx_pg, *prod_rx_pg;
+	struct rx_bd *cons_bd, *prod_bd;
+	dma_addr_t mapping;
+	int i;
+	u16 hw_prod = bp->rx_pg_prod, prod;
+	u16 cons = bp->rx_pg_cons;
+
+	for (i = 0; i < count; i++) {
+		prod = RX_PG_RING_IDX(hw_prod);
+
+		prod_rx_pg = &bp->rx_pg_ring[prod];
+		cons_rx_pg = &bp->rx_pg_ring[cons];
+		cons_bd = &bp->rx_pg_desc_ring[RX_RING(cons)][RX_IDX(cons)];
+		prod_bd = &bp->rx_pg_desc_ring[RX_RING(prod)][RX_IDX(prod)];
+
+		if (i == 0 && skb) {
+			struct page *page;
+			struct skb_shared_info *shinfo;
+
+			shinfo = skb_shinfo(skb);
+			shinfo->nr_frags--;
+			page = shinfo->frags[shinfo->nr_frags].page;
+			shinfo->frags[shinfo->nr_frags].page = NULL;
+			mapping = pci_map_page(bp->pdev, page, 0, PAGE_SIZE,
+					       PCI_DMA_FROMDEVICE);
+			cons_rx_pg->page = page;
+			pci_unmap_addr_set(cons_rx_pg, mapping, mapping);
+			dev_kfree_skb(skb);
+		}
+		if (prod != cons) {
+			prod_rx_pg->page = cons_rx_pg->page;
+			cons_rx_pg->page = NULL;
+			pci_unmap_addr_set(prod_rx_pg, mapping,
+				pci_unmap_addr(cons_rx_pg, mapping));
+
+			prod_bd->rx_bd_haddr_hi = cons_bd->rx_bd_haddr_hi;
+			prod_bd->rx_bd_haddr_lo = cons_bd->rx_bd_haddr_lo;
+
+		}
+		cons = RX_PG_RING_IDX(NEXT_RX_BD(cons));
+		hw_prod = NEXT_RX_BD(hw_prod);
+	}
+	bp->rx_pg_prod = hw_prod;
+	bp->rx_pg_cons = cons;
+}
+
 static inline void
 bnx2_reuse_rx_skb(struct bnx2 *bp, struct sk_buff *skb,
 	u16 cons, u16 prod)
@@ -2443,7 +2492,7 @@ bnx2_reuse_rx_skb(struct bnx2 *bp, struct sk_buff *skb,
 
 static int
 bnx2_rx_skb(struct bnx2 *bp, struct sk_buff *skb, unsigned int len,
-	    dma_addr_t dma_addr, u32 ring_idx)
+	    unsigned int hdr_len, dma_addr_t dma_addr, u32 ring_idx)
 {
 	int err;
 	u16 prod = ring_idx & 0xffff;
@@ -2451,6 +2500,12 @@ bnx2_rx_skb(struct bnx2 *bp, struct sk_buff *skb, unsigned int len,
 	err = bnx2_alloc_rx_skb(bp, prod);
 	if (unlikely(err)) {
 		bnx2_reuse_rx_skb(bp, skb, (u16) (ring_idx >> 16), prod);
+		if (hdr_len) {
+			unsigned int raw_len = len + 4;
+			int pages = PAGE_ALIGN(raw_len - hdr_len) >> PAGE_SHIFT;
+
+			bnx2_reuse_rx_skb_pages(bp, NULL, pages);
+		}
 		return err;
 	}
 
@@ -2458,7 +2513,69 @@ bnx2_rx_skb(struct bnx2 *bp, struct sk_buff *skb, unsigned int len,
 	pci_unmap_single(bp->pdev, dma_addr, bp->rx_buf_use_size,
 			 PCI_DMA_FROMDEVICE);
 
-	skb_put(skb, len);
+	if (hdr_len == 0) {
+		skb_put(skb, len);
+		return 0;
+	} else {
+		unsigned int i, frag_len, frag_size, pages;
+		struct sw_pg *rx_pg;
+		u16 pg_cons = bp->rx_pg_cons;
+		u16 pg_prod = bp->rx_pg_prod;
+
+		frag_size = len + 4 - hdr_len;
+		pages = PAGE_ALIGN(frag_size) >> PAGE_SHIFT;
+		skb_put(skb, hdr_len);
+
+		for (i = 0; i < pages; i++) {
+			frag_len = min(frag_size, (unsigned int) PAGE_SIZE);
+			if (unlikely(frag_len <= 4)) {
+				unsigned int tail = 4 - frag_len;
+
+				bp->rx_pg_cons = pg_cons;
+				bp->rx_pg_prod = pg_prod;
+				bnx2_reuse_rx_skb_pages(bp, NULL, pages - i);
+				skb->len -= tail;
+				if (i == 0) {
+					skb->tail -= tail;
+				} else {
+					skb_frag_t *frag =
+						&skb_shinfo(skb)->frags[i - 1];
+					frag->size -= tail;
+					skb->data_len -= tail;
+					skb->truesize -= tail;
+				}
+				return 0;
+			}
+			rx_pg = &bp->rx_pg_ring[pg_cons];
+
+			pci_unmap_page(bp->pdev, pci_unmap_addr(rx_pg, mapping),
+				       PAGE_SIZE, PCI_DMA_FROMDEVICE);
+
+			if (i == pages - 1)
+				frag_len -= 4;
+
+			skb_fill_page_desc(skb, i, rx_pg->page, 0, frag_len);
+			rx_pg->page = NULL;
+
+			err = bnx2_alloc_rx_page(bp, RX_PG_RING_IDX(pg_prod));
+			if (unlikely(err)) {
+				bp->rx_pg_cons = pg_cons;
+				bp->rx_pg_prod = pg_prod;
+				bnx2_reuse_rx_skb_pages(bp, skb, pages - i);
+				return err;
+			}
+
+			frag_size -= frag_len;
+			skb->data_len += frag_len;
+			skb->truesize += frag_len;
+			skb->len += frag_len;
+
+			pg_prod = NEXT_RX_BD(pg_prod);
+			pg_cons = RX_PG_RING_IDX(NEXT_RX_BD(pg_cons));
+		}
+		bp->rx_pg_prod = pg_prod;
+		bp->rx_pg_cons = pg_cons;
+	}
 	return 0;
 }
 
@@ -2477,7 +2594,7 @@ bnx2_rx_int(struct bnx2 *bp, int budget)
 {
 	u16 hw_cons, sw_cons, sw_ring_cons, sw_prod, sw_ring_prod;
 	struct l2_fhdr *rx_hdr;
-	int rx_pkt = 0;
+	int rx_pkt = 0, pg_ring_used = 0;
 
 	hw_cons = bnx2_get_hw_rx_cons(bp);
 	sw_cons = bp->rx_cons;
@@ -2488,7 +2605,7 @@ bnx2_rx_int(struct bnx2 *bp, int budget)
 	 */
 	rmb();
 	while (sw_cons != hw_cons) {
-		unsigned int len;
+		unsigned int len, hdr_len;
 		u32 status;
 		struct sw_bd *rx_buf;
 		struct sk_buff *skb;
@@ -2508,7 +2625,7 @@ bnx2_rx_int(struct bnx2 *bp, int budget)
 			bp->rx_offset + RX_COPY_THRESH, PCI_DMA_FROMDEVICE);
 
 		rx_hdr = (struct l2_fhdr *) skb->data;
-		len = rx_hdr->l2_fhdr_pkt_len - 4;
+		len = rx_hdr->l2_fhdr_pkt_len;
 
 		if ((status = rx_hdr->l2_fhdr_status) &
 			(L2_FHDR_ERRORS_BAD_CRC |
@@ -2520,6 +2637,16 @@ bnx2_rx_int(struct bnx2 *bp, int budget)
 			bnx2_reuse_rx_skb(bp, skb, sw_ring_cons, sw_ring_prod);
 			goto next_rx;
 		}
+		hdr_len = 0;
+		if (status & L2_FHDR_STATUS_SPLIT) {
+			hdr_len = rx_hdr->l2_fhdr_ip_xsum;
+			pg_ring_used = 1;
+		} else if (len > bp->rx_jumbo_thresh) {
+			hdr_len = bp->rx_jumbo_thresh;
+			pg_ring_used = 1;
+		}
+
+		len -= 4;
 
 		if (len <= bp->rx_copy_thresh) {
 			struct sk_buff *new_skb;
@@ -2541,7 +2668,7 @@ bnx2_rx_int(struct bnx2 *bp, int budget)
 				sw_ring_cons, sw_ring_prod);
 
 			skb = new_skb;
-		} else if (unlikely(bnx2_rx_skb(bp, skb, len, dma_addr,
+		} else if (unlikely(bnx2_rx_skb(bp, skb, len, hdr_len, dma_addr,
 				    (sw_ring_cons << 16) | sw_ring_prod)))
 			goto next_rx;
 
@@ -2593,6 +2720,10 @@ next_rx:
 	bp->rx_cons = sw_cons;
 	bp->rx_prod = sw_prod;
 
+	if (pg_ring_used)
+		REG_WR16(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_PG_BDIDX,
+			 bp->rx_pg_prod);
+
 	REG_WR16(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BDIDX, sw_prod);
 
 	REG_WR(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BSEQ, bp->rx_prod_bseq);
@@ -4375,6 +4506,7 @@ bnx2_set_rx_ring_size(struct bnx2 *bp, u32 size)
 	bp->rx_buf_use_size = rx_size;
 	/* hw alignment */
 	bp->rx_buf_size = bp->rx_buf_use_size + BNX2_RX_ALIGN;
+	bp->rx_jumbo_thresh = rx_size - bp->rx_offset;
 	bp->rx_ring_size = size;
 	bp->rx_max_ring = bnx2_find_max_ring(size, MAX_RX_RINGS);
 	bp->rx_max_ring_idx = (bp->rx_max_ring * RX_DESC_CNT) - 1;
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index 93c2436..1f244fa 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -259,6 +259,7 @@ struct l2_fhdr {
 		#define L2_FHDR_STATUS_TCP_SEGMENT	(1<<14)
 		#define L2_FHDR_STATUS_UDP_DATAGRAM	(1<<15)
 
+		#define L2_FHDR_STATUS_SPLIT		(1<<16)
 		#define L2_FHDR_ERRORS_BAD_CRC		(1<<17)
 		#define L2_FHDR_ERRORS_PHY_DECODE	(1<<18)
 		#define L2_FHDR_ERRORS_ALIGNMENT	(1<<19)
@@ -6537,6 +6538,7 @@ struct bnx2 {
 	u32			rx_buf_use_size;	/* useable size */
 	u32			rx_buf_size;		/* with alignment */
 	u32			rx_copy_thresh;
+	u32			rx_jumbo_thresh;
 	u32			rx_max_ring_idx;
 	u32			rx_max_pg_ring_idx;
 



^ permalink raw reply related

* [PATCH 5/8][BNX2]: Add init. code to handle RX pages.
From: Michael Chan @ 2007-12-12 18:59 UTC (permalink / raw)
  To: davem, netdev

[BNX2]: Add init. code to handle RX pages.

Add new fields to keep track of the pages and the page rings.
Add functions to allocate and free pages.

Signed-off-by: Michael Chan <mchan@broadcom.com>

diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index db3b750..38e8e31 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -483,6 +483,16 @@ bnx2_free_mem(struct bnx2 *bp)
 	}
 	vfree(bp->rx_buf_ring);
 	bp->rx_buf_ring = NULL;
+	for (i = 0; i < bp->rx_max_pg_ring; i++) {
+		if (bp->rx_pg_desc_ring[i])
+			pci_free_consistent(bp->pdev, RXBD_RING_SIZE,
+					    bp->rx_pg_desc_ring[i],
+					    bp->rx_pg_desc_mapping[i]);
+		bp->rx_pg_desc_ring[i] = NULL;
+	}
+	if (bp->rx_pg_ring)
+		vfree(bp->rx_pg_ring);
+	bp->rx_pg_ring = NULL;
 }
 
 static int
@@ -514,6 +524,25 @@ bnx2_alloc_mem(struct bnx2 *bp)
 
 	}
 
+	if (bp->rx_pg_ring_size) {
+		bp->rx_pg_ring = vmalloc(SW_RXPG_RING_SIZE *
+					 bp->rx_max_pg_ring);
+		if (bp->rx_pg_ring == NULL)
+			goto alloc_mem_err;
+
+		memset(bp->rx_pg_ring, 0, SW_RXPG_RING_SIZE *
+		       bp->rx_max_pg_ring);
+	}
+
+	for (i = 0; i < bp->rx_max_pg_ring; i++) {
+		bp->rx_pg_desc_ring[i] =
+			pci_alloc_consistent(bp->pdev, RXBD_RING_SIZE,
+					     &bp->rx_pg_desc_mapping[i]);
+		if (bp->rx_pg_desc_ring[i] == NULL)
+			goto alloc_mem_err;
+
+	}
+
 	/* Combine status and statistics blocks into one allocation. */
 	status_blk_size = L1_CACHE_ALIGN(sizeof(struct status_block));
 	bp->status_stats_size = status_blk_size +
@@ -2195,6 +2224,42 @@ bnx2_set_mac_addr(struct bnx2 *bp)
 }
 
 static inline int
+bnx2_alloc_rx_page(struct bnx2 *bp, u16 index)
+{
+	dma_addr_t mapping;
+	struct sw_pg *rx_pg = &bp->rx_pg_ring[index];
+	struct rx_bd *rxbd =
+		&bp->rx_pg_desc_ring[RX_RING(index)][RX_IDX(index)];
+	struct page *page = alloc_page(GFP_ATOMIC);
+
+	if (!page)
+		return -ENOMEM;
+	mapping = pci_map_page(bp->pdev, page, 0, PAGE_SIZE,
+			       PCI_DMA_FROMDEVICE);
+	rx_pg->page = page;
+	pci_unmap_addr_set(rx_pg, mapping, mapping);
+	rxbd->rx_bd_haddr_hi = (u64) mapping >> 32;
+	rxbd->rx_bd_haddr_lo = (u64) mapping & 0xffffffff;
+	return 0;
+}
+
+static void
+bnx2_free_rx_page(struct bnx2 *bp, u16 index)
+{
+	struct sw_pg *rx_pg = &bp->rx_pg_ring[index];
+	struct page *page = rx_pg->page;
+
+	if (!page)
+		return;
+
+	pci_unmap_page(bp->pdev, pci_unmap_addr(rx_pg, mapping), PAGE_SIZE,
+		       PCI_DMA_FROMDEVICE);
+
+	__free_page(page);
+	rx_pg->page = NULL;
+}
+
+static inline int
 bnx2_alloc_rx_skb(struct bnx2 *bp, u16 index)
 {
 	struct sk_buff *skb;
@@ -4213,11 +4278,31 @@ bnx2_init_rx_ring(struct bnx2 *bp)
 	bp->rx_prod = 0;
 	bp->rx_cons = 0;
 	bp->rx_prod_bseq = 0;
+	bp->rx_pg_prod = 0;
+	bp->rx_pg_cons = 0;
 
 	bnx2_init_rxbd_rings(bp->rx_desc_ring, bp->rx_desc_mapping,
 			     bp->rx_buf_use_size, bp->rx_max_ring);
 
 	CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_PG_BUF_SIZE, 0);
+	if (bp->rx_pg_ring_size) {
+		bnx2_init_rxbd_rings(bp->rx_pg_desc_ring,
+				     bp->rx_pg_desc_mapping,
+				     PAGE_SIZE, bp->rx_max_pg_ring);
+		val = (bp->rx_buf_use_size << 16) | PAGE_SIZE;
+		CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_PG_BUF_SIZE, val);
+		CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_RBDC_KEY,
+		       BNX2_L2CTX_RBDC_JUMBO_KEY);
+
+		val = (u64) bp->rx_pg_desc_mapping[0] >> 32;
+		CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_NX_PG_BDHADDR_HI, val);
+
+		val = (u64) bp->rx_pg_desc_mapping[0] & 0xffffffff;
+		CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_NX_PG_BDHADDR_LO, val);
+
+		if (CHIP_NUM(bp) == CHIP_NUM_5709)
+			REG_WR(bp, BNX2_MQ_MAP_L2_3, BNX2_MQ_MAP_L2_3_DEFAULT);
+	}
 
 	val = BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE;
 	val |= BNX2_L2CTX_CTX_TYPE_SIZE_L2;
@@ -4230,6 +4315,15 @@ bnx2_init_rx_ring(struct bnx2 *bp)
 	val = (u64) bp->rx_desc_mapping[0] & 0xffffffff;
 	CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_NX_BDHADDR_LO, val);
 
+	ring_prod = prod = bp->rx_pg_prod;
+	for (i = 0; i < bp->rx_pg_ring_size; i++) {
+		if (bnx2_alloc_rx_page(bp, ring_prod) < 0)
+			break;
+		prod = NEXT_RX_BD(prod);
+		ring_prod = RX_PG_RING_IDX(prod);
+	}
+	bp->rx_pg_prod = prod;
+
 	ring_prod = prod = bp->rx_prod;
 	for (i = 0; i < bp->rx_ring_size; i++) {
 		if (bnx2_alloc_rx_skb(bp, ring_prod) < 0) {
@@ -4240,6 +4334,7 @@ bnx2_init_rx_ring(struct bnx2 *bp)
 	}
 	bp->rx_prod = prod;
 
+	REG_WR16(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_PG_BDIDX, bp->rx_pg_prod);
 	REG_WR16(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BDIDX, prod);
 
 	REG_WR(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BSEQ, bp->rx_prod_bseq);
@@ -4273,6 +4368,9 @@ bnx2_set_rx_ring_size(struct bnx2 *bp, u32 size)
 	rx_size = bp->dev->mtu + ETH_HLEN + bp->rx_offset + 8;
 
 	bp->rx_copy_thresh = RX_COPY_THRESH;
+	bp->rx_pg_ring_size = 0;
+	bp->rx_max_pg_ring = 0;
+	bp->rx_max_pg_ring_idx = 0;
 
 	bp->rx_buf_use_size = rx_size;
 	/* hw alignment */
@@ -4341,6 +4439,8 @@ bnx2_free_rx_skbs(struct bnx2 *bp)
 
 		dev_kfree_skb(skb);
 	}
+	for (i = 0; i < bp->rx_max_pg_ring_idx; i++)
+		bnx2_free_rx_page(bp, i);
 }
 
 static void
@@ -5813,11 +5913,11 @@ bnx2_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
 
 	ering->rx_max_pending = MAX_TOTAL_RX_DESC_CNT;
 	ering->rx_mini_max_pending = 0;
-	ering->rx_jumbo_max_pending = 0;
+	ering->rx_jumbo_max_pending = MAX_TOTAL_RX_PG_DESC_CNT;
 
 	ering->rx_pending = bp->rx_ring_size;
 	ering->rx_mini_pending = 0;
-	ering->rx_jumbo_pending = 0;
+	ering->rx_jumbo_pending = bp->rx_pg_ring_size;
 
 	ering->tx_max_pending = MAX_TX_DESC_CNT;
 	ering->tx_pending = bp->tx_ring_size;
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index 8354efc..93c2436 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -335,6 +335,7 @@ struct l2_fhdr {
 #define BNX2_L2CTX_HOST_PG_BDIDX			0x00000044
 #define BNX2_L2CTX_PG_BUF_SIZE				0x00000048
 #define BNX2_L2CTX_RBDC_KEY				0x0000004c
+#define BNX2_L2CTX_RBDC_JUMBO_KEY			 0x3ffe
 #define BNX2_L2CTX_NX_PG_BDHADDR_HI			0x00000050
 #define BNX2_L2CTX_NX_PG_BDHADDR_LO			0x00000054
 
@@ -4450,6 +4451,14 @@ struct l2_fhdr {
 #define BNX2_MQ_MEM_RD_DATA2_VALUE			 (0x3fffffffL<<0)
 #define BNX2_MQ_MEM_RD_DATA2_VALUE_XI			 (0x7fffffffL<<0)
 
+#define BNX2_MQ_MAP_L2_3				0x00003d2c
+#define BNX2_MQ_MAP_L2_3_MQ_OFFSET			 (0xffL<<0)
+#define BNX2_MQ_MAP_L2_3_SZ				 (0x3L<<8)
+#define BNX2_MQ_MAP_L2_3_CTX_OFFSET			 (0x2ffL<<10)
+#define BNX2_MQ_MAP_L2_3_BIN_OFFSET			 (0x7L<<23)
+#define BNX2_MQ_MAP_L2_3_ARM				 (0x3L<<26)
+#define BNX2_MQ_MAP_L2_3_ENA				 (0x1L<<31)
+#define BNX2_MQ_MAP_L2_3_DEFAULT			 0x82004646
 
 /*
  *  tsch_reg definition
@@ -6360,9 +6369,11 @@ struct l2_fhdr {
 #define MAX_TX_DESC_CNT (TX_DESC_CNT - 1)
 
 #define MAX_RX_RINGS	4
+#define MAX_RX_PG_RINGS	16
 #define RX_DESC_CNT  (BCM_PAGE_SIZE / sizeof(struct rx_bd))
 #define MAX_RX_DESC_CNT (RX_DESC_CNT - 1)
 #define MAX_TOTAL_RX_DESC_CNT (MAX_RX_DESC_CNT * MAX_RX_RINGS)
+#define MAX_TOTAL_RX_PG_DESC_CNT (MAX_RX_DESC_CNT * MAX_RX_PG_RINGS)
 
 #define NEXT_TX_BD(x) (((x) & (MAX_TX_DESC_CNT - 1)) ==			\
 		(MAX_TX_DESC_CNT - 1)) ?				\
@@ -6375,6 +6386,7 @@ struct l2_fhdr {
 	(x) + 2 : (x) + 1
 
 #define RX_RING_IDX(x) ((x) & bp->rx_max_ring_idx)
+#define RX_PG_RING_IDX(x) ((x) & bp->rx_max_pg_ring_idx)
 
 #define RX_RING(x) (((x) & ~MAX_RX_DESC_CNT) >> (BCM_PAGE_BITS - 4))
 #define RX_IDX(x) ((x) & MAX_RX_DESC_CNT)
@@ -6413,7 +6425,13 @@ struct sw_bd {
 	DECLARE_PCI_UNMAP_ADDR(mapping)
 };
 
+struct sw_pg {
+	struct page		*page;
+	DECLARE_PCI_UNMAP_ADDR(mapping)
+};
+
 #define SW_RXBD_RING_SIZE (sizeof(struct sw_bd) * RX_DESC_CNT)
+#define SW_RXPG_RING_SIZE (sizeof(struct sw_pg) * RX_DESC_CNT)
 #define RXBD_RING_SIZE (sizeof(struct rx_bd) * RX_DESC_CNT)
 #define SW_TXBD_RING_SIZE (sizeof(struct sw_bd) * TX_DESC_CNT)
 #define TXBD_RING_SIZE (sizeof(struct tx_bd) * TX_DESC_CNT)
@@ -6520,15 +6538,21 @@ struct bnx2 {
 	u32			rx_buf_size;		/* with alignment */
 	u32			rx_copy_thresh;
 	u32			rx_max_ring_idx;
+	u32			rx_max_pg_ring_idx;
 
 	u32			rx_prod_bseq;
 	u16			rx_prod;
 	u16			rx_cons;
 
+	u16			rx_pg_prod;
+	u16			rx_pg_cons;
+
 	u32			rx_csum;
 
 	struct sw_bd		*rx_buf_ring;
 	struct rx_bd		*rx_desc_ring[MAX_RX_RINGS];
+	struct sw_pg		*rx_pg_ring;
+	struct rx_bd		*rx_pg_desc_ring[MAX_RX_PG_RINGS];
 
 	/* TX constants */
 	struct tx_bd	*tx_desc_ring;
@@ -6616,6 +6640,10 @@ struct bnx2 {
 	int			rx_ring_size;
 	dma_addr_t		rx_desc_mapping[MAX_RX_RINGS];
 
+	int			rx_max_pg_ring;
+	int			rx_pg_ring_size;
+	dma_addr_t		rx_pg_desc_mapping[MAX_RX_PG_RINGS];
+
 	u16			tx_quick_cons_trip;
 	u16			tx_quick_cons_trip_int;
 	u16			rx_quick_cons_trip;



^ permalink raw reply related

* Re: [PATCH resent] virtio_net: Fix stalled inbound trafficon early packets
From: Christian Borntraeger @ 2007-12-12 18:14 UTC (permalink / raw)
  To: dor.laor-atKUWr5tajBWk0Htik3J/w
  Cc: kvm-devel, netdev-u79uwXL29TY76Z2rM5mHXA,
	virtualization-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
In-Reply-To: <476002E7.5050301-atKUWr5tajBWk0Htik3J/w@public.gmane.org>

Am Mittwoch, 12. Dezember 2007 schrieb Dor Laor:
> I think the change below handles the race. Otherwise please detail the 
> use case.
[...]
> > @@ -292,6 +292,9 @@ static int virtnet_open(struct net_devic
> >                 return -ENOMEM;
> >
> >         napi_enable(&vi->napi);
> > +
> > +       vi->rvq->vq_ops->enable(vi->rvq);
> > +       vi->svq->vq_ops->enable(vi->svq);
> >
> If you change it to:
> if (!vi->rvq->vq_ops->enable(vi->rvq))
>     vi->rvq->vq_ops->kick(vi->rvq);
> if (!vi->rvq->vq_ops->enable(vi->svq))
>     vi->rvq->vq_ops->kick(vi->svq);
> 
> You solve the race of packets already waiting in the queue without 
> triggering the irq.

Hmm, I dont fully understand your point. I think this will work as long as 
the host has not consumed all inbound buffers. It will also require that 
the host sends an additional packet, no? If no additional packet comes the 
host has no reason to send an interrupt just because it got a notify 
hypercall. kick inside a guest also does not trigger the poll routine. 

It also wont work on the following scenario:
in virtnet open we will allocate buffers and send them to the host using the 
kick callback. The host can now use _all_ buffers for incoming data while 
interrupts are still disabled and the guest is not running.( Lets say the 
host bridge has lots of multicast traffic and the guest gets not scheduled 
for a while). When the guest now continues and enables the interrupts 
nothing happens. Doing a kick does not help, as the host code will bail out 
with "no dma memory for transfer".

Christian


-------------------------------------------------------------------------
SF.Net email is sponsored by:
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services
for just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace

^ permalink raw reply

* [PATCH 3/8][BNX2]: Restructure RX ring init. code.
From: Michael Chan @ 2007-12-12 18:59 UTC (permalink / raw)
  To: davem, netdev

[BNX2]: Restructure RX ring init. code.

Factor out the common functions that will be used to initialize the
normal RX rings and the page rings.

Change the copybreak constant RX_COPY_THRESH to 128.  This same
constant will be used for the max. size of the linear SKB when pages
are used.  Copybreak will be turned off when pages are used.

Signed-off-by: Michael Chan <mchan@broadcom.com>

diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 14119fb..81971b1 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -2117,15 +2117,12 @@ bnx2_init_context(struct bnx2 *bp)
 			vcid_addr += (i << PHY_CTX_SHIFT);
 			pcid_addr += (i << PHY_CTX_SHIFT);
 
-			REG_WR(bp, BNX2_CTX_VIRT_ADDR, 0x00);
+			REG_WR(bp, BNX2_CTX_VIRT_ADDR, vcid_addr);
 			REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr);
 
 			/* Zero out the context. */
 			for (offset = 0; offset < PHY_CTX_SIZE; offset += 4)
-				CTX_WR(bp, 0x00, offset, 0);
-
-			REG_WR(bp, BNX2_CTX_VIRT_ADDR, vcid_addr);
-			REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr);
+				CTX_WR(bp, vcid_addr, offset, 0);
 		}
 	}
 }
@@ -2459,10 +2456,7 @@ bnx2_rx_int(struct bnx2 *bp, int budget)
 			goto next_rx;
 		}
 
-		/* Since we don't have a jumbo ring, copy small packets
-		 * if mtu > 1500
-		 */
-		if ((bp->dev->mtu > 1500) && (len <= RX_COPY_THRESH)) {
+		if (len <= bp->rx_copy_thresh) {
 			struct sk_buff *new_skb;
 
 			new_skb = netdev_alloc_skb(bp->dev, len + 2);
@@ -4172,50 +4166,57 @@ bnx2_init_tx_ring(struct bnx2 *bp)
 }
 
 static void
-bnx2_init_rx_ring(struct bnx2 *bp)
+bnx2_init_rxbd_rings(struct rx_bd *rx_ring[], dma_addr_t dma[], u32 buf_size,
+		     int num_rings)
 {
-	struct rx_bd *rxbd;
 	int i;
-	u16 prod, ring_prod;
-	u32 val;
-
-	/* 8 for CRC and VLAN */
-	bp->rx_buf_use_size = bp->dev->mtu + ETH_HLEN + bp->rx_offset + 8;
-	/* hw alignment */
-	bp->rx_buf_size = bp->rx_buf_use_size + BNX2_RX_ALIGN;
-
-	ring_prod = prod = bp->rx_prod = 0;
-	bp->rx_cons = 0;
-	bp->rx_prod_bseq = 0;
+	struct rx_bd *rxbd;
 
-	for (i = 0; i < bp->rx_max_ring; i++) {
+	for (i = 0; i < num_rings; i++) {
 		int j;
 
-		rxbd = &bp->rx_desc_ring[i][0];
+		rxbd = &rx_ring[i][0];
 		for (j = 0; j < MAX_RX_DESC_CNT; j++, rxbd++) {
-			rxbd->rx_bd_len = bp->rx_buf_use_size;
+			rxbd->rx_bd_len = buf_size;
 			rxbd->rx_bd_flags = RX_BD_FLAGS_START | RX_BD_FLAGS_END;
 		}
-		if (i == (bp->rx_max_ring - 1))
+		if (i == (num_rings - 1))
 			j = 0;
 		else
 			j = i + 1;
-		rxbd->rx_bd_haddr_hi = (u64) bp->rx_desc_mapping[j] >> 32;
-		rxbd->rx_bd_haddr_lo = (u64) bp->rx_desc_mapping[j] &
-				       0xffffffff;
+		rxbd->rx_bd_haddr_hi = (u64) dma[j] >> 32;
+		rxbd->rx_bd_haddr_lo = (u64) dma[j] & 0xffffffff;
 	}
+}
+
+static void
+bnx2_init_rx_ring(struct bnx2 *bp)
+{
+	int i;
+	u16 prod, ring_prod;
+	u32 val, rx_cid_addr = GET_CID_ADDR(RX_CID);
+
+	bp->rx_prod = 0;
+	bp->rx_cons = 0;
+	bp->rx_prod_bseq = 0;
+
+	bnx2_init_rxbd_rings(bp->rx_desc_ring, bp->rx_desc_mapping,
+			     bp->rx_buf_use_size, bp->rx_max_ring);
+
+	CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_PG_BUF_SIZE, 0);
 
 	val = BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE;
 	val |= BNX2_L2CTX_CTX_TYPE_SIZE_L2;
 	val |= 0x02 << 8;
-	CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_CTX_TYPE, val);
+	CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_CTX_TYPE, val);
 
 	val = (u64) bp->rx_desc_mapping[0] >> 32;
-	CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_NX_BDHADDR_HI, val);
+	CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_NX_BDHADDR_HI, val);
 
 	val = (u64) bp->rx_desc_mapping[0] & 0xffffffff;
-	CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_NX_BDHADDR_LO, val);
+	CTX_WR(bp, rx_cid_addr, BNX2_L2CTX_NX_BDHADDR_LO, val);
 
+	ring_prod = prod = bp->rx_prod;
 	for (i = 0; i < bp->rx_ring_size; i++) {
 		if (bnx2_alloc_rx_skb(bp, ring_prod) < 0) {
 			break;
@@ -4230,26 +4231,40 @@ bnx2_init_rx_ring(struct bnx2 *bp)
 	REG_WR(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BSEQ, bp->rx_prod_bseq);
 }
 
-static void
-bnx2_set_rx_ring_size(struct bnx2 *bp, u32 size)
+static u32 bnx2_find_max_ring(u32 ring_size, u32 max_size)
 {
-	u32 num_rings, max;
+	u32 max, num_rings = 1;
 
-	bp->rx_ring_size = size;
-	num_rings = 1;
-	while (size > MAX_RX_DESC_CNT) {
-		size -= MAX_RX_DESC_CNT;
+	while (ring_size > MAX_RX_DESC_CNT) {
+		ring_size -= MAX_RX_DESC_CNT;
 		num_rings++;
 	}
 	/* round to next power of 2 */
-	max = MAX_RX_RINGS;
+	max = max_size;
 	while ((max & num_rings) == 0)
 		max >>= 1;
 
 	if (num_rings != max)
 		max <<= 1;
 
-	bp->rx_max_ring = max;
+	return max;
+}
+
+static void
+bnx2_set_rx_ring_size(struct bnx2 *bp, u32 size)
+{
+	u32 rx_size;
+
+	/* 8 for CRC and VLAN */
+	rx_size = bp->dev->mtu + ETH_HLEN + bp->rx_offset + 8;
+
+	bp->rx_copy_thresh = RX_COPY_THRESH;
+
+	bp->rx_buf_use_size = rx_size;
+	/* hw alignment */
+	bp->rx_buf_size = bp->rx_buf_use_size + BNX2_RX_ALIGN;
+	bp->rx_ring_size = size;
+	bp->rx_max_ring = bnx2_find_max_ring(size, MAX_RX_RINGS);
 	bp->rx_max_ring_idx = (bp->rx_max_ring * RX_DESC_CNT) - 1;
 }
 
@@ -5795,16 +5810,8 @@ bnx2_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
 }
 
 static int
-bnx2_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
+bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx)
 {
-	struct bnx2 *bp = netdev_priv(dev);
-
-	if ((ering->rx_pending > MAX_TOTAL_RX_DESC_CNT) ||
-		(ering->tx_pending > MAX_TX_DESC_CNT) ||
-		(ering->tx_pending <= MAX_SKB_FRAGS)) {
-
-		return -EINVAL;
-	}
 	if (netif_running(bp->dev)) {
 		bnx2_netif_stop(bp);
 		bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET);
@@ -5812,8 +5819,8 @@ bnx2_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
 		bnx2_free_mem(bp);
 	}
 
-	bnx2_set_rx_ring_size(bp, ering->rx_pending);
-	bp->tx_ring_size = ering->tx_pending;
+	bnx2_set_rx_ring_size(bp, rx);
+	bp->tx_ring_size = tx;
 
 	if (netif_running(bp->dev)) {
 		int rc;
@@ -5824,10 +5831,25 @@ bnx2_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
 		bnx2_init_nic(bp);
 		bnx2_netif_start(bp);
 	}
-
 	return 0;
 }
 
+static int
+bnx2_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
+{
+	struct bnx2 *bp = netdev_priv(dev);
+	int rc;
+
+	if ((ering->rx_pending > MAX_TOTAL_RX_DESC_CNT) ||
+		(ering->tx_pending > MAX_TX_DESC_CNT) ||
+		(ering->tx_pending <= MAX_SKB_FRAGS)) {
+
+		return -EINVAL;
+	}
+	rc = bnx2_change_ring_size(bp, ering->rx_pending, ering->tx_pending);
+	return rc;
+}
+
 static void
 bnx2_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
 {
@@ -6316,14 +6338,7 @@ bnx2_change_mtu(struct net_device *dev, int new_mtu)
 		return -EINVAL;
 
 	dev->mtu = new_mtu;
-	if (netif_running(dev)) {
-		bnx2_netif_stop(bp);
-
-		bnx2_init_nic(bp);
-
-		bnx2_netif_start(bp);
-	}
-	return 0;
+	return (bnx2_change_ring_size(bp, bp->rx_ring_size, bp->tx_ring_size));
 }
 
 #if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER)
@@ -6644,13 +6659,13 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
 	bp->mac_addr[4] = (u8) (reg >> 8);
 	bp->mac_addr[5] = (u8) reg;
 
+	bp->rx_offset = sizeof(struct l2_fhdr) + 2;
+
 	bp->tx_ring_size = MAX_TX_DESC_CNT;
 	bnx2_set_rx_ring_size(bp, 255);
 
 	bp->rx_csum = 1;
 
-	bp->rx_offset = sizeof(struct l2_fhdr) + 2;
-
 	bp->tx_quick_cons_trip_int = 20;
 	bp->tx_quick_cons_trip = 20;
 	bp->tx_ticks_int = 80;
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index e6a2153..8354efc 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -332,6 +332,11 @@ struct l2_fhdr {
 #define BNX2_L2CTX_NX_BDHADDR_LO			0x00000014
 #define BNX2_L2CTX_NX_BDIDX				0x00000018
 
+#define BNX2_L2CTX_HOST_PG_BDIDX			0x00000044
+#define BNX2_L2CTX_PG_BUF_SIZE				0x00000048
+#define BNX2_L2CTX_RBDC_KEY				0x0000004c
+#define BNX2_L2CTX_NX_PG_BDHADDR_HI			0x00000050
+#define BNX2_L2CTX_NX_PG_BDHADDR_LO			0x00000054
 
 /*
  *  pci_config_l definition
@@ -6336,7 +6341,7 @@ struct l2_fhdr {
 #define MAX_ETHERNET_PACKET_SIZE	1514
 #define MAX_ETHERNET_JUMBO_PACKET_SIZE	9014
 
-#define RX_COPY_THRESH			92
+#define RX_COPY_THRESH			128
 
 #define BNX2_MISC_ENABLE_DEFAULT	0x7ffffff
 
@@ -6513,6 +6518,7 @@ struct bnx2 {
 	u32			rx_offset;
 	u32			rx_buf_use_size;	/* useable size */
 	u32			rx_buf_size;		/* with alignment */
+	u32			rx_copy_thresh;
 	u32			rx_max_ring_idx;
 
 	u32			rx_prod_bseq;



^ permalink raw reply related

* [PATCH 2/8][BNX2]: Restructure RX fast path handling.
From: Michael Chan @ 2007-12-12 18:58 UTC (permalink / raw)
  To: davem, netdev

[BNX2]: Restructure RX fast path handling.

Add a new function to handle new SKB allocation and to prepare the
completed SKB.  This makes it easier to add support for non-linear
SKB.
 
Signed-off-by: Michael Chan <mchan@broadcom.com>

diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index dfe50c2..14119fb 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -2379,6 +2379,27 @@ bnx2_reuse_rx_skb(struct bnx2 *bp, struct sk_buff *skb,
 	prod_bd->rx_bd_haddr_lo = cons_bd->rx_bd_haddr_lo;
 }
 
+static int
+bnx2_rx_skb(struct bnx2 *bp, struct sk_buff *skb, unsigned int len,
+	    dma_addr_t dma_addr, u32 ring_idx)
+{
+	int err;
+	u16 prod = ring_idx & 0xffff;
+
+	err = bnx2_alloc_rx_skb(bp, prod);
+	if (unlikely(err)) {
+		bnx2_reuse_rx_skb(bp, skb, (u16) (ring_idx >> 16), prod);
+		return err;
+	}
+
+	skb_reserve(skb, bp->rx_offset);
+	pci_unmap_single(bp->pdev, dma_addr, bp->rx_buf_use_size,
+			 PCI_DMA_FROMDEVICE);
+
+	skb_put(skb, len);
+	return 0;
+}
+
 static inline u16
 bnx2_get_hw_rx_cons(struct bnx2 *bp)
 {
@@ -2434,7 +2455,8 @@ bnx2_rx_int(struct bnx2 *bp, int budget)
 			L2_FHDR_ERRORS_TOO_SHORT |
 			L2_FHDR_ERRORS_GIANT_FRAME)) {
 
-			goto reuse_rx;
+			bnx2_reuse_rx_skb(bp, skb, sw_ring_cons, sw_ring_prod);
+			goto next_rx;
 		}
 
 		/* Since we don't have a jumbo ring, copy small packets
@@ -2444,8 +2466,11 @@ bnx2_rx_int(struct bnx2 *bp, int budget)
 			struct sk_buff *new_skb;
 
 			new_skb = netdev_alloc_skb(bp->dev, len + 2);
-			if (new_skb == NULL)
-				goto reuse_rx;
+			if (new_skb == NULL) {
+				bnx2_reuse_rx_skb(bp, skb, sw_ring_cons,
+						  sw_ring_prod);
+				goto next_rx;
+			}
 
 			/* aligned copy */
 			skb_copy_from_linear_data_offset(skb, bp->rx_offset - 2,
@@ -2457,20 +2482,9 @@ bnx2_rx_int(struct bnx2 *bp, int budget)
 				sw_ring_cons, sw_ring_prod);
 
 			skb = new_skb;
-		}
-		else if (bnx2_alloc_rx_skb(bp, sw_ring_prod) == 0) {
-			pci_unmap_single(bp->pdev, dma_addr,
-				bp->rx_buf_use_size, PCI_DMA_FROMDEVICE);
-
-			skb_reserve(skb, bp->rx_offset);
-			skb_put(skb, len);
-		}
-		else {
-reuse_rx:
-			bnx2_reuse_rx_skb(bp, skb,
-				sw_ring_cons, sw_ring_prod);
+		} else if (unlikely(bnx2_rx_skb(bp, skb, len, dma_addr,
+				    (sw_ring_cons << 16) | sw_ring_prod)))
 			goto next_rx;
-		}
 
 		skb->protocol = eth_type_trans(skb, bp->dev);
 



^ permalink raw reply related

* [PATCH 0/8][BNX2]: Add S/G jumbo RX support.
From: Michael Chan @ 2007-12-12 18:57 UTC (permalink / raw)
  To: davem, netdev

[BNX2]: Add S/G jumbo RX support.

David, 8 patches will follow to implement S/G for jumbo RX packets.
Please review for 2.6.25.  Thanks.

Signed-off-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/bnx2.c     |  510 +++-
 drivers/net/bnx2.h     |   43 +-
 drivers/net/bnx2_fw.h  | 7034 +++++++++++++++++++++++++---------------
 drivers/net/bnx2_fw2.h | 8416 +++++++++++++++++++++++++-----------------------
 4 files changed, 9301 insertions(+), 6702 deletions(-)

---
[PATCH 1/8][BNX2]: Add ring constants.
[PATCH 2/8][BNX2]: Restructure RX fast path handling.
[PATCH 3/8][BNX2]: Restructure RX ring init. code.
[PATCH 4/8 gzipped][BNX2]: Update firmware to support S/G RX buffers.
[PATCH 5/8][BNX2]: Add init. code to handle RX pages.
[PATCH 6/8][BNX2]: Add fast path code to handle RX pages.
[PATCH 7/8][BNX2]: Enable S/G for jumbo RX.
[PATCH 8/8][BNX2]: Update version to 1.6.9.



^ permalink raw reply

* Re: 2.6.24-rc4-mm1
From: Cedric Le Goater @ 2007-12-12 17:57 UTC (permalink / raw)
  To: Ilpo Järvinen
  Cc: reuben-linuxkernel, akpm, LKML, Netdev, auke-jan.h.kok,
	David Miller
In-Reply-To: <Pine.LNX.4.64.0712061146120.28055@kivilampi-30.cs.helsinki.fi>

Ilpo Järvinen wrote:
> On Wed, 5 Dec 2007, David Miller wrote:
> 
>> From: Reuben Farrelly <reuben-linuxkernel@reub.net>
>> Date: Thu, 06 Dec 2007 17:59:37 +1100
>>
>>> On 5/12/2007 4:17 PM, Andrew Morton wrote:
>>>> - Lots of device IDs have been removed from the e1000 driver and moved over
>>>>   to e1000e.  So if your e1000 stops working, you forgot to set CONFIG_E1000E.
>>> This non fatal oops which I have just noticed may be related to this change then 
>>> - certainly looks networking related.
>>>
>>> WARNING: at net/ipv4/tcp_input.c:2518 tcp_fastretrans_alert()
>>> Pid: 0, comm: swapper Not tainted 2.6.24-rc4-mm1 #1
>>>
>>> Call Trace:
>>>   <IRQ>  [<ffffffff8046e038>] tcp_fastretrans_alert+0x229/0xe63
>>>   [<ffffffff80470975>] tcp_ack+0xa3f/0x127d
>>>   [<ffffffff804747b7>] tcp_rcv_established+0x55f/0x7f8
>>>   [<ffffffff8047b1aa>] tcp_v4_do_rcv+0xdb/0x3a7
>>>   [<ffffffff881148a8>] :nf_conntrack:nf_ct_deliver_cached_events+0x75/0x99
>> No, it's from TCP assertions and changes added by Ilpo to the
>> net-2.6.25 tree recently.
> 
> Yeah, this (very likely) due to the new SACK processing (in net-2.6.25). 
> I'll look what could go wrong with fack_count calculations, most likely 
> it's the reason (I've found earlier one out-of-place retransmission 
> segment in one of my test case which already indicated that there's 
> something incorrect with them but didn't have time to debug it yet).
> 
> Thanks for report. Some info about how easily you can reproduce & 
> couple of sentences about the test case might be useful later on when 
> evaluating the fix.

I also got plenty of these when untaring a tarball on NFS.

C. 

WARNING: at /home/legoater/linux/2.6.24-rc4-mm1/net/ipv4/tcp_input.c:2518 tcp_fastretrans_alert()
Pid: 0, comm: swapper Not tainted 2.6.24-rc4-mm1 #2

Call Trace:
 <IRQ>  [<ffffffff804115bf>] tcp_fastretrans_alert+0xb6/0xbf2
 [<ffffffff80413f30>] tcp_ack+0xdf3/0xfbe
 [<ffffffff803da8fb>] sk_reset_timer+0x17/0x23
 [<ffffffff80416d1e>] tcp_rcv_established+0xf3/0x76d
 [<ffffffff8041d231>] tcp_v4_do_rcv+0x37/0x3aa
 [<ffffffff8041fb1f>] tcp_v4_rcv+0x9a9/0xa76
 [<ffffffff80402e4e>] ip_local_deliver_finish+0x161/0x23c
 [<ffffffff80403363>] ip_local_deliver+0x72/0x77
 [<ffffffff80402ca9>] ip_rcv_finish+0x371/0x3b5
 [<ffffffff804032bd>] ip_rcv+0x292/0x2c6
 [<ffffffff803e3dcc>] netif_receive_skb+0x267/0x340
 [<ffffffff8806eff4>] :tg3:tg3_poll+0x5d2/0x89e
 [<ffffffff803e639d>] net_rx_action+0xd5/0x1ad
 [<ffffffff8023b605>] __do_softirq+0x5f/0xe3
 [<ffffffff8020c86c>] call_softirq+0x1c/0x28
 [<ffffffff8020e739>] do_softirq+0x39/0x9f
 [<ffffffff8023b5a4>] irq_exit+0x4e/0x50
 [<ffffffff8020e880>] do_IRQ+0xb7/0xd7
 [<ffffffff8020a803>] mwait_idle+0x0/0x55
 [<ffffffff8020bb66>] ret_from_intr+0x0/0xf
 <EOI>  [<ffffffff8024d623>] __atomic_notifier_call_chain+0x20/0x83
 [<ffffffff8020a84b>] mwait_idle+0x48/0x55
 [<ffffffff80209e79>] enter_idle+0x22/0x24
 [<ffffffff8020a793>] cpu_idle+0xa1/0xc5
 [<ffffffff8021dfd5>] start_secondary+0x3b9/0x3c5

WARNING: at /home/legoater/linux/2.6.24-rc4-mm1/net/ipv4/tcp_input.c:2518 tcp_fastretrans_alert()
Pid: 0, comm: swapper Not tainted 2.6.24-rc4-mm1 #2

Call Trace:
 <IRQ>  [<ffffffff804115bf>] tcp_fastretrans_alert+0xb6/0xbf2
 [<ffffffff80413f30>] tcp_ack+0xdf3/0xfbe
 [<ffffffff804153b8>] tcp_data_queue+0x5da/0xb0a
 [<ffffffff80416d1e>] tcp_rcv_established+0xf3/0x76d
 [<ffffffff8041d231>] tcp_v4_do_rcv+0x37/0x3aa
 [<ffffffff8041fb1f>] tcp_v4_rcv+0x9a9/0xa76
 [<ffffffff80402e4e>] ip_local_deliver_finish+0x161/0x23c
 [<ffffffff80403363>] ip_local_deliver+0x72/0x77
 [<ffffffff80402ca9>] ip_rcv_finish+0x371/0x3b5
 [<ffffffff804032bd>] ip_rcv+0x292/0x2c6
 [<ffffffff803e3dcc>] netif_receive_skb+0x267/0x340
 [<ffffffff8806eff4>] :tg3:tg3_poll+0x5d2/0x89e
 [<ffffffff803e639d>] net_rx_action+0xd5/0x1ad
 [<ffffffff8023b605>] __do_softirq+0x5f/0xe3
 [<ffffffff8020c86c>] call_softirq+0x1c/0x28
 [<ffffffff8020e739>] do_softirq+0x39/0x9f
 [<ffffffff8023b5a4>] irq_exit+0x4e/0x50
 [<ffffffff8020e880>] do_IRQ+0xb7/0xd7
 [<ffffffff8020a803>] mwait_idle+0x0/0x55
 [<ffffffff8020bb66>] ret_from_intr+0x0/0xf
 <EOI>  [<ffffffff8024d623>] __atomic_notifier_call_chain+0x20/0x83
 [<ffffffff8020a84b>] mwait_idle+0x48/0x55
 [<ffffffff80209e79>] enter_idle+0x22/0x24
 [<ffffffff8020a793>] cpu_idle+0xa1/0xc5
 [<ffffffff8021dfd5>] start_secondary+0x3b9/0x3c5

WARNING: at /home/legoater/linux/2.6.24-rc4-mm1/net/ipv4/tcp_input.c:2518 tcp_fastretrans_alert()
Pid: 0, comm: swapper Not tainted 2.6.24-rc4-mm1 #2

Call Trace:
 <IRQ>  [<ffffffff804115bf>] tcp_fastretrans_alert+0xb6/0xbf2
 [<ffffffff80413f30>] tcp_ack+0xdf3/0xfbe
 [<ffffffff804153b8>] tcp_data_queue+0x5da/0xb0a
 [<ffffffff80416d1e>] tcp_rcv_established+0xf3/0x76d
 [<ffffffff8041d231>] tcp_v4_do_rcv+0x37/0x3aa
 [<ffffffff8041fb1f>] tcp_v4_rcv+0x9a9/0xa76
 [<ffffffff80402e4e>] ip_local_deliver_finish+0x161/0x23c
 [<ffffffff80403363>] ip_local_deliver+0x72/0x77
 [<ffffffff80402ca9>] ip_rcv_finish+0x371/0x3b5
 [<ffffffff804032bd>] ip_rcv+0x292/0x2c6
 [<ffffffff803e3dcc>] netif_receive_skb+0x267/0x340
 [<ffffffff8806eff4>] :tg3:tg3_poll+0x5d2/0x89e
 [<ffffffff803e639d>] net_rx_action+0xd5/0x1ad
 [<ffffffff8023b605>] __do_softirq+0x5f/0xe3
 [<ffffffff8020c86c>] call_softirq+0x1c/0x28
 [<ffffffff8020e739>] do_softirq+0x39/0x9f
 [<ffffffff8023b5a4>] irq_exit+0x4e/0x50
 [<ffffffff8020e880>] do_IRQ+0xb7/0xd7
 [<ffffffff8020a803>] mwait_idle+0x0/0x55
 [<ffffffff8020bb66>] ret_from_intr+0x0/0xf
 <EOI>  [<ffffffff8024d623>] __atomic_notifier_call_chain+0x20/0x83
 [<ffffffff8020a84b>] mwait_idle+0x48/0x55
 [<ffffffff80209e79>] enter_idle+0x22/0x24
 [<ffffffff8020a793>] cpu_idle+0xa1/0xc5
 [<ffffffff8021dfd5>] start_secondary+0x3b9/0x3c5


^ permalink raw reply

* Re: [Bugme-new] [Bug 9543] New: RTNL: assertion failed at net/ipv6/addrconf.c (2164)/RTNL: assertion failed at net/ipv4/devinet.c (1055)
From: Jay Vosburgh @ 2007-12-12 17:46 UTC (permalink / raw)
  To: Herbert Xu
  Cc: Andrew Morton, olel, bugme-daemon, shemminger, davem, netdev,
	andy
In-Reply-To: <E1J2Rgs-0006mz-00@gondolin.me.apana.org.au>

Herbert Xu <herbert@gondor.apana.org.au> wrote:

>> diff -puN drivers/net/bonding/bond_sysfs.c~bonding-locking-fix drivers/net/bonding/bond_sysfs.c
>> --- a/drivers/net/bonding/bond_sysfs.c~bonding-locking-fix
>> +++ a/drivers/net/bonding/bond_sysfs.c
>> @@ -1111,8 +1111,6 @@ static ssize_t bonding_store_primary(str
>> out:
>>        write_unlock_bh(&bond->lock);
>> 
>> -       rtnl_unlock();
>> -
>
>Looking at the changeset that added this perhaps the intention
>is to hold the lock? If so we should add an rtnl_lock to the start
>of the function.

	Yes, this function needs to hold locks, and more than just
what's there now.  I believe the following should be correct; I haven't
tested it, though (I'm supposedly on vacation right now).

	The following change should be correct for the
bonding_store_primary case discussed in this thread, and also corrects
the bonding_store_active case which performs similar functions.

	The bond_change_active_slave and bond_select_active_slave
functions both require rtnl, bond->lock for read and curr_slave_lock for
write_bh, and no other locks.  This is so that the lower level
mode-specific functions can release locks down to just rtnl in order to
call, e.g., dev_set_mac_address with the locks it expects (rtnl only).

Signed-off-by: Jay Vosburgh <fubar@us.ibm.com>

diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 11b76b3..28a2d80 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -1075,7 +1075,10 @@ static ssize_t bonding_store_primary(struct device *d,
 	struct slave *slave;
 	struct bonding *bond = to_bond(d);
 
-	write_lock_bh(&bond->lock);
+	rtnl_lock();
+	read_lock(&bond->lock);
+	write_lock_bh(&bond->curr_slave_lock);
+
 	if (!USES_PRIMARY(bond->params.mode)) {
 		printk(KERN_INFO DRV_NAME
 		       ": %s: Unable to set primary slave; %s is in mode %d\n",
@@ -1109,8 +1112,8 @@ static ssize_t bonding_store_primary(struct device *d,
 		}
 	}
 out:
-	write_unlock_bh(&bond->lock);
-
+	write_unlock_bh(&bond->curr_slave_lock);
+	read_unlock(&bond->lock);
 	rtnl_unlock();
 
 	return count;
@@ -1190,7 +1193,8 @@ static ssize_t bonding_store_active_slave(struct device *d,
 	struct bonding *bond = to_bond(d);
 
 	rtnl_lock();
-	write_lock_bh(&bond->lock);
+	read_lock(&bond->lock);
+	write_lock_bh(&bond->curr_slave_lock);
 
 	if (!USES_PRIMARY(bond->params.mode)) {
 		printk(KERN_INFO DRV_NAME
@@ -1247,7 +1251,8 @@ static ssize_t bonding_store_active_slave(struct device *d,
 		}
 	}
 out:
-	write_unlock_bh(&bond->lock);
+	write_unlock_bh(&bond->curr_slave_lock);
+	read_unlock(&bond->lock);
 	rtnl_unlock();
 
 	return count;


^ permalink raw reply related

* Re: [RFC] net: napi fix
From: Andrew Gallatin @ 2007-12-12 17:40 UTC (permalink / raw)
  To: David Miller; +Cc: joonwpark81, netdev, linux-kernel, jgarzik, shemminger
In-Reply-To: <20071212.093819.205755031.davem@davemloft.net>

David Miller wrote:
> From: Andrew Gallatin <gallatin@myri.com>
> Date: Wed, 12 Dec 2007 12:29:23 -0500
> 
>> Is the netif_running() check even required?
> 
> No, it is not.
> 
> When a device is brought down, one of the first things
> that happens is that we wait for all pending NAPI polls
> to complete, then block any new polls from starting.

Great, thanks.  I will submit a patch to remove the bogus
check.  This should fix myri10ge properly.


Thank you,

Drew

^ permalink raw reply

* Re: [RFC] net: napi fix
From: David Miller @ 2007-12-12 17:38 UTC (permalink / raw)
  To: gallatin; +Cc: joonwpark81, netdev, linux-kernel, jgarzik, shemminger
In-Reply-To: <47601A73.5010804@myri.com>

From: Andrew Gallatin <gallatin@myri.com>
Date: Wed, 12 Dec 2007 12:29:23 -0500

> Is the netif_running() check even required?

No, it is not.

When a device is brought down, one of the first things
that happens is that we wait for all pending NAPI polls
to complete, then block any new polls from starting.

^ permalink raw reply

* [PATCH 8/8] gianfar: Magic Packet and suspend/resume support.
From: Scott Wood @ 2007-12-12 17:36 UTC (permalink / raw)
  To: paulus, jgarzik; +Cc: linuxppc-dev, netdev
In-Reply-To: <20071212173519.GA5577@loki.buserror.net>

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
Jeff, can you ack this to go through Paul's tree
(assuming nothing wrong with it)?

 drivers/net/gianfar.c         |  137 ++++++++++++++++++++++++++++++++++++++++-
 drivers/net/gianfar.h         |   13 +++-
 drivers/net/gianfar_ethtool.c |   41 ++++++++++++-
 3 files changed, 185 insertions(+), 6 deletions(-)

diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 0431e9e..2c1b8d5 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -142,6 +142,7 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit);
 static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int length);
 static void gfar_vlan_rx_register(struct net_device *netdev,
 		                struct vlan_group *grp);
+static void gfar_halt_nodisable(struct net_device *dev);
 void gfar_halt(struct net_device *dev);
 void gfar_start(struct net_device *dev);
 static void gfar_clear_exact_match(struct net_device *dev);
@@ -216,6 +217,7 @@ static int gfar_probe(struct platform_device *pdev)
 
 	spin_lock_init(&priv->txlock);
 	spin_lock_init(&priv->rxlock);
+	spin_lock_init(&priv->bflock);
 
 	platform_set_drvdata(pdev, dev);
 
@@ -393,6 +395,122 @@ static int gfar_remove(struct platform_device *pdev)
 	return 0;
 }
 
+#ifdef CONFIG_PM
+static int gfar_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct net_device *dev = platform_get_drvdata(pdev);
+	struct gfar_private *priv = netdev_priv(dev);
+	unsigned long flags;
+	u32 tempval;
+
+	int magic_packet = priv->wol_en &&
+		(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
+
+	netif_device_detach(dev);
+
+	if (netif_running(dev)) {
+		spin_lock_irqsave(&priv->txlock, flags);
+		spin_lock(&priv->rxlock);
+
+		gfar_halt_nodisable(dev);
+
+		/* Disable Tx, and Rx if wake-on-LAN is disabled. */
+		tempval = gfar_read(&priv->regs->maccfg1);
+
+		tempval &= ~MACCFG1_TX_EN;
+
+		if (!magic_packet)
+			tempval &= ~MACCFG1_RX_EN;
+
+		gfar_write(&priv->regs->maccfg1, tempval);
+
+		spin_unlock(&priv->rxlock);
+		spin_unlock_irqrestore(&priv->txlock, flags);
+
+#ifdef CONFIG_GFAR_NAPI
+		napi_disable(&priv->napi);
+#endif
+
+		if (magic_packet) {
+			/* Enable interrupt on Magic Packet */
+			gfar_write(&priv->regs->imask, IMASK_MAG);
+
+			/* Enable Magic Packet mode */
+			tempval = gfar_read(&priv->regs->maccfg2);
+			tempval |= MACCFG2_MPEN;
+			gfar_write(&priv->regs->maccfg2, tempval);
+		} else {
+			phy_stop(priv->phydev);
+		}
+	}
+
+	if (!magic_packet || !netif_running(dev)) {
+		/* The device with the MDIO in its register block must
+		 * not be put to sleep if any other network devices
+		 * using the same MDIO are active.  Ideally, some sort
+		 * of reference counting could be done, but for now
+		 * just don't put the MDIO-containing dev to sleep
+		 * at all.
+		 */
+		if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MDIO)) {
+			fsl_sleep_device(&priv->einfo->sleep);
+			priv->suspended = 1;
+		}
+	}
+
+	return 0;
+}
+
+static int gfar_resume(struct platform_device *pdev)
+{
+	struct net_device *dev = platform_get_drvdata(pdev);
+	struct gfar_private *priv = netdev_priv(dev);
+	unsigned long flags;
+	u32 tempval;
+	int magic_packet = priv->wol_en &&
+		(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
+
+	if (priv->suspended) {
+		fsl_wake_device(&priv->einfo->sleep);
+		priv->suspended = 0;
+	}
+
+	if (!netif_running(dev)) {
+		netif_device_attach(dev);
+		return 0;
+	}
+
+	if (!magic_packet && priv->phydev)
+		phy_start(priv->phydev);
+
+	/* Disable Magic Packet mode, in case something
+	 * else woke us up.
+	 */
+
+	spin_lock_irqsave(&priv->txlock, flags);
+	spin_lock(&priv->rxlock);
+
+	tempval = gfar_read(&priv->regs->maccfg2);
+	tempval &= ~MACCFG2_MPEN;
+	gfar_write(&priv->regs->maccfg2, tempval);
+
+	gfar_start(dev);
+
+	spin_unlock(&priv->rxlock);
+	spin_unlock_irqrestore(&priv->txlock, flags);
+
+	netif_device_attach(dev);
+
+#ifdef CONFIG_GFAR_NAPI
+	napi_enable(&priv->napi);
+#endif
+
+	return 0;
+}
+#else
+#define gfar_suspend NULL
+#define gfar_resume NULL
+#endif
 
 /* Reads the controller's registers to determine what interface
  * connects it to the PHY.
@@ -547,7 +665,7 @@ static void init_registers(struct net_device *dev)
 
 
 /* Halt the receive and transmit queues */
-void gfar_halt(struct net_device *dev)
+static void gfar_halt_nodisable(struct net_device *dev)
 {
 	struct gfar_private *priv = netdev_priv(dev);
 	struct gfar __iomem *regs = priv->regs;
@@ -570,6 +688,14 @@ void gfar_halt(struct net_device *dev)
 			 (IEVENT_GRSC | IEVENT_GTSC)))
 			cpu_relax();
 	}
+}
+
+/* Halt the receive and transmit queues */
+void gfar_halt(struct net_device *dev)
+{
+	struct gfar_private *priv = netdev_priv(dev);
+	struct gfar __iomem *regs = priv->regs;
+	u32 tempval;
 
 	/* Disable Rx and Tx */
 	tempval = gfar_read(&regs->maccfg1);
@@ -1909,7 +2035,12 @@ static irqreturn_t gfar_error(int irq, void *dev_id)
 	u32 events = gfar_read(&priv->regs->ievent);
 
 	/* Clear IEVENT */
-	gfar_write(&priv->regs->ievent, IEVENT_ERR_MASK);
+	gfar_write(&priv->regs->ievent, events & IEVENT_ERR_MASK);
+
+	/* Magic Packet is not an error. */
+	if ((priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) &&
+	    (events & IEVENT_MAG))
+		events &= ~IEVENT_MAG;
 
 	/* Hmm... */
 	if (netif_msg_rx_err(priv) || netif_msg_tx_err(priv))
@@ -1979,6 +2110,8 @@ static irqreturn_t gfar_error(int irq, void *dev_id)
 static struct platform_driver gfar_driver = {
 	.probe = gfar_probe,
 	.remove = gfar_remove,
+	.suspend = gfar_suspend,
+	.resume = gfar_resume,
 	.driver	= {
 		.name = "fsl-gianfar",
 	},
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index 46cd773..922ed36 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -162,6 +162,7 @@ extern const char gfar_driver_version[];
 #define MACCFG2_GMII            0x00000200
 #define MACCFG2_HUGEFRAME	0x00000020
 #define MACCFG2_LENGTHCHECK	0x00000010
+#define MACCFG2_MPEN		0x00000008
 
 #define ECNTRL_INIT_SETTINGS	0x00001000
 #define ECNTRL_TBI_MODE         0x00000020
@@ -234,6 +235,7 @@ extern const char gfar_driver_version[];
 #define IEVENT_CRL		0x00020000
 #define IEVENT_XFUN		0x00010000
 #define IEVENT_RXB0		0x00008000
+#define IEVENT_MAG		0x00000800
 #define IEVENT_GRSC		0x00000100
 #define IEVENT_RXF0		0x00000080
 #define IEVENT_FIR		0x00000008
@@ -245,7 +247,8 @@ extern const char gfar_driver_version[];
 #define IEVENT_ERR_MASK         \
 (IEVENT_RXC | IEVENT_BSY | IEVENT_EBERR | IEVENT_MSRO | \
  IEVENT_BABT | IEVENT_TXC | IEVENT_TXE | IEVENT_LC \
- | IEVENT_CRL | IEVENT_XFUN | IEVENT_DPE | IEVENT_PERR)
+ | IEVENT_CRL | IEVENT_XFUN | IEVENT_DPE | IEVENT_PERR \
+ | IEVENT_MAG)
 
 #define IMASK_INIT_CLEAR	0x00000000
 #define IMASK_BABR              0x80000000
@@ -263,6 +266,7 @@ extern const char gfar_driver_version[];
 #define IMASK_CRL		0x00020000
 #define IMASK_XFUN		0x00010000
 #define IMASK_RXB0              0x00008000
+#define IMASK_MAG		0x00000800
 #define IMASK_GTSC              0x00000100
 #define IMASK_RXFEN0		0x00000080
 #define IMASK_FIR		0x00000008
@@ -726,10 +730,15 @@ struct gfar_private {
 	unsigned int fifo_starve;
 	unsigned int fifo_starve_off;
 
+	/* Bitfield update lock */
+	spinlock_t bflock;
+
 	unsigned char vlan_enable:1,
 		rx_csum_enable:1,
 		extended_hash:1,
-		bd_stash_en:1;
+		bd_stash_en:1,
+		wol_en:1, /* Wake-on-LAN enabled */
+		suspended:1;
 	unsigned short padding;
 
 	unsigned int interruptTransmit;
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c
index 6007147..fb7d3cc 100644
--- a/drivers/net/gianfar_ethtool.c
+++ b/drivers/net/gianfar_ethtool.c
@@ -479,14 +479,13 @@ static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rva
 static int gfar_set_rx_csum(struct net_device *dev, uint32_t data)
 {
 	struct gfar_private *priv = netdev_priv(dev);
+	unsigned long flags;
 	int err = 0;
 
 	if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM))
 		return -EOPNOTSUPP;
 
 	if (dev->flags & IFF_UP) {
-		unsigned long flags;
-
 		/* Halt TX and RX, and process the frames which
 		 * have already been received */
 		spin_lock_irqsave(&priv->txlock, flags);
@@ -502,7 +501,9 @@ static int gfar_set_rx_csum(struct net_device *dev, uint32_t data)
 		stop_gfar(dev);
 	}
 
+	spin_lock_irqsave(&priv->bflock, flags);
 	priv->rx_csum_enable = data;
+	spin_unlock_irqrestore(&priv->bflock, flags);
 
 	if (dev->flags & IFF_UP)
 		err = startup_gfar(dev);
@@ -564,6 +565,38 @@ static void gfar_set_msglevel(struct net_device *dev, uint32_t data)
 	priv->msg_enable = data;
 }
 
+#ifdef CONFIG_PM
+static void gfar_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct gfar_private *priv = netdev_priv(dev);
+
+	if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) {
+		wol->supported = WAKE_MAGIC;
+		wol->wolopts = priv->wol_en ? WAKE_MAGIC : 0;
+	} else {
+		wol->supported = wol->wolopts = 0;
+	}
+}
+
+static int gfar_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct gfar_private *priv = netdev_priv(dev);
+	unsigned long flags;
+
+	if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) &&
+	    wol->wolopts != 0)
+		return -EINVAL;
+
+	if (wol->wolopts & ~WAKE_MAGIC)
+		return -EINVAL;
+
+	spin_lock_irqsave(&priv->bflock, flags);
+	priv->wol_en = wol->wolopts & WAKE_MAGIC ? 1 : 0;
+	spin_unlock_irqrestore(&priv->bflock, flags);
+
+	return 0;
+}
+#endif
 
 const struct ethtool_ops gfar_ethtool_ops = {
 	.get_settings = gfar_gsettings,
@@ -585,4 +618,8 @@ const struct ethtool_ops gfar_ethtool_ops = {
 	.set_tx_csum = gfar_set_tx_csum,
 	.get_msglevel = gfar_get_msglevel,
 	.set_msglevel = gfar_set_msglevel,
+#ifdef CONFIG_PM
+	.get_wol = gfar_get_wol,
+	.set_wol = gfar_set_wol,
+#endif
 };
-- 
1.5.3.7

^ permalink raw reply related

* Re: [RFC] net: napi fix
From: Andrew Gallatin @ 2007-12-12 17:29 UTC (permalink / raw)
  To: David Miller
  Cc: joonwpark81, netdev, linux-kernel, jgarzik, Stephen Hemminger

[I apologize for loosing threading, I'm replying from the archives]

 > The problem is that the driver is doing a NAPI completion and
 > re-enabling chip interrupts with work_done == weight, and that is
 > illegal.

The only time at least myri10ge will do this is due to
the !netif_running(netdev) check.   Eg, from myri10ge's poll:

	work_done = myri10ge_clean_rx_done(mgp, budget);

	if (work_done < budget || !netif_running(netdev)) {
		netif_rx_complete(netdev, napi);
		put_be32(htonl(3), mgp->irq_claim);
	}

Is the netif_running() check even required? Is this just
a bad way to solve a race with running NAPI at down() time
that would be better solved by putting a napi_synchronize()
in the driver's down() routine?

I'd rather fix this right than add another check to a
questionable code path.

Thanks,

Drew

^ permalink raw reply

* Re: RFC: igb: Intel 82575 gigabit ethernet driver (take #2)
From: Kok, Auke @ 2007-12-12 17:18 UTC (permalink / raw)
  To: Kok, Auke
  Cc: NetDev, Jeff Garzik, Arjan van de Ven, Jesse Brandeburg,
	Ronciak, John, Mitch Williams
In-Reply-To: <475F107A.8080201@intel.com>

Kok, Auke wrote:
> All,
> 
> here is the second version of the igb (82575) ethernet controller driver. This
> driver was previously posted 2007-07-13. Many comments received were addressed:
> 
> - removed indirection wrappers in the same way as e1000e and ixgbe.
> - cleaned up largely against sparse, checkpatch
> - removed module parameters and moved functionality to ethtool ioctls
> - new NAPI API rewrites
> - by default the driver runs in multiqueue mode with 2 to 40 RX queues enabled.
> 
> Since the driver is still too large (allthough the patch shrunk from 558k to 416k,
> almost 34% of its size) to post to this list I am attaching the bzipped patch
> here. You can get the same driver alternatively from here:
> 
> http://foo-projects.org/~sofar/0001-igb-PCI-Express-82575-Gigabit-Ethernet-driver.patch
> [416k]
> http://foo-projects.org/~sofar/0001-igb-PCI-Express-82575-Gigabit-Ethernet-driver.patch.bz2
> [74k]
> 
> or through git:
>     git://lost.foo-projects.org/~ahkok/git/linux-2.6 #igb
> 
> 
> There are several concerns still open for this driver:
> - namespace collisions with e1000. Since there are cleanups planned for e1000
> since pci-e hardware is now moved to e1000e, this might resolve them.
> - hardware code is still a large API. we're expecting more hardware to be
> supported by this driver in the future and it's not certain which parts we need to
> keep or not.


unfortunately a last-minute effort of mine inserted a stray character. Please
re-download the patch files from http or through git to get the updated patch that
fixes this issue. The changes needed are below.

Cheers,

Auke


---
diff --git a/drivers/net/igb/e1000_phy.c b/drivers/net/igb/e1000_phy.c
index e57222a..1c13156 100644
--- a/drivers/net/igb/e1000_phy.c
+++ b/drivers/net/igb/e1000_phy.c
@@ -1555,7 +1555,7 @@ s32 e1000_get_phy_info_igp(struct e1000_hw *hw)
 		goto out;

 	ret_val = hw->phy.ops.read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS,
-			`		   &data);
+					   &data);
 	if (ret_val)
 		goto out;

^ permalink raw reply related

* Re: [PATCH 8/8] [PATCH v2] [CCID3]: Interface CCID3 code with newer Loss Intervals Database
From: Gerrit Renker @ 2007-12-12 17:21 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, dccp, netdev
In-Reply-To: <20071212170523.GT24046@ghostprotocols.net>

| > +static struct kmem_cache  *tfrc_lh_slab  __read_mostly;	/* <=== */
| 
| Yup, this one, is introduced as above but is not initialized at the
| module init routine, please see, it should be OK and we can move on:
| 
| http://git.kernel.org/?p=linux/kernel/git/acme/net-2.6.25.git;a=commitdiff;h=a925429ce2189b548dc19037d3ebd4ff35ae4af7
| 
Sorry for the confusion - you were right, the initialisation was sitting
in the wrong patch, not the one in the subject line. In your online
version the problem is fixed. Thanks a lot for all the work and for the
clarification.

Gerrit

^ permalink raw reply

* Re: [PATCH 8/8] [PATCH v2] [CCID3]: Interface CCID3 code with newer Loss Intervals Database
From: Arnaldo Carvalho de Melo @ 2007-12-12 17:05 UTC (permalink / raw)
  To: Gerrit Renker, Arnaldo Carvalho de Melo, dccp, netdev
In-Reply-To: <20071212165632.GB2282@gerrit.erg.abdn.ac.uk>

Em Wed, Dec 12, 2007 at 04:56:32PM +0000, Gerrit Renker escreveu:
> | This time around I'm not doing any reordering, just trying to use your
> | patches as is, but adding this patch as-is produces a kernel that will
> | crash, no?
> | 
> | > The loss history and the RX/TX packet history slabs are all created in
> | > tfrc.c using the three different __init routines of the dccp_tfrc_lib.
> | 
> | Yes, the init routines are called and in turn they create the slab
> | caches, but up to the patch "[PATCH 8/8] [PATCH v2] [CCID3]: Interface
> | CCID3 code with newer Loss Intervals Database" the new li slab is not
> | being created, no? See what I'm talking?
> | 
> Sorry, there is some weird kind of mix-up going on. Can you please check
> your patch set: it seems this email exchange refers to an older variant.
> In the most recent patch set, the slab is introduced in the patch
> 
> 	[TFRC]: Ringbuffer to track loss interval history
> 
> --- a/net/dccp/ccids/lib/loss_interval.c
> +++ b/net/dccp/ccids/lib/loss_interval.c
> @@ -27,6 +23,54 @@ struct dccp_li_hist_entry {
>         u32              dccplih_interval;
>  };
> 
> +static struct kmem_cache  *tfrc_lh_slab  __read_mostly;	/* <=== */

Yup, this one, is introduced as above but is not initialized at the
module init routine, please see, it should be OK and we can move on:

http://git.kernel.org/?p=linux/kernel/git/acme/net-2.6.25.git;a=commitdiff;h=a925429ce2189b548dc19037d3ebd4ff35ae4af7

> +/* Loss Interval weights from [RFC 3448, 5.4], scaled by 10 */
> +static const int tfrc_lh_weights[NINTERVAL] = { 10, 10, 10, 10, 8, 6, 4, 2 };
> // ...
> 
> And this is 6/8, i.e. before 8/8, cf.
> 	http://www.mail-archive.com/dccp@vger.kernel.org/msg03000.html
>      
> I don't know which tree you are working off, would it be possible to
> check against the test tree
> 	git://eden-feed.erg.abdn.ac.uk/dccp_exp		[dccp]

I'm doing a fresh clone now. But I think that everything is OK after
today's merge request I sent to David.

- Arnaldo

^ permalink raw reply

* Re: [RFC] ehea: kdump support using new shutdown hook
From: Dave Jones @ 2007-12-12 17:04 UTC (permalink / raw)
  To: Thomas Klein
  Cc: Paul Mackerras, Christoph Raisch, Jan-Bernd Themann, linux-kernel,
	linux-ppc, Marcus Eder, netdev, Stefan Roscher, Michael Ellermann,
	Michael Neuling
In-Reply-To: <200712121753.43543.osstklei@de.ibm.com>

On Wed, Dec 12, 2007 at 05:53:43PM +0100, Thomas Klein wrote:

 > +static void ehea_update_adapter_handles(struct ehea_adapter *adapter)
 > +{
 > +	int i, k;
 > +	int j = 0;
 > +
 > +	memset(adapter->res_handles, sizeof(adapter->res_handles), 0);

arguments wrong way around.
 
	Dave
 
-- 
http://www.codemonkey.org.uk

^ permalink raw reply

* Re: [PATCHES 0/7]: DCCP patches for 2.6.25
From: David Miller @ 2007-12-12 17:00 UTC (permalink / raw)
  To: acme; +Cc: netdev, dccp
In-Reply-To: <1197477413-1456-1-git-send-email-acme@redhat.com>

From: Arnaldo Carvalho de Melo <acme@redhat.com>
Date: Wed, 12 Dec 2007 14:36:46 -0200

> 	Please consider pulling from:
> 
> master.kernel.org:/pub/scm/linux/kernel/git/acme/net-2.6.25

Pulled and pushed out to net-2.6.25, thanks!

^ permalink raw reply


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