linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] RealTek(R) RTL-8169 PCI Gigabit Ethernet Card
@ 2003-07-13 17:00 Fernando Alencar Maróstica
  2003-07-13 17:17 ` Jeff Garzik
  2003-08-30 20:18 ` Jeff Garzik
  0 siblings, 2 replies; 3+ messages in thread
From: Fernando Alencar Maróstica @ 2003-07-13 17:00 UTC (permalink / raw)
  To: Marcelo Tosatti
  Cc: Linus Torvalds, Alan Cox, Jeff Garzik, Donald Becker,
	RealTek Mailing List, Kernel Mailing List

[-- 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

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] RealTek(R) RTL-8169 PCI Gigabit Ethernet Card
  2003-07-13 17:00 [PATCH] RealTek(R) RTL-8169 PCI Gigabit Ethernet Card Fernando Alencar Maróstica
@ 2003-07-13 17:17 ` Jeff Garzik
  2003-08-30 20:18 ` Jeff Garzik
  1 sibling, 0 replies; 3+ messages in thread
From: Jeff Garzik @ 2003-07-13 17:17 UTC (permalink / raw)
  To: Fernando Alencar Maróstica
  Cc: Marcelo Tosatti, Linus Torvalds, Alan Cox, Donald Becker,
	RealTek Mailing List, Kernel Mailing List

Looks technically OK but some of the whitespace changes are a bit annoying.

I'll fix it up manually and apply.

Thanks!

	Jeff




^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] RealTek(R) RTL-8169 PCI Gigabit Ethernet Card
  2003-07-13 17:00 [PATCH] RealTek(R) RTL-8169 PCI Gigabit Ethernet Card Fernando Alencar Maróstica
  2003-07-13 17:17 ` Jeff Garzik
@ 2003-08-30 20:18 ` Jeff Garzik
  1 sibling, 0 replies; 3+ messages in thread
From: Jeff Garzik @ 2003-08-30 20:18 UTC (permalink / raw)
  To: Fernando Alencar Maróstica
  Cc: Marcelo Tosatti, Linus Torvalds, Alan Cox, Donald Becker,
	RealTek Mailing List, Kernel Mailing List

Looks good, I'll test it and queue it up.


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2003-08-30 20:18 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-07-13 17:00 [PATCH] RealTek(R) RTL-8169 PCI Gigabit Ethernet Card Fernando Alencar Maróstica
2003-07-13 17:17 ` Jeff Garzik
2003-08-30 20:18 ` Jeff Garzik

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).