X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fnet%2Fnatsemi.c;h=df0961ab99facd893d240765877fdb2a8ada78ac;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=fd44cb7229902babeeb5d5259c427c2f36652479;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index fd44cb722..df0961ab9 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -159,8 +159,8 @@ #include #include #include +#include #include /* Processor type for cache alignment. */ -#include #include #include #include @@ -251,12 +251,12 @@ MODULE_AUTHOR("Donald Becker "); MODULE_DESCRIPTION("National Semiconductor DP8381x series PCI Ethernet driver"); MODULE_LICENSE("GPL"); -MODULE_PARM(max_interrupt_work, "i"); -MODULE_PARM(mtu, "i"); -MODULE_PARM(debug, "i"); -MODULE_PARM(rx_copybreak, "i"); -MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); -MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); +module_param(max_interrupt_work, int, 0); +module_param(mtu, int, 0); +module_param(debug, int, 0); +module_param(rx_copybreak, int, 0); +module_param_array(options, int, NULL, 0); +module_param_array(full_duplex, int, NULL, 0); MODULE_PARM_DESC(max_interrupt_work, "DP8381x maximum events handled per interrupt"); MODULE_PARM_DESC(mtu, "DP8381x MTU (all boards)"); @@ -441,6 +441,7 @@ enum register_offsets { #define DSPCFG_VAL 0x5040 #define SDCFG_VAL 0x008c /* set voltage thresholds for Signal Detect */ #define DSPCFG_LOCK 0x20 /* coefficient lock bit in DSPCFG */ +#define DSPCFG_COEF 0x1000 /* see coefficient (in TSTDAT) bit in DSPCFG */ #define TSTDAT_FIXED 0xe8 /* magic number for bad coefficients */ /* misc PCI space registers */ @@ -768,6 +769,7 @@ static void enable_wol_mode(struct net_device *dev, int enable_intr); static int netdev_close(struct net_device *dev); static int netdev_get_regs(struct net_device *dev, u8 *buf); static int netdev_get_eeprom(struct net_device *dev, u8 *buf); +static struct ethtool_ops ethtool_ops; static inline void __iomem *ns_ioaddr(struct net_device *dev) { @@ -933,6 +935,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev, #ifdef CONFIG_NET_POLL_CONTROLLER dev->poll_controller = &natsemi_poll_controller; #endif + SET_ETHTOOL_OPS(dev, ðtool_ops); if (mtu) dev->mtu = mtu; @@ -1241,7 +1244,8 @@ static void init_phy_fixup(struct net_device *dev) writew(1, ioaddr + PGSEL); writew(PMDCSR_VAL, ioaddr + PMDCSR); writew(TSTDAT_VAL, ioaddr + TSTDAT); - np->dspcfg = DSPCFG_VAL; + np->dspcfg = (np->srr <= SRR_DP83815_C)? + DSPCFG_VAL : (DSPCFG_COEF | readw(ioaddr + DSPCFG)); writew(np->dspcfg, ioaddr + DSPCFG); writew(SDCFG_VAL, ioaddr + SDCFG); writew(0, ioaddr + PGSEL); @@ -2477,177 +2481,136 @@ static void set_rx_mode(struct net_device *dev) spin_unlock_irq(&np->lock); } -static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr) +static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { struct netdev_private *np = netdev_priv(dev); - u32 cmd; - - if (get_user(cmd, (u32 __user *)useraddr)) - return -EFAULT; - - switch (cmd) { - /* get driver info */ - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = {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(np->pci_dev), - ETHTOOL_BUSINFO_LEN); - info.eedump_len = NATSEMI_EEPROM_SIZE; - info.regdump_len = NATSEMI_REGS_SIZE; - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; - } - /* get settings */ - case ETHTOOL_GSET: { - struct ethtool_cmd ecmd = { ETHTOOL_GSET }; - spin_lock_irq(&np->lock); - netdev_get_ecmd(dev, &ecmd); - spin_unlock_irq(&np->lock); - if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; - } - /* set settings */ - case ETHTOOL_SSET: { - struct ethtool_cmd ecmd; - int r; - if (copy_from_user(&ecmd, useraddr, sizeof(ecmd))) - return -EFAULT; - spin_lock_irq(&np->lock); - r = netdev_set_ecmd(dev, &ecmd); - spin_unlock_irq(&np->lock); - return r; - } - /* get wake-on-lan */ - case ETHTOOL_GWOL: { - struct ethtool_wolinfo wol = {ETHTOOL_GWOL}; - spin_lock_irq(&np->lock); - netdev_get_wol(dev, &wol.supported, &wol.wolopts); - netdev_get_sopass(dev, wol.sopass); - spin_unlock_irq(&np->lock); - if (copy_to_user(useraddr, &wol, sizeof(wol))) - return -EFAULT; - return 0; - } - /* set wake-on-lan */ - case ETHTOOL_SWOL: { - struct ethtool_wolinfo wol; - int r; - if (copy_from_user(&wol, useraddr, sizeof(wol))) - return -EFAULT; - spin_lock_irq(&np->lock); - netdev_set_wol(dev, wol.wolopts); - r = netdev_set_sopass(dev, wol.sopass); - spin_unlock_irq(&np->lock); - return r; - } - /* get registers */ - case ETHTOOL_GREGS: { - struct ethtool_regs regs; - u8 regbuf[NATSEMI_REGS_SIZE]; - int r; - - if (copy_from_user(®s, useraddr, sizeof(regs))) - return -EFAULT; + strncpy(info->driver, DRV_NAME, ETHTOOL_BUSINFO_LEN); + strncpy(info->version, DRV_VERSION, ETHTOOL_BUSINFO_LEN); + strncpy(info->bus_info, pci_name(np->pci_dev), ETHTOOL_BUSINFO_LEN); +} - if (regs.len > NATSEMI_REGS_SIZE) { - regs.len = NATSEMI_REGS_SIZE; - } - regs.version = NATSEMI_REGS_VER; - if (copy_to_user(useraddr, ®s, sizeof(regs))) - return -EFAULT; +static int get_regs_len(struct net_device *dev) +{ + return NATSEMI_REGS_SIZE; +} - useraddr += offsetof(struct ethtool_regs, data); +static int get_eeprom_len(struct net_device *dev) +{ + return NATSEMI_EEPROM_SIZE; +} - spin_lock_irq(&np->lock); - r = netdev_get_regs(dev, regbuf); - spin_unlock_irq(&np->lock); +static int get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct netdev_private *np = netdev_priv(dev); + spin_lock_irq(&np->lock); + netdev_get_ecmd(dev, ecmd); + spin_unlock_irq(&np->lock); + return 0; +} - if (r) - return r; - if (copy_to_user(useraddr, regbuf, regs.len)) - return -EFAULT; - return 0; - } - /* get message-level */ - case ETHTOOL_GMSGLVL: { - struct ethtool_value edata = {ETHTOOL_GMSGLVL}; - edata.data = np->msg_enable; - 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; - np->msg_enable = edata.data; - return 0; - } - /* restart autonegotiation */ - case ETHTOOL_NWAY_RST: { - int tmp; - int r = -EINVAL; - /* if autoneg is off, it's an error */ - tmp = mdio_read(dev, MII_BMCR); - if (tmp & BMCR_ANENABLE) { - tmp |= (BMCR_ANRESTART); - mdio_write(dev, MII_BMCR, tmp); - r = 0; - } - return r; - } - /* get link status */ - case ETHTOOL_GLINK: { - struct ethtool_value edata = {ETHTOOL_GLINK}; - /* LSTATUS is latched low until a read - so read twice */ - mdio_read(dev, MII_BMSR); - edata.data = (mdio_read(dev, MII_BMSR)&BMSR_LSTATUS) ? 1:0; - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - /* get EEPROM */ - case ETHTOOL_GEEPROM: { - struct ethtool_eeprom eeprom; - u8 eebuf[NATSEMI_EEPROM_SIZE]; - int r; +static int set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct netdev_private *np = netdev_priv(dev); + int res; + spin_lock_irq(&np->lock); + res = netdev_set_ecmd(dev, ecmd); + spin_unlock_irq(&np->lock); + return res; +} - if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) - return -EFAULT; +static void get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct netdev_private *np = netdev_priv(dev); + spin_lock_irq(&np->lock); + netdev_get_wol(dev, &wol->supported, &wol->wolopts); + netdev_get_sopass(dev, wol->sopass); + spin_unlock_irq(&np->lock); +} - if (eeprom.offset > eeprom.offset+eeprom.len) - return -EINVAL; +static int set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct netdev_private *np = netdev_priv(dev); + int res; + spin_lock_irq(&np->lock); + netdev_set_wol(dev, wol->wolopts); + res = netdev_set_sopass(dev, wol->sopass); + spin_unlock_irq(&np->lock); + return res; +} - if ((eeprom.offset+eeprom.len) > NATSEMI_EEPROM_SIZE) { - eeprom.len = NATSEMI_EEPROM_SIZE-eeprom.offset; - } - eeprom.magic = PCI_VENDOR_ID_NS | (PCI_DEVICE_ID_NS_83815<<16); - if (copy_to_user(useraddr, &eeprom, sizeof(eeprom))) - return -EFAULT; +static void get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf) +{ + struct netdev_private *np = netdev_priv(dev); + regs->version = NATSEMI_REGS_VER; + spin_lock_irq(&np->lock); + netdev_get_regs(dev, buf); + spin_unlock_irq(&np->lock); +} - useraddr += offsetof(struct ethtool_eeprom, data); +static u32 get_msglevel(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + return np->msg_enable; +} - spin_lock_irq(&np->lock); - r = netdev_get_eeprom(dev, eebuf); - spin_unlock_irq(&np->lock); +static void set_msglevel(struct net_device *dev, u32 val) +{ + struct netdev_private *np = netdev_priv(dev); + np->msg_enable = val; +} - if (r) - return r; - if (copy_to_user(useraddr, eebuf+eeprom.offset, eeprom.len)) - return -EFAULT; - return 0; +static int nway_reset(struct net_device *dev) +{ + int tmp; + int r = -EINVAL; + /* if autoneg is off, it's an error */ + tmp = mdio_read(dev, MII_BMCR); + if (tmp & BMCR_ANENABLE) { + tmp |= (BMCR_ANRESTART); + mdio_write(dev, MII_BMCR, tmp); + r = 0; } + return r; +} - } +static u32 get_link(struct net_device *dev) +{ + /* LSTATUS is latched low until a read - so read twice */ + mdio_read(dev, MII_BMSR); + return (mdio_read(dev, MII_BMSR)&BMSR_LSTATUS) ? 1:0; +} - return -EOPNOTSUPP; +static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data) +{ + struct netdev_private *np = netdev_priv(dev); + u8 eebuf[NATSEMI_EEPROM_SIZE]; + int res; + + eeprom->magic = PCI_VENDOR_ID_NS | (PCI_DEVICE_ID_NS_83815<<16); + spin_lock_irq(&np->lock); + res = netdev_get_eeprom(dev, eebuf); + spin_unlock_irq(&np->lock); + if (!res) + memcpy(data, eebuf+eeprom->offset, eeprom->len); + return res; } +static struct ethtool_ops ethtool_ops = { + .get_drvinfo = get_drvinfo, + .get_regs_len = get_regs_len, + .get_eeprom_len = get_eeprom_len, + .get_settings = get_settings, + .set_settings = set_settings, + .get_wol = get_wol, + .set_wol = set_wol, + .get_regs = get_regs, + .get_msglevel = get_msglevel, + .set_msglevel = set_msglevel, + .nway_reset = nway_reset, + .get_link = get_link, + .get_eeprom = get_eeprom, +}; + static int netdev_set_wol(struct net_device *dev, u32 newval) { struct netdev_private *np = netdev_priv(dev); @@ -3002,8 +2965,6 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) struct netdev_private *np = netdev_priv(dev); switch(cmd) { - case SIOCETHTOOL: - return netdev_ethtool_ioctl(dev, rq->ifr_data); case SIOCGMIIPHY: /* Get address of MII PHY in use. */ case SIOCDEVPRIVATE: /* for binary compat, remove in 2.5 */ data->phy_id = np->phy_addr_external;