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; }