* [patch 0/7] 2.6.6-rc3-mm1 - description of the r8169 queue
@ 2004-05-01 0:23 Francois Romieu
2004-05-01 0:24 ` [patch 1/7] 2.6.6-rc3-mm1 - r8169 napi Francois Romieu
` (3 more replies)
0 siblings, 4 replies; 11+ messages in thread
From: Francois Romieu @ 2004-05-01 0:23 UTC (permalink / raw)
To: jgarzik; +Cc: Andy Lutomirski, Jon D Mason, netdev
With some delay, the following patches include Jon D Mason's NAPI changes
(+ fixes) and code from Andy Lutomirski with minor changes.
I have not moved the initialization of the phy timer in the pci probe
routine as:
- I believe it belongs to the netdevice;
- it should work as is without significant change for the user.
If someone sees a good reason to move it, just complain (with an axe).
The patches apply to 2.6.6-rc3 as well as to 2.6.6-rc3-mm1.
All the patches are merged in a single patch against 2.6.6-rc3 available at:
http://www.fr.zoreil.com/people/francois/misc/20040501-2.6.6-rc3-r8169.c-test.patch
The patches are archived below as well:
http://www.fr.zoreil.com/linux/kernel/2.6.x/2.6.6-rc3
If the patches prove to behave decently on 2.6, a backport for 2.4.x will be
generated.
--
Ueimor
^ permalink raw reply [flat|nested] 11+ messages in thread* [patch 1/7] 2.6.6-rc3-mm1 - r8169 napi 2004-05-01 0:23 [patch 0/7] 2.6.6-rc3-mm1 - description of the r8169 queue Francois Romieu @ 2004-05-01 0:24 ` Francois Romieu 2004-05-01 0:25 ` [patch 2/7] 2.6.6-rc3-mm1 - r8169 janitoring Francois Romieu 2004-05-01 6:32 ` [patch 0/7] 2.6.6-rc3-mm1 - description of the r8169 queue Andy Lutomirski ` (2 subsequent siblings) 3 siblings, 1 reply; 11+ messages in thread From: Francois Romieu @ 2004-05-01 0:24 UTC (permalink / raw) To: jgarzik; +Cc: Andy Lutomirski, Jon D Mason, netdev Napi for r8169 (Jon D Mason <jonmason@us.ibm.com>). Both Tx and Rx processing are moved to the ->poll() function. diff -puN drivers/net/r8169.c~r8169-napi drivers/net/r8169.c --- linux-2.6.6-rc3/drivers/net/r8169.c~r8169-napi 2004-05-01 01:46:29.000000000 +0200 +++ linux-2.6.6-rc3-fr/drivers/net/r8169.c 2004-05-01 01:46:29.000000000 +0200 @@ -64,6 +64,14 @@ VERSION 1.2 <2002/11/30> #define dprintk(fmt, args...) do {} while (0) #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 */ #define MAX_UNITS 8 static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 }; @@ -90,8 +98,9 @@ static int multicast_filter_limit = 32; #define RxPacketMaxSize 0x0800 /* Maximum size supported is 16K-1 */ #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_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 R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) #define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) @@ -326,6 +335,7 @@ struct rtl8169_private { struct timer_list timer; unsigned long phy_link_down_cnt; u16 cp_cmd; + u16 intr_mask; }; MODULE_AUTHOR("Realtek"); @@ -344,9 +354,14 @@ static int rtl8169_close(struct net_devi static void rtl8169_set_rx_mode(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); +#ifdef CONFIG_R8169_NAPI +static int rtl8169_poll(struct net_device *dev, int *budget); +#endif 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 = (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); @@ -836,9 +851,12 @@ rtl8169_init_one(struct pci_dev *pdev, c dev->watchdog_timeo = RTL8169_TX_TIMEOUT; dev->irq = pdev->irq; dev->base_addr = (unsigned long) ioaddr; -// dev->do_ioctl = mii_ioctl; - - tp = dev->priv; // private data // +#ifdef CONFIG_R8169_NAPI + dev->poll = rtl8169_poll; + dev->weight = R8169_NAPI_WEIGHT; + printk(KERN_INFO PFX "NAPI enabled\n"); +#endif + tp->intr_mask = 0xffff; tp->pci_dev = pdev; tp->mmio_addr = ioaddr; @@ -1442,11 +1460,11 @@ static inline int rtl8169_try_rx_copy(st return ret; } -static void +static int rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, void *ioaddr) { - unsigned long cur_rx, rx_left; + unsigned int cur_rx, rx_left, count; int delta; assert(dev != NULL); @@ -1455,6 +1473,7 @@ rtl8169_rx_interrupt(struct net_device * cur_rx = tp->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) { int entry = cur_rx % NUM_RX_DESC; @@ -1494,7 +1513,7 @@ rtl8169_rx_interrupt(struct net_device * skb_put(skb, pkt_size); skb->protocol = eth_type_trans(skb, dev); - netif_rx(skb); + rtl8169_rx_skb(skb); dev->last_rx = jiffies; tp->stats.rx_bytes += pkt_size; @@ -1505,13 +1524,15 @@ rtl8169_rx_interrupt(struct net_device * rx_left--; } + count = cur_rx - tp->cur_rx; tp->cur_rx = cur_rx; delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx); - if (delta > 0) - tp->dirty_rx += delta; - else if (delta < 0) + if (delta < 0) { 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, @@ -1522,6 +1543,8 @@ rtl8169_rx_interrupt(struct net_device * */ if (tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) 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. */ @@ -1547,12 +1570,25 @@ rtl8169_interrupt(int irq, void *dev_ins if (status & RxUnderrun) link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; */ + status &= tp->intr_mask; RTL_W16(IntrStatus, (status & RxFIFOOver) ? (status | RxOverflow) : status); if (!(status & rtl8169_intr_mask)) 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 if (status & (RxOK | RxUnderrun | RxOverflow | RxFIFOOver)) { rtl8169_rx_interrupt(dev, tp, ioaddr); @@ -1563,6 +1599,7 @@ rtl8169_interrupt(int irq, void *dev_ins rtl8169_tx_interrupt(dev, tp, ioaddr); spin_unlock(&tp->lock); } +#endif boguscnt--; } while (boguscnt > 0); @@ -1576,6 +1613,36 @@ rtl8169_interrupt(int irq, void *dev_ins 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 rtl8169_close(struct net_device *dev) { diff -puN drivers/net/Kconfig~r8169-napi drivers/net/Kconfig --- linux-2.6.6-rc3/drivers/net/Kconfig~r8169-napi 2004-05-01 01:46:29.000000000 +0200 +++ linux-2.6.6-rc3-fr/drivers/net/Kconfig 2004-05-01 01:46:29.000000000 +0200 @@ -1979,6 +1979,11 @@ config R8169 To compile this driver as a module, choose M here: the module will be called r8169. This is recommended. +config R8169_NAPI + bool "Use Rx and Tx Polling (NAPI) (EXPERIMENTAL)" + depends on R8169 && EXPERIMENTAL + + config SK98LIN tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support" depends on PCI _ ^ permalink raw reply [flat|nested] 11+ messages in thread
* [patch 2/7] 2.6.6-rc3-mm1 - r8169 janitoring 2004-05-01 0:24 ` [patch 1/7] 2.6.6-rc3-mm1 - r8169 napi Francois Romieu @ 2004-05-01 0:25 ` Francois Romieu 2004-05-01 0:26 ` [patch 3/7] 2.6.6-rc3-mm1 - r8169 register rename Francois Romieu 0 siblings, 1 reply; 11+ messages in thread From: Francois Romieu @ 2004-05-01 0:25 UTC (permalink / raw) To: jgarzik; +Cc: Andy Lutomirski, Jon D Mason, netdev Spring cleanup - missing ULL qualifier; - unsigned int (u32) should be slightly faster on ppc64 (Jon D Mason); - misc minor de-uglyfication. diff -puN drivers/net/r8169.c~r8169-janitorial drivers/net/r8169.c --- linux-2.6.6-rc3/drivers/net/r8169.c~r8169-janitorial 2004-05-01 01:46:31.000000000 +0200 +++ linux-2.6.6-rc3-fr/drivers/net/r8169.c 2004-05-01 01:46:31.000000000 +0200 @@ -315,10 +315,10 @@ struct RxDesc { }; struct rtl8169_private { - void *mmio_addr; /* memory map physical address */ + void *mmio_addr; /* memory map physical address */ struct pci_dev *pci_dev; /* Index of PCI device */ struct net_device_stats stats; /* statistics of net device */ - spinlock_t lock; /* spin lock flag */ + spinlock_t lock; /* spin lock flag */ int chipset; int mac_version; int phy_version; @@ -326,12 +326,12 @@ struct rtl8169_private { u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ u32 dirty_rx; u32 dirty_tx; - struct TxDesc *TxDescArray; /* Index of 256-alignment Tx Descriptor buffer */ - struct RxDesc *RxDescArray; /* Index of 256-alignment Rx Descriptor buffer */ + struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ + struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ dma_addr_t TxPhyAddr; dma_addr_t RxPhyAddr; struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ - struct sk_buff *Tx_skbuff[NUM_TX_DESC]; /* Index of Transmit data buffer */ + struct sk_buff *Tx_skbuff[NUM_TX_DESC]; /* Tx data buffers */ struct timer_list timer; unsigned long phy_link_down_cnt; u16 cp_cmd; @@ -379,11 +379,9 @@ static void mdio_write(void *ioaddr, int for (i = 2000; i > 0; i--) { // Check if the RTL8169 has completed writing to the specified MII register - if (!(RTL_R32(PHYAR) & 0x80000000)) { + if (!(RTL_R32(PHYAR) & 0x80000000)) break; - } else { - udelay(100); - } + udelay(100); } } @@ -408,7 +406,7 @@ static int mdio_read(void *ioaddr, int R static void rtl8169_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); strcpy(info->driver, RTL8169_DRIVER_NAME); strcpy(info->version, RTL8169_VERSION ); @@ -515,7 +513,7 @@ static void rtl8169_print_phy_version(st static void rtl8169_hw_phy_config(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; struct { u16 regs[5]; /* Beware of bit-sign propagation */ @@ -583,7 +581,7 @@ static void rtl8169_hw_phy_config(struct static void rtl8169_hw_phy_reset(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; int i, val; @@ -607,7 +605,7 @@ static void rtl8169_hw_phy_reset(struct static void rtl8169_phy_timer(unsigned long __opaque) { struct net_device *dev = (struct net_device *)__opaque; - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); struct timer_list *timer = &tp->timer; void *ioaddr = tp->mmio_addr; @@ -635,7 +633,7 @@ static void rtl8169_phy_timer(unsigned l static inline void rtl8169_delete_timer(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); struct timer_list *timer = &tp->timer; if ((tp->mac_version <= RTL_GIGA_MAC_VER_B) || @@ -649,7 +647,7 @@ static inline void rtl8169_delete_timer( static inline void rtl8169_request_timer(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); struct timer_list *timer = &tp->timer; if ((tp->mac_version <= RTL_GIGA_MAC_VER_B) || @@ -696,7 +694,7 @@ rtl8169_init_board(struct pci_dev *pdev, // enable device (incl. PCI PM wakeup and hotplug setup) rc = pci_enable_device(pdev); if (rc) { - printk(KERN_ERR PFX "%s: unable to enable device\n", pdev->slot_name); + printk(KERN_ERR PFX "%s: enable failure\n", pdev->slot_name); goto err_out; } @@ -708,7 +706,8 @@ rtl8169_init_board(struct pci_dev *pdev, pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command); acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK; } else { - printk(KERN_ERR PFX "Cannot find PowerManagement capability, aborting.\n"); + printk(KERN_ERR PFX + "Cannot find PowerManagement capability, aborting.\n"); goto err_out_free_res; } @@ -733,7 +732,8 @@ rtl8169_init_board(struct pci_dev *pdev, rc = pci_request_regions(pdev, dev->name); if (rc) { - printk(KERN_ERR PFX "%s: Could not request regions.\n", pdev->slot_name); + printk(KERN_ERR PFX "%s: could not request regions.\n", + pdev->slot_name); goto err_out_disable; } @@ -937,13 +937,16 @@ rtl8169_init_one(struct pci_dev *pdev, c default: break; } - mdio_write(ioaddr, PHY_AUTO_NEGO_REG, Cap10_100 | (val & 0x1F)); //leave PHY_AUTO_NEGO_REG bit4:0 unchanged + // leave PHY_AUTO_NEGO_REG bit4:0 unchanged + mdio_write(ioaddr, PHY_AUTO_NEGO_REG, + Cap10_100 | (val & 0x1F)); mdio_write(ioaddr, PHY_1000_CTRL_REG, Cap1000); } else { printk(KERN_INFO "%s: Auto-negotiation Enabled.\n", dev->name); - // enable 10/100 Full/Half Mode, leave PHY_AUTO_NEGO_REG bit4:0 unchanged + // enable 10/100 Full/Half Mode + // leave PHY_AUTO_NEGO_REG bit4:0 unchanged mdio_write(ioaddr, PHY_AUTO_NEGO_REG, PHY_Cap_100_Full_Or_Less | (val & 0x1f)); @@ -982,7 +985,7 @@ rtl8169_init_one(struct pci_dev *pdev, c } else { udelay(100); } - } // end for-loop to wait for auto-negotiation process + } // end for-loop to wait for auto-negotiation process } else { udelay(100); @@ -990,7 +993,6 @@ rtl8169_init_one(struct pci_dev *pdev, c "%s: 1000Mbps Full-duplex operation, TBI Link %s!\n", dev->name, (RTL_R32(TBICSR) & TBILinkOK) ? "OK" : "Failed"); - } return 0; @@ -1000,7 +1002,7 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); assert(dev != NULL); assert(tp != NULL); @@ -1019,7 +1021,7 @@ rtl8169_remove_one(struct pci_dev *pdev) static int rtl8169_suspend(struct pci_dev *pdev, u32 state) { struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; unsigned long flags; @@ -1060,7 +1062,7 @@ static int rtl8169_resume(struct pci_dev static int rtl8169_open(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); struct pci_dev *pdev = tp->pci_dev; int retval; @@ -1109,7 +1111,7 @@ err_free_irq: static void rtl8169_hw_start(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; u32 i; @@ -1120,8 +1122,7 @@ rtl8169_hw_start(struct net_device *dev) for (i = 1000; i > 0; i--) { if ((RTL_R8(ChipCmd) & CmdReset) == 0) break; - else - udelay(10); + udelay(10); } RTL_W8(Cfg9346, Cfg9346_Unlock); @@ -1132,8 +1133,8 @@ rtl8169_hw_start(struct net_device *dev) RTL_W16(RxMaxSize, RxPacketMaxSize); // Set Rx Config register - i = rtl8169_rx_config | (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset]. - RxConfigMask); + i = rtl8169_rx_config | + (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); RTL_W32(RxConfig, i); /* Set DMA burst size and Interframe Gap Time */ @@ -1144,7 +1145,8 @@ rtl8169_hw_start(struct net_device *dev) RTL_W16(CPlusCmd, tp->cp_cmd); if (tp->mac_version == RTL_GIGA_MAC_VER_D) { - dprintk(KERN_INFO PFX "Set MAC Reg C+CR Offset 0xE0: bit-3 and bit-14 MUST be 1\n"); + dprintk(KERN_INFO PFX "Set MAC Reg C+CR Offset 0xE0. " + "Bit-3 and bit-14 MUST be 1\n"); tp->cp_cmd |= (1 << 14) | PCIMulRW; RTL_W16(CPlusCmd, tp->cp_cmd); } @@ -1169,12 +1171,11 @@ rtl8169_hw_start(struct net_device *dev) RTL_W16(IntrMask, rtl8169_intr_mask); netif_start_queue(dev); - } static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) { - desc->addr = 0x0badbadbadbadbad; + desc->addr = 0x0badbadbadbadbadULL; desc->status &= ~cpu_to_le32(OWNbit | RsvdMask); } @@ -1266,7 +1267,7 @@ static inline void rtl8169_mark_as_last_ static int rtl8169_init_ring(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); tp->cur_rx = tp->dirty_rx = 0; tp->cur_tx = tp->dirty_tx = 0; @@ -1320,10 +1321,11 @@ rtl8169_tx_clear(struct rtl8169_private static void rtl8169_tx_timeout(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; u8 tmp8; + printk(KERN_INFO "%s: TX Timeout\n", dev->name); /* disable Tx, if not already */ tmp8 = RTL_R8(ChipCmd); if (tmp8 & CmdTxEnb) @@ -1346,9 +1348,9 @@ rtl8169_tx_timeout(struct net_device *de static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; - int entry = tp->cur_tx % NUM_TX_DESC; + unsigned int entry = tp->cur_tx % NUM_TX_DESC; u32 len = skb->len; if (unlikely(skb->len < ETH_ZLEN)) { @@ -1400,7 +1402,7 @@ static void rtl8169_tx_interrupt(struct net_device *dev, struct rtl8169_private *tp, void *ioaddr) { - unsigned long dirty_tx, tx_left; + unsigned int dirty_tx, tx_left; assert(dev != NULL); assert(tp != NULL); @@ -1410,7 +1412,7 @@ rtl8169_tx_interrupt(struct net_device * tx_left = tp->cur_tx - dirty_tx; while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; + unsigned int entry = dirty_tx % NUM_TX_DESC; struct sk_buff *skb = tp->Tx_skbuff[entry]; u32 status; @@ -1476,7 +1478,7 @@ rtl8169_rx_interrupt(struct net_device * rx_left = rtl8169_rx_quota(rx_left, (u32) dev->quota); while (rx_left > 0) { - int entry = cur_rx % NUM_RX_DESC; + unsigned int entry = cur_rx % NUM_RX_DESC; u32 status; rmb(); @@ -1552,7 +1554,7 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs) { struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); int boguscnt = max_interrupt_work; void *ioaddr = tp->mmio_addr; int status = 0; @@ -1646,7 +1648,7 @@ static int rtl8169_poll(struct net_devic static int rtl8169_close(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); struct pci_dev *pdev = tp->pci_dev; void *ioaddr = tp->mmio_addr; @@ -1688,7 +1690,7 @@ rtl8169_close(struct net_device *dev) static void rtl8169_set_rx_mode(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; unsigned long flags; u32 mc_filter[2]; /* Multicast hash filter */ @@ -1722,10 +1724,8 @@ rtl8169_set_rx_mode(struct net_device *d spin_lock_irqsave(&tp->lock, flags); - tmp = - rtl8169_rx_config | rx_mode | (RTL_R32(RxConfig) & - rtl_chip_info[tp->chipset]. - RxConfigMask); + tmp = rtl8169_rx_config | rx_mode | + (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); RTL_W32(RxConfig, tmp); RTL_W32(MAR0 + 0, mc_filter[0]); @@ -1742,7 +1742,7 @@ rtl8169_set_rx_mode(struct net_device *d */ static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; unsigned long flags; _ ^ permalink raw reply [flat|nested] 11+ messages in thread
* [patch 3/7] 2.6.6-rc3-mm1 - r8169 register rename 2004-05-01 0:25 ` [patch 2/7] 2.6.6-rc3-mm1 - r8169 janitoring Francois Romieu @ 2004-05-01 0:26 ` Francois Romieu 2004-05-01 0:28 ` [patch 4/7] 2.6.6-rc3-mm1 - r8169 ethtool .set_settings Francois Romieu 0 siblings, 1 reply; 11+ messages in thread From: Francois Romieu @ 2004-05-01 0:26 UTC (permalink / raw) To: jgarzik; +Cc: Andy Lutomirski, Jon D Mason, netdev RxUnderrun status bit renamed to LinkChg (identical to the 8139cp driver). diff -puN drivers/net/r8169.c~r8169-register-rename drivers/net/r8169.c --- linux-2.6.6-rc3/drivers/net/r8169.c~r8169-register-rename 2004-05-01 01:46:33.000000000 +0200 +++ linux-2.6.6-rc3-fr/drivers/net/r8169.c 2004-05-01 01:46:33.000000000 +0200 @@ -203,7 +203,7 @@ enum RTL8169_register_content { SWInt = 0x0100, TxDescUnavail = 0x80, RxFIFOOver = 0x40, - RxUnderrun = 0x20, + LinkChg = 0x20, RxOverflow = 0x10, TxErr = 0x08, TxOK = 0x04, @@ -359,9 +359,9 @@ static int rtl8169_poll(struct net_devic #endif static const u16 rtl8169_intr_mask = - RxUnderrun | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK; + LinkChg | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK; static const u16 rtl8169_napi_event = - RxOK | RxUnderrun | RxOverflow | RxFIFOOver | TxOK | TxErr; + RxOK | LinkChg | RxOverflow | RxFIFOOver | TxOK | TxErr; static const unsigned int rtl8169_rx_config = (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); @@ -1569,7 +1569,7 @@ rtl8169_interrupt(int irq, void *dev_ins handled = 1; /* - if (status & RxUnderrun) + if (status & LinkChg) link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; */ status &= tp->intr_mask; @@ -1592,7 +1592,7 @@ rtl8169_interrupt(int irq, void *dev_ins break; #else // Rx interrupt - if (status & (RxOK | RxUnderrun | RxOverflow | RxFIFOOver)) { + if (status & (RxOK | LinkChg | RxOverflow | RxFIFOOver)) { rtl8169_rx_interrupt(dev, tp, ioaddr); } // Tx interrupt _ ^ permalink raw reply [flat|nested] 11+ messages in thread
* [patch 4/7] 2.6.6-rc3-mm1 - r8169 ethtool .set_settings 2004-05-01 0:26 ` [patch 3/7] 2.6.6-rc3-mm1 - r8169 register rename Francois Romieu @ 2004-05-01 0:28 ` Francois Romieu 2004-05-01 0:29 ` [patch 5/7] 2.6.6-rc3-mm1 - r8169 ethtool .get_settings Francois Romieu 0 siblings, 1 reply; 11+ messages in thread From: Francois Romieu @ 2004-05-01 0:28 UTC (permalink / raw) To: jgarzik; +Cc: Andy Lutomirski, Jon D Mason, netdev ethtool set_settings support (Andy Lutomirski <luto@myrealbox.com>). diff -puN drivers/net/r8169.c~r8169-ethtool-set_settings drivers/net/r8169.c --- linux-2.6.6-rc3/drivers/net/r8169.c~r8169-ethtool-set_settings 2004-05-01 01:46:36.000000000 +0200 +++ linux-2.6.6-rc3-fr/drivers/net/r8169.c 2004-05-01 01:46:36.000000000 +0200 @@ -413,8 +413,68 @@ static void rtl8169_get_drvinfo(struct n strcpy(info->bus_info, pci_name(tp->pci_dev)); } +static void rtl8169_set_speed(struct net_device *dev, + u8 autoneg, u16 speed, u8 duplex) +{ + struct rtl8169_private *tp = netdev_priv(dev); + void *ioaddr = tp->mmio_addr; + int auto_nego, giga_ctrl; + u8 status; + + status = RTL_R8(PHYstatus); + if ((status & TBI_Enable) && (autoneg == AUTONEG_DISABLE)) { + autoneg = AUTONEG_ENABLE; + printk(KERN_WARNING PFX + "%s: ignoring request to force speed in TBI mode\n", + dev->name); + } + + auto_nego = mdio_read(ioaddr, PHY_AUTO_NEGO_REG); + auto_nego &= ~(PHY_Cap_10_Half | PHY_Cap_10_Full | + PHY_Cap_100_Half | PHY_Cap_100_Full); + giga_ctrl = mdio_read(ioaddr, PHY_1000_CTRL_REG); + giga_ctrl &= ~(PHY_Cap_1000_Full | PHY_Cap_Null); + + if (autoneg == AUTONEG_ENABLE) { + auto_nego |= (PHY_Cap_10_Half | PHY_Cap_10_Full | + PHY_Cap_100_Half | PHY_Cap_100_Full); + giga_ctrl |= PHY_Cap_1000_Full; + } else { + if (speed == SPEED_10) + auto_nego |= PHY_Cap_10_Half | PHY_Cap_10_Full; + else if (speed == SPEED_100) + auto_nego |= PHY_Cap_100_Half | PHY_Cap_100_Full; + else if (speed == SPEED_1000) + giga_ctrl |= PHY_Cap_1000_Full; + + if (duplex == DUPLEX_HALF) + auto_nego &= ~(PHY_Cap_10_Full | PHY_Cap_100_Full); + } + + if (!(status & TBI_Enable)) { + mdio_write(ioaddr, PHY_AUTO_NEGO_REG, auto_nego); + mdio_write(ioaddr, PHY_1000_CTRL_REG, giga_ctrl); + } + + mdio_write(ioaddr, PHY_CTRL_REG, + PHY_Enable_Auto_Nego | PHY_Restart_Auto_Nego); +} + +static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct rtl8169_private *tp = netdev_priv(dev); + unsigned long flags; + + spin_lock_irqsave(&tp->lock, flags); + rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex); + spin_unlock_irqrestore(&tp->lock, flags); + + return 0; +} + static struct ethtool_ops rtl8169_ethtool_ops = { .get_drvinfo = rtl8169_get_drvinfo, + .set_settings = rtl8169_set_settings, }; static void rtl8169_write_gmii_reg_bit(void *ioaddr, int reg, int bitnum, _ ^ permalink raw reply [flat|nested] 11+ messages in thread
* [patch 5/7] 2.6.6-rc3-mm1 - r8169 ethtool .get_settings 2004-05-01 0:28 ` [patch 4/7] 2.6.6-rc3-mm1 - r8169 ethtool .set_settings Francois Romieu @ 2004-05-01 0:29 ` Francois Romieu 2004-05-01 0:30 ` [patch 6/7] 2.6.6-rc3-mm1 - r8169 link handling rework (1/2) Francois Romieu 0 siblings, 1 reply; 11+ messages in thread From: Francois Romieu @ 2004-05-01 0:29 UTC (permalink / raw) To: jgarzik; +Cc: Andy Lutomirski, Jon D Mason, netdev ethtool get_settings() for r8169 (Andy Lutomirski <luto@myrealbox.com>). The locking does not need to be specially clever. diff -puN drivers/net/r8169.c~r8169-ethtool-get_settings drivers/net/r8169.c --- linux-2.6.6-rc3/drivers/net/r8169.c~r8169-ethtool-get_settings 2004-05-01 01:46:38.000000000 +0200 +++ linux-2.6.6-rc3-fr/drivers/net/r8169.c 2004-05-01 01:46:38.000000000 +0200 @@ -336,6 +336,8 @@ struct rtl8169_private { unsigned long phy_link_down_cnt; u16 cp_cmd; u16 intr_mask; + int phy_auto_nego_reg; + int phy_1000_ctrl_reg; }; MODULE_AUTHOR("Realtek"); @@ -451,6 +453,9 @@ static void rtl8169_set_speed(struct net auto_nego &= ~(PHY_Cap_10_Full | PHY_Cap_100_Full); } + tp->phy_auto_nego_reg = auto_nego; + tp->phy_1000_ctrl_reg = giga_ctrl; + if (!(status & TBI_Enable)) { mdio_write(ioaddr, PHY_AUTO_NEGO_REG, auto_nego); mdio_write(ioaddr, PHY_1000_CTRL_REG, giga_ctrl); @@ -460,6 +465,56 @@ static void rtl8169_set_speed(struct net PHY_Enable_Auto_Nego | PHY_Restart_Auto_Nego); } +static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct rtl8169_private *tp = netdev_priv(dev); + void *ioaddr = tp->mmio_addr; + unsigned long flags; + u8 status; + + spin_lock_irqsave(&tp->lock, flags); + + status = RTL_R8(PHYstatus); + cmd->supported = SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_1000baseT_Full | + SUPPORTED_Autoneg | + SUPPORTED_TP; + + cmd->autoneg = 1; + cmd->advertising = ADVERTISED_TP | ADVERTISED_Autoneg; + /* + * FIXME: the driver should retrieve the values from the registers + * of the rtl8169. + */ + if (tp->phy_auto_nego_reg & PHY_Cap_10_Half) + cmd->advertising |= ADVERTISED_10baseT_Half; + if (tp->phy_auto_nego_reg & PHY_Cap_10_Full) + cmd->advertising |= ADVERTISED_10baseT_Full; + if (tp->phy_auto_nego_reg & PHY_Cap_100_Half) + cmd->advertising |= ADVERTISED_100baseT_Half; + if (tp->phy_auto_nego_reg & PHY_Cap_100_Full) + cmd->advertising |= ADVERTISED_100baseT_Full; + if (tp->phy_1000_ctrl_reg & PHY_Cap_1000_Full) + cmd->advertising |= ADVERTISED_1000baseT_Full; + + if (status & _1000bpsF) + cmd->speed = SPEED_1000; + else if (status & _100bps) + cmd->speed = SPEED_100; + else if (status & _10bps) + cmd->speed = SPEED_10; + + cmd->duplex = ((status & _1000bpsF) || (status & FullDup)) ? + DUPLEX_FULL : DUPLEX_HALF; + + spin_unlock_irqrestore(&tp->lock, flags); + + return 0; +} + static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct rtl8169_private *tp = netdev_priv(dev); @@ -474,6 +529,7 @@ static int rtl8169_set_settings(struct n static struct ethtool_ops rtl8169_ethtool_ops = { .get_drvinfo = rtl8169_get_drvinfo, + .get_settings = rtl8169_get_settings, .set_settings = rtl8169_set_settings, }; _ ^ permalink raw reply [flat|nested] 11+ messages in thread
* [patch 6/7] 2.6.6-rc3-mm1 - r8169 link handling rework (1/2) 2004-05-01 0:29 ` [patch 5/7] 2.6.6-rc3-mm1 - r8169 ethtool .get_settings Francois Romieu @ 2004-05-01 0:30 ` Francois Romieu 2004-05-01 0:31 ` [patch 7/7] 2.6.6-rc3-mm1 - r8169 link handling rework (2/2) Francois Romieu 0 siblings, 1 reply; 11+ messages in thread From: Francois Romieu @ 2004-05-01 0:30 UTC (permalink / raw) To: jgarzik; +Cc: Andy Lutomirski, Jon D Mason, netdev Link handling changes (Andy Lutomirski <luto@myrealbox.com>): - the LinkChg irq enables the phy timer when the link goes down; - the phy timer is enabled in rtl8169_set_speed() to protect against link negociation failure; - removed rtl8169_hw_phy_reset() and its busy loop; - added spinlocking in timer context for rtl8169_phy_timer to avoid messing with the {set/get}_settings commands issued via ethtool. diff -puN drivers/net/r8169.c~r8169-link-00 drivers/net/r8169.c --- linux-2.6.6-rc3/drivers/net/r8169.c~r8169-link-00 2004-05-01 01:46:40.000000000 +0200 +++ linux-2.6.6-rc3-fr/drivers/net/r8169.c 2004-05-01 01:46:40.000000000 +0200 @@ -41,6 +41,7 @@ VERSION 1.2 <2002/11/30> #include <linux/etherdevice.h> #include <linux/delay.h> #include <linux/ethtool.h> +#include <linux/mii.h> #include <linux/crc32.h> #include <linux/init.h> #include <linux/dma-mapping.h> @@ -333,7 +334,8 @@ struct rtl8169_private { struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ struct sk_buff *Tx_skbuff[NUM_TX_DESC]; /* Tx data buffers */ struct timer_list timer; - unsigned long phy_link_down_cnt; + unsigned int phy_tried_renegotiate; + unsigned int phy_reset_warned; u16 cp_cmd; u16 intr_mask; int phy_auto_nego_reg; @@ -363,7 +365,7 @@ static int rtl8169_poll(struct net_devic static const u16 rtl8169_intr_mask = LinkChg | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK; static const u16 rtl8169_napi_event = - RxOK | LinkChg | RxOverflow | RxFIFOOver | TxOK | TxErr; + RxOK | RxOverflow | RxFIFOOver | TxOK | TxErr; static const unsigned int rtl8169_rx_config = (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); @@ -405,6 +407,31 @@ static int mdio_read(void *ioaddr, int R return value; } + +static inline int rtl8169_phy_reset_pending(void *ioaddr) +{ + return mdio_read(ioaddr, 0) & 0x8000; +} + +static void rtl8169_check_link_status(struct net_device *dev, + struct rtl8169_private *tp, void *ioaddr) +{ + unsigned long flags; + u8 status; + + status = RTL_R8(PHYstatus) & LinkStatus; + + spin_lock_irqsave(&tp->lock, flags); + if (status) { + netif_carrier_on(dev); + tp->phy_reset_warned = 0; + } else { + netif_carrier_off(dev); + mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); + } + spin_unlock_irqrestore(&tp->lock, flags); +} + static void rtl8169_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { @@ -463,6 +490,9 @@ static void rtl8169_set_speed(struct net mdio_write(ioaddr, PHY_CTRL_REG, PHY_Enable_Auto_Nego | PHY_Restart_Auto_Nego); + + if (giga_ctrl & PHY_Cap_1000_Full) + mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); } static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) @@ -695,56 +725,56 @@ static void rtl8169_hw_phy_config(struct mdio_write(ioaddr, 31, 0x0000); //w 31 2 0 0 } -static void rtl8169_hw_phy_reset(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void *ioaddr = tp->mmio_addr; - int i, val; - - printk(KERN_WARNING PFX "%s: Reset RTL8169s PHY\n", dev->name); - - val = (mdio_read(ioaddr, 0) | 0x8000) & 0xffff; - mdio_write(ioaddr, 0, val); - - for (i = 50; i >= 0; i--) { - if (!(mdio_read(ioaddr, 0) & 0x8000)) - break; - udelay(100); /* Gross */ - } - - if (i < 0) { - printk(KERN_WARNING PFX "%s: no PHY Reset ack. Giving up.\n", - dev->name); - } -} - static void rtl8169_phy_timer(unsigned long __opaque) { struct net_device *dev = (struct net_device *)__opaque; struct rtl8169_private *tp = netdev_priv(dev); struct timer_list *timer = &tp->timer; void *ioaddr = tp->mmio_addr; + unsigned long timeout = RTL8169_PHY_TIMEOUT; + unsigned int val; + u8 status; assert(tp->mac_version > RTL_GIGA_MAC_VER_B); assert(tp->phy_version < RTL_GIGA_PHY_VER_G); - if (RTL_R8(PHYstatus) & LinkStatus) - tp->phy_link_down_cnt = 0; - else { - tp->phy_link_down_cnt++; - if (tp->phy_link_down_cnt >= 12) { - int reg; - - // If link on 1000, perform phy reset. - reg = mdio_read(ioaddr, PHY_1000_CTRL_REG); - if (reg & PHY_Cap_1000_Full) - rtl8169_hw_phy_reset(dev); + if (!(tp->phy_1000_ctrl_reg & PHY_Cap_1000_Full)) + return; + + spin_lock_irq(&tp->lock); - tp->phy_link_down_cnt = 0; + if (rtl8169_phy_reset_pending(ioaddr)) { + /* + * A busy loop could burn quite a few cycles on nowadays CPU. + * Let's delay the execution of the timer for a few ticks. + */ + timeout = 2; + goto out_mod_timer; + } + + status = RTL_R8(PHYstatus); + if (status & LinkStatus) { + if (!tp->phy_tried_renegotiate && !(status & _1000bpsF)) { + mdio_write(ioaddr, PHY_CTRL_REG, + BMCR_ANRESTART | BMCR_ANENABLE); + tp->phy_tried_renegotiate = 1; } + goto out_unlock; } - mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT); + if (tp->phy_reset_warned == 0) { + printk(KERN_WARNING PFX "%s: PHY reset until link up\n", + dev->name); + tp->phy_reset_warned = 1; + } + + val = (mdio_read(ioaddr, 0) | 0x8000) & 0xffff; + mdio_write(ioaddr, 0, val); + +out_mod_timer: + mod_timer(timer, jiffies + timeout); +out_unlock: + spin_unlock_irq(&tp->lock); } static inline void rtl8169_delete_timer(struct net_device *dev) @@ -757,8 +787,6 @@ static inline void rtl8169_delete_timer( return; del_timer_sync(timer); - - tp->phy_link_down_cnt = 0; } static inline void rtl8169_request_timer(struct net_device *dev) @@ -770,8 +798,6 @@ static inline void rtl8169_request_timer (tp->phy_version >= RTL_GIGA_PHY_VER_G)) return; - tp->phy_link_down_cnt = 0; - init_timer(timer); timer->expires = jiffies + RTL8169_PHY_TIMEOUT; timer->data = (unsigned long)(dev); @@ -1684,10 +1710,7 @@ rtl8169_interrupt(int irq, void *dev_ins break; handled = 1; -/* - if (status & LinkChg) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; -*/ + status &= tp->intr_mask; RTL_W16(IntrStatus, (status & RxFIFOOver) ? (status | RxOverflow) : status); @@ -1695,6 +1718,9 @@ rtl8169_interrupt(int irq, void *dev_ins if (!(status & rtl8169_intr_mask)) break; + if (status & LinkChg) + rtl8169_check_link_status(dev, tp, ioaddr); + #ifdef CONFIG_R8169_NAPI RTL_W16(IntrMask, rtl8169_intr_mask & ~rtl8169_napi_event); tp->intr_mask = ~rtl8169_napi_event; @@ -1708,7 +1734,7 @@ rtl8169_interrupt(int irq, void *dev_ins break; #else // Rx interrupt - if (status & (RxOK | LinkChg | RxOverflow | RxFIFOOver)) { + if (status & (RxOK | RxOverflow | RxFIFOOver)) { rtl8169_rx_interrupt(dev, tp, ioaddr); } // Tx interrupt _ ^ permalink raw reply [flat|nested] 11+ messages in thread
* [patch 7/7] 2.6.6-rc3-mm1 - r8169 link handling rework (2/2) 2004-05-01 0:30 ` [patch 6/7] 2.6.6-rc3-mm1 - r8169 link handling rework (1/2) Francois Romieu @ 2004-05-01 0:31 ` Francois Romieu 0 siblings, 0 replies; 11+ messages in thread From: Francois Romieu @ 2004-05-01 0:31 UTC (permalink / raw) To: jgarzik; +Cc: Andy Lutomirski, Jon D Mason, netdev Use rtl8169_set_speed() for link setup in rtl8169_init_one(): - the code whic handles the option checking is isolated; - display (once) a notice message about the deprecated interface; - rtl8169_open() enables the phy timer if the link is not up; - rtl8169_set_speed() checks that the netdevice is actually ready in order to activate the timer. diff -puN drivers/net/r8169.c~r8169-link-10 drivers/net/r8169.c --- linux-2.6.6-rc3/drivers/net/r8169.c~r8169-link-10 2004-05-01 01:46:42.000000000 +0200 +++ linux-2.6.6-rc3-fr/drivers/net/r8169.c 2004-05-01 01:46:42.000000000 +0200 @@ -7,7 +7,7 @@ Feb 4 2002 - created initially by ShuChen <shuchen@realtek.com.tw>. May 20 2002 - Add link status force-mode and TBI mode support. ========================================================================= - 1. The media can be forced in 5 modes. + 1. [DEPRECATED: use ethtool instead] The media can be forced in 5 modes. Command: 'insmod r8169 media = SET_MEDIA' Ex: 'insmod r8169 media = 0x04' will force PHY to operate in 100Mpbs Half-duplex. @@ -432,6 +432,37 @@ static void rtl8169_check_link_status(st spin_unlock_irqrestore(&tp->lock, flags); } +static void rtl8169_link_option(int idx, u8 *autoneg, u16 *speed, u8 *duplex) +{ + struct { + u16 speed; + u8 duplex; + u8 autoneg; + u8 media; + } link_settings[] = { + { SPEED_10, DUPLEX_HALF, AUTONEG_DISABLE, _10_Half }, + { SPEED_10, DUPLEX_FULL, AUTONEG_DISABLE, _10_Full }, + { SPEED_100, DUPLEX_HALF, AUTONEG_DISABLE, _100_Half }, + { SPEED_100, DUPLEX_FULL, AUTONEG_DISABLE, _100_Full }, + { SPEED_1000, DUPLEX_FULL, AUTONEG_DISABLE, _1000_Full }, + { SPEED_1000, DUPLEX_FULL, AUTONEG_ENABLE, 0xff } + }, *p; + unsigned char option; + + option = ((idx < MAX_UNITS) && (idx >= 0)) ? media[idx] : 0xff; + + if ((option != 0xff) && !idx) + printk(KERN_WARNING PFX "media option is deprecated.\n"); + + for (p = link_settings; p->media != 0xff; p++) { + if (p->media == option) + break; + } + *autoneg = p->autoneg; + *speed = p->speed; + *duplex = p->duplex; +} + static void rtl8169_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { @@ -491,7 +522,7 @@ static void rtl8169_set_speed(struct net mdio_write(ioaddr, PHY_CTRL_REG, PHY_Enable_Auto_Nego | PHY_Restart_Auto_Nego); - if (giga_ctrl & PHY_Cap_1000_Full) + if (netif_running(dev) && (giga_ctrl & PHY_Cap_1000_Full)) mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); } @@ -957,8 +988,9 @@ rtl8169_init_one(struct pci_dev *pdev, c void *ioaddr = NULL; static int board_idx = -1; static int printed_version = 0; + u8 autoneg, duplex; + u16 speed; int i, rc; - int option = -1, Cap10_100 = 0, Cap1000 = 0; assert(pdev != NULL); assert(ent != NULL); @@ -1045,91 +1077,11 @@ rtl8169_init_one(struct pci_dev *pdev, c mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0 } - // if TBI is not endbled - if (!(RTL_R8(PHYstatus) & TBI_Enable)) { - int val = mdio_read(ioaddr, PHY_AUTO_NEGO_REG); - - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - // Force RTL8169 in 10/100/1000 Full/Half mode. - if (option > 0) { - printk(KERN_INFO "%s: Force-mode Enabled.\n", - dev->name); - Cap10_100 = 0, Cap1000 = 0; - switch (option) { - case _10_Half: - Cap10_100 = PHY_Cap_10_Half_Or_Less; - Cap1000 = PHY_Cap_Null; - break; - case _10_Full: - Cap10_100 = PHY_Cap_10_Full_Or_Less; - Cap1000 = PHY_Cap_Null; - break; - case _100_Half: - Cap10_100 = PHY_Cap_100_Half_Or_Less; - Cap1000 = PHY_Cap_Null; - break; - case _100_Full: - Cap10_100 = PHY_Cap_100_Full_Or_Less; - Cap1000 = PHY_Cap_Null; - break; - case _1000_Full: - Cap10_100 = PHY_Cap_100_Full_Or_Less; - Cap1000 = PHY_Cap_1000_Full; - break; - default: - break; - } - // leave PHY_AUTO_NEGO_REG bit4:0 unchanged - mdio_write(ioaddr, PHY_AUTO_NEGO_REG, - Cap10_100 | (val & 0x1F)); - mdio_write(ioaddr, PHY_1000_CTRL_REG, Cap1000); - } else { - printk(KERN_INFO "%s: Auto-negotiation Enabled.\n", - dev->name); - - // enable 10/100 Full/Half Mode - // leave PHY_AUTO_NEGO_REG bit4:0 unchanged - mdio_write(ioaddr, PHY_AUTO_NEGO_REG, - PHY_Cap_100_Full_Or_Less | (val & 0x1f)); - - // enable 1000 Full Mode - mdio_write(ioaddr, PHY_1000_CTRL_REG, - PHY_Cap_1000_Full); - - } - - // Enable auto-negotiation and restart auto-nigotiation - mdio_write(ioaddr, PHY_CTRL_REG, - PHY_Enable_Auto_Nego | PHY_Restart_Auto_Nego); - udelay(100); + rtl8169_link_option(board_idx, &autoneg, &speed, &duplex); - // wait for auto-negotiation process - for (i = 10000; i > 0; i--) { - //check if auto-negotiation complete - if (mdio_read(ioaddr, PHY_STAT_REG) & - PHY_Auto_Neco_Comp) { - udelay(100); - option = RTL_R8(PHYstatus); - if (option & _1000bpsF) { - printk(KERN_INFO - "%s: 1000Mbps Full-duplex operation.\n", - dev->name); - } else { - printk(KERN_INFO - "%s: %sMbps %s-duplex operation.\n", - dev->name, - (option & _100bps) ? "100" : - "10", - (option & FullDup) ? "Full" : - "Half"); - } - break; - } else { - udelay(100); - } - } // end for-loop to wait for auto-negotiation process - - } else { + rtl8169_set_speed(dev, autoneg, speed, duplex); + + if (RTL_R8(PHYstatus) & TBI_Enable) { udelay(100); printk(KERN_INFO "%s: 1000Mbps Full-duplex operation, TBI Link %s!\n", @@ -1236,6 +1188,8 @@ rtl8169_open(struct net_device *dev) rtl8169_hw_start(dev); rtl8169_request_timer(dev); + + rtl8169_check_link_status(dev, tp, tp->mmio_addr); out: return retval; _ ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [patch 0/7] 2.6.6-rc3-mm1 - description of the r8169 queue 2004-05-01 0:23 [patch 0/7] 2.6.6-rc3-mm1 - description of the r8169 queue Francois Romieu 2004-05-01 0:24 ` [patch 1/7] 2.6.6-rc3-mm1 - r8169 napi Francois Romieu @ 2004-05-01 6:32 ` Andy Lutomirski [not found] ` <40954DE9.3020209@myrealbox.com> 2004-05-02 22:34 ` [patch 0/7] 2.6.6-rc3-mm1 - description of the r8169 queue [resend] Andy Lutomirski 3 siblings, 0 replies; 11+ messages in thread From: Andy Lutomirski @ 2004-05-01 6:32 UTC (permalink / raw) To: Francois Romieu; +Cc: jgarzik, Andy Lutomirski, Jon D Mason, netdev Francois Romieu wrote: > With some delay, the following patches include Jon D Mason's NAPI changes > (+ fixes) and code from Andy Lutomirski with minor changes. > I have not moved the initialization of the phy timer in the pci probe > routine as: > - I believe it belongs to the netdevice; > - it should work as is without significant change for the user. > > If someone sees a good reason to move it, just complain (with an axe). I moved the timer because I didn't know about netif_running(). This looks fine. > > The patches apply to 2.6.6-rc3 as well as to 2.6.6-rc3-mm1. > > All the patches are merged in a single patch against 2.6.6-rc3 available at: > http://www.fr.zoreil.com/people/francois/misc/20040501-2.6.6-rc3-r8169.c-test.patch > > The patches are archived below as well: > http://www.fr.zoreil.com/linux/kernel/2.6.x/2.6.6-rc3 > > If the patches prove to behave decently on 2.6, a backport for 2.4.x will be > generated. Everything looks fine. I'm recompiling now; I'll let you know if I have any problems. Thanks, Andy > > -- > Ueimor ^ permalink raw reply [flat|nested] 11+ messages in thread
[parent not found: <40954DE9.3020209@myrealbox.com>]
* Re: [patch 0/7] 2.6.6-rc3-mm1 - description of the r8169 queue [not found] ` <40954DE9.3020209@myrealbox.com> @ 2004-05-02 20:51 ` Francois Romieu 0 siblings, 0 replies; 11+ messages in thread From: Francois Romieu @ 2004-05-02 20:51 UTC (permalink / raw) To: Andy Lutomirski; +Cc: jgarzik, Jon D Mason, netdev Andy Lutomirski <luto@myrealbox.com> : [...] > 3. NAPI is missing from Kconfig It appears in patch 1/7 but it has not been included in the global patch which is available online (fixed by now). This part of your patch should be ignored. The remaining parts are fine. > These patches also chance the initial chipset reset timer from 2 jiffies > to 100ms (for HZ-independence, and 2ms sounds overly short.) Compared to the initial busy-looping, the 2ms timer did not look _that_ inefficient :o) As the reset is expected to take place in 0.5s at worst, your change makes more sense. -- Ueimor ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [patch 0/7] 2.6.6-rc3-mm1 - description of the r8169 queue [resend] 2004-05-01 0:23 [patch 0/7] 2.6.6-rc3-mm1 - description of the r8169 queue Francois Romieu ` (2 preceding siblings ...) [not found] ` <40954DE9.3020209@myrealbox.com> @ 2004-05-02 22:34 ` Andy Lutomirski 3 siblings, 0 replies; 11+ messages in thread From: Andy Lutomirski @ 2004-05-02 22:34 UTC (permalink / raw) To: Francois Romieu; +Cc: jgarzik, Andy Lutomirski, Jon D Mason, netdev [-- Attachment #1: Type: text/plain, Size: 1406 bytes --] [resend -- I'm not sure the first one went out] Three problems: 1. ethtool forgets to report link status 2. On my system, this driver can't bring up the link. That's because the PHY reset timer of 1 second is WAAAY too short -- the PHY gets stuck in a reset loop. (In the old driver it was 12 seconds because there was a multiplier in the timer.) 3. NAPI is missing from Kconfig These patches also chance the initial chipset reset timer from 2 jiffies to 100ms (for HZ-independence, and 2ms sounds overly short.) --Andy Francois Romieu wrote: > With some delay, the following patches include Jon D Mason's NAPI changes > (+ fixes) and code from Andy Lutomirski with minor changes. > I have not moved the initialization of the phy timer in the pci probe > routine as: > - I believe it belongs to the netdevice; > - it should work as is without significant change for the user. > > If someone sees a good reason to move it, just complain (with an axe). > > The patches apply to 2.6.6-rc3 as well as to 2.6.6-rc3-mm1. > > All the patches are merged in a single patch against 2.6.6-rc3 available at: > http://www.fr.zoreil.com/people/francois/misc/20040501-2.6.6-rc3-r8169.c-test.patch > > The patches are archived below as well: > http://www.fr.zoreil.com/linux/kernel/2.6.x/2.6.6-rc3 > > If the patches prove to behave decently on 2.6, a backport for 2.4.x will be > generated. > > -- > Ueimor [-- Attachment #2: r8169_new_fixes --] [-- Type: text/plain, Size: 862 bytes --] --- linux-2.6.6-rc2/drivers/net/r8169.c~fr 2004-04-30 23:27:48.683174600 -0700 +++ linux-2.6.6-rc2/drivers/net/r8169.c 2004-05-02 12:31:00.720041072 -0700 @@ -111,7 +111,7 @@ #define RTL_MIN_IO_SIZE 0x80 #define RTL8169_TX_TIMEOUT (6*HZ) -#define RTL8169_PHY_TIMEOUT (HZ) +#define RTL8169_PHY_TIMEOUT (10*HZ) /* write/read MMIO register */ #define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) @@ -593,6 +593,7 @@ static struct ethtool_ops rtl8169_ethtool_ops = { .get_drvinfo = rtl8169_get_drvinfo, + .get_link = ethtool_op_get_link, .get_settings = rtl8169_get_settings, .set_settings = rtl8169_set_settings, }; @@ -782,7 +783,7 @@ * A busy loop could burn quite a few cycles on nowadays CPU. * Let's delay the execution of the timer for a few ticks. */ - timeout = 2; + timeout = HZ/10; goto out_mod_timer; } [-- Attachment #3: r8169_kconfig --] [-- Type: text/plain, Size: 498 bytes --] --- linux-2.6.6-rc2/drivers/net/Kconfig~r8169_napi 2004-05-02 12:34:44.810974072 -0700 +++ linux-2.6.6-rc2/drivers/net/Kconfig 2004-05-02 12:35:46.553587768 -0700 @@ -1958,6 +1958,10 @@ To compile this driver as a module, choose M here: the module will be called r8169. This is recommended. +config R8169_NAPI + bool "Realtek 8169 NAPI (EXPERIMENTAL)" + depends on R8169 && EXPERIMENTAL + config SK98LIN tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support" depends on PCI ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2004-05-02 22:34 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-05-01 0:23 [patch 0/7] 2.6.6-rc3-mm1 - description of the r8169 queue Francois Romieu
2004-05-01 0:24 ` [patch 1/7] 2.6.6-rc3-mm1 - r8169 napi Francois Romieu
2004-05-01 0:25 ` [patch 2/7] 2.6.6-rc3-mm1 - r8169 janitoring Francois Romieu
2004-05-01 0:26 ` [patch 3/7] 2.6.6-rc3-mm1 - r8169 register rename Francois Romieu
2004-05-01 0:28 ` [patch 4/7] 2.6.6-rc3-mm1 - r8169 ethtool .set_settings Francois Romieu
2004-05-01 0:29 ` [patch 5/7] 2.6.6-rc3-mm1 - r8169 ethtool .get_settings Francois Romieu
2004-05-01 0:30 ` [patch 6/7] 2.6.6-rc3-mm1 - r8169 link handling rework (1/2) Francois Romieu
2004-05-01 0:31 ` [patch 7/7] 2.6.6-rc3-mm1 - r8169 link handling rework (2/2) Francois Romieu
2004-05-01 6:32 ` [patch 0/7] 2.6.6-rc3-mm1 - description of the r8169 queue Andy Lutomirski
[not found] ` <40954DE9.3020209@myrealbox.com>
2004-05-02 20:51 ` Francois Romieu
2004-05-02 22:34 ` [patch 0/7] 2.6.6-rc3-mm1 - description of the r8169 queue [resend] Andy Lutomirski
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).