* [PATCH]NET/KS8695: add support NAPI for Rx
@ 2009-10-26 16:00 Figo.zhang
2009-10-26 16:27 ` Daniel Silverstone
2009-10-26 16:49 ` Ben Hutchings
0 siblings, 2 replies; 4+ messages in thread
From: Figo.zhang @ 2009-10-26 16:00 UTC (permalink / raw)
To: Daniel Silverstone, David S. Miller; +Cc: netdev, Vincent Sanders, Ben Dooks
Add support NAPI Rx API for KS8695NET driver.
Signed-off-by: Figo.zhang <figo1802@gmail.com>
---
drivers/net/arm/ks8695net.c | 165 +++++++++++++++++++++++++++++++++++++++++++
1 files changed, 165 insertions(+), 0 deletions(-)
diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c
index 2a7b774..7f9d4bd 100644
--- a/drivers/net/arm/ks8695net.c
+++ b/drivers/net/arm/ks8695net.c
@@ -35,12 +35,16 @@
#include <mach/regs-switch.h>
#include <mach/regs-misc.h>
+#include <asm/mach/irq.h>
+#include <mach/regs-irq.h>
#include "ks8695net.h"
#define MODULENAME "ks8695_ether"
#define MODULEVERSION "1.01"
+#define KS8695NET_NAPI 1
+
/*
* Transmit and device reset timeout, default 5 seconds.
*/
@@ -152,6 +156,10 @@ struct ks8695_priv {
enum ks8695_dtype dtype;
void __iomem *io_regs;
+ #ifdef KS8695NET_NAPI
+ struct napi_struct napi;
+ #endif
+
const char *rx_irq_name, *tx_irq_name, *link_irq_name;
int rx_irq, tx_irq, link_irq;
@@ -172,6 +180,7 @@ struct ks8695_priv {
dma_addr_t rx_ring_dma;
struct ks8695_skbuff rx_buffers[MAX_RX_DESC];
int next_rx_desc_read;
+ spinlock_t rx_lock;
int msg_enable;
};
@@ -391,6 +400,155 @@ ks8695_tx_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
+#ifdef KS8695NET_NAPI
+static irqreturn_t
+ks8695_rx_irq(int irq, void *dev_id)
+{
+ struct net_device *ndev = (struct net_device *)dev_id;
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+ unsigned long status;
+
+ unsigned long mask_bit = 1 << ksp->rx_irq;
+
+ spin_lock(&ksp->rx_lock);
+
+ status = __raw_readl(KS8695_IRQ_VA + KS8695_INTST);
+
+ /*clean rx status bit*/
+ __raw_writel(status | mask_bit , KS8695_IRQ_VA + KS8695_INTST);
+
+ if (status & mask_bit) {
+ if (napi_schedule_prep(&ksp->napi)) {
+ /*disable rx interrupt*/
+ status &= ~mask_bit;
+ __raw_writel(status , KS8695_IRQ_VA + KS8695_INTEN);
+ __napi_schedule(&ksp->napi);
+ }
+ }
+
+ spin_unlock(&ksp->rx_lock);
+ return IRQ_HANDLED;
+}
+
+static int ks8695_rx(struct net_device *ndev, int budget)
+{
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+ struct sk_buff *skb;
+ int buff_n;
+ u32 flags;
+ int pktlen;
+ int last_rx_processed = -1;
+ int received = 0;
+
+ buff_n = ksp->next_rx_desc_read;
+ while (netif_running(ndev) && received < budget
+ && ksp->rx_buffers[buff_n].skb
+ && (!(ksp->rx_ring[buff_n].status &
+ cpu_to_le32(RDES_OWN)))) {
+ rmb();
+ flags = le32_to_cpu(ksp->rx_ring[buff_n].status);
+ /* Found an SKB which we own, this means we
+ * received a packet
+ */
+ if ((flags & (RDES_FS | RDES_LS)) !=
+ (RDES_FS | RDES_LS)) {
+ /* This packet is not the first and
+ * the last segment. Therefore it is
+ * a "spanning" packet and we can't
+ * handle it
+ */
+ goto rx_failure;
+ }
+
+ if (flags & (RDES_ES | RDES_RE)) {
+ /* It's an error packet */
+ ndev->stats.rx_errors++;
+ if (flags & RDES_TL)
+ ndev->stats.rx_length_errors++;
+ if (flags & RDES_RF)
+ ndev->stats.rx_length_errors++;
+ if (flags & RDES_CE)
+ ndev->stats.rx_crc_errors++;
+ if (flags & RDES_RE)
+ ndev->stats.rx_missed_errors++;
+
+ goto rx_failure;
+ }
+
+ pktlen = flags & RDES_FLEN;
+ pktlen -= 4; /* Drop the CRC */
+
+ /* Retrieve the sk_buff */
+ skb = ksp->rx_buffers[buff_n].skb;
+
+ /* Clear it from the ring */
+ ksp->rx_buffers[buff_n].skb = NULL;
+ ksp->rx_ring[buff_n].data_ptr = 0;
+
+ /* Unmap the SKB */
+ dma_unmap_single(ksp->dev,
+ ksp->rx_buffers[buff_n].dma_ptr,
+ ksp->rx_buffers[buff_n].length,
+ DMA_FROM_DEVICE);
+
+ /* Relinquish the SKB to the network layer */
+ skb_put(skb, pktlen);
+ skb->protocol = eth_type_trans(skb, ndev);
+ netif_receive_skb(skb);
+
+ /* Record stats */
+ ndev->stats.rx_packets++;
+ ndev->stats.rx_bytes += pktlen;
+ goto rx_finished;
+
+rx_failure:
+ /* This ring entry is an error, but we can
+ * re-use the skb
+ */
+ /* Give the ring entry back to the hardware */
+ ksp->rx_ring[buff_n].status = cpu_to_le32(RDES_OWN);
+rx_finished:
+ received++;
+ /* And note this as processed so we can start
+ * from here next time
+ */
+ last_rx_processed = buff_n;
+ buff_n = (buff_n + 1) & MAX_RX_DESC_MASK;
+ /*And note which RX descriptor we last did */
+ if (likely(last_rx_processed != -1))
+ ksp->next_rx_desc_read =
+ (last_rx_processed + 1) &
+ MAX_RX_DESC_MASK;
+
+ /* And refill the buffers */
+ ks8695_refill_rxbuffers(ksp);
+ }
+ return received;
+}
+
+static int ks8695_poll(struct napi_struct *napi, int budget)
+{
+ struct ks8695_priv *ksp = container_of(napi, struct ks8695_priv, napi);
+ struct net_device *dev = ksp->ndev;
+ unsigned long mask_bit = 1 << ksp->rx_irq;
+ unsigned long isr = __raw_readl(KS8695_IRQ_VA + KS8695_INTEN);
+
+ unsigned long work_done = 0;
+
+ work_done = ks8695_rx(dev, budget);
+
+ if (work_done < budget) {
+ unsigned long flags;
+ spin_lock_irqsave(&ksp->rx_lock, flags);
+ /*enable rx interrupt*/
+ __raw_writel(isr | mask_bit, KS8695_IRQ_VA + KS8695_INTEN);
+ __napi_complete(napi);
+ spin_unlock_irqrestore(&ksp->rx_lock, flags);
+ }
+ return work_done;
+}
+
+#else
/**
* ks8695_rx_irq - Receive IRQ handler
* @irq: The IRQ which went off (ignored)
@@ -503,6 +661,8 @@ rx_finished:
return IRQ_HANDLED;
}
+#endif
+
/**
* ks8695_link_irq - Link change IRQ handler
* @irq: The IRQ which went off (ignored)
@@ -1472,6 +1632,10 @@ ks8695_probe(struct platform_device *pdev)
SET_ETHTOOL_OPS(ndev, &ks8695_ethtool_ops);
ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
+#ifdef KS8695NET_NAPI
+ netif_napi_add(ndev, &ksp->napi, ks8695_poll, 64);
+#endif
+
/* Retrieve the default MAC addr from the chip. */
/* The bootloader should have left it in there for us. */
@@ -1505,6 +1669,7 @@ ks8695_probe(struct platform_device *pdev)
/* And initialise the queue's lock */
spin_lock_init(&ksp->txq_lock);
+ spin_lock_init(&ksp->rx_lock);
/* Specify the RX DMA ring buffer */
ksp->rx_ring = ksp->ring_base + TX_RING_DMA_SIZE;
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH]NET/KS8695: add support NAPI for Rx
2009-10-26 16:00 [PATCH]NET/KS8695: add support NAPI for Rx Figo.zhang
@ 2009-10-26 16:27 ` Daniel Silverstone
2009-10-26 16:49 ` Ben Hutchings
1 sibling, 0 replies; 4+ messages in thread
From: Daniel Silverstone @ 2009-10-26 16:27 UTC (permalink / raw)
To: Figo.zhang; +Cc: David S. Miller, netdev, Vincent Sanders, Ben Dooks
On Tue, Oct 27, 2009 at 12:00:28AM +0800, Figo.zhang wrote:
> +#ifdef KS8695NET_NAPI
> +static irqreturn_t
> +ks8695_rx_irq(int irq, void *dev_id)
This routine lacks its documentation comment. This driver is fully documented
in order to serve as a good example for others. Indeed this lack of
documentation comments continues through your patch, I won't bring up each
instance, instead trusting you to go back over your patch and sort them out.
> + status = __raw_readl(KS8695_IRQ_VA + KS8695_INTST);
[snip]
> + __raw_writel(status | mask_bit , KS8695_IRQ_VA + KS8695_INTST);
[snip]
> + __raw_writel(status , KS8695_IRQ_VA + KS8695_INTEN);
[snip]
> + unsigned long isr = __raw_readl(KS8695_IRQ_VA + KS8695_INTEN);
[snip]
> + __raw_writel(isr | mask_bit, KS8695_IRQ_VA + KS8695_INTEN);
Please don't use __raw_readl or __raw_writel. This driver was nice and clean,
don't ruin it.
Also, as an aside, you seem to add a spinlock (rx_lock) which afaict is only
used by NAPI related routines, and yet you include it regardless of NAPI being
enabled or not. Did I misread your patch, or is this an oversight?
Regards,
Daniel.
--
Daniel Silverstone http://www.simtec.co.uk/
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH]NET/KS8695: add support NAPI for Rx
2009-10-26 16:00 [PATCH]NET/KS8695: add support NAPI for Rx Figo.zhang
2009-10-26 16:27 ` Daniel Silverstone
@ 2009-10-26 16:49 ` Ben Hutchings
2009-10-26 22:43 ` David Miller
1 sibling, 1 reply; 4+ messages in thread
From: Ben Hutchings @ 2009-10-26 16:49 UTC (permalink / raw)
To: Figo.zhang
Cc: Daniel Silverstone, David S. Miller, netdev, Vincent Sanders,
Ben Dooks
On Tue, 2009-10-27 at 00:00 +0800, Figo.zhang wrote:
> Add support NAPI Rx API for KS8695NET driver.
>
> Signed-off-by: Figo.zhang <figo1802@gmail.com>
> ---
> drivers/net/arm/ks8695net.c | 165 +++++++++++++++++++++++++++++++++++++++++++
> 1 files changed, 165 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c
> index 2a7b774..7f9d4bd 100644
> --- a/drivers/net/arm/ks8695net.c
> +++ b/drivers/net/arm/ks8695net.c
> @@ -35,12 +35,16 @@
>
> #include <mach/regs-switch.h>
> #include <mach/regs-misc.h>
> +#include <asm/mach/irq.h>
> +#include <mach/regs-irq.h>
>
> #include "ks8695net.h"
>
> #define MODULENAME "ks8695_ether"
> #define MODULEVERSION "1.01"
I think this merits a version bump.
> +#define KS8695NET_NAPI 1
> +
> /*
> * Transmit and device reset timeout, default 5 seconds.
> */
> @@ -152,6 +156,10 @@ struct ks8695_priv {
> enum ks8695_dtype dtype;
> void __iomem *io_regs;
>
> + #ifdef KS8695NET_NAPI
> + struct napi_struct napi;
> + #endif
> +
NAPI is well-established and there should be no need to make it
optional. So far as I'm aware, all other drivers that had it as an
option now use it unconditionally.
> const char *rx_irq_name, *tx_irq_name, *link_irq_name;
> int rx_irq, tx_irq, link_irq;
>
> @@ -172,6 +180,7 @@ struct ks8695_priv {
> dma_addr_t rx_ring_dma;
> struct ks8695_skbuff rx_buffers[MAX_RX_DESC];
> int next_rx_desc_read;
> + spinlock_t rx_lock;
>
> int msg_enable;
> };
> @@ -391,6 +400,155 @@ ks8695_tx_irq(int irq, void *dev_id)
> return IRQ_HANDLED;
> }
>
> +#ifdef KS8695NET_NAPI
> +static irqreturn_t
> +ks8695_rx_irq(int irq, void *dev_id)
> +{
> + struct net_device *ndev = (struct net_device *)dev_id;
> + struct ks8695_priv *ksp = netdev_priv(ndev);
> + unsigned long status;
> +
> + unsigned long mask_bit = 1 << ksp->rx_irq;
> +
> + spin_lock(&ksp->rx_lock);
> +
> + status = __raw_readl(KS8695_IRQ_VA + KS8695_INTST);
> +
> + /*clean rx status bit*/
> + __raw_writel(status | mask_bit , KS8695_IRQ_VA + KS8695_INTST);
> +
> + if (status & mask_bit) {
> + if (napi_schedule_prep(&ksp->napi)) {
> + /*disable rx interrupt*/
> + status &= ~mask_bit;
> + __raw_writel(status , KS8695_IRQ_VA + KS8695_INTEN);
> + __napi_schedule(&ksp->napi);
> + }
> + }
> +
> + spin_unlock(&ksp->rx_lock);
> + return IRQ_HANDLED;
> +}
The interrupt register manipulation here looks wrong, but I don't have
specific knowledge of this platform.
Since the interrupt control registers appear to be shared with other
devices, this needs to be serialised with manipulation by other drivers.
> +static int ks8695_rx(struct net_device *ndev, int budget)
> +{
> + struct ks8695_priv *ksp = netdev_priv(ndev);
> + struct sk_buff *skb;
> + int buff_n;
> + u32 flags;
> + int pktlen;
> + int last_rx_processed = -1;
> + int received = 0;
> +
> + buff_n = ksp->next_rx_desc_read;
> + while (netif_running(ndev) && received < budget
netif_running() is quite redundant here.
> + && ksp->rx_buffers[buff_n].skb
> + && (!(ksp->rx_ring[buff_n].status &
> + cpu_to_le32(RDES_OWN)))) {
> + rmb();
> + flags = le32_to_cpu(ksp->rx_ring[buff_n].status);
> + /* Found an SKB which we own, this means we
> + * received a packet
> + */
> + if ((flags & (RDES_FS | RDES_LS)) !=
> + (RDES_FS | RDES_LS)) {
> + /* This packet is not the first and
> + * the last segment. Therefore it is
> + * a "spanning" packet and we can't
> + * handle it
> + */
> + goto rx_failure;
> + }
> +
> + if (flags & (RDES_ES | RDES_RE)) {
> + /* It's an error packet */
> + ndev->stats.rx_errors++;
> + if (flags & RDES_TL)
> + ndev->stats.rx_length_errors++;
> + if (flags & RDES_RF)
> + ndev->stats.rx_length_errors++;
> + if (flags & RDES_CE)
> + ndev->stats.rx_crc_errors++;
> + if (flags & RDES_RE)
> + ndev->stats.rx_missed_errors++;
> +
> + goto rx_failure;
> + }
> +
> + pktlen = flags & RDES_FLEN;
> + pktlen -= 4; /* Drop the CRC */
> +
> + /* Retrieve the sk_buff */
> + skb = ksp->rx_buffers[buff_n].skb;
> +
> + /* Clear it from the ring */
> + ksp->rx_buffers[buff_n].skb = NULL;
> + ksp->rx_ring[buff_n].data_ptr = 0;
> +
> + /* Unmap the SKB */
> + dma_unmap_single(ksp->dev,
> + ksp->rx_buffers[buff_n].dma_ptr,
> + ksp->rx_buffers[buff_n].length,
> + DMA_FROM_DEVICE);
> +
> + /* Relinquish the SKB to the network layer */
> + skb_put(skb, pktlen);
> + skb->protocol = eth_type_trans(skb, ndev);
> + netif_receive_skb(skb);
> +
> + /* Record stats */
> + ndev->stats.rx_packets++;
> + ndev->stats.rx_bytes += pktlen;
> + goto rx_finished;
> +
> +rx_failure:
> + /* This ring entry is an error, but we can
> + * re-use the skb
> + */
> + /* Give the ring entry back to the hardware */
> + ksp->rx_ring[buff_n].status = cpu_to_le32(RDES_OWN);
> +rx_finished:
> + received++;
> + /* And note this as processed so we can start
> + * from here next time
> + */
> + last_rx_processed = buff_n;
> + buff_n = (buff_n + 1) & MAX_RX_DESC_MASK;
> + /*And note which RX descriptor we last did */
> + if (likely(last_rx_processed != -1))
> + ksp->next_rx_desc_read =
> + (last_rx_processed + 1) &
> + MAX_RX_DESC_MASK;
> +
> + /* And refill the buffers */
> + ks8695_refill_rxbuffers(ksp);
> + }
> + return received;
> +}
> +
> +static int ks8695_poll(struct napi_struct *napi, int budget)
> +{
> + struct ks8695_priv *ksp = container_of(napi, struct ks8695_priv, napi);
> + struct net_device *dev = ksp->ndev;
> + unsigned long mask_bit = 1 << ksp->rx_irq;
> + unsigned long isr = __raw_readl(KS8695_IRQ_VA + KS8695_INTEN);
This is surely the wrong place to be reading this register.
> + unsigned long work_done = 0;
Pointless initialisation.
> +
> + work_done = ks8695_rx(dev, budget);
> +
> + if (work_done < budget) {
> + unsigned long flags;
> + spin_lock_irqsave(&ksp->rx_lock, flags);
> + /*enable rx interrupt*/
> + __raw_writel(isr | mask_bit, KS8695_IRQ_VA + KS8695_INTEN);
> + __napi_complete(napi);
> + spin_unlock_irqrestore(&ksp->rx_lock, flags);
> + }
> + return work_done;
> +}
> +
> +#else
> /**
> * ks8695_rx_irq - Receive IRQ handler
> * @irq: The IRQ which went off (ignored)
> @@ -503,6 +661,8 @@ rx_finished:
> return IRQ_HANDLED;
> }
>
> +#endif
> +
> /**
> * ks8695_link_irq - Link change IRQ handler
> * @irq: The IRQ which went off (ignored)
> @@ -1472,6 +1632,10 @@ ks8695_probe(struct platform_device *pdev)
> SET_ETHTOOL_OPS(ndev, &ks8695_ethtool_ops);
> ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
>
> +#ifdef KS8695NET_NAPI
> + netif_napi_add(ndev, &ksp->napi, ks8695_poll, 64);
> +#endif
> +
> /* Retrieve the default MAC addr from the chip. */
> /* The bootloader should have left it in there for us. */
>
> @@ -1505,6 +1669,7 @@ ks8695_probe(struct platform_device *pdev)
>
> /* And initialise the queue's lock */
> spin_lock_init(&ksp->txq_lock);
> + spin_lock_init(&ksp->rx_lock);
>
> /* Specify the RX DMA ring buffer */
> ksp->rx_ring = ksp->ring_base + TX_RING_DMA_SIZE;
You're missing a netif_napi_del() on removal.
Ben.
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH]NET/KS8695: add support NAPI for Rx
2009-10-26 16:49 ` Ben Hutchings
@ 2009-10-26 22:43 ` David Miller
0 siblings, 0 replies; 4+ messages in thread
From: David Miller @ 2009-10-26 22:43 UTC (permalink / raw)
To: bhutchings; +Cc: figo1802, dsilvers, netdev, vince, ben
From: Ben Hutchings <bhutchings@solarflare.com>
Date: Mon, 26 Oct 2009 16:49:06 +0000
>> @@ -152,6 +156,10 @@ struct ks8695_priv {
>> enum ks8695_dtype dtype;
>> void __iomem *io_regs;
>>
>> + #ifdef KS8695NET_NAPI
>> + struct napi_struct napi;
>> + #endif
>> +
>
> NAPI is well-established and there should be no need to make it
> optional. So far as I'm aware, all other drivers that had it as an
> option now use it unconditionally.
I absolutely refuse to apply this patch with the CPP conditional
present, if you convert to NAPI make it unconditional.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2009-10-26 22:42 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-10-26 16:00 [PATCH]NET/KS8695: add support NAPI for Rx Figo.zhang
2009-10-26 16:27 ` Daniel Silverstone
2009-10-26 16:49 ` Ben Hutchings
2009-10-26 22:43 ` David Miller
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).