aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-06-28 21:28:46 -0700
committerDavid S. Miller <davem@davemloft.net>2008-06-28 21:28:46 -0700
commit332e4af80d1214fbf0e263e1408fc7c5b64ecdd6 (patch)
tree7c8f8ada7ab8fc9cb2497d95e52dce4d2c4493a3
parent1b63ba8a86c85524a8d7e5953b314ce71ebcb9c9 (diff)
parentbe0976be9148f31ee0d1997354c3e30ff8d07587 (diff)
Merge branch 'davem-next' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6
-rw-r--r--Documentation/networking/dm9000.txt167
-rw-r--r--arch/blackfin/mach-bf527/boards/ezkit.c7
-rw-r--r--arch/blackfin/mach-bf533/boards/H8606.c7
-rw-r--r--arch/blackfin/mach-bf537/boards/generic_board.c7
-rw-r--r--drivers/net/8139cp.c1
-rw-r--r--drivers/net/8139too.c13
-rw-r--r--drivers/net/Kconfig31
-rw-r--r--drivers/net/cxgb3/cxgb3_offload.c21
-rw-r--r--drivers/net/cxgb3/t3cdev.h3
-rw-r--r--drivers/net/dl2k.c2
-rw-r--r--drivers/net/dm9000.c1159
-rw-r--r--drivers/net/dm9000.h11
-rw-r--r--drivers/net/e1000/e1000_main.c34
-rw-r--r--drivers/net/e1000e/e1000.h4
-rw-r--r--drivers/net/e1000e/netdev.c48
-rw-r--r--drivers/net/fealnx.c43
-rw-r--r--drivers/net/forcedeth.c5
-rw-r--r--drivers/net/igb/igb.h4
-rw-r--r--drivers/net/igb/igb_main.c47
-rw-r--r--drivers/net/ixgbe/ixgbe.h9
-rw-r--r--drivers/net/ixgbe/ixgbe_ethtool.c11
-rw-r--r--drivers/net/ixgbe/ixgbe_main.c111
-rw-r--r--drivers/net/pci-skeleton.c1
-rw-r--r--drivers/net/sh_eth.c4
-rw-r--r--drivers/net/sh_eth.h4
-rw-r--r--drivers/net/tsi108_eth.c1
-rw-r--r--drivers/net/tulip/21142.c6
-rw-r--r--drivers/net/tulip/de2104x.c10
-rw-r--r--drivers/net/tulip/eeprom.c6
-rw-r--r--drivers/net/tulip/interrupt.c5
-rw-r--r--drivers/net/tulip/media.c5
-rw-r--r--drivers/net/tulip/pnic.c5
-rw-r--r--drivers/net/tulip/pnic2.c5
-rw-r--r--drivers/net/tulip/timer.c6
-rw-r--r--drivers/net/tulip/tulip.h4
-rw-r--r--drivers/net/tulip/tulip_core.c8
-rw-r--r--drivers/net/typhoon.c3
-rw-r--r--drivers/net/usb/rndis_host.c14
-rw-r--r--drivers/net/wireless/rndis_wlan.c4
-rw-r--r--drivers/pci/pci-acpi.c20
-rw-r--r--include/linux/dm9000.h1
-rw-r--r--include/linux/usb/rndis_host.h3
42 files changed, 1122 insertions, 738 deletions
diff --git a/Documentation/networking/dm9000.txt b/Documentation/networking/dm9000.txt
new file mode 100644
index 00000000000..65df3dea556
--- /dev/null
+++ b/Documentation/networking/dm9000.txt
@@ -0,0 +1,167 @@
+DM9000 Network driver
+=====================
+
+Copyright 2008 Simtec Electronics,
+ Ben Dooks <ben@simtec.co.uk> <ben-linux@fluff.org>
+
+
+Introduction
+------------
+
+This file describes how to use the DM9000 platform-device based network driver
+that is contained in the files drivers/net/dm9000.c and drivers/net/dm9000.h.
+
+The driver supports three DM9000 variants, the DM9000E which is the first chip
+supported as well as the newer DM9000A and DM9000B devices. It is currently
+maintained and tested by Ben Dooks, who should be CC: to any patches for this
+driver.
+
+
+Defining the platform device
+----------------------------
+
+The minimum set of resources attached to the platform device are as follows:
+
+ 1) The physical address of the address register
+ 2) The physical address of the data register
+ 3) The IRQ line the device's interrupt pin is connected to.
+
+These resources should be specified in that order, as the ordering of the
+two address regions is important (the driver expects these to be address
+and then data).
+
+An example from arch/arm/mach-s3c2410/mach-bast.c is:
+
+static struct resource bast_dm9k_resource[] = {
+ [0] = {
+ .start = S3C2410_CS5 + BAST_PA_DM9000,
+ .end = S3C2410_CS5 + BAST_PA_DM9000 + 3,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = S3C2410_CS5 + BAST_PA_DM9000 + 0x40,
+ .end = S3C2410_CS5 + BAST_PA_DM9000 + 0x40 + 0x3f,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .start = IRQ_DM9000,
+ .end = IRQ_DM9000,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+ }
+};
+
+static struct platform_device bast_device_dm9k = {
+ .name = "dm9000",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bast_dm9k_resource),
+ .resource = bast_dm9k_resource,
+};
+
+Note the setting of the IRQ trigger flag in bast_dm9k_resource[2].flags,
+as this will generate a warning if it is not present. The trigger from
+the flags field will be passed to request_irq() when registering the IRQ
+handler to ensure that the IRQ is setup correctly.
+
+This shows a typical platform device, without the optional configuration
+platform data supplied. The next example uses the same resources, but adds
+the optional platform data to pass extra configuration data:
+
+static struct dm9000_plat_data bast_dm9k_platdata = {
+ .flags = DM9000_PLATF_16BITONLY,
+};
+
+static struct platform_device bast_device_dm9k = {
+ .name = "dm9000",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bast_dm9k_resource),
+ .resource = bast_dm9k_resource,
+ .dev = {
+ .platform_data = &bast_dm9k_platdata,
+ }
+};
+
+The platform data is defined in include/linux/dm9000.h and described below.
+
+
+Platform data
+-------------
+
+Extra platform data for the DM9000 can describe the IO bus width to the
+device, whether or not an external PHY is attached to the device and
+the availability of an external configuration EEPROM.
+
+The flags for the platform data .flags field are as follows:
+
+DM9000_PLATF_8BITONLY
+
+ The IO should be done with 8bit operations.
+
+DM9000_PLATF_16BITONLY
+
+ The IO should be done with 16bit operations.
+
+DM9000_PLATF_32BITONLY
+
+ The IO should be done with 32bit operations.
+
+DM9000_PLATF_EXT_PHY
+
+ The chip is connected to an external PHY.
+
+DM9000_PLATF_NO_EEPROM
+
+ This can be used to signify that the board does not have an
+ EEPROM, or that the EEPROM should be hidden from the user.
+
+DM9000_PLATF_SIMPLE_PHY
+
+ Switch to using the simpler PHY polling method which does not
+ try and read the MII PHY state regularly. This is only available
+ when using the internal PHY. See the section on link state polling
+ for more information.
+
+ The config symbol DM9000_FORCE_SIMPLE_PHY_POLL, Kconfig entry
+ "Force simple NSR based PHY polling" allows this flag to be
+ forced on at build time.
+
+
+PHY Link state polling
+----------------------
+
+The driver keeps track of the link state and informs the network core
+about link (carrier) availablilty. This is managed by several methods
+depending on the version of the chip and on which PHY is being used.
+
+For the internal PHY, the original (and currently default) method is
+to read the MII state, either when the status changes if we have the
+necessary interrupt support in the chip or every two seconds via a
+periodic timer.
+
+To reduce the overhead for the internal PHY, there is now the option
+of using the DM9000_FORCE_SIMPLE_PHY_POLL config, or DM9000_PLATF_SIMPLE_PHY
+platform data option to read the summary information without the
+expensive MII accesses. This method is faster, but does not print
+as much information.
+
+When using an external PHY, the driver currently has to poll the MII
+link status as there is no method for getting an interrupt on link change.
+
+
+DM9000A / DM9000B
+-----------------
+
+These chips are functionally similar to the DM9000E and are supported easily
+by the same driver. The features are:
+
+ 1) Interrupt on internal PHY state change. This means that the periodic
+ polling of the PHY status may be disabled on these devices when using
+ the internal PHY.
+
+ 2) TCP/UDP checksum offloading, which the driver does not currently support.
+
+
+ethtool
+-------
+
+The driver supports the ethtool interface for access to the driver
+state information, the PHY state and the EEPROM.
diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c
index 5958eecefcf..689b69c98ee 100644
--- a/arch/blackfin/mach-bf527/boards/ezkit.c
+++ b/arch/blackfin/mach-bf527/boards/ezkit.c
@@ -323,10 +323,15 @@ static struct platform_device smc91x_device = {
static struct resource dm9000_resources[] = {
[0] = {
.start = 0x203FB800,
- .end = 0x203FB800 + 8,
+ .end = 0x203FB800 + 1,
.flags = IORESOURCE_MEM,
},
[1] = {
+ .start = 0x203FB800 + 4,
+ .end = 0x203FB800 + 5,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
.start = IRQ_PF9,
.end = IRQ_PF9,
.flags = (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE),
diff --git a/arch/blackfin/mach-bf533/boards/H8606.c b/arch/blackfin/mach-bf533/boards/H8606.c
index 7cc4864f6aa..4103a97c1a7 100644
--- a/arch/blackfin/mach-bf533/boards/H8606.c
+++ b/arch/blackfin/mach-bf533/boards/H8606.c
@@ -65,10 +65,15 @@ static struct platform_device rtc_device = {
static struct resource dm9000_resources[] = {
[0] = {
.start = 0x20300000,
- .end = 0x20300000 + 8,
+ .end = 0x20300000 + 1,
.flags = IORESOURCE_MEM,
},
[1] = {
+ .start = 0x20300000 + 4,
+ .end = 0x20300000 + 5,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
.start = IRQ_PF10,
.end = IRQ_PF10,
.flags = (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE),
diff --git a/arch/blackfin/mach-bf537/boards/generic_board.c b/arch/blackfin/mach-bf537/boards/generic_board.c
index 7d250828dad..01b63e2ec18 100644
--- a/arch/blackfin/mach-bf537/boards/generic_board.c
+++ b/arch/blackfin/mach-bf537/boards/generic_board.c
@@ -166,10 +166,15 @@ static struct platform_device smc91x_device = {
static struct resource dm9000_resources[] = {
[0] = {
.start = 0x203FB800,
- .end = 0x203FB800 + 8,
+ .end = 0x203FB800 + 1,
.flags = IORESOURCE_MEM,
},
[1] = {
+ .start = 0x203FB800 + 4,
+ .end = 0x203FB800 + 5,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
.start = IRQ_PF9,
.end = IRQ_PF9,
.flags = (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE),
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index 934db350e33..6011d6fabef 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -1213,7 +1213,6 @@ static int cp_close (struct net_device *dev)
spin_unlock_irqrestore(&cp->lock, flags);
- synchronize_irq(dev->irq);
free_irq(dev->irq, dev);
cp_free_rings(cp);
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index b23a00c5b84..75317a14ad1 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -107,8 +107,8 @@
#include <linux/mii.h>
#include <linux/completion.h>
#include <linux/crc32.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
#include <asm/irq.h>
#define RTL8139_DRIVER_NAME DRV_NAME " Fast Ethernet driver " DRV_VERSION
@@ -134,7 +134,7 @@
#if RTL8139_DEBUG
/* note: prints function name for you */
-# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
+# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
#else
# define DPRINTK(fmt, args...)
#endif
@@ -145,7 +145,7 @@
# define assert(expr) \
if(unlikely(!(expr))) { \
printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \
- #expr,__FILE__,__FUNCTION__,__LINE__); \
+ #expr, __FILE__, __func__, __LINE__); \
}
#endif
@@ -219,7 +219,7 @@ enum {
#define RTL8139B_IO_SIZE 256
#define RTL8129_CAPS HAS_MII_XCVR
-#define RTL8139_CAPS HAS_CHIP_XCVR|HAS_LNK_CHNG
+#define RTL8139_CAPS (HAS_CHIP_XCVR|HAS_LNK_CHNG)
typedef enum {
RTL8139 = 0,
@@ -1889,7 +1889,7 @@ static void rtl8139_rx_err (u32 rx_status, struct net_device *dev,
}
#if RX_BUF_IDX == 3
-static __inline__ void wrap_copy(struct sk_buff *skb, const unsigned char *ring,
+static inline void wrap_copy(struct sk_buff *skb, const unsigned char *ring,
u32 offset, unsigned int size)
{
u32 left = RX_BUF_LEN - offset;
@@ -2231,7 +2231,6 @@ static int rtl8139_close (struct net_device *dev)
spin_unlock_irqrestore (&tp->lock, flags);
- synchronize_irq (dev->irq); /* racy, but that's ok here */
free_irq (dev->irq, dev);
rtl8139_tx_clear (tp);
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 287d0873c60..d85b9d06759 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -938,6 +938,23 @@ config DM9000
To compile this driver as a module, choose M here. The module
will be called dm9000.
+config DM9000_DEBUGLEVEL
+ int "DM9000 maximum debug level"
+ depends on DM9000
+ default 4
+ help
+ The maximum level of debugging code compiled into the DM9000
+ driver.
+
+config DM9000_FORCE_SIMPLE_PHY_POLL
+ bool "Force simple NSR based PHY polling"
+ depends on DM9000
+ ---help---
+ This configuration forces the DM9000 to use the NSR's LinkStatus
+ bit to determine if the link is up or down instead of the more
+ costly MII PHY reads. Note, this will not work if the chip is
+ operating with an external PHY.
+
config ENC28J60
tristate "ENC28J60 support"
depends on EXPERIMENTAL && SPI && NET_ETHERNET
@@ -955,14 +972,6 @@ config ENC28J60_WRITEVERIFY
Enable the verify after the buffer write useful for debugging purpose.
If unsure, say N.
-config DM9000_DEBUGLEVEL
- int "DM9000 maximum debug level"
- depends on DM9000
- default 4
- help
- The maximum level of debugging code compiled into the DM9000
- driver.
-
config SMC911X
tristate "SMSC LAN911[5678] support"
select CRC32
@@ -2025,9 +2034,6 @@ config E1000E
To compile this driver as a module, choose M here. The module
will be called e1000e.
-config E1000E_ENABLED
- def_bool E1000E != n
-
config IP1000
tristate "IP1000 Gigabit Ethernet support"
depends on PCI && EXPERIMENTAL
@@ -2462,7 +2468,8 @@ config EHEA
config IXGBE
tristate "Intel(R) 10GbE PCI Express adapters support"
- depends on PCI
+ depends on PCI && INET
+ select INET_LRO
---help---
This driver supports Intel(R) 10GbE PCI Express family of
adapters. For more information on how to identify your adapter, go
diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c
index ff9c013ce53..ae6ff5df779 100644
--- a/drivers/net/cxgb3/cxgb3_offload.c
+++ b/drivers/net/cxgb3/cxgb3_offload.c
@@ -1248,6 +1248,25 @@ static inline void unregister_tdev(struct t3cdev *tdev)
mutex_unlock(&cxgb3_db_lock);
}
+static inline int adap2type(struct adapter *adapter)
+{
+ int type = 0;
+
+ switch (adapter->params.rev) {
+ case T3_REV_A:
+ type = T3A;
+ break;
+ case T3_REV_B:
+ case T3_REV_B2:
+ type = T3B;
+ break;
+ case T3_REV_C:
+ type = T3C;
+ break;
+ }
+ return type;
+}
+
void __devinit cxgb3_adapter_ofld(struct adapter *adapter)
{
struct t3cdev *tdev = &adapter->tdev;
@@ -1257,7 +1276,7 @@ void __devinit cxgb3_adapter_ofld(struct adapter *adapter)
cxgb3_set_dummy_ops(tdev);
tdev->send = t3_offload_tx;
tdev->ctl = cxgb_offload_ctl;
- tdev->type = adapter->params.rev == 0 ? T3A : T3B;
+ tdev->type = adap2type(adapter);
register_tdev(tdev);
}
diff --git a/drivers/net/cxgb3/t3cdev.h b/drivers/net/cxgb3/t3cdev.h
index a18c8a14042..8556628fd5a 100644
--- a/drivers/net/cxgb3/t3cdev.h
+++ b/drivers/net/cxgb3/t3cdev.h
@@ -45,7 +45,8 @@ struct cxgb3_client;
enum t3ctype {
T3A = 0,
- T3B
+ T3B,
+ T3C,
};
struct t3cdev {
diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c
index 8277e89e552..f8037110a52 100644
--- a/drivers/net/dl2k.c
+++ b/drivers/net/dl2k.c
@@ -1753,7 +1753,7 @@ rio_close (struct net_device *dev)
/* Stop Tx and Rx logics */
writel (TxDisable | RxDisable | StatsDisable, ioaddr + MACCtrl);
- synchronize_irq (dev->irq);
+
free_irq (dev->irq, dev);
del_timer_sync (&np->timer);
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index 08a7365a7d1..952e10d686e 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -44,9 +44,8 @@
#define DM9000_PHY 0x40 /* PHY address 0x01 */
-#define CARDNAME "dm9000"
-#define PFX CARDNAME ": "
-#define DRV_VERSION "1.30"
+#define CARDNAME "dm9000"
+#define DRV_VERSION "1.31"
#ifdef CONFIG_BLACKFIN
#define readsb insb
@@ -55,9 +54,6 @@
#define writesb outsb
#define writesw outsw
#define writesl outsl
-#define DEFAULT_TRIGGER IRQF_TRIGGER_HIGH
-#else
-#define DEFAULT_TRIGGER (0)
#endif
/*
@@ -85,23 +81,36 @@ MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
* these two devices.
*/
+/* The driver supports the original DM9000E, and now the two newer
+ * devices, DM9000A and DM9000B.
+ */
+
+enum dm9000_type {
+ TYPE_DM9000E, /* original DM9000 */
+ TYPE_DM9000A,
+ TYPE_DM9000B
+};
+
/* Structure/enum declaration ------------------------------- */
typedef struct board_info {
- void __iomem *io_addr; /* Register I/O base address */
- void __iomem *io_data; /* Data I/O address */
- u16 irq; /* IRQ */
+ void __iomem *io_addr; /* Register I/O base address */
+ void __iomem *io_data; /* Data I/O address */
+ u16 irq; /* IRQ */
- u16 tx_pkt_cnt;
- u16 queue_pkt_len;
- u16 queue_start_addr;
- u16 dbug_cnt;
- u8 io_mode; /* 0:word, 2:byte */
- u8 phy_addr;
- unsigned int flags;
- unsigned int in_suspend :1;
+ u16 tx_pkt_cnt;
+ u16 queue_pkt_len;
+ u16 queue_start_addr;
+ u16 dbug_cnt;
+ u8 io_mode; /* 0:word, 2:byte */
+ u8 phy_addr;
+ u8 imr_all;
- int debug_level;
+ unsigned int flags;
+ unsigned int in_suspend :1;
+ int debug_level;
+
+ enum dm9000_type type;
void (*inblk)(void __iomem *port, void *data, int length);
void (*outblk)(void __iomem *port, void *data, int length);
@@ -120,10 +129,10 @@ typedef struct board_info {
struct delayed_work phy_poll;
struct net_device *ndev;
- spinlock_t lock;
+ spinlock_t lock;
struct mii_if_info mii;
- u32 msg_enable;
+ u32 msg_enable;
} board_info_t;
/* debug code */
@@ -140,26 +149,6 @@ static inline board_info_t *to_dm9000_board(struct net_device *dev)
return dev->priv;
}
-/* function declaration ------------------------------------- */
-static int dm9000_probe(struct platform_device *);
-static int dm9000_open(struct net_device *);
-static int dm9000_start_xmit(struct sk_buff *, struct net_device *);
-static int dm9000_stop(struct net_device *);
-static int dm9000_ioctl(struct net_device *dev, struct ifreq *req, int cmd);
-
-static void dm9000_init_dm9000(struct net_device *);
-
-static irqreturn_t dm9000_interrupt(int, void *);
-
-static int dm9000_phy_read(struct net_device *dev, int phyaddr_unsused, int reg);
-static void dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg,
- int value);
-
-static void dm9000_read_eeprom(board_info_t *, int addr, u8 *to);
-static void dm9000_write_eeprom(board_info_t *, int addr, u8 *dp);
-static void dm9000_rx(struct net_device *);
-static void dm9000_hash_table(struct net_device *);
-
/* DM9000 network board routine ---------------------------- */
static void
@@ -302,52 +291,135 @@ static void dm9000_set_io(struct board_info *db, int byte_width)
static void dm9000_schedule_poll(board_info_t *db)
{
- schedule_delayed_work(&db->phy_poll, HZ * 2);
+ if (db->type == TYPE_DM9000E)
+ schedule_delayed_work(&db->phy_poll, HZ * 2);
}
-/* Our watchdog timed out. Called by the networking layer */
-static void dm9000_timeout(struct net_device *dev)
+static int dm9000_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+{
+ board_info_t *dm = to_dm9000_board(dev);
+
+ if (!netif_running(dev))
+ return -EINVAL;
+
+ return generic_mii_ioctl(&dm->mii, if_mii(req), cmd, NULL);
+}
+
+static unsigned int
+dm9000_read_locked(board_info_t *db, int reg)
{
- board_info_t *db = (board_info_t *) dev->priv;
- u8 reg_save;
unsigned long flags;
+ unsigned int ret;
- /* Save previous register address */
- reg_save = readb(db->io_addr);
- spin_lock_irqsave(&db->lock,flags);
+ spin_lock_irqsave(&db->lock, flags);
+ ret = ior(db, reg);
+ spin_unlock_irqrestore(&db->lock, flags);
- netif_stop_queue(dev);
- dm9000_reset(db);
- dm9000_init_dm9000(dev);
- /* We can accept TX packets again */
- dev->trans_start = jiffies;
- netif_wake_queue(dev);
+ return ret;
+}
- /* Restore previous register address */
- writeb(reg_save, db->io_addr);
- spin_unlock_irqrestore(&db->lock,flags);
+static int dm9000_wait_eeprom(board_info_t *db)
+{
+ unsigned int status;
+ int timeout = 8; /* wait max 8msec */
+
+ /* The DM9000 data sheets say we should be able to
+ * poll the ERRE bit in EPCR to wait for the EEPROM
+ * operation. From testing several chips, this bit
+ * does not seem to work.
+ *
+ * We attempt to use the bit, but fall back to the
+ * timeout (which is why we do not return an error
+ * on expiry) to say that the EEPROM operation has
+ * completed.
+ */
+
+ while (1) {
+ status = dm9000_read_locked(db, DM9000_EPCR);
+
+ if ((status & EPCR_ERRE) == 0)
+ break;
+
+ msleep(1);
+
+ if (timeout-- < 0) {
+ dev_dbg(db->dev, "timeout waiting EEPROM\n");
+ break;
+ }
+ }
+
+ return 0;
}
-#ifdef CONFIG_NET_POLL_CONTROLLER
/*
- *Used by netconsole
+ * Read a word data from EEPROM
*/
-static void dm9000_poll_controller(struct net_device *dev)
+static void
+dm9000_read_eeprom(board_info_t *db, int offset, u8 *to)
{
- disable_irq(dev->irq);
- dm9000_interrupt(dev->irq,dev);
- enable_irq(dev->irq);
+ unsigned long flags;
+
+ if (db->flags & DM9000_PLATF_NO_EEPROM) {
+ to[0] = 0xff;
+ to[1] = 0xff;
+ return;
+ }
+
+ mutex_lock(&db->addr_lock);
+
+ spin_lock_irqsave(&db->lock, flags);
+
+ iow(db, DM9000_EPAR, offset);
+ iow(db, DM9000_EPCR, EPCR_ERPRR);
+
+ spin_unlock_irqrestore(&db->lock, flags);
+
+ dm9000_wait_eeprom(db);
+
+ /* delay for at-least 150uS */
+ msleep(1);
+
+ spin_lock_irqsave(&db->lock, flags);
+
+ iow(db, DM9000_EPCR, 0x0);
+
+ to[0] = ior(db, DM9000_EPDRL);
+ to[1] = ior(db, DM9000_EPDRH);
+
+ spin_unlock_irqrestore(&db->lock, flags);
+
+ mutex_unlock(&db->addr_lock);
}
-#endif
-static int dm9000_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+/*
+ * Write a word data to SROM
+ */
+static void
+dm9000_write_eeprom(board_info_t *db, int offset, u8 *data)
{
- board_info_t *dm = to_dm9000_board(dev);
+ unsigned long flags;
- if (!netif_running(dev))
- return -EINVAL;
+ if (db->flags & DM9000_PLATF_NO_EEPROM)
+ return;
- return generic_mii_ioctl(&dm->mii, if_mii(req), cmd, NULL);
+ mutex_lock(&db->addr_lock);
+
+ spin_lock_irqsave(&db->lock, flags);
+ iow(db, DM9000_EPAR, offset);
+ iow(db, DM9000_EPDRH, data[1]);
+ iow(db, DM9000_EPDRL, data[0]);
+ iow(db, DM9000_EPCR, EPCR_WEP | EPCR_ERPRW);
+ spin_unlock_irqrestore(&db->lock, flags);
+
+ dm9000_wait_eeprom(db);
+
+ mdelay(1); /* wait at least 150uS to clear */
+
+ spin_lock_irqsave(&db->lock, flags);
+ iow(db, DM9000_EPCR, 0);
+ spin_unlock_irqrestore(&db->lock, flags);
+
+ mutex_unlock(&db->addr_lock);
}
/* ethtool ops */
@@ -400,7 +472,14 @@ static int dm9000_nway_reset(struct net_device *dev)
static u32 dm9000_get_link(struct net_device *dev)
{
board_info_t *dm = to_dm9000_board(dev);
- return mii_link_ok(&dm->mii);
+ u32 ret;
+
+ if (dm->flags & DM9000_PLATF_EXT_PHY)
+ ret = mii_link_ok(&dm->mii);
+ else
+ ret = dm9000_read_locked(dm, DM9000_NSR) & NSR_LINKST ? 1 : 0;
+
+ return ret;
}
#define DM_EEPROM_MAGIC (0x444D394B)
@@ -472,15 +551,48 @@ static const struct ethtool_ops dm9000_ethtool_ops = {
.set_eeprom = dm9000_set_eeprom,
};
+static void dm9000_show_carrier(board_info_t *db,
+ unsigned carrier, unsigned nsr)
+{
+ struct net_device *ndev = db->ndev;
+ unsigned ncr = dm9000_read_locked(db, DM9000_NCR);
+
+ if (carrier)
+ dev_info(db->dev, "%s: link up, %dMbps, %s-duplex, no LPA\n",
+ ndev->name, (nsr & NSR_SPEED) ? 10 : 100,
+ (ncr & NCR_FDX) ? "full" : "half");
+ else
+ dev_info(db->dev, "%s: link down\n", ndev->name);
+}
+
static void
dm9000_poll_work(struct work_struct *w)
{
struct delayed_work *dw = container_of(w, struct delayed_work, work);
board_info_t *db = container_of(dw, board_info_t, phy_poll);
+ struct net_device *ndev = db->ndev;
+
+ if (db->flags & DM9000_PLATF_SIMPLE_PHY &&
+ !(db->flags & DM9000_PLATF_EXT_PHY)) {
+ unsigned nsr = dm9000_read_locked(db, DM9000_NSR);
+ unsigned old_carrier = netif_carrier_ok(ndev) ? 1 : 0;
+ unsigned new_carrier;
- mii_check_media(&db->mii, netif_msg_link(db), 0);
+ new_carrier = (nsr & NSR_LINKST) ? 1 : 0;
+
+ if (old_carrier != new_carrier) {
+ if (netif_msg_link(db))
+ dm9000_show_carrier(db, new_carrier, nsr);
+
+ if (!new_carrier)
+ netif_carrier_off(ndev);
+ else
+ netif_carrier_on(ndev);
+ }
+ } else
+ mii_check_media(&db->mii, netif_msg_link(db), 0);
- if (netif_running(db->ndev))
+ if (netif_running(ndev))
dm9000_schedule_poll(db);
}
@@ -492,12 +604,6 @@ dm9000_poll_work(struct work_struct *w)
static void
dm9000_release_board(struct platform_device *pdev, struct board_info *db)
{