* [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: [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
* 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: [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
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).