From fdee1a5a5a85fc23f3360a19cc09fd0e7c9b4c85 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <juhosg@openwrt.org>
Date: Thu, 31 Jan 2008 10:18:58 +0000
Subject: [PATCH] add a 2.6.24 specific patch for the switch driver, thanks to
 Francesco Gringoli for his 2.6.24-rc2 patch

SVN-Revision: 10337
---
 .../900-adm5120_switch_napi.patch             | 144 ++++++++++++++++++
 1 file changed, 144 insertions(+)
 create mode 100644 target/linux/adm5120/patches-2.6.24/900-adm5120_switch_napi.patch

diff --git a/target/linux/adm5120/patches-2.6.24/900-adm5120_switch_napi.patch b/target/linux/adm5120/patches-2.6.24/900-adm5120_switch_napi.patch
new file mode 100644
index 0000000000..5c757a10b4
--- /dev/null
+++ b/target/linux/adm5120/patches-2.6.24/900-adm5120_switch_napi.patch
@@ -0,0 +1,144 @@
+Index: linux-2.6.24/drivers/net/adm5120sw.c
+===================================================================
+--- linux-2.6.24.orig/drivers/net/adm5120sw.c
++++ linux-2.6.24/drivers/net/adm5120sw.c
+@@ -93,8 +93,14 @@
+ /* ------------------------------------------------------------------------ */
+ 
+ struct adm5120_if_priv {
++	struct net_device *dev;
++
+ 	unsigned int	vlan_no;
+ 	unsigned int	port_mask;
++
++#ifdef CONFIG_ADM5120_SWITCH_NAPI
++	struct napi_struct napi;
++#endif
+ };
+ 
+ struct dma_desc {
+@@ -333,7 +339,6 @@ static void sw_dump_regs(void)
+ 	SW_DBG("rlda: %08X\n", t);
+ }
+ 
+-
+ /* ------------------------------------------------------------------------ */
+ 
+ static inline void adm5120_rx_dma_update(struct dma_desc *desc,
+@@ -495,9 +500,11 @@ static void adm5120_switch_tx(void)
+ }
+ 
+ #ifdef CONFIG_ADM5120_SWITCH_NAPI
+-static int adm5120_if_poll(struct net_device *dev, int *budget)
++static int adm5120_if_poll(struct napi_struct *napi, int limit)
+ {
+-	int limit = min(dev->quota, *budget);
++	struct adm5120_if_priv *priv = container_of(napi,
++				struct adm5120_if_priv, napi);
++	struct net_device *dev = priv->dev;
+ 	int done;
+ 	u32 status;
+ 
+@@ -509,13 +516,10 @@ static int adm5120_if_poll(struct net_de
+ 	SW_DBG("%s: processing RX ring\n", dev->name);
+ 	done = adm5120_switch_rx(limit);
+ 
+-	*budget -= done;
+-	dev->quota -= done;
+-
+ 	status = sw_int_status() & SWITCH_INTS_POLL;
+ 	if ((done < limit) && (!status)) {
+ 		SW_DBG("disable polling mode for %s\n", dev->name);
+-		netif_rx_complete(dev);
++		netif_rx_complete(dev, napi);
+ 		sw_int_unmask(SWITCH_INTS_POLL);
+ 		return 0;
+ 	}
+@@ -541,10 +545,12 @@ static irqreturn_t adm5120_switch_irq(in
+ 
+ 	if (status & SWITCH_INTS_POLL) {
+ 		struct net_device *dev = dev_id;
++		struct adm5120_if_priv *priv = netdev_priv(dev);
++
+ 		sw_dump_intr_mask("poll ints", status);
+ 		SW_DBG("enable polling mode for %s\n", dev->name);
+ 		sw_int_mask(SWITCH_INTS_POLL);
+-		netif_rx_schedule(dev);
++		netif_rx_schedule(dev, &priv->napi);
+ 	}
+ #else
+ 	sw_int_ack(status);
+@@ -779,12 +785,31 @@ static void adm5120_switch_set_vlan_port
+ 
+ /* ------------------------------------------------------------------------ */
+ 
++#ifdef CONFIG_ADM5120_SWITCH_NAPI
++static inline void adm5120_if_napi_enable(struct net_device *dev)
++{
++	struct adm5120_if_priv *priv = netdev_priv(dev);
++	napi_enable(&priv->napi);
++}
++
++static inline void adm5120_if_napi_disable(struct net_device *dev)
++{
++	struct adm5120_if_priv *priv = netdev_priv(dev);
++	napi_disable(&priv->napi);
++}
++#else
++static inline void adm5120_if_napi_enable(struct net_device *dev) {}
++static inline void adm5120_if_napi_disable(struct net_device *dev) {}
++#endif /* CONFIG_ADM5120_SWITCH_NAPI */
++
+ static int adm5120_if_open(struct net_device *dev)
+ {
+ 	u32 t;
+ 	int err;
+ 	int i;
+ 
++	adm5120_if_napi_enable(dev);
++
+ 	err = request_irq(dev->irq, adm5120_switch_irq,
+ 		(IRQF_SHARED | IRQF_DISABLED), dev->name, dev);
+ 	if (err) {
+@@ -809,6 +834,7 @@ static int adm5120_if_open(struct net_de
+ 	return 0;
+ 
+ err:
++	adm5120_if_napi_disable(dev);
+ 	return err;
+ }
+ 
+@@ -818,6 +844,7 @@ static int adm5120_if_stop(struct net_de
+ 	int i;
+ 
+ 	netif_stop_queue(dev);
++	adm5120_if_napi_disable(dev);
+ 
+ 	/* disable port if not assigned to other devices */
+ 	t = sw_read_reg(SWITCH_REG_PORT_CONF0);
+@@ -1001,6 +1028,9 @@ static struct net_device *adm5120_if_all
+ 	if (!dev)
+ 		return NULL;
+ 
++	priv = netdev_priv(dev);
++	priv->dev = dev;
++
+ 	dev->irq		= ADM5120_IRQ_SWITCH;
+ 	dev->open		= adm5120_if_open;
+ 	dev->hard_start_xmit 	= adm5120_if_hard_start_xmit;
+@@ -1010,13 +1040,11 @@ static struct net_device *adm5120_if_all
+ 	dev->tx_timeout		= adm5120_if_tx_timeout;
+ 	dev->watchdog_timeo 	= TX_TIMEOUT;
+ 	dev->set_mac_address 	= adm5120_if_set_mac_address;
++
+ #ifdef CONFIG_ADM5120_SWITCH_NAPI
+-	dev->poll		= adm5120_if_poll;
+-	dev->weight		= 64;
++	netif_napi_add(dev, &priv->napi, adm5120_if_poll, 64);
+ #endif
+ 
+-	SET_MODULE_OWNER(dev);
+-
+ 	return dev;
+ }
+ 
-- 
2.30.2