Netdev List
 help / color / mirror / Atom feed
* [PATCH 2.6.18 2/6] bnx2: Allow WoL settings on new 5708 chips
From: Michael Chan @ 2006-06-13  0:17 UTC (permalink / raw)
  To: davem; +Cc: netdev

Allow WOL settings on 5708 B2 and newer chips that have the problem
fixed.

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


diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 1a5f7a8..49c09da 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -5642,7 +5642,9 @@ bnx2_init_board(struct pci_dev *pdev, st
 		}
 	}
 
-	if (CHIP_NUM(bp) == CHIP_NUM_5708)
+	if ((CHIP_ID(bp) == CHIP_ID_5708_A0) ||
+	    (CHIP_ID(bp) == CHIP_ID_5708_B0) ||
+	    (CHIP_ID(bp) == CHIP_ID_5708_B1))
 		bp->flags |= NO_WOL_FLAG;
 
 	if (CHIP_ID(bp) == CHIP_ID_5706_A0) {



^ permalink raw reply related

* [PATCH 2.6.18 1/6] bnx2: Add an rx drop counter
From: Michael Chan @ 2006-06-13  0:17 UTC (permalink / raw)
  To: davem; +Cc: netdev

Add a counter for packets dropped by firmware.

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


diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 7a1fb52..1a5f7a8 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -4034,6 +4034,8 @@ bnx2_timer(unsigned long data)
 	msg = (u32) ++bp->fw_drv_pulse_wr_seq;
 	REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_PULSE_MB, msg);
 
+	bp->stats_blk->stat_FwRxDrop = REG_RD_IND(bp, BNX2_FW_RX_DROP_COUNT);
+
 	if ((bp->phy_flags & PHY_SERDES_FLAG) &&
 	    (CHIP_NUM(bp) == CHIP_NUM_5706)) {
 
@@ -4504,6 +4506,10 @@ bnx2_get_stats(struct net_device *dev)
 		net_stats->tx_aborted_errors +
 		net_stats->tx_carrier_errors;
 
+	net_stats->rx_missed_errors =
+		(unsigned long) (stats_blk->stat_IfInMBUFDiscards +
+		stats_blk->stat_FwRxDrop);
+
 	return net_stats;
 }
 
@@ -4986,7 +4992,7 @@ bnx2_set_rx_csum(struct net_device *dev,
 	return 0;
 }
 
-#define BNX2_NUM_STATS 45
+#define BNX2_NUM_STATS 46
 
 static struct {
 	char string[ETH_GSTRING_LEN];
@@ -5036,6 +5042,7 @@ static struct {
 	{ "rx_mac_ctrl_frames" },
 	{ "rx_filtered_packets" },
 	{ "rx_discards" },
+	{ "rx_fw_discards" },
 };
 
 #define STATS_OFFSET32(offset_name) (offsetof(struct statistics_block, offset_name) / 4)
@@ -5086,6 +5093,7 @@ static const unsigned long bnx2_stats_of
     STATS_OFFSET32(stat_MacControlFramesReceived),                    
     STATS_OFFSET32(stat_IfInFramesL2FilterDiscards),                  
     STATS_OFFSET32(stat_IfInMBUFDiscards),                            
+    STATS_OFFSET32(stat_FwRxDrop),
 };
 
 /* stat_IfHCInBadOctets and stat_Dot3StatsCarrierSenseErrors are
@@ -5096,7 +5104,7 @@ static u8 bnx2_5706_stats_len_arr[BNX2_N
 	4,0,4,4,4,4,4,4,4,4,
 	4,4,4,4,4,4,4,4,4,4,
 	4,4,4,4,4,4,4,4,4,4,
-	4,4,4,4,4,
+	4,4,4,4,4,4,
 };
 
 static u8 bnx2_5708_stats_len_arr[BNX2_NUM_STATS] = {
@@ -5104,7 +5112,7 @@ static u8 bnx2_5708_stats_len_arr[BNX2_N
 	4,4,4,4,4,4,4,4,4,4,
 	4,4,4,4,4,4,4,4,4,4,
 	4,4,4,4,4,4,4,4,4,4,
-	4,4,4,4,4,
+	4,4,4,4,4,4,
 };
 
 #define BNX2_NUM_TESTS 6
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index b87925f..ea1ab06 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -231,6 +231,7 @@ struct statistics_block {
 	u32 stat_GenStat13;
 	u32 stat_GenStat14;
 	u32 stat_GenStat15;
+	u32 stat_FwRxDrop;
 };
 
 
@@ -3481,6 +3482,8 @@ struct l2_fhdr {
 
 #define BNX2_COM_SCRATCH				0x00120000
 
+#define BNX2_FW_RX_DROP_COUNT				 0x00120084
+
 
 /*
  *  cp_reg definition



^ permalink raw reply related

* Re: [PATCH 2.6.17-rc6] Remove Prism II support from Orinoco
From: Jesse Brandeburg @ 2006-06-13  0:10 UTC (permalink / raw)
  To: John W. Linville; +Cc: Faidon Liambotis, Dave Jones, netdev, proski, hermes
In-Reply-To: <20060612152434.GA14851@tuxdriver.com>

On 6/12/06, John W. Linville <linville@tuxdriver.com> wrote:
> On Mon, Jun 12, 2006 at 01:49:54AM +0300, Faidon Liambotis wrote:
>
> > Having two drivers supporting the same set of hardware seems pretty
> > pointless to me. Plus, it confuses hotplugging/automatic detection.
>
> This subject comes-up from time to time.  In fact, I'm pretty sure
> it came-up very recently w.r.t. orinoco and hostap.
>
> The consensus seems to be that drivers should have IDs for all devices
> they support, even if that means that some devices are supported by
> multiple drivers.  This leaves the choice of which driver to use in
> the hands of the user and/or distro.

my problem is that for my prism 2 adapter both drivers are loaded at
which point neither of them works.  I'm running FC5, and i have to
keep removing the orinoco*.ko files to keep them from loading, so I'm
all for this patch.

Jesse

^ permalink raw reply

* [RFC/PATCH 1/2] in-kernel sockets API
From: Sridhar Samudrala @ 2006-06-12 23:56 UTC (permalink / raw)
  To: netdev, linux-kernel

This patch makes it convenient to use the sockets API by the in-kernel
users like sunrpc, cifs & ocfs2 etc and any future users.
Currently they get to this API by directly accesing the function pointers
in the sock structure.

Most of these functions are pretty simple and can be made inline and moved
to linux/net.h.

I used kernel_ prefix for this API to match with the existing kernel_sendmsg
and kernel_recvmsg() although i would prefer ksock_.

I have updated sunrpc to use this API.

I would appreciate any comments or suggestions for improvements.

Thanks
Sridhar

diff --git a/include/linux/net.h b/include/linux/net.h
index 84a490e..b70c28f 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -208,6 +208,25 @@ extern int   	     kernel_recvmsg(struct
 				    struct kvec *vec, size_t num,
 				    size_t len, int flags);
 
+extern int kernel_bind(struct socket *sock, struct sockaddr *addr,
+		       int addrlen);
+extern int kernel_listen(struct socket *sock, int backlog);
+extern int kernel_accept(struct socket *sock, struct socket **newsock,
+			 int flags);
+extern int kernel_connect(struct socket *sock, struct sockaddr *addr,
+			  int addrlen, int flags);
+extern int kernel_getsockname(struct socket *sock, struct sockaddr *addr,
+			      int *addrlen);
+extern int kernel_getpeername(struct socket *sock, struct sockaddr *addr,
+			      int *addrlen);
+extern int kernel_getsockopt(struct socket *sock, int level, int optname,
+			     char *optval, int *optlen);
+extern int kernel_setsockopt(struct socket *sock, int level, int optname,
+			     char *optval, int optlen);
+extern int kernel_sendpage(struct socket *sock, struct page *page, int offset,
+			   size_t size, int flags);
+extern int kernel_ioctl(struct socket *sock, int cmd, unsigned long arg);
+
 #ifndef CONFIG_SMP
 #define SOCKOPS_WRAPPED(name) name
 #define SOCKOPS_WRAP(name, fam)
diff --git a/net/socket.c b/net/socket.c
index 02948b6..8f36be7 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -2160,6 +2160,109 @@ static long compat_sock_ioctl(struct fil
 }
 #endif
 
+int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
+{
+	return sock->ops->bind(sock, addr, addrlen);
+}
+
+int kernel_listen(struct socket *sock, int backlog)
+{
+	return sock->ops->listen(sock, backlog);
+}
+
+int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
+{
+	struct sock *sk = sock->sk;
+	int err;
+
+	err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
+			       newsock);	
+	if (err < 0)
+		goto done;	
+
+	err = sock->ops->accept(sock, *newsock, flags);
+	if (err < 0) {
+		sock_release(*newsock);
+		goto done;
+	}
+			
+	(*newsock)->ops = sock->ops;
+
+done:
+	return err;
+}
+
+int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
+                   int flags)
+{
+	return sock->ops->connect(sock, addr, addrlen, flags);
+}	
+
+int kernel_getsockname(struct socket *sock, struct sockaddr *addr,
+			 int *addrlen)
+{
+	return sock->ops->getname(sock, addr, addrlen, 0);
+}
+
+int kernel_getpeername(struct socket *sock, struct sockaddr *addr,
+			 int *addrlen)
+{
+	return sock->ops->getname(sock, addr, addrlen, 1);
+}
+
+int kernel_getsockopt(struct socket *sock, int level, int optname,
+			char *optval, int *optlen)
+{
+	mm_segment_t oldfs = get_fs();
+	int err;
+
+	set_fs(KERNEL_DS);
+	if (level == SOL_SOCKET)
+		err = sock_getsockopt(sock, level, optname, optval, optlen);
+	else
+		err = sock->ops->getsockopt(sock, level, optname, optval,
+					    optlen);
+	set_fs(oldfs);
+	return err;
+}
+
+int kernel_setsockopt(struct socket *sock, int level, int optname,
+			char *optval, int optlen)
+{
+	mm_segment_t oldfs = get_fs();
+	int err;
+
+	set_fs(KERNEL_DS);
+	if (level == SOL_SOCKET)
+		err = sock_setsockopt(sock, level, optname, optval, optlen);
+	else
+		err = sock->ops->setsockopt(sock, level, optname, optval,
+					    optlen);
+	set_fs(oldfs);
+	return err;
+}
+
+int kernel_sendpage(struct socket *sock, struct page *page, int offset,
+		    size_t size, int flags)
+{
+	if (sock->ops->sendpage)
+		return sock->ops->sendpage(sock, page, offset, size, flags);
+	
+	return sock_no_sendpage(sock, page, offset, size, flags);
+}
+
+int kernel_ioctl(struct socket *sock, int cmd, unsigned long arg)
+{
+	mm_segment_t oldfs = get_fs();
+	int err;
+
+	set_fs(KERNEL_DS);
+	err = sock->ops->ioctl(sock, cmd, arg);
+	set_fs(oldfs);
+	
+	return err;
+}
+
 /* ABI emulation layers need these two */
 EXPORT_SYMBOL(move_addr_to_kernel);
 EXPORT_SYMBOL(move_addr_to_user);
@@ -2176,3 +2279,13 @@ EXPORT_SYMBOL(sock_wake_async);
 EXPORT_SYMBOL(sockfd_lookup);
 EXPORT_SYMBOL(kernel_sendmsg);
 EXPORT_SYMBOL(kernel_recvmsg);
+EXPORT_SYMBOL(kernel_bind);
+EXPORT_SYMBOL(kernel_listen);
+EXPORT_SYMBOL(kernel_accept);
+EXPORT_SYMBOL(kernel_connect);
+EXPORT_SYMBOL(kernel_getsockname);
+EXPORT_SYMBOL(kernel_getpeername);
+EXPORT_SYMBOL(kernel_getsockopt);
+EXPORT_SYMBOL(kernel_setsockopt);
+EXPORT_SYMBOL(kernel_sendpage);
+EXPORT_SYMBOL(kernel_ioctl);



^ permalink raw reply related

* [RFC/PATCH 2/2] update sunrpc to use in-kernel sockets API
From: Sridhar Samudrala @ 2006-06-12 23:56 UTC (permalink / raw)
  To: netdev, linux-kernel

This patch updates sunrpc to use in-kernel sockets API.

Thanks
Sridhar

diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index a27905a..ee80b3c 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -388,7 +388,7 @@ svc_sendto(struct svc_rqst *rqstp, struc
 	/* send head */
 	if (slen == xdr->head[0].iov_len)
 		flags = 0;
-	len = sock->ops->sendpage(sock, rqstp->rq_respages[0], 0, xdr->head[0].iov_len, flags);
+	len = kernel_sendpage(sock, rqstp->rq_respages[0], 0, xdr->head[0].iov_len, flags);
 	if (len != xdr->head[0].iov_len)
 		goto out;
 	slen -= xdr->head[0].iov_len;
@@ -400,7 +400,7 @@ svc_sendto(struct svc_rqst *rqstp, struc
 	while (pglen > 0) {
 		if (slen == size)
 			flags = 0;
-		result = sock->ops->sendpage(sock, *ppage, base, size, flags);
+		result = kernel_sendpage(sock, *ppage, base, size, flags);
 		if (result > 0)
 			len += result;
 		if (result != size)
@@ -413,7 +413,7 @@ svc_sendto(struct svc_rqst *rqstp, struc
 	}
 	/* send tail */
 	if (xdr->tail[0].iov_len) {
-		result = sock->ops->sendpage(sock, rqstp->rq_respages[rqstp->rq_restailpage], 
+		result = kernel_sendpage(sock, rqstp->rq_respages[rqstp->rq_restailpage], 
 					     ((unsigned long)xdr->tail[0].iov_base)& (PAGE_SIZE-1),
 					     xdr->tail[0].iov_len, 0);
 
@@ -434,13 +434,10 @@ out:
 static int
 svc_recv_available(struct svc_sock *svsk)
 {
-	mm_segment_t	oldfs;
 	struct socket	*sock = svsk->sk_sock;
 	int		avail, err;
 
-	oldfs = get_fs(); set_fs(KERNEL_DS);
-	err = sock->ops->ioctl(sock, TIOCINQ, (unsigned long) &avail);
-	set_fs(oldfs);
+	err = kernel_ioctl(sock, TIOCINQ, (unsigned long) &avail);
 
 	return (err >= 0)? avail : err;
 }
@@ -472,7 +469,7 @@ svc_recvfrom(struct svc_rqst *rqstp, str
 	 * at accept time. FIXME
 	 */
 	alen = sizeof(rqstp->rq_addr);
-	sock->ops->getname(sock, (struct sockaddr *)&rqstp->rq_addr, &alen, 1);
+	kernel_getpeername(sock, (struct sockaddr *)&rqstp->rq_addr, &alen);
 
 	dprintk("svc: socket %p recvfrom(%p, %Zu) = %d\n",
 		rqstp->rq_sock, iov[0].iov_base, iov[0].iov_len, len);
@@ -758,7 +755,6 @@ svc_tcp_accept(struct svc_sock *svsk)
 	struct svc_serv	*serv = svsk->sk_server;
 	struct socket	*sock = svsk->sk_sock;
 	struct socket	*newsock;
-	const struct proto_ops *ops;
 	struct svc_sock	*newsvsk;
 	int		err, slen;
 
@@ -766,29 +762,23 @@ svc_tcp_accept(struct svc_sock *svsk)
 	if (!sock)
 		return;
 
-	err = sock_create_lite(PF_INET, SOCK_STREAM, IPPROTO_TCP, &newsock);
-	if (err) {
+	clear_bit(SK_CONN, &svsk->sk_flags);
+	err = kernel_accept(sock, &newsock, O_NONBLOCK);
+	if (err < 0) {
 		if (err == -ENOMEM)
 			printk(KERN_WARNING "%s: no more sockets!\n",
 			       serv->sv_name);
-		return;
-	}
-
-	dprintk("svc: tcp_accept %p allocated\n", newsock);
-	newsock->ops = ops = sock->ops;
-
-	clear_bit(SK_CONN, &svsk->sk_flags);
-	if ((err = ops->accept(sock, newsock, O_NONBLOCK)) < 0) {
-		if (err != -EAGAIN && net_ratelimit())
+		else if (err != -EAGAIN && net_ratelimit())
 			printk(KERN_WARNING "%s: accept failed (err %d)!\n",
 				   serv->sv_name, -err);
-		goto failed;		/* aborted connection or whatever */
+		return;
 	}
+
 	set_bit(SK_CONN, &svsk->sk_flags);
 	svc_sock_enqueue(svsk);
 
 	slen = sizeof(sin);
-	err = ops->getname(newsock, (struct sockaddr *) &sin, &slen, 1);
+	err = kernel_getpeername(newsock, (struct sockaddr *) &sin, &slen);
 	if (err < 0) {
 		if (net_ratelimit())
 			printk(KERN_WARNING "%s: peername failed (err %d)!\n",
@@ -1407,14 +1397,14 @@ svc_create_socket(struct svc_serv *serv,
 	if (sin != NULL) {
 		if (type == SOCK_STREAM)
 			sock->sk->sk_reuse = 1; /* allow address reuse */
-		error = sock->ops->bind(sock, (struct sockaddr *) sin,
+		error = kernel_bind(sock, (struct sockaddr *) sin,
 						sizeof(*sin));
 		if (error < 0)
 			goto bummer;
 	}
 
 	if (protocol == IPPROTO_TCP) {
-		if ((error = sock->ops->listen(sock, 64)) < 0)
+		if ((error = kernel_listen(sock, 64)) < 0)
 			goto bummer;
 	}
 
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 4b4e7df..c60b422 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -207,7 +207,7 @@ static inline int xs_sendpages(struct so
 		base &= ~PAGE_CACHE_MASK;
 	}
 
-	sendpage = sock->ops->sendpage ? : sock_no_sendpage;
+	sendpage = kernel_sendpage ? : sock_no_sendpage;
 	do {
 		int flags = XS_SENDMSG_FLAGS;
 
@@ -952,7 +952,7 @@ static int xs_bindresvport(struct rpc_xp
 
 	do {
 		myaddr.sin_port = htons(port);
-		err = sock->ops->bind(sock, (struct sockaddr *) &myaddr,
+		err = kernel_bind(sock, (struct sockaddr *) &myaddr,
 						sizeof(myaddr));
 		if (err == 0) {
 			xprt->port = port;
@@ -1047,7 +1047,7 @@ static void xs_tcp_reuse_connection(stru
 	 */
 	memset(&any, 0, sizeof(any));
 	any.sa_family = AF_UNSPEC;
-	result = sock->ops->connect(sock, &any, sizeof(any), 0);
+	result = kernel_connect(sock, &any, sizeof(any), 0);
 	if (result)
 		dprintk("RPC:      AF_UNSPEC connect return code %d\n",
 				result);
@@ -1117,7 +1117,7 @@ static void xs_tcp_connect_worker(void *
 	/* Tell the socket layer to start connecting... */
 	xprt->stat.connect_count++;
 	xprt->stat.connect_start = jiffies;
-	status = sock->ops->connect(sock, (struct sockaddr *) &xprt->addr,
+	status = kernel_connect(sock, (struct sockaddr *) &xprt->addr,
 			sizeof(xprt->addr), O_NONBLOCK);
 	dprintk("RPC: %p  connect status %d connected %d sock state %d\n",
 			xprt, -status, xprt_connected(xprt), sock->sk->sk_state);



^ permalink raw reply related

* Re: [RFT] Realtek 8168 ethernet support
From: Francois Romieu @ 2006-06-12 22:29 UTC (permalink / raw)
  To: Mourad De Clerck; +Cc: netdev
In-Reply-To: <448DE38D.8070503@aquazul.com>

Mourad De Clerck <mourad@aquazul.com> :
[...]
> I do notice a pattern with more and less "complicated"/cpu intensive
> traffic: using http (wget) I manage to finish doing the transfer of the
> same reasonably big file. With scp I only manage to get to 90% of that
> file before it freezes - I should still test whether I can get a http
> transfer to lock up if I use a (much) bigger file.

wget goes faster, right ? Do you have some vmstat 1 output at hand
for it ?

[...]
> > Unrelated: have you checked the link setting ?
> 
> ethtool reports "Link detected: yes" and so does my switch.

Ok but can you set correctly the link with the command which was told
to fail in you first mail ? The patch could fix it.

[...]
> shuttle:~# scp hell:/srv/bigfile.bin .
> bigfile.bin                                   90%  155MB  17.5MB/s   00:00 ETA

Can you try something like:
dd if=/dev/zero bs=1024k count=1000 | ssh -c blowfish hell dd of=/tmp/1000m.bin 

May I assume that the freeze locks everything (keyboard, mouse, led) beyond
the scp command itself ?

-- 
Ueimor

^ permalink raw reply

* Hi, milo maize
From: Myrna Pereira @ 2006-06-12 22:11 UTC (permalink / raw)
  To: netdev

Join and Play at the best Emperial zCASINOz!
As a Special Welcome TODAY, we will DOUBL your 1 Deposit up to 200 bucks!

For example:
Deposit 50 play with 100!
Deposit 100 play with 200!
And your FREE Bonuses will be INSTANTLY added to your acount!

Try us, inhere: 

http://EBR7I3.erprost.com/d1/today

==========
inverted spin, the gull bunt, the pinwheel.
unscrewed the  cap, and attached myself to it  like  a lamprey. I sat on the
     Then one day Jonathan, standing  on  the  shore,  closing  his  eyes,
hours unless he  can answer this question: 'How do you know you're sane?' ";
Tender.
==
     Still, it was easier for them to practice high  performance  than  it
     He spread out the  map on the windowsill, leaned on his hands, and bent
     "Why is it," Jonathan puzzled, "that the hardest thing in  the  world
==
     "Not bad. And  you?" He didn't answer. He hugged my neck, pressed me to
     The squawks and grockles of everyday life in the Flock were  cut  off
     I kicked him in  his bare  can and dove  into my  stall and locked  the



^ permalink raw reply

* Re: Using netconsole for debugging suspend/resume
From: Jeremy Fitzhardinge @ 2006-06-12 21:25 UTC (permalink / raw)
  To: Andi Kleen; +Cc: Mark Lord, Matt Mackall, Linux Kernel Mailing List, netdev
In-Reply-To: <200606121746.34880.ak@suse.de>

Andi Kleen wrote:
> On Monday 12 June 2006 17:38, Mark Lord wrote:
>   
>> Okay, so I'm daft.  But.. *what* is "it" ??
>>
>> We have two machines:  target (being debugged), and host (anything).
>> Sure, the target has to have ohci1394 loaded, and firescope running.
>> But what about the *other* end of the connection?  What commands?
>>     
>
> From the same manpage:
> "The raw1394 module must be loaded and its device node
>  be writable (this normally requires root)" 
>
> Ok it doesn't say you need ohci1394 too and doesn't say that's the target.
> If I do a new revision I'll perhaps expand the docs a bit.
>
> So load ohci1394/raw1394 and run firescope as root. Your distribution
> will hopefully take care of the device nodes. Usually you want 
> something like firescope -Au System.map  
>   

I think the confusion here is that the target doesn't need to be running 
anything; you can DMA chunks of memory with the OHCI controller with no 
need for any software support.  The debugger host is what's running 
firescope.

Unless I'm confused too, which is likely.  Andi, I think your docs 
should be more explicit about what runs where.

Also, the tricky bit for me is debugging resume; firescope still 
requires the OHCI device to come up to be useful, but I that's no 
different from using netconsole.

Neat stuff; I need to get my two firewire-enabled machines close enough 
to each other to try it out.

    J

^ permalink raw reply

* Re: [PATCH RFC] netpoll: don't spin forever sending to stopped queues
From: Jeremy Fitzhardinge @ 2006-06-12 21:20 UTC (permalink / raw)
  To: Matt Mackall; +Cc: Linux Kernel Mailing List, netdev
In-Reply-To: <20060612205310.GU24227@waste.org>

Matt Mackall wrote:
> Ahh, right. I forgot that I'd done that. Can you resend?
>   
I just respun it against 2.6.17-rc6-mm2.

    J


--

Subject: netpoll: don't spin forever sending to blocked queues

When transmitting a skb in netpoll_send_skb(), only retry a limited
number of times if the device queue is stopped.

Signed-off-by: Jeremy Fitzhardinge <jeremy@goop.org>

diff -r 0b8d3d4ee182 net/core/netpoll.c
--- a/net/core/netpoll.c	Mon Jun 12 13:46:23 2006 -0700
+++ b/net/core/netpoll.c	Mon Jun 12 13:48:34 2006 -0700
@@ -279,14 +279,10 @@ static void netpoll_send_skb(struct netp
 		 * network drivers do not expect to be called if the queue is
 		 * stopped.
 		 */
-		if (netif_queue_stopped(np->dev)) {
-			netif_tx_unlock(np->dev);
-			netpoll_poll(np);
-			udelay(50);
-			continue;
-		}
-
-		status = np->dev->hard_start_xmit(skb, np->dev);
+		status = NETDEV_TX_BUSY;
+		if (!netif_queue_stopped(np->dev))
+			status = np->dev->hard_start_xmit(skb, np->dev);
+
 		netif_tx_unlock(np->dev);
 
 		/* success */



^ permalink raw reply

* Re: [PATCH RFC] netpoll: don't spin forever sending to stopped queues
From: Matt Mackall @ 2006-06-12 20:53 UTC (permalink / raw)
  To: Jeremy Fitzhardinge; +Cc: Linux Kernel Mailing List, netdev
In-Reply-To: <448DD556.6030705@goop.org>

On Mon, Jun 12, 2006 at 01:57:58PM -0700, Jeremy Fitzhardinge wrote:
> Matt Mackall wrote:
> >On Thu, Jun 08, 2006 at 07:15:50PM -0700, Jeremy Fitzhardinge wrote:
> >  
> >>Here's a patch.  I haven't tested it beyond compiling it, and I don't 
> >>know if it is actually correct.  In this case, it seems pointless to 
> >>spin waiting for an even which will never happen.  Should 
> >>netif_poll_disable() cause netpoll_send_skb() (or something) to not even 
> >>bother trying to send?  netif_poll_disable seems mysteriously simple to 
> >>me.
> >>
> >>   J
> >>    
> >
> >Did this work for you at all?
> >  
> 
> No, it didn't appear to help; I get the same symptom.  I think fix is 
> correct (in that its better than what was there before), but there's 
> probably more going on in my case.  I haven't looked into it more deeply 
> yet.  I suspect there's another netpoll code path which is spinning 
> forever on an XOFFed queue.
> 
> >>When transmitting a skb in netpoll_send_skb(), only retry a limited
> >>number of times if the device queue is stopped.
> >>    
> >
> >Where limited = once?
> >  
> 
> No, it reuses the existing retry logic.  It retries 20000 times with a 
> 50us pause between attempts, so up to a second.  This seems excessive to 
> me; I don't know where those original numbers came from.  I tried 5000 
> retries, but it didn't make any difference to my case.

Ahh, right. I forgot that I'd done that. Can you resend?

-- 
Mathematics is the supreme nostalgia of our time.

^ permalink raw reply

* Re: [PATCH RFC] netpoll: don't spin forever sending to stopped queues
From: Jeremy Fitzhardinge @ 2006-06-12 20:57 UTC (permalink / raw)
  To: Matt Mackall; +Cc: Linux Kernel Mailing List, netdev
In-Reply-To: <20060611200407.GG24227@waste.org>

Matt Mackall wrote:
> On Thu, Jun 08, 2006 at 07:15:50PM -0700, Jeremy Fitzhardinge wrote:
>   
>> Here's a patch.  I haven't tested it beyond compiling it, and I don't 
>> know if it is actually correct.  In this case, it seems pointless to 
>> spin waiting for an even which will never happen.  Should 
>> netif_poll_disable() cause netpoll_send_skb() (or something) to not even 
>> bother trying to send?  netif_poll_disable seems mysteriously simple to me.
>>
>>    J
>>     
>
> Did this work for you at all?
>   

No, it didn't appear to help; I get the same symptom.  I think fix is 
correct (in that its better than what was there before), but there's 
probably more going on in my case.  I haven't looked into it more deeply 
yet.  I suspect there's another netpoll code path which is spinning 
forever on an XOFFed queue.

>> When transmitting a skb in netpoll_send_skb(), only retry a limited
>> number of times if the device queue is stopped.
>>     
>
> Where limited = once?
>   

No, it reuses the existing retry logic.  It retries 20000 times with a 
50us pause between attempts, so up to a second.  This seems excessive to 
me; I don't know where those original numbers came from.  I tried 5000 
retries, but it didn't make any difference to my case.

    J

^ permalink raw reply

* Re: [PATCH 2.6.17-rc6] Remove Prism II support from Orinoco
From: Dave Jones @ 2006-06-12 20:55 UTC (permalink / raw)
  To: Faidon Liambotis; +Cc: John W. Linville, netdev, proski, hermes
In-Reply-To: <20060612153958.GA6719@divinity>

On Mon, Jun 12, 2006 at 06:39:58PM +0300, Faidon Liambotis wrote:
 
 > FWIW, I think we've experienced a similar situation like this in the
 > past in the networking land and the consensus was to completely remove
 > the other driver. I'm referring to e100/eepro100, of course.

The difference with e100/eepro100, was that there the interface
name remained constant regardless of which driver you were using,
which isn't the case with orinoco->hostap.

		Dave

-- 
http://www.codemonkey.org.uk

^ permalink raw reply

* New Qlogic qla3xxx NIC Driver v2.02.00k31 for upstream inclusion
From: Ron Mercer @ 2006-06-12 20:33 UTC (permalink / raw)
  To: jeff; +Cc: linux-driver, netdev

Jeff,

Please find the Qlogic qla3xxx Ethernet driver posted at the URL below.
This is a complementary network driver for our ISP4XXX parts.
There is a concurrent effort underway to get the iSCSI driver (qla4xxx)
integrated upstream as well.

I have been through several iterations with the linux-netdev list and
have had much response from Stephen Hemminger. In his last response he
suggested I submit the driver to you.

This submission is contained in a patch file that does the following:

Adds:
drivers/net/qla3xxx.c
drivers/net/qla3xxx.h

Modifies:
MAINTAINERS
drivers/net/Makefile
drivers/net/Kconfig

Patch file qla3xxxpatch1-v2.02.00-k31.txt is at the following link:

ftp://ftp.qlogic.com/outgoing/linux/network/upstream/2.02.00k31/qla3xxxp
atch1-v2.02.00-k31.txt


Some notes on the driver/hardware:

- Built and tested using kernel 2.6.17-rc4.
- The chip supports two ethernet and two iSCSI functions.
- The functions ql_sem_lock, ql_sem_spinlock, ql_sem_unlock, and
ql_wait_for_drvr_lock are used to protect resources that are shared
across the network and iSCSI functions.  This protection is mostly
during chip initialization and resets, but also include link management.
- The PHY/MII are not exported through ethtool due to the fact that the
iSCSI function will control the common link at least 50% of the time.



Regards,

Ron Mercer
Qlogic Corporation

^ permalink raw reply

* Your future, mortgage broker
From: Leah Horner @ 2006-06-12 20:18 UTC (permalink / raw)
  To: netdev

Even if you have no erectin problems SOFT CIAzLIS 
would help you to make BETTER SE  X MORE OFTEN!
and to bring  unimagnable plesure to her.

Just disolve half a pil under your tongue 
and get ready for action in 15 minutes. 

The tests showed that the majority of men 
after taking this medic ation were able to have 
PERFECT ER ECTI ON during 36 hours!

VISIT US, AND GET OUR SPECIAL 70% DISC OUNT OFER!

http://hlbeuu.mistnear.net/?23325044

==========
Gray-feathered backs were turned upon Jonathan from  that  moment  onward,
spot. To be honest, I could have gotten by with seven, but I  threw one just
at the base of the cliff, in the center  of  the  whole  Flock  assembled.
used to  be the town dump was under us. And  I  felt a light  breeze. Except
when I'm going to appear out of thin air on your beach,  and  show  you  a
discoveries--that's not my field."

on the join-up..."
the whole thing-just  emptiness and more emptiness,  thin  air. And for  all

^ permalink raw reply

* Re: MIB "ipInHdrErrors" error
From: David Miller @ 2006-06-12 20:10 UTC (permalink / raw)
  To: weid; +Cc: netdev
In-Reply-To: <1150102163.2974.9.camel@L-tech>

From: Wei Dong <weid@nanjing-fnst.com>
Date: Mon, 12 Jun 2006 16:49:23 +0800

> On Mon, 2006-06-12 at 15:24 +0800, Wei Dong wrote:
> > > Also, when kernel receives an IP packet and need to forward, but
> > > TTL=1 or TTL=0, kernel just sends an ICMP packet to inform the
> > > sender TTL count exceeded, and doesn't increase this counter.
> > 
> > This part of your change seems correct, please just resubmit
> > this part.
> The following is the latest patch for MIB ipIHdrErrors. 

Patch applied, thanks a lot.

^ permalink raw reply

* Re: [patch] undo AF_UNIX _bh locking changes and split lock-type instead
From: David Miller @ 2006-06-12 20:08 UTC (permalink / raw)
  To: mingo
  Cc: akpm, Valdis.Kletnieks, herbert, netdev, linux-kernel, stefanr,
	jirislaby, linux1394-devel, mingo, arjan
In-Reply-To: <20060612084936.GA29516@elte.hu>

From: Ingo Molnar <mingo@elte.hu>
Date: Mon, 12 Jun 2006 10:49:36 +0200

> Subject: undo AF_UNIX _bh locking changes and split lock-type
> From: Ingo Molnar <mingo@elte.hu>
> 
> this cleans up lock-validator-special-locking-af_unix.patch: instead
> of adding _bh locking to AF_UNIX, this patch splits their
> sk_receive_queue.lock type from the other networking skb-queue locks.
> 
> Signed-off-by: Ingo Molnar <mingo@elte.hu>

Signed-off-by: David S. Miller <davem@davemloft.net>

^ permalink raw reply

* Re: [PATCH 3/12] d80211: separate allocation of ieee80211_local
From: John W. Linville @ 2006-06-12 19:52 UTC (permalink / raw)
  To: Jiri Benc; +Cc: David S. Miller, netdev
In-Reply-To: <20060612213523.473a9714@griffin.suse.cz>

On Mon, Jun 12, 2006 at 09:35:23PM +0200, Jiri Benc wrote:
> On Thu,  8 Jun 2006 09:49:07 +0200 (CEST), Jiri Benc wrote:
> > ieee80211_local has a separate class_device. That means it has reference
> > counting independent of master net_device and can be freed at a different
> > time, therefore these two structures cannot be allocated together.
> > 
> > Solve this by adding ieee80211_ptr pointer to net_device structure (similar
> > to other pointers already presented there) and using it as a pointer to
> > independently allocated ieee80211_local.
> 
> I suppose approval from Dave will be needed for adding that pointer to
> net_device, right?

Ulitmately, yes. :-)

John
-- 
John W. Linville
linville@tuxdriver.com

^ permalink raw reply

* Re: [PATCH 5/5] bcm43xx-d80211: fix sending of fragments
From: Michael Buesch @ 2006-06-12 19:35 UTC (permalink / raw)
  To: Jiri Benc; +Cc: John W. Linville, netdev
In-Reply-To: <20060612191606.7AA8E48391@silver.suse.cz>

On Monday 12 June 2006 21:16, Jiri Benc wrote:
> This makes fragmentation work with bcm43xx.
> 
> Signed-off-by: Jiri Benc <jbenc@suse.cz>

Signed-off-by: Michael Buesch <mb@bu3sch.de>

The other patch will get my sign-off tomorrow (I think modified, though).
I don't have time to look at it more close, now.

> ---
>  drivers/net/wireless/d80211/bcm43xx/bcm43xx_dma.c |    2 +-
>  drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.c |    2 +-
>  2 files changed, 2 insertions(+), 2 deletions(-)
> 
> --- dscape.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_dma.c
> +++ dscape/drivers/net/wireless/d80211/bcm43xx/bcm43xx_dma.c
> @@ -703,7 +703,7 @@ static int dma_tx_fragment(struct bcm43x
>  	bcm43xx_generate_txhdr(ring->bcm,
>  			       (struct bcm43xx_txhdr *)hdr_skb->data,
>  			       skb->data, skb->len,
> -			       1,//FIXME
> +			       ctl->first_fragment,
>  			       generate_cookie(ring, slot),
>  			       ctl);
>  
> --- dscape.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.c
> +++ dscape/drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.c
> @@ -183,7 +183,7 @@ static void pio_tx_write_fragment(struct
>  	assert(skb_shinfo(skb)->nr_frags == 0);
>  	bcm43xx_generate_txhdr(queue->bcm,
>  			       &txhdr, skb->data, skb->len,
> -			       1,//FIXME
> +			       packet->ctl->first_fragment,
>  			       generate_cookie(queue, pio_txpacket_getindex(packet)),
>  			       packet->ctl);
>  
> 

-- 
Greetings Michael.

^ permalink raw reply

* Re: [PATCH 3/12] d80211: separate allocation of ieee80211_local
From: Jiri Benc @ 2006-06-12 19:35 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev, John W. Linville
In-Reply-To: <20060608074907.2CB5B48391@silver.suse.cz>

On Thu,  8 Jun 2006 09:49:07 +0200 (CEST), Jiri Benc wrote:
> ieee80211_local has a separate class_device. That means it has reference
> counting independent of master net_device and can be freed at a different
> time, therefore these two structures cannot be allocated together.
> 
> Solve this by adding ieee80211_ptr pointer to net_device structure (similar
> to other pointers already presented there) and using it as a pointer to
> independently allocated ieee80211_local.

I suppose approval from Dave will be needed for adding that pointer to
net_device, right?

> [...]
>  include/linux/netdevice.h    |    1 
>  net/d80211/ieee80211.c       |  100 +++++++++++++++++++++---------------------
>  net/d80211/ieee80211_dev.c   |   17 +++++++
>  net/d80211/ieee80211_i.h     |    9 +++-
>  net/d80211/ieee80211_iface.c |   20 ++++----
>  net/d80211/ieee80211_ioctl.c |   92 +++++++++++++++++++--------------------
>  net/d80211/ieee80211_proc.c  |    6 +--
>  net/d80211/ieee80211_scan.c  |   10 ++--
>  net/d80211/ieee80211_sta.c   |   58 ++++++++++++------------
>  net/d80211/ieee80211_sysfs.c |   26 ++++++++---
>  net/d80211/rate_control.c    |    4 +-
>  net/d80211/rate_control.h    |    4 +-
>  net/d80211/wme.c             |   26 +++++------
>  13 files changed, 206 insertions(+), 167 deletions(-)
> 
> [...]
> --- a/include/linux/netdevice.h
> +++ b/include/linux/netdevice.h
> @@ -371,6 +371,7 @@ #define NETIF_F_UFO             8192    
>  	void                    *ip6_ptr;       /* IPv6 specific data */
>  	void			*ec_ptr;	/* Econet specific data	*/
>  	void			*ax25_ptr;	/* AX.25 specific data */
> +	void			*ieee80211_ptr;	/* IEEE 802.11 specific data */
>  
>  /*
>   * Cache line mostly used on receive path (including eth_type_trans())
> [...]

Thanks,

-- 
Jiri Benc
SUSE Labs

^ permalink raw reply

* [PATCH] Make in-kernel hostap less annoying
From: Kyle McMartin @ 2006-06-12 19:13 UTC (permalink / raw)
  To: jkmaline; +Cc: netdev

Most user don't want their kern.log/dmesg filled with
debugging gibberish, and could turn it on if prompted.

( Example:
wifi0: TXEXC - status=0x0004 ([Discon]) tx_control=000c
retry_count=0 tx_rate=0 fc=0x0108 (Data::0 ToDS)
A1=00:0f:66:43:d7:0a A2=00:05:3c:06:63:01 A3=33:33:00:00:00:16 
A4=00:00:00:00:00:00 )


Also make hostap default to managed mode, instead of master mode, which
has bitten a few users expecting it to behave like the orinoco driver
it is replacing.

Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>

---
Two minor things I've been carrying around in my personal tree
for quite some time. (This is only relevant to the in-kernel driver,
I see no reason to change the out-of-tree driver.)

Cheers,
Kyle

diff --git a/drivers/net/wireless/hostap/hostap_config.h b/drivers/net/wireless/hostap/hostap_config.h
index c090a5a..bc51fa9 100644
--- a/drivers/net/wireless/hostap/hostap_config.h
+++ b/drivers/net/wireless/hostap/hostap_config.h
@@ -38,7 +38,7 @@ #endif
  */
 
 /* Do not include debug messages into the driver */
-/* #define PRISM2_NO_DEBUG */
+#define PRISM2_NO_DEBUG
 
 /* Do not include /proc/net/prism2/wlan#/{registers,debug} */
 /* #define PRISM2_NO_PROCFS_DEBUG */
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
index 328e9a1..57438e8 100644
--- a/drivers/net/wireless/hostap/hostap_hw.c
+++ b/drivers/net/wireless/hostap/hostap_hw.c
@@ -70,7 +70,7 @@ static char essid[33] = "test";
 module_param_string(essid, essid, sizeof(essid), 0444);
 MODULE_PARM_DESC(essid, "Host AP's ESSID");
 
-static int iw_mode[MAX_PARM_DEVICES] = { IW_MODE_MASTER, DEF_INTS };
+static int iw_mode[MAX_PARM_DEVICES] = { IW_MODE_INFRA, DEF_INTS };
 module_param_array(iw_mode, int, NULL, 0444);
 MODULE_PARM_DESC(iw_mode, "Initial operation mode");
 

^ permalink raw reply related

* [PATCH 5/5] bcm43xx-d80211: fix sending of fragments
From: Jiri Benc @ 2006-06-12 19:16 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville, Michael Buesch
In-Reply-To: <20060612211454.409884000.midnight@suse.cz>

This makes fragmentation work with bcm43xx.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_dma.c |    2 +-
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.c |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

--- dscape.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_dma.c
+++ dscape/drivers/net/wireless/d80211/bcm43xx/bcm43xx_dma.c
@@ -703,7 +703,7 @@ static int dma_tx_fragment(struct bcm43x
 	bcm43xx_generate_txhdr(ring->bcm,
 			       (struct bcm43xx_txhdr *)hdr_skb->data,
 			       skb->data, skb->len,
-			       1,//FIXME
+			       ctl->first_fragment,
 			       generate_cookie(ring, slot),
 			       ctl);
 
--- dscape.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.c
+++ dscape/drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.c
@@ -183,7 +183,7 @@ static void pio_tx_write_fragment(struct
 	assert(skb_shinfo(skb)->nr_frags == 0);
 	bcm43xx_generate_txhdr(queue->bcm,
 			       &txhdr, skb->data, skb->len,
-			       1,//FIXME
+			       packet->ctl->first_fragment,
 			       generate_cookie(queue, pio_txpacket_getindex(packet)),
 			       packet->ctl);
 

^ permalink raw reply

* [PATCH 4/5] d80211: add first_fragment flag to ieee80211_tx_control
From: Jiri Benc @ 2006-06-12 19:16 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville, Michael Buesch
In-Reply-To: <20060612211454.409884000.midnight@suse.cz>

If a driver needs to find out if the fragment it is supposed to pass to the
hardware is the first fragment, the only way to do this is to check if
a Fragment Number part of seq_ctrl field in the frame header equals to 0.
Let's make it easier.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---
 include/net/d80211.h   |    2 ++
 net/d80211/ieee80211.c |    2 ++
 2 files changed, 4 insertions(+)

--- dscape.orig/include/net/d80211.h
+++ dscape/include/net/d80211.h
@@ -158,6 +158,8 @@ struct ieee80211_tx_control {
 	unsigned int rate_ctrl_probe:1;
 	unsigned int clear_dst_mask:1;
 	unsigned int requeue:1;
+	unsigned int first_fragment:1;	/* This is a first fragment of the
+					 * frame */
 	 /* following three flags are only used with Atheros Super A/G */
 	unsigned int compress:1;
 	unsigned int turbo_prime_notify:1; /* notify HostaAPd after frame
--- dscape.orig/net/d80211/ieee80211.c
+++ dscape/net/d80211/ieee80211.c
@@ -1120,6 +1120,7 @@ __ieee80211_tx_prepare(struct ieee80211_
 		u8 *pos = &skb->data[hdrlen + sizeof(rfc1042_header)];
 		tx->ethertype = (pos[0] << 8) | pos[1];
 	}
+	control->first_fragment = 1;
 
 }
 
@@ -1190,6 +1191,7 @@ static int __ieee80211_tx(struct ieee802
 		control->use_rts_cts = 0;
 		control->use_cts_protect = 0;
 		control->clear_dst_mask = 0;
+		control->first_fragment = 0;
 		for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
 			if (!tx->u.tx.extra_frag[i])
 				continue;

^ permalink raw reply

* [PATCH 3/5] d80211: handle full queue when sending fragments
From: Jiri Benc @ 2006-06-12 19:16 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville, Michael Buesch
In-Reply-To: <20060612211454.409884000.midnight@suse.cz>

When the queue gets filled up while sending fragments, do not discard the
frame.

Partially sent frames are stored in a buffer in ieee80211_local (there is
place for one frame for each queue there). When the space in hw queue gets
available again, stored frame for that queue is sent first.

Also, the case when driver returns NETDEV_TX_BUSY is handled properly now.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---
 net/d80211/ieee80211.c   |  229 +++++++++++++++++++++++++++++++++++++----------
 net/d80211/ieee80211_i.h |   14 ++
 net/d80211/wme.c         |    5 -
 3 files changed, 199 insertions(+), 49 deletions(-)

--- dscape.orig/net/d80211/ieee80211.c
+++ dscape/net/d80211/ieee80211.c
@@ -1153,6 +1153,74 @@ static void inline ieee80211_tx_prepare(
 	__ieee80211_tx_prepare(tx, skb, dev, control);
 }
 
+static inline int __ieee80211_queue_stopped(struct ieee80211_local *local,
+					    int queue)
+{
+	return test_bit(IEEE80211_LINK_STATE_XOFF, &local->state[queue]);
+}
+
+static inline int __ieee80211_queue_pending(struct ieee80211_local *local,
+					    int queue)
+{
+	return test_bit(IEEE80211_LINK_STATE_PENDING, &local->state[queue]);
+}
+
+#define IEEE80211_TX_OK		0
+#define IEEE80211_TX_AGAIN	1
+#define IEEE80211_TX_FRAG_AGAIN	2
+
+static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb,
+			  struct ieee80211_txrx_data *tx)
+{
+	struct ieee80211_tx_control *control = tx->u.tx.control;
+	int ret, i;
+
+	if (skb) {
+		ieee80211_dump_frame(local->mdev->name, "TX to low-level driver", skb);
+		ret = local->hw->tx(local->mdev, skb, control);
+		if (ret)
+			return IEEE80211_TX_AGAIN;
+#ifdef IEEE80211_LEDS
+		if (local->tx_led_counter++ == 0) {
+			ieee80211_tx_led(1, local->mdev);
+		}
+#endif /* IEEE80211_LEDS */
+	}
+	if (tx->u.tx.extra_frag) {
+		control->use_rts_cts = 0;
+		control->use_cts_protect = 0;
+		control->clear_dst_mask = 0;
+		for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
+			if (!tx->u.tx.extra_frag[i])
+				continue;
+			if (__ieee80211_queue_stopped(local, control->queue))
+				return IEEE80211_TX_FRAG_AGAIN;
+			if (i == tx->u.tx.num_extra_frag) {
+				control->tx_rate = tx->u.tx.last_frag_hwrate;
+				control->rateidx = tx->u.tx.last_frag_rateidx;
+				control->rate_ctrl_probe =
+					tx->u.tx.probe_last_frag;
+			}
+
+			ieee80211_dump_frame(local->mdev->name,
+					     "TX to low-level driver", skb);
+			ret = local->hw->tx(local->mdev, tx->u.tx.extra_frag[i],
+					    control);
+			if (ret)
+				return IEEE80211_TX_FRAG_AGAIN;
+#ifdef IEEE80211_LEDS
+			if (local->tx_led_counter++ == 0) {
+				ieee80211_tx_led(1, local->mdev);
+			}
+#endif /* IEEE80211_LEDS */
+			tx->u.tx.extra_frag[i] = NULL;
+		}
+		kfree(tx->u.tx.extra_frag);
+		tx->u.tx.extra_frag = NULL;
+	}
+	return IEEE80211_TX_OK;
+}
+
 static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb,
 			struct ieee80211_tx_control *control, int mgmt)
 {
@@ -1163,6 +1231,8 @@ static int ieee80211_tx(struct net_devic
 	ieee80211_txrx_result res = TXRX_DROP;
         int ret, i;
 
+	WARN_ON(__ieee80211_queue_pending(local, control->queue));
+
 	if (unlikely(skb->len < 10)) {
 		dev_kfree_skb(skb);
 		return 0;
@@ -1193,65 +1263,60 @@ static int ieee80211_tx(struct net_devic
 		return 0;
 	}
 
-	ieee80211_dump_frame(local->mdev->name, "TX to low-level driver", skb);
-	ret = local->hw->tx(local->mdev, skb, control);
-#ifdef IEEE80211_LEDS
-	if (!ret && local->tx_led_counter++ == 0) {
-                ieee80211_tx_led(1, dev);
-        }
-#endif /* IEEE80211_LEDS */
 	if (tx.u.tx.extra_frag) {
-		if (ret > 0) {
-			/* Must free all fragments and return 0 since skb data
-			 * has been fragmented into multiple buffers.
-			 * TODO: could free extra fragments and restore skb to
-			 * the original form since the data is still there and
-			 * then return nonzero so that Linux netif would
-			 * retry. */
-			goto drop;
-		}
-
-		skb = NULL; /* skb is now owned by low-level driver */
-		control->use_rts_cts = 0;
-		control->use_cts_protect = 0;
-		control->clear_dst_mask = 0;
 		for (i = 0; i < tx.u.tx.num_extra_frag; i++) {
 			int next_len, dur;
 			struct ieee80211_hdr *hdr =
 				(struct ieee80211_hdr *)
 				tx.u.tx.extra_frag[i]->data;
-			if (i + 1 < tx.u.tx.num_extra_frag)
+
+			if (i + 1 < tx.u.tx.num_extra_frag) {
 				next_len = tx.u.tx.extra_frag[i + 1]->len;
-			else {
+			} else {
 				next_len = 0;
 				tx.u.tx.rate = tx.u.tx.last_frag_rate;
-				tx.u.tx.control->tx_rate = tx.u.tx.rate->val;
-				tx.u.tx.control->rateidx =
-					tx.u.tx.last_frag_rateidx;
-				tx.u.tx.control->rate_ctrl_probe =
-					tx.u.tx.probe_last_frag;
+				tx.u.tx.last_frag_hwrate = tx.u.tx.rate->val;
 			}
 			dur = ieee80211_duration(&tx, 0, next_len);
 			hdr->duration_id = cpu_to_le16(dur);
-
-			ieee80211_dump_frame(local->mdev->name,
-					     "TX to low-level driver", skb);
-			ret = local->hw->tx(local->mdev, tx.u.tx.extra_frag[i],
-					    control);
-			if (ret > 0)
-				goto drop;
-#ifdef IEEE80211_LEDS
-			if (local->tx_led_counter++ == 0) {
-                                ieee80211_tx_led(1, dev);
-                        }
-#endif /* IEEE80211_LEDS */
-			tx.u.tx.extra_frag[i] = NULL;
 		}
-		kfree(tx.u.tx.extra_frag);
-        }
-        if (ret == -1)
-		ret = 0;
-	return ret;
+	}
+
+retry:
+	ret = __ieee80211_tx(local, skb, &tx);
+	if (ret) {
+		struct ieee80211_tx_stored_packet *store =
+			&local->pending_packet[control->queue];
+
+		if (ret == IEEE80211_TX_FRAG_AGAIN)
+			skb = NULL;
+		set_bit(IEEE80211_LINK_STATE_PENDING,
+			&local->state[control->queue]);
+		smp_mb();
+		/* When the driver gets out of buffers during sending of
+		 * fragments and calls ieee80211_stop_queue, there is
+		 * a small window between IEEE80211_LINK_STATE_XOFF and
+		 * IEEE80211_LINK_STATE_PENDING flags are set. If a buffer
+		 * gets available in that window (i.e. driver calls
+		 * ieee80211_wake_queue), we would end up with ieee80211_tx
+		 * called with IEEE80211_LINK_STATE_PENDING. Prevent this by
+		 * continuing transmitting here when that situation is
+		 * possible to have happened. */
+		if (!__ieee80211_queue_stopped(local, control->queue)) {
+			clear_bit(IEEE80211_LINK_STATE_PENDING,
+				  &local->state[control->queue]);
+			goto retry;
+		}
+		memcpy(&store->control, control,
+		       sizeof(struct ieee80211_tx_control));
+		store->skb = skb;
+		store->extra_frag = tx.u.tx.extra_frag;
+		store->num_extra_frag = tx.u.tx.num_extra_frag;
+		store->last_frag_hwrate = tx.u.tx.last_frag_hwrate;
+		store->last_frag_rateidx = tx.u.tx.last_frag_rateidx;
+		store->last_frag_rate_ctrl_probe = tx.u.tx.probe_last_frag;
+	}
+	return 0;
 
  drop:
 	if (skb)
@@ -1263,6 +1328,62 @@ static int ieee80211_tx(struct net_devic
 	return 0;
 }
 
+static void ieee80211_tx_pending(unsigned long data)
+{
+	struct ieee80211_local *local = (struct ieee80211_local *)data;
+	struct net_device *dev = local->mdev;
+	struct ieee80211_tx_stored_packet *store;
+	struct ieee80211_txrx_data tx;
+	int i, ret, reschedule = 0;
+
+	spin_lock_bh(&dev->xmit_lock);
+	dev->xmit_lock_owner = smp_processor_id();
+	for (i = 0; i < local->hw->queues; i++) {
+		if (__ieee80211_queue_stopped(local, i))
+			continue;
+		if (!__ieee80211_queue_pending(local, i)) {
+			reschedule = 1;
+			continue;
+		}
+		store = &local->pending_packet[i];
+		tx.u.tx.control = &store->control;
+		tx.u.tx.extra_frag = store->extra_frag;
+		tx.u.tx.num_extra_frag = store->num_extra_frag;
+		tx.u.tx.last_frag_hwrate = store->last_frag_hwrate;
+		tx.u.tx.last_frag_rateidx = store->last_frag_rateidx;
+		tx.u.tx.probe_last_frag = store->last_frag_rate_ctrl_probe;
+		ret = __ieee80211_tx(local, store->skb, &tx);
+		if (ret) {
+			if (ret == IEEE80211_TX_FRAG_AGAIN)
+				store->skb = NULL;
+		} else {
+			clear_bit(IEEE80211_LINK_STATE_PENDING,
+				  &local->state[i]);
+			reschedule = 1;
+		}
+	}
+	dev->xmit_lock_owner = -1;
+	spin_unlock_bh(&dev->xmit_lock);
+	if (reschedule)
+		netif_schedule(dev);
+}
+
+static void ieee80211_clear_tx_pending(struct ieee80211_local *local)
+{
+	int i, j;
+	struct ieee80211_tx_stored_packet *store;
+
+	for (i = 0; i < local->hw->queues; i++) {
+		if (!__ieee80211_queue_pending(local, i))
+			continue;
+		store = &local->pending_packet[i];
+		kfree_skb(store->skb);
+		for (j = 0; j < store->num_extra_frag; j++)
+			kfree_skb(store->extra_frag[j]);
+		kfree(store->extra_frag);
+		clear_bit(IEEE80211_LINK_STATE_PENDING, &local->state[i]);
+	}
+}
 
 static int ieee80211_master_start_xmit(struct sk_buff *skb,
 				       struct net_device *dev)
@@ -1999,6 +2120,7 @@ static int ieee80211_master_open(struct 
 	list_for_each_entry(sdata, &local->sub_if_list, list) {
 		if (sdata->dev != dev && netif_running(sdata->dev)) {
 			res = 0;
+			tasklet_enable(&local->tx_pending_tasklet);
 			break;
 		}
 	}
@@ -2010,6 +2132,7 @@ static int ieee80211_master_stop(struct 
 	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_sub_if_data *sdata;
 
+	tasklet_disable(&local->tx_pending_tasklet);
 	list_for_each_entry(sdata, &local->sub_if_list, list) {
 		if (sdata->dev != dev && netif_running(sdata->dev))
 			return -EOPNOTSUPP;
@@ -4175,6 +4298,10 @@ struct net_device *ieee80211_alloc_hw(si
         sdata->local = local;
         list_add_tail(&sdata->list, &local->sub_if_list);
 
+	tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending,
+		     (unsigned long)local);
+	tasklet_disable(&local->tx_pending_tasklet);
+
         tasklet_init(&local->tasklet,
 		     ieee80211_tasklet_handler,
 		     (unsigned long) local);
@@ -4344,6 +4471,7 @@ void ieee80211_unregister_hw(struct net_
 	}
 	rtnl_unlock();
 
+	ieee80211_clear_tx_pending(local);
 	sta_info_stop(local);
 	rate_control_remove_attrs(local, local->rate_ctrl_priv,
 				  &local->class_dev.kobj);
@@ -4426,8 +4554,13 @@ void ieee80211_wake_queue(struct net_dev
 	struct ieee80211_local *local = dev->ieee80211_ptr;
 
 	if (test_and_clear_bit(IEEE80211_LINK_STATE_XOFF,
-			       &local->state[queue]))
-		__netif_schedule(dev);
+			       &local->state[queue])) {
+		if (test_bit(IEEE80211_LINK_STATE_PENDING,
+			     &local->state[queue]))
+			tasklet_schedule(&local->tx_pending_tasklet);
+		else
+			__netif_schedule(dev);
+	}
 }
 
 void ieee80211_stop_queue(struct net_device *dev, int queue)
--- dscape.orig/net/d80211/ieee80211_i.h
+++ dscape/net/d80211/ieee80211_i.h
@@ -125,6 +125,7 @@ struct ieee80211_txrx_data {
 			 * when using CTS protection with IEEE 802.11g. */
 			struct ieee80211_rate *last_frag_rate;
 			int last_frag_rateidx;
+			int last_frag_hwrate;
 			int mgmt_interface;
 
 			/* Extra fragments (in addition to the first fragment
@@ -155,6 +156,16 @@ struct ieee80211_tx_packet_data {
 	unsigned int mgmt_iface:1;
 };
 
+struct ieee80211_tx_stored_packet {
+	struct ieee80211_tx_control control;
+	struct sk_buff *skb;
+	int num_extra_frag;
+	struct sk_buff **extra_frag;
+	int last_frag_rateidx;
+	int last_frag_hwrate;
+	unsigned int last_frag_rate_ctrl_probe:1;
+};
+
 struct ieee80211_passive_scan {
         unsigned int in_scan:1; /* this must be cleared before calling
 				 * netif_oper(WAKEUP) */
@@ -354,6 +365,8 @@ struct ieee80211_local {
 	struct timer_list sta_cleanup;
 
 	unsigned long state[NUM_TX_DATA_QUEUES];
+	struct ieee80211_tx_stored_packet pending_packet[NUM_TX_DATA_QUEUES];
+	struct tasklet_struct tx_pending_tasklet;
 
 	int mc_count;	/* total count of multicast entries in all interfaces */
 	int iff_allmultis, iff_promiscs;
@@ -518,6 +531,7 @@ struct ieee80211_local {
 
 enum ieee80211_link_state_t {
 	IEEE80211_LINK_STATE_XOFF = 0,
+	IEEE80211_LINK_STATE_PENDING,
 };
 
 struct sta_attribute {
--- dscape.orig/net/d80211/wme.c
+++ dscape/net/d80211/wme.c
@@ -323,7 +323,10 @@ static struct sk_buff *wme_qdiscop_deque
 	/* check all the h/w queues in numeric/priority order */
 	for (queue = 0; queue < hw->queues; queue++) {
 		/* see if there is room in this hardware queue */
-		if (test_bit(IEEE80211_LINK_STATE_XOFF, &local->state[queue]))
+		if (test_bit(IEEE80211_LINK_STATE_XOFF,
+			     &local->state[queue]) ||
+		    test_bit(IEEE80211_LINK_STATE_PENDING,
+			     &local->state[queue]))
 			continue;
 
 		/* there is space - try and get a frame */

^ permalink raw reply

* [PATCH 1/5] d80211: per-queue TX flow control
From: Jiri Benc @ 2006-06-12 19:16 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville, Michael Buesch
In-Reply-To: <20060612211454.409884000.midnight@suse.cz>

Currently, before a packet is passed to the driver, the driver is asked
about status of its TX queues (i.e. how many packets are queued in each
queue and how large are queues).

This is different from the way generic networking works in Linux and it
doesn't allow easy implementation of resubmitting fragments to the driver
when the queue gets filled up during transmitting.

This patch changes the stack not to ask driver about queue status but
require driver to do TX flow control.

Please note that this breaks drivers.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---
 include/net/d80211.h     |   30 ++++++++++++++++++++++++++++++
 net/d80211/ieee80211.c   |   27 +++++++++++++++++++++++++++
 net/d80211/ieee80211_i.h |    6 ++++++
 net/d80211/wme.c         |    6 +-----
 4 files changed, 64 insertions(+), 5 deletions(-)

--- dscape.orig/include/net/d80211.h
+++ dscape/include/net/d80211.h
@@ -781,6 +781,7 @@ int ieee80211_get_hdrlen(u16 fc);
  * netdevices for each hardware device. The low-level driver does not "see"
  * these interfaces, so it should use this function to perform netif
  * operations on all interface. */
+/* This function is deprecated. */
 typedef enum {
 	NETIF_ATTACH, NETIF_DETACH, NETIF_START, NETIF_STOP, NETIF_WAKE,
 	NETIF_IS_STOPPED, NETIF_UPDATE_TX_START
@@ -788,6 +789,35 @@ typedef enum {
 int ieee80211_netif_oper(struct net_device *dev, Netif_Oper op);
 
 /**
+ * ieee80211_wake_queue - wake specific queue
+ * @dev: pointer to &struct net_device as obtained from
+ *	ieee80211_alloc_hw().
+ * @queue: queue number (counted from zero).
+ *
+ * Drivers should use this function instead of netif_wake_queue.
+ */
+void ieee80211_wake_queue(struct net_device *dev, int queue);
+
+/**
+ * ieee80211_stop_queue - stop specific queue
+ * @dev: pointer to &struct net_device as obtained from
+ *	ieee80211_alloc_hw().
+ * @queue: queue number (counted from zero).
+ *
+ * Drivers should use this function instead of netif_stop_queue.
+ */
+void ieee80211_stop_queue(struct net_device *dev, int queue);
+
+/**
+ * ieee80211_start_queues - start all queues
+ * @dev: pointer to &struct net_device as obtained from
+ *	ieee80211_alloc_hw().
+ *
+ * Drivers should use this function instead of netif_start_queue.
+ */
+void ieee80211_start_queues(struct net_device *dev);
+
+/**
  * ieee80211_get_mc_list_item - iteration over items in multicast list
  * @dev: pointer to &struct net_device as obtained from
  *	ieee80211_alloc_hw().
--- dscape.orig/net/d80211/ieee80211.c
+++ dscape/net/d80211/ieee80211.c
@@ -4421,6 +4421,30 @@ int ieee80211_netif_oper(struct net_devi
         return 0;
 }
 
+void ieee80211_wake_queue(struct net_device *dev, int queue)
+{
+	struct ieee80211_local *local = dev->ieee80211_ptr;
+
+	if (test_and_clear_bit(IEEE80211_LINK_STATE_XOFF,
+			       &local->state[queue]))
+		__netif_schedule(dev);
+}
+
+void ieee80211_stop_queue(struct net_device *dev, int queue)
+{
+	struct ieee80211_local *local = dev->ieee80211_ptr;
+
+	set_bit(IEEE80211_LINK_STATE_XOFF, &local->state[queue]);
+}
+
+void ieee80211_start_queues(struct net_device *dev)
+{
+	struct ieee80211_local *local = dev->ieee80211_ptr;
+	int i;
+
+	for (i = 0; i < local->hw->queues; i++)
+		clear_bit(IEEE80211_LINK_STATE_XOFF, &local->state[i]);
+}
 
 void * ieee80211_dev_hw_data(struct net_device *dev)
 {
@@ -4548,6 +4572,9 @@ EXPORT_SYMBOL(ieee80211_tx_status);
 EXPORT_SYMBOL(ieee80211_beacon_get);
 EXPORT_SYMBOL(ieee80211_get_buffered_bc);
 EXPORT_SYMBOL(ieee80211_netif_oper);
+EXPORT_SYMBOL(ieee80211_wake_queue);
+EXPORT_SYMBOL(ieee80211_stop_queue);
+EXPORT_SYMBOL(ieee80211_start_queues);
 EXPORT_SYMBOL(ieee80211_dev_hw_data);
 EXPORT_SYMBOL(ieee80211_dev_stats);
 EXPORT_SYMBOL(ieee80211_get_hw_conf);
--- dscape.orig/net/d80211/ieee80211_i.h
+++ dscape/net/d80211/ieee80211_i.h
@@ -353,6 +353,8 @@ struct ieee80211_local {
 	struct sta_info *sta_hash[STA_HASH_SIZE];
 	struct timer_list sta_cleanup;
 
+	unsigned long state[NUM_TX_DATA_QUEUES];
+
 	int mc_count;	/* total count of multicast entries in all interfaces */
 	int iff_allmultis, iff_promiscs;
 			/* number of interfaces with corresponding IFF_ flags */
@@ -514,6 +516,10 @@ struct ieee80211_local {
 	int user_space_mlme;
 };
 
+enum ieee80211_link_state_t {
+	IEEE80211_LINK_STATE_XOFF = 0,
+};
+
 struct sta_attribute {
 	struct attribute attr;
 	ssize_t (*show)(const struct sta_info *, char *buf);
--- dscape.orig/net/d80211/wme.c
+++ dscape/net/d80211/wme.c
@@ -316,18 +316,14 @@ static struct sk_buff *wme_qdiscop_deque
 	struct net_device *dev = qd->dev;
 	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_hw *hw = local->hw;
-	struct ieee80211_tx_queue_stats stats;
 	struct sk_buff *skb;
 	struct Qdisc *qdisc;
 	int queue;
 
-	/* find which hardware queues have space in them */
-	hw->get_tx_stats(dev, &stats);
-
 	/* check all the h/w queues in numeric/priority order */
 	for (queue = 0; queue < hw->queues; queue++) {
 		/* see if there is room in this hardware queue */
-		if (stats.data[queue].len >= stats.data[queue].limit)
+		if (test_bit(IEEE80211_LINK_STATE_XOFF, &local->state[queue]))
 			continue;
 
 		/* there is space - try and get a frame */

^ permalink raw reply

* [incomplete 2/5] bcm43xx-d80211: per-queue TX flow control
From: Jiri Benc @ 2006-06-12 19:16 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville, Michael Buesch
In-Reply-To: <20060612211454.409884000.midnight@suse.cz>

This is an attempt to fix bcm43xx driver. It is for DMA mode only and
incomplete even for that mode - ieee80211_hw->tx() callback should return
NETDEV_TX_* constants which is not completely fixed by this patch.

---
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_dma.c  |    6 +++++-
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c |    1 +
 2 files changed, 6 insertions(+), 1 deletion(-)

--- dscape.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_dma.c
+++ dscape/drivers/net/wireless/d80211/bcm43xx/bcm43xx_dma.c
@@ -778,13 +778,16 @@ int bcm43xx_dma_tx(struct bcm43xx_privat
 		 * recognizes if the device queue is full and does
 		 * not send data anymore.
 		 */
+		ieee80211_stop_queue(bcm->net_dev, 0);
 		printk(KERN_ERR PFX "DMA queue overflow\n");
-		return -ENOMEM;
+		return NETDEV_TX_BUSY;
 	}
 
 	err = dma_tx_fragment(ring, skb, ctl);
 	if (likely(!err))
 		ring->nr_tx_packets++;
+	if (free_slots(ring) < SLOTS_PER_PACKET)
+		ieee80211_stop_queue(bcm->net_dev, 0);
 
 	return err;
 }
@@ -833,6 +836,7 @@ void bcm43xx_dma_handle_xmitstatus(struc
 		slot = next_slot(ring, slot);
 	}
 	bcm->stats.last_tx = jiffies;
+	ieee80211_wake_queue(bcm->net_dev, 0);
 }
 
 void bcm43xx_dma_get_tx_stats(struct bcm43xx_private *bcm,
--- dscape.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
+++ dscape/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
@@ -3737,6 +3737,7 @@ static int bcm43xx_init_board(struct bcm
 	bcm43xx_security_init(bcm);
 	bcm43xx_measure_channel_change_time(bcm);
 	ieee80211_update_hw(bcm->net_dev, bcm->ieee);
+	ieee80211_start_queues(bcm->net_dev);
 	ieee80211_netif_oper(bcm->net_dev, NETIF_ATTACH);
 	ieee80211_netif_oper(bcm->net_dev, NETIF_START);
 	ieee80211_netif_oper(bcm->net_dev, NETIF_WAKE);

^ 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