diff options
author | David S. Miller <davem@davemloft.net> | 2008-06-28 21:28:46 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-06-28 21:28:46 -0700 |
commit | 332e4af80d1214fbf0e263e1408fc7c5b64ecdd6 (patch) | |
tree | 7c8f8ada7ab8fc9cb2497d95e52dce4d2c4493a3 | |
parent | 1b63ba8a86c85524a8d7e5953b314ce71ebcb9c9 (diff) | |
parent | be0976be9148f31ee0d1997354c3e30ff8d07587 (diff) |
Merge branch 'davem-next' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6
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) { |