Netdev List
 help / color / mirror / Atom feed
* [PATCH 05/10] net: convert protocols to SKB frag APIs
From: Ian Campbell @ 2011-07-15 11:07 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-nfs-u79uwXL29TY76Z2rM5mHXA, Ian Campbell
In-Reply-To: <1310728006.20648.3.camel-o4Be2W7LfRlXesXXhkcM7miJhflN2719@public.gmane.org>

NB: should likely be split into per-protocol patches.

Signed-off-by: Ian Campbell <ian.campbell-Sxgqhf6Nn4DQT0dZR+AlfA@public.gmane.org>
---
 net/ipv4/inet_lro.c    |    2 +-
 net/ipv4/ip_output.c   |    8 +++++---
 net/ipv4/tcp.c         |    3 ++-
 net/ipv4/tcp_output.c  |    2 +-
 net/ipv6/ip6_output.c  |    8 +++++---
 net/xfrm/xfrm_ipcomp.c |   11 +++++++----
 6 files changed, 21 insertions(+), 13 deletions(-)

diff --git a/net/ipv4/inet_lro.c b/net/ipv4/inet_lro.c
index 85a0f75..63f3def 100644
--- a/net/ipv4/inet_lro.c
+++ b/net/ipv4/inet_lro.c
@@ -449,7 +449,7 @@ static struct sk_buff *__lro_proc_segment(struct net_lro_mgr *lro_mgr,
 	if (!lro_mgr->get_frag_header ||
 	    lro_mgr->get_frag_header(frags, (void *)&mac_hdr, (void *)&iph,
 				     (void *)&tcph, &flags, priv)) {
-		mac_hdr = page_address(frags->page) + frags->page_offset;
+		mac_hdr = skb_frag_address(frags);
 		goto out1;
 	}
 
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index a8024ea..29941ec 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -985,14 +985,14 @@ alloc_new_skb:
 			if (page && (left = PAGE_SIZE - off) > 0) {
 				if (copy >= left)
 					copy = left;
-				if (page != frag->page) {
+				if (page != skb_frag_page(frag)) {
 					if (i == MAX_SKB_FRAGS) {
 						err = -EMSGSIZE;
 						goto error;
 					}
-					get_page(page);
 					skb_fill_page_desc(skb, i, page, off, 0);
 					frag = &skb_shinfo(skb)->frags[i];
+					__skb_frag_ref(frag);
 				}
 			} else if (i < MAX_SKB_FRAGS) {
 				if (copy > PAGE_SIZE)
@@ -1005,13 +1005,15 @@ alloc_new_skb:
 				cork->page = page;
 				cork->off = 0;
 
+				/* XXX no ref ? */
 				skb_fill_page_desc(skb, i, page, 0, 0);
 				frag = &skb_shinfo(skb)->frags[i];
 			} else {
 				err = -EMSGSIZE;
 				goto error;
 			}
-			if (getfrag(from, page_address(frag->page)+frag->page_offset+frag->size, offset, copy, skb->len, skb) < 0) {
+			if (getfrag(from, skb_frag_address(frag)+frag->size,
+				    offset, copy, skb->len, skb) < 0) {
 				err = -EFAULT;
 				goto error;
 			}
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 054a59d..3a3703c 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -3035,7 +3035,8 @@ int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *hp,
 
 	for (i = 0; i < shi->nr_frags; ++i) {
 		const struct skb_frag_struct *f = &shi->frags[i];
-		sg_set_page(&sg, f->page, f->size, f->page_offset);
+		struct page *page = __skb_frag_page(f); /* XXX */
+		sg_set_page(&sg, page, f->size, f->page_offset);
 		if (crypto_hash_update(desc, &sg, f->size))
 			return 1;
 	}
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 882e0b0..0377c06 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -1095,7 +1095,7 @@ static void __pskb_trim_head(struct sk_buff *skb, int len)
 	k = 0;
 	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
 		if (skb_shinfo(skb)->frags[i].size <= eat) {
-			put_page(skb_shinfo(skb)->frags[i].page);
+			skb_frag_unref(skb, i);
 			eat -= skb_shinfo(skb)->frags[i].size;
 		} else {
 			skb_shinfo(skb)->frags[k] = skb_shinfo(skb)->frags[i];
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 9d4b165..fdd4f61 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1441,14 +1441,14 @@ alloc_new_skb:
 			if (page && (left = PAGE_SIZE - off) > 0) {
 				if (copy >= left)
 					copy = left;
-				if (page != frag->page) {
+				if (page != skb_frag_page(frag)) {
 					if (i == MAX_SKB_FRAGS) {
 						err = -EMSGSIZE;
 						goto error;
 					}
-					get_page(page);
 					skb_fill_page_desc(skb, i, page, sk->sk_sndmsg_off, 0);
 					frag = &skb_shinfo(skb)->frags[i];
+					__skb_frag_ref(frag);
 				}
 			} else if(i < MAX_SKB_FRAGS) {
 				if (copy > PAGE_SIZE)
@@ -1461,13 +1461,15 @@ alloc_new_skb:
 				sk->sk_sndmsg_page = page;
 				sk->sk_sndmsg_off = 0;
 
+				/* XXX no ref ? */
 				skb_fill_page_desc(skb, i, page, 0, 0);
 				frag = &skb_shinfo(skb)->frags[i];
 			} else {
 				err = -EMSGSIZE;
 				goto error;
 			}
-			if (getfrag(from, page_address(frag->page)+frag->page_offset+frag->size, offset, copy, skb->len, skb) < 0) {
+			if (getfrag(from, skb_frag_address(frag)+frag->size,
+				    offset, copy, skb->len, skb) < 0) {
 				err = -EFAULT;
 				goto error;
 			}
diff --git a/net/xfrm/xfrm_ipcomp.c b/net/xfrm/xfrm_ipcomp.c
index fc91ad7..f781b9a 100644
--- a/net/xfrm/xfrm_ipcomp.c
+++ b/net/xfrm/xfrm_ipcomp.c
@@ -70,26 +70,29 @@ static int ipcomp_decompress(struct xfrm_state *x, struct sk_buff *skb)
 
 	while ((scratch += len, dlen -= len) > 0) {
 		skb_frag_t *frag;
+		struct page *page;
 
 		err = -EMSGSIZE;
 		if (WARN_ON(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS))
 			goto out;
 
 		frag = skb_shinfo(skb)->frags + skb_shinfo(skb)->nr_frags;
-		frag->page = alloc_page(GFP_ATOMIC);
+		page = alloc_page(GFP_ATOMIC);
 
 		err = -ENOMEM;
-		if (!frag->page)
+		if (!page)
 			goto out;
 
+		__skb_frag_set_page(frag, page);
+
 		len = PAGE_SIZE;
 		if (dlen < len)
 			len = dlen;
 
-		memcpy(page_address(frag->page), scratch, len);
-
 		frag->page_offset = 0;
 		frag->size = len;
+		memcpy(skb_frag_address(frag), scratch, len);
+
 		skb->truesize += len;
 		skb->data_len += len;
 		skb->len += len;
-- 
1.7.2.5

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

^ permalink raw reply related

* [PATCH 04/10] net: convert core to skb paged frag APIs
From: Ian Campbell @ 2011-07-15 11:07 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-nfs-u79uwXL29TY76Z2rM5mHXA, Ian Campbell
In-Reply-To: <1310728006.20648.3.camel-o4Be2W7LfRlXesXXhkcM7miJhflN2719@public.gmane.org>

Signed-off-by: Ian Campbell <ian.campbell-Sxgqhf6Nn4DQT0dZR+AlfA@public.gmane.org>
---
 include/linux/skbuff.h |    4 ++--
 net/core/datagram.c    |   20 ++++++++------------
 net/core/dev.c         |    7 +++----
 net/core/kmap_skb.h    |    2 +-
 net/core/pktgen.c      |    3 +--
 net/core/skbuff.c      |   31 +++++++++++++++++--------------
 net/core/sock.c        |   12 +++++-------
 net/core/user_dma.c    |    2 +-
 8 files changed, 38 insertions(+), 43 deletions(-)

diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index c061257..982c6a3 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1927,12 +1927,12 @@ static inline int skb_add_data(struct sk_buff *skb,
 }
 
 static inline int skb_can_coalesce(struct sk_buff *skb, int i,
-				   struct page *page, int off)
+				   const struct page *page, int off)
 {
 	if (i) {
 		struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i - 1];
 
-		return page == frag->page &&
+		return page == skb_frag_page(frag) &&
 		       off == frag->page_offset + frag->size;
 	}
 	return 0;
diff --git a/net/core/datagram.c b/net/core/datagram.c
index 18ac112..f0dcaa2 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -332,14 +332,13 @@ int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset,
 			int err;
 			u8  *vaddr;
 			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-			struct page *page = frag->page;
 
 			if (copy > len)
 				copy = len;
-			vaddr = kmap(page);
+			vaddr = skb_frag_kmap(frag);
 			err = memcpy_toiovec(to, vaddr + frag->page_offset +
 					     offset - start, copy);
-			kunmap(page);
+			skb_frag_kunmap(frag);
 			if (err)
 				goto fault;
 			if (!(len -= copy))
@@ -418,14 +417,13 @@ int skb_copy_datagram_const_iovec(const struct sk_buff *skb, int offset,
 			int err;
 			u8  *vaddr;
 			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-			struct page *page = frag->page;
 
 			if (copy > len)
 				copy = len;
-			vaddr = kmap(page);
+			vaddr = skb_frag_kmap(frag);
 			err = memcpy_toiovecend(to, vaddr + frag->page_offset +
 						offset - start, to_offset, copy);
-			kunmap(page);
+			skb_frag_kunmap(frag);
 			if (err)
 				goto fault;
 			if (!(len -= copy))
@@ -508,15 +506,14 @@ int skb_copy_datagram_from_iovec(struct sk_buff *skb, int offset,
 			int err;
 			u8  *vaddr;
 			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-			struct page *page = frag->page;
 
 			if (copy > len)
 				copy = len;
-			vaddr = kmap(page);
+			vaddr = skb_frag_kmap(frag);
 			err = memcpy_fromiovecend(vaddr + frag->page_offset +
 						  offset - start,
 						  from, from_offset, copy);
-			kunmap(page);
+			skb_frag_kunmap(frag);
 			if (err)
 				goto fault;
 
@@ -594,16 +591,15 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
 			int err = 0;
 			u8  *vaddr;
 			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-			struct page *page = frag->page;
 
 			if (copy > len)
 				copy = len;
-			vaddr = kmap(page);
+			vaddr = skb_frag_kmap(frag);
 			csum2 = csum_and_copy_to_user(vaddr +
 							frag->page_offset +
 							offset - start,
 						      to, copy, 0, &err);
-			kunmap(page);
+			skb_frag_kunmap(frag);
 			if (err)
 				goto fault;
 			*csump = csum_block_add(*csump, csum2, pos);
diff --git a/net/core/dev.c b/net/core/dev.c
index 9c58c1e..9ab39c0 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3414,7 +3414,7 @@ pull:
 		skb_shinfo(skb)->frags[0].size -= grow;
 
 		if (unlikely(!skb_shinfo(skb)->frags[0].size)) {
-			put_page(skb_shinfo(skb)->frags[0].page);
+			skb_frag_unref(skb, 0);
 			memmove(skb_shinfo(skb)->frags,
 				skb_shinfo(skb)->frags + 1,
 				--skb_shinfo(skb)->nr_frags * sizeof(skb_frag_t));
@@ -3478,10 +3478,9 @@ void skb_gro_reset_offset(struct sk_buff *skb)
 	NAPI_GRO_CB(skb)->frag0_len = 0;
 
 	if (skb->mac_header == skb->tail &&
-	    !PageHighMem(skb_shinfo(skb)->frags[0].page)) {
+	    !PageHighMem(skb_frag_page(&skb_shinfo(skb)->frags[0]))) {
 		NAPI_GRO_CB(skb)->frag0 =
-			page_address(skb_shinfo(skb)->frags[0].page) +
-			skb_shinfo(skb)->frags[0].page_offset;
+			skb_frag_address(&skb_shinfo(skb)->frags[0]);
 		NAPI_GRO_CB(skb)->frag0_len = skb_shinfo(skb)->frags[0].size;
 	}
 }
diff --git a/net/core/kmap_skb.h b/net/core/kmap_skb.h
index 283c2b9..b1e9711 100644
--- a/net/core/kmap_skb.h
+++ b/net/core/kmap_skb.h
@@ -7,7 +7,7 @@ static inline void *kmap_skb_frag(const skb_frag_t *frag)
 
 	local_bh_disable();
 #endif
-	return kmap_atomic(frag->page, KM_SKB_DATA_SOFTIRQ);
+	return kmap_atomic(__skb_frag_page(frag), KM_SKB_DATA_SOFTIRQ);
 }
 
 static inline void kunmap_skb_frag(void *vaddr)
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index f76079c..989b2b6 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -2600,8 +2600,7 @@ static void pktgen_finalize_skb(struct pktgen_dev *pkt_dev, struct sk_buff *skb,
 				if (!pkt_dev->page)
 					break;
 			}
-			skb_shinfo(skb)->frags[i].page = pkt_dev->page;
-			get_page(pkt_dev->page);
+			skb_frag_set_page(skb, i, pkt_dev->page);
 			skb_shinfo(skb)->frags[i].page_offset = 0;
 			/*last fragment, fill rest of data*/
 			if (i == (frags - 1))
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 46cbd28..2133600 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -326,7 +326,7 @@ static void skb_release_data(struct sk_buff *skb)
 		if (skb_shinfo(skb)->nr_frags) {
 			int i;
 			for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
-				put_page(skb_shinfo(skb)->frags[i].page);
+				skb_frag_unref(skb, i);
 		}
 
 		if (skb_has_frag_list(skb))
@@ -733,7 +733,7 @@ struct sk_buff *pskb_copy(struct sk_buff *skb, gfp_t gfp_mask)
 
 		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
 			skb_shinfo(n)->frags[i] = skb_shinfo(skb)->frags[i];
-			get_page(skb_shinfo(n)->frags[i].page);
+			skb_frag_ref(skb, i);
 		}
 		skb_shinfo(n)->nr_frags = i;
 	}
@@ -820,7 +820,7 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
 		kfree(skb->head);
 	} else {
 		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
-			get_page(skb_shinfo(skb)->frags[i].page);
+			skb_frag_ref(skb, i);
 
 		if (skb_has_frag_list(skb))
 			skb_clone_fraglist(skb);
@@ -1098,7 +1098,7 @@ drop_pages:
 		skb_shinfo(skb)->nr_frags = i;
 
 		for (; i < nfrags; i++)
-			put_page(skb_shinfo(skb)->frags[i].page);
+			skb_frag_unref(skb, i);
 
 		if (skb_has_frag_list(skb))
 			skb_drop_fraglist(skb);
@@ -1267,7 +1267,7 @@ pull_pages:
 	k = 0;
 	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
 		if (skb_shinfo(skb)->frags[i].size <= eat) {
-			put_page(skb_shinfo(skb)->frags[i].page);
+			skb_frag_unref(skb, i);
 			eat -= skb_shinfo(skb)->frags[i].size;
 		} else {
 			skb_shinfo(skb)->frags[k] = skb_shinfo(skb)->frags[i];
@@ -1512,7 +1512,9 @@ static int __skb_splice_bits(struct sk_buff *skb, struct pipe_inode_info *pipe,
 	for (seg = 0; seg < skb_shinfo(skb)->nr_frags; seg++) {
 		const skb_frag_t *f = &skb_shinfo(skb)->frags[seg];
 
-		if (__splice_segment(f->page, f->page_offset, f->size,
+		/* XXX */
+		if (__splice_segment(__skb_frag_page(f),
+				     f->page_offset, f->size,
 				     offset, len, skb, spd, 0, sk, pipe))
 			return 1;
 	}
@@ -2057,7 +2059,7 @@ static inline void skb_split_no_header(struct sk_buff *skb,
 				 *    where splitting is expensive.
 				 * 2. Split is accurately. We make this.
 				 */
-				get_page(skb_shinfo(skb)->frags[i].page);
+				skb_frag_ref(skb, i);
 				skb_shinfo(skb1)->frags[0].page_offset += len - pos;
 				skb_shinfo(skb1)->frags[0].size -= len - pos;
 				skb_shinfo(skb)->frags[i].size	= len - pos;
@@ -2132,7 +2134,8 @@ int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen)
 	 * commit all, so that we don't have to undo partial changes
 	 */
 	if (!to ||
-	    !skb_can_coalesce(tgt, to, fragfrom->page, fragfrom->page_offset)) {
+	    !skb_can_coalesce(tgt, to, skb_frag_page(fragfrom),
+			      fragfrom->page_offset)) {
 		merge = -1;
 	} else {
 		merge = to - 1;
@@ -2179,7 +2182,7 @@ int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen)
 			to++;
 
 		} else {
-			get_page(fragfrom->page);
+			__skb_frag_ref(fragfrom);
 			fragto->page = fragfrom->page;
 			fragto->page_offset = fragfrom->page_offset;
 			fragto->size = todo;
@@ -2201,7 +2204,7 @@ int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen)
 		fragto = &skb_shinfo(tgt)->frags[merge];
 
 		fragto->size += fragfrom->size;
-		put_page(fragfrom->page);
+		__skb_frag_unref(fragfrom);
 	}
 
 	/* Reposition in the original skb */
@@ -2446,8 +2449,7 @@ int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb,
 		left = PAGE_SIZE - frag->page_offset;
 		copy = (length > left)? left : length;
 
-		ret = getfrag(from, (page_address(frag->page) +
-			    frag->page_offset + frag->size),
+		ret = getfrag(from, skb_frag_address(frag) + frag->size,
 			    offset, copy, 0, skb);
 		if (ret < 0)
 			return -EFAULT;
@@ -2599,7 +2601,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, u32 features)
 
 		while (pos < offset + len && i < nfrags) {
 			*frag = skb_shinfo(skb)->frags[i];
-			get_page(frag->page);
+			__skb_frag_ref(frag);
 			size = frag->size;
 
 			if (pos < offset) {
@@ -2822,7 +2824,8 @@ __skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
 
 			if (copy > len)
 				copy = len;
-			sg_set_page(&sg[elt], frag->page, copy,
+			/* XXX */
+			sg_set_page(&sg[elt], __skb_frag_page(frag), copy,
 					frag->page_offset+offset-start);
 			elt++;
 			if (!(len -= copy))
diff --git a/net/core/sock.c b/net/core/sock.c
index 6e81978..0fb2160 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1530,7 +1530,6 @@ struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len,
 				skb_shinfo(skb)->nr_frags = npages;
 				for (i = 0; i < npages; i++) {
 					struct page *page;
-					skb_frag_t *frag;
 
 					page = alloc_pages(sk->sk_allocation, 0);
 					if (!page) {
@@ -1540,12 +1539,11 @@ struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len,
 						goto failure;
 					}
 
-					frag = &skb_shinfo(skb)->frags[i];
-					frag->page = page;
-					frag->page_offset = 0;
-					frag->size = (data_len >= PAGE_SIZE ?
-						      PAGE_SIZE :
-						      data_len);
+					__skb_fill_page_desc(skb, i,
+							page, 0,
+							(data_len >= PAGE_SIZE ?
+							 PAGE_SIZE :
+							 data_len));
 					data_len -= PAGE_SIZE;
 				}
 
diff --git a/net/core/user_dma.c b/net/core/user_dma.c
index 25d717e..d22ec3e 100644
--- a/net/core/user_dma.c
+++ b/net/core/user_dma.c
@@ -78,7 +78,7 @@ int dma_skb_copy_datagram_iovec(struct dma_chan *chan,
 		copy = end - offset;
 		if (copy > 0) {
 			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-			struct page *page = frag->page;
+			struct page *page = __skb_frag_page(frag); /* XXX */
 
 			if (copy > len)
 				copy = len;
-- 
1.7.2.5

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

^ permalink raw reply related

* [PATCH 02/10] mm: use const struct page for r/o page-flag accessor methods
From: Ian Campbell @ 2011-07-15 11:07 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-nfs-u79uwXL29TY76Z2rM5mHXA, Ian Campbell
In-Reply-To: <1310728006.20648.3.camel-o4Be2W7LfRlXesXXhkcM7miJhflN2719@public.gmane.org>

Signed-off-by: Ian Campbell <ian.campbell-Sxgqhf6Nn4DQT0dZR+AlfA@public.gmane.org>
---
 include/linux/page-flags.h |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 6081493..7d632cc 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -135,7 +135,7 @@ enum pageflags {
  * Macros to create function definitions for page flags
  */
 #define TESTPAGEFLAG(uname, lname)					\
-static inline int Page##uname(struct page *page) 			\
+static inline int Page##uname(const struct page *page) 			\
 			{ return test_bit(PG_##lname, &page->flags); }
 
 #define SETPAGEFLAG(uname, lname)					\
@@ -173,7 +173,7 @@ static inline int __TestClearPage##uname(struct page *page)		\
 	__SETPAGEFLAG(uname, lname)  __CLEARPAGEFLAG(uname, lname)
 
 #define PAGEFLAG_FALSE(uname) 						\
-static inline int Page##uname(struct page *page) 			\
+static inline int Page##uname(const struct page *page) 			\
 			{ return 0; }
 
 #define TESTSCFLAG(uname, lname)					\
-- 
1.7.2.5

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

^ permalink raw reply related

* [PATCH/RFC 0/10] enable SKB paged fragment lifetime visibility
From: Ian Campbell @ 2011-07-15 11:06 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA; +Cc: linux-nfs-u79uwXL29TY76Z2rM5mHXA

Hi,

The following is my attempt to allow entities which inject pages into
the networking stack to receive a notification when the stack has really
finished with those pages (i.e. including retransmissions, clones,
pull-ups etc) and not just when the original skb is finished with. It
implements something broadly along the lines of what was described in
[0].

The series is a proof-of-concept but I have used it to implement a fix
for the NFS issue which I described in [1] (for O_DIRECT writes only, I
presume non O_DIRECT writes would benefit from the same treatment), by
delaying completion of the write() until the pages are no longer
referenced by the network stack (which can happen due to retransmissions
or cloning). I expect that other block and filesystem users of the
network subsystem (e.g. iSCSI) would also benefit from this
functionality since they will suffer from the same class of issue.

Although I've not rebased onto it yet (this series is on 3.0-rc5) I also
expect it would be possible to remove the need to copy on clone which
was recently added to support the SKBTX_DEV_ZEROCOPY stuff by Shirley
Ma. I also expect that this functionality will be useful in my attempts
to add foreign page mapping to Xen's netback (per [2]).

Lastly I think the AF_PACKET mmap'd TX ring completion could also
benefit, although I wasn't able to cause an actual failure in that case,
it seems like cloning of skb's would cause pages which are still
referenced by the stack to be released back to userspace.

In order to do this I have introduced an API to manipulate an SKBs paged
fragments (which unfortunately necessitated changing each driver),
including an explicit fragment ref and unref API to replace the direct
use of get/put_page. Using those I was then able to add an optional
extra layer of reference counting to the paged fragments which can be
used by the creator of the fragment to receive a callback at the time
the page would normally be freed.

What is the general feeling regarding this approach?

The series has been built allmodconfig on x86_64 so I have likely missed
some arch-specific drivers etc. I'll take care of that in future
postings, as well as addressing the issues mentioned in some of the
commit messages.

Ian.

[0] http://marc.info/?l=linux-netdev&m=130925719513084&w=2
[1] http://marc.info/?l=linux-nfs&m=122424132729720&w=2
[2] http://marc.info/?l=linux-netdev&m=130893020922848&w=2



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

^ permalink raw reply

* [PATCH] 8139cp: convert to new VLAN model.
From: Francois Romieu @ 2011-07-15 10:21 UTC (permalink / raw)
  To: Jiri Pirko; +Cc: Stephen Hemminger, netdev

The registers and descriptors bits are identical to the pre-8168
8169 chipsets : {RxDesc / TxDesc}.opts2 can only contain VLAN information.

Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
---
 drivers/net/8139cp.c |   83 ++++++++++++++++---------------------------------
 1 files changed, 27 insertions(+), 56 deletions(-)

diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index 73b10b0..cc4c210 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -78,17 +78,6 @@
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 
-/* VLAN tagging feature enable/disable */
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-#define CP_VLAN_TAG_USED 1
-#define CP_VLAN_TX_TAG(tx_desc,vlan_tag_value) \
-	do { (tx_desc)->opts2 = cpu_to_le32(vlan_tag_value); } while (0)
-#else
-#define CP_VLAN_TAG_USED 0
-#define CP_VLAN_TX_TAG(tx_desc,vlan_tag_value) \
-	do { (tx_desc)->opts2 = 0; } while (0)
-#endif
-
 /* These identify the driver base version and may not be removed. */
 static char version[] =
 DRV_NAME ": 10/100 PCI Ethernet driver v" DRV_VERSION " (" DRV_RELDATE ")\n";
@@ -356,9 +345,6 @@ struct cp_private {
 	unsigned		rx_buf_sz;
 	unsigned		wol_enabled : 1; /* Is Wake-on-LAN enabled? */
 
-#if CP_VLAN_TAG_USED
-	struct vlan_group	*vlgrp;
-#endif
 	dma_addr_t		ring_dma;
 
 	struct mii_if_info	mii_if;
@@ -423,24 +409,6 @@ static struct {
 };
 
 
-#if CP_VLAN_TAG_USED
-static void cp_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
-{
-	struct cp_private *cp = netdev_priv(dev);
-	unsigned long flags;
-
-	spin_lock_irqsave(&cp->lock, flags);
-	cp->vlgrp = grp;
-	if (grp)
-		cp->cpcmd |= RxVlanOn;
-	else
-		cp->cpcmd &= ~RxVlanOn;
-
-	cpw16(CpCmd, cp->cpcmd);
-	spin_unlock_irqrestore(&cp->lock, flags);
-}
-#endif /* CP_VLAN_TAG_USED */
-
 static inline void cp_set_rxbufsize (struct cp_private *cp)
 {
 	unsigned int mtu = cp->dev->mtu;
@@ -455,18 +423,17 @@ static inline void cp_set_rxbufsize (struct cp_private *cp)
 static inline void cp_rx_skb (struct cp_private *cp, struct sk_buff *skb,
 			      struct cp_desc *desc)
 {
+	u32 opts2 = le32_to_cpu(desc->opts2);
+
 	skb->protocol = eth_type_trans (skb, cp->dev);
 
 	cp->dev->stats.rx_packets++;
 	cp->dev->stats.rx_bytes += skb->len;
 
-#if CP_VLAN_TAG_USED
-	if (cp->vlgrp && (desc->opts2 & cpu_to_le32(RxVlanTagged))) {
-		vlan_hwaccel_receive_skb(skb, cp->vlgrp,
-					 swab16(le32_to_cpu(desc->opts2) & 0xffff));
-	} else
-#endif
-		netif_receive_skb(skb);
+	if (opts2 & RxVlanTagged)
+		__vlan_hwaccel_put_tag(skb, swab16(opts2 & 0xffff));
+
+	napi_gro_receive(&cp->napi, skb);
 }
 
 static void cp_rx_err_acct (struct cp_private *cp, unsigned rx_tail,
@@ -730,6 +697,12 @@ static void cp_tx (struct cp_private *cp)
 		netif_wake_queue(cp->dev);
 }
 
+static inline u32 cp_tx_vlan_tag(struct sk_buff *skb)
+{
+	return vlan_tx_tag_present(skb) ?
+		TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00;
+}
+
 static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
 					struct net_device *dev)
 {
@@ -737,9 +710,7 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
 	unsigned entry;
 	u32 eor, flags;
 	unsigned long intr_flags;
-#if CP_VLAN_TAG_USED
-	u32 vlan_tag = 0;
-#endif
+	__le32 opts2;
 	int mss = 0;
 
 	spin_lock_irqsave(&cp->lock, intr_flags);
@@ -752,15 +723,12 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
 		return NETDEV_TX_BUSY;
 	}
 
-#if CP_VLAN_TAG_USED
-	if (vlan_tx_tag_present(skb))
-		vlan_tag = TxVlanTag | swab16(vlan_tx_tag_get(skb));
-#endif
-
 	entry = cp->tx_head;
 	eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
 	mss = skb_shinfo(skb)->gso_size;
 
+	opts2 = cpu_to_le32(cp_tx_vlan_tag(skb));
+
 	if (skb_shinfo(skb)->nr_frags == 0) {
 		struct cp_desc *txd = &cp->tx_ring[entry];
 		u32 len;
@@ -768,7 +736,7 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
 
 		len = skb->len;
 		mapping = dma_map_single(&cp->pdev->dev, skb->data, len, PCI_DMA_TODEVICE);
-		CP_VLAN_TX_TAG(txd, vlan_tag);
+		txd->opts2 = opts2;
 		txd->addr = cpu_to_le64(mapping);
 		wmb();
 
@@ -839,7 +807,7 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
 				ctrl |= LastFrag;
 
 			txd = &cp->tx_ring[entry];
-			CP_VLAN_TX_TAG(txd, vlan_tag);
+			txd->opts2 = opts2;
 			txd->addr = cpu_to_le64(mapping);
 			wmb();
 
@@ -851,7 +819,7 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
 		}
 
 		txd = &cp->tx_ring[first_entry];
-		CP_VLAN_TX_TAG(txd, vlan_tag);
+		txd->opts2 = opts2;
 		txd->addr = cpu_to_le64(first_mapping);
 		wmb();
 
@@ -1431,6 +1399,11 @@ static int cp_set_features(struct net_device *dev, u32 features)
 	else
 		cp->cpcmd &= ~RxChkSum;
 
+	if (features & NETIF_F_HW_VLAN_RX)
+		cp->cpcmd |= RxVlanOn;
+	else
+		cp->cpcmd &= ~RxVlanOn;
+
 	cpw16_f(CpCmd, cp->cpcmd);
 	spin_unlock_irqrestore(&cp->lock, flags);
 
@@ -1818,9 +1791,6 @@ static const struct net_device_ops cp_netdev_ops = {
 	.ndo_start_xmit		= cp_start_xmit,
 	.ndo_tx_timeout		= cp_tx_timeout,
 	.ndo_set_features	= cp_set_features,
-#if CP_VLAN_TAG_USED
-	.ndo_vlan_rx_register	= cp_vlan_rx_register,
-#endif
 #ifdef BROKEN
 	.ndo_change_mtu		= cp_change_mtu,
 #endif
@@ -1949,15 +1919,16 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 	dev->ethtool_ops = &cp_ethtool_ops;
 	dev->watchdog_timeo = TX_TIMEOUT;
 
-#if CP_VLAN_TAG_USED
 	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-#endif
 
 	if (pci_using_dac)
 		dev->features |= NETIF_F_HIGHDMA;
 
 	/* disabled by default until verified */
-	dev->hw_features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO;
+	dev->hw_features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
+		NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+	dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
+		NETIF_F_HIGHDMA;
 
 	dev->irq = pdev->irq;
 
-- 
1.7.4.4


^ permalink raw reply related

* Re: [RFC 46/72] ixp2000: Move the Radisys driver
From: Lennert Buytenhek @ 2011-07-15 10:32 UTC (permalink / raw)
  To: Jeff Kirsher; +Cc: davem@davemloft.net, netdev@vger.kernel.org
In-Reply-To: <1310692758.2628.30.camel@jtkirshe-mobl>

On Thu, Jul 14, 2011 at 06:19:17PM -0700, Jeff Kirsher wrote:

> > > > > Move the Radisys driver into drivers/net/ethernet/radisys/ and
> > > > > make the necessary Kconfig and Makefile changes
> > > > > 
> > > > > CC: Lennert Buytenhek <kernel@wantstofly.org>
> > > > > Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
> > > > > ---
> > > > >  MAINTAINERS                                        |    2 +-
> > > > >  drivers/net/Kconfig                                |    2 --
> > > > >  drivers/net/Makefile                               |    1 -
> > > > >  drivers/net/ethernet/Kconfig                       |    1 +
> > > > >  drivers/net/ethernet/Makefile                      |    1 +
> > > > >  drivers/net/ethernet/radisys/Kconfig               |   16 ++++++++++++++++
> > > > >  drivers/net/ethernet/radisys/Makefile              |    5 +++++
> > > > >  drivers/net/{ => ethernet/radisys}/ixp2000/Kconfig |    2 +-
> > > > >  .../net/{ => ethernet/radisys}/ixp2000/Makefile    |    0
> > > > 
> > > > The ixp2000 is a series of Intel ARM SoCs, and the ENP2611 is a Radisys
> > > > PCI board based on the ixp2000 series (ixp2400), so it doesn't make
> > > > sense to put everything in the radisys/ directory.
> > > 
> > > It was suggested earlier that it probably should be in either ixp/ or
> > > radisys/, and someone suggested that ixp/ might be confusing.  If you
> > > would like to keep it under drivers/net/ethernet/ixp2000, I am fine with
> > > that as well.
> > > 
> > > > If you insist on moving all drivers into vendor directories (I don't
> > > > like that idea at all -- are we going to rename directories and shuffle
> > > > stuff around every time vendor A buys vendor B or takes over one of
> > > > vendor B's products?), at least the core ixp2000 code should be under
> > > > intel/.
> > > 
> > > It was not my preference to place drivers into vendor specific
> > > directories because of that very reason, as I did the work, it just
> > > tended to work out that way.
> > > 
> > > The reason (as stated before) that it was not moved into intel/
> > > directory is because the driver was not written (and supported) by
> > > Intel.
> > 
> > I didn't follow the discussion, but that seems like a silly argument.
> > Does that mean that any non-vendor supported driver can't go into
> > drivers/net/$vendor/?  What if the vendor starts contributing to the
> > driver later on, will the driver be moved then?
> > 
> > It seems that what you're saying is that you don't want the ixp2000
> > driver in "your" subdirectory.
> 
> It is more that all the drivers that in intel/ are all very similar and
> have "common" code which potentially code be shared.  We have been
> looking at what possibilities there are for the common code between the
> Intel supported drivers.  So it really did not make sense to throw a
> driver into the intel/ directory just because it used an Intel chip, but
> has nothing in common with the other drivers in that directory.  Sorry
> if my previous explanation sounded like it I just did not want the
> drivers in the intel/ because we did not write or support it.
> 
> After looking at ixp2000/ixp4xx drivers and the 82586/82596 drivers a
> bit more, I came up with the solution of putting the IXP drivers in
> xscale/ and the 82586/82596 drivers in i825xx/ directory.

That sounds fine with me.

^ permalink raw reply

* [PATCH] Fix panic in virtnet_remove
From: Krishna Kumar @ 2011-07-15  9:16 UTC (permalink / raw)
  To: davem; +Cc: netdev, shemminger, Krishna Kumar

modprobe -r virtio_net panics in free_netdev() as the
dev is already freed in the newly introduced virtnet_free
(commit 3fa2a1df9094). Since virtnet_remove doesn't require
dev after unregister, I am removing the free_netdev call
in virtnet_remove instead of in virtnet_free (which seems
to be the right place to free the dev). Confirmed that
the panic is fixed with this patch.

Signed-off-by: Krishna Kumar <krkumar2@in.ibm.com>
---
 drivers/net/virtio_net.c |    2 --
 1 file changed, 2 deletions(-)

diff -ruNp org/drivers/net/virtio_net.c new/drivers/net/virtio_net.c
--- org/drivers/net/virtio_net.c	2011-07-04 10:38:33.000000000 +0530
+++ new/drivers/net/virtio_net.c	2011-07-15 14:27:48.000000000 +0530
@@ -1121,8 +1121,6 @@ static void __devexit virtnet_remove(str
 
 	while (vi->pages)
 		__free_pages(get_a_page(vi, GFP_KERNEL), 0);
-
-	free_netdev(vi->dev);
 }
 
 static struct virtio_device_id id_table[] = {

^ permalink raw reply

* [PATCH] [RFC] Batch statistics update in free_old_xmit_skbs
From: Krishna Kumar @ 2011-07-15  9:16 UTC (permalink / raw)
  To: davem; +Cc: netdev, shemminger, Krishna Kumar

Improve performance for update of stats counters for 32-bit
guests. The following table shows the average number of skbs
that were processed in free_old_xmit_skbs under various
cases:

-----------------------------------------------------------
#Procs      #packets (512 I/O)      #packets (16K I/O)
-----------------------------------------------------------
1           2.81                    1.23
4           4.52                    18.63
16          4.23                    17.58
32          9.81                    18.07
64          15.86                   17.69
96          21.30                   16.72
-----------------------------------------------------------

Batching u64_stats_update_begin/ends seems to be useful
for 32-bit guests, as free_old_xmit_skbs is called at
every xmit.

Signed-off-by: Krishna Kumar <krkumar2@in.ibm.com>
---
 drivers/net/virtio_net.c |   18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff -ruNp org/drivers/net/virtio_net.c new/drivers/net/virtio_net.c
--- org/drivers/net/virtio_net.c	2011-07-04 10:38:33.000000000 +0530
+++ new/drivers/net/virtio_net.c	2011-07-15 12:27:41.000000000 +0530
@@ -531,19 +531,27 @@ static unsigned int free_old_xmit_skbs(s
 {
 	struct sk_buff *skb;
 	unsigned int len, tot_sgs = 0;
-	struct virtnet_stats __percpu *stats = this_cpu_ptr(vi->stats);
+	u64 tx_bytes = 0, tx_packets = 0;
 
 	while ((skb = virtqueue_get_buf(vi->svq, &len)) != NULL) {
 		pr_debug("Sent skb %p\n", skb);
 
-		u64_stats_update_begin(&stats->syncp);
-		stats->tx_bytes += skb->len;
-		stats->tx_packets++;
-		u64_stats_update_end(&stats->syncp);
+		tx_bytes += skb->len;
+		tx_packets++;
 
 		tot_sgs += skb_vnet_hdr(skb)->num_sg;
 		dev_kfree_skb_any(skb);
 	}
+
+	if (tx_packets) {
+		struct virtnet_stats __percpu *stats = this_cpu_ptr(vi->stats);
+
+		u64_stats_update_begin(&stats->syncp);
+		stats->tx_bytes += tx_bytes;
+		stats->tx_packets += tx_packets;
+		u64_stats_update_end(&stats->syncp);
+	}
+
 	return tot_sgs;
 }
 

^ permalink raw reply

* [PATCH] Remove redundant variable/code in __qdisc_run
From: Krishna Kumar @ 2011-07-15  9:16 UTC (permalink / raw)
  To: davem; +Cc: netdev, Krishna Kumar

Remove redundant variable "work".

Signed-off-by: Krishna Kumar <krkumar2@in.ibm.com>
---
 net/sched/sch_generic.c |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff -ruNp org/net/sched/sch_generic.c new/net/sched/sch_generic.c
--- org/net/sched/sch_generic.c	2011-06-27 16:16:07.000000000 +0530
+++ new/net/sched/sch_generic.c	2011-07-13 10:58:39.000000000 +0530
@@ -190,16 +190,14 @@ static inline int qdisc_restart(struct Q
 void __qdisc_run(struct Qdisc *q)
 {
 	int quota = weight_p;
-	int work = 0;
 
 	while (qdisc_restart(q)) {
-		work++;
 		/*
 		 * Ordered by possible occurrence: Postpone processing if
 		 * 1. we've exceeded packet quota
 		 * 2. another process needs the CPU;
 		 */
-		if (work >= quota || need_resched()) {
+		if (--quota <= 0 || need_resched()) {
 			__netif_schedule(q);
 			break;
 		}

^ permalink raw reply

* Re: gianfar vlan
From: Jiri Pirko @ 2011-07-15  9:16 UTC (permalink / raw)
  To: Sebastian Pöhn; +Cc: sandeep.kumar, netdev, Sebastian Pöhn
In-Reply-To: <1310716743.1789.9.camel@DENEC1DT0191>

Fri, Jul 15, 2011 at 09:59:03AM CEST, sebastian.belden@googlemail.com wrote:
>Hi Jirka!
>
>The rx queue filer table also needs the RCTRL_PRSDEP_INIT to be set. So I would suggest to add FILREN to RCTRL_REQ_PARSER.
>
>Further I guess the parser should only be enabled if it is necessary (because of VLAN, IP, TCP or FILREN acceleration modes).
>
>What about putting the
>
>if (tempval & RCTRL_REQ_PARSER)
>	tempval |= RCTRL_PRSDEP_INIT;
>else
>	tempval &= ~RCTRL_PRSDEP_INIT;
>
>in a dedicated routine and call it every time one of the four features is altered?

Ok why not. Would you please cook up the patch and post it? Thanks.

Jirka

>
>Greetings
>Sebastian
>
>> Hi Sandeep.
>> 
>> I'm trying to remove gfar_vlan_rx_register() and move the vlan accel
>> enabling/disabling to gfar_set_features() -> startup_gfar() ->
>> gfar_init_mac(). I'm not sure how to handle following lines in
>> gfar_vlan_rx_register():
>> 
>> /* If parse is no longer required, then disable parser */
>> if (tempval & RCTRL_REQ_PARSER)
>> tempval |= RCTRL_PRSDEP_INIT;
>> else
>> tempval &= ~RCTRL_PRSDEP_INIT;
>> 
>> Should this be done only on disabling vlan accel (both rx an tx)?
>> Or can I just do that always in startup_gfar() ?
>> 
>> Thanks.
>> 
>> Jirka
>

^ permalink raw reply

* Re: iwlagn: Random "Time out reading EEPROM".
From: Nicolas de Pesloüan @ 2011-07-15  8:22 UTC (permalink / raw)
  To: wwguy, dhalperi; +Cc: netdev@vger.kernel.org, wireless
In-Reply-To: <1307284276.6918.17.camel@wwguy-ubuntu>

Le 05/06/2011 16:31, wwguy a écrit :
> On Sat, 2011-06-04 at 06:14 -0700, Nicolas de Pesloüan wrote:
>> Hi,
>>
>>   From time to time, my Intel Wifi adapter fail on cold boot, with the following in dmesg:
>>
>> [    7.442634] iwlagn: Intel(R) Wireless WiFi Link AGN driver for Linux, 1.3.27ks
>> [    7.442636] iwlagn: Copyright(c) 2003-2009 Intel Corporation
>> [    7.442701] iwlagn 0000:05:00.0: PCI INT A ->  GSI 18 (level, low) ->  IRQ 18
>> [    7.442708] iwlagn 0000:05:00.0: setting latency timer to 64
>> [    7.442788] iwlagn 0000:05:00.0: Detected Intel Wireless WiFi Link 5100AGN REV=0x54
>> [    7.455547] iwlagn 0000:05:00.0: Time out reading EEPROM[0]
>> [    7.455611] iwlagn 0000:05:00.0: Unable to init EEPROM
>> [    7.455678] iwlagn 0000:05:00.0: PCI INT A disabled
>> [    7.455685] iwlagn: probe of 0000:05:00.0 failed with error -110
>>
>> After "modprobe -r iwlagn ; modprobe iwlagn" or after a reboot, everything work fine:
>>
>> [  346.332166] iwlagn: Intel(R) Wireless WiFi Link AGN driver for Linux, 1.3.27ks
>> [  346.332169] iwlagn: Copyright(c) 2003-2009 Intel Corporation
>> [  346.332225] iwlagn 0000:05:00.0: PCI INT A ->  GSI 18 (level, low) ->  IRQ 18
>> [  346.332234] iwlagn 0000:05:00.0: setting latency timer to 64
>> [  346.332277] iwlagn 0000:05:00.0: Detected Intel Wireless WiFi Link 5100AGN REV=0x54
>> [  346.365739] iwlagn 0000:05:00.0: Tunable channels: 13 802.11bg, 24 802.11a channels
>> [  346.365787]   alloc irq_desc for 33 on node -1
>> [  346.365788]   alloc kstat_irqs on node -1
>> [  346.365804] iwlagn 0000:05:00.0: irq 33 for MSI/MSI-X
>> [  346.449989] phy0: Selected rate control algorithm 'iwl-agn-rs'
>>
>> This happens using 2.6.32-5 from Debian. I didn't had the opportunity to reproduce it using recent
>> kernel, but it occurs too rarely to conclude anything.
>>
>> I had a look at the git log, without finding something that seems related to this problem. Does this
>> ring a bell for someone?
>>
>> 	Nicolas.
>>
>> 05:00.0 Network controller: Intel Corporation WiFi Link 5100
>>           Subsystem: Intel Corporation WiFi Link 5100 AGN
>>           Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR-
>> FastB2B- DisINTx-
>>           Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast>TAbort-<TAbort-<MAbort->SERR-
>> <PERR- INTx-
>>           Latency: 0, Cache Line Size: 64 bytes
>>           Interrupt: pin A routed to IRQ 33
>>           Region 0: Memory at d6d00000 (64-bit, non-prefetchable) [size=8K]
>>           Capabilities: [c8] Power Management version 3
>>                   Flags: PMEClk- DSI+ D1- D2- AuxCurrent=0mA PME(D0+,D1-,D2-,D3hot+,D3cold+)
>>                   Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
>>           Capabilities: [d0] MSI: Enable+ Count=1/1 Maskable- 64bit+
>>                   Address: 00000000fee0300c  Data: 41c9
>>           Capabilities: [e0] Express (v1) Endpoint, MSI 00
>>                   DevCap: MaxPayload 128 bytes, PhantFunc 0, Latency L0s<512ns, L1 unlimited
>>                           ExtTag- AttnBtn- AttnInd- PwrInd- RBE+ FLReset+
>>                   DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
>>                           RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop+ FLReset-
>>                           MaxPayload 128 bytes, MaxReadReq 128 bytes
>>                   DevSta: CorrErr+ UncorrErr- FatalErr- UnsuppReq+ AuxPwr+ TransPend-
>>                   LnkCap: Port #0, Speed 2.5GT/s, Width x1, ASPM L0s L1, Latency L0<128ns, L1<32us
>>                           ClockPM+ Surprise- LLActRep- BwNot-
>>                   LnkCtl: ASPM L1 Enabled; RCB 64 bytes Disabled- Retrain- CommClk+
>>                           ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
>>                   LnkSta: Speed 2.5GT/s, Width x1, TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-
>>           Capabilities: [100 v1] Advanced Error Reporting
>>                   UESta:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC-
>> UnsupReq- ACSViol-
>>                   UEMsk:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC-
>> UnsupReq- ACSViol-
>>                   UESvrt: DLP+ SDES- TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+ ECRC-
>> UnsupReq- ACSViol-
>>                   CESta:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+
>>                   CEMsk:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+
>>                   AERCap: First Error Pointer: 00, GenCap- CGenEn- ChkCap- ChkEn-
>>           Capabilities: [140 v1] Device Serial Number 00-22-fb-ff-ff-28-46-c8
>>           Kernel driver in use: iwlagn
>>
>
> no sure, you are the ONLY one report this issue, since the device works
> after you reload the module, the HW/SW is ok. maybe the timing/sequence
> have problem on the kernel you are using on your system. The bus is not
> ready when you boot the system and access the EEPROM.
>
> What model of the laptop you have? could you try to upgrade to newer
> kernel?

This problem also happens using 2.6.39-2-amd64 from Debian.

[    8.507426] iwlagn: Intel(R) Wireless WiFi Link AGN driver for Linux, in-tree:
[    8.507429] iwlagn: Copyright(c) 2003-2010 Intel Corporation
[    8.507521] iwlagn 0000:05:00.0: PCI INT A -> GSI 18 (level, low) -> IRQ 18
[    8.507529] iwlagn 0000:05:00.0: setting latency timer to 64
[    8.507556] iwlagn 0000:05:00.0: Detected Intel(R) WiFi Link 5100 AGN, REV=0x54
[    8.516687] iwlagn 0000:05:00.0: Time out reading EEPROM[2]
[    8.516724] iwlagn 0000:05:00.0: Unable to init EEPROM
[    8.516739] iwlagn 0000:05:00.0: PCI INT A disabled
[    8.516745] iwlagn: probe of 0000:05:00.0 failed with error -110

modprobe -r iwlagn ; modprobe iwlagn

[  208.948664] iwlagn: Intel(R) Wireless WiFi Link AGN driver for Linux, in-tree:
[  208.948666] iwlagn: Copyright(c) 2003-2010 Intel Corporation
[  208.948743] iwlagn 0000:05:00.0: PCI INT A -> GSI 18 (level, low) -> IRQ 18
[  208.948753] iwlagn 0000:05:00.0: setting latency timer to 64
[  208.948817] iwlagn 0000:05:00.0: Detected Intel(R) WiFi Link 5100 AGN, REV=0x54
[  208.969659] iwlagn 0000:05:00.0: device EEPROM VER=0x11f, CALIB=0x4
[  208.969661] iwlagn 0000:05:00.0: Device SKU: 0Xb
[  208.969701] iwlagn 0000:05:00.0: Tunable channels: 13 802.11bg, 24 802.11a channels
[  208.969766] iwlagn 0000:05:00.0: irq 50 for MSI/MSI-X
[  209.048366] iwlagn 0000:05:00.0: loaded firmware version 8.83.5.1 build 33692

Because it happens not very often, I still didn't had the opportunity to reproduce it with up to 
date kernel.

The laptop is a two years old Sony Vaio VGN-AW21M.

	Nicolas.

^ permalink raw reply

* RE: gianfar vlan
From: Sebastian Pöhn @ 2011-07-15  7:59 UTC (permalink / raw)
  To: sandeep.kumar, sandeep.kumar, netdev, jpirko; +Cc: Sebastian Pöhn

Hi Jirka!

The rx queue filer table also needs the RCTRL_PRSDEP_INIT to be set. So I would suggest to add FILREN to RCTRL_REQ_PARSER.

Further I guess the parser should only be enabled if it is necessary (because of VLAN, IP, TCP or FILREN acceleration modes).

What about putting the

if (tempval & RCTRL_REQ_PARSER)
	tempval |= RCTRL_PRSDEP_INIT;
else
	tempval &= ~RCTRL_PRSDEP_INIT;

in a dedicated routine and call it every time one of the four features is altered?

Greetings
Sebastian

> Hi Sandeep.
> 
> I'm trying to remove gfar_vlan_rx_register() and move the vlan accel
> enabling/disabling to gfar_set_features() -> startup_gfar() ->
> gfar_init_mac(). I'm not sure how to handle following lines in
> gfar_vlan_rx_register():
> 
> /* If parse is no longer required, then disable parser */
> if (tempval & RCTRL_REQ_PARSER)
> tempval |= RCTRL_PRSDEP_INIT;
> else
> tempval &= ~RCTRL_PRSDEP_INIT;
> 
> Should this be done only on disabling vlan accel (both rx an tx)?
> Or can I just do that always in startup_gfar() ?
> 
> Thanks.
> 
> Jirka


^ permalink raw reply

* [PATCH net-next-2.6] slcan: remove obsolete code in slcan initialisation
From: Oliver Hartkopp @ 2011-07-15  7:49 UTC (permalink / raw)
  To: David Miller; +Cc: Linux Netdev List, Matvejchikov Ilya

This patch removes obsolete code in the initialisation/creation of
slcan devices.

It follows the suggested cleanups from Ilya Matvejchikov in
drivers/net/slip.c that where recently applied to net-next-2.6:

- slip: remove dead code within the slip initialization
- slip: remove redundant check slip_devs for NULL

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>

---

diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
index 1b49df6..aa8ad73 100644
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -473,12 +473,10 @@ static void slc_sync(void)
 static struct slcan *slc_alloc(dev_t line)
 {
 	int i;
+	char name[IFNAMSIZ];
 	struct net_device *dev = NULL;
 	struct slcan       *sl;

-	if (slcan_devs == NULL)
-		return NULL;	/* Master array missing ! */
-
 	for (i = 0; i < maxdev; i++) {
 		dev = slcan_devs[i];
 		if (dev == NULL)
@@ -490,25 +488,12 @@ static struct slcan *slc_alloc(dev_t line)
 	if (i >= maxdev)
 		return NULL;

-	if (dev) {
-		sl = netdev_priv(dev);
-		if (test_bit(SLF_INUSE, &sl->flags)) {
-			unregister_netdevice(dev);
-			dev = NULL;
-			slcan_devs[i] = NULL;
-		}
-	}
-
-	if (!dev) {
-		char name[IFNAMSIZ];
-		sprintf(name, "slcan%d", i);
-
-		dev = alloc_netdev(sizeof(*sl), name, slc_setup);
-		if (!dev)
-			return NULL;
-		dev->base_addr  = i;
-	}
+	sprintf(name, "slcan%d", i);
+	dev = alloc_netdev(sizeof(*sl), name, slc_setup);
+	if (!dev)
+		return NULL;

+	dev->base_addr  = i;
 	sl = netdev_priv(dev);

 	/* Initialize channel control data */


^ permalink raw reply related

* Re: [PATCH] [net][bna] Separate handling of irq type flags variable from the irq_flags request_irq variable
From: Ivan Vecera @ 2011-07-15  6:35 UTC (permalink / raw)
  To: Shyam Iyer; +Cc: netdev, rmody, ddutt, huangj, davem, Shyam Iyer
In-Reply-To: <1310691632-22914-1-git-send-email-shyam_iyer@dell.com>

On Thu, 2011-07-14 at 21:00 -0400, Shyam Iyer wrote:
> Commit 5f77898de17ff983ff0e2988b73a6bdf4b6f9f8b does not completely fix the problem of handling allocations with irqs disabled..
> The below patch on top of it fixes the problem completely.
The commit fixes the issue, but it does not separate enough the
'irq_flags' and the 'flags', so it is a little bit confusing. The patch
below corrects this imprecision and looks fine.

> Based on review by "Ivan Vecera" <ivecera@redhat.com>..
> "
> Small note, the root of the problem was that non-atomic allocation was requested with IRQs disabled. Your patch description does not contain wwhy were the IRQs disabled.
> 
> The function bnad_mbox_irq_alloc incorrectly uses 'flags' var for two different things, 1) to save current CPU flags and 2) for request_irq
> call.
> First the spin_lock_irqsave disables the IRQs and saves _all_ CPU flags (including one that enables/disables interrupts) to 'flags'. Then the 'flags' is overwritten by 0 or 0x80 (IRQF_SHARED). Finally the spin_unlock_irqrestore should restore saved flags, but these flags are now either 0x00 or 0x80. The interrupt bit value in flags register on x86 arch is 0x100.
> This means that the interrupt bit is zero (IRQs disabled) after spin_unlock_irqrestore so the request_irq function is called with disabled interrupts.
> "
> 
> Signed-off-by: Shyam Iyer <shyam_iyer@dell.com>
> ---
>  drivers/net/bna/bnad.c |    6 +++---
>  1 files changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c
> index 44e219c..ea13605 100644
> --- a/drivers/net/bna/bnad.c
> +++ b/drivers/net/bna/bnad.c
> @@ -1111,7 +1111,7 @@ bnad_mbox_irq_alloc(struct bnad *bnad,
>  		    struct bna_intr_info *intr_info)
>  {
>  	int 		err = 0;
> -	unsigned long 	irq_flags = 0, flags;
> +	unsigned long 	irq_flags, flags;
>  	u32	irq;
>  	irq_handler_t 	irq_handler;
>  
> @@ -1125,6 +1125,7 @@ bnad_mbox_irq_alloc(struct bnad *bnad,
>  	if (bnad->cfg_flags & BNAD_CF_MSIX) {
>  		irq_handler = (irq_handler_t)bnad_msix_mbox_handler;
>  		irq = bnad->msix_table[bnad->msix_num - 1].vector;
> +		irq_flags = 0;
>  		intr_info->intr_type = BNA_INTR_T_MSIX;
>  		intr_info->idl[0].vector = bnad->msix_num - 1;
>  	} else {
> @@ -1135,7 +1136,6 @@ bnad_mbox_irq_alloc(struct bnad *bnad,
>  		/* intr_info->idl.vector = 0 ? */
>  	}
>  	spin_unlock_irqrestore(&bnad->bna_lock, flags);
> -	flags = irq_flags;
>  	sprintf(bnad->mbox_irq_name, "%s", BNAD_NAME);
>  
>  	/*
> @@ -1146,7 +1146,7 @@ bnad_mbox_irq_alloc(struct bnad *bnad,
>  
>  	BNAD_UPDATE_CTR(bnad, mbox_intr_disabled);
>  
> -	err = request_irq(irq, irq_handler, flags,
> +	err = request_irq(irq, irq_handler, irq_flags,
>  			  bnad->mbox_irq_name, bnad);
>  
>  	if (err) {




^ permalink raw reply

* Re: [PATCH v2 1/5] dt: add of_alias_scan and of_alias_get_id
From: Grant Likely @ 2011-07-15  2:53 UTC (permalink / raw)
  To: Shawn Guo
  Cc: linux-arm-kernel, linux-kernel, netdev, linux-serial,
	devicetree-discuss, patches
In-Reply-To: <1308938676-31121-2-git-send-email-shawn.guo@linaro.org>

On Sat, Jun 25, 2011 at 02:04:32AM +0800, Shawn Guo wrote:
> The patch adds function of_alias_scan to populate a global lookup
> table with the properties of 'aliases' node and function
> of_alias_get_id for drivers to find alias id from the lookup table.
> 
> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> Cc: Grant Likely <grant.likely@secretlab.ca>

Hey Shawn,

Comments below, but I've gone ahead and fixed them because I'm keen to
get this patch merged.  I just wanted to let you know what I changed.
I'll post the modified version so you can test it.

> ---
>  drivers/of/base.c  |  181 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/of/fdt.c   |    6 ++
>  include/linux/of.h |    7 ++
>  3 files changed, 194 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index 632ebae..89efd10 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -17,14 +17,38 @@
>   *      as published by the Free Software Foundation; either version
>   *      2 of the License, or (at your option) any later version.
>   */
> +#include <linux/bootmem.h>
> +#include <linux/ctype.h>
>  #include <linux/module.h>
>  #include <linux/of.h>
>  #include <linux/spinlock.h>
>  #include <linux/slab.h>
>  #include <linux/proc_fs.h>
>  
> +/**
> + * struct alias_prop - Alias property in 'aliases' node
> + * @link:	List node to link the structure in aliases_lookup list
> + * @alias:	Alias property name
> + * @np:		Pointer to device_node that the alias stands for
> + * @alias_id:	Alias id decoded from alias
> + * @alias_stem:	Alias stem name decoded from alias
> + *
> + * The structure represents one alias property of 'aliases' node as
> + * an entry in aliases_lookup list.
> + */
> +struct alias_prop {
> +	struct list_head link;
> +	const char *alias;
> +	struct device_node *np;
> +	int alias_id;
> +	char alias_stem[0];
> +};
> +
> +static LIST_HEAD(aliases_lookup);
> +
>  struct device_node *allnodes;
>  struct device_node *of_chosen;
> +struct device_node *of_aliases;
>  
>  /* use when traversing tree through the allnext, child, sibling,
>   * or parent members of struct device_node.
> @@ -922,3 +946,160 @@ out_unlock:
>  }
>  #endif /* defined(CONFIG_OF_DYNAMIC) */
>  
> +/*
> + * of_alias_find_available_id - Find an available id for the given device_node

Nit: kerneldoc format is "/**" to start the comment, and function
names should have '()' on it.

> + * @np:		Pointer to the given device_node
> + * @stem:	Alias stem of the given device_node
> + *
> + * The function travels the lookup table to find an available id for the
> + * given device_node with given alias stem.  It returns the id found.
> + */
> +static int of_alias_find_available_id(struct device_node *np, const char *stem)
> +{
> +	struct alias_prop *app;
> +	int id = 0;
> +
> +	while (1) {
> +		bool used = false;
> +		list_for_each_entry(app, &aliases_lookup, link) {
> +			if (!strcmp(app->alias_stem, stem) &&
> +			    app->alias_id == id) {
> +				used = true;
> +				break;
> +			}
> +		}
> +
> +		if (used)
> +			id++;
> +		else
> +			return id;
> +	}
> +}

I've simplified this somewhat to do the list_for_each_entry() only
once, and to bump up the id to +1 the largest entry:

	list_for_each_entry(app, &aliases_lookup, link)
		if ((strcmp(app->stem, stem) == 0) && id <= app->id)
			id = app->id + 1;

.... actually, after looking further, I've rolled this code into the
of_alias_get_id() function.

> +
> +/**
> + * of_alias_lookup_add - Add alias into lookup table
> + * @alias:	Alias name
> + * @id:		Alias id
> + * @stem:	Alias stem name
> + * @np:		Pointer to device_node
> + *
> + * The function adds one alias into the lookup table and populate it
> + * with the info passed in.  It returns 0 in sucess, or error code.
> + */
> +static int of_alias_lookup_add(char *alias, int id, const char *stem,
> +			       struct device_node *np)
> +{
> +	struct alias_prop *app;
> +	size_t sz = sizeof(*app) + strlen(stem) + 1;
> +
> +	app = kzalloc(sz, GFP_KERNEL);
> +	if (!app) {
> +		/*
> +		 * It may fail due to being called by boot code,
> +		 * so try alloc_bootmem before return error.
> +		 */
> +		app = alloc_bootmem(sz);
> +		if (!app)
> +			return -ENOMEM;
> +	}

I'm not too fond of this since we *know* when this is going to be
called from early boot.  So, instead, I've changed the code to use the
already existing dt_alloc functions as an argument to of_alias_lookup_add().

Also, alloc_bootmem() doesn't work on all platforms.
early_init_dt_alloc_memory_arch() needs to be used instead.


> +
> +	app->np = np;
> +	app->alias = alias;
> +	app->alias_id = id;
> +	strcpy(app->alias_stem, stem);
> +	list_add_tail(&app->link, &aliases_lookup);
> +
> +	return 0;
> +}
> +
> +/**
> + * of_alias_decode - Decode alias stem and id from alias name
> + * @alias:	Alias name to be decoded
> + * @stem:	Pointer used to return stem name
> + *
> + * The function decodes alias stem name and alias id from the given
> + * alias name.  It returns stem name via parameter 'stem', and stem id
> + * via the return value.  If no id is found in alias name, it returns 0
> + * as the default.
> + */
> +static int of_alias_decode(char *alias, char *stem)
> +{
> +	int len = strlen(alias);
> +	char *end = alias + len;
> +
> +	while (isdigit(*--end))
> +		len--;

Need to protect against len < 0

> +
> +	strncpy(stem, alias, len);
> +	stem[len] = '\0';
> +
> +	return strlen(++end) ? simple_strtoul(end, NULL, 10) : 0;
> +}
> +
> +/**
> + * of_alias_scan - Scan all properties of 'aliases' node
> + *
> + * The function scans all the properties of 'aliases' node and populate
> + * the the global lookup table with the properties.  It returns the
> + * number of alias_prop found, or error code in error case.
> + */
> +int of_alias_scan(void)

Changed to '__init void of_aliases_scan(void)'.  There is no point in
returning an error code since it is never checked, and there is no
point in bailing on an error just in case it is a problem with only
one alias.

> +{
> +	struct property *pp;
> +	int ret, num = 0;
> +
> +	if (!of_aliases)
> +		return -ENODEV;
> +
> +	for_each_property(pp, of_aliases->properties) {
> +		char stem[32];
> +		int id = of_alias_decode(pp->name, stem);
> +
> +		/* Skip those we do not want to proceed */
> +		if (!strcmp(pp->name, "name") ||
> +		    !strcmp(pp->name, "phandle") ||
> +		    !strcmp(pp->name, "linux,phandle"))
> +			continue;
> +
> +		ret = of_alias_lookup_add(pp->name, id, stem,
> +					  of_find_node_by_path(pp->value));
> +		if (ret < 0)
> +			return ret;
> +		else
> +			num++;
> +	}
> +
> +	return num;
> +}
> +
> +/**
> + * of_alias_get_id - Get alias id for the given device_node
> + * @np:		Pointer to the given device_node
> + * @stem:	Alias stem of the given device_node
> + *
> + * The function travels the lookup table to get alias id for the given
> + * device_node and alias stem.  It returns the alias id if find it.
> + * If not, dynamically creates one in the lookup table and returns it,
> + * or returns error code if fail to create.
> + */
> +int of_alias_get_id(struct device_node *np, const char *stem)
> +{
> +	struct alias_prop *app;
> +	int id = -1;
> +
> +	list_for_each_entry(app, &aliases_lookup, link) {
> +		if (np == app->np) {
> +			id = app->alias_id;
> +			break;
> +		}
> +	}
> +
> +	if (id == -1) {
> +		id = of_alias_find_available_id(np, stem);
> +		if (of_alias_lookup_add(NULL, id, stem, np) < 0)
> +			return -ENODEV;
> +	}
> +
> +	return id;
> +}

This whole function needs to be protected by a mutex.

> +EXPORT_SYMBOL_GPL(of_alias_get_id);
> diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
> index 65200af..998dc63 100644
> --- a/drivers/of/fdt.c
> +++ b/drivers/of/fdt.c
> @@ -711,6 +711,12 @@ void __init unflatten_device_tree(void)
>  	of_chosen = of_find_node_by_path("/chosen");
>  	if (of_chosen == NULL)
>  		of_chosen = of_find_node_by_path("/chosen@0");
> +
> +	of_aliases = of_find_node_by_path("/aliases");
> +	if (of_aliases == NULL)
> +		of_aliases = of_find_node_by_path("/aliases@0");

I don't think the /aliases@0 variant is necessary.  I've dropped it.

g.

> +
> +	of_alias_scan();
>  }
>  
>  #endif /* CONFIG_OF_EARLY_FLATTREE */
> diff --git a/include/linux/of.h b/include/linux/of.h
> index bfc0ed1..c35cc47 100644
> --- a/include/linux/of.h
> +++ b/include/linux/of.h
> @@ -68,6 +68,7 @@ struct device_node {
>  /* Pointer for first entry in chain of all nodes. */
>  extern struct device_node *allnodes;
>  extern struct device_node *of_chosen;
> +extern struct device_node *of_aliases;
>  extern rwlock_t devtree_lock;
>  
>  static inline bool of_have_populated_dt(void)
> @@ -201,6 +202,9 @@ extern int of_device_is_available(const struct device_node *device);
>  extern const void *of_get_property(const struct device_node *node,
>  				const char *name,
>  				int *lenp);
> +#define for_each_property(pp, properties) \
> +	for (pp = properties; pp != NULL; pp = pp->next)
> +
>  extern int of_n_addr_cells(struct device_node *np);
>  extern int of_n_size_cells(struct device_node *np);
>  extern const struct of_device_id *of_match_node(
> @@ -213,6 +217,9 @@ extern int of_parse_phandles_with_args(struct device_node *np,
>  	const char *list_name, const char *cells_name, int index,
>  	struct device_node **out_node, const void **out_args);
>  
> +extern int of_alias_scan(void);
> +extern int of_alias_get_id(struct device_node *np, const char *stem);
> +
>  extern int of_machine_is_compatible(const char *compat);
>  
>  extern int prom_add_property(struct device_node* np, struct property* prop);
> -- 
> 1.7.4.1
> 

^ permalink raw reply

* Re: [RFC 46/72] ixp2000: Move the Radisys driver
From: Jeff Kirsher @ 2011-07-15  1:19 UTC (permalink / raw)
  To: Lennert Buytenhek; +Cc: davem@davemloft.net, netdev@vger.kernel.org
In-Reply-To: <20110715000819.GK951@wantstofly.org>

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

On Thu, 2011-07-14 at 17:08 -0700, Lennert Buytenhek wrote:
> On Sat, Jul 09, 2011 at 08:58:56AM -0700, Jeff Kirsher wrote:
> 
> > > > Move the Radisys driver into drivers/net/ethernet/radisys/ and
> > > > make the necessary Kconfig and Makefile changes
> > > > 
> > > > CC: Lennert Buytenhek <kernel@wantstofly.org>
> > > > Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
> > > > ---
> > > >  MAINTAINERS                                        |    2 +-
> > > >  drivers/net/Kconfig                                |    2 --
> > > >  drivers/net/Makefile                               |    1 -
> > > >  drivers/net/ethernet/Kconfig                       |    1 +
> > > >  drivers/net/ethernet/Makefile                      |    1 +
> > > >  drivers/net/ethernet/radisys/Kconfig               |   16 ++++++++++++++++
> > > >  drivers/net/ethernet/radisys/Makefile              |    5 +++++
> > > >  drivers/net/{ => ethernet/radisys}/ixp2000/Kconfig |    2 +-
> > > >  .../net/{ => ethernet/radisys}/ixp2000/Makefile    |    0
> > > 
> > > The ixp2000 is a series of Intel ARM SoCs, and the ENP2611 is a Radisys
> > > PCI board based on the ixp2000 series (ixp2400), so it doesn't make
> > > sense to put everything in the radisys/ directory.
> > 
> > It was suggested earlier that it probably should be in either ixp/ or
> > radisys/, and someone suggested that ixp/ might be confusing.  If you
> > would like to keep it under drivers/net/ethernet/ixp2000, I am fine with
> > that as well.
> > 
> > > If you insist on moving all drivers into vendor directories (I don't
> > > like that idea at all -- are we going to rename directories and shuffle
> > > stuff around every time vendor A buys vendor B or takes over one of
> > > vendor B's products?), at least the core ixp2000 code should be under
> > > intel/.
> > 
> > It was not my preference to place drivers into vendor specific
> > directories because of that very reason, as I did the work, it just
> > tended to work out that way.
> > 
> > The reason (as stated before) that it was not moved into intel/
> > directory is because the driver was not written (and supported) by
> > Intel.
> 
> I didn't follow the discussion, but that seems like a silly argument.
> Does that mean that any non-vendor supported driver can't go into
> drivers/net/$vendor/?  What if the vendor starts contributing to the
> driver later on, will the driver be moved then?
> 
> It seems that what you're saying is that you don't want the ixp2000
> driver in "your" subdirectory.

It is more that all the drivers that in intel/ are all very similar and
have "common" code which potentially code be shared.  We have been
looking at what possibilities there are for the common code between the
Intel supported drivers.  So it really did not make sense to throw a
driver into the intel/ directory just because it used an Intel chip, but
has nothing in common with the other drivers in that directory.  Sorry
if my previous explanation sounded like it I just did not want the
drivers in the intel/ because we did not write or support it.

After looking at ixp2000/ixp4xx drivers and the 82586/82596 drivers a
bit more, I came up with the solution of putting the IXP drivers in
xscale/ and the 82586/82596 drivers in i825xx/ directory.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply

* [PATCH] [net][bna] Separate handling of irq type flags variable from the irq_flags request_irq variable
From: Shyam Iyer @ 2011-07-15  1:00 UTC (permalink / raw)
  To: netdev; +Cc: rmody, ddutt, huangj, davem, ivecera, Shyam Iyer

Commit 5f77898de17ff983ff0e2988b73a6bdf4b6f9f8b does not completely fix the problem of handling allocations with irqs disabled..
The below patch on top of it fixes the problem completely.

Based on review by "Ivan Vecera" <ivecera@redhat.com>..
"
Small note, the root of the problem was that non-atomic allocation was requested with IRQs disabled. Your patch description does not contain wwhy were the IRQs disabled.

The function bnad_mbox_irq_alloc incorrectly uses 'flags' var for two different things, 1) to save current CPU flags and 2) for request_irq
call.
First the spin_lock_irqsave disables the IRQs and saves _all_ CPU flags (including one that enables/disables interrupts) to 'flags'. Then the 'flags' is overwritten by 0 or 0x80 (IRQF_SHARED). Finally the spin_unlock_irqrestore should restore saved flags, but these flags are now either 0x00 or 0x80. The interrupt bit value in flags register on x86 arch is 0x100.
This means that the interrupt bit is zero (IRQs disabled) after spin_unlock_irqrestore so the request_irq function is called with disabled interrupts.
"

Signed-off-by: Shyam Iyer <shyam_iyer@dell.com>
---
 drivers/net/bna/bnad.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c
index 44e219c..ea13605 100644
--- a/drivers/net/bna/bnad.c
+++ b/drivers/net/bna/bnad.c
@@ -1111,7 +1111,7 @@ bnad_mbox_irq_alloc(struct bnad *bnad,
 		    struct bna_intr_info *intr_info)
 {
 	int 		err = 0;
-	unsigned long 	irq_flags = 0, flags;
+	unsigned long 	irq_flags, flags;
 	u32	irq;
 	irq_handler_t 	irq_handler;
 
@@ -1125,6 +1125,7 @@ bnad_mbox_irq_alloc(struct bnad *bnad,
 	if (bnad->cfg_flags & BNAD_CF_MSIX) {
 		irq_handler = (irq_handler_t)bnad_msix_mbox_handler;
 		irq = bnad->msix_table[bnad->msix_num - 1].vector;
+		irq_flags = 0;
 		intr_info->intr_type = BNA_INTR_T_MSIX;
 		intr_info->idl[0].vector = bnad->msix_num - 1;
 	} else {
@@ -1135,7 +1136,6 @@ bnad_mbox_irq_alloc(struct bnad *bnad,
 		/* intr_info->idl.vector = 0 ? */
 	}
 	spin_unlock_irqrestore(&bnad->bna_lock, flags);
-	flags = irq_flags;
 	sprintf(bnad->mbox_irq_name, "%s", BNAD_NAME);
 
 	/*
@@ -1146,7 +1146,7 @@ bnad_mbox_irq_alloc(struct bnad *bnad,
 
 	BNAD_UPDATE_CTR(bnad, mbox_intr_disabled);
 
-	err = request_irq(irq, irq_handler, flags,
+	err = request_irq(irq, irq_handler, irq_flags,
 			  bnad->mbox_irq_name, bnad);
 
 	if (err) {
-- 
1.7.5.4


^ permalink raw reply related

* Re: [PATCH 07/10] net: remove NETIF_F_NO_CSUM feature
From: Michał Mirosław @ 2011-07-15  0:28 UTC (permalink / raw)
  To: David Miller; +Cc: therbert, bhutchings, netdev
In-Reply-To: <20110714.170506.1425372007221475085.davem@davemloft.net>

On Thu, Jul 14, 2011 at 05:05:06PM -0700, David Miller wrote:
> From: Michał Mirosław <mirq-linux@rere.qmqm.pl>
> Date: Fri, 15 Jul 2011 00:44:45 +0200
> 
> > On Thu, Jul 14, 2011 at 02:31:21PM -0700, David Miller wrote:
> >> From: Michał Mirosław <mirq-linux@rere.qmqm.pl>
> >> Date: Thu, 14 Jul 2011 22:56:23 +0200
> >> > That's why its turned off by default and should be enabled only when user
> >> > knows he will win some pps with it.
> >> More people are going to lose than win by your change.
> >> 
> >> The nocopy feature helps more real situations than it hurts, the
> >> existing default is the best.
> > 
> > I see. I still want to remove NO_CSUM (as I explained in other mail),
> > so would you accept replacing it with something more specific to
> > nocache-copy feature? READS_DATA maybe? That could be later added to
> > sk_route_caps whenever it's known for a route there will be need to
> > read packets' data.
> 
> I don't actually see what the problem is.
> 
> The code wants to conditionalize the nocache-copy feature based upon
> whether hardware will checksum the packet or not.
> 
> And that's exactly what it's testing.
> 
> The reason, of course, is because it doesn't want to enable
> nocache-copy if the cpu is just going to read the data back into it's
> caches during the checksum.  But that's no reason to change the
> flag name to have the word "read" instead of "checksum" in it.

But the real condition is that CPU doesn't read the data. I doesn't matter
if reading is to calculate the checksum or parsing it. The change would
make this obvious.

BTW, 
Best Regards,
Michał Mirosław

^ permalink raw reply

* Re: [PATCH] bnx2: do not start the interface if reset fails
From: Michael Chan @ 2011-07-15  0:13 UTC (permalink / raw)
  To: Flavio Leitner; +Cc: netdev
In-Reply-To: <1310579690-24622-1-git-send-email-fbl@redhat.com>


On Wed, 2011-07-13 at 10:54 -0700, Flavio Leitner wrote:
> When bnx2_reset_task() is called, it will stop,
> (re)initialize and start the interface to restore
> the working condition.
> 
> The bnx2_init_nic() calls bnx2_reset_nic() which will
> reset the chip and then call bnx2_free_skbs() to free
> all the skbs.
> 
> The problem happens when bnx2_init_chip() fails because
> bnx2_reset_nic() will just return skipping the ring
> initializations at bnx2_init_all_rings(). Later, the
> reset task starts the interface again and the system
> crashes due a NULL pointer access (no skb in the ring).
> 
> This patch just check the return code and if an error is
> reported, warn the user and abort. It's better to have a
> non working interface than a crash.
> 
> Signed-off-by: Flavio Leitner <fbl@redhat.com>
> ---
>  drivers/net/bnx2.c |    8 +++++++-
>  1 files changed, 7 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
> index 7915d14..7fb71fc 100644
> --- a/drivers/net/bnx2.c
> +++ b/drivers/net/bnx2.c
> @@ -6296,6 +6296,7 @@ static void
>  bnx2_reset_task(struct work_struct *work)
>  {
>  	struct bnx2 *bp = container_of(work, struct bnx2, reset_task);
> +	int rc;
>  
>  	rtnl_lock();
>  	if (!netif_running(bp->dev)) {
> @@ -6305,10 +6306,15 @@ bnx2_reset_task(struct work_struct *work)
>  
>  	bnx2_netif_stop(bp, true);
>  
> -	bnx2_init_nic(bp, 1);
> +	rc = bnx2_init_nic(bp, 1);
> +	if (rc) {
> +		netdev_err(bp->dev, "failed to reset the NIC, aborting\n");
> +		goto out;
> +	}

I think it is better to call dev_close() instead.  I'll post a patch
soon.  Thanks.

>  
>  	atomic_set(&bp->intr_sem, 1);
>  	bnx2_netif_start(bp, true);
> +out:
>  	rtnl_unlock();
>  }
>  



^ permalink raw reply

* Re: [RFC 46/72] ixp2000: Move the Radisys driver
From: Lennert Buytenhek @ 2011-07-15  0:08 UTC (permalink / raw)
  To: Jeff Kirsher; +Cc: davem@davemloft.net, netdev@vger.kernel.org
In-Reply-To: <1310227137.26989.43.camel@jtkirshe-mobl>

On Sat, Jul 09, 2011 at 08:58:56AM -0700, Jeff Kirsher wrote:

> > > Move the Radisys driver into drivers/net/ethernet/radisys/ and
> > > make the necessary Kconfig and Makefile changes
> > > 
> > > CC: Lennert Buytenhek <kernel@wantstofly.org>
> > > Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
> > > ---
> > >  MAINTAINERS                                        |    2 +-
> > >  drivers/net/Kconfig                                |    2 --
> > >  drivers/net/Makefile                               |    1 -
> > >  drivers/net/ethernet/Kconfig                       |    1 +
> > >  drivers/net/ethernet/Makefile                      |    1 +
> > >  drivers/net/ethernet/radisys/Kconfig               |   16 ++++++++++++++++
> > >  drivers/net/ethernet/radisys/Makefile              |    5 +++++
> > >  drivers/net/{ => ethernet/radisys}/ixp2000/Kconfig |    2 +-
> > >  .../net/{ => ethernet/radisys}/ixp2000/Makefile    |    0
> > 
> > The ixp2000 is a series of Intel ARM SoCs, and the ENP2611 is a Radisys
> > PCI board based on the ixp2000 series (ixp2400), so it doesn't make
> > sense to put everything in the radisys/ directory.
> 
> It was suggested earlier that it probably should be in either ixp/ or
> radisys/, and someone suggested that ixp/ might be confusing.  If you
> would like to keep it under drivers/net/ethernet/ixp2000, I am fine with
> that as well.
> 
> > If you insist on moving all drivers into vendor directories (I don't
> > like that idea at all -- are we going to rename directories and shuffle
> > stuff around every time vendor A buys vendor B or takes over one of
> > vendor B's products?), at least the core ixp2000 code should be under
> > intel/.
> 
> It was not my preference to place drivers into vendor specific
> directories because of that very reason, as I did the work, it just
> tended to work out that way.
> 
> The reason (as stated before) that it was not moved into intel/
> directory is because the driver was not written (and supported) by
> Intel.

I didn't follow the discussion, but that seems like a silly argument.
Does that mean that any non-vendor supported driver can't go into
drivers/net/$vendor/?  What if the vendor starts contributing to the
driver later on, will the driver be moved then?

It seems that what you're saying is that you don't want the ixp2000
driver in "your" subdirectory.

^ permalink raw reply

* Re: [PATCH 07/10] net: remove NETIF_F_NO_CSUM feature
From: David Miller @ 2011-07-15  0:05 UTC (permalink / raw)
  To: mirq-linux; +Cc: therbert, bhutchings, netdev
In-Reply-To: <20110714224445.GA18237@rere.qmqm.pl>

From: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Date: Fri, 15 Jul 2011 00:44:45 +0200

> On Thu, Jul 14, 2011 at 02:31:21PM -0700, David Miller wrote:
>> From: Michał Mirosław <mirq-linux@rere.qmqm.pl>
>> Date: Thu, 14 Jul 2011 22:56:23 +0200
>> > That's why its turned off by default and should be enabled only when user
>> > knows he will win some pps with it.
>> More people are going to lose than win by your change.
>> 
>> The nocopy feature helps more real situations than it hurts, the
>> existing default is the best.
> 
> I see. I still want to remove NO_CSUM (as I explained in other mail),
> so would you accept replacing it with something more specific to
> nocache-copy feature? READS_DATA maybe? That could be later added to
> sk_route_caps whenever it's known for a route there will be need to
> read packets' data.

I don't actually see what the problem is.

The code wants to conditionalize the nocache-copy feature based upon
whether hardware will checksum the packet or not.

And that's exactly what it's testing.

The reason, of course, is because it doesn't want to enable
nocache-copy if the cpu is just going to read the data back into it's
caches during the checksum.  But that's no reason to change the
flag name to have the word "read" instead of "checksum" in it.


^ permalink raw reply

* Re: [PATCH] bnx2: do not start the interface if reset fails
From: David Miller @ 2011-07-15  0:06 UTC (permalink / raw)
  To: fbl; +Cc: netdev, mchan
In-Reply-To: <1310579690-24622-1-git-send-email-fbl@redhat.com>

From: Flavio Leitner <fbl@redhat.com>
Date: Wed, 13 Jul 2011 14:54:50 -0300

> When bnx2_reset_task() is called, it will stop,
> (re)initialize and start the interface to restore
> the working condition.
> 
> The bnx2_init_nic() calls bnx2_reset_nic() which will
> reset the chip and then call bnx2_free_skbs() to free
> all the skbs.
> 
> The problem happens when bnx2_init_chip() fails because
> bnx2_reset_nic() will just return skipping the ring
> initializations at bnx2_init_all_rings(). Later, the
> reset task starts the interface again and the system
> crashes due a NULL pointer access (no skb in the ring).
> 
> This patch just check the return code and if an error is
> reported, warn the user and abort. It's better to have a
> non working interface than a crash.
> 
> Signed-off-by: Flavio Leitner <fbl@redhat.com>

Broadcom folks?

^ permalink raw reply

* [PATCH 1/7] at91rm9200: emac move register header to drivers
From: Jean-Christophe PLAGNIOL-VILLARD @ 2011-07-14 23:51 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: Nicolas Ferre, Jean-Christophe PLAGNIOL-VILLARD, netdev

move from mach-at91/include/mach/at91rm9200_emac.h to drivers/net/arm/at91_ether.h

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Cc: Nicolas Ferre <nicolas.ferre@atmel.com>
Cc: netdev@vger.kernel.org
---
 drivers/net/arm/at91_ether.c                       |    1 -
 .../net/arm/at91_ether.h                           |  112 ++++++++++++++++++--
 2 files changed, 101 insertions(+), 12 deletions(-)
 rename arch/arm/mach-at91/include/mach/at91rm9200_emac.h => drivers/net/arm/at91_ether.h (65%)

diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c
index e07b314..8f0b212 100644
--- a/drivers/net/arm/at91_ether.c
+++ b/drivers/net/arm/at91_ether.c
@@ -33,7 +33,6 @@
 #include <asm/uaccess.h>
 #include <asm/mach-types.h>
 
-#include <mach/at91rm9200_emac.h>
 #include <mach/gpio.h>
 #include <mach/board.h>
 
diff --git a/arch/arm/mach-at91/include/mach/at91rm9200_emac.h b/drivers/net/arm/at91_ether.h
similarity index 65%
rename from arch/arm/mach-at91/include/mach/at91rm9200_emac.h
rename to drivers/net/arm/at91_ether.h
index b8260cd..58aed66 100644
--- a/arch/arm/mach-at91/include/mach/at91rm9200_emac.h
+++ b/drivers/net/arm/at91_ether.h
@@ -1,21 +1,21 @@
 /*
- * arch/arm/mach-at91/include/mach/at91rm9200_emac.h
+ * Ethernet driver for the Atmel AT91RM9200 (Thunder)
  *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
+ *  Copyright (C) SAN People (Pty) Ltd
  *
- * Ethernet MAC registers.
- * Based on AT91RM9200 datasheet revision E.
+ * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc.
+ * Initial version by Rick Bronson.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
  */
 
-#ifndef AT91RM9200_EMAC_H
-#define AT91RM9200_EMAC_H
+#ifndef AT91_ETHERNET
+#define AT91_ETHERNET
 
+/* registers */
 #define	AT91_EMAC_CTL		0x00	/* Control Register */
 #define		AT91_EMAC_LB		(1 <<  0)	/* Loopback */
 #define		AT91_EMAC_LBL		(1 <<  1)	/* Loopback Local */
@@ -135,4 +135,94 @@
 #define AT91_EMAC_SA4L		0xb0	/* Specific Address 4 Low, bytes 0-3 */
 #define AT91_EMAC_SA4H		0xb4	/* Specific Address 4 High, bytes 4-5 */
 
+/* Davicom 9161 PHY */
+#define MII_DM9161_ID		0x0181b880
+#define MII_DM9161A_ID		0x0181b8a0
+#define MII_DSCR_REG		16
+#define MII_DSCSR_REG		17
+#define MII_DSINTR_REG		21
+
+/* Intel LXT971A PHY */
+#define MII_LXT971A_ID		0x001378E0
+#define MII_ISINTE_REG		18
+#define MII_ISINTS_REG		19
+#define MII_LEDCTRL_REG		20
+
+/* Realtek RTL8201 PHY */
+#define MII_RTL8201_ID		0x00008200
+
+/* Broadcom BCM5221 PHY */
+#define MII_BCM5221_ID		0x004061e0
+#define MII_BCMINTR_REG		26
+
+/* National Semiconductor DP83847 */
+#define MII_DP83847_ID		0x20005c30
+
+/* National Semiconductor DP83848 */
+#define MII_DP83848_ID		0x20005c90
+#define MII_DPPHYSTS_REG	16
+#define MII_DPMICR_REG		17
+#define MII_DPMISR_REG		18
+
+/* Altima AC101L PHY */
+#define MII_AC101L_ID		0x00225520
+
+/* Micrel KS8721 PHY */
+#define MII_KS8721_ID		0x00221610
+
+/* Teridian 78Q2123/78Q2133 */
+#define MII_T78Q21x3_ID		0x000e7230
+#define MII_T78Q21INT_REG	17
+
+/* SMSC LAN83C185 */
+#define MII_LAN83C185_ID	0x0007C0A0
+
+/* ........................................................................ */
+
+#define MAX_RBUFF_SZ	0x600		/* 1518 rounded up */
+#define MAX_RX_DESCR	9		/* max number of receive buffers */
+
+#define EMAC_DESC_DONE	0x00000001	/* bit for if DMA is done */
+#define EMAC_DESC_WRAP	0x00000002	/* bit for wrap */
+
+#define EMAC_BROADCAST	0x80000000	/* broadcast address */
+#define EMAC_MULTICAST	0x40000000	/* multicast address */
+#define EMAC_UNICAST	0x20000000	/* unicast address */
+
+struct rbf_t
+{
+	unsigned int addr;
+	unsigned long size;
+};
+
+struct recv_desc_bufs
+{
+	struct rbf_t descriptors[MAX_RX_DESCR];		/* must be on sizeof (rbf_t) boundary */
+	char recv_buf[MAX_RX_DESCR][MAX_RBUFF_SZ];	/* must be on long boundary */
+};
+
+struct at91_private
+{
+	struct mii_if_info mii;			/* ethtool support */
+	struct at91_eth_data board_data;	/* board-specific configuration */
+	struct clk *ether_clk;			/* clock */
+
+	/* PHY */
+	unsigned long phy_type;			/* type of PHY (PHY_ID) */
+	spinlock_t lock;			/* lock for MDI interface */
+	short phy_media;			/* media interface type */
+	unsigned short phy_address;		/* 5-bit MDI address of PHY (0..31) */
+	struct timer_list check_timer;		/* Poll link status */
+
+	/* Transmit */
+	struct sk_buff *skb;			/* holds skb until xmit interrupt completes */
+	dma_addr_t skb_physaddr;		/* phys addr from pci_map_single */
+	int skb_length;				/* saved skb length for pci_unmap_single */
+
+	/* Receive */
+	int rxBuffIndex;			/* index into receive descriptor list */
+	struct recv_desc_bufs *dlist;		/* descriptor list address */
+	struct recv_desc_bufs *dlist_phys;	/* descriptor list physical address */
+};
+
 #endif
-- 
1.7.5.4

^ permalink raw reply related

* Re: [PATCH] net/ps3: Fix gelic RX DMA restart
From: David Miller @ 2011-07-14 23:03 UTC (permalink / raw)
  To: geoff; +Cc: netdev, cbe-oss-dev
In-Reply-To: <4E1F242E.7070509@infradead.org>

From: Geoff Levand <geoff@infradead.org>
Date: Thu, 14 Jul 2011 10:15:26 -0700

> Fix the condition where PS3 network RX hangs when no network
> TX is occurring by calling gelic_card_enable_rxdmac() during
> RX_DMA_CHAIN_END event processing.
> 
> The gelic hardware automatically clears its RX_DMA_EN flag when
> it detects an RX_DMA_CHAIN_END event.  In its processing of
> RX_DMA_CHAIN_END the gelic driver is required to set RX_DMA_EN
> (with a call to gelic_card_enable_rxdmac()) to restart RX DMA
> transfers.  The existing gelic driver code does not set
> RX_DMA_EN directly in its processing of the RX_DMA_CHAIN_END
> event, but uses a flag variable card->rx_dma_restart_required
> to schedule the setting of RX_DMA_EN until next inside the
> interrupt handler.
> 
> It seems this delayed setting of RX_DMA_EN causes the hang since
> the next RX interrupt after the RX_DMA_CHAIN_END event where
> RX_DMA_EN is scheduled to be set will not occur since RX_DMA_EN
> was not set.  In the case were network TX is occuring, RX_DMA_EN
> is set in the next TX interrupt and RX processing continues.
> 
> Signed-off-by: Geoff Levand <geoff@infradead.org>

Applied.

^ permalink raw reply

* Re: preempting while holding rtnl_lock
From: Ben Hutchings @ 2011-07-14 23:06 UTC (permalink / raw)
  To: Flavio Leitner; +Cc: netdev
In-Reply-To: <20110714181502.4a5602aa@asterix.rh>

On Thu, 2011-07-14 at 18:15 -0300, Flavio Leitner wrote:
> Hi,
> 
> I was reviewing driver sources and found that
> ethtool ops holds rtnl_lock() and there are few
> drivers (for example: tg3, bnx2) that use napi_disable()
> in this context.
[...]
> The msleep() above will preempt.  I believe this is wrong.
[...]
> What am I missing?

The RTNL lock is a mutex so it's OK to sleep (but preferably not very
long) while holding it.

Ben.

-- 
Ben Hutchings, Senior Software Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


^ 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