Commit c48ce926 authored by David S. Miller's avatar David S. Miller

[SPARC]: Update ethtool support in Sun net drivers.

parent 9696b971
/* $Id: sunbmac.c,v 1.30 2002/01/15 06:48:55 davem Exp $ /* $Id: sunbmac.c,v 1.30 2002/01/15 06:48:55 davem Exp $
* sunbmac.c: Driver for Sparc BigMAC 100baseT ethernet adapters. * sunbmac.c: Driver for Sparc BigMAC 100baseT ethernet adapters.
* *
* Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com) * Copyright (C) 1997, 1998, 1999, 2003 David S. Miller (davem@redhat.com)
*/ */
#include <linux/module.h> #include <linux/module.h>
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/crc32.h> #include <linux/crc32.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/ethtool.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
...@@ -37,7 +38,7 @@ ...@@ -37,7 +38,7 @@
#include "sunbmac.h" #include "sunbmac.h"
static char version[] __initdata = static char version[] __initdata =
"sunbmac.c:v1.9 11/Sep/99 David S. Miller (davem@redhat.com)\n"; "sunbmac.c:v2.0 24/Nov/03 David S. Miller (davem@redhat.com)\n";
#undef DEBUG_PROBE #undef DEBUG_PROBE
#undef DEBUG_TX #undef DEBUG_TX
...@@ -1035,6 +1036,33 @@ static void bigmac_set_multicast(struct net_device *dev) ...@@ -1035,6 +1036,33 @@ static void bigmac_set_multicast(struct net_device *dev)
sbus_writel(tmp, bregs + BMAC_RXCFG); sbus_writel(tmp, bregs + BMAC_RXCFG);
} }
/* Ethtool support... */
static void bigmac_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
struct bigmac *bp = dev->priv;
strcpy(info->driver, "sunbmac");
strcpy(info->version, "2.0");
sprintf(info->bus_info, "SBUS:%d",
bp->qec_sdev->slot);
}
static u32 bigmac_get_link(struct net_device *dev)
{
struct bigmac *bp = dev->priv;
spin_lock_irq(&bp->lock);
bp->sw_bmsr = bigmac_tcvr_read(bp, bp->tregs, BIGMAC_BMSR);
spin_unlock_irq(&bp->lock);
return (bp->sw_bmsr & BMSR_LSTATUS);
}
static struct ethtool_ops bigmac_ethtool_ops = {
.get_drvinfo = bigmac_get_drvinfo,
.get_link = bigmac_get_link,
};
static int __init bigmac_ether_init(struct sbus_dev *qec_sdev) static int __init bigmac_ether_init(struct sbus_dev *qec_sdev)
{ {
struct net_device *dev; struct net_device *dev;
...@@ -1169,6 +1197,7 @@ static int __init bigmac_ether_init(struct sbus_dev *qec_sdev) ...@@ -1169,6 +1197,7 @@ static int __init bigmac_ether_init(struct sbus_dev *qec_sdev)
dev->open = &bigmac_open; dev->open = &bigmac_open;
dev->stop = &bigmac_close; dev->stop = &bigmac_close;
dev->hard_start_xmit = &bigmac_start_xmit; dev->hard_start_xmit = &bigmac_start_xmit;
dev->ethtool_ops = &bigmac_ethtool_ops;
/* Set links to BigMAC statistic and multi-cast loading code. */ /* Set links to BigMAC statistic and multi-cast loading code. */
dev->get_stats = &bigmac_get_stats; dev->get_stats = &bigmac_get_stats;
......
/* $Id: sungem.c,v 1.44.2.22 2002/03/13 01:18:12 davem Exp $ /* $Id: sungem.c,v 1.44.2.22 2002/03/13 01:18:12 davem Exp $
* sungem.c: Sun GEM ethernet driver. * sungem.c: Sun GEM ethernet driver.
* *
* Copyright (C) 2000, 2001, 2002 David S. Miller (davem@redhat.com) * Copyright (C) 2000, 2001, 2002, 2003 David S. Miller (davem@redhat.com)
* *
* Support for Apple GMAC and assorted PHYs by * Support for Apple GMAC and assorted PHYs by
* Benjamin Herrenscmidt (benh@kernel.crashing.org) * Benjamin Herrenscmidt (benh@kernel.crashing.org)
...@@ -70,8 +70,8 @@ ...@@ -70,8 +70,8 @@
SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full) SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full)
#define DRV_NAME "sungem" #define DRV_NAME "sungem"
#define DRV_VERSION "0.97" #define DRV_VERSION "0.98"
#define DRV_RELDATE "3/20/02" #define DRV_RELDATE "8/24/03"
#define DRV_AUTHOR "David S. Miller (davem@redhat.com)" #define DRV_AUTHOR "David S. Miller (davem@redhat.com)"
static char version[] __devinitdata = static char version[] __devinitdata =
...@@ -2317,95 +2317,94 @@ static void gem_set_multicast(struct net_device *dev) ...@@ -2317,95 +2317,94 @@ static void gem_set_multicast(struct net_device *dev)
spin_unlock_irq(&gp->lock); spin_unlock_irq(&gp->lock);
} }
/* Eventually add support for changing the advertisement static void gem_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
* on autoneg.
*/
static int gem_ethtool_ioctl(struct net_device *dev, void *ep_user)
{ {
struct gem *gp = dev->priv; struct gem *gp = dev->priv;
struct ethtool_cmd ecmd;
if (copy_from_user(&ecmd, ep_user, sizeof(ecmd)))
return -EFAULT;
switch(ecmd.cmd) {
case ETHTOOL_GDRVINFO: {
struct ethtool_drvinfo info = { .cmd = ETHTOOL_GDRVINFO };
strncpy(info.driver, DRV_NAME, ETHTOOL_BUSINFO_LEN);
strncpy(info.version, DRV_VERSION, ETHTOOL_BUSINFO_LEN);
info.fw_version[0] = '\0';
strncpy(info.bus_info, pci_name(gp->pdev), ETHTOOL_BUSINFO_LEN);
info.regdump_len = 0; /*SUNGEM_NREGS;*/
if (copy_to_user(ep_user, &info, sizeof(info))) strcpy(info->driver, DRV_NAME);
return -EFAULT; strcpy(info->version, DRV_VERSION);
strcpy(info->bus_info, pci_name(gp->pdev));
}
return 0; static int gem_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
} {
struct gem *gp = dev->priv;
case ETHTOOL_GSET:
if (gp->phy_type == phy_mii_mdio0 || if (gp->phy_type == phy_mii_mdio0 ||
gp->phy_type == phy_mii_mdio1) { gp->phy_type == phy_mii_mdio1) {
if (gp->phy_mii.def) if (gp->phy_mii.def)
ecmd.supported = gp->phy_mii.def->features; cmd->supported = gp->phy_mii.def->features;
else else
ecmd.supported = SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full; cmd->supported = (SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full);
/* XXX hardcoded stuff for now */ /* XXX hardcoded stuff for now */
ecmd.port = PORT_MII; cmd->port = PORT_MII;
ecmd.transceiver = XCVR_EXTERNAL; cmd->transceiver = XCVR_EXTERNAL;
ecmd.phy_address = 0; /* XXX fixed PHYAD */ cmd->phy_address = 0; /* XXX fixed PHYAD */
/* Return current PHY settings */ /* Return current PHY settings */
spin_lock_irq(&gp->lock); spin_lock_irq(&gp->lock);
ecmd.autoneg = gp->want_autoneg; cmd->autoneg = gp->want_autoneg;
ecmd.speed = gp->phy_mii.speed; cmd->speed = gp->phy_mii.speed;
ecmd.duplex = gp->phy_mii.duplex; cmd->duplex = gp->phy_mii.duplex;
ecmd.advertising = gp->phy_mii.advertising; cmd->advertising = gp->phy_mii.advertising;
/* If we started with a forced mode, we don't have a default /* If we started with a forced mode, we don't have a default
* advertise set, we need to return something sensible so * advertise set, we need to return something sensible so
* userland can re-enable autoneg properly */ * userland can re-enable autoneg properly.
if (ecmd.advertising == 0) */
ecmd.advertising = ecmd.supported; if (cmd->advertising == 0)
cmd->advertising = cmd->supported;
spin_unlock_irq(&gp->lock); spin_unlock_irq(&gp->lock);
} else { // XXX PCS ? } else { // XXX PCS ?
ecmd.supported = cmd->supported =
(SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
SUPPORTED_Autoneg); SUPPORTED_Autoneg);
ecmd.advertising = ecmd.supported; cmd->advertising = cmd->supported;
cmd->speed = 0;
cmd->duplex = cmd->port = cmd->phy_address =
cmd->transceiver = cmd->autoneg = 0;
} }
if (copy_to_user(ep_user, &ecmd, sizeof(ecmd))) cmd->maxtxpkt = cmd->maxrxpkt = 0;
return -EFAULT;
return 0; return 0;
}
static int gem_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct gem *gp = dev->priv;
case ETHTOOL_SSET:
/* Verify the settings we care about. */ /* Verify the settings we care about. */
if (ecmd.autoneg != AUTONEG_ENABLE && if (cmd->autoneg != AUTONEG_ENABLE &&
ecmd.autoneg != AUTONEG_DISABLE) cmd->autoneg != AUTONEG_DISABLE)
return -EINVAL; return -EINVAL;
if (ecmd.autoneg == AUTONEG_ENABLE && if (cmd->autoneg == AUTONEG_ENABLE &&
ecmd.advertising == 0) cmd->advertising == 0)
return -EINVAL; return -EINVAL;
if (ecmd.autoneg == AUTONEG_DISABLE && if (cmd->autoneg == AUTONEG_DISABLE &&
((ecmd.speed != SPEED_1000 && ((cmd->speed != SPEED_1000 &&
ecmd.speed != SPEED_100 && cmd->speed != SPEED_100 &&
ecmd.speed != SPEED_10) || cmd->speed != SPEED_10) ||
(ecmd.duplex != DUPLEX_HALF && (cmd->duplex != DUPLEX_HALF &&
ecmd.duplex != DUPLEX_FULL))) cmd->duplex != DUPLEX_FULL)))
return -EINVAL; return -EINVAL;
/* Apply settings and restart link process. */ /* Apply settings and restart link process. */
spin_lock_irq(&gp->lock); spin_lock_irq(&gp->lock);
gem_begin_auto_negotiation(gp, &ecmd); gem_begin_auto_negotiation(gp, cmd);
spin_unlock_irq(&gp->lock); spin_unlock_irq(&gp->lock);
return 0; return 0;
}
static int gem_nway_reset(struct net_device *dev)
{
struct gem *gp = dev->priv;
case ETHTOOL_NWAY_RST:
if (!gp->want_autoneg) if (!gp->want_autoneg)
return -EINVAL; return -EINVAL;
...@@ -2415,80 +2414,38 @@ static int gem_ethtool_ioctl(struct net_device *dev, void *ep_user) ...@@ -2415,80 +2414,38 @@ static int gem_ethtool_ioctl(struct net_device *dev, void *ep_user)
spin_unlock_irq(&gp->lock); spin_unlock_irq(&gp->lock);
return 0; return 0;
}
case ETHTOOL_GWOL: static u32 gem_get_link(struct net_device *dev)
case ETHTOOL_SWOL: {
break; /* todo */ struct gem *gp = dev->priv;
/* get link status */
case ETHTOOL_GLINK: {
struct ethtool_value edata = { .cmd = ETHTOOL_GLINK };
edata.data = (gp->lstate == link_up);
if (copy_to_user(ep_user, &edata, sizeof(edata)))
return -EFAULT;
return 0;
}
/* get message-level */
case ETHTOOL_GMSGLVL: {
struct ethtool_value edata = { .cmd = ETHTOOL_GMSGLVL };
edata.data = gp->msg_enable;
if (copy_to_user(ep_user, &edata, sizeof(edata)))
return -EFAULT;
return 0;
}
/* set message-level */
case ETHTOOL_SMSGLVL: {
struct ethtool_value edata;
if (copy_from_user(&edata, ep_user, sizeof(edata)))
return -EFAULT;
gp->msg_enable = edata.data;
return 0;
}
#if 0
case ETHTOOL_GREGS: {
struct ethtool_regs regs;
u32 *regbuf;
int r = 0;
if (copy_from_user(&regs, useraddr, sizeof(regs)))
return -EFAULT;
if (regs.len > SUNGEM_NREGS) {
regs.len = SUNGEM_NREGS;
}
regs.version = 0;
if (copy_to_user(useraddr, &regs, sizeof(regs)))
return -EFAULT;
if (!gp->hw_running)
return -ENODEV;
useraddr += offsetof(struct ethtool_regs, data);
/* Use kmalloc to avoid bloating the stack */ return (gp->lstate == link_up);
regbuf = kmalloc(4 * SUNGEM_NREGS, GFP_KERNEL); }
if (!regbuf)
return -ENOMEM;
spin_lock_irq(&np->lock);
gem_get_regs(gp, regbuf);
spin_unlock_irq(&np->lock);
if (copy_to_user(useraddr, regbuf, regs.len*sizeof(u32))) static u32 gem_get_msglevel(struct net_device *dev)
r = -EFAULT; {
kfree(regbuf); struct gem *gp = dev->priv;
return r; return gp->msg_enable;
} }
#endif
};
return -EOPNOTSUPP; static void gem_set_msglevel(struct net_device *dev, u32 value)
{
struct gem *gp = dev->priv;
gp->msg_enable = value;
} }
static struct ethtool_ops gem_ethtool_ops = {
.get_drvinfo = gem_get_drvinfo,
.get_link = ethtool_op_get_link,
.get_settings = gem_get_settings,
.set_settings = gem_set_settings,
.nway_reset = gem_nway_reset,
.get_link = gem_get_link,
.get_msglevel = gem_get_msglevel,
.set_msglevel = gem_set_msglevel,
};
static int gem_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) static int gem_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{ {
struct gem *gp = dev->priv; struct gem *gp = dev->priv;
...@@ -2501,10 +2458,6 @@ static int gem_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ...@@ -2501,10 +2458,6 @@ static int gem_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
down(&gp->pm_sem); down(&gp->pm_sem);
switch (cmd) { switch (cmd) {
case SIOCETHTOOL:
rc = gem_ethtool_ioctl(dev, ifr->ifr_data);
break;
case SIOCGMIIPHY: /* Get address of MII PHY in use. */ case SIOCGMIIPHY: /* Get address of MII PHY in use. */
data->phy_id = gp->mii_phy_addr; data->phy_id = gp->mii_phy_addr;
/* Fallthrough... */ /* Fallthrough... */
...@@ -2812,6 +2765,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev, ...@@ -2812,6 +2765,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
dev->get_stats = gem_get_stats; dev->get_stats = gem_get_stats;
dev->set_multicast_list = gem_set_multicast; dev->set_multicast_list = gem_set_multicast;
dev->do_ioctl = gem_ioctl; dev->do_ioctl = gem_ioctl;
dev->ethtool_ops = &gem_ethtool_ops;
dev->tx_timeout = gem_tx_timeout; dev->tx_timeout = gem_tx_timeout;
dev->watchdog_timeo = 5 * HZ; dev->watchdog_timeo = 5 * HZ;
dev->change_mtu = gem_change_mtu; dev->change_mtu = gem_change_mtu;
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* auto carrier detecting ethernet driver. Also known as the * auto carrier detecting ethernet driver. Also known as the
* "Happy Meal Ethernet" found on SunSwift SBUS cards. * "Happy Meal Ethernet" found on SunSwift SBUS cards.
* *
* Copyright (C) 1996, 1998, 1999, 2002 David S. Miller (davem@redhat.com) * Copyright (C) 1996, 1998, 1999, 2002, 2003 David S. Miller (davem@redhat.com)
* *
* Changes : * Changes :
* 2000/11/11 Willy Tarreau <willy AT meta-x.org> * 2000/11/11 Willy Tarreau <willy AT meta-x.org>
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
*/ */
static char version[] = static char version[] =
"sunhme.c:v2.01 26/Mar/2002 David S. Miller (davem@redhat.com)\n"; "sunhme.c:v2.02 24/Aug/2003 David S. Miller (davem@redhat.com)\n";
#include <linux/module.h> #include <linux/module.h>
#include <linux/config.h> #include <linux/config.h>
...@@ -2426,28 +2426,19 @@ static void happy_meal_set_multicast(struct net_device *dev) ...@@ -2426,28 +2426,19 @@ static void happy_meal_set_multicast(struct net_device *dev)
} }
/* Ethtool support... */ /* Ethtool support... */
static int happy_meal_ioctl(struct net_device *dev, static int hme_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
struct ifreq *rq, int cmd)
{ {
struct happy_meal *hp = dev->priv; struct happy_meal *hp = dev->priv;
struct ethtool_cmd *ep_user = (struct ethtool_cmd *) rq->ifr_data;
struct ethtool_cmd ecmd;
if (cmd != SIOCETHTOOL) cmd->supported =
return -EOPNOTSUPP;
if (copy_from_user(&ecmd, ep_user, sizeof(ecmd)))
return -EFAULT;
if (ecmd.cmd == ETHTOOL_GSET) {
ecmd.supported =
(SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII); SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII);
/* XXX hardcoded stuff for now */ /* XXX hardcoded stuff for now */
ecmd.port = PORT_TP; /* XXX no MII support */ cmd->port = PORT_TP; /* XXX no MII support */
ecmd.transceiver = XCVR_INTERNAL; /* XXX no external xcvr support */ cmd->transceiver = XCVR_INTERNAL; /* XXX no external xcvr support */
ecmd.phy_address = 0; /* XXX fixed PHYAD */ cmd->phy_address = 0; /* XXX fixed PHYAD */
/* Record PHY settings. */ /* Record PHY settings. */
spin_lock_irq(&hp->happy_lock); spin_lock_irq(&hp->happy_lock);
...@@ -2456,55 +2447,88 @@ static int happy_meal_ioctl(struct net_device *dev, ...@@ -2456,55 +2447,88 @@ static int happy_meal_ioctl(struct net_device *dev,
spin_unlock_irq(&hp->happy_lock); spin_unlock_irq(&hp->happy_lock);
if (hp->sw_bmcr & BMCR_ANENABLE) { if (hp->sw_bmcr & BMCR_ANENABLE) {
ecmd.autoneg = AUTONEG_ENABLE; cmd->autoneg = AUTONEG_ENABLE;
ecmd.speed = cmd->speed =
(hp->sw_lpa & (LPA_100HALF | LPA_100FULL)) ? (hp->sw_lpa & (LPA_100HALF | LPA_100FULL)) ?
SPEED_100 : SPEED_10; SPEED_100 : SPEED_10;
if (ecmd.speed == SPEED_100) if (cmd->speed == SPEED_100)
ecmd.duplex = cmd->duplex =
(hp->sw_lpa & (LPA_100FULL)) ? (hp->sw_lpa & (LPA_100FULL)) ?
DUPLEX_FULL : DUPLEX_HALF; DUPLEX_FULL : DUPLEX_HALF;
else else
ecmd.duplex = cmd->duplex =
(hp->sw_lpa & (LPA_10FULL)) ? (hp->sw_lpa & (LPA_10FULL)) ?
DUPLEX_FULL : DUPLEX_HALF; DUPLEX_FULL : DUPLEX_HALF;
} else { } else {
ecmd.autoneg = AUTONEG_DISABLE; cmd->autoneg = AUTONEG_DISABLE;
ecmd.speed = cmd->speed =
(hp->sw_bmcr & BMCR_SPEED100) ? (hp->sw_bmcr & BMCR_SPEED100) ?
SPEED_100 : SPEED_10; SPEED_100 : SPEED_10;
ecmd.duplex = cmd->duplex =
(hp->sw_bmcr & BMCR_FULLDPLX) ? (hp->sw_bmcr & BMCR_FULLDPLX) ?
DUPLEX_FULL : DUPLEX_HALF; DUPLEX_FULL : DUPLEX_HALF;
} }
if (copy_to_user(ep_user, &ecmd, sizeof(ecmd)))
return -EFAULT;
return 0; return 0;
} else if (ecmd.cmd == ETHTOOL_SSET) { }
static int hme_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct happy_meal *hp = dev->priv;
/* Verify the settings we care about. */ /* Verify the settings we care about. */
if (ecmd.autoneg != AUTONEG_ENABLE && if (cmd->autoneg != AUTONEG_ENABLE &&
ecmd.autoneg != AUTONEG_DISABLE) cmd->autoneg != AUTONEG_DISABLE)
return -EINVAL; return -EINVAL;
if (ecmd.autoneg == AUTONEG_DISABLE && if (cmd->autoneg == AUTONEG_DISABLE &&
((ecmd.speed != SPEED_100 && ((cmd->speed != SPEED_100 &&
ecmd.speed != SPEED_10) || cmd->speed != SPEED_10) ||
(ecmd.duplex != DUPLEX_HALF && (cmd->duplex != DUPLEX_HALF &&
ecmd.duplex != DUPLEX_FULL))) cmd->duplex != DUPLEX_FULL)))
return -EINVAL; return -EINVAL;
/* Ok, do it to it. */ /* Ok, do it to it. */
spin_lock_irq(&hp->happy_lock); spin_lock_irq(&hp->happy_lock);
del_timer(&hp->happy_timer); del_timer(&hp->happy_timer);
happy_meal_begin_auto_negotiation(hp, happy_meal_begin_auto_negotiation(hp, hp->tcvregs, cmd);
hp->tcvregs,
&ecmd);
spin_unlock_irq(&hp->happy_lock); spin_unlock_irq(&hp->happy_lock);
return 0; return 0;
} else
return -EOPNOTSUPP;
} }
static void hme_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
struct happy_meal *hp = dev->priv;
strcpy(info->driver, "sunhme");
strcpy(info->version, "2.02");
if (hp->happy_flags & HFLAG_PCI) {
struct pci_dev *pdev = hp->happy_dev;
strcpy(info->bus_info, pci_name(pdev));
} else {
struct sbus_dev *sdev = hp->happy_dev;
sprintf(info->bus_info, "SBUS:%d",
sdev->slot);
}
}
static u32 hme_get_link(struct net_device *dev)
{
struct happy_meal *hp = dev->priv;
spin_lock_irq(&hp->happy_lock);
hp->sw_bmcr = happy_meal_tcvr_read(hp, hp->tcvregs, MII_BMCR);
spin_unlock_irq(&hp->happy_lock);
return (hp->sw_bmsr & BMSR_LSTATUS);
}
static struct ethtool_ops hme_ethtool_ops = {
.get_settings = hme_get_settings,
.set_settings = hme_set_settings,
.get_drvinfo = hme_get_drvinfo,
.get_link = hme_get_link,
};
static int hme_version_printed; static int hme_version_printed;
#ifdef CONFIG_SBUS #ifdef CONFIG_SBUS
...@@ -2797,7 +2821,7 @@ static int __init happy_meal_sbus_init(struct sbus_dev *sdev, int is_qfe) ...@@ -2797,7 +2821,7 @@ static int __init happy_meal_sbus_init(struct sbus_dev *sdev, int is_qfe)
dev->set_multicast_list = &happy_meal_set_multicast; dev->set_multicast_list = &happy_meal_set_multicast;
dev->tx_timeout = &happy_meal_tx_timeout; dev->tx_timeout = &happy_meal_tx_timeout;
dev->watchdog_timeo = 5*HZ; dev->watchdog_timeo = 5*HZ;
dev->do_ioctl = &happy_meal_ioctl; dev->ethtool_ops = &hme_ethtool_ops;
/* Happy Meal can do it all... except VLAN. */ /* Happy Meal can do it all... except VLAN. */
dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_VLAN_CHALLENGED; dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_VLAN_CHALLENGED;
...@@ -3141,7 +3165,7 @@ static int __init happy_meal_pci_init(struct pci_dev *pdev) ...@@ -3141,7 +3165,7 @@ static int __init happy_meal_pci_init(struct pci_dev *pdev)
dev->set_multicast_list = &happy_meal_set_multicast; dev->set_multicast_list = &happy_meal_set_multicast;
dev->tx_timeout = &happy_meal_tx_timeout; dev->tx_timeout = &happy_meal_tx_timeout;
dev->watchdog_timeo = 5*HZ; dev->watchdog_timeo = 5*HZ;
dev->do_ioctl = &happy_meal_ioctl; dev->ethtool_ops = &hme_ethtool_ops;
dev->irq = pdev->irq; dev->irq = pdev->irq;
dev->dma = 0; dev->dma = 0;
......
...@@ -70,7 +70,7 @@ ...@@ -70,7 +70,7 @@
#undef DEBUG_DRIVER #undef DEBUG_DRIVER
static char version[] = static char version[] =
"sunlance.c:v2.01 08/Nov/01 Miguel de Icaza (miguel@nuclecu.unam.mx)\n"; "sunlance.c:v2.02 24/Aug/03 Miguel de Icaza (miguel@nuclecu.unam.mx)\n";
static char lancestr[] = "LANCE"; static char lancestr[] = "LANCE";
...@@ -93,6 +93,7 @@ static char lancestr[] = "LANCE"; ...@@ -93,6 +93,7 @@ static char lancestr[] = "LANCE";
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/ethtool.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/bitops.h> #include <asm/bitops.h>
...@@ -1287,6 +1288,30 @@ static void lance_free_hwresources(struct lance_private *lp) ...@@ -1287,6 +1288,30 @@ static void lance_free_hwresources(struct lance_private *lp)
} }
} }
/* Ethtool support... */
static void sparc_lance_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
struct lance_private *lp = dev->priv;
strcpy(info->driver, "sunlance");
strcpy(info->version, "2.02");
sprintf(info->bus_info, "SBUS:%d",
lp->sdev->slot);
}
static u32 sparc_lance_get_link(struct net_device *dev)
{
/* We really do not keep track of this, but this
* is better than not reporting anything at all.
*/
return 1;
}
static struct ethtool_ops sparc_lance_ethtool_ops = {
.get_drvinfo = sparc_lance_get_drvinfo,
.get_link = sparc_lance_get_link,
};
static int __init sparc_lance_init(struct net_device *dev, static int __init sparc_lance_init(struct net_device *dev,
struct sbus_dev *sdev, struct sbus_dev *sdev,
struct sbus_dma *ledma, struct sbus_dma *ledma,
...@@ -1456,6 +1481,7 @@ static int __init sparc_lance_init(struct net_device *dev, ...@@ -1456,6 +1481,7 @@ static int __init sparc_lance_init(struct net_device *dev,
dev->watchdog_timeo = 5*HZ; dev->watchdog_timeo = 5*HZ;
dev->get_stats = &lance_get_stats; dev->get_stats = &lance_get_stats;
dev->set_multicast_list = &lance_set_multicast; dev->set_multicast_list = &lance_set_multicast;
dev->ethtool_ops = &sparc_lance_ethtool_ops;
dev->irq = sdev->irqs[0]; dev->irq = sdev->irqs[0];
......
...@@ -4,11 +4,11 @@ ...@@ -4,11 +4,11 @@
* controller out there can be most efficiently programmed * controller out there can be most efficiently programmed
* if you make it look like a LANCE. * if you make it look like a LANCE.
* *
* Copyright (C) 1996, 1999 David S. Miller (davem@redhat.com) * Copyright (C) 1996, 1999, 2003 David S. Miller (davem@redhat.com)
*/ */
static char version[] = static char version[] =
"sunqe.c:v2.9 9/11/99 David S. Miller (davem@redhat.com)\n"; "sunqe.c:v3.0 8/24/03 David S. Miller (davem@redhat.com)\n";
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -26,6 +26,7 @@ static char version[] = ...@@ -26,6 +26,7 @@ static char version[] =
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/ethtool.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/bitops.h> #include <asm/bitops.h>
...@@ -684,6 +685,35 @@ static void qe_set_multicast(struct net_device *dev) ...@@ -684,6 +685,35 @@ static void qe_set_multicast(struct net_device *dev)
netif_wake_queue(dev); netif_wake_queue(dev);
} }
/* Ethtool support... */
static void qe_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
struct sunqe *qep = dev->priv;
strcpy(info->driver, "sunqe");
strcpy(info->version, "3.0");
sprintf(info->bus_info, "SBUS:%d",
qep->qe_sdev->slot);
}
static u32 qe_get_link(struct net_device *dev)
{
struct sunqe *qep = dev->priv;
unsigned long mregs = qep->mregs;
u8 phyconfig;
spin_lock_irq(&qep->lock);
phyconfig = sbus_readb(mregs + MREGS_PHYCONFIG);
spin_unlock_irq(&qep->lock);
return (phyconfig & MREGS_PHYCONFIG_LSTAT);
}
static struct ethtool_ops qe_ethtool_ops = {
.get_drvinfo = qe_get_drvinfo,
.get_link = qe_get_link,
};
/* This is only called once at boot time for each card probed. */ /* This is only called once at boot time for each card probed. */
static inline void qec_init_once(struct sunqec *qecp, struct sbus_dev *qsdev) static inline void qec_init_once(struct sunqec *qecp, struct sbus_dev *qsdev)
{ {
...@@ -850,6 +880,7 @@ static int __init qec_ether_init(struct net_device *dev, struct sbus_dev *sdev) ...@@ -850,6 +880,7 @@ static int __init qec_ether_init(struct net_device *dev, struct sbus_dev *sdev)
qe_devs[i]->watchdog_timeo = 5*HZ; qe_devs[i]->watchdog_timeo = 5*HZ;
qe_devs[i]->irq = sdev->irqs[0]; qe_devs[i]->irq = sdev->irqs[0];
qe_devs[i]->dma = 0; qe_devs[i]->dma = 0;
qe_devs[i]->ethtool_ops = &qe_ethtool_ops;
} }
/* QEC receives interrupts from each QE, then it sends the actual /* QEC receives interrupts from each QE, then it sends the actual
......
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