Re: [PATCH] 2.6 driver for Silan SC92031

2006-12-02 Thread Cesar Eduardo Barros

Jeff Garzik escreveu:

Cesar Eduardo Barros wrote:

From: Cesar Eduardo Barros [EMAIL PROTECTED]

This is a driver for the Silan SC92031/Rsltek 8139D NIC chip. It's a
rewrite of the vendor 2.4 driver for 2.6, and has been lightly tested
on a 2.6.17 x86-64 kernel with the Ubuntu patches (as a out-of-tree
module only).



Seems like it would be best to modify the existing 8139 driver...


I'm not sure it would help. Either the hardware differences are too 
large (for instance, the MII/link part, where the way the vendor driver 
did things implies the MII has only the two basic registers plus two 
vendor registers, meaning I simply cannot use the generic mii code) or 
the code is already modified from the 8139 driver (the vendor driver 
seems to be based on an old version of either pci-skeleton.c or 
8139too.c, and I based my rewrite on the vendor driver).


Of course, one thing I probably will copy from 8139too.c later is the 
NAPI code; I wanted to avoid the extra locking complexity in this first 
version (the fact that the interrupt status register is cleared on 
reading only makes things more complex). If you can suggest other things 
to copy, it would be good, since the copied code is less likely to be wrong.


--
Cesar Eduardo Barros
[EMAIL PROTECTED]
[EMAIL PROTECTED]
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] 2.6 driver for Silan SC92031 (second try)

2006-12-08 Thread Cesar Eduardo Barros
From: Cesar Eduardo Barros [EMAIL PROTECTED]

This is a driver for the Silan SC92031/Rsltek 8139D NIC chip.

This chip is found on at least one counterfeit Encore ENL832-TX-RENT
NIC [1], which came with a mini-CD with the 2.4 driver. A slightly
older version of the driver was found at [2]. The main difference
between them is that the newer one has a small bugfix in the RX path,
a lot of gratuitous renaming of functions, all the printable strings
changed to show as a Rsltek 8139D [sic], and a PCI ID of 8139 instead
of 2031. The driver on this patch is a rewrite of the vendor drivers
(based mostly on the older one).

This patch is against 2.6.19; it is currently being used on a 2.6.17 [3]
kernel on one of my boxes (Ubuntu x86-64 vendor kernel, with the driver
compiled as a out-of-tree module), and compiles on 2.6.19 without any
errors or warnings.

Changes from the previous patch sent to netdev:
- Use MMIO instead of PIO
- Changed TX bounce buffers allocation
- Use skb_copy_and_csum_dev
- Several small bug fixes
- Tested for more than just a few minutes each time

[1] See http://www.encore-usa.com/faq.php under ENL832-TX-RENT for more
information
[2] Look for SL_LINUX.ZIP (which is really a .tar.gz) at
http://broadbandforum.in/dataone_Intex_LAN_cardlinux-t4207-s15.html
[3] To compile on 2.6.17, simply add back the last argument to the
interrupt handler in two places, and copy the boolean declarations
from 2.6.19

Signed-off-by: Cesar Eduardo Barros [EMAIL PROTECTED]

---

diff -uprN -X linux-2.6.19.orig/Documentation/dontdiff 
linux-2.6.19.orig/drivers/net/Kconfig linux-2.6.19/drivers/net/Kconfig
--- linux-2.6.19.orig/drivers/net/Kconfig   2006-11-29 19:57:37.0 
-0200
+++ linux-2.6.19/drivers/net/Kconfig2006-12-02 18:50:23.0 -0200
@@ -1777,6 +1777,18 @@ config LAN_SAA9730
  workstations.
  See http://www.semiconductors.philips.com/pip/SAA9730_flyer_1.

+config SC92031
+   tristate Silan SC92031 PCI Fast Ethernet Adapter driver (EXPERIMENTAL)
+   depends on NET_PCI  PCI  EXPERIMENTAL
+   select CRC32
+   ---help---
+ This is a driver for the Fast Ethernet PCI network cards based on
+ the Silan SC92031 chip (sometimes also called Rsltek 8139D). If you
+ have one of these, say Y here.
+
+ To compile this driver as a module, choose M here: the module
+ will be called sc92031.  This is recommended.
+
 config NET_POCKET
bool Pocket and portable adapters
depends on NET_ETHERNET  PARPORT
diff -uprN -X linux-2.6.19.orig/Documentation/dontdiff 
linux-2.6.19.orig/drivers/net/Makefile linux-2.6.19/drivers/net/Makefile
--- linux-2.6.19.orig/drivers/net/Makefile  2006-11-29 19:57:37.0 
-0200
+++ linux-2.6.19/drivers/net/Makefile   2006-12-02 18:50:23.0 -0200
@@ -160,6 +160,7 @@ obj-$(CONFIG_APRICOT) += 82596.o
 obj-$(CONFIG_LASI_82596) += lasi_82596.o
 obj-$(CONFIG_MVME16x_NET) += 82596.o
 obj-$(CONFIG_BVME6000_NET) += 82596.o
+obj-$(CONFIG_SC92031) += sc92031.o

 # This is also a 82596 and should probably be merged
 obj-$(CONFIG_LP486E) += lp486e.o
diff -uprN -X linux-2.6.19.orig/Documentation/dontdiff 
linux-2.6.19.orig/drivers/net/sc92031.c linux-2.6.19/drivers/net/sc92031.c
--- linux-2.6.19.orig/drivers/net/sc92031.c 1969-12-31 21:00:00.0 
-0300
+++ linux-2.6.19/drivers/net/sc92031.c  2006-12-08 17:41:56.0 -0200
@@ -0,0 +1,1583 @@
+/*  Silan SC92031 PCI Fast Ethernet Adapter driver
+ *
+ *  Based on vendor drivers:
+ *  Silan Fast Ethernet Netcard Driver:
+ *MODULE_AUTHOR (gaoyonghong);
+ *MODULE_DESCRIPTION (SILAN Fast Ethernet driver);
+ *MODULE_LICENSE(GPL);
+ *  8139D Fast Ethernet driver:
+ *(C) 2002 by gaoyonghong
+ *MODULE_AUTHOR (gaoyonghong);
+ *MODULE_DESCRIPTION (Rsltek 8139D PCI Fast Ethernet Adapter driver);
+ *MODULE_LICENSE(GPL);
+ *  Both are almost identical and seem to be based on pci-skeleton.c
+ *
+ *  Rewritten for 2.6 by Cesar Eduardo Barros
+ */
+
+/* Note about set_mac_address: I don't know how to change the hardware
+ * matching, so you need to enable IFF_PROMISC when using it.
+ */
+
+#include linux/module.h
+#include linux/kernel.h
+#include linux/delay.h
+#include linux/pci.h
+#include linux/netdevice.h
+#include linux/etherdevice.h
+#include linux/ethtool.h
+#include linux/crc32.h
+
+#define PCI_VENDOR_ID_SILAN0x1904
+#define PCI_DEVICE_ID_SILAN_SC920310x2031
+#define PCI_DEVICE_ID_SILAN_8139D  0x8139
+
+#define SC92031_NAME sc92031
+#define SC92031_DESCRIPTION Silan SC92031 PCI Fast Ethernet Adapter driver
+#define SC92031_VERSION 2.0b
+
+/* BAR 0 is MMIO, BAR 1 is PIO */
+#ifndef SC92031_USE_BAR
+#define SC92031_USE_BAR 0
+#endif
+
+/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). */
+static int multicast_filter_limit = 64;
+module_param(multicast_filter_limit, int, 0);
+MODULE_PARM_DESC(multicast_filter_limit,
+   Maximum number of filtered

Re: [PATCH] 2.6 driver for Silan SC92031 (second try)

2006-12-09 Thread Cesar Eduardo Barros
Andrew Morton escreveu:
 On Fri, 08 Dec 2006 18:17:06 -0200
 Cesar Eduardo Barros [EMAIL PROTECTED] wrote:
 
 From: Cesar Eduardo Barros [EMAIL PROTECTED]

 +} while(unlikely(cmpxchg(priv-intr_status,
 
 You'll have the arm maintainer after you with a pointy stick.
 
 cmpxchg is only available on certain architectures.  It would be acceptable
 to make this driver depend on X86 (or something).  Better to rewrite this
 code so it doesn't use cmpxchg.

Fixed. As long as I make sure the interrupt and the tasklet never run at the
same time, I do not need to protect intr_status against concurrent modification.

Also fixed a potential bug where the tasklet could end up permanently disabled.

Apply on top of the previous (2.0b) patch (if you prefer a merged patch, just
ask and I'll make one).

It has received the same testing as the previous one, only for less time (I'm
using it right now).

Signed-off-by: Cesar Eduardo Barros [EMAIL PROTECTED]

---

diff -uprN -X linux-2.6.19.orig/Documentation/dontdiff 
linux-2.6.19-2.0b/drivers/net/sc92031.c linux-2.6.19/drivers/net/sc92031.c
--- linux-2.6.19-2.0b/drivers/net/sc92031.c 2006-12-09 17:53:22.0 
-0200
+++ linux-2.6.19/drivers/net/sc92031.c  2006-12-09 17:55:20.0 -0200
@@ -34,7 +34,7 @@

 #define SC92031_NAME sc92031
 #define SC92031_DESCRIPTION Silan SC92031 PCI Fast Ethernet Adapter driver
-#define SC92031_VERSION 2.0b
+#define SC92031_VERSION 2.0c

 /* BAR 0 is MMIO, BAR 1 is PIO */
 #ifndef SC92031_USE_BAR
@@ -261,6 +261,12 @@ enum PMConfigBits {
  * Use mmiowb() before unlocking if the hardware was written to.
  */

+/* Locking rules for the interrupt:
+ * - the interrupt and the tasklet never run at the same time
+ * - neither run between sc92031_disable_interrupts and
+ *   sc92031_enable_interrupt
+ */
+
 struct sc92031_priv {
spinlock_t  lock;
/* iomap.h cookie */
@@ -288,6 +294,7 @@ struct sc92031_priv {

/* copies of some hardware registers */
u32 intr_status;
+   atomic_tintr_mask;
u32 rx_config;
u32 tx_config;
u32 pm_config;
@@ -304,6 +311,13 @@ struct sc92031_priv {
struct net_device_stats stats;
 };

+/* I don't know which registers can be safely read; however, I can guess
+ * MAC0 is one of them. */
+static inline void _sc92031_dummy_read(void __iomem *port_base)
+{
+   ioread32(port_base + MAC0);
+}
+
 static u32 _sc92031_mii_wait(void __iomem *port_base)
 {
u32 mii_status;
@@ -348,12 +362,18 @@ static void sc92031_disable_interrupts(s
struct sc92031_priv *priv = netdev_priv(dev);
void __iomem *port_base = priv-port_base;

-   tasklet_disable(priv-tasklet);
+   /* tell the tasklet/interrupt not to enable interrupts */
+   atomic_set(priv-intr_mask, 0);
+   wmb();

+   /* stop interrupts */
iowrite32(0, port_base + IntrMask);
+   _sc92031_dummy_read(port_base);
mmiowb();

+   /* wait for any concurrent interrupt/tasklet to finish */
synchronize_irq(dev-irq);
+   tasklet_disable(priv-tasklet);
 }

 static void sc92031_enable_interrupts(struct net_device *dev)
@@ -363,6 +383,9 @@ static void sc92031_enable_interrupts(st

tasklet_enable(priv-tasklet);

+   atomic_set(priv-intr_mask, IntrBits);
+   wmb();
+
iowrite32(IntrBits, port_base + IntrMask);
mmiowb();
 }
@@ -608,6 +631,7 @@ static void _sc92031_reset(struct net_de

/* clear old register values */
priv-intr_status = 0;
+   atomic_set(priv-intr_mask, 0);
priv-rx_config = 0;
priv-tx_config = 0;
priv-mc_flags = 0;
@@ -824,9 +848,9 @@ static void sc92031_tasklet(unsigned lon
struct net_device *dev = (struct net_device *)data;
struct sc92031_priv *priv = netdev_priv(dev);
void __iomem *port_base = priv-port_base;
-   u32 intr_status;
+   u32 intr_status, intr_mask;

-   intr_status = xchg(priv-intr_status, 0);
+   intr_status = priv-intr_status;

spin_lock(priv-lock);

@@ -851,7 +875,10 @@ static void sc92031_tasklet(unsigned lon
_sc92031_link_tasklet(dev);

 out:
-   iowrite32(IntrBits, port_base + IntrMask);
+   intr_mask = atomic_read(priv-intr_mask);
+   rmb();
+
+   iowrite32(intr_mask, port_base + IntrMask);
mmiowb();

spin_unlock(priv-lock);
@@ -862,29 +889,33 @@ static irqreturn_t sc92031_interrupt(int
struct net_device *dev = dev_id;
struct sc92031_priv *priv = netdev_priv(dev);
void __iomem *port_base = priv-port_base;
-   u32 intr_status, old_intr_status, new_intr_status;
+   u32 intr_status, intr_mask;
+
+   /* mask interrupts before clearing IntrStatus */
+   iowrite32(0, port_base + IntrMask);
+   _sc92031_dummy_read(port_base);

intr_status = ioread32(port_base + IntrStatus