Commit b6f800b1 authored by Jeff Garzik's avatar Jeff Garzik

8139too net driver updates:

* Support new clone board.
* Count rx-lost-in-ring events.
* Support ethtool-compatible bitmapped printk message enable number.
* Support MII ethtool helper interface, and associated ioctls.
* Replace some MII-related magic numbers with linux/mii.h constants.
* Add in optional (and hopefully preferred... after testing) code
for resetting RX DMA engine on error.
parent fca22a09
...@@ -96,7 +96,10 @@ AT-2500TX 10/100 PCI Fast Ethernet Network Adapter Card ...@@ -96,7 +96,10 @@ AT-2500TX 10/100 PCI Fast Ethernet Network Adapter Card
KTI KF-230TX KTI KF-230TX
KTI KF-230TX/2 KTI KF-230TX/2
Lantech FastNet TX Lantech FastNet TX
Ovislink Fast Ethernet
Planet ENW-9504 (V.4) 10/100
SMC EZNET 10/100 SMC EZNET 10/100
UNEX NexNIC ND012C
(please add your adapter model to this list) (please add your adapter model to this list)
...@@ -181,11 +184,18 @@ suggestions welcome) (WIP) ...@@ -181,11 +184,18 @@ suggestions welcome) (WIP)
Change History Change History
-------------- --------------
Version 0.9.23 - In progress
* New, compile-time conditional for testing better RX reset
* Only account specific RX errors if rx_status is !OK
Version 0.9.22 - November 8, 2001 Version 0.9.22 - November 8, 2001
* Additional retries before aborting Tx * Additional retries before aborting Tx
* Do not write other TxConfig bits when writing clear-abort bit. * Do not write other TxConfig bits when writing clear-abort bit.
* Ack TxErr intr status after each Tx abort, too. * Ack TxErr intr status after each Tx abort, too.
* Fix oops in interface restart
Version 0.9.21 - November 1, 2001 Version 0.9.21 - November 1, 2001
......
...@@ -92,7 +92,7 @@ ...@@ -92,7 +92,7 @@
*/ */
#define DRV_NAME "8139too" #define DRV_NAME "8139too"
#define DRV_VERSION "0.9.22" #define DRV_VERSION "0.9.24"
#include <linux/config.h> #include <linux/config.h>
...@@ -160,6 +160,9 @@ static int max_interrupt_work = 20; ...@@ -160,6 +160,9 @@ static int max_interrupt_work = 20;
The RTL chips use a 64 element hash table based on the Ethernet CRC. */ The RTL chips use a 64 element hash table based on the Ethernet CRC. */
static int multicast_filter_limit = 32; static int multicast_filter_limit = 32;
/* bitmapped message enable number */
static int debug = -1;
/* Size of the in-memory receive ring. */ /* Size of the in-memory receive ring. */
#define RX_BUF_LEN_IDX 2 /* 0==8K, 1==16K, 2==32K, 3==64K */ #define RX_BUF_LEN_IDX 2 /* 0==8K, 1==16K, 2==32K, 3==64K */
#define RX_BUF_LEN (8192 << RX_BUF_LEN_IDX) #define RX_BUF_LEN (8192 << RX_BUF_LEN_IDX)
...@@ -213,6 +216,7 @@ typedef enum { ...@@ -213,6 +216,7 @@ typedef enum {
ADDTRON8139, ADDTRON8139,
DFE538TX, DFE538TX,
DFE690TXD, DFE690TXD,
FE2000VX,
RTL8129, RTL8129,
} board_t; } board_t;
...@@ -230,6 +234,7 @@ static struct { ...@@ -230,6 +234,7 @@ static struct {
{ "Addtron Technolgy 8139 10/100BaseTX", RTL8139_CAPS }, { "Addtron Technolgy 8139 10/100BaseTX", RTL8139_CAPS },
{ "D-Link DFE-538TX (RealTek RTL8139)", RTL8139_CAPS }, { "D-Link DFE-538TX (RealTek RTL8139)", RTL8139_CAPS },
{ "D-Link DFE-690TXD (RealTek RTL8139)", RTL8139_CAPS }, { "D-Link DFE-690TXD (RealTek RTL8139)", RTL8139_CAPS },
{ "AboCom FE2000VX (RealTek RTL8139)", RTL8139_CAPS },
{ "RealTek RTL8129", RTL8129_CAPS }, { "RealTek RTL8129", RTL8129_CAPS },
}; };
...@@ -243,6 +248,7 @@ static struct pci_device_id rtl8139_pci_tbl[] __devinitdata = { ...@@ -243,6 +248,7 @@ static struct pci_device_id rtl8139_pci_tbl[] __devinitdata = {
{0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ADDTRON8139 }, {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ADDTRON8139 },
{0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DFE538TX }, {0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DFE538TX },
{0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DFE690TXD }, {0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DFE690TXD },
{0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, FE2000VX },
#ifdef CONFIG_8139TOO_8129 #ifdef CONFIG_8139TOO_8129
{0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 }, {0x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 },
...@@ -254,6 +260,7 @@ static struct pci_device_id rtl8139_pci_tbl[] __devinitdata = { ...@@ -254,6 +260,7 @@ static struct pci_device_id rtl8139_pci_tbl[] __devinitdata = {
*/ */
{PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 }, {PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 },
{PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, DFE538TX }, {PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, DFE538TX },
{PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, FE2000VX },
{0,} {0,}
}; };
...@@ -526,6 +533,7 @@ struct rtl_extra_stats { ...@@ -526,6 +533,7 @@ struct rtl_extra_stats {
unsigned long early_rx; unsigned long early_rx;
unsigned long tx_buf_mapped; unsigned long tx_buf_mapped;
unsigned long tx_timeouts; unsigned long tx_timeouts;
unsigned long rx_lost_in_ring;
}; };
struct rtl8139_private { struct rtl8139_private {
...@@ -544,12 +552,8 @@ struct rtl8139_private { ...@@ -544,12 +552,8 @@ struct rtl8139_private {
dma_addr_t tx_bufs_dma; dma_addr_t tx_bufs_dma;
signed char phys[4]; /* MII device addresses. */ signed char phys[4]; /* MII device addresses. */
char twistie, twist_row, twist_col; /* Twister tune state. */ char twistie, twist_row, twist_col; /* Twister tune state. */
unsigned int full_duplex:1; /* Full-duplex operation requested. */
unsigned int duplex_lock:1;
unsigned int default_port:4; /* Last dev->if_port value. */ unsigned int default_port:4; /* Last dev->if_port value. */
unsigned int media2:4; /* Secondary monitored media port. */
unsigned int medialock:1; /* Don't sense media type. */ unsigned int medialock:1; /* Don't sense media type. */
unsigned int mediasense:1; /* Media sensing in progress. */
spinlock_t lock; spinlock_t lock;
chip_t chipset; chip_t chipset;
pid_t thr_pid; pid_t thr_pid;
...@@ -558,6 +562,7 @@ struct rtl8139_private { ...@@ -558,6 +562,7 @@ struct rtl8139_private {
u32 rx_config; u32 rx_config;
struct rtl_extra_stats xstats; struct rtl_extra_stats xstats;
int time_to_die; int time_to_die;
struct mii_if_info mii;
}; };
MODULE_AUTHOR ("Jeff Garzik <jgarzik@mandrakesoft.com>"); MODULE_AUTHOR ("Jeff Garzik <jgarzik@mandrakesoft.com>");
...@@ -568,6 +573,8 @@ MODULE_PARM (multicast_filter_limit, "i"); ...@@ -568,6 +573,8 @@ MODULE_PARM (multicast_filter_limit, "i");
MODULE_PARM (max_interrupt_work, "i"); MODULE_PARM (max_interrupt_work, "i");
MODULE_PARM (media, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM (media, "1-" __MODULE_STRING(MAX_UNITS) "i");
MODULE_PARM (full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM (full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
MODULE_PARM (debug, "i");
MODULE_PARM_DESC (debug, "8139too bitmapped message enable number");
MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses"); MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses");
MODULE_PARM_DESC (max_interrupt_work, "8139too maximum events handled per interrupt"); MODULE_PARM_DESC (max_interrupt_work, "8139too maximum events handled per interrupt");
MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps"); MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps");
...@@ -948,6 +955,9 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev, ...@@ -948,6 +955,9 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
spin_lock_init (&tp->lock); spin_lock_init (&tp->lock);
init_waitqueue_head (&tp->thr_wait); init_waitqueue_head (&tp->thr_wait);
init_completion (&tp->thr_exited); init_completion (&tp->thr_exited);
tp->mii.dev = dev;
tp->mii.mdio_read = mdio_read;
tp->mii.mdio_write = mdio_write;
/* dev is fully set up and ready to use now */ /* dev is fully set up and ready to use now */
DPRINTK("about to register device named %s (%p)...\n", dev->name, dev); DPRINTK("about to register device named %s (%p)...\n", dev->name, dev);
...@@ -999,18 +1009,18 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev, ...@@ -999,18 +1009,18 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
/* The lower four bits are the media type. */ /* The lower four bits are the media type. */
option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx];
if (option > 0) { if (option > 0) {
tp->full_duplex = (option & 0x210) ? 1 : 0; tp->mii.full_duplex = (option & 0x210) ? 1 : 0;
tp->default_port = option & 0xFF; tp->default_port = option & 0xFF;
if (tp->default_port) if (tp->default_port)
tp->medialock = 1; tp->medialock = 1;
} }
if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0)
tp->full_duplex = full_duplex[board_idx]; tp->mii.full_duplex = full_duplex[board_idx];
if (tp->full_duplex) { if (tp->mii.full_duplex) {
printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name); printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name);
/* Changing the MII-advertised media because might prevent /* Changing the MII-advertised media because might prevent
re-connection. */ re-connection. */
tp->duplex_lock = 1; tp->mii.duplex_lock = 1;
} }
if (tp->default_port) { if (tp->default_port) {
printk(KERN_INFO " Forcing %dMbps %s-duplex operation.\n", printk(KERN_INFO " Forcing %dMbps %s-duplex operation.\n",
...@@ -1267,7 +1277,7 @@ static int rtl8139_open (struct net_device *dev) ...@@ -1267,7 +1277,7 @@ static int rtl8139_open (struct net_device *dev)
} }
tp->full_duplex = tp->duplex_lock; tp->mii.full_duplex = tp->mii.duplex_lock;
tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000;
tp->twistie = 1; tp->twistie = 1;
tp->time_to_die = 0; tp->time_to_die = 0;
...@@ -1279,7 +1289,7 @@ static int rtl8139_open (struct net_device *dev) ...@@ -1279,7 +1289,7 @@ static int rtl8139_open (struct net_device *dev)
" GP Pins %2.2x %s-duplex.\n", " GP Pins %2.2x %s-duplex.\n",
dev->name, pci_resource_start (tp->pci_dev, 1), dev->name, pci_resource_start (tp->pci_dev, 1),
dev->irq, RTL_R8 (MediaStatus), dev->irq, RTL_R8 (MediaStatus),
tp->full_duplex ? "full" : "half"); tp->mii.full_duplex ? "full" : "half");
tp->thr_pid = kernel_thread (rtl8139_thread, dev, CLONE_FS | CLONE_FILES); tp->thr_pid = kernel_thread (rtl8139_thread, dev, CLONE_FS | CLONE_FILES);
if (tp->thr_pid < 0) if (tp->thr_pid < 0)
...@@ -1295,18 +1305,18 @@ static void rtl_check_media (struct net_device *dev) ...@@ -1295,18 +1305,18 @@ static void rtl_check_media (struct net_device *dev)
struct rtl8139_private *tp = dev->priv; struct rtl8139_private *tp = dev->priv;
if (tp->phys[0] >= 0) { if (tp->phys[0] >= 0) {
u16 mii_reg5 = mdio_read(dev, tp->phys[0], 5); u16 mii_lpa = mdio_read(dev, tp->phys[0], MII_LPA);
if (mii_reg5 == 0xffff) if (mii_lpa == 0xffff)
; /* Not there */ ; /* Not there */
else if ((mii_reg5 & 0x0100) == 0x0100 else if ((mii_lpa & LPA_100FULL) == LPA_100FULL
|| (mii_reg5 & 0x00C0) == 0x0040) || (mii_lpa & 0x00C0) == LPA_10FULL)
tp->full_duplex = 1; tp->mii.full_duplex = 1;
printk (KERN_INFO"%s: Setting %s%s-duplex based on" printk (KERN_INFO"%s: Setting %s%s-duplex based on"
" auto-negotiated partner ability %4.4x.\n", " auto-negotiated partner ability %4.4x.\n",
dev->name, mii_reg5 == 0 ? "" : dev->name, mii_lpa == 0 ? "" :
(mii_reg5 & 0x0180) ? "100mbps " : "10mbps ", (mii_lpa & 0x0180) ? "100mbps " : "10mbps ",
tp->full_duplex ? "full" : "half", mii_reg5); tp->mii.full_duplex ? "full" : "half", mii_lpa);
} }
} }
...@@ -1494,30 +1504,30 @@ static inline void rtl8139_thread_iter (struct net_device *dev, ...@@ -1494,30 +1504,30 @@ static inline void rtl8139_thread_iter (struct net_device *dev,
struct rtl8139_private *tp, struct rtl8139_private *tp,
void *ioaddr) void *ioaddr)
{ {
int mii_reg5; int mii_lpa;
mii_reg5 = mdio_read (dev, tp->phys[0], 5); mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA);
if (!tp->duplex_lock && mii_reg5 != 0xffff) { if (!tp->mii.duplex_lock && mii_lpa != 0xffff) {
int duplex = (mii_reg5 & 0x0100) int duplex = (mii_lpa & LPA_100FULL)
|| (mii_reg5 & 0x01C0) == 0x0040; || (mii_lpa & 0x01C0) == 0x0040;
if (tp->full_duplex != duplex) { if (tp->mii.full_duplex != duplex) {
tp->full_duplex = duplex; tp->mii.full_duplex = duplex;
if (mii_reg5) { if (mii_lpa) {
printk (KERN_INFO printk (KERN_INFO
"%s: Setting %s-duplex based on MII #%d link" "%s: Setting %s-duplex based on MII #%d link"
" partner ability of %4.4x.\n", " partner ability of %4.4x.\n",
dev->name, dev->name,
tp->full_duplex ? "full" : "half", tp->mii.full_duplex ? "full" : "half",
tp->phys[0], mii_reg5); tp->phys[0], mii_lpa);
} else { } else {
printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n", printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n",
dev->name); dev->name);
} }
#if 0 #if 0
RTL_W8 (Cfg9346, Cfg9346_Unlock); RTL_W8 (Cfg9346, Cfg9346_Unlock);
RTL_W8 (Config1, tp->full_duplex ? 0x60 : 0x20); RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20);
RTL_W8 (Cfg9346, Cfg9346_Lock); RTL_W8 (Cfg9346, Cfg9346_Lock);
#endif #endif
} }
...@@ -1750,23 +1760,36 @@ static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, ...@@ -1750,23 +1760,36 @@ static void rtl8139_rx_err (u32 rx_status, struct net_device *dev,
struct rtl8139_private *tp, void *ioaddr) struct rtl8139_private *tp, void *ioaddr)
{ {
u8 tmp8; u8 tmp8;
#ifndef CONFIG_8139_NEW_RX_RESET
int tmp_work; int tmp_work;
#endif
DPRINTK ("%s: Ethernet frame had errors, status %8.8x.\n", DPRINTK ("%s: Ethernet frame had errors, status %8.8x.\n",
dev->name, rx_status); dev->name, rx_status);
if (rx_status & RxTooLong) {
DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n",
dev->name, rx_status);
/* A.C.: The chip hangs here. */
}
tp->stats.rx_errors++; tp->stats.rx_errors++;
if (rx_status & (RxBadSymbol | RxBadAlign)) if (!(rx_status & RxStatusOK)) {
tp->stats.rx_frame_errors++; if (rx_status & RxTooLong) {
if (rx_status & (RxRunt | RxTooLong)) DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n",
tp->stats.rx_length_errors++; dev->name, rx_status);
if (rx_status & RxCRCErr) /* A.C.: The chip hangs here. */
tp->stats.rx_crc_errors++; }
if (rx_status & (RxBadSymbol | RxBadAlign))
tp->stats.rx_frame_errors++;
if (rx_status & (RxRunt | RxTooLong))
tp->stats.rx_length_errors++;
if (rx_status & RxCRCErr)
tp->stats.rx_crc_errors++;
} else {
tp->xstats.rx_lost_in_ring++;
}
#ifdef CONFIG_8139_NEW_RX_RESET
tmp8 = RTL_R8 (ChipCmd);
RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb);
RTL_W8 (ChipCmd, tmp8);
RTL_W32 (RxConfig, tp->rx_config);
tp->cur_rx = 0;
#else
/* Reset the receiver, based on RealTek recommendation. (Bug?) */ /* Reset the receiver, based on RealTek recommendation. (Bug?) */
/* disable receive */ /* disable receive */
...@@ -1811,6 +1834,7 @@ static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, ...@@ -1811,6 +1834,7 @@ static void rtl8139_rx_err (u32 rx_status, struct net_device *dev,
/* A.C.: Reset the multicast list. */ /* A.C.: Reset the multicast list. */
__set_rx_mode (dev); __set_rx_mode (dev);
#endif
} }
static void rtl8139_rx_interrupt (struct net_device *dev, static void rtl8139_rx_interrupt (struct net_device *dev,
...@@ -1945,13 +1969,13 @@ static void rtl8139_weird_interrupt (struct net_device *dev, ...@@ -1945,13 +1969,13 @@ static void rtl8139_weird_interrupt (struct net_device *dev,
(tp->drv_flags & HAS_LNK_CHNG)) { (tp->drv_flags & HAS_LNK_CHNG)) {
/* Really link-change on new chips. */ /* Really link-change on new chips. */
int lpar = RTL_R16 (NWayLPAR); int lpar = RTL_R16 (NWayLPAR);
int duplex = (lpar & 0x0100) || (lpar & 0x01C0) == 0x0040 int duplex = (lpar & LPA_100FULL) || (lpar & 0x01C0) == 0x0040
|| tp->duplex_lock; || tp->mii.duplex_lock;
if (tp->full_duplex != duplex) { if (tp->mii.full_duplex != duplex) {
tp->full_duplex = duplex; tp->mii.full_duplex = duplex;
#if 0 #if 0
RTL_W8 (Cfg9346, Cfg9346_Unlock); RTL_W8 (Cfg9346, Cfg9346_Unlock);
RTL_W8 (Config1, tp->full_duplex ? 0x60 : 0x20); RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20);
RTL_W8 (Cfg9346, Cfg9346_Lock); RTL_W8 (Cfg9346, Cfg9346_Lock);
#endif #endif
} }
...@@ -2110,48 +2134,6 @@ static int rtl8139_close (struct net_device *dev) ...@@ -2110,48 +2134,6 @@ static int rtl8139_close (struct net_device *dev)
} }
/* Get the ethtool settings. Assumes that eset points to kernel
memory, *eset has been initialized as {ETHTOOL_GSET}, and other
threads or interrupts aren't messing with the 8139. */
static void netdev_get_eset (struct net_device *dev, struct ethtool_cmd *eset)
{
struct rtl8139_private *np = dev->priv;
void *ioaddr = np->mmio_addr;
u16 advert;
eset->supported = SUPPORTED_10baseT_Half
| SUPPORTED_10baseT_Full
| SUPPORTED_100baseT_Half
| SUPPORTED_100baseT_Full
| SUPPORTED_Autoneg
| SUPPORTED_TP;
eset->advertising = ADVERTISED_TP | ADVERTISED_Autoneg;
advert = mdio_read (dev, np->phys[0], 4);
if (advert & 0x0020)
eset->advertising |= ADVERTISED_10baseT_Half;
if (advert & 0x0040)
eset->advertising |= ADVERTISED_10baseT_Full;
if (advert & 0x0080)
eset->advertising |= ADVERTISED_100baseT_Half;
if (advert & 0x0100)
eset->advertising |= ADVERTISED_100baseT_Full;
eset->speed = (RTL_R8 (MediaStatus) & 0x08) ? 10 : 100;
/* (KON)FIXME: np->full_duplex is set or reset by the thread,
which means this always shows half duplex if the interface
isn't up yet, even if it has already autonegotiated. */
eset->duplex = np->full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
eset->port = PORT_TP;
/* (KON)FIXME: Is np->phys[0] correct? starfire.c uses that. */
eset->phy_address = np->phys[0];
eset->transceiver = XCVR_INTERNAL;
eset->autoneg = (mdio_read (dev, np->phys[0], 0) & 0x1000) != 0;
eset->maxtxpkt = 1;
eset->maxrxpkt = 1;
}
/* Get the ethtool Wake-on-LAN settings. Assumes that wol points to /* Get the ethtool Wake-on-LAN settings. Assumes that wol points to
kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and
other threads or interrupts aren't messing with the 8139. */ other threads or interrupts aren't messing with the 8139. */
...@@ -2226,7 +2208,6 @@ static int netdev_set_wol (struct net_device *dev, ...@@ -2226,7 +2208,6 @@ static int netdev_set_wol (struct net_device *dev,
return 0; return 0;
} }
static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr) static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
{ {
struct rtl8139_private *np = dev->priv; struct rtl8139_private *np = dev->priv;
...@@ -2235,33 +2216,71 @@ static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr) ...@@ -2235,33 +2216,71 @@ static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
/* dev_ioctl() in ../../net/core/dev.c has already checked /* dev_ioctl() in ../../net/core/dev.c has already checked
capable(CAP_NET_ADMIN), so don't bother with that here. */ capable(CAP_NET_ADMIN), so don't bother with that here. */
if (copy_from_user (&ethcmd, useraddr, sizeof (ethcmd))) if (get_user(ethcmd, (u32 *)useraddr))
return -EFAULT; return -EFAULT;
switch (ethcmd) { switch (ethcmd) {
case ETHTOOL_GSET:
{
struct ethtool_cmd eset = { ETHTOOL_GSET };
spin_lock_irq (&np->lock);
netdev_get_eset (dev, &eset);
spin_unlock_irq (&np->lock);
if (copy_to_user (useraddr, &eset, sizeof (eset)))
return -EFAULT;
return 0;
}
/* TODO: ETHTOOL_SSET */ case ETHTOOL_GDRVINFO: {
struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
strcpy (info.driver, DRV_NAME);
strcpy (info.version, DRV_VERSION);
strcpy (info.bus_info, np->pci_dev->slot_name);
if (copy_to_user (useraddr, &info, sizeof (info)))
return -EFAULT;
return 0;
}
case ETHTOOL_GDRVINFO: /* get settings */
{ case ETHTOOL_GSET: {
struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; struct ethtool_cmd ecmd = { ETHTOOL_GSET };
strcpy (info.driver, DRV_NAME); spin_lock_irq(&np->lock);
strcpy (info.version, DRV_VERSION); mii_ethtool_gset(&np->mii, &ecmd);
strcpy (info.bus_info, np->pci_dev->slot_name); spin_unlock_irq(&np->lock);
if (copy_to_user (useraddr, &info, sizeof (info))) if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
return -EFAULT; return -EFAULT;
return 0; return 0;
} }
/* set settings */
case ETHTOOL_SSET: {
int r;
struct ethtool_cmd ecmd;
if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
return -EFAULT;
spin_lock_irq(&np->lock);
r = mii_ethtool_sset(&np->mii, &ecmd);
spin_unlock_irq(&np->lock);
return r;
}
/* restart autonegotiation */
case ETHTOOL_NWAY_RST: {
return mii_nway_restart(&np->mii);
}
/* get link status */
case ETHTOOL_GLINK: {
struct ethtool_value edata = {ETHTOOL_GLINK};
edata.data = mii_link_ok(&np->mii);
if (copy_to_user(useraddr, &edata, sizeof(edata)))
return -EFAULT;
return 0;
}
/* get message-level */
case ETHTOOL_GMSGLVL: {
struct ethtool_value edata = {ETHTOOL_GMSGLVL};
edata.data = debug;
if (copy_to_user(useraddr, &edata, sizeof(edata)))
return -EFAULT;
return 0;
}
/* set message-level */
case ETHTOOL_SMSGLVL: {
struct ethtool_value edata;
if (copy_from_user(&edata, useraddr, sizeof(edata)))
return -EFAULT;
debug = edata.data;
return 0;
}
case ETHTOOL_GWOL: case ETHTOOL_GWOL:
{ {
...@@ -2338,9 +2357,9 @@ static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -2338,9 +2357,9 @@ static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
/* Check for autonegotiation on or reset. */ /* Check for autonegotiation on or reset. */
tp->medialock = (value & 0x9000) ? 0 : 1; tp->medialock = (value & 0x9000) ? 0 : 1;
if (tp->medialock) if (tp->medialock)
tp->full_duplex = (value & 0x0100) ? 1 : 0; tp->mii.full_duplex = (value & 0x0100) ? 1 : 0;
break; break;
case 4: /* tp->advertising = value; */ break; case 4: tp->mii.advertising = value; break;
} }
} }
mdio_write(dev, data->phy_id, data->reg_num, data->val_in); mdio_write(dev, data->phy_id, data->reg_num, data->val_in);
......
...@@ -179,6 +179,7 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then ...@@ -179,6 +179,7 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
dep_mbool ' Use PIO instead of MMIO' CONFIG_8139TOO_PIO $CONFIG_8139TOO dep_mbool ' Use PIO instead of MMIO' CONFIG_8139TOO_PIO $CONFIG_8139TOO
dep_mbool ' Support for automatic channel equalization (EXPERIMENTAL)' CONFIG_8139TOO_TUNE_TWISTER $CONFIG_8139TOO $CONFIG_EXPERIMENTAL dep_mbool ' Support for automatic channel equalization (EXPERIMENTAL)' CONFIG_8139TOO_TUNE_TWISTER $CONFIG_8139TOO $CONFIG_EXPERIMENTAL
dep_mbool ' Support for older RTL-8129/8130 boards' CONFIG_8139TOO_8129 $CONFIG_8139TOO dep_mbool ' Support for older RTL-8129/8130 boards' CONFIG_8139TOO_8129 $CONFIG_8139TOO
dep_mbool ' Experiment for better RX reset (EXPERIMENTAL)' CONFIG_8139_NEW_RX_RESET $CONFIG_8139TOO $CONFIG_EXPERIMENTAL
dep_tristate ' SiS 900/7016 PCI Fast Ethernet Adapter support' CONFIG_SIS900 $CONFIG_PCI dep_tristate ' SiS 900/7016 PCI Fast Ethernet Adapter support' CONFIG_SIS900 $CONFIG_PCI
dep_tristate ' SMC EtherPower II' CONFIG_EPIC100 $CONFIG_PCI dep_tristate ' SMC EtherPower II' CONFIG_EPIC100 $CONFIG_PCI
dep_tristate ' Sundance Alta support' CONFIG_SUNDANCE $CONFIG_PCI dep_tristate ' Sundance Alta support' CONFIG_SUNDANCE $CONFIG_PCI
......
...@@ -165,7 +165,7 @@ obj-$(CONFIG_3C515) += 3c515.o ...@@ -165,7 +165,7 @@ obj-$(CONFIG_3C515) += 3c515.o
obj-$(CONFIG_EEXPRESS) += eexpress.o obj-$(CONFIG_EEXPRESS) += eexpress.o
obj-$(CONFIG_EEXPRESS_PRO) += eepro.o obj-$(CONFIG_EEXPRESS_PRO) += eepro.o
obj-$(CONFIG_8139CP) += 8139cp.o mii.o obj-$(CONFIG_8139CP) += 8139cp.o mii.o
obj-$(CONFIG_8139TOO) += 8139too.o obj-$(CONFIG_8139TOO) += 8139too.o mii.o
obj-$(CONFIG_ARLAN) += arlan.o arlan-proc.o obj-$(CONFIG_ARLAN) += arlan.o arlan-proc.o
obj-$(CONFIG_ZNET) += znet.o obj-$(CONFIG_ZNET) += znet.o
obj-$(CONFIG_LAN_SAA9730) += saa9730.o obj-$(CONFIG_LAN_SAA9730) += saa9730.o
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment