* [DESC 2.6.8.1-mm4] r8169 patches
@ 2004-08-23 22:41 Francois Romieu
2004-08-23 22:44 ` [PATCH 2.6.8.1-mm4 1/11] r8169: add ethtool_ops.{get_regs_len/get_regs} Francois Romieu
2004-08-27 15:09 ` [DESC 2.6.8.1-mm4] r8169 patches Jon Mason
0 siblings, 2 replies; 17+ messages in thread
From: Francois Romieu @ 2004-08-23 22:41 UTC (permalink / raw)
To: jgarzik; +Cc: akpm, netdev
Here comes a new serie of r8169 related patches which should allow
the motivated users to experiment new features, namely:
- Rx/Tx checksum offload;
- vlan support;
- better ethtool integration.
Tx code apart, the changes exhibit some strong similarity with the
8139cp driver.
I have not done vlan-dedicated test and there are no figures to highlight
any performance improvement. The code does not crash in a (really slow)
debug enabled -mm kernel and it does not seem to add huge leak.
Remarks/comments/test reports welcome.
--
Ueimor
^ permalink raw reply [flat|nested] 17+ messages in thread* [PATCH 2.6.8.1-mm4 1/11] r8169: add ethtool_ops.{get_regs_len/get_regs} 2004-08-23 22:41 [DESC 2.6.8.1-mm4] r8169 patches Francois Romieu @ 2004-08-23 22:44 ` Francois Romieu 2004-08-23 22:45 ` [PATCH 2.6.8.1-mm4 2/11] r8169: per device receive buffer size Francois Romieu 2004-08-27 15:09 ` [DESC 2.6.8.1-mm4] r8169 patches Jon Mason 1 sibling, 1 reply; 17+ messages in thread From: Francois Romieu @ 2004-08-23 22:44 UTC (permalink / raw) To: jgarzik; +Cc: akpm, netdev - ethtool_ops.{get_regs_len/get_regs} for r8169; - fix a dubious check: datasheet v1.21 claims on p.44 that io/memory space is exactly 256 bytes wide; - use SET_ETHTOOL_OPS(). Signed-off-by: Francois Romieu <romieu@fr.zoreil.com> diff -puN drivers/net/r8169.c~r8169-000 drivers/net/r8169.c --- linux-2.6.8.1/drivers/net/r8169.c~r8169-000 2004-08-23 23:29:58.000000000 +0200 +++ linux-2.6.8.1-fr/drivers/net/r8169.c 2004-08-23 23:29:58.000000000 +0200 @@ -99,6 +99,7 @@ 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_REGS_SIZE 256 #define R8169_NAPI_WEIGHT 64 #define NUM_TX_DESC 64 /* Number of Tx descriptor registers */ #define NUM_RX_DESC 256 /* Number of Rx descriptor registers */ @@ -106,7 +107,6 @@ static int multicast_filter_limit = 32; #define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) #define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) -#define RTL_MIN_IO_SIZE 0x80 #define RTL8169_TX_TIMEOUT (6*HZ) #define RTL8169_PHY_TIMEOUT (10*HZ) @@ -508,6 +508,11 @@ static void rtl8169_get_drvinfo(struct n strcpy(info->bus_info, pci_name(tp->pci_dev)); } +static int rtl8169_get_regs_len(struct net_device *dev) +{ + return R8169_REGS_SIZE; +} + static int rtl8169_set_speed_tbi(struct net_device *dev, u8 autoneg, u16 speed, u8 duplex) { @@ -671,12 +676,27 @@ static int rtl8169_get_settings(struct n return 0; } +static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, + void *p) +{ + struct rtl8169_private *tp = netdev_priv(dev); + unsigned long flags; + + if (regs->len > R8169_REGS_SIZE) + regs->len = R8169_REGS_SIZE; + + spin_lock_irqsave(&tp->lock, flags); + memcpy_fromio(p, tp->mmio_addr, regs->len); + spin_unlock_irqrestore(&tp->lock, flags); +} static struct ethtool_ops rtl8169_ethtool_ops = { .get_drvinfo = rtl8169_get_drvinfo, + .get_regs_len = rtl8169_get_regs_len, .get_link = ethtool_op_get_link, .get_settings = rtl8169_get_settings, .set_settings = rtl8169_set_settings, + .get_regs = rtl8169_get_regs, }; static void rtl8169_write_gmii_reg_bit(void *ioaddr, int reg, int bitnum, @@ -968,7 +988,7 @@ rtl8169_init_board(struct pci_dev *pdev, goto err_out_disable; } // check for weird/broken PCI region reporting - if (mmio_len < RTL_MIN_IO_SIZE) { + if (mmio_len < R8169_REGS_SIZE) { printk(KERN_ERR PFX "Invalid PCI region size(s), aborting\n"); rc = -ENODEV; goto err_out_disable; @@ -1105,7 +1125,7 @@ rtl8169_init_one(struct pci_dev *pdev, c dev->open = rtl8169_open; dev->hard_start_xmit = rtl8169_start_xmit; dev->get_stats = rtl8169_get_stats; - dev->ethtool_ops = &rtl8169_ethtool_ops; + SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops); dev->stop = rtl8169_close; dev->tx_timeout = rtl8169_tx_timeout; dev->set_multicast_list = rtl8169_set_rx_mode; _ ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 2.6.8.1-mm4 2/11] r8169: per device receive buffer size 2004-08-23 22:44 ` [PATCH 2.6.8.1-mm4 1/11] r8169: add ethtool_ops.{get_regs_len/get_regs} Francois Romieu @ 2004-08-23 22:45 ` Francois Romieu 2004-08-23 22:47 ` [PATCH 2.6.8.1-mm4 3/11] r8169: code cleanup Francois Romieu 0 siblings, 1 reply; 17+ messages in thread From: Francois Romieu @ 2004-08-23 22:45 UTC (permalink / raw) To: jgarzik; +Cc: akpm, netdev Turn the Rx receive buffer size into a per device variable. Signed-off-by: Francois Romieu <romieu@fr.zoreil.com> diff -puN drivers/net/r8169.c~r8169-010 drivers/net/r8169.c --- linux-2.6.8.1/drivers/net/r8169.c~r8169-010 2004-08-23 23:29:59.000000000 +0200 +++ linux-2.6.8.1-fr/drivers/net/r8169.c 2004-08-23 23:29:59.000000000 +0200 @@ -341,6 +341,7 @@ struct rtl8169_private { dma_addr_t RxPhyAddr; struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ struct sk_buff *Tx_skbuff[NUM_TX_DESC]; /* Tx data buffers */ + unsigned rx_buf_sz; struct timer_list timer; u16 cp_cmd; u16 intr_mask; @@ -1056,6 +1057,8 @@ rtl8169_init_board(struct pci_dev *pdev, } tp->chipset = i; + tp->rx_buf_sz = RX_BUF_SIZE; + *ioaddr_out = ioaddr; *dev_out = dev; return 0; @@ -1377,46 +1380,48 @@ static inline void rtl8169_make_unusable desc->status &= ~cpu_to_le32(OWNbit | RsvdMask); } -static void rtl8169_free_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff, - struct RxDesc *desc) +static void rtl8169_free_rx_skb(struct rtl8169_private *tp, + struct sk_buff **sk_buff, struct RxDesc *desc) { - pci_unmap_single(pdev, le64_to_cpu(desc->addr), RX_BUF_SIZE, + struct pci_dev *pdev = tp->pci_dev; + + pci_unmap_single(pdev, le64_to_cpu(desc->addr), tp->rx_buf_sz, PCI_DMA_FROMDEVICE); dev_kfree_skb(*sk_buff); *sk_buff = NULL; rtl8169_make_unusable_by_asic(desc); } -static inline void rtl8169_return_to_asic(struct RxDesc *desc) +static inline void rtl8169_return_to_asic(struct RxDesc *desc, int rx_buf_sz) { - desc->status |= cpu_to_le32(OWNbit + RX_BUF_SIZE); + desc->status |= cpu_to_le32(OWNbit + rx_buf_sz); } -static inline void rtl8169_give_to_asic(struct RxDesc *desc, dma_addr_t mapping) +static inline void rtl8169_give_to_asic(struct RxDesc *desc, dma_addr_t mapping, + int rx_buf_sz) { desc->addr = cpu_to_le64(mapping); - desc->status |= cpu_to_le32(OWNbit + RX_BUF_SIZE); + desc->status |= cpu_to_le32(OWNbit + rx_buf_sz); } -static int rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct net_device *dev, - struct sk_buff **sk_buff, struct RxDesc *desc) +static int rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff, + struct RxDesc *desc, int rx_buf_sz) { struct sk_buff *skb; dma_addr_t mapping; int ret = 0; - skb = dev_alloc_skb(RX_BUF_SIZE); + skb = dev_alloc_skb(rx_buf_sz); if (!skb) goto err_out; - skb->dev = dev; skb_reserve(skb, 2); *sk_buff = skb; - mapping = pci_map_single(pdev, skb->tail, RX_BUF_SIZE, + mapping = pci_map_single(pdev, skb->tail, rx_buf_sz, PCI_DMA_FROMDEVICE); - rtl8169_give_to_asic(desc, mapping); + rtl8169_give_to_asic(desc, mapping, rx_buf_sz); out: return ret; @@ -1433,7 +1438,7 @@ static void rtl8169_rx_clear(struct rtl8 for (i = 0; i < NUM_RX_DESC; i++) { if (tp->Rx_skbuff[i]) { - rtl8169_free_rx_skb(tp->pci_dev, tp->Rx_skbuff + i, + rtl8169_free_rx_skb(tp, tp->Rx_skbuff + i, tp->RxDescArray + i); } } @@ -1450,8 +1455,8 @@ static u32 rtl8169_rx_fill(struct rtl816 if (tp->Rx_skbuff[i]) continue; - ret = rtl8169_alloc_rx_skb(tp->pci_dev, dev, tp->Rx_skbuff + i, - tp->RxDescArray + i); + ret = rtl8169_alloc_rx_skb(tp->pci_dev, tp->Rx_skbuff + i, + tp->RxDescArray + i, tp->rx_buf_sz); if (ret < 0) break; } @@ -1646,8 +1651,7 @@ rtl8169_tx_interrupt(struct net_device * } static inline int rtl8169_try_rx_copy(struct sk_buff **sk_buff, int pkt_size, - struct RxDesc *desc, - struct net_device *dev) + struct RxDesc *desc, int rx_buf_sz) { int ret = -1; @@ -1656,11 +1660,10 @@ static inline int rtl8169_try_rx_copy(st skb = dev_alloc_skb(pkt_size + 2); if (skb) { - skb->dev = dev; skb_reserve(skb, 2); eth_copy_and_sum(skb, sk_buff[0]->tail, pkt_size, 0); *sk_buff = skb; - rtl8169_return_to_asic(desc); + rtl8169_return_to_asic(desc, rx_buf_sz); ret = 0; } } @@ -1707,17 +1710,19 @@ rtl8169_rx_interrupt(struct net_device * pci_dma_sync_single_for_cpu(tp->pci_dev, - le64_to_cpu(desc->addr), RX_BUF_SIZE, + le64_to_cpu(desc->addr), tp->rx_buf_sz, PCI_DMA_FROMDEVICE); - if (rtl8169_try_rx_copy(&skb, pkt_size, desc, dev)) { + if (rtl8169_try_rx_copy(&skb, pkt_size, desc, + tp->rx_buf_sz)) { pci_action = pci_unmap_single; tp->Rx_skbuff[entry] = NULL; } pci_action(tp->pci_dev, le64_to_cpu(desc->addr), - RX_BUF_SIZE, PCI_DMA_FROMDEVICE); + tp->rx_buf_sz, PCI_DMA_FROMDEVICE); + skb->dev = dev; skb_put(skb, pkt_size); skb->protocol = eth_type_trans(skb, dev); rtl8169_rx_skb(skb); _ ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 2.6.8.1-mm4 3/11] r8169: code cleanup 2004-08-23 22:45 ` [PATCH 2.6.8.1-mm4 2/11] r8169: per device receive buffer size Francois Romieu @ 2004-08-23 22:47 ` Francois Romieu 2004-08-23 22:48 ` [PATCH 2.6.8.1-mm4 4/11] r8169: enable MWI Francois Romieu 0 siblings, 1 reply; 17+ messages in thread From: Francois Romieu @ 2004-08-23 22:47 UTC (permalink / raw) To: jgarzik; +Cc: akpm, netdev Cleanup/code removal: - MAX_ETH_FRAME_SIZE is not used; - removal of assertion for impossible condition (if it happens, it will _not_ take long to notice anyway) - introduce rtl8169_release_board() to factor out some code; - rtl8169_init_board: - some variables are not really needed nor do they help read the code; - more explicit name for label; - tp->{Rx/Tx}DescArray: no need to zeroize coherent DMA mapping. Signed-off-by: Francois Romieu <romieu@fr.zoreil.com> diff -puN drivers/net/r8169.c~r8169-020 drivers/net/r8169.c --- linux-2.6.8.1/drivers/net/r8169.c~r8169-020 2004-08-23 23:29:59.000000000 +0200 +++ linux-2.6.8.1-fr/drivers/net/r8169.c 2004-08-23 23:29:59.000000000 +0200 @@ -87,9 +87,6 @@ static int multicast_filter_limit = 32; /* MAC address length*/ #define MAC_ADDR_LEN 6 -/* max supported gigabit ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - #define TX_FIFO_THRESH 256 /* In bytes */ #define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ @@ -928,28 +925,31 @@ static inline void rtl8169_request_timer add_timer(timer); } +static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev, + void *ioaddr) +{ + iounmap(ioaddr); + pci_release_regions(pdev); + pci_disable_device(pdev); + free_netdev(dev); +} + static int __devinit rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out, void **ioaddr_out) { - void *ioaddr = NULL; + void *ioaddr; struct net_device *dev; struct rtl8169_private *tp; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - int rc, i, acpi_idle_state = 0, pm_cap; + int rc = -ENOMEM, i, acpi_idle_state = 0, pm_cap; - - assert(pdev != NULL); assert(ioaddr_out != NULL); - *ioaddr_out = NULL; - *dev_out = NULL; - // dev zeroed in alloc_etherdev dev = alloc_etherdev(sizeof (*tp)); if (dev == NULL) { printk(KERN_ERR PFX "unable to alloc new ethernet\n"); - return -ENOMEM; + goto err_out; } SET_MODULE_OWNER(dev); @@ -960,7 +960,7 @@ rtl8169_init_board(struct pci_dev *pdev, rc = pci_enable_device(pdev); if (rc) { printk(KERN_ERR PFX "%s: enable failure\n", pdev->slot_name); - goto err_out; + goto err_out_free_dev; } /* save power state before pci_enable_device overwrites it */ @@ -976,20 +976,15 @@ rtl8169_init_board(struct pci_dev *pdev, goto err_out_free_res; } - mmio_start = pci_resource_start(pdev, 1); - mmio_end = pci_resource_end(pdev, 1); - mmio_flags = pci_resource_flags(pdev, 1); - mmio_len = pci_resource_len(pdev, 1); - // make sure PCI base addr 1 is MMIO - if (!(mmio_flags & IORESOURCE_MEM)) { + if (!(pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) { printk(KERN_ERR PFX "region #1 not an MMIO resource, aborting\n"); rc = -ENODEV; goto err_out_disable; } // check for weird/broken PCI region reporting - if (mmio_len < R8169_REGS_SIZE) { + if (pci_resource_len(pdev, 1) < R8169_REGS_SIZE) { printk(KERN_ERR PFX "Invalid PCI region size(s), aborting\n"); rc = -ENODEV; goto err_out_disable; @@ -1020,7 +1015,7 @@ rtl8169_init_board(struct pci_dev *pdev, pci_set_master(pdev); // ioremap MMIO region - ioaddr = ioremap(mmio_start, mmio_len); + ioaddr = ioremap(pci_resource_start(pdev, 1), R8169_REGS_SIZE); if (ioaddr == NULL) { printk(KERN_ERR PFX "cannot remap MMIO, aborting\n"); rc = -EIO; @@ -1061,7 +1056,8 @@ rtl8169_init_board(struct pci_dev *pdev, *ioaddr_out = ioaddr; *dev_out = dev; - return 0; +out: + return rc; err_out_free_res: pci_release_regions(pdev); @@ -1069,16 +1065,19 @@ err_out_free_res: err_out_disable: pci_disable_device(pdev); -err_out: +err_out_free_dev: free_netdev(dev); - return rc; +err_out: + *ioaddr_out = NULL; + *dev_out = NULL; + goto out; } static int __devinit rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *dev = NULL; - struct rtl8169_private *tp = NULL; + struct rtl8169_private *tp; void *ioaddr = NULL; static int board_idx = -1; static int printed_version = 0; @@ -1102,8 +1101,6 @@ rtl8169_init_one(struct pci_dev *pdev, c tp = dev->priv; assert(ioaddr != NULL); - assert(dev != NULL); - assert(tp != NULL); if (RTL_R8(PHYstatus) & TBI_Enable) { tp->set_speed = rtl8169_set_speed_tbi; @@ -1148,10 +1145,7 @@ rtl8169_init_one(struct pci_dev *pdev, c rc = register_netdev(dev); if (rc) { - iounmap(ioaddr); - pci_release_regions(pdev); - pci_disable_device(pdev); - free_netdev(dev); + rtl8169_release_board(pdev, dev, ioaddr); return rc; } @@ -1207,11 +1201,7 @@ rtl8169_remove_one(struct pci_dev *pdev) assert(tp != NULL); unregister_netdev(dev); - iounmap(tp->mmio_addr); - pci_release_regions(pdev); - - pci_disable_device(pdev); - free_netdev(dev); + rtl8169_release_board(pdev, dev, tp->mmio_addr); pci_set_drvdata(pdev, NULL); } @@ -1474,8 +1464,6 @@ static int rtl8169_init_ring(struct net_ tp->cur_rx = tp->dirty_rx = 0; tp->cur_tx = tp->dirty_tx = 0; - memset(tp->TxDescArray, 0x0, NUM_TX_DESC * sizeof (struct TxDesc)); - memset(tp->RxDescArray, 0x0, NUM_RX_DESC * sizeof (struct RxDesc)); memset(tp->Tx_skbuff, 0x0, NUM_TX_DESC * sizeof(struct sk_buff *)); memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); _ ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 2.6.8.1-mm4 4/11] r8169: enable MWI 2004-08-23 22:47 ` [PATCH 2.6.8.1-mm4 3/11] r8169: code cleanup Francois Romieu @ 2004-08-23 22:48 ` Francois Romieu 2004-08-23 22:49 ` [PATCH 2.6.8.1-mm4 5/11] r8169: bump version number Francois Romieu 0 siblings, 1 reply; 17+ messages in thread From: Francois Romieu @ 2004-08-23 22:48 UTC (permalink / raw) To: jgarzik; +Cc: akpm, netdev - enable Memory Write and Invalidate (disabled after reset); - fix wrong goto. Signed-off-by: Francois Romieu <romieu@fr.zoreil.com> diff -puN drivers/net/r8169.c~r8169-030 drivers/net/r8169.c --- linux-2.6.8.1/drivers/net/r8169.c~r8169-030 2004-08-23 23:30:00.000000000 +0200 +++ linux-2.6.8.1-fr/drivers/net/r8169.c 2004-08-23 23:30:00.000000000 +0200 @@ -32,7 +32,6 @@ VERSION 1.2 <2002/11/30> - Use ether_crc in stock kernel (linux/crc32.h) - Copy mc_filter setup code from 8139cp (includes an optimization, and avoids set_bit use) - */ #include <linux/module.h> @@ -963,6 +962,10 @@ rtl8169_init_board(struct pci_dev *pdev, goto err_out_free_dev; } + rc = pci_set_mwi(pdev); + if (rc < 0) + goto err_out_disable; + /* save power state before pci_enable_device overwrites it */ pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); if (pm_cap) { @@ -973,7 +976,7 @@ rtl8169_init_board(struct pci_dev *pdev, } else { printk(KERN_ERR PFX "Cannot find PowerManagement capability, aborting.\n"); - goto err_out_free_res; + goto err_out_mwi; } // make sure PCI base addr 1 is MMIO @@ -981,20 +984,20 @@ rtl8169_init_board(struct pci_dev *pdev, printk(KERN_ERR PFX "region #1 not an MMIO resource, aborting\n"); rc = -ENODEV; - goto err_out_disable; + goto err_out_mwi; } // check for weird/broken PCI region reporting if (pci_resource_len(pdev, 1) < R8169_REGS_SIZE) { printk(KERN_ERR PFX "Invalid PCI region size(s), aborting\n"); rc = -ENODEV; - goto err_out_disable; + goto err_out_mwi; } rc = pci_request_regions(pdev, MODULENAME); if (rc) { printk(KERN_ERR PFX "%s: could not request regions.\n", pdev->slot_name); - goto err_out_disable; + goto err_out_mwi; } tp->cp_cmd = PCIMulRW | RxChkSum; @@ -1011,7 +1014,6 @@ rtl8169_init_board(struct pci_dev *pdev, } - // enable PCI bus-mastering pci_set_master(pdev); // ioremap MMIO region @@ -1062,6 +1064,9 @@ out: err_out_free_res: pci_release_regions(pdev); +err_out_mwi: + pci_clear_mwi(pdev); + err_out_disable: pci_disable_device(pdev); _ ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 2.6.8.1-mm4 5/11] r8169: bump version number 2004-08-23 22:48 ` [PATCH 2.6.8.1-mm4 4/11] r8169: enable MWI Francois Romieu @ 2004-08-23 22:49 ` Francois Romieu 2004-08-23 22:51 ` [PATCH 2.6.8.1-mm4 6/11] r8169: sync the names of a few bits with the 8139cp driver Francois Romieu 0 siblings, 1 reply; 17+ messages in thread From: Francois Romieu @ 2004-08-23 22:49 UTC (permalink / raw) To: jgarzik; +Cc: akpm, netdev Help reviewers realize that the in-kernel driver has evolved lately. Signed-off-by: Francois Romieu <romieu@fr.zoreil.com> diff -puN drivers/net/r8169.c~r8169-040 drivers/net/r8169.c --- linux-2.6.8.1/drivers/net/r8169.c~r8169-040 2004-08-23 23:30:00.000000000 +0200 +++ linux-2.6.8.1-fr/drivers/net/r8169.c 2004-08-23 23:30:00.000000000 +0200 @@ -6,6 +6,7 @@ History: Feb 4 2002 - created initially by ShuChen <shuchen@realtek.com.tw>. May 20 2002 - Add link status force-mode and TBI mode support. + 2004 - Massive updates. See kernel SCM system for details. ========================================================================= 1. [DEPRECATED: use ethtool instead] The media can be forced in 5 modes. Command: 'insmod r8169 media = SET_MEDIA' @@ -32,6 +33,14 @@ VERSION 1.2 <2002/11/30> - Use ether_crc in stock kernel (linux/crc32.h) - Copy mc_filter setup code from 8139cp (includes an optimization, and avoids set_bit use) + +VERSION 1.6LK <2004/04/14> + + - Merge of Realtek's version 1.6 + - Conversion to DMA API + - Suspend/resume + - Endianness + - Misc Rx/Tx bugs */ #include <linux/module.h> @@ -47,7 +56,7 @@ VERSION 1.2 <2002/11/30> #include <asm/io.h> -#define RTL8169_VERSION "1.2" +#define RTL8169_VERSION "1.6LK" #define MODULENAME "r8169" #define RTL8169_DRIVER_NAME MODULENAME " Gigabit Ethernet driver " RTL8169_VERSION #define PFX MODULENAME ": " _ ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 2.6.8.1-mm4 6/11] r8169: sync the names of a few bits with the 8139cp driver 2004-08-23 22:49 ` [PATCH 2.6.8.1-mm4 5/11] r8169: bump version number Francois Romieu @ 2004-08-23 22:51 ` Francois Romieu 2004-08-23 22:53 ` [PATCH 2.6.8.1-mm4 7/11] r8169: comment a gcc 2.95.x bug Francois Romieu 0 siblings, 1 reply; 17+ messages in thread From: Francois Romieu @ 2004-08-23 22:51 UTC (permalink / raw) To: jgarzik; +Cc: akpm, netdev Sync the names of the descriptor with these which are used in the 8139cp driver. Though not exactly identical the descriptors are forward compatible. Signed-off-by: Francois Romieu <romieu@fr.zoreil.com> diff -puN drivers/net/r8169.c~r8169-060 drivers/net/r8169.c --- linux-2.6.8.1/drivers/net/r8169.c~r8169-060 2004-08-23 23:30:01.000000000 +0200 +++ linux-2.6.8.1-fr/drivers/net/r8169.c 2004-08-23 23:30:01.000000000 +0200 @@ -308,23 +308,23 @@ enum RTL8169_register_content { }; enum _DescStatusBit { - OWNbit = 0x80000000, - EORbit = 0x40000000, - FSbit = 0x20000000, - LSbit = 0x10000000, + DescOwn = (1 << 31), /* Descriptor is owned by NIC */ + RingEnd = (1 << 30), /* End of descriptor ring */ + FirstFrag = (1 << 29), /* First segment of a packet */ + LastFrag = (1 << 28), /* Final segment of a packet */ }; #define RsvdMask 0x3fffc000 struct TxDesc { - u32 status; - u32 vlan_tag; + u32 opts1; + u32 opts2; u64 addr; }; struct RxDesc { - u32 status; - u32 vlan_tag; + u32 opts1; + u32 opts2; u64 addr; }; @@ -1381,7 +1381,7 @@ rtl8169_hw_start(struct net_device *dev) static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) { desc->addr = 0x0badbadbadbadbadull; - desc->status &= ~cpu_to_le32(OWNbit | RsvdMask); + desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); } static void rtl8169_free_rx_skb(struct rtl8169_private *tp, @@ -1398,14 +1398,14 @@ static void rtl8169_free_rx_skb(struct r static inline void rtl8169_return_to_asic(struct RxDesc *desc, int rx_buf_sz) { - desc->status |= cpu_to_le32(OWNbit + rx_buf_sz); + desc->opts1 |= cpu_to_le32(DescOwn + rx_buf_sz); } static inline void rtl8169_give_to_asic(struct RxDesc *desc, dma_addr_t mapping, int rx_buf_sz) { desc->addr = cpu_to_le64(mapping); - desc->status |= cpu_to_le32(OWNbit + rx_buf_sz); + desc->opts1 |= cpu_to_le32(DescOwn + rx_buf_sz); } static int rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff, @@ -1469,7 +1469,7 @@ static u32 rtl8169_rx_fill(struct rtl816 static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc) { - desc->status |= cpu_to_le32(EORbit); + desc->opts1 |= cpu_to_le32(RingEnd); } static int rtl8169_init_ring(struct net_device *dev) @@ -1565,7 +1565,7 @@ rtl8169_start_xmit(struct sk_buff *skb, len = ETH_ZLEN; } - if (!(le32_to_cpu(tp->TxDescArray[entry].status) & OWNbit)) { + if (!(le32_to_cpu(tp->TxDescArray[entry].opts1) & DescOwn)) { dma_addr_t mapping; u32 status; @@ -1576,9 +1576,9 @@ rtl8169_start_xmit(struct sk_buff *skb, tp->TxDescArray[entry].addr = cpu_to_le64(mapping); /* anti gcc 2.95.3 bugware */ - status = OWNbit | FSbit | LSbit | len | - (EORbit * !((entry + 1) % NUM_TX_DESC)); - tp->TxDescArray[entry].status = cpu_to_le32(status); + status = DescOwn | FirstFrag | LastFrag | len | + (RingEnd * !((entry + 1) % NUM_TX_DESC)); + tp->TxDescArray[entry].opts1 = cpu_to_le32(status); RTL_W8(TxPoll, 0x40); //set polling bit @@ -1628,8 +1628,8 @@ rtl8169_tx_interrupt(struct net_device * u32 status; rmb(); - status = le32_to_cpu(tp->TxDescArray[entry].status); - if (status & OWNbit) + status = le32_to_cpu(tp->TxDescArray[entry].opts1); + if (status & DescOwn) break; /* FIXME: is it really accurate for TxErr ? */ @@ -1692,9 +1692,9 @@ rtl8169_rx_interrupt(struct net_device * u32 status; rmb(); - status = le32_to_cpu(tp->RxDescArray[entry].status); + status = le32_to_cpu(tp->RxDescArray[entry].opts1); - if (status & OWNbit) + if (status & DescOwn) break; if (status & RxRES) { printk(KERN_INFO "%s: Rx ERROR!!!\n", dev->name); _ ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 2.6.8.1-mm4 7/11] r8169: comment a gcc 2.95.x bug 2004-08-23 22:51 ` [PATCH 2.6.8.1-mm4 6/11] r8169: sync the names of a few bits with the 8139cp driver Francois Romieu @ 2004-08-23 22:53 ` Francois Romieu 2004-08-23 22:55 ` [PATCH 2.6.8.1-mm4 8/11] r8169: Tx checksum offload Francois Romieu 0 siblings, 1 reply; 17+ messages in thread From: Francois Romieu @ 2004-08-23 22:53 UTC (permalink / raw) To: jgarzik; +Cc: akpm, netdev gcc 2.95.3 bug has been experienced on gcc 2.95.4. Signed-off-by: Francois Romieu <romieu@fr.zoreil.com> diff -puN drivers/net/r8169.c~r8169-070 drivers/net/r8169.c --- linux-2.6.8.1/drivers/net/r8169.c~r8169-070 2004-08-23 23:30:03.000000000 +0200 +++ linux-2.6.8.1-fr/drivers/net/r8169.c 2004-08-23 23:30:03.000000000 +0200 @@ -1575,7 +1575,7 @@ rtl8169_start_xmit(struct sk_buff *skb, tp->Tx_skbuff[entry] = skb; tp->TxDescArray[entry].addr = cpu_to_le64(mapping); - /* anti gcc 2.95.3 bugware */ + /* anti gcc 2.95.[3/4] bugware - do not merge these lines */ status = DescOwn | FirstFrag | LastFrag | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); tp->TxDescArray[entry].opts1 = cpu_to_le32(status); _ ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 2.6.8.1-mm4 8/11] r8169: Tx checksum offload 2004-08-23 22:53 ` [PATCH 2.6.8.1-mm4 7/11] r8169: comment a gcc 2.95.x bug Francois Romieu @ 2004-08-23 22:55 ` Francois Romieu 2004-08-23 22:56 ` [PATCH 2.6.8.1-mm4 9/11] r8169: advertise DMA to high memory Francois Romieu 2004-08-28 23:15 ` [PATCH 2.6.8.1-mm4 8/11] r8169: Tx checksum offload Jeff Garzik 0 siblings, 2 replies; 17+ messages in thread From: Francois Romieu @ 2004-08-23 22:55 UTC (permalink / raw) To: jgarzik; +Cc: akpm, netdev SG and IP checksumming support on output. Signed-off-by: Francois Romieu <romieu@fr.zoreil.com> diff -puN drivers/net/r8169.c~r8169-080 drivers/net/r8169.c --- linux-2.6.8.1/drivers/net/r8169.c~r8169-080 2004-08-23 23:30:04.000000000 +0200 +++ linux-2.6.8.1-fr/drivers/net/r8169.c 2004-08-23 23:30:04.000000000 +0200 @@ -51,6 +51,9 @@ VERSION 1.6LK <2004/04/14> #include <linux/ethtool.h> #include <linux/mii.h> #include <linux/crc32.h> +#include <linux/in.h> +#include <linux/ip.h> +#include <linux/tcp.h> #include <linux/init.h> #include <linux/dma-mapping.h> @@ -312,6 +315,11 @@ enum _DescStatusBit { RingEnd = (1 << 30), /* End of descriptor ring */ FirstFrag = (1 << 29), /* First segment of a packet */ LastFrag = (1 << 28), /* Final segment of a packet */ + + /* Tx private */ + IPCS = (1 << 18), /* Calculate IP checksum */ + UDPCS = (1 << 17), /* Calculate UDP/IP checksum */ + TCPCS = (1 << 16), /* Calculate TCP/IP checksum */ }; #define RsvdMask 0x3fffc000 @@ -328,6 +336,12 @@ struct RxDesc { u64 addr; }; +struct ring_info { + struct sk_buff *skb; + u32 len; + u8 __pad[sizeof(void *) - sizeof(u32)]; +}; + struct rtl8169_private { void *mmio_addr; /* memory map physical address */ struct pci_dev *pci_dev; /* Index of PCI device */ @@ -345,7 +359,7 @@ struct rtl8169_private { 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]; /* Tx data buffers */ + struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ unsigned rx_buf_sz; struct timer_list timer; u16 cp_cmd; @@ -702,6 +716,10 @@ static struct ethtool_ops rtl8169_ethtoo .get_link = ethtool_op_get_link, .get_settings = rtl8169_get_settings, .set_settings = rtl8169_set_settings, + .get_tx_csum = ethtool_op_get_tx_csum, + .set_tx_csum = ethtool_op_set_tx_csum, + .get_sg = ethtool_op_get_sg, + .set_sg = ethtool_op_set_sg, .get_regs = rtl8169_get_regs, }; @@ -1479,7 +1497,7 @@ static int rtl8169_init_ring(struct net_ tp->cur_rx = tp->dirty_rx = 0; tp->cur_tx = tp->dirty_tx = 0; - memset(tp->Tx_skbuff, 0x0, NUM_TX_DESC * sizeof(struct sk_buff *)); + memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC) @@ -1494,33 +1512,38 @@ err_out: return -ENOMEM; } -static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff, +static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct ring_info *tx_skb, struct TxDesc *desc) { - u32 len = sk_buff[0]->len; + unsigned int len = tx_skb->len; - pci_unmap_single(pdev, le64_to_cpu(desc->addr), - len < ETH_ZLEN ? ETH_ZLEN : len, PCI_DMA_TODEVICE); + pci_unmap_single(pdev, le64_to_cpu(desc->addr), len, PCI_DMA_TODEVICE); desc->addr = 0x00; - *sk_buff = NULL; + tx_skb->len = 0; } -static void -rtl8169_tx_clear(struct rtl8169_private *tp) +static void rtl8169_tx_clear(struct rtl8169_private *tp) { - int i; + unsigned int i; - tp->cur_tx = 0; - for (i = 0; i < NUM_TX_DESC; i++) { - struct sk_buff *skb = tp->Tx_skbuff[i]; + for (i = tp->dirty_tx; i < tp->dirty_tx + NUM_TX_DESC; i++) { + unsigned int entry = i % NUM_TX_DESC; + struct ring_info *tx_skb = tp->tx_skb + entry; + unsigned int len = tx_skb->len; - if (skb) { - rtl8169_unmap_tx_skb(tp->pci_dev, tp->Tx_skbuff + i, - tp->TxDescArray + i); - dev_kfree_skb(skb); + if (len) { + struct sk_buff *skb = tx_skb->skb; + + rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, + tp->TxDescArray + entry); + if (skb) { + dev_kfree_skb(skb); + tx_skb->skb = NULL; + } tp->stats.tx_dropped++; } } + tp->cur_tx = tp->dirty_tx = 0; } static void @@ -1550,51 +1573,121 @@ rtl8169_tx_timeout(struct net_device *de netif_wake_queue(dev); } -static int -rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) +static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, + u32 opts1) +{ + struct skb_shared_info *info = skb_shinfo(skb); + unsigned int cur_frag, entry; + struct TxDesc *txd; + + entry = tp->cur_tx; + for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) { + skb_frag_t *frag = info->frags + cur_frag; + dma_addr_t mapping; + u32 status, len; + void *addr; + + entry = (entry + 1) % NUM_TX_DESC; + + txd = tp->TxDescArray + entry; + len = frag->size; + addr = ((void *) page_address(frag->page)) + frag->page_offset; + mapping = pci_map_single(tp->pci_dev, addr, len, PCI_DMA_TODEVICE); + + /* anti gcc 2.95.3 bugware (sic) */ + status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); + + txd->opts1 = cpu_to_le32(status); + txd->addr = cpu_to_le64(mapping); + + tp->tx_skb[entry].len = len; + } + + if (cur_frag) { + tp->tx_skb[entry].skb = skb; + txd->opts1 |= cpu_to_le32(LastFrag); + } + + return cur_frag; +} + +static inline u32 rtl8169_tx_csum(struct sk_buff *skb) +{ + if (skb->ip_summed == CHECKSUM_HW) { + const struct iphdr *ip = skb->nh.iph; + + if (ip->protocol == IPPROTO_TCP) + return IPCS | TCPCS; + else if (ip->protocol == IPPROTO_UDP) + return IPCS | UDPCS; + BUG(); + } + return 0; +} + +static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); + unsigned int frags, entry = tp->cur_tx % NUM_TX_DESC; + struct TxDesc *txd = tp->TxDescArray + entry; void *ioaddr = tp->mmio_addr; - unsigned int entry = tp->cur_tx % NUM_TX_DESC; - u32 len = skb->len; + dma_addr_t mapping; + u32 status, len; + u32 opts1; + + if (unlikely(tp->cur_tx - tp->dirty_tx < skb_shinfo(skb)->nr_frags)) { + netif_stop_queue(dev); + printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n", + dev->name); + return 1; + } + + if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) + goto err_drop; + + opts1 = DescOwn | rtl8169_tx_csum(skb); + + frags = rtl8169_xmit_frags(tp, skb, opts1); + if (frags) { + len = skb_headlen(skb); + opts1 |= FirstFrag; + } else { + len = skb->len; + + if (unlikely(len < ETH_ZLEN)) { + skb = skb_padto(skb, ETH_ZLEN); + if (!skb) + goto err_update_stats; + len = ETH_ZLEN; + } - if (unlikely(skb->len < ETH_ZLEN)) { - skb = skb_padto(skb, ETH_ZLEN); - if (!skb) - goto err_update_stats; - len = ETH_ZLEN; + opts1 |= FirstFrag | LastFrag; + tp->tx_skb[entry].skb = skb; } - - if (!(le32_to_cpu(tp->TxDescArray[entry].opts1) & DescOwn)) { - dma_addr_t mapping; - u32 status; - mapping = pci_map_single(tp->pci_dev, skb->data, len, - PCI_DMA_TODEVICE); + mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE); - tp->Tx_skbuff[entry] = skb; - tp->TxDescArray[entry].addr = cpu_to_le64(mapping); + tp->tx_skb[entry].len = len; + txd->addr = cpu_to_le64(mapping); - /* anti gcc 2.95.[3/4] bugware - do not merge these lines */ - status = DescOwn | FirstFrag | LastFrag | len | - (RingEnd * !((entry + 1) % NUM_TX_DESC)); - tp->TxDescArray[entry].opts1 = cpu_to_le32(status); - - RTL_W8(TxPoll, 0x40); //set polling bit + wmb(); - dev->trans_start = jiffies; + /* anti gcc 2.95.3 bugware (sic) */ + status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); + txd->opts1 = cpu_to_le32(status); - tp->cur_tx++; - smp_wmb(); - } else - goto err_drop; + dev->trans_start = jiffies; - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) { - u32 dirty = tp->dirty_tx; - + tp->cur_tx += frags + 1; + + smp_wmb(); + + RTL_W8(TxPoll, 0x40); //set polling bit + + if (tp->cur_tx - tp->dirty_tx < MAX_SKB_FRAGS) { netif_stop_queue(dev); smp_rmb(); - if (dirty != tp->dirty_tx) + if (tp->cur_tx - tp->dirty_tx >= MAX_SKB_FRAGS) netif_wake_queue(dev); } @@ -1624,7 +1717,8 @@ rtl8169_tx_interrupt(struct net_device * while (tx_left > 0) { unsigned int entry = dirty_tx % NUM_TX_DESC; - struct sk_buff *skb = tp->Tx_skbuff[entry]; + struct ring_info *tx_skb = tp->tx_skb + entry; + u32 len = tx_skb->len; u32 status; rmb(); @@ -1632,14 +1726,15 @@ rtl8169_tx_interrupt(struct net_device * if (status & DescOwn) break; - /* FIXME: is it really accurate for TxErr ? */ - tp->stats.tx_bytes += skb->len >= ETH_ZLEN ? - skb->len : ETH_ZLEN; + tp->stats.tx_bytes += len; tp->stats.tx_packets++; - rtl8169_unmap_tx_skb(tp->pci_dev, tp->Tx_skbuff + entry, - tp->TxDescArray + entry); - dev_kfree_skb_irq(skb); - tp->Tx_skbuff[entry] = NULL; + + rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, tp->TxDescArray + entry); + + if (status & LastFrag) { + dev_kfree_skb_irq(tx_skb->skb); + tx_skb->skb = NULL; + } dirty_tx++; tx_left--; } _ ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 2.6.8.1-mm4 9/11] r8169: advertise DMA to high memory 2004-08-23 22:55 ` [PATCH 2.6.8.1-mm4 8/11] r8169: Tx checksum offload Francois Romieu @ 2004-08-23 22:56 ` Francois Romieu 2004-08-23 22:57 ` [PATCH 2.6.8.1-mm4 10/11] r8169: Rx checksum support Francois Romieu 2004-08-28 23:15 ` [PATCH 2.6.8.1-mm4 8/11] r8169: Tx checksum offload Jeff Garzik 1 sibling, 1 reply; 17+ messages in thread From: Francois Romieu @ 2004-08-23 22:56 UTC (permalink / raw) To: jgarzik; +Cc: akpm, netdev Advertise the ability to DMA to high memory. Signed-off-by: Francois Romieu <romieu@fr.zoreil.com> diff -puN drivers/net/r8169.c~r8169-090 drivers/net/r8169.c --- linux-2.6.8.1/drivers/net/r8169.c~r8169-090 2004-08-23 23:30:06.000000000 +0200 +++ linux-2.6.8.1-fr/drivers/net/r8169.c 2004-08-23 23:30:06.000000000 +0200 @@ -1029,10 +1029,10 @@ rtl8169_init_board(struct pci_dev *pdev, tp->cp_cmd = PCIMulRW | RxChkSum; - if ((sizeof(dma_addr_t) > 32) && - !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) + if ((sizeof(dma_addr_t) > 32) && !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { tp->cp_cmd |= PCIDAC; - else { + dev->features |= NETIF_F_HIGHDMA; + } else { rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); if (rc < 0) { printk(KERN_ERR PFX "DMA configuration failed.\n"); @@ -1040,7 +1040,6 @@ rtl8169_init_board(struct pci_dev *pdev, } } - pci_set_master(pdev); // ioremap MMIO region _ ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 2.6.8.1-mm4 10/11] r8169: Rx checksum support 2004-08-23 22:56 ` [PATCH 2.6.8.1-mm4 9/11] r8169: advertise DMA to high memory Francois Romieu @ 2004-08-23 22:57 ` Francois Romieu 2004-08-23 22:59 ` [PATCH 2.6.8.1-mm4 11/11] r8169: vlan support Francois Romieu 0 siblings, 1 reply; 17+ messages in thread From: Francois Romieu @ 2004-08-23 22:57 UTC (permalink / raw) To: jgarzik; +Cc: akpm, netdev Rx IP checksumming support. Signed-off-by: Francois Romieu <romieu@fr.zoreil.com> diff -puN drivers/net/r8169.c~r8169-100 drivers/net/r8169.c --- linux-2.6.8.1/drivers/net/r8169.c~r8169-100 2004-08-23 23:30:08.000000000 +0200 +++ linux-2.6.8.1-fr/drivers/net/r8169.c 2004-08-23 23:30:08.000000000 +0200 @@ -320,6 +320,19 @@ enum _DescStatusBit { IPCS = (1 << 18), /* Calculate IP checksum */ UDPCS = (1 << 17), /* Calculate UDP/IP checksum */ TCPCS = (1 << 16), /* Calculate TCP/IP checksum */ + + /* Rx private */ + PID1 = (1 << 18), /* Protocol ID bit 1/2 */ + PID0 = (1 << 17), /* Protocol ID bit 2/2 */ + +#define RxProtoUDP (PID1) +#define RxProtoTCP (PID0) +#define RxProtoIP (PID1 | PID0) +#define RxProtoMask RxProtoIP + + IPFail = (1 << 16), /* IP checksum failed */ + UDPFail = (1 << 15), /* UDP/IP checksum failed */ + TCPFail = (1 << 14), /* TCP/IP checksum failed */ }; #define RsvdMask 0x3fffc000 @@ -623,6 +636,34 @@ static int rtl8169_set_settings(struct n return ret; } +static u32 rtl8169_get_rx_csum(struct net_device *dev) +{ + struct rtl8169_private *tp = netdev_priv(dev); + + return !!(tp->cp_cmd & RxChkSum); +} + +static int rtl8169_set_rx_csum(struct net_device *dev, u32 data) +{ + struct rtl8169_private *tp = netdev_priv(dev); + void *ioaddr = tp->mmio_addr; + unsigned long flags; + + spin_lock_irqsave(&tp->lock, flags); + + if (data) + tp->cp_cmd |= RxChkSum; + else + tp->cp_cmd &= ~RxChkSum; + + RTL_W16(CPlusCmd, tp->cp_cmd); + RTL_R16(CPlusCmd); + + spin_unlock_irqrestore(&tp->lock, flags); + + return 0; +} + static void rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) { struct rtl8169_private *tp = netdev_priv(dev); @@ -716,6 +757,8 @@ static struct ethtool_ops rtl8169_ethtoo .get_link = ethtool_op_get_link, .get_settings = rtl8169_get_settings, .set_settings = rtl8169_set_settings, + .get_rx_csum = rtl8169_get_rx_csum, + .set_rx_csum = rtl8169_set_rx_csum, .get_tx_csum = ethtool_op_get_tx_csum, .set_tx_csum = ethtool_op_set_tx_csum, .get_sg = ethtool_op_get_sg, @@ -1746,6 +1789,19 @@ rtl8169_tx_interrupt(struct net_device * } } +static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc) +{ + u32 opts1 = desc->opts1; + u32 status = opts1 & RxProtoMask; + + if (((status == RxProtoTCP) && !(opts1 & TCPFail)) || + ((status == RxProtoUDP) && !(opts1 & UDPFail)) || + ((status == RxProtoIP) && !(opts1 & IPFail))) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb->ip_summed = CHECKSUM_NONE; +} + static inline int rtl8169_try_rx_copy(struct sk_buff **sk_buff, int pkt_size, struct RxDesc *desc, int rx_buf_sz) { @@ -1804,7 +1860,8 @@ rtl8169_rx_interrupt(struct net_device * void (*pci_action)(struct pci_dev *, dma_addr_t, size_t, int) = pci_dma_sync_single_for_device; - + rtl8169_rx_csum(skb, desc); + pci_dma_sync_single_for_cpu(tp->pci_dev, le64_to_cpu(desc->addr), tp->rx_buf_sz, PCI_DMA_FROMDEVICE); _ ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 2.6.8.1-mm4 11/11] r8169: vlan support 2004-08-23 22:57 ` [PATCH 2.6.8.1-mm4 10/11] r8169: Rx checksum support Francois Romieu @ 2004-08-23 22:59 ` Francois Romieu 2004-08-28 23:21 ` Jeff Garzik 0 siblings, 1 reply; 17+ messages in thread From: Francois Romieu @ 2004-08-23 22:59 UTC (permalink / raw) To: jgarzik; +Cc: akpm, netdev 802.1Q support. Mostly stolen from the 8139cp.c driver. The relevant registers and descriptors bits are identical for both chipsets. Signed-off-by: Francois Romieu <romieu@fr.zoreil.com> diff -puN drivers/net/r8169.c~r8169-110 drivers/net/r8169.c --- linux-2.6.8.1/drivers/net/r8169.c~r8169-110 2004-08-23 23:31:33.000000000 +0200 +++ linux-2.6.8.1-fr/drivers/net/r8169.c 2004-08-23 23:31:33.000000000 +0200 @@ -50,6 +50,7 @@ VERSION 1.6LK <2004/04/14> #include <linux/delay.h> #include <linux/ethtool.h> #include <linux/mii.h> +#include <linux/if_vlan.h> #include <linux/crc32.h> #include <linux/in.h> #include <linux/ip.h> @@ -78,9 +79,11 @@ VERSION 1.6LK <2004/04/14> #ifdef CONFIG_R8169_NAPI #define rtl8169_rx_skb netif_receive_skb +#define rtl8169_rx_hwaccel_skb vlan_hwaccel_rx #define rtl8169_rx_quota(count, quota) min(count, quota) #else #define rtl8169_rx_skb netif_rx +#define rtl8169_rx_hwaccel_skb vlan_hwaccel_receive_skb #define rtl8169_rx_quota(count, quota) count #endif @@ -320,6 +323,7 @@ enum _DescStatusBit { IPCS = (1 << 18), /* Calculate IP checksum */ UDPCS = (1 << 17), /* Calculate UDP/IP checksum */ TCPCS = (1 << 16), /* Calculate TCP/IP checksum */ + TxVlanTag = (1 << 17), /* Add VLAN tag */ /* Rx private */ PID1 = (1 << 18), /* Protocol ID bit 1/2 */ @@ -333,6 +337,7 @@ enum _DescStatusBit { IPFail = (1 << 16), /* IP checksum failed */ UDPFail = (1 << 15), /* UDP/IP checksum failed */ TCPFail = (1 << 14), /* TCP/IP checksum failed */ + RxVlanTag = (1 << 16), /* VLAN tag available */ }; #define RsvdMask 0x3fffc000 @@ -379,7 +384,9 @@ struct rtl8169_private { u16 intr_mask; int phy_auto_nego_reg; int phy_1000_ctrl_reg; - +#ifdef CONFIG_R8169_VLAN + struct vlan_group *vlgrp; +#endif int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); void (*get_settings)(struct net_device *, struct ethtool_cmd *); void (*phy_reset_enable)(void *); @@ -664,6 +671,77 @@ static int rtl8169_set_rx_csum(struct ne return 0; } +#ifdef CONFIG_R8169_VLAN + +static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, + struct sk_buff *skb) +{ + return (tp->vlgrp && vlan_tx_tag_present(skb)) ? + TxVlanTag | cpu_to_be16(vlan_tx_tag_get(skb)) : 0x00; +} + +static void rtl8169_vlan_rx_register(struct net_device *dev, + struct vlan_group *grp) +{ + struct rtl8169_private *tp = netdev_priv(dev); + void *ioaddr = tp->mmio_addr; + unsigned long flags; + + spin_lock_irqsave(&tp->lock, flags); + tp->vlgrp = grp; + tp->cp_cmd |= RxVlan; + RTL_W16(CPlusCmd, tp->cp_cmd); + RTL_R16(CPlusCmd); + spin_unlock_irqrestore(&tp->lock, flags); +} + +static void rtl8169_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) +{ + struct rtl8169_private *tp = netdev_priv(dev); + void *ioaddr = tp->mmio_addr; + unsigned long flags; + + spin_lock_irqsave(&tp->lock, flags); + tp->cp_cmd &= ~RxVlan; + RTL_W16(CPlusCmd, tp->cp_cmd); + RTL_R16(CPlusCmd); + if (tp->vlgrp) + tp->vlgrp->vlan_devices[vid] = NULL; + spin_unlock_irqrestore(&tp->lock, flags); +} + +static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, + struct sk_buff *skb) +{ + u32 opts2 = desc->opts2; + int ret; + + if (tp->vlgrp && (opts2 & RxVlanTag)) { + rtl8169_rx_hwaccel_skb(skb, tp->vlgrp, + be16_to_cpu(opts2 & 0xffff)); + ret = 0; + } else + ret = -1; + desc->opts2 = 0; + return ret; +} + +#else /* !CONFIG_R8169_VLAN */ + +static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, + struct sk_buff *skb) +{ + return 0; +} + +static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, + struct sk_buff *skb) +{ + return -1; +} + +#endif + static void rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) { struct rtl8169_private *tp = netdev_priv(dev); @@ -1072,6 +1150,8 @@ rtl8169_init_board(struct pci_dev *pdev, tp->cp_cmd = PCIMulRW | RxChkSum; + dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; + if ((sizeof(dma_addr_t) > 32) && !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { tp->cp_cmd |= PCIDAC; dev->features |= NETIF_F_HIGHDMA; @@ -1206,11 +1286,19 @@ rtl8169_init_one(struct pci_dev *pdev, c dev->watchdog_timeo = RTL8169_TX_TIMEOUT; dev->irq = pdev->irq; dev->base_addr = (unsigned long) ioaddr; + #ifdef CONFIG_R8169_NAPI dev->poll = rtl8169_poll; dev->weight = R8169_NAPI_WEIGHT; printk(KERN_INFO PFX "NAPI enabled\n"); #endif + +#ifdef CONFIG_R8169_VLAN + dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; + dev->vlan_rx_register = rtl8169_vlan_rx_register; + dev->vlan_rx_kill_vid = rtl8169_vlan_rx_kill_vid; +#endif + tp->intr_mask = 0xffff; tp->pci_dev = pdev; tp->mmio_addr = ioaddr; @@ -1560,6 +1648,7 @@ static void rtl8169_unmap_tx_skb(struct unsigned int len = tx_skb->len; pci_unmap_single(pdev, le64_to_cpu(desc->addr), len, PCI_DMA_TODEVICE); + desc->opts2 = 0x00; desc->addr = 0x00; tx_skb->len = 0; } @@ -1711,6 +1800,7 @@ static int rtl8169_start_xmit(struct sk_ tp->tx_skb[entry].len = len; txd->addr = cpu_to_le64(mapping); + txd->opts2 = rtl8169_tx_vlan_tag(tp, skb); wmb(); @@ -1878,7 +1968,9 @@ rtl8169_rx_interrupt(struct net_device * skb->dev = dev; skb_put(skb, pkt_size); skb->protocol = eth_type_trans(skb, dev); - rtl8169_rx_skb(skb); + + if (rtl8169_rx_vlan_skb(tp, desc, skb) < 0) + rtl8169_rx_skb(skb); dev->last_rx = jiffies; tp->stats.rx_bytes += pkt_size; diff -puN drivers/net/Kconfig~r8169-110 drivers/net/Kconfig --- linux-2.6.8.1/drivers/net/Kconfig~r8169-110 2004-08-23 23:31:33.000000000 +0200 +++ linux-2.6.8.1-fr/drivers/net/Kconfig 2004-08-23 23:31:33.000000000 +0200 @@ -2061,6 +2061,15 @@ config R8169_NAPI If in doubt, say N. +config R8169_VLAN + bool "VLAN support" + depends on R8169 && VLAN_8021Q + ---help--- + Say Y here for the r8169 driver to support the functions required + by the kernel 802.1Q code. + + If in doubt, say Y. + config SK98LIN tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support" depends on PCI _ ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 2.6.8.1-mm4 11/11] r8169: vlan support 2004-08-23 22:59 ` [PATCH 2.6.8.1-mm4 11/11] r8169: vlan support Francois Romieu @ 2004-08-28 23:21 ` Jeff Garzik 2004-08-29 21:00 ` Francois Romieu 0 siblings, 1 reply; 17+ messages in thread From: Jeff Garzik @ 2004-08-28 23:21 UTC (permalink / raw) To: Francois Romieu; +Cc: akpm, netdev applied all 11 patches to netdev-2.6. does this series of patches imply that a librealtek kernel module is coming soon? There's an awful lot of code duplication (due to hardware similarties) in r8169, 8139cp, and 8139too. Jeff ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 2.6.8.1-mm4 11/11] r8169: vlan support 2004-08-28 23:21 ` Jeff Garzik @ 2004-08-29 21:00 ` Francois Romieu 2004-08-29 21:23 ` Jeff Garzik 0 siblings, 1 reply; 17+ messages in thread From: Francois Romieu @ 2004-08-29 21:00 UTC (permalink / raw) To: Jeff Garzik; +Cc: akpm, netdev Jeff Garzik <jgarzik@pobox.com> : [...] > does this series of patches imply that a librealtek kernel module is > coming soon? There's an awful lot of code duplication (due to hardware > similarties) in r8169, 8139cp, and 8139too. I have not really considered 8139too so far as its hardware is a bit "different" but why not. soon ? What have you done to the real Jeff ? -- Ueimor ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 2.6.8.1-mm4 11/11] r8169: vlan support 2004-08-29 21:00 ` Francois Romieu @ 2004-08-29 21:23 ` Jeff Garzik 0 siblings, 0 replies; 17+ messages in thread From: Jeff Garzik @ 2004-08-29 21:23 UTC (permalink / raw) To: Francois Romieu; +Cc: akpm, netdev Francois Romieu wrote: > Jeff Garzik <jgarzik@pobox.com> : > [...] > >>does this series of patches imply that a librealtek kernel module is >>coming soon? There's an awful lot of code duplication (due to hardware >>similarties) in r8169, 8139cp, and 8139too. > > > I have not really considered 8139too so far as its hardware is a bit > "different" but why not. 8139cp and 8139too both share the same phy code, and 8139cp and r8169 both share the same RX/TX code. > soon ? What have you done to the real Jeff ? hehe :) Jeff ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 2.6.8.1-mm4 8/11] r8169: Tx checksum offload 2004-08-23 22:55 ` [PATCH 2.6.8.1-mm4 8/11] r8169: Tx checksum offload Francois Romieu 2004-08-23 22:56 ` [PATCH 2.6.8.1-mm4 9/11] r8169: advertise DMA to high memory Francois Romieu @ 2004-08-28 23:15 ` Jeff Garzik 1 sibling, 0 replies; 17+ messages in thread From: Jeff Garzik @ 2004-08-28 23:15 UTC (permalink / raw) To: Francois Romieu; +Cc: akpm, netdev Francois Romieu wrote: > +static inline u32 rtl8169_tx_csum(struct sk_buff *skb) > +{ > + if (skb->ip_summed == CHECKSUM_HW) { > + const struct iphdr *ip = skb->nh.iph; > + > + if (ip->protocol == IPPROTO_TCP) > + return IPCS | TCPCS; > + else if (ip->protocol == IPPROTO_UDP) > + return IPCS | UDPCS; > + BUG(); > + } > + return 0; > +} I am applying this patch BUT... BUG() is a bit too "rude" when you can obviously return safely. Prefer WARN_ON() because we don't need to kill the machine for this condition. ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [DESC 2.6.8.1-mm4] r8169 patches 2004-08-23 22:41 [DESC 2.6.8.1-mm4] r8169 patches Francois Romieu 2004-08-23 22:44 ` [PATCH 2.6.8.1-mm4 1/11] r8169: add ethtool_ops.{get_regs_len/get_regs} Francois Romieu @ 2004-08-27 15:09 ` Jon Mason 1 sibling, 0 replies; 17+ messages in thread From: Jon Mason @ 2004-08-27 15:09 UTC (permalink / raw) To: Francois Romieu; +Cc: jgarzik, akpm, netdev I've been running the driver with all of the new patchs on my AMD64 system for over 36 hours without any problems. I have Rx/TX checksumming enabled, but have not tried the VLAN changes. On Monday 23 August 2004 05:41 pm, Francois Romieu wrote: > Here comes a new serie of r8169 related patches which should allow > the motivated users to experiment new features, namely: > - Rx/Tx checksum offload; > - vlan support; > - better ethtool integration. > > Tx code apart, the changes exhibit some strong similarity with the > 8139cp driver. > > I have not done vlan-dedicated test and there are no figures to highlight > any performance improvement. The code does not crash in a (really slow) > debug enabled -mm kernel and it does not seem to add huge leak. > > Remarks/comments/test reports welcome. > > -- > Ueimor -- Jon Mason jdmason@us.ibm.com ^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2004-08-29 21:23 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-08-23 22:41 [DESC 2.6.8.1-mm4] r8169 patches Francois Romieu
2004-08-23 22:44 ` [PATCH 2.6.8.1-mm4 1/11] r8169: add ethtool_ops.{get_regs_len/get_regs} Francois Romieu
2004-08-23 22:45 ` [PATCH 2.6.8.1-mm4 2/11] r8169: per device receive buffer size Francois Romieu
2004-08-23 22:47 ` [PATCH 2.6.8.1-mm4 3/11] r8169: code cleanup Francois Romieu
2004-08-23 22:48 ` [PATCH 2.6.8.1-mm4 4/11] r8169: enable MWI Francois Romieu
2004-08-23 22:49 ` [PATCH 2.6.8.1-mm4 5/11] r8169: bump version number Francois Romieu
2004-08-23 22:51 ` [PATCH 2.6.8.1-mm4 6/11] r8169: sync the names of a few bits with the 8139cp driver Francois Romieu
2004-08-23 22:53 ` [PATCH 2.6.8.1-mm4 7/11] r8169: comment a gcc 2.95.x bug Francois Romieu
2004-08-23 22:55 ` [PATCH 2.6.8.1-mm4 8/11] r8169: Tx checksum offload Francois Romieu
2004-08-23 22:56 ` [PATCH 2.6.8.1-mm4 9/11] r8169: advertise DMA to high memory Francois Romieu
2004-08-23 22:57 ` [PATCH 2.6.8.1-mm4 10/11] r8169: Rx checksum support Francois Romieu
2004-08-23 22:59 ` [PATCH 2.6.8.1-mm4 11/11] r8169: vlan support Francois Romieu
2004-08-28 23:21 ` Jeff Garzik
2004-08-29 21:00 ` Francois Romieu
2004-08-29 21:23 ` Jeff Garzik
2004-08-28 23:15 ` [PATCH 2.6.8.1-mm4 8/11] r8169: Tx checksum offload Jeff Garzik
2004-08-27 15:09 ` [DESC 2.6.8.1-mm4] r8169 patches Jon Mason
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).