netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Tom Rix" <trix@specifix.com>
To: "Francois Romieu" <romieu@fr.zoreil.com>
Cc: tbm@cyrius.com, jgarzik@pobox.com, netdev@vger.kernel.org,
	linux-mips@linux-mips.org, mark.e.mason@broadcom.com
Subject: Re: PATCH SB1250 NAPI support
Date: Sat, 01 Jul 2006 08:27:52 -0500	[thread overview]
Message-ID: <op.tb0icqqcthfl8t@localhost.localdomain> (raw)
In-Reply-To: <20060629200107.GA8122@electric-eye.fr.zoreil.com>

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

Here is a revised patch that does the interupt masking earlier.  Since  
resetting the mask is done now in 3 places, I created a macro to handle  
it.  This patch has been tested on the linux-mips kernel from 6/29/06 on a  
sb1250.
Tom

On Thu, 29 Jun 2006 15:01:07 -0500, Francois Romieu <romieu@fr.zoreil.com>  
wrote:

> Tom Rix <trix@specifix.com> :
> [...]
> diff -rup a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c
> --- a/drivers/net/sb1250-mac.c	2006-03-09 04:25:41.000000000 -0600
> +++ b/drivers/net/sb1250-mac.c	2006-03-09 05:30:52.000000000 -0600
> [...]
> @@ -2079,13 +2095,31 @@ static irqreturn_t sbmac_intr(int irq,vo
>  		 * Transmits on channel 0
>  		 */
> +#if defined(CONFIG_SBMAC_NAPI)
>  		if (isr & (M_MAC_INT_CHANNEL << S_MAC_TX_CH0)) {
> -			sbdma_tx_process(sc,&(sc->sbm_txdma));
> +			sbdma_tx_process(sc,&(sc->sbm_txdma), 0);
>  		}
> 		/*
>  		 * Receives on channel 0
>  		 */
> +		if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH0)) {
> +			if (netif_rx_schedule_prep(dev))
> +			{
>
> An irq could appear here. I am skeptical that it is safe to write
> the irq mask register so late.
>
> One should probably consider a break in the enclosing "for" loop too.
>
>
> +				__raw_writeq(0, sc->sbm_imr);
> +				__netif_rx_schedule(dev);
> +			}
> +			else
> +			{
>
> } else {, please.
>



-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/

[-- Attachment #2: mips-sb1250-mac-NAPI-5.patch --]
[-- Type: application/octet-stream, Size: 11138 bytes --]

--- a/drivers/net/Kconfig	2006-07-01 06:29:11.000000000 -0500
+++ b/drivers/net/Kconfig	2006-07-01 06:28:58.000000000 -0500
@@ -2013,10 +2013,6 @@ config R8169_NAPI
 
 	  If in doubt, say N.
 
-config NET_SB1250_MAC
-	tristate "SB1250 Ethernet support"
-	depends on SIBYTE_SB1xxx_SOC
-
 config R8169_VLAN
 	bool "VLAN support"
 	depends on R8169 && VLAN_8021Q
@@ -2026,6 +2022,27 @@ config R8169_VLAN
 	  
 	  If in doubt, say Y.
 
+config NET_SB1250_MAC
+	tristate "SB1250 Ethernet support"
+	depends on SIBYTE_SB1xxx_SOC
+
+config SBMAC_NAPI
+	bool "Use Rx Polling (NAPI) (EXPERIMENTAL)"
+	depends on NET_SB1250_MAC && EXPERIMENTAL
+	help
+	  NAPI is a new driver API designed to reduce CPU and interrupt load
+	  when the driver is receiving lots of packets from the card. It is
+	  still somewhat experimental and thus not yet enabled by default.
+
+	  If your estimated Rx load is 10kpps or more, or if the card will be
+	  deployed on potentially unfriendly networks (e.g. in a firewall),
+	  then say Y here.
+
+	  See <file:Documentation/networking/NAPI_HOWTO.txt> for more
+	  information.
+
+	  If in doubt, say y.
+
 config SIS190
 	tristate "SiS190/SiS191 gigabit ethernet support"
 	depends on PCI
--- a/drivers/net/sb1250-mac.c	2006-07-01 06:29:27.000000000 -0500
+++ b/drivers/net/sb1250-mac.c	2006-07-01 06:29:18.000000000 -0500
@@ -164,6 +164,25 @@ typedef enum { sbmac_state_uninit, sbmac
 #define ENET_PACKET_SIZE	1518
 /*#define ENET_PACKET_SIZE	9216 */
 
+
+#ifdef CONFIG_SBMAC_COALESCE
+/*
+ * Accept any TX interrupt and EOP count/timer RX interrupts on ch 0
+ */
+#define SET_INTR_MASK(S) \
+__raw_writeq(((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) | \
+	     ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_RX_CH0), \
+	     (S)->sbm_imr);
+#else
+/*
+ * Accept any kind of interrupt on TX and RX DMA channel 0
+ */
+#define SET_INTR_MASK(S) \
+__raw_writeq((M_MAC_INT_CHANNEL << S_MAC_TX_CH0) | \
+             (M_MAC_INT_CHANNEL << S_MAC_RX_CH0), (S)->sbm_imr);
+#endif
+
+
 /**********************************************************************
  *  DMA Descriptor structure
  ********************************************************************* */
@@ -205,6 +224,7 @@ typedef struct sbmacdma_s {
 	 * This stuff is for maintenance of the ring
 	 */
 
+	sbdmadscr_t     *sbdma_dscrtable_unaligned; 
 	sbdmadscr_t     *sbdma_dscrtable;	/* base of descriptor table */
 	sbdmadscr_t     *sbdma_dscrtable_end; /* end of descriptor table */
 
@@ -287,8 +307,8 @@ static int sbdma_add_rcvbuffer(sbmacdma_
 static int sbdma_add_txbuffer(sbmacdma_t *d,struct sk_buff *m);
 static void sbdma_emptyring(sbmacdma_t *d);
 static void sbdma_fillring(sbmacdma_t *d);
-static void sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d);
-static void sbdma_tx_process(struct sbmac_softc *sc,sbmacdma_t *d);
+static int sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d, int poll);
+static void sbdma_tx_process(struct sbmac_softc *sc,sbmacdma_t *d, int poll);
 static int sbmac_initctx(struct sbmac_softc *s);
 static void sbmac_channel_start(struct sbmac_softc *s);
 static void sbmac_channel_stop(struct sbmac_softc *s);
@@ -309,6 +329,10 @@ static struct net_device_stats *sbmac_ge
 static void sbmac_set_rx_mode(struct net_device *dev);
 static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static int sbmac_close(struct net_device *dev);
+#if defined (CONFIG_SBMAC_NAPI)
+static int sbmac_poll(struct net_device *poll_dev, int *budget);
+#endif
+
 static int sbmac_mii_poll(struct sbmac_softc *s,int noisy);
 static int sbmac_mii_probe(struct net_device *dev);
 
@@ -736,7 +760,7 @@ static void sbdma_initctx(sbmacdma_t *d,
 
 	d->sbdma_maxdescr = maxdescr;
 
-	d->sbdma_dscrtable = (sbdmadscr_t *)
+	d->sbdma_dscrtable_unaligned = d->sbdma_dscrtable = (sbdmadscr_t *)
 		kmalloc((d->sbdma_maxdescr+1)*sizeof(sbdmadscr_t), GFP_KERNEL);
 
 	/*
@@ -778,7 +802,6 @@ static void sbdma_initctx(sbmacdma_t *d,
 		d->sbdma_int_timeout = 0;
 	}
 #endif
-
 }
 
 /**********************************************************************
@@ -1146,13 +1169,14 @@ static void sbdma_fillring(sbmacdma_t *d
  *  	   nothing
  ********************************************************************* */
 
-static void sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d)
+static int sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d, int poll)
 {
 	int curidx;
 	int hwidx;
 	sbdmadscr_t *dsc;
 	struct sk_buff *sb;
 	int len;
+	int work_done = 0;
 
 	for (;;) {
 		/*
@@ -1230,8 +1254,15 @@ static void sbdma_rx_process(struct sbma
 						sb->ip_summed = CHECKSUM_NONE;
 					}
 				}
-
+				
+#if defined(CONFIG_SBMAC_NAPI)
+				if (0 == poll)
+					netif_rx(sb);
+				else
+					netif_receive_skb(sb);
+#else
 				netif_rx(sb);
+#endif				
 			}
 		} else {
 			/*
@@ -1248,8 +1279,9 @@ static void sbdma_rx_process(struct sbma
 		 */
 
 		d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr);
-
+		work_done++;
 	}
+	return work_done;
 }
 
 
@@ -1271,15 +1303,22 @@ static void sbdma_rx_process(struct sbma
  *  	   nothing
  ********************************************************************* */
 
-static void sbdma_tx_process(struct sbmac_softc *sc,sbmacdma_t *d)
+static void sbdma_tx_process(struct sbmac_softc *sc,sbmacdma_t *d, int poll)
 {
 	int curidx;
 	int hwidx;
 	sbdmadscr_t *dsc;
 	struct sk_buff *sb;
 	unsigned long flags;
+	int packets_handled = 0;
 
 	spin_lock_irqsave(&(sc->sbm_lock), flags);
+	
+	if (d->sbdma_remptr == d->sbdma_addptr)
+		goto end_unlock;
+
+	hwidx = (int) (((__raw_readq(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) -
+			d->sbdma_dscrtable_phys) / sizeof(sbdmadscr_t));
 
 	for (;;) {
 		/*
@@ -1294,15 +1333,12 @@ static void sbdma_tx_process(struct sbma
 		 */
 
 		curidx = d->sbdma_remptr - d->sbdma_dscrtable;
-		hwidx = (int) (((__raw_readq(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) -
-				d->sbdma_dscrtable_phys) / sizeof(sbdmadscr_t));
 
 		/*
 		 * If they're the same, that means we've processed all
 		 * of the descriptors up to (but not including) the one that
 		 * the hardware is working on right now.
 		 */
-
 		if (curidx == hwidx)
 			break;
 
@@ -1333,6 +1369,7 @@ static void sbdma_tx_process(struct sbma
 
 		d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr);
 
+		packets_handled++;
 	}
 
 	/*
@@ -1340,15 +1377,15 @@ static void sbdma_tx_process(struct sbma
 	 * Other drivers seem to do this when we reach a low
 	 * watermark on the transmit queue.
 	 */
+	
+	if (packets_handled)
+		netif_wake_queue(d->sbdma_eth->sbm_dev);
 
-	netif_wake_queue(d->sbdma_eth->sbm_dev);
-
+ end_unlock:
 	spin_unlock_irqrestore(&(sc->sbm_lock), flags);
 
 }
 
-
-
 /**********************************************************************
  *  SBMAC_INITCTX(s)
  *
@@ -1392,7 +1429,6 @@ static int sbmac_initctx(struct sbmac_so
 	 * Initialize the DMA channels.  Right now, only one per MAC is used
 	 * Note: Only do this _once_, as it allocates memory from the kernel!
 	 */
-
 	sbdma_initctx(&(s->sbm_txdma),s,0,DMA_TX,SBMAC_MAX_TXDESCR);
 	sbdma_initctx(&(s->sbm_rxdma),s,0,DMA_RX,SBMAC_MAX_RXDESCR);
 
@@ -1416,9 +1452,9 @@ static int sbmac_initctx(struct sbmac_so
 
 static void sbdma_uninitctx(struct sbmacdma_s *d)
 {
-	if (d->sbdma_dscrtable) {
-		kfree(d->sbdma_dscrtable);
-		d->sbdma_dscrtable = NULL;
+	if (d->sbdma_dscrtable_unaligned) {
+		kfree(d->sbdma_dscrtable_unaligned);
+		d->sbdma_dscrtable_unaligned = d->sbdma_dscrtable = NULL;
 	}
 
 	if (d->sbdma_ctxtable) {
@@ -1605,29 +1641,16 @@ static void sbmac_channel_start(struct s
 
 #if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
 	__raw_writeq(M_MAC_RXDMA_EN0 |
-		       M_MAC_TXDMA_EN0, s->sbm_macenable);
+		     M_MAC_TXDMA_EN0, s->sbm_macenable);
 #elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
 	__raw_writeq(M_MAC_RXDMA_EN0 |
-		       M_MAC_TXDMA_EN0 |
-		       M_MAC_RX_ENABLE |
-		       M_MAC_TX_ENABLE, s->sbm_macenable);
+		     M_MAC_TXDMA_EN0 |
+		     M_MAC_RX_ENABLE |
+		     M_MAC_TX_ENABLE, s->sbm_macenable);
 #else
 #error invalid SiByte MAC configuation
 #endif
-
-#ifdef CONFIG_SBMAC_COALESCE
-	/*
-	 * Accept any TX interrupt and EOP count/timer RX interrupts on ch 0
-	 */
-	__raw_writeq(((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) |
-		       ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_RX_CH0), s->sbm_imr);
-#else
-	/*
-	 * Accept any kind of interrupt on TX and RX DMA channel 0
-	 */
-	__raw_writeq((M_MAC_INT_CHANNEL << S_MAC_TX_CH0) |
-		       (M_MAC_INT_CHANNEL << S_MAC_RX_CH0), s->sbm_imr);
-#endif
+	SET_INTR_MASK(s);
 
 	/*
 	 * Enable receiving unicasts and broadcasts
@@ -2063,7 +2086,6 @@ static irqreturn_t sbmac_intr(int irq,vo
 		 * Read the ISR (this clears the bits in the real
 		 * register, except for counter addr)
 		 */
-
 		isr = __raw_readq(sc->sbm_isr) & ~M_MAC_COUNTER_ADDR;
 
 		if (isr == 0)
@@ -2075,13 +2097,33 @@ static irqreturn_t sbmac_intr(int irq,vo
 		 * Transmits on channel 0
 		 */
 
+#if defined(CONFIG_SBMAC_NAPI)
+		if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH0)) {
+			__raw_writeq(0, sc->sbm_imr);
+		}
+
 		if (isr & (M_MAC_INT_CHANNEL << S_MAC_TX_CH0)) {
-			sbdma_tx_process(sc,&(sc->sbm_txdma));
+			sbdma_tx_process(sc,&(sc->sbm_txdma), 0);
 		}
 
 		/*
 		 * Receives on channel 0
 		 */
+		if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH0)) {
+			if (netif_rx_schedule_prep(dev))
+			{
+				__netif_rx_schedule(dev);
+			} else {
+				SET_INTR_MASK(sc);
+				sbdma_rx_process(sc,&(sc->sbm_rxdma), 0);
+			}
+		}
+#else
+		/* Non NAPI */
+
+		if (isr & (M_MAC_INT_CHANNEL << S_MAC_TX_CH0)) {
+			sbdma_tx_process(sc,&(sc->sbm_txdma), 0);
+		}
 
 		/*
 		 * It's important to test all the bits (or at least the
@@ -2101,8 +2143,9 @@ static irqreturn_t sbmac_intr(int irq,vo
 
 
 		if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH0)) {
-			sbdma_rx_process(sc,&(sc->sbm_rxdma));
+			sbdma_rx_process(sc,&(sc->sbm_rxdma), 0);
 		}
+#endif
 	}
 	return IRQ_RETVAL(handled);
 }
@@ -2401,7 +2444,10 @@ static int sbmac_init(struct net_device 
 	dev->do_ioctl           = sbmac_mii_ioctl;
 	dev->tx_timeout         = sbmac_tx_timeout;
 	dev->watchdog_timeo     = TX_TIMEOUT;
-
+#if defined(CONFIG_SBMAC_NAPI)
+	dev->poll               = sbmac_poll;
+	dev->weight             = 16;
+#endif
 	dev->change_mtu         = sb1250_change_mtu;
 
 	/* This is needed for PASS2 for Rx H/W checksum feature */
@@ -2809,7 +2855,29 @@ static int sbmac_close(struct net_device
 	return 0;
 }
 
+#if defined(CONFIG_SBMAC_NAPI)
+static int sbmac_poll(struct net_device *dev, int *budget)
+{
+	int work_to_do;
+	int work_done;
+	struct sbmac_softc *sc = netdev_priv(dev);
+
+	work_to_do = min(*budget, dev->quota);
+	work_done = sbdma_rx_process(sc,&(sc->sbm_rxdma), 1);
 
+	sbdma_tx_process(sc,&(sc->sbm_txdma), 1);
+
+	*budget -= work_done;
+	dev->quota -= work_done;
+
+	if (work_done < work_to_do) {
+		netif_rx_complete(dev);
+		SET_INTR_MASK(sc);
+	}
+
+	return (work_done >= work_to_do);
+}
+#endif
 
 #if defined(SBMAC_ETH0_HWADDR) || defined(SBMAC_ETH1_HWADDR) || defined(SBMAC_ETH2_HWADDR) || defined(SBMAC_ETH3_HWADDR)
 static void

  reply	other threads:[~2006-07-01 12:55 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20060524125512.GO12089@deprecation.cyrius.com>
     [not found] ` <op.s93yprpethfl8t@localhost.localdomain>
     [not found]   ` <20060525133505.GH8746@deprecation.cyrius.com>
2006-06-04 16:45     ` PATCH SB1250 NAPI support Tom Rix
2006-06-29  8:22       ` Martin Michlmayr
2006-06-29 20:01       ` Francois Romieu
2006-07-01 13:27         ` Tom Rix [this message]
2006-06-29 17:15 Mark E Mason

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=op.tb0icqqcthfl8t@localhost.localdomain \
    --to=trix@specifix.com \
    --cc=jgarzik@pobox.com \
    --cc=linux-mips@linux-mips.org \
    --cc=mark.e.mason@broadcom.com \
    --cc=netdev@vger.kernel.org \
    --cc=romieu@fr.zoreil.com \
    --cc=tbm@cyrius.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).