Netdev List
 help / color / mirror / Atom feed
* [PATCH 2/5] inet_diag: Add the SKMEMINFO extension
From: Pavel Emelyanov @ 2011-12-29 14:13 UTC (permalink / raw)
  To: David Miller, Linux Netdev List

Signed-off-by: Pavel Emelyanov <xemul@parallels.com>

---
 include/linux/inet_diag.h |    3 ++-
 net/ipv4/inet_diag.c      |    4 ++++
 2 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/include/linux/inet_diag.h b/include/linux/inet_diag.h
index afa5d5c..34e8d52 100644
--- a/include/linux/inet_diag.h
+++ b/include/linux/inet_diag.h
@@ -108,9 +108,10 @@ enum {
 	INET_DIAG_CONG,
 	INET_DIAG_TOS,
 	INET_DIAG_TCLASS,
+	INET_DIAG_SKMEMINFO,
 };
 
-#define INET_DIAG_MAX INET_DIAG_TCLASS
+#define INET_DIAG_MAX INET_DIAG_SKMEMINFO
 
 
 /* INET_DIAG_MEM */
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index fb2e47f..2240a8e 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -136,6 +136,10 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
 		minfo->idiag_tmem = sk_wmem_alloc_get(sk);
 	}
 
+	if (ext & (1 << (INET_DIAG_SKMEMINFO - 1)))
+		if (sock_diag_put_meminfo(sk, skb, INET_DIAG_SKMEMINFO))
+			goto rtattr_failure;
+
 	if (icsk == NULL) {
 		r->idiag_rqueue = r->idiag_wqueue = 0;
 		goto out;
-- 
1.5.5.6

^ permalink raw reply related

* [PATCH 3/5] unix_diag: Add the MEMINFO extension
From: Pavel Emelyanov @ 2011-12-29 14:13 UTC (permalink / raw)
  To: David Miller, Linux Netdev List

Signed-off-by: Pavel Emelyanov <xemul@parallels.com>

---
 include/linux/unix_diag.h |    2 ++
 net/unix/diag.c           |    4 ++++
 2 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/include/linux/unix_diag.h b/include/linux/unix_diag.h
index 3f7afb0..5255f51 100644
--- a/include/linux/unix_diag.h
+++ b/include/linux/unix_diag.h
@@ -16,6 +16,7 @@ struct unix_diag_req {
 #define UDIAG_SHOW_PEER		0x00000004	/* show peer socket info */
 #define UDIAG_SHOW_ICONS	0x00000008	/* show pending connections */
 #define UDIAG_SHOW_RQLEN	0x00000010	/* show skb receive queue len */
+#define UDIAG_SHOW_MEMINFO	0x00000020	/* show memory info of a socket */
 
 struct unix_diag_msg {
 	__u8	udiag_family;
@@ -33,6 +34,7 @@ enum {
 	UNIX_DIAG_PEER,
 	UNIX_DIAG_ICONS,
 	UNIX_DIAG_RQLEN,
+	UNIX_DIAG_MEMINFO,
 
 	UNIX_DIAG_MAX,
 };
diff --git a/net/unix/diag.c b/net/unix/diag.c
index c5bdbcb..9517bdd 100644
--- a/net/unix/diag.c
+++ b/net/unix/diag.c
@@ -146,6 +146,10 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct unix_diag_r
 			sk_diag_show_rqlen(sk, skb))
 		goto nlmsg_failure;
 
+	if ((req->udiag_show & UDIAG_SHOW_MEMINFO) &&
+			sock_diag_put_meminfo(sk, skb, UNIX_DIAG_MEMINFO))
+		goto nlmsg_failure;
+
 	nlh->nlmsg_len = skb_tail_pointer(skb) - b;
 	return skb->len;
 
-- 
1.5.5.6

^ permalink raw reply related

* [PATCH 4/5] af_unix: Move CINQ/COUTQ code to helpers
From: Pavel Emelyanov @ 2011-12-29 14:14 UTC (permalink / raw)
  To: David Miller, Linux Netdev List

Currently tcp diag reports rqlen and wqlen values similar to how
the CINQ/COUTQ iotcls do. To make unix diag report these values 
in the same way move the respective code into helpers.

Signed-off-by: Pavel Emelyanov <xemul@parallels.com>

---
 include/net/af_unix.h |    3 ++
 net/unix/af_unix.c    |   59 +++++++++++++++++++++++++++++-------------------
 2 files changed, 39 insertions(+), 23 deletions(-)

diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index 63b1781..5a4e29b 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -66,6 +66,9 @@ struct unix_sock {
 
 #define peer_wait peer_wq.wait
 
+long unix_inq_len(struct sock *sk);
+long unix_outq_len(struct sock *sk);
+
 #ifdef CONFIG_SYSCTL
 extern int unix_sysctl_register(struct net *net);
 extern void unix_sysctl_unregister(struct net *net);
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index e1b9358..f7ee7db 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -2065,6 +2065,36 @@ static int unix_shutdown(struct socket *sock, int mode)
 	return 0;
 }
 
+long unix_inq_len(struct sock *sk)
+{
+	struct sk_buff *skb;
+	long amount = 0;
+
+	if (sk->sk_state == TCP_LISTEN)
+		return -EINVAL;
+
+	spin_lock(&sk->sk_receive_queue.lock);
+	if (sk->sk_type == SOCK_STREAM ||
+			sk->sk_type == SOCK_SEQPACKET) {
+		skb_queue_walk(&sk->sk_receive_queue, skb)
+			amount += skb->len;
+	} else {
+		skb = skb_peek(&sk->sk_receive_queue);
+		if (skb)
+			amount = skb->len;
+	}
+	spin_unlock(&sk->sk_receive_queue.lock);
+
+	return amount;
+}
+EXPORT_SYMBOL_GPL(unix_inq_len);
+
+long unix_outq_len(struct sock *sk)
+{
+	return sk_wmem_alloc_get(sk);
+}
+EXPORT_SYMBOL_GPL(unix_outq_len);
+
 static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
 	struct sock *sk = sock->sk;
@@ -2073,33 +2103,16 @@ static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 
 	switch (cmd) {
 	case SIOCOUTQ:
-		amount = sk_wmem_alloc_get(sk);
+		amount = unix_outq_len(sk);
 		err = put_user(amount, (int __user *)arg);
 		break;
 	case SIOCINQ:
-		{
-			struct sk_buff *skb;
-
-			if (sk->sk_state == TCP_LISTEN) {
-				err = -EINVAL;
-				break;
-			}
-
-			spin_lock(&sk->sk_receive_queue.lock);
-			if (sk->sk_type == SOCK_STREAM ||
-			    sk->sk_type == SOCK_SEQPACKET) {
-				skb_queue_walk(&sk->sk_receive_queue, skb)
-					amount += skb->len;
-			} else {
-				skb = skb_peek(&sk->sk_receive_queue);
-				if (skb)
-					amount = skb->len;
-			}
-			spin_unlock(&sk->sk_receive_queue.lock);
+		amount = unix_inq_len(sk);
+		if (amount < 0)
+			err = amount;
+		else
 			err = put_user(amount, (int __user *)arg);
-			break;
-		}
-
+		break;
 	default:
 		err = -ENOIOCTLCMD;
 		break;
-- 
1.5.5.6

^ permalink raw reply related

* [PATCH 5/5] unix_diag: Fixup RQLEN extenstion report
From: Pavel Emelyanov @ 2011-12-29 14:15 UTC (permalink / raw)
  To: David Miller, Linux Netdev List

While it's not too late fix the recently added RQLEN diag extension
to report rqlen and wqlen in the same way as TCP does.

I.e. for listening sockets the ack backlog length (which is the input
queue length for socket) in rqlen and the max ack backlog length in
wqlen, and what the CINQ/OUTQ ioctls do for established.

Signed-off-by: Pavel Emelyanov <xemul@parallels.com>

---
 include/linux/unix_diag.h |    5 +++++
 net/unix/diag.c           |   13 ++++++++++++-
 2 files changed, 17 insertions(+), 1 deletions(-)

diff --git a/include/linux/unix_diag.h b/include/linux/unix_diag.h
index 5255f51..68ecc8f 100644
--- a/include/linux/unix_diag.h
+++ b/include/linux/unix_diag.h
@@ -44,4 +44,9 @@ struct unix_diag_vfs {
 	__u32	udiag_vfs_dev;
 };
 
+struct unix_diag_rqlen {
+	__u32	udiag_rqueue;
+	__u32	udiag_wqueue;
+};
+
 #endif
diff --git a/net/unix/diag.c b/net/unix/diag.c
index 9517bdd..9eb63a4 100644
--- a/net/unix/diag.c
+++ b/net/unix/diag.c
@@ -101,7 +101,18 @@ rtattr_failure:
 
 static int sk_diag_show_rqlen(struct sock *sk, struct sk_buff *nlskb)
 {
-	RTA_PUT_U32(nlskb, UNIX_DIAG_RQLEN, sk->sk_receive_queue.qlen);
+	struct unix_diag_rqlen *rql;
+
+	rql = UNIX_DIAG_PUT(nlskb, UNIX_DIAG_RQLEN, sizeof(*rql));
+
+	if (sk->sk_state == TCP_LISTEN) {
+		rql->udiag_rqueue = sk->sk_receive_queue.qlen;
+		rql->udiag_wqueue = sk->sk_max_ack_backlog;
+	} else {
+		rql->udiag_rqueue = (__u32)unix_inq_len(sk);
+		rql->udiag_wqueue = (__u32)unix_outq_len(sk);
+	}
+
 	return 0;
 
 rtattr_failure:
-- 
1.5.5.6

^ permalink raw reply related

* Re: [PATCH 1/1] via-rhine: Fix hanging with high CPU load on low-end broads.
From: Francois Romieu @ 2011-12-29 15:39 UTC (permalink / raw)
  To: Bjarke Istrup Pedersen
  Cc: David Miller, shemminger, bhutchings, linux-kernel, netdev, rl
In-Reply-To: <CACPM=kXOddA+T6vQPijR6sh8x5cMO=4baKGeKxEmMKG896Lz4g@mail.gmail.com>

Bjarke Istrup Pedersen <gurligebis@gentoo.org> :
> 2011/12/28 David Miller <davem@davemloft.net>:
[...]
> > This "shut off only some interrupts" scheme is just asking for trouble.
> 
> I agree, it's an ugly hack :)
> 
> Is there some way I can help with this, without having to touch the
> code? (C isn't my strong language, especially not kernel mode code) :)

Feel free to try the extra "new year's eve week end is getting closer"
patch below (against net-next).

You have been warned.

diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c
index 5c4983b..6350a2c 100644
--- a/drivers/net/ethernet/via/via-rhine.c
+++ b/drivers/net/ethernet/via/via-rhine.c
@@ -42,7 +42,8 @@
 
 #define DEBUG
 static int debug = 1;	/* 1 normal messages, 0 quiet .. 7 verbose. */
-static int max_interrupt_work = 20;
+#define RHINE_MSG_DEFAULT \
+        (NETIF_MSG_INTR)
 
 /* Set the copy breakpoint for the copy-only-tiny-frames scheme.
    Setting to > 1518 effectively disables this feature. */
@@ -128,11 +129,9 @@ MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("VIA Rhine PCI Fast Ethernet driver");
 MODULE_LICENSE("GPL");
 
-module_param(max_interrupt_work, int, 0);
 module_param(debug, int, 0);
 module_param(rx_copybreak, int, 0);
 module_param(avoid_D3, bool, 0);
-MODULE_PARM_DESC(max_interrupt_work, "VIA Rhine maximum events handled per interrupt");
 MODULE_PARM_DESC(debug, "VIA Rhine debug level (0-7)");
 MODULE_PARM_DESC(rx_copybreak, "VIA Rhine copy breakpoint for copy-only-tiny-frames");
 MODULE_PARM_DESC(avoid_D3, "Avoid power state D3 (work-around for broken BIOSes)");
@@ -351,16 +350,25 @@ static const int mmio_verify_registers[] = {
 
 /* Bits in the interrupt status/mask registers. */
 enum intr_status_bits {
-	IntrRxDone=0x0001, IntrRxErr=0x0004, IntrRxEmpty=0x0020,
-	IntrTxDone=0x0002, IntrTxError=0x0008, IntrTxUnderrun=0x0210,
-	IntrPCIErr=0x0040,
-	IntrStatsMax=0x0080, IntrRxEarly=0x0100,
-	IntrRxOverflow=0x0400, IntrRxDropped=0x0800, IntrRxNoBuf=0x1000,
-	IntrTxAborted=0x2000, IntrLinkChange=0x4000,
-	IntrRxWakeUp=0x8000,
-	IntrNormalSummary=0x0003, IntrAbnormalSummary=0xC260,
-	IntrTxDescRace=0x080000,	/* mapped from IntrStatus2 */
-	IntrTxErrSummary=0x082218,
+	IntrRxDone	= 0x0001,
+	IntrTxDone	= 0x0002,
+	IntrRxErr	= 0x0004,
+	IntrTxError	= 0x0008,
+	IntrRxEmpty	= 0x0020,
+	IntrPCIErr	= 0x0040,
+	IntrStatsMax	= 0x0080,
+	IntrRxEarly	= 0x0100,
+	IntrTxUnderrun	= 0x0210,
+	IntrRxOverflow	= 0x0400,
+	IntrRxDropped	= 0x0800,
+	IntrRxNoBuf	= 0x1000,
+	IntrTxAborted	= 0x2000,
+	IntrLinkChange	= 0x4000,
+	IntrRxWakeUp	= 0x8000,
+	IntrTxDescRace		= 0x080000,	/* mapped from IntrStatus2 */
+	IntrNormalSummary	= IntrRxDone | IntrTxDone,
+	IntrTxErrSummary	= IntrTxDescRace | IntrTxAborted | IntrTxError |
+				  IntrTxUnderrun,
 };
 
 /* Bits in WOLcrSet/WOLcrClr and PwrcsrSet/PwrcsrClr */
@@ -439,8 +447,12 @@ struct rhine_private {
 	struct net_device *dev;
 	struct napi_struct napi;
 	spinlock_t lock;
+	struct mutex task_lock;
+	struct work_struct slow_event_task;
 	struct work_struct reset_task;
 
+	u32 msg_enable;
+
 	/* Frequently used values: keep some adjacent for cache effect. */
 	u32 quirks;
 	struct rx_desc *rx_head_desc;
@@ -482,7 +494,6 @@ static netdev_tx_t rhine_start_tx(struct sk_buff *skb,
 static irqreturn_t rhine_interrupt(int irq, void *dev_instance);
 static void rhine_tx(struct net_device *dev);
 static int rhine_rx(struct net_device *dev, int limit);
-static void rhine_error(struct net_device *dev, int intr_status);
 static void rhine_set_rx_mode(struct net_device *dev);
 static struct net_device_stats *rhine_get_stats(struct net_device *dev);
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -497,6 +508,8 @@ static void rhine_set_cam_mask(void __iomem *ioaddr, u32 mask);
 static void rhine_set_vlan_cam_mask(void __iomem *ioaddr, u32 mask);
 static void rhine_init_cam_filter(struct net_device *dev);
 static void rhine_update_vcam(struct net_device *dev);
+static void rhine_slow_event_task(struct work_struct *work);
+static void rhine_restart_tx(struct net_device *dev);
 
 #define RHINE_WAIT_FOR(condition)				\
 do {								\
@@ -508,7 +521,7 @@ do {								\
 			1024 - i, __func__, __LINE__);		\
 } while (0)
 
-static inline u32 get_intr_status(struct net_device *dev)
+static u32 get_intr_status(struct net_device *dev)
 {
 	struct rhine_private *rp = netdev_priv(dev);
 	void __iomem *ioaddr = rp->base;
@@ -521,6 +534,16 @@ static inline u32 get_intr_status(struct net_device *dev)
 	return intr_status;
 }
 
+static void rhine_ack_event(struct rhine_private *rp, u32 mask)
+{
+	void __iomem *ioaddr = rp->base;
+
+	if (rp->quirks & rqStatusWBRace)
+		iowrite8(mask >> 16, ioaddr + IntrStatus2);
+	iowrite16(mask, ioaddr + IntrStatus);
+	mmiowb();
+}
+
 /*
  * Get power related registers into sane state.
  * Notify user about past WOL event.
@@ -657,23 +680,62 @@ static void rhine_poll(struct net_device *dev)
 }
 #endif
 
+#define RHINE_EVENT_NAPI_RX	(IntrRxDone | \
+				 IntrRxErr | \
+				 IntrRxEmpty | \
+				 IntrRxOverflow	| \
+				 IntrRxDropped | \
+				 IntrRxNoBuf | \
+				 IntrRxWakeUp)
+
+#define RHINE_EVENT_NAPI_TX_ERR	(IntrTxError | \
+				 IntrTxAborted | \
+				 IntrTxUnderrun | \
+				 IntrTxDescRace)
+#define RHINE_EVENT_NAPI_TX	(IntrTxDone | RHINE_EVENT_NAPI_TX_ERR)
+
+#define RHINE_EVENT_NAPI	(RHINE_EVENT_NAPI_RX | RHINE_EVENT_NAPI_TX)
+#define RHINE_EVENT_SLOW	(IntrPCIErr | IntrStatsMax | IntrLinkChange)
+#define RHINE_EVENT		(RHINE_EVENT_NAPI | RHINE_EVENT_SLOW)
+
 static int rhine_napipoll(struct napi_struct *napi, int budget)
 {
 	struct rhine_private *rp = container_of(napi, struct rhine_private, napi);
 	struct net_device *dev = rp->dev;
 	void __iomem *ioaddr = rp->base;
-	int work_done;
+	u16 enable_mask = RHINE_EVENT & 0xffff;
+	int work_done = 0;
+	u32 status;
+
+	status = get_intr_status(dev);
+	rhine_ack_event(rp, status & ~RHINE_EVENT_SLOW);
+
+	if (status & RHINE_EVENT_NAPI_RX)
+		work_done += rhine_rx(dev, budget);
+
+	if (status & RHINE_EVENT_NAPI_TX) {
+		if (status & RHINE_EVENT_NAPI_TX_ERR) {
+			/* Avoid scavenging before Tx engine turned off */
+			RHINE_WAIT_FOR(!(ioread8(ioaddr + ChipCmd) & CmdTxOn));
+			if (ioread8(ioaddr + ChipCmd) & CmdTxOn)
+				netif_warn(rp, tx_err, dev, "Tx still on\n");
+		}
+
+		rhine_tx(dev);
+
+		if (status & RHINE_EVENT_NAPI_TX_ERR)
+			rhine_restart_tx(dev);
+	}
 
-	work_done = rhine_rx(dev, budget);
+	if (status & RHINE_EVENT_SLOW) {
+		enable_mask &= ~RHINE_EVENT_SLOW;
+		schedule_work(&rp->slow_event_task);
+	}
 
 	if (work_done < budget) {
 		napi_complete(napi);
-
-		iowrite16(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow |
-			  IntrRxDropped | IntrRxNoBuf | IntrTxAborted |
-			  IntrTxDone | IntrTxError | IntrTxUnderrun |
-			  IntrPCIErr | IntrStatsMax | IntrLinkChange,
-			  ioaddr + IntrEnable);
+		iowrite16(enable_mask, ioaddr + IntrEnable);
+		mmiowb();
 	}
 	return work_done;
 }
@@ -797,6 +859,7 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
 	rp->quirks = quirks;
 	rp->pioaddr = pioaddr;
 	rp->pdev = pdev;
+	rp->msg_enable = netif_msg_init(-1, RHINE_MSG_DEFAULT);
 
 	rc = pci_request_regions(pdev, DRV_NAME);
 	if (rc)
@@ -856,7 +919,9 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
 	dev->irq = pdev->irq;
 
 	spin_lock_init(&rp->lock);
+	mutex_init(&rp->task_lock);
 	INIT_WORK(&rp->reset_task, rhine_reset_task);
+	INIT_WORK(&rp->slow_event_task, rhine_slow_event_task);
 
 	rp->mii_if.dev = dev;
 	rp->mii_if.mdio_read = mdio_read;
@@ -1310,12 +1375,7 @@ static void init_registers(struct net_device *dev)
 
 	napi_enable(&rp->napi);
 
-	/* Enable interrupts by setting the interrupt mask. */
-	iowrite16(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow |
-	       IntrRxDropped | IntrRxNoBuf | IntrTxAborted |
-	       IntrTxDone | IntrTxError | IntrTxUnderrun |
-	       IntrPCIErr | IntrStatsMax | IntrLinkChange,
-	       ioaddr + IntrEnable);
+	iowrite16(RHINE_EVENT & 0xffff, ioaddr + IntrEnable);
 
 	iowrite16(CmdStart | CmdTxOn | CmdRxOn | (Cmd1NoTxPoll << 8),
 	       ioaddr + ChipCmd);
@@ -1434,8 +1494,7 @@ static void rhine_reset_task(struct work_struct *work)
 						reset_task);
 	struct net_device *dev = rp->dev;
 
-	/* protect against concurrent rx interrupts */
-	disable_irq(rp->pdev->irq);
+	mutex_lock(&rp->task_lock);
 
 	napi_disable(&rp->napi);
 
@@ -1452,7 +1511,8 @@ static void rhine_reset_task(struct work_struct *work)
 	init_registers(dev);
 
 	spin_unlock_bh(&rp->lock);
-	enable_irq(rp->pdev->irq);
+
+	mutex_unlock(&rp->task_lock);
 
 	dev->trans_start = jiffies; /* prevent tx timeout */
 	dev->stats.tx_errors++;
@@ -1565,63 +1625,26 @@ static irqreturn_t rhine_interrupt(int irq, void *dev_instance)
 {
 	struct net_device *dev = dev_instance;
 	struct rhine_private *rp = netdev_priv(dev);
-	void __iomem *ioaddr = rp->base;
-	u32 intr_status;
-	int boguscnt = max_interrupt_work;
+	u32 status;
 	int handled = 0;
 
-	while ((intr_status = get_intr_status(dev))) {
-		handled = 1;
+	status = get_intr_status(dev);
 
-		/* Acknowledge all of the current interrupt sources ASAP. */
-		if (intr_status & IntrTxDescRace)
-			iowrite8(0x08, ioaddr + IntrStatus2);
-		iowrite16(intr_status & 0xffff, ioaddr + IntrStatus);
-		IOSYNC;
-
-		if (debug > 4)
-			netdev_dbg(dev, "Interrupt, status %08x\n",
-				   intr_status);
-
-		if (intr_status & (IntrRxDone | IntrRxErr | IntrRxDropped |
-				   IntrRxWakeUp | IntrRxEmpty | IntrRxNoBuf)) {
-			iowrite16(IntrTxAborted |
-				  IntrTxDone | IntrTxError | IntrTxUnderrun |
-				  IntrPCIErr | IntrStatsMax | IntrLinkChange,
-				  ioaddr + IntrEnable);
-
-			napi_schedule(&rp->napi);
-		}
+	netif_dbg(rp, intr, dev, "Interrupt, status %08x\n", status);
 
-		if (intr_status & (IntrTxErrSummary | IntrTxDone)) {
-			if (intr_status & IntrTxErrSummary) {
-				/* Avoid scavenging before Tx engine turned off */
-				RHINE_WAIT_FOR(!(ioread8(ioaddr+ChipCmd) & CmdTxOn));
-				if (debug > 2 &&
-				    ioread8(ioaddr+ChipCmd) & CmdTxOn)
-					netdev_warn(dev,
-						    "%s: Tx engine still on\n",
-						    __func__);
-			}
-			rhine_tx(dev);
-		}
+	if (status & RHINE_EVENT) {
+		handled = 1;
 
-		/* Abnormal error summary/uncommon events handlers. */
-		if (intr_status & (IntrPCIErr | IntrLinkChange |
-				   IntrStatsMax | IntrTxError | IntrTxAborted |
-				   IntrTxUnderrun | IntrTxDescRace))
-			rhine_error(dev, intr_status);
+		iowrite16(0x0000, rp->base + IntrEnable);
+		mmiowb();
+		napi_schedule(&rp->napi);
+	}
 
-		if (--boguscnt < 0) {
-			netdev_warn(dev, "Too much work at interrupt, status=%#08x\n",
-				    intr_status);
-			break;
-		}
+	if (status & ~(IntrLinkChange | IntrStatsMax | RHINE_EVENT_NAPI)) {
+		netif_err(rp, intr, dev, "Something Wicked happened! %08x\n",
+			  status);
 	}
 
-	if (debug > 3)
-		netdev_dbg(dev, "exiting interrupt, status=%08x\n",
-			   ioread16(ioaddr + IntrStatus));
 	return IRQ_RETVAL(handled);
 }
 
@@ -1632,8 +1655,6 @@ static void rhine_tx(struct net_device *dev)
 	struct rhine_private *rp = netdev_priv(dev);
 	int txstatus = 0, entry = rp->dirty_tx % TX_RING_SIZE;
 
-	spin_lock(&rp->lock);
-
 	/* find and cleanup dirty tx descriptors */
 	while (rp->dirty_tx != rp->cur_tx) {
 		txstatus = le32_to_cpu(rp->tx_ring[entry].tx_status);
@@ -1687,8 +1708,6 @@ static void rhine_tx(struct net_device *dev)
 	}
 	if ((rp->cur_tx - rp->dirty_tx) < TX_QUEUE_LEN - 4)
 		netif_wake_queue(dev);
-
-	spin_unlock(&rp->lock);
 }
 
 /**
@@ -1852,7 +1871,8 @@ static inline void clear_tally_counters(void __iomem *ioaddr)
 	ioread16(ioaddr + RxMissed);
 }
 
-static void rhine_restart_tx(struct net_device *dev) {
+static void rhine_restart_tx(struct net_device *dev)
+{
 	struct rhine_private *rp = netdev_priv(dev);
 	void __iomem *ioaddr = rp->base;
 	int entry = rp->dirty_tx % TX_RING_SIZE;
@@ -1880,8 +1900,7 @@ static void rhine_restart_tx(struct net_device *dev) {
 		iowrite8(ioread8(ioaddr + ChipCmd1) | Cmd1TxDemand,
 		       ioaddr + ChipCmd1);
 		IOSYNC;
-	}
-	else {
+	} else {
 		/* This should never happen */
 		if (debug > 1)
 			netdev_warn(dev, "%s() Another error occurred %08x\n",
@@ -1890,15 +1909,25 @@ static void rhine_restart_tx(struct net_device *dev) {
 
 }
 
-static void rhine_error(struct net_device *dev, int intr_status)
+static void rhine_slow_event_task(struct work_struct *work)
 {
-	struct rhine_private *rp = netdev_priv(dev);
+	struct rhine_private *rp =
+		container_of(work, struct rhine_private, slow_event_task);
+	struct net_device *dev = rp->dev;
 	void __iomem *ioaddr = rp->base;
+	u32 intr_status;
 
-	spin_lock(&rp->lock);
+	if (!netif_running(dev))
+		return;
+
+	mutex_lock(&rp->task_lock);
+
+	intr_status = get_intr_status(dev);
+	rhine_ack_event(rp, intr_status & RHINE_EVENT_SLOW);
 
 	if (intr_status & IntrLinkChange)
 		rhine_check_media(dev, 0);
+
 	if (intr_status & IntrStatsMax) {
 		dev->stats.rx_crc_errors += ioread16(ioaddr + RxCRCErrs);
 		dev->stats.rx_missed_errors += ioread16(ioaddr + RxMissed);
@@ -1930,19 +1959,15 @@ static void rhine_error(struct net_device *dev, int intr_status)
 			netdev_info(dev, "Unspecified error. Tx threshold now %02x\n",
 				    rp->tx_thresh);
 	}
-	if (intr_status & (IntrTxAborted | IntrTxUnderrun | IntrTxDescRace |
-			   IntrTxError))
-		rhine_restart_tx(dev);
 
-	if (intr_status & ~(IntrLinkChange | IntrStatsMax | IntrTxUnderrun |
-			    IntrTxError | IntrTxAborted | IntrNormalSummary |
-			    IntrTxDescRace)) {
-		if (debug > 1)
-			netdev_err(dev, "Something Wicked happened! %08x\n",
-				   intr_status);
-	}
+	napi_disable(&rp->napi);
+	iowrite16(0x0000, ioaddr + IntrEnable);
+	mmiowb();
+	/* Slow and safe. Consider __napi_schedule as a replacement ? */
+	napi_enable(&rp->napi);
+	napi_schedule(&rp->napi);
 
-	spin_unlock(&rp->lock);
+	mutex_unlock(&rp->task_lock);
 }
 
 static struct net_device_stats *rhine_get_stats(struct net_device *dev)
@@ -2133,6 +2158,7 @@ static int rhine_close(struct net_device *dev)
 	void __iomem *ioaddr = rp->base;
 
 	napi_disable(&rp->napi);
+	cancel_work_sync(&rp->slow_event_task);
 	cancel_work_sync(&rp->reset_task);
 	netif_stop_queue(dev);
 

^ permalink raw reply related

* [FIX PATCH net] mlx4_en: nullify cq->vector field when closing completion queue
From: Yevgeny Petrilin @ 2011-12-29 15:49 UTC (permalink / raw)
  To: davem; +Cc: netdev, yevgenyp


Caused loss of connectivity when changing ring size.

Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
 drivers/net/ethernet/mellanox/mlx4/en_cq.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlx4/en_cq.c b/drivers/net/ethernet/mellanox/mlx4/en_cq.c
index 227997d..5829e0b 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_cq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_cq.c
@@ -147,6 +147,7 @@ void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
 	mlx4_free_hwq_res(mdev->dev, &cq->wqres, cq->buf_size);
 	if (priv->mdev->dev->caps.comp_pool && cq->vector)
 		mlx4_release_eq(priv->mdev->dev, cq->vector);
+	cq->vector = 0;
 	cq->buf_size = 0;
 	cq->buf = NULL;
 }
-- 
1.5.4.3

^ permalink raw reply related

* Allocation of MDIO bus numbers when fixed MDIO bus is enabled?
From: Florian Fainelli @ 2011-12-29 16:09 UTC (permalink / raw)
  To: afleming, netdev, Anton Vorontsov

Hello Andy,

An user of the r6040 driver has enabled support for the Fixed MDIO bus, 
so when the r6040 registers with its first instance, it will also try to 
register a MDIO bus with id 0, and this fails.

What's the proper solution to fixing this kind of issue? The same user 
proposed to use the pci slot and function as an id for registering the 
MDIO bus, which will work for PCI devices, but not for platform_devices 
for instance.

Thanks.
--
Florian

^ permalink raw reply

* Re: [PATCH] skge: restore multicast rx filter on resume
From: Stephen Hemminger @ 2011-12-29 16:18 UTC (permalink / raw)
  To: David Miller; +Cc: florz, netdev
In-Reply-To: <20111229.025611.2043166821951238153.davem@davemloft.net>

On Thu, 29 Dec 2011 02:56:11 -0500 (EST)
David Miller <davem@davemloft.net> wrote:

> From: Florian Zumbiehl <florz@florz.de>
> Date: Thu, 29 Dec 2011 07:48:50 +0100
> 
> > --- a/drivers/net/skge.c
> > +++ b/drivers/net/skge.c  
> 
> This file no longer exists in the current source tree.

Florian the driver has moved to:
  drivers/net/ethernet/marvell/skge.c
in latest kernel release.

^ permalink raw reply

* Re: [Announce] LARTC wiki available
From: Hagen Paul Pfeifer @ 2011-12-29 16:19 UTC (permalink / raw)
  To: Niccolò Belli
  Cc: lartc, netfilter@vger.kernel.org,
	Linux Networking Developer Mailing List
In-Reply-To: <4EFC34E5.4040202@linuxsystems.it>

* Niccolò Belli | 2011-12-29 10:37:41 [+0100]:

>> What about
>>
>> http://www.linuxfoundation.org/collaborate/workgroups/networking/group
>
>I saw it, but I didn't like it because unregistered users cannot edit
>the wiki and even registered users need an invite. Also, it seems
>quite confusing, a traditional wiki is a better solution in my
>opinion.

Anybody knows that network stack lacks documentation - no doubt. Maybe a wiki
is an adequate concept (beside man pages and in Kernel docs). Everybody, not
restricted to kernel hackers, can edit documentation and add examples.

Maybe the netem wiki page at

http://www.linuxfoundation.org/collaborate/workgroups/networking/netem

is a good example for a good documented subsystem.


But I don't like the idea to outhouse the existing wiki. Why two wikis? What
happened with the wiki server if you leave the university? So maybe the user
restriction on linuxfoundation.org should be changed? I strongly suggest to
keep to documentation as tightly as possible to linuxfoundation (or
https://www.wiki.kernel.org/).

Hagen

^ permalink raw reply

* Re: [PATCH net-next] netem: fix classful handling
From: Hagen Paul Pfeifer @ 2011-12-29 16:52 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Stephen Hemminger, David Miller, Dave Taht, John A. Sullivan III,
	netdev
In-Reply-To: <1325149922.2607.33.camel@edumazet-laptop>

* Eric Dumazet | 2011-12-29 10:12:02 [+0100]:

>> Also, the whole tfifo idea is only to support the wierd idea that
>> if doing random delay that packets should get reordered based on the
>> results of the random value; it was an behavior some users wanted
>> because that is what NISTnet did.
>
>tfifo supports a time ordered queuing, wich mimics some jitter in the
>network. This seems quite useful.
>
>I see what you suggest : adding 'time_to_send' in the generic qdisc cb.
>
>But it makes no sense if we attach a reordering qdisc, like SFQ :
>A 'high prio' packet will block the whole netem because we'll have to
>throttle since this packet time_to_send will be in the future, while
>many other elligible packets are in queue.

In other words netem jitter and a qdisc !tfifo will not work. Correct? The
rate extension also peak the last packet to get the reference time (assuming a
strict ordering):

[...]
now = netem_skb_cb(skb_peek_tail(list))->time_to_send;
[...]


We should avoid a different (unseeable) behavior depending on the queue
(tfifo, SFQ).  Another point: operate netem and qdisc on the same computer can
lead to timing abnormalities. In our test setups we operate qdisc/tcp/whatever
setups and netem on more then on computer.

Hagen

^ permalink raw reply

* Re: [Announce] LARTC wiki available
From: Niccolò Belli @ 2011-12-29 17:13 UTC (permalink / raw)
  To: lartc; +Cc: netfilter@vger.kernel.org,
	Linux Networking Developer Mailing List
In-Reply-To: <20111229161919.GA2948@hell>

Il 29/12/2011 17:19, Hagen Paul Pfeifer ha scritto:
> But I don't like the idea to outhouse the existing wiki. Why two wikis?

Because if you need an invite to edit something then it isn't a wiki 
anymore, for example.


> What happened with the wiki server if you leave the university?

This isn't a problem, because relocating would be as simple as doing a 
database dump. Releasing dumps publicly wouldn't be a problem too. Also, 
there is no reason to keep using my servers when better alternatives 
arise. I created the wiki in a dedicated server because I didn't find 
viable alternatives (unlike for the mailing list) and considering the 
few feedbacks I received hopefully doing something tangible would create 
more interest: I'm pretty sure I'm not the only one who thinks there 
isn't enough documentation for the *end user*.

> So maybe the user
> restriction on linuxfoundation.org should be changed?

Yes, IMHO.

> https://www.wiki.kernel.org/.

It seems a wiki for a kernel hacker, not for the end user.

P.S.
Feedbacks are welcome, if there is no interest at all maybe we should 
just discard the idea after all.

Thanks,
Niccolò

^ permalink raw reply

* Re: [PATCH net-next] netem: fix classful handling
From: Eric Dumazet @ 2011-12-29 17:15 UTC (permalink / raw)
  To: Hagen Paul Pfeifer
  Cc: Stephen Hemminger, David Miller, Dave Taht, John A. Sullivan III,
	netdev
In-Reply-To: <20111229165249.GB2948@hell>

Le jeudi 29 décembre 2011 à 17:52 +0100, Hagen Paul Pfeifer a écrit :
> * Eric Dumazet | 2011-12-29 10:12:02 [+0100]:
> 
> >> Also, the whole tfifo idea is only to support the wierd idea that
> >> if doing random delay that packets should get reordered based on the
> >> results of the random value; it was an behavior some users wanted
> >> because that is what NISTnet did.
> >
> >tfifo supports a time ordered queuing, wich mimics some jitter in the
> >network. This seems quite useful.
> >
> >I see what you suggest : adding 'time_to_send' in the generic qdisc cb.
> >
> >But it makes no sense if we attach a reordering qdisc, like SFQ :
> >A 'high prio' packet will block the whole netem because we'll have to
> >throttle since this packet time_to_send will be in the future, while
> >many other elligible packets are in queue.
> 
> In other words netem jitter and a qdisc !tfifo will not work. Correct? The
> rate extension also peak the last packet to get the reference time (assuming a
> strict ordering):
> 

Yep, current situation is borked. It assumes we _use_ tfifo, for delay
jitters but also for rate extension.

> [...]
> now = netem_skb_cb(skb_peek_tail(list))->time_to_send;
> [...]
> 
> 
> We should avoid a different (unseeable) behavior depending on the queue
> (tfifo, SFQ).  Another point: operate netem and qdisc on the same computer can
> lead to timing abnormalities. In our test setups we operate qdisc/tcp/whatever
> setups and netem on more then on computer.
> 

After my patch you could use netem as a delay module before a complex
qdisc setup for example.

[ Simulating a 10ms delay on a 10Gigabit link is expensive, since you
need to allow up to ~150.000 packets in tfifo. Maybe we should switch to
tbfifo [giving a limit in bytes, not packets ] ]

^ permalink raw reply

* iproute2: l2tp support
From: Stephen Hemminger @ 2011-12-29 17:42 UTC (permalink / raw)
  To: James Chapman; +Cc: netdev

I updated the latest iproute2 in git to include support for L2TP.
It is based on James's code but instead of using libnl, it uses netlink
directly (like I asked when rejecting the original patch).

In order to make netlink code in iproute2 cleaner, several libnetlink
have been updated.
  * unused junk argument to rtnl_dump_filter and rtnl_talk have
    been removed.
  * addattr_xx functions for building attributes added.
  * rta_getattr_XXX inline functions for the common case of
    looking at basic type attributes

This will show up in 3.2 version of iproute2 which is ready and
waiting for kernel release.

^ permalink raw reply

* Re: [PATCH net-next] netem: fix classful handling
From: Hagen Paul Pfeifer @ 2011-12-29 17:43 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Stephen Hemminger, David Miller, Dave Taht, John A. Sullivan III,
	netdev
In-Reply-To: <1325178950.2607.46.camel@edumazet-laptop>

* Eric Dumazet | 2011-12-29 18:15:50 [+0100]:

>> In other words netem jitter and a qdisc !tfifo will not work. Correct? The
>> rate extension also peak the last packet to get the reference time (assuming a
>> strict ordering):
>> 
>
>Yep, current situation is borked. It assumes we _use_ tfifo, for delay
>jitters but also for rate extension.

Mhh, should we signal this to the user via 'tc -s qdisc show'? Or should we
assume that a user who set netem rate|jitter AND a qdisc !tfifo knows what he
does - because we assume he is a experienced user? At least somewhere in the
manpage a comment should point to this characteristic.

^ permalink raw reply

* [PATCH net-next 1/2] mlx4_core: using array index for sense_allowed
From: Yevgeny Petrilin @ 2011-12-29 17:42 UTC (permalink / raw)
  To: davem; +Cc: netdev, yevgenyp


Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
 drivers/net/ethernet/mellanox/mlx4/main.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index 1209934..6bb62c5 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -332,7 +332,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
 		 * and perform sense_port FW command to try and set the correct
 		 * port type from beginning
 		 */
-		if (mlx4_priv(dev)->sense.sense_allowed && dev->caps.default_sense[i]) {
+		if (mlx4_priv(dev)->sense.sense_allowed[i] && dev->caps.default_sense[i]) {
 			enum mlx4_port_type sensed_port = MLX4_PORT_TYPE_NONE;
 			dev->caps.possible_type[i] = MLX4_PORT_TYPE_AUTO;
 			mlx4_SENSE_PORT(dev, i, &sensed_port);
-- 
1.7.7

^ permalink raw reply related

* [PATCH net-next 2/2] mlx4_core: limiting VF port options
From: Yevgeny Petrilin @ 2011-12-29 17:42 UTC (permalink / raw)
  To: davem; +Cc: netdev, yevgenyp


At the moment VFs can only operate in Eth mode.
In addition we don't want the VF to attempt link sensing,
so we block this option as well.

Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
 drivers/net/ethernet/mellanox/mlx4/fw.c |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c
index e0639eb..8bcc66f 100644
--- a/drivers/net/ethernet/mellanox/mlx4/fw.c
+++ b/drivers/net/ethernet/mellanox/mlx4/fw.c
@@ -657,6 +657,8 @@ int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave,
 	u8 port_type;
 	int err;
 
+#define MLX4_VF_PORT_ETH_ONLY_MASK	0xE6
+
 	err = mlx4_cmd_box(dev, 0, outbox->dma, vhcr->in_modifier, 0,
 			   MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B,
 			   MLX4_CMD_NATIVE);
@@ -671,8 +673,8 @@ int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave,
 		MLX4_GET(port_type, outbox->buf,
 			 QUERY_PORT_SUPPORTED_TYPE_OFFSET);
 
-		/* disable ib */
-		port_type &= 0xFE;
+		/* Allow only Eth port, no link sensing allowed */
+		port_type &= MLX4_VF_PORT_ETH_ONLY_MASK;
 
 		/* check eth is enabled for this port */
 		if (!(port_type & 2))
-- 
1.7.7

^ permalink raw reply related

* Re: [PATCH net-next] netem: fix classful handling
From: Eric Dumazet @ 2011-12-29 18:10 UTC (permalink / raw)
  To: Hagen Paul Pfeifer
  Cc: Stephen Hemminger, David Miller, Dave Taht, John A. Sullivan III,
	netdev
In-Reply-To: <20111229174323.GC2948@hell>

Le jeudi 29 décembre 2011 à 18:43 +0100, Hagen Paul Pfeifer a écrit :
> * Eric Dumazet | 2011-12-29 18:15:50 [+0100]:
> 
> >> In other words netem jitter and a qdisc !tfifo will not work. Correct? The
> >> rate extension also peak the last packet to get the reference time (assuming a
> >> strict ordering):
> >> 
> >
> >Yep, current situation is borked. It assumes we _use_ tfifo, for delay
> >jitters but also for rate extension.
> 
> Mhh, should we signal this to the user via 'tc -s qdisc show'? Or should we
> assume that a user who set netem rate|jitter AND a qdisc !tfifo knows what he
> does - because we assume he is a experienced user? At least somewhere in the
> manpage a comment should point to this characteristic.

I dont quite understand the question. The patch I posted is supposed to
fix the problem. What do you want to tell to the user ?

netem module is probably only used by experimented users, on very recent
kernels anyway.

^ permalink raw reply

* Re: [PATCH] tcp: detect loss above high_seq in recovery
From: Yuchung Cheng @ 2011-12-29 18:21 UTC (permalink / raw)
  To: Ilpo Järvinen; +Cc: David Miller, ncardwell, nanditad, Netdev
In-Reply-To: <alpine.DEB.2.00.1112281736480.7752@melkinpaasi.cs.helsinki.fi>

Ilpo,
On Wed, Dec 28, 2011 at 7:42 AM, Ilpo Järvinen
<ilpo.jarvinen@helsinki.fi> wrote:
>
> On Tue, 27 Dec 2011, Yuchung Cheng wrote:
> > The new sequences sent during fast-recovery maybe marked as lost
> > and/or retransmitted. It is possible these (new) losses are recovered
> > within the current fast recovery and the state moves back to CA_Open
> > without entering another fast recovery / cwnd redunction. This is
> > especially possible for light losses.  Note RFC 3517 (implicitly)
> > allows this as well.
>
> No it doesn't! It does not allow you to avoid the second cwnd reduction.
> They're from different RTT. What you now claim is that we never need to
> do cwnd reduction until we visit CA_Open in between. That's very very
> dangerous if the congestion suddently spikes because nobody reduces twice
> causing everyone to get losses and continues in the recovery forever.

Should TCP perform another CWR for sequences lost after recovery point?
my colleagues and I all agree with you it should. But my commit message did a
poor job explain some subtle deviations in standard and current Linux.

RFC3517 supports this by principle; however, it may repair such new data losses
in the current recovery: Rue 1.b and 1.c in NextSeg() allow retransmitting any
segment below highest sacked sequence. Thus it may repair every loss in the
current recovery and won't never go into another.

As a matter of fact, Linux already does that today, by implementing rule 3 in
NextSeg(), aka forward-retransmit. But Linux won't mark these packets lost even
if there are >= tp->reordering packets sacked above. This change fixes this.

How often is second CWR avoided? it's probably rare b/c it requires new data
during the recovery RTT and a complete repair any losses of them. It's arguably
 OK to fix small new data losses during current recovery, and RFC/Linux seem
to do so.

To summarize:
1) this change does NOT forbid TCP performing further CWR on new losses
2) this change (merely) marks some forward-retransmitted packets LOST.
3) the commit message is to be explicit that CWR may not always be performed,
    in both my change and current kernel.


HTH. I will update commit message if people can make sense of it :)

^ permalink raw reply

* Re: [PATCH net-next] netem: fix classful handling
From: Hagen Paul Pfeifer @ 2011-12-29 18:25 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Stephen Hemminger, David Miller, Dave Taht, John A. Sullivan III,
	netdev
In-Reply-To: <1325182236.2607.50.camel@edumazet-laptop>

* Eric Dumazet | 2011-12-29 19:10:36 [+0100]:

>I dont quite understand the question. The patch I posted is supposed to
>fix the problem. What do you want to tell to the user ?

I assumed that the patch makes it possible to replace standard tfifo?! Tfifo
provides strict ordering, other qdisc's do not. So I thought if someone use
netem rate|jitter with e.g. SFQ then this should be mentioned somewhere. E.g.
"rate|jitter can only be used with tfifo qdisc". Correct me if I am wrong.

Cheers

^ permalink raw reply

* Re: [PATCH net-next] netem: fix classful handling
From: Stephen Hemminger @ 2011-12-29 18:31 UTC (permalink / raw)
  To: Hagen Paul Pfeifer
  Cc: Eric Dumazet, David Miller, Dave Taht, John A. Sullivan III,
	netdev
In-Reply-To: <20111229182502.GD2948@hell>

On Thu, 29 Dec 2011 19:25:03 +0100
Hagen Paul Pfeifer <hagen@jauu.net> wrote:

> * Eric Dumazet | 2011-12-29 19:10:36 [+0100]:
> 
> >I dont quite understand the question. The patch I posted is supposed to
> >fix the problem. What do you want to tell to the user ?
> 
> I assumed that the patch makes it possible to replace standard tfifo?! Tfifo
> provides strict ordering, other qdisc's do not. So I thought if someone use
> netem rate|jitter with e.g. SFQ then this should be mentioned somewhere. E.g.
> "rate|jitter can only be used with tfifo qdisc". Correct me if I am wrong.
> 
> Cheers

This is actually a feature. It is documented that tfifo can be replaced
with pfifo. In other words, if default (tfifo) is used then packets
can be reordered by the delay/jitter values. But if pfifo (or other
qdisc) is used, the packets will not be reordered.

^ permalink raw reply

* [PATCH] r8169: Enable suspend when device is idle from boot.
From: Todd Broch @ 2011-12-29 18:33 UTC (permalink / raw)
  To: nic_swsd; +Cc: Francois Romieu, netdev, Todd Broch

The r8169 driver supports power management and correctly transitions
from active to suspend when link transitions from connected to
disconnected.  However, if link is not connected at boot the device
remains active after the initial probe.

This change adds a check of the link status to the idle pm_op that
will schedule a suspend if inactive.

Signed-off-by: Todd Broch <tbroch@chromium.org>
---
 drivers/net/ethernet/realtek/r8169.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index 67bf078..3dbb5fd 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -6137,6 +6137,7 @@ static int rtl8169_runtime_idle(struct device *device)
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct rtl8169_private *tp = netdev_priv(dev);
 
+	__rtl8169_check_link_status(dev, tp, tp->mmio_addr, true);
 	return tp->TxDescArray ? -EBUSY : 0;
 }
 
-- 
1.7.3.1

^ permalink raw reply related

* Re: [PATCH net-next] netem: fix classful handling
From: Eric Dumazet @ 2011-12-29 18:36 UTC (permalink / raw)
  To: Hagen Paul Pfeifer
  Cc: Stephen Hemminger, David Miller, Dave Taht, John A. Sullivan III,
	netdev
In-Reply-To: <20111229182502.GD2948@hell>

Le jeudi 29 décembre 2011 à 19:25 +0100, Hagen Paul Pfeifer a écrit :
> * Eric Dumazet | 2011-12-29 19:10:36 [+0100]:
> 
> >I dont quite understand the question. The patch I posted is supposed to
> >fix the problem. What do you want to tell to the user ?
> 
> I assumed that the patch makes it possible to replace standard tfifo?! Tfifo
> provides strict ordering, other qdisc's do not. So I thought if someone use
> netem rate|jitter with e.g. SFQ then this should be mentioned somewhere. E.g.
> "rate|jitter can only be used with tfifo qdisc". Correct me if I am wrong.
> 

Current netem uses a single queue, default tfifo.

Then if you change this tfifo by SFQ, you lose tfifo, and netem doesnt
work at all.

I claim we cannot remove tfifo.

After my patch, you now have :

1) An internal mandatory tfifo queue, to fulfill time_to_send
requirements.

2) An optional qdisc (SFQ in your example), where packets are queued
once dequeued from tfifo at the right time (after netem delay/rate
respected), eventually a packet can finaly be delivered to device with a
_bigger_ delay than the one predicted in tfifo, because of trafic
shaping happening in this optional qdisc.


Full netem block :

              +---------+                   +--------+
-->>-enqueue--| tfifo   |---->>>>--enqueue--|  SFQ   |-dequeue--->>>>> 
              +---------+                   +--------+

^ permalink raw reply

* Re: [PATCH 1/1] via-rhine: Fix hanging with high CPU load on low-end broads.
From: Francois Romieu @ 2011-12-29 18:39 UTC (permalink / raw)
  To: Bjarke Istrup Pedersen
  Cc: David Miller, shemminger, bhutchings, linux-kernel, netdev, rl
In-Reply-To: <20111229153902.GB21946@electric-eye.fr.zoreil.com>

Francois Romieu <romieu@fr.zoreil.com> :
[...]
> Feel free to try the extra "new year's eve week end is getting closer"
> patch below (against net-next).
> 
> You have been warned.

The one below could be a bit better.

Out for dinner.

diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c
index 5c4983b..66e5c08 100644
--- a/drivers/net/ethernet/via/via-rhine.c
+++ b/drivers/net/ethernet/via/via-rhine.c
@@ -42,7 +42,8 @@
 
 #define DEBUG
 static int debug = 1;	/* 1 normal messages, 0 quiet .. 7 verbose. */
-static int max_interrupt_work = 20;
+#define RHINE_MSG_DEFAULT \
+        (NETIF_MSG_INTR)
 
 /* Set the copy breakpoint for the copy-only-tiny-frames scheme.
    Setting to > 1518 effectively disables this feature. */
@@ -128,11 +129,9 @@ MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("VIA Rhine PCI Fast Ethernet driver");
 MODULE_LICENSE("GPL");
 
-module_param(max_interrupt_work, int, 0);
 module_param(debug, int, 0);
 module_param(rx_copybreak, int, 0);
 module_param(avoid_D3, bool, 0);
-MODULE_PARM_DESC(max_interrupt_work, "VIA Rhine maximum events handled per interrupt");
 MODULE_PARM_DESC(debug, "VIA Rhine debug level (0-7)");
 MODULE_PARM_DESC(rx_copybreak, "VIA Rhine copy breakpoint for copy-only-tiny-frames");
 MODULE_PARM_DESC(avoid_D3, "Avoid power state D3 (work-around for broken BIOSes)");
@@ -351,16 +350,25 @@ static const int mmio_verify_registers[] = {
 
 /* Bits in the interrupt status/mask registers. */
 enum intr_status_bits {
-	IntrRxDone=0x0001, IntrRxErr=0x0004, IntrRxEmpty=0x0020,
-	IntrTxDone=0x0002, IntrTxError=0x0008, IntrTxUnderrun=0x0210,
-	IntrPCIErr=0x0040,
-	IntrStatsMax=0x0080, IntrRxEarly=0x0100,
-	IntrRxOverflow=0x0400, IntrRxDropped=0x0800, IntrRxNoBuf=0x1000,
-	IntrTxAborted=0x2000, IntrLinkChange=0x4000,
-	IntrRxWakeUp=0x8000,
-	IntrNormalSummary=0x0003, IntrAbnormalSummary=0xC260,
-	IntrTxDescRace=0x080000,	/* mapped from IntrStatus2 */
-	IntrTxErrSummary=0x082218,
+	IntrRxDone	= 0x0001,
+	IntrTxDone	= 0x0002,
+	IntrRxErr	= 0x0004,
+	IntrTxError	= 0x0008,
+	IntrRxEmpty	= 0x0020,
+	IntrPCIErr	= 0x0040,
+	IntrStatsMax	= 0x0080,
+	IntrRxEarly	= 0x0100,
+	IntrTxUnderrun	= 0x0210,
+	IntrRxOverflow	= 0x0400,
+	IntrRxDropped	= 0x0800,
+	IntrRxNoBuf	= 0x1000,
+	IntrTxAborted	= 0x2000,
+	IntrLinkChange	= 0x4000,
+	IntrRxWakeUp	= 0x8000,
+	IntrTxDescRace		= 0x080000,	/* mapped from IntrStatus2 */
+	IntrNormalSummary	= IntrRxDone | IntrTxDone,
+	IntrTxErrSummary	= IntrTxDescRace | IntrTxAborted | IntrTxError |
+				  IntrTxUnderrun,
 };
 
 /* Bits in WOLcrSet/WOLcrClr and PwrcsrSet/PwrcsrClr */
@@ -439,8 +447,12 @@ struct rhine_private {
 	struct net_device *dev;
 	struct napi_struct napi;
 	spinlock_t lock;
+	struct mutex task_lock;
+	struct work_struct slow_event_task;
 	struct work_struct reset_task;
 
+	u32 msg_enable;
+
 	/* Frequently used values: keep some adjacent for cache effect. */
 	u32 quirks;
 	struct rx_desc *rx_head_desc;
@@ -482,7 +494,6 @@ static netdev_tx_t rhine_start_tx(struct sk_buff *skb,
 static irqreturn_t rhine_interrupt(int irq, void *dev_instance);
 static void rhine_tx(struct net_device *dev);
 static int rhine_rx(struct net_device *dev, int limit);
-static void rhine_error(struct net_device *dev, int intr_status);
 static void rhine_set_rx_mode(struct net_device *dev);
 static struct net_device_stats *rhine_get_stats(struct net_device *dev);
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -497,6 +508,8 @@ static void rhine_set_cam_mask(void __iomem *ioaddr, u32 mask);
 static void rhine_set_vlan_cam_mask(void __iomem *ioaddr, u32 mask);
 static void rhine_init_cam_filter(struct net_device *dev);
 static void rhine_update_vcam(struct net_device *dev);
+static void rhine_slow_event_task(struct work_struct *work);
+static void rhine_restart_tx(struct net_device *dev);
 
 #define RHINE_WAIT_FOR(condition)				\
 do {								\
@@ -508,7 +521,7 @@ do {								\
 			1024 - i, __func__, __LINE__);		\
 } while (0)
 
-static inline u32 get_intr_status(struct net_device *dev)
+static u32 get_intr_status(struct net_device *dev)
 {
 	struct rhine_private *rp = netdev_priv(dev);
 	void __iomem *ioaddr = rp->base;
@@ -521,6 +534,16 @@ static inline u32 get_intr_status(struct net_device *dev)
 	return intr_status;
 }
 
+static void rhine_ack_event(struct rhine_private *rp, u32 mask)
+{
+	void __iomem *ioaddr = rp->base;
+
+	if (rp->quirks & rqStatusWBRace)
+		iowrite8(mask >> 16, ioaddr + IntrStatus2);
+	iowrite16(mask, ioaddr + IntrStatus);
+	mmiowb();
+}
+
 /*
  * Get power related registers into sane state.
  * Notify user about past WOL event.
@@ -657,23 +680,127 @@ static void rhine_poll(struct net_device *dev)
 }
 #endif
 
+static void rhine_kick_tx_threshold(struct rhine_private *rp)
+{
+	if (rp->tx_thresh < 0xe0) {
+		void __iomem *ioaddr = rp->base;
+
+		rp->tx_thresh += 0x20;
+		BYTE_REG_BITS_SET(rp->tx_thresh, 0x80, ioaddr + TxConfig);
+	}
+}
+
+static void rhine_tx_err(struct rhine_private *rp, u32 status)
+{
+	struct net_device *dev = rp->dev;
+
+	if (status & IntrTxAborted) {
+		netif_info(rp, tx_err, dev,
+			   "Abort %08x, frame dropped\n", status);
+	}
+
+	if (status & IntrTxUnderrun) {
+		rhine_kick_tx_threshold(rp);
+		netif_info(rp, tx_err ,dev, "Transmitter underrun, "
+			   "Tx threshold now %02x\n", rp->tx_thresh);
+	}
+
+	if (status & IntrTxDescRace)
+		netif_info(rp, tx_err, dev, "Tx descriptor write-back race\n");
+
+	if ((status & IntrTxError) &&
+	    (status & (IntrTxAborted | IntrTxUnderrun | IntrTxDescRace)) == 0) {
+		rhine_kick_tx_threshold(rp);
+		netif_info(rp, tx_err, dev, "Unspecified error. "
+			   "Tx threshold now %02x\n", rp->tx_thresh);
+	}
+
+	rhine_restart_tx(dev);
+}
+
+static void rhine_update_rx_crc_and_missed_errord(struct rhine_private *rp)
+{
+	void __iomem *ioaddr = rp->base;
+	struct net_device_stats *stats = &rp->dev->stats;
+
+	stats->rx_crc_errors    += ioread16(ioaddr + RxCRCErrs);
+	stats->rx_missed_errors += ioread16(ioaddr + RxMissed);
+
+	/*
+	 * Clears the "tally counters" for CRC errors and missed frames(?).
+	 * It has been reported that some chips need a write of 0 to clear
+	 * these, for others the counters are set to 1 when written to and
+	 * instead cleared when read. So we clear them both ways ...
+	 */
+	iowrite32(0, ioaddr + RxMissed);
+	ioread16(ioaddr + RxCRCErrs);
+	ioread16(ioaddr + RxMissed);
+}
+
+#define RHINE_EVENT_NAPI_RX	(IntrRxDone | \
+				 IntrRxErr | \
+				 IntrRxEmpty | \
+				 IntrRxOverflow	| \
+				 IntrRxDropped | \
+				 IntrRxNoBuf | \
+				 IntrRxWakeUp)
+
+#define RHINE_EVENT_NAPI_TX_ERR	(IntrTxError | \
+				 IntrTxAborted | \
+				 IntrTxUnderrun | \
+				 IntrTxDescRace)
+#define RHINE_EVENT_NAPI_TX	(IntrTxDone | RHINE_EVENT_NAPI_TX_ERR)
+
+#define RHINE_EVENT_NAPI	(RHINE_EVENT_NAPI_RX | \
+				 RHINE_EVENT_NAPI_TX | \
+				 IntrStatsMax)
+#define RHINE_EVENT_SLOW	(IntrPCIErr | IntrLinkChange)
+#define RHINE_EVENT		(RHINE_EVENT_NAPI | RHINE_EVENT_SLOW)
+
 static int rhine_napipoll(struct napi_struct *napi, int budget)
 {
 	struct rhine_private *rp = container_of(napi, struct rhine_private, napi);
 	struct net_device *dev = rp->dev;
 	void __iomem *ioaddr = rp->base;
-	int work_done;
+	u16 enable_mask = RHINE_EVENT & 0xffff;
+	int work_done = 0;
+	u32 status;
+
+	status = get_intr_status(dev);
+	rhine_ack_event(rp, status & ~RHINE_EVENT_SLOW);
+
+	if (status & RHINE_EVENT_NAPI_RX)
+		work_done += rhine_rx(dev, budget);
+
+	if (status & RHINE_EVENT_NAPI_TX) {
+		if (status & RHINE_EVENT_NAPI_TX_ERR) {
+			/* Avoid scavenging before Tx engine turned off */
+			RHINE_WAIT_FOR(!(ioread8(ioaddr + ChipCmd) & CmdTxOn));
+			if (ioread8(ioaddr + ChipCmd) & CmdTxOn)
+				netif_warn(rp, tx_err, dev, "Tx still on\n");
+		}
 
-	work_done = rhine_rx(dev, budget);
+		rhine_tx(dev);
+
+		if (status & RHINE_EVENT_NAPI_TX_ERR)
+			rhine_tx_err(rp, status);
+	}
+
+	if (status & IntrStatsMax) {
+		spin_lock(&rp->lock);
+		rhine_update_rx_crc_and_missed_errord(rp);
+		spin_unlock(&rp->lock);
+	}
+
+	if (status & RHINE_EVENT_SLOW) {
+		enable_mask &= ~RHINE_EVENT_SLOW;
+		schedule_work(&rp->slow_event_task);
+	}
 
 	if (work_done < budget) {
 		napi_complete(napi);
-
-		iowrite16(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow |
-			  IntrRxDropped | IntrRxNoBuf | IntrTxAborted |
-			  IntrTxDone | IntrTxError | IntrTxUnderrun |
-			  IntrPCIErr | IntrStatsMax | IntrLinkChange,
-			  ioaddr + IntrEnable);
+		iowrite16(enable_mask, ioaddr + IntrEnable);
+		mmiowb();
 	}
 	return work_done;
 }
@@ -797,6 +924,7 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
 	rp->quirks = quirks;
 	rp->pioaddr = pioaddr;
 	rp->pdev = pdev;
+	rp->msg_enable = netif_msg_init(-1, RHINE_MSG_DEFAULT);
 
 	rc = pci_request_regions(pdev, DRV_NAME);
 	if (rc)
@@ -856,7 +984,9 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
 	dev->irq = pdev->irq;
 
 	spin_lock_init(&rp->lock);
+	mutex_init(&rp->task_lock);
 	INIT_WORK(&rp->reset_task, rhine_reset_task);
+	INIT_WORK(&rp->slow_event_task, rhine_slow_event_task);
 
 	rp->mii_if.dev = dev;
 	rp->mii_if.mdio_read = mdio_read;
@@ -1310,12 +1440,7 @@ static void init_registers(struct net_device *dev)
 
 	napi_enable(&rp->napi);
 
-	/* Enable interrupts by setting the interrupt mask. */
-	iowrite16(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow |
-	       IntrRxDropped | IntrRxNoBuf | IntrTxAborted |
-	       IntrTxDone | IntrTxError | IntrTxUnderrun |
-	       IntrPCIErr | IntrStatsMax | IntrLinkChange,
-	       ioaddr + IntrEnable);
+	iowrite16(RHINE_EVENT & 0xffff, ioaddr + IntrEnable);
 
 	iowrite16(CmdStart | CmdTxOn | CmdRxOn | (Cmd1NoTxPoll << 8),
 	       ioaddr + ChipCmd);
@@ -1434,13 +1559,10 @@ static void rhine_reset_task(struct work_struct *work)
 						reset_task);
 	struct net_device *dev = rp->dev;
 
-	/* protect against concurrent rx interrupts */
-	disable_irq(rp->pdev->irq);
+	mutex_lock(&rp->task_lock);
 
 	napi_disable(&rp->napi);
 
-	spin_lock_bh(&rp->lock);
-
 	/* clear all descriptors */
 	free_tbufs(dev);
 	free_rbufs(dev);
@@ -1451,12 +1573,11 @@ static void rhine_reset_task(struct work_struct *work)
 	rhine_chip_reset(dev);
 	init_registers(dev);
 
-	spin_unlock_bh(&rp->lock);
-	enable_irq(rp->pdev->irq);
-
 	dev->trans_start = jiffies; /* prevent tx timeout */
 	dev->stats.tx_errors++;
 	netif_wake_queue(dev);
+
+	mutex_unlock(&rp->task_lock);
 }
 
 static void rhine_tx_timeout(struct net_device *dev)
@@ -1477,7 +1598,6 @@ static netdev_tx_t rhine_start_tx(struct sk_buff *skb,
 	struct rhine_private *rp = netdev_priv(dev);
 	void __iomem *ioaddr = rp->base;
 	unsigned entry;
-	unsigned long flags;
 
 	/* Caution: the write order is important here, set the field
 	   with the "ownership" bits last. */
@@ -1529,7 +1649,6 @@ static netdev_tx_t rhine_start_tx(struct sk_buff *skb,
 		rp->tx_ring[entry].tx_status = 0;
 
 	/* lock eth irq */
-	spin_lock_irqsave(&rp->lock, flags);
 	wmb();
 	rp->tx_ring[entry].tx_status |= cpu_to_le32(DescOwn);
 	wmb();
@@ -1543,15 +1662,12 @@ static netdev_tx_t rhine_start_tx(struct sk_buff *skb,
 		BYTE_REG_BITS_ON(1 << 7, ioaddr + TQWake);
 
 	/* Wake the potentially-idle transmit channel */
-	iowrite8(ioread8(ioaddr + ChipCmd1) | Cmd1TxDemand,
-	       ioaddr + ChipCmd1);
+	iowrite8(ioread8(ioaddr + ChipCmd1) | Cmd1TxDemand, ioaddr + ChipCmd1);
 	IOSYNC;
 
 	if (rp->cur_tx == rp->dirty_tx + TX_QUEUE_LEN)
 		netif_stop_queue(dev);
 
-	spin_unlock_irqrestore(&rp->lock, flags);
-
 	if (debug > 4) {
 		netdev_dbg(dev, "Transmit frame #%d queued in slot %d\n",
 			   rp->cur_tx-1, entry);
@@ -1565,63 +1681,26 @@ static irqreturn_t rhine_interrupt(int irq, void *dev_instance)
 {
 	struct net_device *dev = dev_instance;
 	struct rhine_private *rp = netdev_priv(dev);
-	void __iomem *ioaddr = rp->base;
-	u32 intr_status;
-	int boguscnt = max_interrupt_work;
+	u32 status;
 	int handled = 0;
 
-	while ((intr_status = get_intr_status(dev))) {
-		handled = 1;
-
-		/* Acknowledge all of the current interrupt sources ASAP. */
-		if (intr_status & IntrTxDescRace)
-			iowrite8(0x08, ioaddr + IntrStatus2);
-		iowrite16(intr_status & 0xffff, ioaddr + IntrStatus);
-		IOSYNC;
-
-		if (debug > 4)
-			netdev_dbg(dev, "Interrupt, status %08x\n",
-				   intr_status);
-
-		if (intr_status & (IntrRxDone | IntrRxErr | IntrRxDropped |
-				   IntrRxWakeUp | IntrRxEmpty | IntrRxNoBuf)) {
-			iowrite16(IntrTxAborted |
-				  IntrTxDone | IntrTxError | IntrTxUnderrun |
-				  IntrPCIErr | IntrStatsMax | IntrLinkChange,
-				  ioaddr + IntrEnable);
+	status = get_intr_status(dev);
 
-			napi_schedule(&rp->napi);
-		}
+	netif_dbg(rp, intr, dev, "Interrupt, status %08x\n", status);
 
-		if (intr_status & (IntrTxErrSummary | IntrTxDone)) {
-			if (intr_status & IntrTxErrSummary) {
-				/* Avoid scavenging before Tx engine turned off */
-				RHINE_WAIT_FOR(!(ioread8(ioaddr+ChipCmd) & CmdTxOn));
-				if (debug > 2 &&
-				    ioread8(ioaddr+ChipCmd) & CmdTxOn)
-					netdev_warn(dev,
-						    "%s: Tx engine still on\n",
-						    __func__);
-			}
-			rhine_tx(dev);
-		}
+	if (status & RHINE_EVENT) {
+		handled = 1;
 
-		/* Abnormal error summary/uncommon events handlers. */
-		if (intr_status & (IntrPCIErr | IntrLinkChange |
-				   IntrStatsMax | IntrTxError | IntrTxAborted |
-				   IntrTxUnderrun | IntrTxDescRace))
-			rhine_error(dev, intr_status);
+		iowrite16(0x0000, rp->base + IntrEnable);
+		mmiowb();
+		napi_schedule(&rp->napi);
+	}
 
-		if (--boguscnt < 0) {
-			netdev_warn(dev, "Too much work at interrupt, status=%#08x\n",
-				    intr_status);
-			break;
-		}
+	if (status & ~(IntrLinkChange | IntrStatsMax | RHINE_EVENT_NAPI)) {
+		netif_err(rp, intr, dev, "Something Wicked happened! %08x\n",
+			  status);
 	}
 
-	if (debug > 3)
-		netdev_dbg(dev, "exiting interrupt, status=%08x\n",
-			   ioread16(ioaddr + IntrStatus));
 	return IRQ_RETVAL(handled);
 }
 
@@ -1632,8 +1711,6 @@ static void rhine_tx(struct net_device *dev)
 	struct rhine_private *rp = netdev_priv(dev);
 	int txstatus = 0, entry = rp->dirty_tx % TX_RING_SIZE;
 
-	spin_lock(&rp->lock);
-
 	/* find and cleanup dirty tx descriptors */
 	while (rp->dirty_tx != rp->cur_tx) {
 		txstatus = le32_to_cpu(rp->tx_ring[entry].tx_status);
@@ -1687,8 +1764,6 @@ static void rhine_tx(struct net_device *dev)
 	}
 	if ((rp->cur_tx - rp->dirty_tx) < TX_QUEUE_LEN - 4)
 		netif_wake_queue(dev);
-
-	spin_unlock(&rp->lock);
 }
 
 /**
@@ -1839,20 +1914,8 @@ static int rhine_rx(struct net_device *dev, int limit)
 	return count;
 }
 
-/*
- * Clears the "tally counters" for CRC errors and missed frames(?).
- * It has been reported that some chips need a write of 0 to clear
- * these, for others the counters are set to 1 when written to and
- * instead cleared when read. So we clear them both ways ...
- */
-static inline void clear_tally_counters(void __iomem *ioaddr)
+static void rhine_restart_tx(struct net_device *dev)
 {
-	iowrite32(0, ioaddr + RxMissed);
-	ioread16(ioaddr + RxCRCErrs);
-	ioread16(ioaddr + RxMissed);
-}
-
-static void rhine_restart_tx(struct net_device *dev) {
 	struct rhine_private *rp = netdev_priv(dev);
 	void __iomem *ioaddr = rp->base;
 	int entry = rp->dirty_tx % TX_RING_SIZE;
@@ -1880,8 +1943,7 @@ static void rhine_restart_tx(struct net_device *dev) {
 		iowrite8(ioread8(ioaddr + ChipCmd1) | Cmd1TxDemand,
 		       ioaddr + ChipCmd1);
 		IOSYNC;
-	}
-	else {
+	} else {
 		/* This should never happen */
 		if (debug > 1)
 			netdev_warn(dev, "%s() Another error occurred %08x\n",
@@ -1890,72 +1952,46 @@ static void rhine_restart_tx(struct net_device *dev) {
 
 }
 
-static void rhine_error(struct net_device *dev, int intr_status)
+static void rhine_slow_event_task(struct work_struct *work)
 {
-	struct rhine_private *rp = netdev_priv(dev);
+	struct rhine_private *rp =
+		container_of(work, struct rhine_private, slow_event_task);
+	struct net_device *dev = rp->dev;
 	void __iomem *ioaddr = rp->base;
+	u32 intr_status;
 
-	spin_lock(&rp->lock);
+	if (!netif_running(dev))
+		return;
+
+	mutex_lock(&rp->task_lock);
+
+	intr_status = get_intr_status(dev);
+	rhine_ack_event(rp, intr_status & RHINE_EVENT_SLOW);
 
 	if (intr_status & IntrLinkChange)
 		rhine_check_media(dev, 0);
-	if (intr_status & IntrStatsMax) {
-		dev->stats.rx_crc_errors += ioread16(ioaddr + RxCRCErrs);
-		dev->stats.rx_missed_errors += ioread16(ioaddr + RxMissed);
-		clear_tally_counters(ioaddr);
-	}
-	if (intr_status & IntrTxAborted) {
-		if (debug > 1)
-			netdev_info(dev, "Abort %08x, frame dropped\n",
-				    intr_status);
-	}
-	if (intr_status & IntrTxUnderrun) {
-		if (rp->tx_thresh < 0xE0)
-			BYTE_REG_BITS_SET((rp->tx_thresh += 0x20), 0x80, ioaddr + TxConfig);
-		if (debug > 1)
-			netdev_info(dev, "Transmitter underrun, Tx threshold now %02x\n",
-				    rp->tx_thresh);
-	}
-	if (intr_status & IntrTxDescRace) {
-		if (debug > 2)
-			netdev_info(dev, "Tx descriptor write-back race\n");
-	}
-	if ((intr_status & IntrTxError) &&
-	    (intr_status & (IntrTxAborted |
-	     IntrTxUnderrun | IntrTxDescRace)) == 0) {
-		if (rp->tx_thresh < 0xE0) {
-			BYTE_REG_BITS_SET((rp->tx_thresh += 0x20), 0x80, ioaddr + TxConfig);
-		}
-		if (debug > 1)
-			netdev_info(dev, "Unspecified error. Tx threshold now %02x\n",
-				    rp->tx_thresh);
-	}
-	if (intr_status & (IntrTxAborted | IntrTxUnderrun | IntrTxDescRace |
-			   IntrTxError))
-		rhine_restart_tx(dev);
 
-	if (intr_status & ~(IntrLinkChange | IntrStatsMax | IntrTxUnderrun |
-			    IntrTxError | IntrTxAborted | IntrNormalSummary |
-			    IntrTxDescRace)) {
-		if (debug > 1)
-			netdev_err(dev, "Something Wicked happened! %08x\n",
-				   intr_status);
-	}
+	/* FIXME: ignore ? */
+	if (intr_status & IntrPCIErr)
+		netif_warn(rp, hw, dev, "PCI error\n");
 
-	spin_unlock(&rp->lock);
+	napi_disable(&rp->napi);
+	iowrite16(0x0000, ioaddr + IntrEnable);
+	mmiowb();
+	/* Slow and safe. Consider __napi_schedule as a replacement ? */
+	napi_enable(&rp->napi);
+	napi_schedule(&rp->napi);
+
+	mutex_unlock(&rp->task_lock);
 }
 
 static struct net_device_stats *rhine_get_stats(struct net_device *dev)
 {
 	struct rhine_private *rp = netdev_priv(dev);
-	void __iomem *ioaddr = rp->base;
-	unsigned long flags;
 
-	spin_lock_irqsave(&rp->lock, flags);
-	dev->stats.rx_crc_errors += ioread16(ioaddr + RxCRCErrs);
-	dev->stats.rx_missed_errors += ioread16(ioaddr + RxMissed);
-	clear_tally_counters(ioaddr);
-	spin_unlock_irqrestore(&rp->lock, flags);
+	spin_lock_bh(&rp->lock);
+	rhine_update_rx_crc_and_missed_errord(rp);
+	spin_unlock_bh(&rp->lock);
 
 	return &dev->stats;
 }
@@ -2022,9 +2058,9 @@ static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 	struct rhine_private *rp = netdev_priv(dev);
 	int rc;
 
-	spin_lock_irq(&rp->lock);
+	mutex_lock(&rp->task_lock);
 	rc = mii_ethtool_gset(&rp->mii_if, cmd);
-	spin_unlock_irq(&rp->lock);
+	mutex_unlock(&rp->task_lock);
 
 	return rc;
 }
@@ -2034,10 +2070,10 @@ static int netdev_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 	struct rhine_private *rp = netdev_priv(dev);
 	int rc;
 
-	spin_lock_irq(&rp->lock);
+	mutex_lock(&rp->task_lock);
 	rc = mii_ethtool_sset(&rp->mii_if, cmd);
-	spin_unlock_irq(&rp->lock);
 	rhine_set_carrier(&rp->mii_if);
+	mutex_unlock(&rp->task_lock);
 
 	return rc;
 }
@@ -2073,6 +2109,7 @@ static void rhine_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 	if (!(rp->quirks & rqWOL))
 		return;
 
+	/* FIXME: huh ? */
 	spin_lock_irq(&rp->lock);
 	wol->supported = WAKE_PHY | WAKE_MAGIC |
 			 WAKE_UCAST | WAKE_MCAST | WAKE_BCAST;	/* Untested */
@@ -2092,6 +2129,7 @@ static int rhine_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 	if (wol->wolopts & ~support)
 		return -EINVAL;
 
+	/* FIXME: huh (sic) ? */
 	spin_lock_irq(&rp->lock);
 	rp->wolopts = wol->wolopts;
 	spin_unlock_irq(&rp->lock);
@@ -2119,10 +2157,10 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 	if (!netif_running(dev))
 		return -EINVAL;
 
-	spin_lock_irq(&rp->lock);
+	mutex_lock(&rp->task_lock);
 	rc = generic_mii_ioctl(&rp->mii_if, if_mii(rq), cmd, NULL);
-	spin_unlock_irq(&rp->lock);
 	rhine_set_carrier(&rp->mii_if);
+	mutex_unlock(&rp->task_lock);
 
 	return rc;
 }
@@ -2133,11 +2171,10 @@ static int rhine_close(struct net_device *dev)
 	void __iomem *ioaddr = rp->base;
 
 	napi_disable(&rp->napi);
+	cancel_work_sync(&rp->slow_event_task);
 	cancel_work_sync(&rp->reset_task);
 	netif_stop_queue(dev);
 
-	spin_lock_irq(&rp->lock);
-
 	if (debug > 1)
 		netdev_dbg(dev, "Shutting down ethercard, status was %04x\n",
 			   ioread16(ioaddr + ChipCmd));
@@ -2151,8 +2188,6 @@ static int rhine_close(struct net_device *dev)
 	/* Stop the chip's Tx and Rx processes. */
 	iowrite16(CmdStop, ioaddr + ChipCmd);
 
-	spin_unlock_irq(&rp->lock);
-
 	free_irq(rp->pdev->irq, dev);
 	free_rbufs(dev);
 	free_tbufs(dev);
@@ -2239,10 +2274,12 @@ static int rhine_suspend(struct pci_dev *pdev, pm_message_t state)
 	netif_device_detach(dev);
 	pci_save_state(pdev);
 
+	/* FIXME: ? */
 	spin_lock_irqsave(&rp->lock, flags);
 	rhine_shutdown(pdev);
 	spin_unlock_irqrestore(&rp->lock, flags);
 
+	/* FIXME: nuclear workaround ? Check the commit log. */
 	free_irq(dev->irq, dev);
 	return 0;
 }
@@ -2257,6 +2294,7 @@ static int rhine_resume(struct pci_dev *pdev)
 	if (!netif_running(dev))
 		return 0;
 
+	/* FIXME: see above. */
 	if (request_irq(dev->irq, rhine_interrupt, IRQF_SHARED, dev->name, dev))
 		netdev_err(dev, "request_irq failed\n");
 

^ permalink raw reply related

* Re: linux-next: Tree for Dec 28 (nfnetlink)
From: Randy Dunlap @ 2011-12-29 18:53 UTC (permalink / raw)
  To: Pablo Neira Ayuso
  Cc: David Miller, sfr, linux-next, linux-kernel, netdev,
	netfilter-devel
In-Reply-To: <20111229010330.GA2663@1984>

On 12/28/2011 05:03 PM, Pablo Neira Ayuso wrote:
> On Wed, Dec 28, 2011 at 03:33:04PM -0500, David Miller wrote:
>> From: Randy Dunlap <rdunlap@xenotime.net>
>> Date: Wed, 28 Dec 2011 13:19:08 -0800
>>
>>> On 12/28/2011 01:18 AM, Stephen Rothwell wrote:
>>>> Hi all,
>>>>
>>>> I got bored :-(  I also hate tree wide, flag day changes :-(
>>>>
>>>> Changes since 20111222:
>>>
>>>
>>>
>>> warning: (NETFILTER_XT_MATCH_NFACCT) selects NETFILTER_NETLINK_ACCT which has unmet direct dependencies (NET && INET && NETFILTER && NETFILTER_ADVANCED)
>>>
>>> and then
>>>
>>> ERROR: "nfnetlink_subsys_unregister" [net/netfilter/nfnetlink_acct.ko] undefined!
>>> ERROR: "nfnetlink_subsys_register" [net/netfilter/nfnetlink_acct.ko] undefined!
>>>
>>>
>>> Full randconfig file is attached.
>>
>> Pablo please fix this, thanks.
> 
> Please, apply the following patch.

Acked-by: Randy Dunlap <rdunlap@xenotime.net>

Thanks.


-- 
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***

^ permalink raw reply

* Re: [Announce] LARTC wiki available
From: John A. Sullivan III @ 2011-12-29 19:04 UTC (permalink / raw)
  To: Niccolò Belli
  Cc: netfilter, Linux Networking Developer Mailing List, lartc
In-Reply-To: <4EFC9FC2.1090503@linuxsystems.it>



----- Original Message -----
> From: "Niccolò Belli" <darkbasic@linuxsystems.it>
> To: lartc@vger.kernel.org
> Cc: netfilter@vger.kernel.org, "Linux Networking Developer Mailing List" <netdev@vger.kernel.org>
> Sent: Thursday, December 29, 2011 12:13:38 PM
> Subject: Re: [Announce] LARTC wiki available
> 
> Il 29/12/2011 17:19, Hagen Paul Pfeifer ha scritto:
> > But I don't like the idea to outhouse the existing wiki. Why two
> > wikis?
> 
> Because if you need an invite to edit something then it isn't a wiki
> anymore, for example.
> 
> 
> > What happened with the wiki server if you leave the university?
> 
> This isn't a problem, because relocating would be as simple as doing
> a
> database dump. Releasing dumps publicly wouldn't be a problem too.
> Also,
> there is no reason to keep using my servers when better alternatives
> arise. I created the wiki in a dedicated server because I didn't find
> viable alternatives (unlike for the mailing list) and considering the
> few feedbacks I received hopefully doing something tangible would
> create
> more interest: I'm pretty sure I'm not the only one who thinks there
> isn't enough documentation for the *end user*.
> 
> > So maybe the user
> > restriction on linuxfoundation.org should be changed?
> 
> Yes, IMHO.
> 
> > https://www.wiki.kernel.org/.
> 
> It seems a wiki for a kernel hacker, not for the end user.
> 
> P.S.
> Feedbacks are welcome, if there is no interest at all maybe we should
> just discard the idea after all.
> 
> <snip>
I can certainly concur that there is a lack of end user documentation.  I have found the net devs extremely helpful and am deeply grateful for their support but I do sometimes chuckle because the documentation and the responses are written from such a developer's context.  Of course, that is entirely expected and I don't mean the least bit of disrespect; I stand in complete awe of the net devs.

But the needs and perspectives of net devs and system engineers/admins are very different and rightly so.  So, I'd love to see a hybrid environment where we have the best of both worlds (but where sys admin types don't feel completely lost and overwhelmed).  Thanks, all - John

^ 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