From: "Fernando Alencar Maróstica" <famarost@unimep.br>
To: Marcelo Tosatti <marcelo@conectiva.com.br>
Cc: Linus Torvalds <torvalds@osdl.org>,
Alan Cox <alan@lxorguk.ukuu.org.uk>,
Jeff Garzik <jgarzik@pobox.com>, Donald Becker <becker@scyld.com>,
RealTek Mailing List <realtek@scyld.com>,
Kernel Mailing List <linux-kernel@vger.kernel.org>
Subject: [PATCH] RealTek(R) RTL-8169 PCI Gigabit Ethernet Card
Date: 13 Jul 2003 14:00:12 -0300 [thread overview]
Message-ID: <1058115615.887.85.camel@nitrogenium> (raw)
[-- Attachment #1: Type: text/plain, Size: 579 bytes --]
Hi all,
Here's a patch for the new RealTek(R) RTL-8169 PCI Gigabit driver
(drivers/net/r8169.c) in the 2.4.22-pre5 kernel. This patch fixes
severals functions, add new PCI suspend and resume stuff and cleanup
code.
The patch applies against 2.4.22-pre5 and 2.5.75. I've tested the
compilation with 2.4.22-pre5.
Cheers!
--
Fernando Alencar Maróstica
Graduate Student, Computer Science
Linux Register User Id #281457
University Methodist of Piracicaba
Departament of Computer Science
email: famarost@unimep.br
homepage: http://www.unimep.br/~famarost
[-- Attachment #2: r8169-linux-2.4.22-pre5.pach --]
[-- Type: text/plain, Size: 10183 bytes --]
--- r8169.c.orig Sun Jul 13 13:32:55 2003
+++ r8169.c Sun Jul 13 13:55:02 2003
@@ -32,7 +32,15 @@
- Use ether_crc in stock kernel (linux/crc32.h)
- Copy mc_filter setup code from 8139cp
(includes an optimization, and avoids set_bit use)
-
+
+ <2003/07/13>
+ Fernando Alencar Marostica <famarost@unimep.br>
+ - Fix rtl8169_init_one()
+ - Fix rtl8169_get_stats()
+ - Fix rtl8169_remove_one()
+ - Add new rtl8169_resume() support
+ - Add new rtl8169_suspend() support
+ - Several fixes and cleanup code
*/
#include <linux/module.h>
@@ -46,9 +54,9 @@
#include <asm/io.h>
#define RTL8169_VERSION "1.2"
-#define MODULENAME "r8169"
-#define RTL8169_DRIVER_NAME MODULENAME " Gigabit Ethernet driver " RTL8169_VERSION
-#define PFX MODULENAME ": "
+#define MODULE_NAME "r8169"
+#define RTL8169_DRIVER_NAME MODULE_NAME " Realtek(R) RTL-8169 PCI Gigabit Ethernet Card " RTL8169_VERSION
+#define PFX MODULE_NAME ": "
#ifdef RTL8169_DEBUG
#define assert(expr) \
@@ -101,11 +109,17 @@
#define RTL_R16(reg) readw (ioaddr + (reg))
#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg)))
-static struct {
+
+struct rtl8169_card_info {
const char *name;
-} board_info[] __devinitdata = {
- {
-"RealTek RTL8169 Gigabit Ethernet"},};
+ u8 mac_version; /* depend on RTL8169 docs */
+ u32 RxConfigMask; /* should clear the bits supported by this chip */
+};
+
+struct rtl8169_card_info rtl8169_card_info_tbl[] __devinitdata = {
+ { "RealTek RTL8169 Gigabit Ethernet", 0x02, 0xff7e1880 },
+ { "RealTek RTL8169s/8110s Gigabit Ethernet", 0x03, 0xff7e1880 },
+};
static struct pci_device_id rtl8169_pci_tbl[] __devinitdata = {
{0x10ec, 0x8169, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
@@ -287,16 +301,19 @@
unsigned char *RxBufferRings; /* Index of Rx Buffer */
unsigned char *RxBufferRing[NUM_RX_DESC]; /* Index of Rx Buffer array */
struct sk_buff *Tx_skbuff[NUM_TX_DESC]; /* Index of Transmit data buffer */
+#ifdef CONFIG_PM
+ u32 power_state[16];
+#endif
};
MODULE_AUTHOR("Realtek");
-MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
+MODULE_DESCRIPTION("RealTek(R) RTL-8169 PCI Gigabit Ethernet Card");
+MODULE_LICENSE("GPL");
MODULE_PARM(media, "1-" __MODULE_STRING(MAX_UNITS) "i");
static int rtl8169_open(struct net_device *dev);
-static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static void rtl8169_interrupt(int irq, void *dev_instance,
- struct pt_regs *regs);
+static int rtl8169_start_xmit(struct sk_buff *skb,struct net_device *dev);
+static void rtl8169_interrupt(int irq,void *dev_instance,struct pt_regs *regs);
static void rtl8169_init_ring(struct net_device *dev);
static void rtl8169_hw_start(struct net_device *dev);
static int rtl8169_close(struct net_device *dev);
@@ -358,6 +375,7 @@
int rc, i;
unsigned long mmio_start, mmio_end, mmio_flags, mmio_len;
u32 tmp;
+ int acpi_idle_state = 0, pm_cap;
assert(pdev != NULL);
assert(ioaddr_out != NULL);
@@ -365,20 +383,34 @@
*ioaddr_out = NULL;
*dev_out = NULL;
- // dev zeroed in alloc_etherdev
+ /* dev zeroed in alloc_etherdev */
dev = alloc_etherdev(sizeof (*tp));
- if (dev == NULL) {
- printk(KERN_ERR PFX "unable to alloc new ethernet\n");
+ if (!dev) {
+ printk(KERN_ERR PFX "%s: Could not allocate new ethernet device.\n", pdev->slot_name);
return -ENOMEM;
}
SET_MODULE_OWNER(dev);
tp = dev->priv;
- // enable device (incl. PCI PM wakeup and hotplug setup)
+ /* enable device (incl. PCI PM wakeup and hotplug setup) */
rc = pci_enable_device(pdev);
- if (rc)
+ if(rc) {
+ printk(KERN_ERR PFX "%s: unable to enable device\n", pdev->slot_name);
goto err_out;
+ }
+
+ /* save power state before pci_enable_device overwrites it */
+ pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
+ if (pm_cap) {
+ u16 pwr_command;
+ pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command);
+ acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK;
+ }
+ else {
+ printk(KERN_ERR PFX "Cannot find PowerManagement capability, aborting.\n");
+ goto err_out_free_res;
+ }
mmio_start = pci_resource_start(pdev, 1);
mmio_end = pci_resource_end(pdev, 1);
@@ -400,10 +432,12 @@
}
rc = pci_request_regions(pdev, dev->name);
- if (rc)
+ if(rc) {
+ printk(KERN_ERR PFX "%s: Could not request regions.\n", pdev->slot_name);
goto err_out_disable;
-
- // enable PCI bus-mastering
+ }
+
+ /* enable PCI bus-mastering */
pci_set_master(pdev);
// ioremap MMIO region
@@ -464,7 +498,6 @@
struct rtl8169_private *tp = NULL;
void *ioaddr = NULL;
static int board_idx = -1;
- static int printed_version = 0;
int i, rc;
int option = -1, Cap10_100 = 0, Cap1000 = 0;
@@ -473,10 +506,15 @@
board_idx++;
- if (!printed_version) {
- printk(KERN_INFO RTL8169_DRIVER_NAME " loaded\n");
- printed_version = 1;
+#ifndef MODULE
+ {
+ /* when built-in, we only print version if device is found */
+ static int did_version;
+
+ if (!did_version++)
+ printk(KERN_INFO RTL8169_DRIVER_NAME " loaded\n");
}
+#endif
rc = rtl8169_init_board(pdev, &dev, &ioaddr);
if (rc)
@@ -500,7 +538,7 @@
dev->watchdog_timeo = TX_TIMEOUT;
dev->irq = pdev->irq;
dev->base_addr = (unsigned long) ioaddr;
-// dev->do_ioctl = mii_ioctl;
+ //dev->do_ioctl = mii_ioctl;
tp = dev->priv; // private data //
tp->pci_dev = pdev;
@@ -526,7 +564,7 @@
"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
"IRQ %d\n",
dev->name,
- board_info[ent->driver_data].name,
+ rtl8169_card_info_tbl[ent->driver_data].name,
dev->base_addr,
dev->dev_addr[0], dev->dev_addr[1],
dev->dev_addr[2], dev->dev_addr[3],
@@ -627,28 +665,104 @@
return 0;
}
-static void __devexit
-rtl8169_remove_one(struct pci_dev *pdev)
+/**
+ * rtl8169_get_stats: - Get rtl8169 read/write statistics
+ * @ethernet_device: The Ethernet Device to get statistics for
+ *
+ * Get TX/RX statistics for rtl8169
+ */
+struct net_device_stats *rtl8169_get_stats (struct net_device *ethernet_device)
{
- struct net_device *dev = pci_get_drvdata(pdev);
- struct rtl8169_private *tp = dev->priv;
+ struct rtl8169_private *tp = ethernet_device->priv;
+ void *ioaddr = tp->mmio_addr;
+ unsigned long flags;
- assert(dev != NULL);
- assert(tp != NULL);
+ if (netif_running(ethernet_device)) {
+ spin_lock_irqsave (&tp->lock, flags);
+ tp->stats.rx_missed_errors += ((unsigned long) readl (ioaddr + (RxMissed)));
+ writel ((0), ioaddr + (RxMissed));
+ spin_unlock_irqrestore (&tp->lock, flags);
+ }
- unregister_netdev(dev);
- iounmap(tp->mmio_addr);
- pci_release_regions(pdev);
+ return &tp->stats;
+}
- // poison memory before freeing
- memset(dev, 0xBC,
- sizeof (struct net_device) + sizeof (struct rtl8169_private));
+/**
+ * rtl8169_remove_one: - Remove rtl8169 device
+ * @pci_device: The PCI Device to be removed
+ *
+ * Remove and release rtl8169 PCI Ethernet Device
+ */
+static void __devexit rtl8169_remove_one (struct pci_dev *pci_device)
+{
+ struct net_device *ethernet_device = pci_get_drvdata (pci_device);
+ struct rtl8169_private *tp = (struct rtl8169_private *) (ethernet_device->priv);
- pci_disable_device(pdev);
- kfree(dev);
- pci_set_drvdata(pdev, NULL);
+ if (!ethernet_device)
+ BUG();
+
+ unregister_netdev(ethernet_device);
+ iounmap((char *) (tp->mmio_addr));
+
+#ifdef CONFIG_PM
+ pci_set_power_state (pci_device, 0);
+ pci_restore_state (pci_device, tp->power_state);
+#endif
+
+ pci_release_regions(pci_device);
+ pci_disable_device(pci_device);
+ pci_set_drvdata(pci_device, NULL);
+
+ /* poison memory before freeing */
+ memset(ethernet_device, 0xBC, sizeof(struct net_device) + sizeof(struct rtl8169_private));
+ kfree(ethernet_device);
+}
+
+
+#ifdef CONFIG_PM
+
+static int rtl8169_suspend (struct pci_dev *pci_device, u32 state)
+{
+ struct net_device *ethernet_device = pci_get_drvdata (pci_device);
+ struct rtl8169_private *tp = (struct rtl8169_private *) (ethernet_device->priv);
+ void *ioaddr = tp->mmio_addr;
+ unsigned long flags;
+
+ if (!netif_running (ethernet_device))
+ return 0;
+
+ netif_device_detach (ethernet_device);
+ netif_stop_queue (ethernet_device);
+ spin_lock_irqsave (&tp->lock, flags);
+
+ /* Disable interrupts, stop Rx and Tx */
+ writew ((0), ioaddr + (IntrMask));
+ writeb ((0), ioaddr + (ChipCmd));
+
+ /* Update the error counts. */
+ tp->stats.rx_missed_errors += RTL_R32 (RxMissed);
+ writel ((0), ioaddr + (RxMissed));
+ spin_unlock_irqrestore (&tp->lock, flags);
+
+ return 0;
+}
+
+static int rtl8169_resume (struct pci_dev *pci_device)
+{
+ struct net_device *ethernet_device = pci_get_drvdata (pci_device);
+
+ if (!netif_running (ethernet_device))
+ return 0;
+
+ netif_device_attach (ethernet_device);
+ rtl8169_hw_start (ethernet_device);
+ netif_start_queue (ethernet_device);
+
+ return 0;
}
+#endif /* CONFIG_PM */
+
static int
rtl8169_open(struct net_device *dev)
{
@@ -696,6 +810,7 @@
rtl8169_init_ring(dev);
rtl8169_hw_start(dev);
+ netif_start_queue(dev);
return 0;
@@ -752,9 +867,6 @@
/* Enable all known interrupts by setting the interrupt mask. */
RTL_W16(IntrMask, rtl8169_intr_mask);
-
- netif_start_queue(dev);
-
}
static void
@@ -1108,21 +1220,17 @@
spin_unlock_irqrestore(&tp->lock, flags);
}
-struct net_device_stats *
-rtl8169_get_stats(struct net_device *dev)
-{
- struct rtl8169_private *tp = dev->priv;
- return &tp->stats;
-}
static struct pci_driver rtl8169_pci_driver = {
- .name = MODULENAME,
+ .name = MODULE_NAME,
.id_table = rtl8169_pci_tbl,
.probe = rtl8169_init_one,
.remove = __devexit_p(rtl8169_remove_one),
- .suspend = NULL,
- .resume = NULL,
+#ifdef CONFIG_PM
+ .suspend = rtl8169_suspend,
+ .resume = rtl8169_resume,
+#endif
};
static int __init
next reply other threads:[~2003-07-13 16:56 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-07-13 17:00 Fernando Alencar Maróstica [this message]
2003-07-13 17:17 ` [PATCH] RealTek(R) RTL-8169 PCI Gigabit Ethernet Card Jeff Garzik
2003-08-30 20:18 ` Jeff Garzik
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1058115615.887.85.camel@nitrogenium \
--to=famarost@unimep.br \
--cc=alan@lxorguk.ukuu.org.uk \
--cc=becker@scyld.com \
--cc=jgarzik@pobox.com \
--cc=linux-kernel@vger.kernel.org \
--cc=marcelo@conectiva.com.br \
--cc=realtek@scyld.com \
--cc=torvalds@osdl.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.