Commit a774cdb7 authored by François Romieu's avatar François Romieu Committed by Jeff Garzik

[PATCH] r8169: napi support

Napi for r8169 (Jon D Mason <jonmason@us.ibm.com>).
Both Tx and Rx processing are moved to the ->poll() function.
parent bd7b6c43
...@@ -1987,6 +1987,11 @@ config R8169 ...@@ -1987,6 +1987,11 @@ config R8169
To compile this driver as a module, choose M here: the module To compile this driver as a module, choose M here: the module
will be called r8169. This is recommended. will be called r8169. This is recommended.
config R8169_NAPI
bool "Use Rx and Tx Polling (NAPI) (EXPERIMENTAL)"
depends on R8169 && EXPERIMENTAL
config SK98LIN config SK98LIN
tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support" tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support"
depends on PCI depends on PCI
......
...@@ -64,6 +64,14 @@ VERSION 1.2 <2002/11/30> ...@@ -64,6 +64,14 @@ VERSION 1.2 <2002/11/30>
#define dprintk(fmt, args...) do {} while (0) #define dprintk(fmt, args...) do {} while (0)
#endif /* RTL8169_DEBUG */ #endif /* RTL8169_DEBUG */
#ifdef CONFIG_R8169_NAPI
#define rtl8169_rx_skb netif_receive_skb
#define rtl8169_rx_quota(count, quota) min(count, quota)
#else
#define rtl8169_rx_skb netif_rx
#define rtl8169_rx_quota(count, quota) count
#endif
/* media options */ /* media options */
#define MAX_UNITS 8 #define MAX_UNITS 8
static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 }; static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 };
...@@ -90,8 +98,9 @@ static int multicast_filter_limit = 32; ...@@ -90,8 +98,9 @@ static int multicast_filter_limit = 32;
#define RxPacketMaxSize 0x0800 /* Maximum size supported is 16K-1 */ #define RxPacketMaxSize 0x0800 /* Maximum size supported is 16K-1 */
#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ #define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */
#define R8169_NAPI_WEIGHT 64
#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */ #define NUM_TX_DESC 64 /* Number of Tx descriptor registers */
#define NUM_RX_DESC 64 /* Number of Rx descriptor registers */ #define NUM_RX_DESC 256 /* Number of Rx descriptor registers */
#define RX_BUF_SIZE 1536 /* Rx Buffer size */ #define RX_BUF_SIZE 1536 /* Rx Buffer size */
#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) #define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc))
#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) #define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc))
...@@ -326,6 +335,7 @@ struct rtl8169_private { ...@@ -326,6 +335,7 @@ struct rtl8169_private {
struct timer_list timer; struct timer_list timer;
unsigned long phy_link_down_cnt; unsigned long phy_link_down_cnt;
u16 cp_cmd; u16 cp_cmd;
u16 intr_mask;
}; };
MODULE_AUTHOR("Realtek"); MODULE_AUTHOR("Realtek");
...@@ -344,9 +354,14 @@ static int rtl8169_close(struct net_device *dev); ...@@ -344,9 +354,14 @@ static int rtl8169_close(struct net_device *dev);
static void rtl8169_set_rx_mode(struct net_device *dev); static void rtl8169_set_rx_mode(struct net_device *dev);
static void rtl8169_tx_timeout(struct net_device *dev); static void rtl8169_tx_timeout(struct net_device *dev);
static struct net_device_stats *rtl8169_get_stats(struct net_device *netdev); static struct net_device_stats *rtl8169_get_stats(struct net_device *netdev);
#ifdef CONFIG_R8169_NAPI
static int rtl8169_poll(struct net_device *dev, int *budget);
#endif
static const u16 rtl8169_intr_mask = static const u16 rtl8169_intr_mask =
RxUnderrun | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK; RxUnderrun | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK;
static const u16 rtl8169_napi_event =
RxOK | RxUnderrun | RxOverflow | RxFIFOOver | TxOK | TxErr;
static const unsigned int rtl8169_rx_config = static const unsigned int rtl8169_rx_config =
(RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift);
...@@ -836,9 +851,12 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -836,9 +851,12 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
dev->watchdog_timeo = RTL8169_TX_TIMEOUT; dev->watchdog_timeo = RTL8169_TX_TIMEOUT;
dev->irq = pdev->irq; dev->irq = pdev->irq;
dev->base_addr = (unsigned long) ioaddr; dev->base_addr = (unsigned long) ioaddr;
// dev->do_ioctl = mii_ioctl; #ifdef CONFIG_R8169_NAPI
dev->poll = rtl8169_poll;
tp = dev->priv; // private data // dev->weight = R8169_NAPI_WEIGHT;
printk(KERN_INFO PFX "NAPI enabled\n");
#endif
tp->intr_mask = 0xffff;
tp->pci_dev = pdev; tp->pci_dev = pdev;
tp->mmio_addr = ioaddr; tp->mmio_addr = ioaddr;
...@@ -1442,11 +1460,11 @@ static inline int rtl8169_try_rx_copy(struct sk_buff **sk_buff, int pkt_size, ...@@ -1442,11 +1460,11 @@ static inline int rtl8169_try_rx_copy(struct sk_buff **sk_buff, int pkt_size,
return ret; return ret;
} }
static void static int
rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
void *ioaddr) void *ioaddr)
{ {
unsigned long cur_rx, rx_left; unsigned int cur_rx, rx_left, count;
int delta; int delta;
assert(dev != NULL); assert(dev != NULL);
...@@ -1455,6 +1473,7 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, ...@@ -1455,6 +1473,7 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
cur_rx = tp->cur_rx; cur_rx = tp->cur_rx;
rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;
rx_left = rtl8169_rx_quota(rx_left, (u32) dev->quota);
while (rx_left > 0) { while (rx_left > 0) {
int entry = cur_rx % NUM_RX_DESC; int entry = cur_rx % NUM_RX_DESC;
...@@ -1494,7 +1513,7 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, ...@@ -1494,7 +1513,7 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
skb_put(skb, pkt_size); skb_put(skb, pkt_size);
skb->protocol = eth_type_trans(skb, dev); skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb); rtl8169_rx_skb(skb);
dev->last_rx = jiffies; dev->last_rx = jiffies;
tp->stats.rx_bytes += pkt_size; tp->stats.rx_bytes += pkt_size;
...@@ -1505,13 +1524,15 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, ...@@ -1505,13 +1524,15 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
rx_left--; rx_left--;
} }
count = cur_rx - tp->cur_rx;
tp->cur_rx = cur_rx; tp->cur_rx = cur_rx;
delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx); delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx);
if (delta > 0) if (delta < 0) {
tp->dirty_rx += delta;
else if (delta < 0)
printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name); printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name);
delta = 0;
}
tp->dirty_rx += delta;
/* /*
* FIXME: until there is periodic timer to try and refill the ring, * FIXME: until there is periodic timer to try and refill the ring,
...@@ -1522,6 +1543,8 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, ...@@ -1522,6 +1543,8 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
*/ */
if (tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) if (tp->dirty_rx + NUM_RX_DESC == tp->cur_rx)
printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name); printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name);
return count;
} }
/* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */
...@@ -1547,12 +1570,25 @@ rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs) ...@@ -1547,12 +1570,25 @@ rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
if (status & RxUnderrun) if (status & RxUnderrun)
link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit;
*/ */
status &= tp->intr_mask;
RTL_W16(IntrStatus, RTL_W16(IntrStatus,
(status & RxFIFOOver) ? (status | RxOverflow) : status); (status & RxFIFOOver) ? (status | RxOverflow) : status);
if (!(status & rtl8169_intr_mask)) if (!(status & rtl8169_intr_mask))
break; break;
#ifdef CONFIG_R8169_NAPI
RTL_W16(IntrMask, rtl8169_intr_mask & ~rtl8169_napi_event);
tp->intr_mask = ~rtl8169_napi_event;
if (likely(netif_rx_schedule_prep(dev)))
__netif_rx_schedule(dev);
else {
printk(KERN_INFO "%s: interrupt %x taken in poll\n",
dev->name, status);
}
break;
#else
// Rx interrupt // Rx interrupt
if (status & (RxOK | RxUnderrun | RxOverflow | RxFIFOOver)) { if (status & (RxOK | RxUnderrun | RxOverflow | RxFIFOOver)) {
rtl8169_rx_interrupt(dev, tp, ioaddr); rtl8169_rx_interrupt(dev, tp, ioaddr);
...@@ -1563,6 +1599,7 @@ rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs) ...@@ -1563,6 +1599,7 @@ rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
rtl8169_tx_interrupt(dev, tp, ioaddr); rtl8169_tx_interrupt(dev, tp, ioaddr);
spin_unlock(&tp->lock); spin_unlock(&tp->lock);
} }
#endif
boguscnt--; boguscnt--;
} while (boguscnt > 0); } while (boguscnt > 0);
...@@ -1576,6 +1613,36 @@ rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs) ...@@ -1576,6 +1613,36 @@ rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
return IRQ_RETVAL(handled); return IRQ_RETVAL(handled);
} }
#ifdef CONFIG_R8169_NAPI
static int rtl8169_poll(struct net_device *dev, int *budget)
{
unsigned int work_done, work_to_do = min(*budget, dev->quota);
struct rtl8169_private *tp = netdev_priv(dev);
void *ioaddr = tp->mmio_addr;
work_done = rtl8169_rx_interrupt(dev, tp, ioaddr);
rtl8169_tx_interrupt(dev, tp, ioaddr);
*budget -= work_done;
dev->quota -= work_done;
if ((work_done < work_to_do) || !netif_running(dev)) {
netif_rx_complete(dev);
tp->intr_mask = 0xffff;
/*
* 20040426: the barrier is not strictly required but the
* behavior of the irq handler could be less predictable
* without it. Btw, the lack of flush for the posted pci
* write is safe - FR
*/
smp_wmb();
RTL_W16(IntrMask, rtl8169_intr_mask);
}
return (work_done >= work_to_do);
}
#endif
static int static int
rtl8169_close(struct net_device *dev) rtl8169_close(struct net_device *dev)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment