Signed-off-by: Andrew Morton --- 25-akpm/arch/cris/arch-v10/drivers/ethernet.c | 140 ++-- 25-akpm/drivers/ieee1394/eth1394.c | 95 +-- 25-akpm/drivers/media/dvb/dvb-core/dvb_net.c | 9 25-akpm/drivers/net/3c509.c | 151 +---- 25-akpm/drivers/net/8139cp.c | 75 +- 25-akpm/drivers/net/8139too.c | 14 25-akpm/drivers/net/Kconfig | 9 25-akpm/drivers/net/amd8111e.c | 248 +++----- 25-akpm/drivers/net/defxx.c | 144 ++--- 25-akpm/drivers/net/defxx.h | 2 25-akpm/drivers/net/dl2k.c | 267 ++++----- 25-akpm/drivers/net/eepro100.c | 132 ++-- 25-akpm/drivers/net/ewrk3.c | 326 +++++------ 25-akpm/drivers/net/forcedeth.c | 111 +-- 25-akpm/drivers/net/hamachi.c | 155 ++--- 25-akpm/drivers/net/ibmlana.c | 9 25-akpm/drivers/net/iseries_veth.c | 83 +- 25-akpm/drivers/net/ixgb/ixgb_ethtool.c | 494 +++++------------ 25-akpm/drivers/net/ixgb/ixgb_main.c | 24 25-akpm/drivers/net/mac8390.c | 4 25-akpm/drivers/net/meth.c | 26 25-akpm/drivers/net/natsemi.c | 273 ++++----- 25-akpm/drivers/net/ns83820.c | 61 -- 25-akpm/drivers/net/pcmcia/smc91c92_cs.c | 181 +++--- 25-akpm/drivers/net/r8169.c | 564 ++++++++++++++----- 25-akpm/drivers/net/sk_mca.c | 9 25-akpm/drivers/net/starfire.c | 191 +++--- 25-akpm/drivers/net/sundance.c | 187 ++---- 25-akpm/drivers/net/tulip/de4x5.c | 2 25-akpm/drivers/net/tulip/tulip_core.c | 32 - 25-akpm/drivers/net/tulip/xircom_tulip_cb.c | 194 +++--- 25-akpm/drivers/net/typhoon.c | 145 +---- 25-akpm/drivers/net/wan/lmc/lmc_main.c | 9 25-akpm/drivers/net/wireless/airo.c | 45 + 25-akpm/drivers/net/wireless/netwave_cs.c | 12 25-akpm/drivers/net/wireless/prism54/isl_38xx.c | 15 25-akpm/drivers/net/wireless/prism54/isl_38xx.h | 4 25-akpm/drivers/net/wireless/prism54/isl_ioctl.c | 629 +++++++++++++++++++--- 25-akpm/drivers/net/wireless/prism54/isl_ioctl.h | 2 25-akpm/drivers/net/wireless/prism54/isl_oid.h | 9 25-akpm/drivers/net/wireless/prism54/islpci_dev.c | 35 - 25-akpm/drivers/net/wireless/prism54/islpci_dev.h | 4 25-akpm/drivers/net/wireless/prism54/islpci_eth.c | 5 25-akpm/drivers/net/wireless/prism54/oid_mgt.c | 121 +++- 25-akpm/drivers/net/wireless/prism54/oid_mgt.h | 3 25-akpm/drivers/net/wireless/wavelan.c | 19 25-akpm/drivers/net/wireless/wavelan.p.h | 3 25-akpm/drivers/net/wireless/wavelan_cs.c | 181 ++---- 25-akpm/drivers/net/wireless/wavelan_cs.p.h | 3 25-akpm/drivers/net/wireless/wl3501_cs.c | 53 - 25-akpm/drivers/net/yellowfin.c | 62 -- 25-akpm/drivers/usb/gadget/ether.c | 73 -- 25-akpm/drivers/usb/net/catc.c | 122 +--- 25-akpm/drivers/usb/net/kaweth.c | 34 - 25-akpm/drivers/usb/net/pegasus.c | 293 +++------- 25-akpm/drivers/usb/net/rtl8150.c | 186 ++---- 25-akpm/include/linux/netdevice.h | 4 25-akpm/include/linux/wireless.h | 64 +- 25-akpm/include/net/iw_handler.h | 60 +- 25-akpm/net/core/dev.c | 2 25-akpm/net/core/wireless.c | 212 +++++-- 25-akpm/net/irda/irlan/irlan_client.c | 2 62 files changed, 3329 insertions(+), 3294 deletions(-) diff -puN arch/cris/arch-v10/drivers/ethernet.c~bk-netdev arch/cris/arch-v10/drivers/ethernet.c --- 25/arch/cris/arch-v10/drivers/ethernet.c~bk-netdev 2004-09-15 21:06:53.248648696 -0700 +++ 25-akpm/arch/cris/arch-v10/drivers/ethernet.c 2004-09-15 21:06:53.354632584 -0700 @@ -401,7 +401,6 @@ static irqreturn_t e100nw_interrupt(int static void e100_rx(struct net_device *dev); static int e100_close(struct net_device *dev); static int e100_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); -static int e100_ethtool_ioctl(struct net_device* dev, struct ifreq *ifr); static int e100_set_config(struct net_device* dev, struct ifmap* map); static void e100_tx_timeout(struct net_device *dev); static struct net_device_stats *e100_get_stats(struct net_device *dev); @@ -410,6 +409,7 @@ static void e100_hardware_send_packet(ch static void update_rx_stats(struct net_device_stats *); static void update_tx_stats(struct net_device_stats *); static int e100_probe_transceiver(void); +static struct ethtool_ops ethtool_ops; static void e100_check_speed(unsigned long dummy); static void e100_set_speed(unsigned long speed); @@ -483,6 +483,7 @@ etrax_ethernet_init(void) dev->do_ioctl = e100_ioctl; dev->set_config = e100_set_config; dev->tx_timeout = e100_tx_timeout; + SET_ETHTOOL_OPS(dev, ðtool_ops); /* Initialise the list of Etrax DMA-descriptors */ @@ -1401,8 +1402,6 @@ e100_ioctl(struct net_device *dev, struc spin_lock(&np->lock); /* Preempt protection */ switch (cmd) { - case SIOCETHTOOL: - return e100_ethtool_ioctl(dev,ifr); case SIOCGMIIPHY: /* Get PHY address */ data->phy_id = mdio_phy_addr; break; @@ -1439,88 +1438,71 @@ e100_ioctl(struct net_device *dev, struc return 0; } -static int -e100_ethtool_ioctl(struct net_device *dev, struct ifreq *ifr) +static int e100_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) { - struct ethtool_cmd ecmd; - - if (copy_from_user(&ecmd, ifr->ifr_data, sizeof (ecmd))) - return -EFAULT; + ecmd->supported = + SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII | + SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full; + ecmd->port = PORT_TP; + ecmd->transceiver = XCVR_EXTERNAL; + ecmd->phy_address = mdio_phy_addr; + ecmd->speed = current_speed; + ecmd->duplex = full_duplex ? DUPLEX_FULL : DUPLEX_HALF; + ecmd->advertising = ADVERTISED_TP; + if (current_duplex == autoneg && current_speed_selection == 0) + ecmd->advertising |= ADVERTISED_Autoneg; + else { + ecmd->advertising |= + ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full; + if (current_speed_selection == 10) + ecmd->advertising &= ~(ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full); + else if (current_speed_selection == 100) + ecmd->advertising &= ~(ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full); + if (current_duplex == half) + ecmd->advertising &= ~(ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Full); + else if (current_duplex == full) + ecmd->advertising &= ~(ADVERTISED_10baseT_Half | ADVERTISED_100baseT_Half); + } + ecmd->autoneg = AUTONEG_ENABLE; + return 0; +} - switch (ecmd.cmd) { - case ETHTOOL_GSET: - { - memset((void *) &ecmd, 0, sizeof (ecmd)); - ecmd.supported = - SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII | - SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full; - ecmd.port = PORT_TP; - ecmd.transceiver = XCVR_EXTERNAL; - ecmd.phy_address = mdio_phy_addr; - ecmd.speed = current_speed; - ecmd.duplex = full_duplex ? DUPLEX_FULL : DUPLEX_HALF; - ecmd.advertising = ADVERTISED_TP; - if (current_duplex == autoneg && current_speed_selection == 0) - ecmd.advertising |= ADVERTISED_Autoneg; - else { - ecmd.advertising |= - ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full; - if (current_speed_selection == 10) - ecmd.advertising &= ~(ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full); - else if (current_speed_selection == 100) - ecmd.advertising &= ~(ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full); - if (current_duplex == half) - ecmd.advertising &= ~(ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Full); - else if (current_duplex == full) - ecmd.advertising &= ~(ADVERTISED_10baseT_Half | ADVERTISED_100baseT_Half); - } - ecmd.autoneg = AUTONEG_ENABLE; - if (copy_to_user(ifr->ifr_data, &ecmd, sizeof (ecmd))) - return -EFAULT; - } - break; - case ETHTOOL_SSET: - { - if (!capable(CAP_NET_ADMIN)) { - return -EPERM; - } - if (ecmd.autoneg == AUTONEG_ENABLE) { - e100_set_duplex(autoneg); - e100_set_speed(0); - } else { - e100_set_duplex(ecmd.duplex == DUPLEX_HALF ? half : full); - e100_set_speed(ecmd.speed == SPEED_10 ? 10: 100); - } - } - break; - case ETHTOOL_GDRVINFO: - { - struct ethtool_drvinfo info; - memset((void *) &info, 0, sizeof (info)); - strncpy(info.driver, "ETRAX 100LX", sizeof(info.driver) - 1); - strncpy(info.version, "$Revision: 1.22 $", sizeof(info.version) - 1); - strncpy(info.fw_version, "N/A", sizeof(info.fw_version) - 1); - strncpy(info.bus_info, "N/A", sizeof(info.bus_info) - 1); - info.regdump_len = 0; - info.eedump_len = 0; - info.testinfo_len = 0; - if (copy_to_user(ifr->ifr_data, &info, sizeof (info))) - return -EFAULT; - } - break; - case ETHTOOL_NWAY_RST: - if (current_duplex == autoneg && current_speed_selection == 0) - e100_negotiate(); - break; - default: - return -EOPNOTSUPP; - break; +static int e100_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + if (ecmd->autoneg == AUTONEG_ENABLE) { + e100_set_duplex(autoneg); + e100_set_speed(0); + } else { + e100_set_duplex(ecmd->duplex == DUPLEX_HALF ? half : full); + e100_set_speed(ecmd->speed == SPEED_10 ? 10: 100); } return 0; } +static void e100_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + strncpy(info->driver, "ETRAX 100LX", sizeof(info->driver) - 1); + strncpy(info->version, "$Revision: 1.22 $", sizeof(info->version) - 1); + strncpy(info->fw_version, "N/A", sizeof(info->fw_version) - 1); + strncpy(info->bus_info, "N/A", sizeof(info->bus_info) - 1); +} + +static int e100_nway_reset(struct net_device *dev) +{ + if (current_duplex == autoneg && current_speed_selection == 0) + e100_negotiate(); + return 0; +} + +static struct ethtool_ops ethtool_ops = { + .get_settings = e100_get_settings, + .set_settings = e100_set_settings, + .get_drvinfo = e100_get_drvinfo, + .nway_reset = e100_nway_reset, +}; + static int e100_set_config(struct net_device *dev, struct ifmap *map) { diff -puN drivers/ieee1394/eth1394.c~bk-netdev drivers/ieee1394/eth1394.c --- 25/drivers/ieee1394/eth1394.c~bk-netdev 2004-09-15 21:06:53.250648392 -0700 +++ 25-akpm/drivers/ieee1394/eth1394.c 2004-09-15 21:07:21.875296784 -0700 @@ -190,8 +190,7 @@ static inline void purge_partial_datagra static int ether1394_tx(struct sk_buff *skb, struct net_device *dev); static void ether1394_iso(struct hpsb_iso *iso); -static int ether1394_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); -static int ether1394_ethtool_ioctl(struct net_device *dev, void __user *useraddr); +static struct ethtool_ops ethtool_ops; static int ether1394_write(struct hpsb_host *host, int srcid, int destid, quadlet_t *data, u64 addr, size_t len, u16 flags); @@ -216,7 +215,7 @@ static struct hpsb_highlevel eth1394_hig /* This is called after an "ifup" */ static int ether1394_open (struct net_device *dev) { - struct eth1394_priv *priv = dev->priv; + struct eth1394_priv *priv = netdev_priv(dev); int ret = 0; /* Something bad happened, don't even try */ @@ -261,7 +260,7 @@ static int ether1394_stop (struct net_de /* Return statistics to the caller */ static struct net_device_stats *ether1394_stats (struct net_device *dev) { - return &(((struct eth1394_priv *)dev->priv)->stats); + return &(((struct eth1394_priv *)netdev_priv(dev))->stats); } /* What to do if we timeout. I think a host reset is probably in order, so @@ -269,16 +268,16 @@ static struct net_device_stats *ether139 static void ether1394_tx_timeout (struct net_device *dev) { ETH1394_PRINT (KERN_ERR, dev->name, "Timeout, resetting host %s\n", - ((struct eth1394_priv *)(dev->priv))->host->driver->name); + ((struct eth1394_priv *)netdev_priv(dev))->host->driver->name); - highlevel_host_reset (((struct eth1394_priv *)(dev->priv))->host); + highlevel_host_reset (((struct eth1394_priv *)netdev_priv(dev))->host); netif_wake_queue (dev); } static int ether1394_change_mtu(struct net_device *dev, int new_mtu) { - struct eth1394_priv *priv = dev->priv; + struct eth1394_priv *priv = netdev_priv(dev); if ((new_mtu < 68) || (new_mtu > min(ETH1394_DATA_LEN, @@ -379,7 +378,7 @@ static int eth1394_probe(struct device * ud->device.driver_data = node_info; new_node->ud = ud; - priv = (struct eth1394_priv *)hi->dev->priv; + priv = netdev_priv(hi->dev); list_add_tail(&new_node->list, &priv->ip_node_list); return 0; @@ -400,7 +399,7 @@ static int eth1394_remove(struct device if (!hi) return -ENOENT; - priv = (struct eth1394_priv *)hi->dev->priv; + priv = netdev_priv(hi->dev); old_node = eth1394_find_node(&priv->ip_node_list, ud); @@ -435,7 +434,7 @@ static int eth1394_update(struct unit_di if (!hi) return -ENOENT; - priv = (struct eth1394_priv *)hi->dev->priv; + priv = netdev_priv(hi->dev); node = eth1394_find_node(&priv->ip_node_list, ud); @@ -459,7 +458,7 @@ static int eth1394_update(struct unit_di ud->device.driver_data = node_info; node->ud = ud; - priv = (struct eth1394_priv *)hi->dev->priv; + priv = netdev_priv(hi->dev); list_add_tail(&node->list, &priv->ip_node_list); } @@ -496,7 +495,7 @@ static void ether1394_reset_priv (struct { unsigned long flags; int i; - struct eth1394_priv *priv = dev->priv; + struct eth1394_priv *priv = netdev_priv(dev); struct hpsb_host *host = priv->host; u64 guid = *((u64*)&(host->csr.rom->bus_info_data[3])); u16 maxpayload = 1 << (host->csr.max_rec + 1); @@ -547,7 +546,7 @@ static void ether1394_init_dev (struct n dev->header_cache_update= ether1394_header_cache_update; dev->hard_header_parse = ether1394_header_parse; dev->set_mac_address = ether1394_mac_addr; - dev->do_ioctl = ether1394_do_ioctl; + SET_ETHTOOL_OPS(dev, ðtool_ops); /* Some constants */ dev->watchdog_timeo = ETHER1394_TIMEOUT; @@ -602,7 +601,7 @@ static void ether1394_add_host (struct h SET_MODULE_OWNER(dev); - priv = (struct eth1394_priv *)dev->priv; + priv = netdev_priv(dev); INIT_LIST_HEAD(&priv->ip_node_list); @@ -672,7 +671,7 @@ static void ether1394_remove_host (struc hi = hpsb_get_hostinfo(ð1394_highlevel, host); if (hi != NULL) { - struct eth1394_priv *priv = (struct eth1394_priv *)hi->dev->priv; + struct eth1394_priv *priv = netdev_priv(hi->dev); hpsb_unregister_addrspace(ð1394_highlevel, host, priv->local_fifo); @@ -707,7 +706,7 @@ static void ether1394_host_reset (struct return; dev = hi->dev; - priv = (struct eth1394_priv *)dev->priv; + priv = netdev_priv(dev); /* Reset our private host data, but not our mtu */ netif_stop_queue (dev); @@ -882,7 +881,7 @@ static inline u16 ether1394_parse_encap( nodeid_t srcid, nodeid_t destid, u16 ether_type) { - struct eth1394_priv *priv = dev->priv; + struct eth1394_priv *priv = netdev_priv(dev); u64 dest_hw; unsigned short ret = 0; @@ -1112,7 +1111,7 @@ static int ether1394_data_handler(struct { struct sk_buff *skb; unsigned long flags; - struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv; + struct eth1394_priv *priv = netdev_priv(dev); union eth1394_hdr *hdr = (union eth1394_hdr *)buf; u16 ether_type = 0; /* initialized to clear warning */ int hdr_len; @@ -1350,7 +1349,7 @@ static void ether1394_iso(struct hpsb_is ((be32_to_cpu(data[1]) & 0xff000000) >> 24)); source_id = be32_to_cpu(data[0]) >> 16; - priv = (struct eth1394_priv *)dev->priv; + priv = netdev_priv(dev); if (info->channel != (iso->host->csr.broadcast_channel & 0x3f) || specifier_id != ETHER1394_GASP_SPECIFIER_ID) { @@ -1384,7 +1383,7 @@ static void ether1394_iso(struct hpsb_is static inline void ether1394_arp_to_1394arp(struct sk_buff *skb, struct net_device *dev) { - struct eth1394_priv *priv = (struct eth1394_priv *)(dev->priv); + struct eth1394_priv *priv = netdev_priv(dev); struct arphdr *arp = (struct arphdr *)skb->data; unsigned char *arp_ptr = (unsigned char *)(arp + 1); @@ -1582,7 +1581,7 @@ static inline void ether1394_dg_complete { struct sk_buff *skb = ptask->skb; struct net_device *dev = skb->dev; - struct eth1394_priv *priv = dev->priv; + struct eth1394_priv *priv = netdev_priv(dev); unsigned long flags; /* Statistics */ @@ -1635,7 +1634,7 @@ static int ether1394_tx (struct sk_buff { int kmflags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL; struct eth1394hdr *eth; - struct eth1394_priv *priv = dev->priv; + struct eth1394_priv *priv = netdev_priv(dev); int proto; unsigned long flags; nodeid_t dest_node; @@ -1768,53 +1767,17 @@ fail: return 0; /* returning non-zero causes serious problems */ } -static int ether1394_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +static void ether1394_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - switch(cmd) { - case SIOCETHTOOL: - return ether1394_ethtool_ioctl(dev, ifr->ifr_data); - - case SIOCGMIIPHY: /* Get address of MII PHY in use. */ - case SIOCGMIIREG: /* Read MII PHY register. */ - case SIOCSMIIREG: /* Write MII PHY register. */ - default: - return -EOPNOTSUPP; - } - - return 0; -} - -static int ether1394_ethtool_ioctl(struct net_device *dev, void __user *useraddr) -{ - u32 ethcmd; - - if (get_user(ethcmd, (u32 __user *)useraddr)) - return -EFAULT; - - switch (ethcmd) { - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; - strcpy (info.driver, driver_name); - strcpy (info.version, "$Rev: 1231 $"); - /* FIXME XXX provide sane businfo */ - strcpy (info.bus_info, "ieee1394"); - if (copy_to_user (useraddr, &info, sizeof (info))) - return -EFAULT; - break; - } - case ETHTOOL_GSET: - case ETHTOOL_SSET: - case ETHTOOL_NWAY_RST: - case ETHTOOL_GLINK: - case ETHTOOL_GMSGLVL: - case ETHTOOL_SMSGLVL: - default: - return -EOPNOTSUPP; - } - - return 0; + strcpy (info->driver, driver_name); + strcpy (info->version, "$Rev: 1224 $"); + /* FIXME XXX provide sane businfo */ + strcpy (info->bus_info, "ieee1394"); } +static struct ethtool_ops ethtool_ops = { + .get_drvinfo = ether1394_get_drvinfo +}; static int __init ether1394_init_module (void) { diff -puN drivers/media/dvb/dvb-core/dvb_net.c~bk-netdev drivers/media/dvb/dvb-core/dvb_net.c --- 25/drivers/media/dvb/dvb-core/dvb_net.c~bk-netdev 2004-09-15 21:06:53.251648240 -0700 +++ 25-akpm/drivers/media/dvb/dvb-core/dvb_net.c 2004-09-15 21:06:53.358631976 -0700 @@ -919,14 +919,6 @@ static void dvb_net_set_multicast_list ( } -static int dvb_net_set_config(struct net_device *dev, struct ifmap *map) -{ - if (netif_running(dev)) - return -EBUSY; - return 0; -} - - static void wq_restart_net_feed (void *data) { struct net_device *dev = data; @@ -985,7 +977,6 @@ static void dvb_net_setup(struct net_dev dev->hard_start_xmit = dvb_net_tx; dev->get_stats = dvb_net_get_stats; dev->set_multicast_list = dvb_net_set_multicast_list; - dev->set_config = dvb_net_set_config; dev->set_mac_address = dvb_net_set_mac; dev->mtu = 4096; dev->mc_count = 0; diff -puN drivers/net/3c509.c~bk-netdev drivers/net/3c509.c --- 25/drivers/net/3c509.c~bk-netdev 2004-09-15 21:06:53.253647936 -0700 +++ 25-akpm/drivers/net/3c509.c 2004-09-15 21:06:53.360631672 -0700 @@ -197,9 +197,9 @@ static int el3_rx(struct net_device *dev static int el3_close(struct net_device *dev); static void set_multicast_list(struct net_device *dev); static void el3_tx_timeout (struct net_device *dev); -static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); static void el3_down(struct net_device *dev); static void el3_up(struct net_device *dev); +static struct ethtool_ops ethtool_ops; #ifdef CONFIG_PM static int el3_suspend(struct pm_dev *pdev); static int el3_resume(struct pm_dev *pdev); @@ -321,7 +321,7 @@ static int __init el3_common_init(struct dev->set_multicast_list = &set_multicast_list; dev->tx_timeout = el3_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; - dev->do_ioctl = netdev_ioctl; + SET_ETHTOOL_OPS(dev, ðtool_ops); err = register_netdev(dev); if (err) { @@ -1285,123 +1285,64 @@ el3_netdev_set_ecmd(struct net_device *d return 0; } -/** - * netdev_ethtool_ioctl: Handle network interface SIOCETHTOOL ioctls - * @dev: network interface on which out-of-band action is to be performed - * @useraddr: userspace address to which data is to be read and returned - * - * Process the various commands of the SIOCETHTOOL interface. - */ +static void el3_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); +} -static int -netdev_ethtool_ioctl (struct net_device *dev, void __user *useraddr) +static int el3_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) { - u32 ethcmd; struct el3_private *lp = netdev_priv(dev); + int ret; - /* dev_ioctl() in ../../net/core/dev.c has already checked - capable(CAP_NET_ADMIN), so don't bother with that here. */ - - if (get_user(ethcmd, (u32 __user *)useraddr)) - return -EFAULT; - - switch (ethcmd) { - - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; - strcpy (info.driver, DRV_NAME); - strcpy (info.version, DRV_VERSION); - if (copy_to_user (useraddr, &info, sizeof (info))) - return -EFAULT; - return 0; - } - - /* get settings */ - case ETHTOOL_GSET: { - int ret; - struct ethtool_cmd ecmd = { ETHTOOL_GSET }; - spin_lock_irq(&lp->lock); - ret = el3_netdev_get_ecmd(dev, &ecmd); - spin_unlock_irq(&lp->lock); - if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return ret; - } - - /* set settings */ - case ETHTOOL_SSET: { - int ret; - struct ethtool_cmd ecmd; - if (copy_from_user(&ecmd, useraddr, sizeof(ecmd))) - return -EFAULT; - spin_lock_irq(&lp->lock); - ret = el3_netdev_set_ecmd(dev, &ecmd); - spin_unlock_irq(&lp->lock); - return ret; - } - - /* get link status */ - case ETHTOOL_GLINK: { - struct ethtool_value edata = { ETHTOOL_GLINK }; - spin_lock_irq(&lp->lock); - edata.data = el3_link_ok(dev); - spin_unlock_irq(&lp->lock); - 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 = el3_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; - el3_debug = edata.data; - return 0; - } + spin_lock_irq(&lp->lock); + ret = el3_netdev_get_ecmd(dev, ecmd); + spin_unlock_irq(&lp->lock); + return ret; +} - default: - break; - } +static int el3_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct el3_private *lp = netdev_priv(dev); + int ret; - return -EOPNOTSUPP; + spin_lock_irq(&lp->lock); + ret = el3_netdev_set_ecmd(dev, ecmd); + spin_unlock_irq(&lp->lock); + return ret; } -/** - * netdev_ioctl: Handle network interface ioctls - * @dev: network interface on which out-of-band action is to be performed - * @rq: user request data - * @cmd: command issued by user - * - * Process the various out-of-band ioctls passed to this driver. - */ - -static int -netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) +static u32 el3_get_link(struct net_device *dev) { - int rc = 0; + struct el3_private *lp = netdev_priv(dev); + u32 ret; - switch (cmd) { - case SIOCETHTOOL: - rc = netdev_ethtool_ioctl(dev, rq->ifr_data); - break; + spin_lock_irq(&lp->lock); + ret = el3_link_ok(dev); + spin_unlock_irq(&lp->lock); + return ret; +} - default: - rc = -EOPNOTSUPP; - break; - } +static u32 el3_get_msglevel(struct net_device *dev) +{ + return el3_debug; +} - return rc; +static void el3_set_msglevel(struct net_device *dev, u32 v) +{ + el3_debug = v; } +static struct ethtool_ops ethtool_ops = { + .get_drvinfo = el3_get_drvinfo, + .get_settings = el3_get_settings, + .set_settings = el3_set_settings, + .get_link = el3_get_link, + .get_msglevel = el3_get_msglevel, + .set_msglevel = el3_set_msglevel, +}; + static void el3_down(struct net_device *dev) { diff -puN drivers/net/8139cp.c~bk-netdev drivers/net/8139cp.c --- 25/drivers/net/8139cp.c~bk-netdev 2004-09-15 21:06:53.254647784 -0700 +++ 25-akpm/drivers/net/8139cp.c 2004-09-15 21:06:53.362631368 -0700 @@ -185,6 +185,9 @@ enum { RingEnd = (1 << 30), /* End of descriptor ring */ FirstFrag = (1 << 29), /* First segment of a packet */ LastFrag = (1 << 28), /* Final segment of a packet */ + LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ + MSSShift = 16, /* MSS value position */ + MSSMask = 0xfff, /* MSS value: 11 bits */ TxError = (1 << 23), /* Tx error summary */ RxError = (1 << 20), /* Rx error summary */ IPCS = (1 << 18), /* Calculate IP checksum */ @@ -311,7 +314,7 @@ struct cp_desc { struct ring_info { struct sk_buff *skb; dma_addr_t mapping; - unsigned frag; + u32 len; }; struct cp_dma_stats { @@ -705,7 +708,7 @@ static void cp_tx (struct cp_private *cp BUG(); pci_unmap_single(cp->pdev, cp->tx_skb[tx_tail].mapping, - skb->len, PCI_DMA_TODEVICE); + cp->tx_skb[tx_tail].len, PCI_DMA_TODEVICE); if (status & LastFrag) { if (status & (TxError | TxFIFOUnder)) { @@ -747,10 +750,11 @@ static int cp_start_xmit (struct sk_buff { struct cp_private *cp = netdev_priv(dev); unsigned entry; - u32 eor; + u32 eor, flags; #if CP_VLAN_TAG_USED u32 vlan_tag = 0; #endif + int mss = 0; spin_lock_irq(&cp->lock); @@ -770,6 +774,9 @@ static int cp_start_xmit (struct sk_buff entry = cp->tx_head; eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0; + if (dev->features & NETIF_F_TSO) + mss = skb_shinfo(skb)->tso_size; + if (skb_shinfo(skb)->nr_frags == 0) { struct cp_desc *txd = &cp->tx_ring[entry]; u32 len; @@ -781,26 +788,26 @@ static int cp_start_xmit (struct sk_buff txd->addr = cpu_to_le64(mapping); wmb(); - if (skb->ip_summed == CHECKSUM_HW) { + flags = eor | len | DescOwn | FirstFrag | LastFrag; + + if (mss) + flags |= LargeSend | ((mss & MSSMask) << MSSShift); + else if (skb->ip_summed == CHECKSUM_HW) { const struct iphdr *ip = skb->nh.iph; if (ip->protocol == IPPROTO_TCP) - txd->opts1 = cpu_to_le32(eor | len | DescOwn | - FirstFrag | LastFrag | - IPCS | TCPCS); + flags |= IPCS | TCPCS; else if (ip->protocol == IPPROTO_UDP) - txd->opts1 = cpu_to_le32(eor | len | DescOwn | - FirstFrag | LastFrag | - IPCS | UDPCS); + flags |= IPCS | UDPCS; else - BUG(); - } else - txd->opts1 = cpu_to_le32(eor | len | DescOwn | - FirstFrag | LastFrag); + WARN_ON(1); /* we need a WARN() */ + } + + txd->opts1 = cpu_to_le32(flags); wmb(); cp->tx_skb[entry].skb = skb; cp->tx_skb[entry].mapping = mapping; - cp->tx_skb[entry].frag = 0; + cp->tx_skb[entry].len = len; entry = NEXT_TX(entry); } else { struct cp_desc *txd; @@ -818,7 +825,7 @@ static int cp_start_xmit (struct sk_buff first_len, PCI_DMA_TODEVICE); cp->tx_skb[entry].skb = skb; cp->tx_skb[entry].mapping = first_mapping; - cp->tx_skb[entry].frag = 1; + cp->tx_skb[entry].len = first_len; entry = NEXT_TX(entry); for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) { @@ -834,16 +841,19 @@ static int cp_start_xmit (struct sk_buff len, PCI_DMA_TODEVICE); eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0; - if (skb->ip_summed == CHECKSUM_HW) { - ctrl = eor | len | DescOwn | IPCS; + ctrl = eor | len | DescOwn; + + if (mss) + ctrl |= LargeSend | + ((mss & MSSMask) << MSSShift); + else if (skb->ip_summed == CHECKSUM_HW) { if (ip->protocol == IPPROTO_TCP) - ctrl |= TCPCS; + ctrl |= IPCS | TCPCS; else if (ip->protocol == IPPROTO_UDP) - ctrl |= UDPCS; + ctrl |= IPCS | UDPCS; else BUG(); - } else - ctrl = eor | len | DescOwn; + } if (frag == skb_shinfo(skb)->nr_frags - 1) ctrl |= LastFrag; @@ -858,7 +868,7 @@ static int cp_start_xmit (struct sk_buff cp->tx_skb[entry].skb = skb; cp->tx_skb[entry].mapping = mapping; - cp->tx_skb[entry].frag = frag + 2; + cp->tx_skb[entry].len = len; entry = NEXT_TX(entry); } @@ -1072,7 +1082,6 @@ static int cp_refill_rx (struct cp_priva cp->rx_skb[i].mapping = pci_map_single(cp->pdev, skb->tail, cp->rx_buf_sz, PCI_DMA_FROMDEVICE); cp->rx_skb[i].skb = skb; - cp->rx_skb[i].frag = 0; cp->rx_ring[i].opts2 = 0; cp->rx_ring[i].addr = cpu_to_le64(cp->rx_skb[i].mapping); @@ -1124,9 +1133,6 @@ static void cp_clean_rings (struct cp_pr { unsigned i; - memset(cp->rx_ring, 0, sizeof(struct cp_desc) * CP_RX_RING_SIZE); - memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE); - for (i = 0; i < CP_RX_RING_SIZE; i++) { if (cp->rx_skb[i].skb) { pci_unmap_single(cp->pdev, cp->rx_skb[i].mapping, @@ -1138,13 +1144,18 @@ static void cp_clean_rings (struct cp_pr for (i = 0; i < CP_TX_RING_SIZE; i++) { if (cp->tx_skb[i].skb) { struct sk_buff *skb = cp->tx_skb[i].skb; + pci_unmap_single(cp->pdev, cp->tx_skb[i].mapping, - skb->len, PCI_DMA_TODEVICE); - dev_kfree_skb(skb); + cp->tx_skb[i].len, PCI_DMA_TODEVICE); + if (le32_to_cpu(cp->tx_ring[i].opts1) & LastFrag) + dev_kfree_skb(skb); cp->net_stats.tx_dropped++; } } + memset(cp->rx_ring, 0, sizeof(struct cp_desc) * CP_RX_RING_SIZE); + memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE); + memset(&cp->rx_skb, 0, sizeof(struct ring_info) * CP_RX_RING_SIZE); memset(&cp->tx_skb, 0, sizeof(struct ring_info) * CP_TX_RING_SIZE); } @@ -1536,6 +1547,8 @@ static struct ethtool_ops cp_ethtool_ops .set_tx_csum = ethtool_op_set_tx_csum, /* local! */ .get_sg = ethtool_op_get_sg, .set_sg = ethtool_op_set_sg, + .get_tso = ethtool_op_get_tso, + .set_tso = ethtool_op_set_tso, .get_regs = cp_get_regs, .get_wol = cp_get_wol, .set_wol = cp_set_wol, @@ -1766,6 +1779,10 @@ static int cp_init_one (struct pci_dev * if (pci_using_dac) dev->features |= NETIF_F_HIGHDMA; +#if 0 /* disabled by default until verified */ + dev->features |= NETIF_F_TSO; +#endif + dev->irq = pdev->irq; rc = register_netdev(dev); diff -puN drivers/net/8139too.c~bk-netdev drivers/net/8139too.c --- 25/drivers/net/8139too.c~bk-netdev 2004-09-15 21:06:53.256647480 -0700 +++ 25-akpm/drivers/net/8139too.c 2004-09-15 21:06:53.365630912 -0700 @@ -390,8 +390,14 @@ enum rx_mode_bits { /* Bits in TxConfig. */ enum tx_config_bits { - TxIFG1 = (1 << 25), /* Interframe Gap Time */ - TxIFG0 = (1 << 24), /* Enabling these bits violates IEEE 802.3 */ + + /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */ + TxIFGShift = 24, + TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */ + TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */ + TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */ + TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */ + TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ TxCRC = (1 << 16), /* DISABLE appending CRC to end of Tx packets */ TxClearAbt = (1 << 0), /* Clear abort (WO) */ @@ -724,7 +730,7 @@ static const unsigned int rtl8139_rx_con #endif static const unsigned int rtl8139_tx_config = - (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); + TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift); static void __rtl8139_cleanup_dev (struct net_device *dev) { @@ -1400,8 +1406,6 @@ static void rtl8139_hw_start (struct net tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys; RTL_W32 (RxConfig, tp->rx_config); - - /* Check this value: the documentation for IFG contradicts ifself. */ RTL_W32 (TxConfig, rtl8139_tx_config); tp->cur_rx = 0; diff -puN drivers/net/amd8111e.c~bk-netdev drivers/net/amd8111e.c --- 25/drivers/net/amd8111e.c~bk-netdev 2004-09-15 21:06:53.258647176 -0700 +++ 25-akpm/drivers/net/amd8111e.c 2004-09-15 21:06:53.370630152 -0700 @@ -1464,32 +1464,25 @@ static int amd8111e_start_xmit(struct sk /* This function returns all the memory mapped registers of the device. */ -static char* amd8111e_read_regs(struct amd8111e_priv* lp) +static void amd8111e_read_regs(struct amd8111e_priv *lp, u32 *buf) { - void * mmio = lp->mmio; - u32 * reg_buff; - - reg_buff = kmalloc( AMD8111E_REG_DUMP_LEN,GFP_KERNEL); - if(NULL == reg_buff) - return NULL; - + void *mmio = lp->mmio; /* Read only necessary registers */ - reg_buff[0] = readl(mmio + XMT_RING_BASE_ADDR0); - reg_buff[1] = readl(mmio + XMT_RING_LEN0); - reg_buff[2] = readl(mmio + RCV_RING_BASE_ADDR0); - reg_buff[3] = readl(mmio + RCV_RING_LEN0); - reg_buff[4] = readl(mmio + CMD0); - reg_buff[5] = readl(mmio + CMD2); - reg_buff[6] = readl(mmio + CMD3); - reg_buff[7] = readl(mmio + CMD7); - reg_buff[8] = readl(mmio + INT0); - reg_buff[9] = readl(mmio + INTEN0); - reg_buff[10] = readl(mmio + LADRF); - reg_buff[11] = readl(mmio + LADRF+4); - reg_buff[12] = readl(mmio + STAT0); - - return (char *)reg_buff; + buf[0] = readl(mmio + XMT_RING_BASE_ADDR0); + buf[1] = readl(mmio + XMT_RING_LEN0); + buf[2] = readl(mmio + RCV_RING_BASE_ADDR0); + buf[3] = readl(mmio + RCV_RING_LEN0); + buf[4] = readl(mmio + CMD0); + buf[5] = readl(mmio + CMD2); + buf[6] = readl(mmio + CMD3); + buf[7] = readl(mmio + CMD7); + buf[8] = readl(mmio + INT0); + buf[9] = readl(mmio + INTEN0); + buf[10] = readl(mmio + LADRF); + buf[11] = readl(mmio + LADRF+4); + buf[12] = readl(mmio + STAT0); } + /* amd8111e crc generator implementation is different from the kernel ether_crc() function. @@ -1567,131 +1560,101 @@ static void amd8111e_set_multicast_list( } -/* -This function handles all the ethtool ioctls. It gives driver info, gets/sets driver speed, gets memory mapped register values, forces auto negotiation, sets/gets WOL options for ethtool application. -*/ - -static int amd8111e_ethtool_ioctl(struct net_device* dev, void __user *useraddr) +static void amd8111e_get_drvinfo(struct net_device* dev, struct ethtool_drvinfo *info) { struct amd8111e_priv *lp = netdev_priv(dev); struct pci_dev *pci_dev = lp->pci_dev; - u32 ethcmd; - - if( useraddr == NULL) - return -EINVAL; - if(copy_from_user (ðcmd, useraddr, sizeof (ethcmd))) - return -EFAULT; - - switch(ethcmd){ - - case ETHTOOL_GDRVINFO:{ - struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; - strcpy (info.driver, MODULE_NAME); - strcpy (info.version, MODULE_VERS); - memset(&info.fw_version, 0, sizeof(info.fw_version)); - sprintf(info.fw_version,"%u",chip_version); - strcpy (info.bus_info, pci_name(pci_dev)); - info.eedump_len = 0; - info.regdump_len = AMD8111E_REG_DUMP_LEN; - 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(&lp->lock); - mii_ethtool_gset(&lp->mii_if, &ecmd); - spin_unlock_irq(&lp->lock); - if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; - } - /* set settings */ - case ETHTOOL_SSET: { - int r; - struct ethtool_cmd ecmd; - if (copy_from_user(&ecmd, useraddr, sizeof(ecmd))) - return -EFAULT; + strcpy (info->driver, MODULE_NAME); + strcpy (info->version, MODULE_VERS); + sprintf(info->fw_version,"%u",chip_version); + strcpy (info->bus_info, pci_name(pci_dev)); +} - spin_lock_irq(&lp->lock); - r = mii_ethtool_sset(&lp->mii_if, &ecmd); - spin_unlock_irq(&lp->lock); - return r; - } - case ETHTOOL_GREGS: { - struct ethtool_regs regs; - u8 *regbuf; - int ret; - - if (copy_from_user(®s, useraddr, sizeof(regs))) - return -EFAULT; - if (regs.len > AMD8111E_REG_DUMP_LEN) - regs.len = AMD8111E_REG_DUMP_LEN; - regs.version = 0; - if (copy_to_user(useraddr, ®s, sizeof(regs))) - return -EFAULT; - - regbuf = amd8111e_read_regs(lp); - if (!regbuf) - return -ENOMEM; - - useraddr += offsetof(struct ethtool_regs, data); - ret = 0; - if (copy_to_user(useraddr, regbuf, regs.len)) - ret = -EFAULT; - kfree(regbuf); - return ret; - } - /* restart autonegotiation */ - case ETHTOOL_NWAY_RST: { - return mii_nway_restart(&lp->mii_if); - } - /* get link status */ - case ETHTOOL_GLINK: { - struct ethtool_value val = {ETHTOOL_GLINK}; - val.data = mii_link_ok(&lp->mii_if); - if (copy_to_user(useraddr, &val, sizeof(val))) - return -EFAULT; - return 0; - } - case ETHTOOL_GWOL: { - struct ethtool_wolinfo wol_info = { ETHTOOL_GWOL }; +static int amd8111e_get_regs_len(struct net_device *dev) +{ + return AMD8111E_REG_DUMP_LEN; +} - wol_info.supported = WAKE_MAGIC|WAKE_PHY; - wol_info.wolopts = 0; - if (lp->options & OPTION_WOL_ENABLE) - wol_info.wolopts = WAKE_MAGIC; - memset(&wol_info.sopass, 0, sizeof(wol_info.sopass)); - if (copy_to_user(useraddr, &wol_info, sizeof(wol_info))) - return -EFAULT; - return 0; - } - case ETHTOOL_SWOL: { - struct ethtool_wolinfo wol_info; +static void amd8111e_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf) +{ + struct amd8111e_priv *lp = netdev_priv(dev); + regs->version = 0; + amd8111e_read_regs(lp, buf); +} - if (copy_from_user(&wol_info, useraddr, sizeof(wol_info))) - return -EFAULT; - if (wol_info.wolopts & ~(WAKE_MAGIC |WAKE_PHY)) - return -EINVAL; - spin_lock_irq(&lp->lock); - if(wol_info.wolopts & WAKE_MAGIC) - lp->options |= - (OPTION_WOL_ENABLE | OPTION_WAKE_MAGIC_ENABLE); - else if(wol_info.wolopts & WAKE_PHY) - lp->options |= - (OPTION_WOL_ENABLE | OPTION_WAKE_PHY_ENABLE); - else - lp->options &= ~OPTION_WOL_ENABLE; - spin_unlock_irq(&lp->lock); - return 0; - } - - default: - break; - } - return -EOPNOTSUPP; +static int amd8111e_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct amd8111e_priv *lp = netdev_priv(dev); + spin_lock_irq(&lp->lock); + mii_ethtool_gset(&lp->mii_if, ecmd); + spin_unlock_irq(&lp->lock); + return 0; +} + +static int amd8111e_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct amd8111e_priv *lp = netdev_priv(dev); + int res; + spin_lock_irq(&lp->lock); + res = mii_ethtool_sset(&lp->mii_if, ecmd); + spin_unlock_irq(&lp->lock); + return res; +} + +static int amd8111e_nway_reset(struct net_device *dev) +{ + struct amd8111e_priv *lp = netdev_priv(dev); + return mii_nway_restart(&lp->mii_if); +} + +static u32 amd8111e_get_link(struct net_device *dev) +{ + struct amd8111e_priv *lp = netdev_priv(dev); + return mii_link_ok(&lp->mii_if); } + +static void amd8111e_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol_info) +{ + struct amd8111e_priv *lp = netdev_priv(dev); + wol_info->supported = WAKE_MAGIC|WAKE_PHY; + if (lp->options & OPTION_WOL_ENABLE) + wol_info->wolopts = WAKE_MAGIC; +} + +static int amd8111e_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol_info) +{ + struct amd8111e_priv *lp = netdev_priv(dev); + if (wol_info->wolopts & ~(WAKE_MAGIC|WAKE_PHY)) + return -EINVAL; + spin_lock_irq(&lp->lock); + if (wol_info->wolopts & WAKE_MAGIC) + lp->options |= + (OPTION_WOL_ENABLE | OPTION_WAKE_MAGIC_ENABLE); + else if(wol_info->wolopts & WAKE_PHY) + lp->options |= + (OPTION_WOL_ENABLE | OPTION_WAKE_PHY_ENABLE); + else + lp->options &= ~OPTION_WOL_ENABLE; + spin_unlock_irq(&lp->lock); + return 0; +} + +static struct ethtool_ops ops = { + .get_drvinfo = amd8111e_get_drvinfo, + .get_regs_len = amd8111e_get_regs_len, + .get_regs = amd8111e_get_regs, + .get_settings = amd8111e_get_settings, + .set_settings = amd8111e_set_settings, + .nway_reset = amd8111e_nway_reset, + .get_link = amd8111e_get_link, + .get_wol = amd8111e_get_wol, + .set_wol = amd8111e_set_wol, +}; + +/* +This function handles all the ethtool ioctls. It gives driver info, gets/sets driver speed, gets memory mapped register values, forces auto negotiation, sets/gets WOL options for ethtool application. +*/ + static int amd8111e_ioctl(struct net_device * dev , struct ifreq *ifr, int cmd) { struct mii_ioctl_data *data = if_mii(ifr); @@ -1703,8 +1666,6 @@ static int amd8111e_ioctl(struct net_dev return -EPERM; switch(cmd) { - case SIOCETHTOOL: - return amd8111e_ethtool_ioctl(dev, ifr->ifr_data); case SIOCGMIIPHY: data->phy_id = PHY_ID; @@ -2085,6 +2046,7 @@ static int __devinit amd8111e_probe_one( dev->set_mac_address = amd8111e_set_mac_address; dev->do_ioctl = amd8111e_ioctl; dev->change_mtu = amd8111e_change_mtu; + SET_ETHTOOL_OPS(dev, &ops); dev->irq =pdev->irq; dev->tx_timeout = amd8111e_tx_timeout; dev->watchdog_timeo = AMD8111E_TX_TIMEOUT; diff -puN drivers/net/defxx.c~bk-netdev drivers/net/defxx.c --- 25/drivers/net/defxx.c~bk-netdev 2004-09-15 21:06:53.259647024 -0700 +++ 25-akpm/drivers/net/defxx.c 2004-09-15 21:06:53.374629544 -0700 @@ -19,7 +19,7 @@ * LVS Lawrence V. Stefani * * Maintainers: - * macro Maciej W. Rozycki + * macro Maciej W. Rozycki * * Credits: * I'd like to thank Patricia Cross for helping me get started with @@ -190,6 +190,7 @@ * Feb 2001 Skb allocation fixes * Feb 2001 davej PCI enable cleanups. * 04 Aug 2003 macro Converted to the DMA API. + * 14 Aug 2004 macro Fix device names reported. */ /* Include files */ @@ -214,12 +215,14 @@ #include "defxx.h" -/* Version information string - should be updated prior to each new release!!! */ +/* Version information string should be updated prior to each new release! */ +#define DRV_NAME "defxx" +#define DRV_VERSION "v1.07" +#define DRV_RELDATE "2004/08/14" static char version[] __devinitdata = - "defxx.c:v1.06 2003/08/04 Lawrence V. Stefani and others\n"; - -#define DRV_NAME "defxx" + DRV_NAME ": " DRV_VERSION " " DRV_RELDATE + " Lawrence V. Stefani and others\n"; #define DYNAMIC_BUFFERS 1 @@ -235,7 +238,7 @@ static char version[] __devinitdata = static void dfx_bus_init(struct net_device *dev); static void dfx_bus_config_check(DFX_board_t *bp); -static int dfx_driver_init(struct net_device *dev); +static int dfx_driver_init(struct net_device *dev, const char *print_name); static int dfx_adap_init(DFX_board_t *bp, int get_buffers); static int dfx_open(struct net_device *dev); @@ -404,24 +407,25 @@ static inline void dfx_port_read_long( */ static int __devinit dfx_init_one_pci_or_eisa(struct pci_dev *pdev, long ioaddr) { + static int version_disp; + char *print_name = DRV_NAME; struct net_device *dev; DFX_board_t *bp; /* board pointer */ int alloc_size; /* total buffer size used */ int err; -#ifndef MODULE - static int version_disp; - - if (!version_disp) /* display version info if adapter is found */ - { + if (!version_disp) { /* display version info if adapter is found */ version_disp = 1; /* set display flag to TRUE so that */ printk(version); /* we only display this string ONCE */ } -#endif + + if (pdev != NULL) + print_name = pdev->slot_name; dev = alloc_fddidev(sizeof(*bp)); if (!dev) { - printk (KERN_ERR "defxx: unable to allocate fddidev, aborting\n"); + printk(KERN_ERR "%s: unable to allocate fddidev, aborting\n", + print_name); return -ENOMEM; } @@ -437,9 +441,12 @@ static int __devinit dfx_init_one_pci_or bp = dev->priv; - if (!request_region (ioaddr, pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN, DRV_NAME)) { - printk (KERN_ERR "%s: Cannot reserve I/O resource 0x%x @ 0x%lx, aborting\n", - DRV_NAME, PFI_K_CSR_IO_LEN, ioaddr); + if (!request_region(ioaddr, + pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN, + print_name)) { + printk(KERN_ERR "%s: Cannot reserve I/O resource " + "0x%x @ 0x%lx, aborting\n", print_name, + pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN, ioaddr); err = -EBUSY; goto err_out; } @@ -468,7 +475,7 @@ static int __devinit dfx_init_one_pci_or pci_set_master (pdev); } - if (dfx_driver_init(dev) != DFX_K_SUCCESS) { + if (dfx_driver_init(dev, print_name) != DFX_K_SUCCESS) { err = -ENODEV; goto err_out_region; } @@ -477,6 +484,7 @@ static int __devinit dfx_init_one_pci_or if (err) goto err_out_kfree; + printk("%s: registered as %s\n", print_name, dev->name); return 0; err_out_kfree: @@ -770,6 +778,7 @@ static void __devinit dfx_bus_config_che * * Arguments: * dev - pointer to device information + * print_name - printable device name * * Functional Description: * This function allocates additional resources such as the host memory @@ -792,7 +801,8 @@ static void __devinit dfx_bus_config_che * returning from this routine. */ -static int __devinit dfx_driver_init(struct net_device *dev) +static int __devinit dfx_driver_init(struct net_device *dev, + const char *print_name) { DFX_board_t *bp = dev->priv; int alloc_size; /* total buffer size needed */ @@ -841,26 +851,20 @@ static int __devinit dfx_driver_init(str /* Read the factory MAC address from the adapter then save it */ - if (dfx_hw_port_ctrl_req(bp, - PI_PCTRL_M_MLA, - PI_PDATA_A_MLA_K_LO, - 0, - &data) != DFX_K_SUCCESS) - { - printk("%s: Could not read adapter factory MAC address!\n", dev->name); + if (dfx_hw_port_ctrl_req(bp, PI_PCTRL_M_MLA, PI_PDATA_A_MLA_K_LO, 0, + &data) != DFX_K_SUCCESS) { + printk("%s: Could not read adapter factory MAC address!\n", + print_name); return(DFX_K_FAILURE); - } + } memcpy(&bp->factory_mac_addr[0], &data, sizeof(u32)); - if (dfx_hw_port_ctrl_req(bp, - PI_PCTRL_M_MLA, - PI_PDATA_A_MLA_K_HI, - 0, - &data) != DFX_K_SUCCESS) - { - printk("%s: Could not read adapter factory MAC address!\n", dev->name); + if (dfx_hw_port_ctrl_req(bp, PI_PCTRL_M_MLA, PI_PDATA_A_MLA_K_HI, 0, + &data) != DFX_K_SUCCESS) { + printk("%s: Could not read adapter factory MAC address!\n", + print_name); return(DFX_K_FAILURE); - } + } memcpy(&bp->factory_mac_addr[4], &data, sizeof(u16)); /* @@ -872,27 +876,19 @@ static int __devinit dfx_driver_init(str memcpy(dev->dev_addr, bp->factory_mac_addr, FDDI_K_ALEN); if (bp->bus_type == DFX_BUS_TYPE_EISA) - printk("%s: DEFEA at I/O addr = 0x%lX, IRQ = %d, Hardware addr = %02X-%02X-%02X-%02X-%02X-%02X\n", - dev->name, - dev->base_addr, - dev->irq, - dev->dev_addr[0], - dev->dev_addr[1], - dev->dev_addr[2], - dev->dev_addr[3], - dev->dev_addr[4], - dev->dev_addr[5]); + printk("%s: DEFEA at I/O addr = 0x%lX, IRQ = %d, " + "Hardware addr = %02X-%02X-%02X-%02X-%02X-%02X\n", + print_name, dev->base_addr, dev->irq, + dev->dev_addr[0], dev->dev_addr[1], + dev->dev_addr[2], dev->dev_addr[3], + dev->dev_addr[4], dev->dev_addr[5]); else - printk("%s: DEFPA at I/O addr = 0x%lX, IRQ = %d, Hardware addr = %02X-%02X-%02X-%02X-%02X-%02X\n", - dev->name, - dev->base_addr, - dev->irq, - dev->dev_addr[0], - dev->dev_addr[1], - dev->dev_addr[2], - dev->dev_addr[3], - dev->dev_addr[4], - dev->dev_addr[5]); + printk("%s: DEFPA at I/O addr = 0x%lX, IRQ = %d, " + "Hardware addr = %02X-%02X-%02X-%02X-%02X-%02X\n", + print_name, dev->base_addr, dev->irq, + dev->dev_addr[0], dev->dev_addr[1], + dev->dev_addr[2], dev->dev_addr[3], + dev->dev_addr[4], dev->dev_addr[5]); /* * Get memory for descriptor block, consumer block, and other buffers @@ -909,11 +905,11 @@ static int __devinit dfx_driver_init(str (PI_ALIGN_K_DESC_BLK - 1); bp->kmalloced = top_v = pci_alloc_consistent(bp->pci_dev, alloc_size, &bp->kmalloced_dma); - if (top_v == NULL) - { - printk("%s: Could not allocate memory for host buffers and structures!\n", dev->name); + if (top_v == NULL) { + printk("%s: Could not allocate memory for host buffers " + "and structures!\n", print_name); return(DFX_K_FAILURE); - } + } memset(top_v, 0, alloc_size); /* zero out memory before continuing */ top_p = bp->kmalloced_dma; /* get physical address of buffer */ @@ -970,14 +966,20 @@ static int __devinit dfx_driver_init(str /* Display virtual and physical addresses if debug driver */ - DBG_printk("%s: Descriptor block virt = %0lX, phys = %0X\n", dev->name, (long)bp->descr_block_virt, bp->descr_block_phys); - DBG_printk("%s: Command Request buffer virt = %0lX, phys = %0X\n", dev->name, (long)bp->cmd_req_virt, bp->cmd_req_phys); - DBG_printk("%s: Command Response buffer virt = %0lX, phys = %0X\n", dev->name, (long)bp->cmd_rsp_virt, bp->cmd_rsp_phys); - DBG_printk("%s: Receive buffer block virt = %0lX, phys = %0X\n", dev->name, (long)bp->rcv_block_virt, bp->rcv_block_phys); - DBG_printk("%s: Consumer block virt = %0lX, phys = %0X\n", dev->name, (long)bp->cons_block_virt, bp->cons_block_phys); + DBG_printk("%s: Descriptor block virt = %0lX, phys = %0X\n", + print_name, + (long)bp->descr_block_virt, bp->descr_block_phys); + DBG_printk("%s: Command Request buffer virt = %0lX, phys = %0X\n", + print_name, (long)bp->cmd_req_virt, bp->cmd_req_phys); + DBG_printk("%s: Command Response buffer virt = %0lX, phys = %0X\n", + print_name, (long)bp->cmd_rsp_virt, bp->cmd_rsp_phys); + DBG_printk("%s: Receive buffer block virt = %0lX, phys = %0X\n", + print_name, (long)bp->rcv_block_virt, bp->rcv_block_phys); + DBG_printk("%s: Consumer block virt = %0lX, phys = %0X\n", + print_name, (long)bp->cons_block_virt, bp->cons_block_phys); return(DFX_K_SUCCESS); - } +} /* @@ -2666,12 +2668,12 @@ static int dfx_hw_dma_uninit(DFX_board_t static void my_skb_align(struct sk_buff *skb, int n) { - unsigned long x=(unsigned long)skb->data; + unsigned long x = (unsigned long)skb->data; unsigned long v; - v=(x+n-1)&~(n-1); /* Where we want to be */ + v = ALIGN(x, n); /* Where we want to be */ - skb_reserve(skb, v-x); + skb_reserve(skb, v - x); } @@ -3426,11 +3428,6 @@ static int __init dfx_init(void) { int rc_pci, rc_eisa; -/* when a module, this is printed whether or not devices are found in probe */ -#ifdef MODULE - printk(version); -#endif - rc_pci = pci_module_init(&dfx_driver); if (rc_pci >= 0) dfx_have_pci = 1; @@ -3451,6 +3448,9 @@ static void __exit dfx_cleanup(void) module_init(dfx_init); module_exit(dfx_cleanup); +MODULE_AUTHOR("Lawrence V. Stefani"); +MODULE_DESCRIPTION("DEC FDDIcontroller EISA/PCI (DEFEA/DEFPA) driver " + DRV_VERSION " " DRV_RELDATE); MODULE_LICENSE("GPL"); diff -puN drivers/net/defxx.h~bk-netdev drivers/net/defxx.h --- 25/drivers/net/defxx.h~bk-netdev 2004-09-15 21:06:53.261646720 -0700 +++ 25-akpm/drivers/net/defxx.h 2004-09-15 21:06:53.376629240 -0700 @@ -16,7 +16,7 @@ * LVS Lawrence V. Stefani * * Maintainers: - * macro Maciej W. Rozycki + * macro Maciej W. Rozycki * * Modification History: * Date Name Description diff -puN drivers/net/dl2k.c~bk-netdev drivers/net/dl2k.c --- 25/drivers/net/dl2k.c~bk-netdev 2004-09-15 21:06:53.263646416 -0700 +++ 25-akpm/drivers/net/dl2k.c 2004-09-15 21:06:53.379628784 -0700 @@ -107,7 +107,6 @@ static int change_mtu (struct net_device static void set_multicast (struct net_device *dev); static struct net_device_stats *get_stats (struct net_device *dev); static int clear_stats (struct net_device *dev); -static int rio_ethtool_ioctl (struct net_device *dev, void __user *useraddr); static int rio_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); static int rio_close (struct net_device *dev); static int find_miiphy (struct net_device *dev); @@ -122,6 +121,8 @@ static int mii_read (struct net_device * static int mii_write (struct net_device *dev, int phy_addr, int reg_num, u16 data); +static struct ethtool_ops ethtool_ops; + static int __devinit rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -168,7 +169,7 @@ rio_probe1 (struct pci_dev *pdev, const #endif dev->base_addr = ioaddr; dev->irq = irq; - np = dev->priv; + np = netdev_priv(dev); np->chip_id = chip_idx; np->pdev = pdev; spin_lock_init (&np->tx_lock); @@ -244,6 +245,7 @@ rio_probe1 (struct pci_dev *pdev, const dev->tx_timeout = &rio_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; dev->change_mtu = &change_mtu; + SET_ETHTOOL_OPS(dev, ðtool_ops); #if 0 dev->features = NETIF_F_IP_CSUM; #endif @@ -335,7 +337,7 @@ find_miiphy (struct net_device *dev) int i, phy_found = 0; struct netdev_private *np; long ioaddr; - np = dev->priv; + np = netdev_priv(dev); ioaddr = dev->base_addr; np->phy_addr = 1; @@ -362,7 +364,7 @@ parse_eeprom (struct net_device *dev) u8 *psib; u32 crc; PSROM_t psrom = (PSROM_t) sromdata; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int cid, next; @@ -432,7 +434,7 @@ parse_eeprom (struct net_device *dev) static int rio_open (struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); long ioaddr = dev->base_addr; int i; u16 macctrl; @@ -516,7 +518,7 @@ static void rio_timer (unsigned long data) { struct net_device *dev = (struct net_device *)data; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); unsigned int entry; int next_tick = 1*HZ; unsigned long flags; @@ -574,7 +576,7 @@ rio_tx_timeout (struct net_device *dev) static void alloc_list (struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int i; np->cur_rx = np->cur_tx = 0; @@ -631,7 +633,7 @@ alloc_list (struct net_device *dev) static int start_xmit (struct sk_buff *skb, struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); struct netdev_desc *txdesc; unsigned entry; u32 ioaddr; @@ -711,7 +713,7 @@ rio_interrupt (int irq, void *dev_instan int handled = 0; ioaddr = dev->base_addr; - np = dev->priv; + np = netdev_priv(dev); while (1) { int_status = readw (ioaddr + IntStatus); writew (int_status, ioaddr + IntStatus); @@ -745,7 +747,7 @@ rio_interrupt (int irq, void *dev_instan static void rio_free_tx (struct net_device *dev, int irq) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int entry = np->old_tx % TX_RING_SIZE; int tx_use = 0; unsigned long flag = 0; @@ -798,7 +800,7 @@ tx_error (struct net_device *dev, int tx int frame_id; int i; - np = dev->priv; + np = netdev_priv(dev); frame_id = (tx_status & 0xffff0000); printk (KERN_ERR "%s: Transmit error, TxStatus %4.4x, FrameId %d.\n", @@ -855,7 +857,7 @@ tx_error (struct net_device *dev, int tx static int receive_packet (struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int entry = np->cur_rx % RX_RING_SIZE; int cnt = 30; @@ -965,7 +967,7 @@ static void rio_error (struct net_device *dev, int int_status) { long ioaddr = dev->base_addr; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); u16 macctrl; /* Link change event */ @@ -1016,7 +1018,7 @@ static struct net_device_stats * get_stats (struct net_device *dev) { long ioaddr = dev->base_addr; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); #ifdef MEM_MAPPING int i; #endif @@ -1132,7 +1134,7 @@ clear_stats (struct net_device *dev) int change_mtu (struct net_device *dev, int new_mtu) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int max = (np->jumbo) ? MAX_JUMBO : 1536; if ((new_mtu < 68) || (new_mtu > max)) { @@ -1150,7 +1152,7 @@ set_multicast (struct net_device *dev) long ioaddr = dev->base_addr; u32 hash_table[2]; u16 rx_mode = 0; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); hash_table[0] = hash_table[1] = 0; /* RxFlowcontrol DA: 01-80-C2-00-00-01. Hash index=0x39 */ @@ -1194,137 +1196,118 @@ set_multicast (struct net_device *dev) writew (rx_mode, ioaddr + ReceiveMode); } -static int -rio_ethtool_ioctl (struct net_device *dev, void __user *useraddr) +static void rio_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + struct netdev_private *np = netdev_priv(dev); + strcpy(info->driver, "DL2K"); + strcpy(info->version, DRV_VERSION); + strcpy(info->bus_info, pci_name(np->pdev)); +} + +static int rio_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - struct netdev_private *np = dev->priv; - u32 ethcmd; + struct netdev_private *np = netdev_priv(dev); + if (np->phy_media) { + /* fiber device */ + cmd->supported = SUPPORTED_Autoneg | SUPPORTED_FIBRE; + cmd->advertising= ADVERTISED_Autoneg | ADVERTISED_FIBRE; + cmd->port = PORT_FIBRE; + cmd->transceiver = XCVR_INTERNAL; + } else { + /* copper device */ + cmd->supported = SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half + | SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Full | + SUPPORTED_Autoneg | SUPPORTED_MII; + cmd->advertising = ADVERTISED_10baseT_Half | + ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full | ADVERTISED_1000baseT_Full| + ADVERTISED_Autoneg | ADVERTISED_MII; + cmd->port = PORT_MII; + cmd->transceiver = XCVR_INTERNAL; + } + if ( np->link_status ) { + cmd->speed = np->speed; + cmd->duplex = np->full_duplex ? DUPLEX_FULL : DUPLEX_HALF; + } else { + cmd->speed = -1; + cmd->duplex = -1; + } + if ( np->an_enable) + cmd->autoneg = AUTONEG_ENABLE; + else + cmd->autoneg = AUTONEG_DISABLE; - if (copy_from_user (ðcmd, useraddr, sizeof (ethcmd))) - return -EFAULT; - switch (ethcmd) { - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; - strcpy(info.driver, "DL2K"); - strcpy(info.version, DRV_VERSION); - strcpy(info.bus_info, pci_name(np->pdev)); - memset(&info.fw_version, 0, sizeof(info.fw_version)); - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; + cmd->phy_address = np->phy_addr; + return 0; +} + +static int rio_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct netdev_private *np = netdev_priv(dev); + netif_carrier_off(dev); + if (cmd->autoneg == AUTONEG_ENABLE) { + if (np->an_enable) return 0; + else { + np->an_enable = 1; + mii_set_media(dev); + return 0; } - - case ETHTOOL_GSET: { - struct ethtool_cmd cmd = { ETHTOOL_GSET }; - if (np->phy_media) { - /* fiber device */ - cmd.supported = SUPPORTED_Autoneg | - SUPPORTED_FIBRE; - cmd.advertising= ADVERTISED_Autoneg | - ADVERTISED_FIBRE; - cmd.port = PORT_FIBRE; - cmd.transceiver = XCVR_INTERNAL; - } else { - /* copper device */ - cmd.supported = SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half - | SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Full | - SUPPORTED_Autoneg | SUPPORTED_MII; - cmd.advertising = ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full | ADVERTISED_1000baseT_Full| - ADVERTISED_Autoneg | ADVERTISED_MII; - cmd.port = PORT_MII; - cmd.transceiver = XCVR_INTERNAL; - } - if ( np->link_status ) { - cmd.speed = np->speed; - cmd.duplex = np->full_duplex ? - DUPLEX_FULL : DUPLEX_HALF; - } else { - cmd.speed = -1; - cmd.duplex = -1; - } - if ( np->an_enable) - cmd.autoneg = AUTONEG_ENABLE; - else - cmd.autoneg = AUTONEG_DISABLE; - - cmd.phy_address = np->phy_addr; - - if (copy_to_user(useraddr, &cmd, - sizeof(cmd))) - return -EFAULT; - return 0; - } - case ETHTOOL_SSET: { - struct ethtool_cmd cmd; - if (copy_from_user(&cmd, useraddr, sizeof(cmd))) - return -EFAULT; - netif_carrier_off(dev); - if (cmd.autoneg == AUTONEG_ENABLE) { - if (np->an_enable) - return 0; - else { - np->an_enable = 1; - mii_set_media(dev); - return 0; - } - } else { - np->an_enable = 0; - if (np->speed == 1000){ - cmd.speed = SPEED_100; - cmd.duplex = DUPLEX_FULL; - printk("Warning!! Can't disable Auto negotiation in 1000Mbps, change to Manul 100Mbps, Full duplex.\n"); - } - switch(cmd.speed + cmd.duplex){ - - case SPEED_10 + DUPLEX_HALF: - np->speed = 10; - np->full_duplex = 0; - break; - - case SPEED_10 + DUPLEX_FULL: - np->speed = 10; - np->full_duplex = 1; - break; - case SPEED_100 + DUPLEX_HALF: - np->speed = 100; - np->full_duplex = 0; - break; - case SPEED_100 + DUPLEX_FULL: - np->speed = 100; - np->full_duplex = 1; - break; - case SPEED_1000 + DUPLEX_HALF:/* not supported */ - case SPEED_1000 + DUPLEX_FULL:/* not supported */ - default: - return -EINVAL; - } - mii_set_media(dev); - } - return 0; + } else { + np->an_enable = 0; + if (np->speed == 1000) { + cmd->speed = SPEED_100; + cmd->duplex = DUPLEX_FULL; + printk("Warning!! Can't disable Auto negotiation in 1000Mbps, change to Manual 100Mbps, Full duplex.\n"); } -#ifdef ETHTOOL_GLINK - case ETHTOOL_GLINK:{ - struct ethtool_value link = { ETHTOOL_GLINK }; - link.data = np->link_status; - if (copy_to_user(useraddr, &link, sizeof(link))) - return -EFAULT; - return 0; - } -#endif + switch(cmd->speed + cmd->duplex) { + + case SPEED_10 + DUPLEX_HALF: + np->speed = 10; + np->full_duplex = 0; + break; + + case SPEED_10 + DUPLEX_FULL: + np->speed = 10; + np->full_duplex = 1; + break; + case SPEED_100 + DUPLEX_HALF: + np->speed = 100; + np->full_duplex = 0; + break; + case SPEED_100 + DUPLEX_FULL: + np->speed = 100; + np->full_duplex = 1; + break; + case SPEED_1000 + DUPLEX_HALF:/* not supported */ + case SPEED_1000 + DUPLEX_FULL:/* not supported */ default: - return -EOPNOTSUPP; - } + return -EINVAL; + } + mii_set_media(dev); + } + return 0; +} + +static u32 rio_get_link(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + return np->link_status; } +static struct ethtool_ops ethtool_ops = { + .get_drvinfo = rio_get_drvinfo, + .get_settings = rio_get_settings, + .set_settings = rio_set_settings, + .get_link = rio_get_link, +}; static int rio_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) { int phy_addr; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); struct mii_data *miidata = (struct mii_data *) &rq->ifr_ifru; struct netdev_desc *desc; @@ -1332,8 +1315,6 @@ rio_ioctl (struct net_device *dev, struc phy_addr = np->phy_addr; switch (cmd) { - case SIOCETHTOOL: - return rio_ethtool_ioctl(dev, rq->ifr_data); case SIOCDEVPRIVATE: break; @@ -1490,7 +1471,7 @@ mii_wait_link (struct net_device *dev, i int phy_addr; struct netdev_private *np; - np = dev->priv; + np = netdev_priv(dev); phy_addr = np->phy_addr; do { @@ -1512,7 +1493,7 @@ mii_get_media (struct net_device *dev) int phy_addr; struct netdev_private *np; - np = dev->priv; + np = netdev_priv(dev); phy_addr = np->phy_addr; bmsr.image = mii_read (dev, phy_addr, MII_BMSR); @@ -1594,7 +1575,7 @@ mii_set_media (struct net_device *dev) ANAR_t anar; int phy_addr; struct netdev_private *np; - np = dev->priv; + np = netdev_priv(dev); phy_addr = np->phy_addr; /* Does user set speed? */ @@ -1684,7 +1665,7 @@ mii_get_media_pcs (struct net_device *de int phy_addr; struct netdev_private *np; - np = dev->priv; + np = netdev_priv(dev); phy_addr = np->phy_addr; bmsr.image = mii_read (dev, phy_addr, PCS_BMSR); @@ -1740,7 +1721,7 @@ mii_set_media_pcs (struct net_device *de ANAR_PCS_t anar; int phy_addr; struct netdev_private *np; - np = dev->priv; + np = netdev_priv(dev); phy_addr = np->phy_addr; /* Auto-Negotiation? */ @@ -1794,7 +1775,7 @@ static int rio_close (struct net_device *dev) { long ioaddr = dev->base_addr; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); struct sk_buff *skb; int i; @@ -1840,7 +1821,7 @@ rio_remove1 (struct pci_dev *pdev) struct net_device *dev = pci_get_drvdata (pdev); if (dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); unregister_netdev (dev); pci_free_consistent (pdev, RX_TOTAL_SIZE, np->rx_ring, diff -puN drivers/net/eepro100.c~bk-netdev drivers/net/eepro100.c --- 25/drivers/net/eepro100.c~bk-netdev 2004-09-15 21:06:53.265646112 -0700 +++ 25-akpm/drivers/net/eepro100.c 2004-09-15 21:06:53.382628328 -0700 @@ -541,6 +541,7 @@ static struct net_device_stats *speedo_g static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static void set_rx_mode(struct net_device *dev); static void speedo_show_state(struct net_device *dev); +static struct ethtool_ops ethtool_ops; @@ -895,6 +896,7 @@ static int __devinit speedo_found1(struc dev->get_stats = &speedo_get_stats; dev->set_multicast_list = &set_rx_mode; dev->do_ioctl = &speedo_ioctl; + SET_ETHTOOL_OPS(dev, ðtool_ops); #ifdef CONFIG_NET_POLL_CONTROLLER dev->poll_controller = &poll_speedo; #endif @@ -2010,82 +2012,68 @@ speedo_get_stats(struct net_device *dev) return &sp->stats; } -static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr) +static void speedo_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - u32 ethcmd; struct speedo_private *sp = netdev_priv(dev); - - if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) - return -EFAULT; - - switch (ethcmd) { - /* get driver-specific version/etc. info */ - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; - strncpy(info.driver, "eepro100", sizeof(info.driver)-1); - strncpy(info.version, version, sizeof(info.version)-1); - if (sp && sp->pdev) - strcpy(info.bus_info, pci_name(sp->pdev)); - 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(&sp->lock); - mii_ethtool_gset(&sp->mii_if, &ecmd); - spin_unlock_irq(&sp->lock); - if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) - return -EFAULT; - 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(&sp->lock); - r = mii_ethtool_sset(&sp->mii_if, &ecmd); - spin_unlock_irq(&sp->lock); - return r; - } - /* restart autonegotiation */ - case ETHTOOL_NWAY_RST: { - return mii_nway_restart(&sp->mii_if); - } - /* get link status */ - case ETHTOOL_GLINK: { - struct ethtool_value edata = {ETHTOOL_GLINK}; - edata.data = mii_link_ok(&sp->mii_if); - 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 = sp->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; - sp->msg_enable = edata.data; - return 0; - } + strncpy(info->driver, "eepro100", sizeof(info->driver)-1); + strncpy(info->version, version, sizeof(info->version)-1); + if (sp->pdev) + strcpy(info->bus_info, pci_name(sp->pdev)); +} - } - - return -EOPNOTSUPP; +static int speedo_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct speedo_private *sp = netdev_priv(dev); + spin_lock_irq(&sp->lock); + mii_ethtool_gset(&sp->mii_if, ecmd); + spin_unlock_irq(&sp->lock); + return 0; +} + +static int speedo_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct speedo_private *sp = netdev_priv(dev); + int res; + spin_lock_irq(&sp->lock); + res = mii_ethtool_sset(&sp->mii_if, ecmd); + spin_unlock_irq(&sp->lock); + return res; +} + +static int speedo_nway_reset(struct net_device *dev) +{ + struct speedo_private *sp = netdev_priv(dev); + return mii_nway_restart(&sp->mii_if); +} + +static u32 speedo_get_link(struct net_device *dev) +{ + struct speedo_private *sp = netdev_priv(dev); + return mii_link_ok(&sp->mii_if); } +static u32 speedo_get_msglevel(struct net_device *dev) +{ + struct speedo_private *sp = netdev_priv(dev); + return sp->msg_enable; +} + +static void speedo_set_msglevel(struct net_device *dev, u32 v) +{ + struct speedo_private *sp = netdev_priv(dev); + sp->msg_enable = v; +} + +static struct ethtool_ops ethtool_ops = { + .get_drvinfo = speedo_get_drvinfo, + .get_settings = speedo_get_settings, + .set_settings = speedo_set_settings, + .nway_reset = speedo_nway_reset, + .get_link = speedo_get_link, + .get_msglevel = speedo_get_msglevel, + .set_msglevel = speedo_set_msglevel, +}; + static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { struct speedo_private *sp = netdev_priv(dev); @@ -2121,8 +2109,6 @@ static int speedo_ioctl(struct net_devic add_timer(&sp->timer); /* may be set to the past --SAW */ pci_set_power_state(sp->pdev, saved_acpi); return 0; - case SIOCETHTOOL: - return netdev_ethtool_ioctl(dev, rq->ifr_data); default: return -EOPNOTSUPP; } diff -puN drivers/net/ewrk3.c~bk-netdev drivers/net/ewrk3.c --- 25/drivers/net/ewrk3.c~bk-netdev 2004-09-15 21:06:53.266645960 -0700 +++ 25-akpm/drivers/net/ewrk3.c 2004-09-15 21:06:53.386627720 -0700 @@ -305,6 +305,8 @@ static int ewrk3_close(struct net_device static struct net_device_stats *ewrk3_get_stats(struct net_device *dev); static void set_multicast_list(struct net_device *dev); static int ewrk3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); +static struct ethtool_ops ethtool_ops_203; +static struct ethtool_ops ethtool_ops; /* ** Private functions @@ -532,7 +534,7 @@ ewrk3_hw_init(struct net_device *dev, u_ printk(" is in I/O only mode"); } - lp = (struct ewrk3_private *) dev->priv; + lp = netdev_priv(dev); lp->shmem_base = mem_start; lp->shmem_length = shmem_length; lp->lemac = lemac; @@ -610,6 +612,10 @@ ewrk3_hw_init(struct net_device *dev, u_ dev->get_stats = ewrk3_get_stats; dev->set_multicast_list = set_multicast_list; dev->do_ioctl = ewrk3_ioctl; + if (lp->adapter_name[4] == '3') + SET_ETHTOOL_OPS(dev, ðtool_ops_203); + else + SET_ETHTOOL_OPS(dev, ðtool_ops); dev->tx_timeout = ewrk3_timeout; dev->watchdog_timeo = QUEUE_PKT_TIMEOUT; @@ -621,7 +627,7 @@ ewrk3_hw_init(struct net_device *dev, u_ static int ewrk3_open(struct net_device *dev) { - struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv; + struct ewrk3_private *lp = netdev_priv(dev); u_long iobase = dev->base_addr; int i, status = 0; u_char icr, csr; @@ -684,7 +690,7 @@ static int ewrk3_open(struct net_device */ static void ewrk3_init(struct net_device *dev) { - struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv; + struct ewrk3_private *lp = netdev_priv(dev); u_char csr, page; u_long iobase = dev->base_addr; int i; @@ -725,7 +731,7 @@ static void ewrk3_init(struct net_device static void ewrk3_timeout(struct net_device *dev) { - struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv; + struct ewrk3_private *lp = netdev_priv(dev); u_char icr, csr; u_long iobase = dev->base_addr; @@ -761,7 +767,7 @@ static void ewrk3_timeout(struct net_dev */ static int ewrk3_queue_pkt (struct sk_buff *skb, struct net_device *dev) { - struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv; + struct ewrk3_private *lp = netdev_priv(dev); u_long iobase = dev->base_addr; u_long buf = 0; u_char icr; @@ -883,7 +889,7 @@ static irqreturn_t ewrk3_interrupt(int i u_long iobase; u_char icr, cr, csr; - lp = (struct ewrk3_private *) dev->priv; + lp = netdev_priv(dev); iobase = dev->base_addr; /* get the interrupt information */ @@ -931,7 +937,7 @@ static irqreturn_t ewrk3_interrupt(int i /* Called with lp->hw_lock held */ static int ewrk3_rx(struct net_device *dev) { - struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv; + struct ewrk3_private *lp = netdev_priv(dev); u_long iobase = dev->base_addr; int i, status = 0; u_char page; @@ -1059,7 +1065,7 @@ static int ewrk3_rx(struct net_device *d */ static int ewrk3_tx(struct net_device *dev) { - struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv; + struct ewrk3_private *lp = netdev_priv(dev); u_long iobase = dev->base_addr; u_char tx_status; @@ -1095,7 +1101,7 @@ static int ewrk3_tx(struct net_device *d static int ewrk3_close(struct net_device *dev) { - struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv; + struct ewrk3_private *lp = netdev_priv(dev); u_long iobase = dev->base_addr; u_char icr, csr; @@ -1130,7 +1136,7 @@ static int ewrk3_close(struct net_device static struct net_device_stats *ewrk3_get_stats(struct net_device *dev) { - struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv; + struct ewrk3_private *lp = netdev_priv(dev); /* Null body since there is no framing error counter */ return &lp->stats; @@ -1141,7 +1147,7 @@ static struct net_device_stats *ewrk3_ge */ static void set_multicast_list(struct net_device *dev) { - struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv; + struct ewrk3_private *lp = netdev_priv(dev); u_long iobase = dev->base_addr; u_char csr; @@ -1174,7 +1180,7 @@ static void set_multicast_list(struct ne */ static void SetMulticastFilter(struct net_device *dev) { - struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv; + struct ewrk3_private *lp = netdev_priv(dev); struct dev_mc_list *dmi = dev->mc_list; u_long iobase = dev->base_addr; int i; @@ -1520,187 +1526,165 @@ static int __init EISA_signature(char *n return status; /* return the device name string */ } -static int ewrk3_ethtool_ioctl(struct net_device *dev, void __user *useraddr) +static void ewrk3_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv; - u_long iobase = dev->base_addr; - u32 ethcmd; - - if (get_user(ethcmd, (u32 __user *)useraddr)) - return -EFAULT; - - switch (ethcmd) { - - /* Get driver info */ - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; - int fwrev = Read_EEPROM(dev->base_addr, EEPROM_REVLVL); - - strcpy(info.driver, DRV_NAME); - strcpy(info.version, DRV_VERSION); - sprintf(info.fw_version, "%d", fwrev); - strcpy(info.bus_info, "N/A"); - info.eedump_len = EEPROM_MAX; - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; - } - - /* Get settings */ - case ETHTOOL_GSET: { - struct ethtool_cmd ecmd = { ETHTOOL_GSET }; - u_char cr = inb(EWRK3_CR); - - switch (lp->adapter_name[4]) { - case '3': /* DE203 */ - ecmd.supported = SUPPORTED_BNC; - ecmd.port = PORT_BNC; - break; - - case '4': /* DE204 */ - ecmd.supported = SUPPORTED_TP; - ecmd.port = PORT_TP; - break; - - case '5': /* DE205 */ - ecmd.supported = SUPPORTED_TP | SUPPORTED_BNC | SUPPORTED_AUI; - ecmd.autoneg = !(cr & CR_APD); - /* - ** Port is only valid if autoneg is disabled - ** and even then we don't know if AUI is jumpered. - */ - if (!ecmd.autoneg) - ecmd.port = (cr & CR_PSEL) ? PORT_BNC : PORT_TP; - break; - } + int fwrev = Read_EEPROM(dev->base_addr, EEPROM_REVLVL); - ecmd.supported |= SUPPORTED_10baseT_Half; - ecmd.speed = SPEED_10; - ecmd.duplex = DUPLEX_HALF; - - if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; - } - - /* Set settings */ - case ETHTOOL_SSET: { - struct ethtool_cmd ecmd; - u_char cr; - u_long flags; - - /* DE205 is the only card with anything to set */ - if (lp->adapter_name[4] != '5') - return -EOPNOTSUPP; - - if (copy_from_user(&ecmd, useraddr, sizeof(ecmd))) - return -EFAULT; - - /* Sanity-check parameters */ - if (ecmd.speed != SPEED_10) - return -EINVAL; - if (ecmd.port != PORT_TP && ecmd.port != PORT_BNC) - return -EINVAL; /* AUI is not software-selectable */ - if (ecmd.transceiver != XCVR_INTERNAL) - return -EINVAL; - if (ecmd.duplex != DUPLEX_HALF) - return -EINVAL; - if (ecmd.phy_address != 0) - return -EINVAL; + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); + sprintf(info->fw_version, "%d", fwrev); + strcpy(info->bus_info, "N/A"); + info->eedump_len = EEPROM_MAX; +} - spin_lock_irqsave(&lp->hw_lock, flags); - cr = inb(EWRK3_CR); +static int ewrk3_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct ewrk3_private *lp = netdev_priv(dev); + unsigned long iobase = dev->base_addr; + u8 cr = inb(EWRK3_CR); - /* If Autoneg is set, change to Auto Port mode */ - /* Otherwise, disable Auto Port and set port explicitly */ - if (ecmd.autoneg) { - cr &= ~CR_APD; - } else { - cr |= CR_APD; - if (ecmd.port == PORT_TP) - cr &= ~CR_PSEL; /* Force TP */ - else - cr |= CR_PSEL; /* Force BNC */ - } + switch (lp->adapter_name[4]) { + case '3': /* DE203 */ + ecmd->supported = SUPPORTED_BNC; + ecmd->port = PORT_BNC; + break; - /* Commit the changes */ - outb(cr, EWRK3_CR); + case '4': /* DE204 */ + ecmd->supported = SUPPORTED_TP; + ecmd->port = PORT_TP; + break; - spin_unlock_irqrestore(&lp->hw_lock, flags); - if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; + case '5': /* DE205 */ + ecmd->supported = SUPPORTED_TP | SUPPORTED_BNC | SUPPORTED_AUI; + ecmd->autoneg = !(cr & CR_APD); + /* + ** Port is only valid if autoneg is disabled + ** and even then we don't know if AUI is jumpered. + */ + if (!ecmd->autoneg) + ecmd->port = (cr & CR_PSEL) ? PORT_BNC : PORT_TP; + break; } - /* Get link status */ - case ETHTOOL_GLINK: { - struct ethtool_value edata = { ETHTOOL_GLINK }; - u_char cmr = inb(EWRK3_CMR); + ecmd->supported |= SUPPORTED_10baseT_Half; + ecmd->speed = SPEED_10; + ecmd->duplex = DUPLEX_HALF; + return 0; +} - /* DE203 has BNC only and link status does not apply */ - if (lp->adapter_name[4] == '3') - return -EOPNOTSUPP; +static int ewrk3_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct ewrk3_private *lp = netdev_priv(dev); + unsigned long iobase = dev->base_addr; + unsigned long flags; + u8 cr; - /* On DE204 this is always valid since TP is the only port. */ - /* On DE205 this reflects TP status even if BNC or AUI is selected. */ - edata.data = !(cmr & CMR_LINK); + /* DE205 is the only card with anything to set */ + if (lp->adapter_name[4] != '5') + return -EOPNOTSUPP; - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } + /* Sanity-check parameters */ + if (ecmd->speed != SPEED_10) + return -EINVAL; + if (ecmd->port != PORT_TP && ecmd->port != PORT_BNC) + return -EINVAL; /* AUI is not software-selectable */ + if (ecmd->transceiver != XCVR_INTERNAL) + return -EINVAL; + if (ecmd->duplex != DUPLEX_HALF) + return -EINVAL; + if (ecmd->phy_address != 0) + return -EINVAL; - /* Blink LED for identification */ - case ETHTOOL_PHYS_ID: { - struct ethtool_value edata; - u_long flags; - u_char cr; - int count; + spin_lock_irqsave(&lp->hw_lock, flags); + cr = inb(EWRK3_CR); - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; + /* If Autoneg is set, change to Auto Port mode */ + /* Otherwise, disable Auto Port and set port explicitly */ + if (ecmd->autoneg) { + cr &= ~CR_APD; + } else { + cr |= CR_APD; + if (ecmd->port == PORT_TP) + cr &= ~CR_PSEL; /* Force TP */ + else + cr |= CR_PSEL; /* Force BNC */ + } - /* Toggle LED 4x per second */ - count = edata.data << 2; + /* Commit the changes */ + outb(cr, EWRK3_CR); + spin_unlock_irqrestore(&lp->hw_lock, flags); + return 0; +} - spin_lock_irqsave(&lp->hw_lock, flags); +static u32 ewrk3_get_link(struct net_device *dev) +{ + unsigned long iobase = dev->base_addr; + u8 cmr = inb(EWRK3_CMR); + /* DE203 has BNC only and link status does not apply */ + /* On DE204 this is always valid since TP is the only port. */ + /* On DE205 this reflects TP status even if BNC or AUI is selected. */ + return !(cmr & CMR_LINK); +} - /* Bail if a PHYS_ID is already in progress */ - if (lp->led_mask == 0) { - spin_unlock_irqrestore(&lp->hw_lock, flags); - return -EBUSY; - } +static int ewrk3_phys_id(struct net_device *dev, u32 data) +{ + struct ewrk3_private *lp = netdev_priv(dev); + unsigned long iobase = dev->base_addr; + unsigned long flags; + u8 cr; + int count; - /* Prevent ISR from twiddling the LED */ - lp->led_mask = 0; + /* Toggle LED 4x per second */ + count = data << 2; - while (count--) { - /* Toggle the LED */ - cr = inb(EWRK3_CR); - outb(cr ^ CR_LED, EWRK3_CR); + spin_lock_irqsave(&lp->hw_lock, flags); - /* Wait a little while */ - spin_unlock_irqrestore(&lp->hw_lock, flags); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ>>2); - spin_lock_irqsave(&lp->hw_lock, flags); + /* Bail if a PHYS_ID is already in progress */ + if (lp->led_mask == 0) { + spin_unlock_irqrestore(&lp->hw_lock, flags); + return -EBUSY; + } - /* Exit if we got a signal */ - if (signal_pending(current)) - break; - } + /* Prevent ISR from twiddling the LED */ + lp->led_mask = 0; - lp->led_mask = CR_LED; + while (count--) { + /* Toggle the LED */ cr = inb(EWRK3_CR); - outb(cr & ~CR_LED, EWRK3_CR); + outb(cr ^ CR_LED, EWRK3_CR); + + /* Wait a little while */ spin_unlock_irqrestore(&lp->hw_lock, flags); - return signal_pending(current) ? -ERESTARTSYS : 0; - } + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ>>2); + spin_lock_irqsave(&lp->hw_lock, flags); + /* Exit if we got a signal */ + if (signal_pending(current)) + break; } - return -EOPNOTSUPP; -} + lp->led_mask = CR_LED; + cr = inb(EWRK3_CR); + outb(cr & ~CR_LED, EWRK3_CR); + spin_unlock_irqrestore(&lp->hw_lock, flags); + return signal_pending(current) ? -ERESTARTSYS : 0; +} + +static struct ethtool_ops ethtool_ops_203 = { + .get_drvinfo = ewrk3_get_drvinfo, + .get_settings = ewrk3_get_settings, + .set_settings = ewrk3_set_settings, + .phys_id = ewrk3_phys_id, +}; + +static struct ethtool_ops ethtool_ops = { + .get_drvinfo = ewrk3_get_drvinfo, + .get_settings = ewrk3_get_settings, + .set_settings = ewrk3_set_settings, + .get_link = ewrk3_get_link, + .phys_id = ewrk3_phys_id, +}; /* ** Perform IOCTL call functions here. Some are privileged operations and the @@ -1708,7 +1692,7 @@ static int ewrk3_ethtool_ioctl(struct ne */ static int ewrk3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { - struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv; + struct ewrk3_private *lp = netdev_priv(dev); struct ewrk3_ioctl *ioc = (struct ewrk3_ioctl *) &rq->ifr_ifru; u_long iobase = dev->base_addr; int i, j, status = 0; @@ -1721,11 +1705,7 @@ static int ewrk3_ioctl(struct net_device union ewrk3_addr *tmp; - /* ethtool IOCTLs are handled elsewhere */ - if (cmd == SIOCETHTOOL) - return ewrk3_ethtool_ioctl(dev, rq->ifr_data); - - /* Other than ethtool, all we handle are private IOCTLs */ + /* All we handle are private IOCTLs */ if (cmd != EWRK3IOCTL) return -EOPNOTSUPP; diff -puN drivers/net/forcedeth.c~bk-netdev drivers/net/forcedeth.c --- 25/drivers/net/forcedeth.c~bk-netdev 2004-09-15 21:06:53.268645656 -0700 +++ 25-akpm/drivers/net/forcedeth.c 2004-09-15 21:06:53.388627416 -0700 @@ -748,91 +748,50 @@ static struct net_device_stats *nv_get_s return &np->stats; } -static int nv_ethtool_ioctl(struct net_device *dev, void __user *useraddr) +static void nv_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { struct fe_priv *np = get_nvpriv(dev); - u8 *base = get_hwbase(dev); - u32 ethcmd; - - if (copy_from_user(ðcmd, useraddr, sizeof (ethcmd))) - return -EFAULT; - - switch (ethcmd) { - case ETHTOOL_GDRVINFO: - { - struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; - strcpy(info.driver, "forcedeth"); - strcpy(info.version, FORCEDETH_VERSION); - strcpy(info.bus_info, pci_name(np->pci_dev)); - if (copy_to_user(useraddr, &info, sizeof (info))) - return -EFAULT; - return 0; - } - case ETHTOOL_GLINK: - { - struct ethtool_value edata = { ETHTOOL_GLINK }; - - edata.data = !!netif_carrier_ok(dev); - - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - case ETHTOOL_GWOL: - { - struct ethtool_wolinfo wolinfo; - memset(&wolinfo, 0, sizeof(wolinfo)); - wolinfo.supported = WAKE_MAGIC; - - spin_lock_irq(&np->lock); - if (np->wolenabled) - wolinfo.wolopts = WAKE_MAGIC; - spin_unlock_irq(&np->lock); - - if (copy_to_user(useraddr, &wolinfo, sizeof(wolinfo))) - return -EFAULT; - return 0; - } - case ETHTOOL_SWOL: - { - struct ethtool_wolinfo wolinfo; - if (copy_from_user(&wolinfo, useraddr, sizeof(wolinfo))) - return -EFAULT; - - spin_lock_irq(&np->lock); - if (wolinfo.wolopts == 0) { - writel(0, base + NvRegWakeUpFlags); - np->wolenabled = 0; - } - if (wolinfo.wolopts & WAKE_MAGIC) { - writel(NVREG_WAKEUPFLAGS_ENABLE, base + NvRegWakeUpFlags); - np->wolenabled = 1; - } - spin_unlock_irq(&np->lock); - return 0; - } + strcpy(info->driver, "forcedeth"); + strcpy(info->version, FORCEDETH_VERSION); + strcpy(info->bus_info, pci_name(np->pci_dev)); +} - default: - break; - } +static void nv_get_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo) +{ + struct fe_priv *np = get_nvpriv(dev); + wolinfo->supported = WAKE_MAGIC; - return -EOPNOTSUPP; + spin_lock_irq(&np->lock); + if (np->wolenabled) + wolinfo->wolopts = WAKE_MAGIC; + spin_unlock_irq(&np->lock); } -/* - * nv_ioctl: dev->do_ioctl function - * Called with rtnl_lock held. - */ -static int nv_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) + +static int nv_set_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo) { - switch(cmd) { - case SIOCETHTOOL: - return nv_ethtool_ioctl(dev, rq->ifr_data); + struct fe_priv *np = get_nvpriv(dev); + u8 *base = get_hwbase(dev); - default: - return -EOPNOTSUPP; + spin_lock_irq(&np->lock); + if (wolinfo->wolopts == 0) { + writel(0, base + NvRegWakeUpFlags); + np->wolenabled = 0; + } + if (wolinfo->wolopts & WAKE_MAGIC) { + writel(NVREG_WAKEUPFLAGS_ENABLE, base + NvRegWakeUpFlags); + np->wolenabled = 1; } + spin_unlock_irq(&np->lock); + return 0; } +static struct ethtool_ops ops = { + .get_drvinfo = nv_get_drvinfo, + .get_link = ethtool_op_get_link, + .get_wol = nv_get_wol, + .set_wol = nv_set_wol, +}; + /* * nv_alloc_rx: fill rx ring entries. * Return 1 if the allocations for the skbs failed and the @@ -1777,7 +1736,7 @@ static int __devinit nv_probe(struct pci dev->get_stats = nv_get_stats; dev->change_mtu = nv_change_mtu; dev->set_multicast_list = nv_set_multicast; - dev->do_ioctl = nv_ioctl; + SET_ETHTOOL_OPS(dev, &ops); dev->tx_timeout = nv_tx_timeout; dev->watchdog_timeo = NV_WATCHDOG_TIMEO; diff -puN drivers/net/hamachi.c~bk-netdev drivers/net/hamachi.c --- 25/drivers/net/hamachi.c~bk-netdev 2004-09-15 21:06:53.270645352 -0700 +++ 25-akpm/drivers/net/hamachi.c 2004-09-15 21:06:53.391626960 -0700 @@ -565,7 +565,8 @@ static void hamachi_error(struct net_dev static int hamachi_close(struct net_device *dev); static struct net_device_stats *hamachi_get_stats(struct net_device *dev); static void set_rx_mode(struct net_device *dev); - +static struct ethtool_ops ethtool_ops; +static struct ethtool_ops ethtool_ops_no_mii; static int __devinit hamachi_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) @@ -631,7 +632,7 @@ static int __devinit hamachi_init_one (s read_eeprom(ioaddr, i), i % 16 != 15 ? " " : "\n"); #endif - hmp = dev->priv; + hmp = netdev_priv(dev); spin_lock_init(&hmp->lock); hmp->mii_if.dev = dev; @@ -725,6 +726,10 @@ static int __devinit hamachi_init_one (s dev->get_stats = &hamachi_get_stats; dev->set_multicast_list = &set_rx_mode; dev->do_ioctl = &netdev_ioctl; + if (chip_tbl[hmp->chip_id].flags & CanHaveMII) + SET_ETHTOOL_OPS(dev, ðtool_ops); + else + SET_ETHTOOL_OPS(dev, ðtool_ops_no_mii); dev->tx_timeout = &hamachi_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; if (mtu) @@ -851,7 +856,7 @@ static void mdio_write(struct net_device static int hamachi_open(struct net_device *dev) { - struct hamachi_private *hmp = dev->priv; + struct hamachi_private *hmp = netdev_priv(dev); long ioaddr = dev->base_addr; int i; u32 rx_int_var, tx_int_var; @@ -1000,7 +1005,7 @@ static int hamachi_open(struct net_devic static inline int hamachi_tx(struct net_device *dev) { - struct hamachi_private *hmp = dev->priv; + struct hamachi_private *hmp = netdev_priv(dev); /* Update the dirty pointer until we find an entry that is still owned by the card */ @@ -1032,7 +1037,7 @@ static inline int hamachi_tx(struct net_ static void hamachi_timer(unsigned long data) { struct net_device *dev = (struct net_device *)data; - struct hamachi_private *hmp = dev->priv; + struct hamachi_private *hmp = netdev_priv(dev); long ioaddr = dev->base_addr; int next_tick = 10*HZ; @@ -1057,7 +1062,7 @@ static void hamachi_timer(unsigned long static void hamachi_tx_timeout(struct net_device *dev) { int i; - struct hamachi_private *hmp = dev->priv; + struct hamachi_private *hmp = netdev_priv(dev); long ioaddr = dev->base_addr; printk(KERN_WARNING "%s: Hamachi transmit timed out, status %8.8x," @@ -1163,7 +1168,7 @@ static void hamachi_tx_timeout(struct ne /* Initialize the Rx and Tx rings, along with various 'dev' bits. */ static void hamachi_init_ring(struct net_device *dev) { - struct hamachi_private *hmp = dev->priv; + struct hamachi_private *hmp = netdev_priv(dev); int i; hmp->tx_full = 0; @@ -1255,7 +1260,7 @@ do { \ static int hamachi_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct hamachi_private *hmp = dev->priv; + struct hamachi_private *hmp = netdev_priv(dev); unsigned entry; u16 status; @@ -1383,7 +1388,7 @@ static irqreturn_t hamachi_interrupt(int #endif ioaddr = dev->base_addr; - hmp = dev->priv; + hmp = netdev_priv(dev); spin_lock(&hmp->lock); do { @@ -1477,7 +1482,7 @@ static irqreturn_t hamachi_interrupt(int for clarity and better register allocation. */ static int hamachi_rx(struct net_device *dev) { - struct hamachi_private *hmp = dev->priv; + struct hamachi_private *hmp = netdev_priv(dev); int entry = hmp->cur_rx % RX_RING_SIZE; int boguscnt = (hmp->dirty_rx + RX_RING_SIZE) - hmp->cur_rx; @@ -1693,7 +1698,7 @@ static int hamachi_rx(struct net_device static void hamachi_error(struct net_device *dev, int intr_status) { long ioaddr = dev->base_addr; - struct hamachi_private *hmp = dev->priv; + struct hamachi_private *hmp = netdev_priv(dev); if (intr_status & (LinkChange|NegotiationChange)) { if (hamachi_debug > 1) @@ -1727,7 +1732,7 @@ static void hamachi_error(struct net_dev static int hamachi_close(struct net_device *dev) { long ioaddr = dev->base_addr; - struct hamachi_private *hmp = dev->priv; + struct hamachi_private *hmp = netdev_priv(dev); struct sk_buff *skb; int i; @@ -1813,7 +1818,7 @@ static int hamachi_close(struct net_devi static struct net_device_stats *hamachi_get_stats(struct net_device *dev) { long ioaddr = dev->base_addr; - struct hamachi_private *hmp = dev->priv; + struct hamachi_private *hmp = netdev_priv(dev); /* We should lock this segment of code for SMP eventually, although the vulnerability window is very small and statistics are @@ -1867,84 +1872,76 @@ static void set_rx_mode(struct net_devic } } -static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr) +static int check_if_running(struct net_device *dev) { - struct hamachi_private *np = dev->priv; - u32 ethcmd; - - if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) - return -EFAULT; + if (!netif_running(dev)) + return -EINVAL; + return 0; +} - switch (ethcmd) { - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; - strcpy(info.driver, DRV_NAME); - strcpy(info.version, DRV_VERSION); - strcpy(info.bus_info, pci_name(np->pci_dev)); - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; - } +static void hamachi_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + struct hamachi_private *np = netdev_priv(dev); + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); + strcpy(info->bus_info, pci_name(np->pci_dev)); +} - /* get settings */ - case ETHTOOL_GSET: { - struct ethtool_cmd ecmd = { ETHTOOL_GSET }; - if (!(chip_tbl[np->chip_id].flags & CanHaveMII)) - return -EINVAL; - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii_if, &ecmd); - spin_unlock_irq(&np->lock); - if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; - } - /* set settings */ - case ETHTOOL_SSET: { - int r; - struct ethtool_cmd ecmd; - if (!(chip_tbl[np->chip_id].flags & CanHaveMII)) - return -EINVAL; - if (copy_from_user(&ecmd, useraddr, sizeof(ecmd))) - return -EFAULT; - spin_lock_irq(&np->lock); - r = mii_ethtool_sset(&np->mii_if, &ecmd); - spin_unlock_irq(&np->lock); - return r; - } - /* restart autonegotiation */ - case ETHTOOL_NWAY_RST: { - if (!(chip_tbl[np->chip_id].flags & CanHaveMII)) - return -EINVAL; - return mii_nway_restart(&np->mii_if); - } - /* get link status */ - case ETHTOOL_GLINK: { - struct ethtool_value edata = {ETHTOOL_GLINK}; - if (!(chip_tbl[np->chip_id].flags & CanHaveMII)) - return -EINVAL; - edata.data = mii_link_ok(&np->mii_if); - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - } - - return -EOPNOTSUPP; +static int hamachi_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct hamachi_private *np = netdev_priv(dev); + spin_lock_irq(&np->lock); + mii_ethtool_gset(&np->mii_if, ecmd); + spin_unlock_irq(&np->lock); + return 0; +} + +static int hamachi_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct hamachi_private *np = netdev_priv(dev); + int res; + spin_lock_irq(&np->lock); + res = mii_ethtool_sset(&np->mii_if, ecmd); + spin_unlock_irq(&np->lock); + return res; +} + +static int hamachi_nway_reset(struct net_device *dev) +{ + struct hamachi_private *np = netdev_priv(dev); + return mii_nway_restart(&np->mii_if); } +static u32 hamachi_get_link(struct net_device *dev) +{ + struct hamachi_private *np = netdev_priv(dev); + return mii_link_ok(&np->mii_if); +} + +static struct ethtool_ops ethtool_ops = { + .begin = check_if_running, + .get_drvinfo = hamachi_get_drvinfo, + .get_settings = hamachi_get_settings, + .set_settings = hamachi_set_settings, + .nway_reset = hamachi_nway_reset, + .get_link = hamachi_get_link, +}; + +static struct ethtool_ops ethtool_ops_no_mii = { + .begin = check_if_running, + .get_drvinfo = hamachi_get_drvinfo, +}; + static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { - struct hamachi_private *np = dev->priv; + struct hamachi_private *np = netdev_priv(dev); struct mii_ioctl_data *data = if_mii(rq); int rc; if (!netif_running(dev)) return -EINVAL; - if (cmd == SIOCETHTOOL) - rc = netdev_ethtool_ioctl(dev, rq->ifr_data); - - else if (cmd == (SIOCDEVPRIVATE+3)) { /* set rx,tx intr params */ + if (cmd == (SIOCDEVPRIVATE+3)) { /* set rx,tx intr params */ u32 *d = (u32 *)&rq->ifr_ifru; /* Should add this check here or an ordinary user can do nasty * things. -KDU @@ -1976,7 +1973,7 @@ static void __devexit hamachi_remove_one struct net_device *dev = pci_get_drvdata(pdev); if (dev) { - struct hamachi_private *hmp = dev->priv; + struct hamachi_private *hmp = netdev_priv(dev); pci_free_consistent(pdev, RX_TOTAL_SIZE, hmp->rx_ring, hmp->rx_ring_dma); diff -puN drivers/net/ibmlana.c~bk-netdev drivers/net/ibmlana.c --- 25/drivers/net/ibmlana.c~bk-netdev 2004-09-15 21:06:53.271645200 -0700 +++ 25-akpm/drivers/net/ibmlana.c 2004-09-15 21:06:53.392626808 -0700 @@ -885,14 +885,6 @@ static struct net_device_stats *ibmlana_ return &priv->stat; } -/* we don't support runtime reconfiguration, since am MCA card can - be unambigously identified by its POS registers. */ - -static int ibmlana_config(struct net_device *dev, struct ifmap *map) -{ - return 0; -} - /* switch receiver mode. */ static void ibmlana_set_multicast_list(struct net_device *dev) @@ -984,7 +976,6 @@ static int ibmlana_probe(struct net_devi dev->open = ibmlana_open; dev->stop = ibmlana_close; - dev->set_config = ibmlana_config; dev->hard_start_xmit = ibmlana_tx; dev->do_ioctl = NULL; dev->get_stats = ibmlana_stats; diff -puN drivers/net/iseries_veth.c~bk-netdev drivers/net/iseries_veth.c --- 25/drivers/net/iseries_veth.c~bk-netdev 2004-09-15 21:06:53.273644896 -0700 +++ 25-akpm/drivers/net/iseries_veth.c 2004-09-15 21:06:53.393626656 -0700 @@ -747,60 +747,41 @@ static void veth_set_multicast_list(stru write_unlock_irqrestore(&port->mcast_gate, flags); } -static int veth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +static void veth_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { -#ifdef SIOCETHTOOL - struct ethtool_cmd ecmd; - - if (cmd != SIOCETHTOOL) - return -EOPNOTSUPP; - if (copy_from_user(&ecmd, ifr->ifr_data, sizeof (ecmd))) - return -EFAULT; - switch (ecmd.cmd) { - case ETHTOOL_GSET: - ecmd.supported = (SUPPORTED_1000baseT_Full - | SUPPORTED_Autoneg | SUPPORTED_FIBRE); - ecmd.advertising = (SUPPORTED_1000baseT_Full - | SUPPORTED_Autoneg | SUPPORTED_FIBRE); - - ecmd.port = PORT_FIBRE; - ecmd.transceiver = XCVR_INTERNAL; - ecmd.phy_address = 0; - ecmd.speed = SPEED_1000; - ecmd.duplex = DUPLEX_FULL; - ecmd.autoneg = AUTONEG_ENABLE; - ecmd.maxtxpkt = 120; - ecmd.maxrxpkt = 120; - if (copy_to_user(ifr->ifr_data, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; - - case ETHTOOL_GDRVINFO:{ - struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; - strncpy(info.driver, "veth", sizeof(info.driver) - 1); - info.driver[sizeof(info.driver) - 1] = '\0'; - strncpy(info.version, "1.0", sizeof(info.version) - 1); - if (copy_to_user(ifr->ifr_data, &info, sizeof(info))) - return -EFAULT; - return 0; - } - /* get link status */ - case ETHTOOL_GLINK:{ - struct ethtool_value edata = { ETHTOOL_GLINK }; - edata.data = 1; - if (copy_to_user(ifr->ifr_data, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - - default: - break; - } + strncpy(info->driver, "veth", sizeof(info->driver) - 1); + info->driver[sizeof(info->driver) - 1] = '\0'; + strncpy(info->version, "1.0", sizeof(info->version) - 1); +} + +static int veth_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + ecmd->supported = (SUPPORTED_1000baseT_Full + | SUPPORTED_Autoneg | SUPPORTED_FIBRE); + ecmd->advertising = (SUPPORTED_1000baseT_Full + | SUPPORTED_Autoneg | SUPPORTED_FIBRE); + ecmd->port = PORT_FIBRE; + ecmd->transceiver = XCVR_INTERNAL; + ecmd->phy_address = 0; + ecmd->speed = SPEED_1000; + ecmd->duplex = DUPLEX_FULL; + ecmd->autoneg = AUTONEG_ENABLE; + ecmd->maxtxpkt = 120; + ecmd->maxrxpkt = 120; + return 0; +} -#endif - return -EOPNOTSUPP; +static u32 veth_get_link(struct net_device *dev) +{ + return 1; } +static struct ethtool_ops ops = { + .get_drvinfo = veth_get_drvinfo, + .get_settings = veth_get_settings, + .get_link = veth_get_link, +}; + static void veth_tx_timeout(struct net_device *dev) { struct veth_port *port = (struct veth_port *)dev->priv; @@ -889,7 +870,7 @@ static struct net_device * __init veth_p dev->change_mtu = veth_change_mtu; dev->set_mac_address = NULL; dev->set_multicast_list = veth_set_multicast_list; - dev->do_ioctl = veth_ioctl; + SET_ETHTOOL_OPS(dev, &ops); dev->watchdog_timeo = 2 * (VETH_ACKTIMEOUT * HZ / 1000000); dev->tx_timeout = veth_tx_timeout; diff -puN drivers/net/ixgb/ixgb_ethtool.c~bk-netdev drivers/net/ixgb/ixgb_ethtool.c --- 25/drivers/net/ixgb/ixgb_ethtool.c~bk-netdev 2004-09-15 21:06:53.274644744 -0700 +++ 25-akpm/drivers/net/ixgb/ixgb_ethtool.c 2004-09-15 21:06:53.397626048 -0700 @@ -38,12 +38,6 @@ extern char ixgb_driver_version[]; extern int ixgb_up(struct ixgb_adapter *adapter); extern void ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog); -static inline int ixgb_eeprom_size(struct ixgb_hw *hw) -{ - /* return size in bytes */ - return (IXGB_EEPROM_SIZE << 1); -} - struct ixgb_stats { char stat_string[ETH_GSTRING_LEN]; int sizeof_stat; @@ -94,9 +88,10 @@ static struct ixgb_stats ixgb_gstrings_s #define IXGB_STATS_LEN \ sizeof(ixgb_gstrings_stats) / sizeof(struct ixgb_stats) -static void -ixgb_ethtool_gset(struct ixgb_adapter *adapter, struct ethtool_cmd *ecmd) +static int +ixgb_ethtool_gset(struct net_device *netdev, struct ethtool_cmd *ecmd) { + struct ixgb_adapter *adapter = netdev->priv; ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE); ecmd->advertising = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE); ecmd->port = PORT_FIBRE; @@ -111,11 +106,13 @@ ixgb_ethtool_gset(struct ixgb_adapter *a } ecmd->autoneg = AUTONEG_DISABLE; + return 0; } static int -ixgb_ethtool_sset(struct ixgb_adapter *adapter, struct ethtool_cmd *ecmd) +ixgb_ethtool_sset(struct net_device *netdev, struct ethtool_cmd *ecmd) { + struct ixgb_adapter *adapter = netdev->priv; if (ecmd->autoneg == AUTONEG_ENABLE || ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL) return -EINVAL; @@ -123,14 +120,14 @@ ixgb_ethtool_sset(struct ixgb_adapter *a ixgb_down(adapter, TRUE); ixgb_up(adapter); } - return 0; } -static int -ixgb_ethtool_gpause(struct ixgb_adapter *adapter, +static void +ixgb_ethtool_gpause(struct net_device *dev, struct ethtool_pauseparam *epause) { + struct ixgb_adapter *adapter = dev->priv; struct ixgb_hw *hw = &adapter->hw; epause->autoneg = AUTONEG_DISABLE; @@ -143,14 +140,13 @@ ixgb_ethtool_gpause(struct ixgb_adapter epause->rx_pause = 1; epause->tx_pause = 1; } - - return 0; } static int -ixgb_ethtool_spause(struct ixgb_adapter *adapter, +ixgb_ethtool_spause(struct net_device *dev, struct ethtool_pauseparam *epause) { + struct ixgb_adapter *adapter = dev->priv; struct ixgb_hw *hw = &adapter->hw; if (epause->autoneg == AUTONEG_ENABLE) @@ -172,26 +168,23 @@ ixgb_ethtool_spause(struct ixgb_adapter } static void -ixgb_ethtool_gdrvinfo(struct ixgb_adapter *adapter, +ixgb_ethtool_gdrvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) { + struct ixgb_adapter *adapter = netdev->priv; strncpy(drvinfo->driver, ixgb_driver_name, 32); strncpy(drvinfo->version, ixgb_driver_version, 32); strncpy(drvinfo->fw_version, "N/A", 32); strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32); - drvinfo->n_stats = IXGB_STATS_LEN; -#define IXGB_REG_DUMP_LEN 136*sizeof(uint32_t) - drvinfo->regdump_len = IXGB_REG_DUMP_LEN; - drvinfo->eedump_len = ixgb_eeprom_size(&adapter->hw); } #define IXGB_GET_STAT(_A_, _R_) _A_->stats._R_ static void -ixgb_ethtool_gregs(struct ixgb_adapter *adapter, - struct ethtool_regs *regs, uint32_t * regs_buff) +ixgb_ethtool_gregs(struct net_device *dev, struct ethtool_regs *regs, void *buf) { + struct ixgb_adapter *adapter = dev->priv; struct ixgb_hw *hw = &adapter->hw; - uint32_t *reg = regs_buff; + uint32_t *reg = buf; uint32_t *reg_start = reg; uint8_t i; @@ -323,69 +316,37 @@ ixgb_ethtool_gregs(struct ixgb_adapter * } static int -ixgb_ethtool_geeprom(struct ixgb_adapter *adapter, - struct ethtool_eeprom *eeprom, uint16_t * eeprom_buff) +ixgb_ethtool_geeprom(struct net_device *dev, + struct ethtool_eeprom *eeprom, u8 *data) { + struct ixgb_adapter *adapter = dev->priv; struct ixgb_hw *hw = &adapter->hw; - int i, max_len, first_word, last_word; - int ret_val = 0; - - if (eeprom->len == 0) { - ret_val = -EINVAL; - goto geeprom_error; - } eeprom->magic = hw->vendor_id | (hw->device_id << 16); - max_len = ixgb_eeprom_size(hw); - /* use our function to read the eeprom and update our cache */ ixgb_get_eeprom_data(hw); - - if (eeprom->offset > eeprom->offset + eeprom->len) { - ret_val = -EINVAL; - goto geeprom_error; - } - - if ((eeprom->offset + eeprom->len) > max_len) - eeprom->len = (max_len - eeprom->offset); - - first_word = eeprom->offset >> 1; - last_word = (eeprom->offset + eeprom->len - 1) >> 1; - - for (i = 0; i <= (last_word - first_word); i++) { - eeprom_buff[i] = hw->eeprom[first_word + i]; - } - geeprom_error: - return ret_val; + memcpy(data, (char *)hw->eeprom + eeprom->offset, eeprom->len); + return 0; } static int -ixgb_ethtool_seeprom(struct ixgb_adapter *adapter, - struct ethtool_eeprom *eeprom, void __user *user_data) +ixgb_ethtool_seeprom(struct net_device *dev, + struct ethtool_eeprom *eeprom, u8 *data) { + struct ixgb_adapter *adapter = dev->priv; struct ixgb_hw *hw = &adapter->hw; - uint16_t eeprom_buff[256]; - int i, max_len, first_word, last_word; - void *ptr; + /* We are under rtnl, so static is OK */ + static uint16_t eeprom_buff[IXGB_EEPROM_SIZE]; + int i, first_word, last_word; + char *ptr; if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) return -EFAULT; - if (eeprom->len == 0) - return -EINVAL; - - max_len = ixgb_eeprom_size(hw); - - if (eeprom->offset > eeprom->offset + eeprom->len) - return -EINVAL; - - if ((eeprom->offset + eeprom->len) > max_len) - eeprom->len = (max_len - eeprom->offset); - first_word = eeprom->offset >> 1; last_word = (eeprom->offset + eeprom->len - 1) >> 1; - ptr = (void *)eeprom_buff; + ptr = (char *)eeprom_buff; if (eeprom->offset & 1) { /* need read/modify/write of first changed EEPROM word */ @@ -399,8 +360,7 @@ ixgb_ethtool_seeprom(struct ixgb_adapter eeprom_buff[last_word - first_word] = ixgb_read_eeprom(hw, last_word); } - if (copy_from_user(ptr, user_data, eeprom->len)) - return -EFAULT; + memcpy(ptr, data, eeprom->len); for (i = 0; i <= (last_word - first_word); i++) ixgb_write_eeprom(hw, first_word + i, eeprom_buff[i]); @@ -431,8 +391,9 @@ static void ixgb_led_blink_callback(unsi } static int -ixgb_ethtool_led_blink(struct ixgb_adapter *adapter, struct ethtool_value *id) +ixgb_ethtool_led_blink(struct net_device *netdev, u32 data) { + struct ixgb_adapter *adapter = netdev->priv; if (!adapter->blink_timer.function) { init_timer(&adapter->blink_timer); adapter->blink_timer.function = ixgb_led_blink_callback; @@ -442,8 +403,8 @@ ixgb_ethtool_led_blink(struct ixgb_adapt mod_timer(&adapter->blink_timer, jiffies); set_current_state(TASK_INTERRUPTIBLE); - if (id->data) - schedule_timeout(id->data * HZ); + if (data) + schedule_timeout(data * HZ); else schedule_timeout(MAX_SCHEDULE_TIMEOUT); @@ -454,268 +415,141 @@ ixgb_ethtool_led_blink(struct ixgb_adapt return 0; } -int ixgb_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr) +static int ixgb_nway_reset(struct net_device *netdev) { - struct ixgb_adapter *adapter = netdev->priv; - void __user *addr = ifr->ifr_data; - uint32_t cmd; + if (netif_running(netdev)) { + struct ixgb_adapter *adapter = netdev->priv; + ixgb_down(adapter, TRUE); + ixgb_up(adapter); + } + return 0; +} - if (get_user(cmd, (uint32_t __user *) addr)) - return -EFAULT; +static int ixgb_get_stats_count(struct net_device *dev) +{ + return IXGB_STATS_LEN; +} - switch (cmd) { - case ETHTOOL_GSET:{ - struct ethtool_cmd ecmd = { ETHTOOL_GSET }; - ixgb_ethtool_gset(adapter, &ecmd); - if (copy_to_user(addr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; - } - case ETHTOOL_SSET:{ - struct ethtool_cmd ecmd; - if (copy_from_user(&ecmd, addr, sizeof(ecmd))) - return -EFAULT; - return ixgb_ethtool_sset(adapter, &ecmd); - } - case ETHTOOL_GDRVINFO:{ - struct ethtool_drvinfo drvinfo = { ETHTOOL_GDRVINFO }; - ixgb_ethtool_gdrvinfo(adapter, &drvinfo); - if (copy_to_user(addr, &drvinfo, sizeof(drvinfo))) - return -EFAULT; - return 0; - } - case ETHTOOL_GSTRINGS:{ - struct ethtool_gstrings gstrings = { ETHTOOL_GSTRINGS }; - char *strings = NULL; - int err = 0; - - if (copy_from_user(&gstrings, addr, sizeof(gstrings))) - return -EFAULT; - switch (gstrings.string_set) { - case ETH_SS_STATS:{ - int i; - gstrings.len = IXGB_STATS_LEN; - strings = - kmalloc(IXGB_STATS_LEN * - ETH_GSTRING_LEN, - GFP_KERNEL); - if (!strings) - return -ENOMEM; - for (i = 0; i < IXGB_STATS_LEN; i++) { - memcpy(&strings - [i * ETH_GSTRING_LEN], - ixgb_gstrings_stats[i]. - stat_string, - ETH_GSTRING_LEN); - } - break; - } - default: - return -EOPNOTSUPP; - } - if (copy_to_user(addr, &gstrings, sizeof(gstrings))) - err = -EFAULT; - addr += offsetof(struct ethtool_gstrings, data); - if (!err && copy_to_user(addr, strings, - gstrings.len * - ETH_GSTRING_LEN)) - err = -EFAULT; - - kfree(strings); - return err; - } - case ETHTOOL_GREGS:{ - struct ethtool_regs regs = { ETHTOOL_GREGS }; - uint32_t regs_buff[IXGB_REG_DUMP_LEN]; - - if (copy_from_user(®s, addr, sizeof(regs))) - return -EFAULT; - ixgb_ethtool_gregs(adapter, ®s, regs_buff); - if (copy_to_user(addr, ®s, sizeof(regs))) - return -EFAULT; - - addr += offsetof(struct ethtool_regs, data); - if (copy_to_user(addr, regs_buff, regs.len)) - return -EFAULT; - - return 0; - } - case ETHTOOL_NWAY_RST:{ - if (netif_running(netdev)) { - ixgb_down(adapter, TRUE); - ixgb_up(adapter); - } - return 0; - } - case ETHTOOL_PHYS_ID:{ - struct ethtool_value id; - if (copy_from_user(&id, addr, sizeof(id))) - return -EFAULT; - return ixgb_ethtool_led_blink(adapter, &id); - } - case ETHTOOL_GLINK:{ - struct ethtool_value link = { ETHTOOL_GLINK }; - link.data = netif_carrier_ok(netdev); - if (copy_to_user(addr, &link, sizeof(link))) - return -EFAULT; - return 0; - } - - case ETHTOOL_GEEPROM:{ - struct ethtool_eeprom eeprom = { ETHTOOL_GEEPROM }; - uint16_t eeprom_buff[IXGB_EEPROM_SIZE]; - void *ptr; - int err = 0; - - if (copy_from_user(&eeprom, addr, sizeof(eeprom))) - return -EFAULT; - - if ((err = - ixgb_ethtool_geeprom(adapter, &eeprom, - eeprom_buff)) < 0) - return err; - - if (copy_to_user(addr, &eeprom, sizeof(eeprom))) - return -EFAULT; - - addr += offsetof(struct ethtool_eeprom, data); - ptr = ((void *)eeprom_buff) + (eeprom.offset & 1); - - if (copy_to_user(addr, ptr, eeprom.len)) - return -EFAULT; - return 0; - } - case ETHTOOL_SEEPROM:{ - struct ethtool_eeprom eeprom; - - if (copy_from_user(&eeprom, addr, sizeof(eeprom))) - return -EFAULT; - - addr += offsetof(struct ethtool_eeprom, data); - return ixgb_ethtool_seeprom(adapter, &eeprom, addr); - } - case ETHTOOL_GPAUSEPARAM:{ - struct ethtool_pauseparam epause = - { ETHTOOL_GPAUSEPARAM }; - ixgb_ethtool_gpause(adapter, &epause); - if (copy_to_user(addr, &epause, sizeof(epause))) - return -EFAULT; - return 0; - } - case ETHTOOL_SPAUSEPARAM:{ - struct ethtool_pauseparam epause; - if (copy_from_user(&epause, addr, sizeof(epause))) - return -EFAULT; - return ixgb_ethtool_spause(adapter, &epause); - } - case ETHTOOL_GSTATS:{ - struct { - struct ethtool_stats eth_stats; - uint64_t data[IXGB_STATS_LEN]; - } stats = { { - ETHTOOL_GSTATS, IXGB_STATS_LEN}}; - int i; - - for (i = 0; i < IXGB_STATS_LEN; i++) - stats.data[i] = - (ixgb_gstrings_stats[i].sizeof_stat == - sizeof(uint64_t)) ? *(uint64_t *) ((char *) - adapter - + - ixgb_gstrings_stats - [i]. - stat_offset) - : *(uint32_t *) ((char *)adapter + - ixgb_gstrings_stats[i]. - stat_offset); - if (copy_to_user(addr, &stats, sizeof(stats))) - return -EFAULT; - return 0; - } - case ETHTOOL_GRXCSUM:{ - struct ethtool_value edata = { ETHTOOL_GRXCSUM }; - - edata.data = adapter->rx_csum; - if (copy_to_user(addr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - case ETHTOOL_SRXCSUM:{ - struct ethtool_value edata; - - if (copy_from_user(&edata, addr, sizeof(edata))) - return -EFAULT; - adapter->rx_csum = edata.data; - ixgb_down(adapter, TRUE); - ixgb_up(adapter); - return 0; - } - case ETHTOOL_GTXCSUM:{ - struct ethtool_value edata = { ETHTOOL_GTXCSUM }; - - edata.data = (netdev->features & NETIF_F_HW_CSUM) != 0; - if (copy_to_user(addr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - case ETHTOOL_STXCSUM:{ - struct ethtool_value edata; - - if (copy_from_user(&edata, addr, sizeof(edata))) - return -EFAULT; - - if (edata.data) - netdev->features |= NETIF_F_HW_CSUM; - else - netdev->features &= ~NETIF_F_HW_CSUM; - - return 0; - } - case ETHTOOL_GSG:{ - struct ethtool_value edata = { ETHTOOL_GSG }; - - edata.data = (netdev->features & NETIF_F_SG) != 0; - if (copy_to_user(addr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - case ETHTOOL_SSG:{ - struct ethtool_value edata; - - if (copy_from_user(&edata, addr, sizeof(edata))) - return -EFAULT; - - if (edata.data) - netdev->features |= NETIF_F_SG; - else - netdev->features &= ~NETIF_F_SG; +static void ixgb_get_strings(struct net_device *dev, u32 stringset, u8 *data) +{ + int i; + for (i = 0; i < IXGB_STATS_LEN; i++) { + memcpy(data + i * ETH_GSTRING_LEN, + ixgb_gstrings_stats[i].stat_string, + ETH_GSTRING_LEN); + } +} - return 0; - } -#ifdef NETIF_F_TSO - case ETHTOOL_GTSO:{ - struct ethtool_value edata = { ETHTOOL_GTSO }; +static int ixgb_get_regs_len(struct net_device *dev) +{ + return 136*sizeof(uint32_t); +} + +static int ixgb_get_eeprom_len(struct net_device *dev) +{ + /* return size in bytes */ + return (IXGB_EEPROM_SIZE << 1); +} - edata.data = (netdev->features & NETIF_F_TSO) != 0; - if (copy_to_user(addr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - case ETHTOOL_STSO:{ - struct ethtool_value edata; - - if (copy_from_user(&edata, addr, sizeof(edata))) - return -EFAULT; - - if (edata.data) - netdev->features |= NETIF_F_TSO; - else - netdev->features &= ~NETIF_F_TSO; +static void get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *stats, u64 *data) +{ + struct ixgb_adapter *adapter = dev->priv; + int i; - return 0; - } -#endif - default: - return -EOPNOTSUPP; + for (i = 0; i < IXGB_STATS_LEN; i++) { + void *p = (char *)adapter + ixgb_gstrings_stats[i].stat_offset; + stats->data[i] = + (ixgb_gstrings_stats[i].sizeof_stat == sizeof(uint64_t)) + ? *(uint64_t *) p + : *(uint32_t *) p; } } + +static u32 ixgb_get_rx_csum(struct net_device *dev) +{ + struct ixgb_adapter *adapter = dev->priv; + return adapter->rx_csum; +} + +static int ixgb_set_rx_csum(struct net_device *dev, u32 sum) +{ + struct ixgb_adapter *adapter = dev->priv; + adapter->rx_csum = sum; + ixgb_down(adapter, TRUE); + ixgb_up(adapter); + return 0; +} + +static u32 ixgb_get_tx_csum(struct net_device *dev) +{ + return (dev->features & NETIF_F_HW_CSUM) != 0; +} + +static int ixgb_set_tx_csum(struct net_device *dev, u32 sum) +{ + if (sum) + dev->features |= NETIF_F_HW_CSUM; + else + dev->features &= ~NETIF_F_HW_CSUM; + return 0; +} + +static u32 ixgb_get_sg(struct net_device *dev) +{ + return (dev->features & NETIF_F_SG) != 0; +} + +static int ixgb_set_sg(struct net_device *dev, u32 sum) +{ + if (sum) + dev->features |= NETIF_F_SG; + else + dev->features &= ~NETIF_F_SG; + return 0; +} + +#ifdef NETIF_F_TSO +static u32 ixgb_get_tso(struct net_device *dev) +{ + return (dev->features & NETIF_F_TSO) != 0; +} + +static int ixgb_set_tso(struct net_device *dev, u32 sum) +{ + if (sum) + dev->features |= NETIF_F_TSO; + else + dev->features &= ~NETIF_F_TSO; + return 0; +} +#endif + +struct ethtool_ops ixgb_ethtool_ops = { + .get_settings = ixgb_ethtool_gset, + .set_settings = ixgb_ethtool_sset, + .get_drvinfo = ixgb_ethtool_gdrvinfo, + .nway_reset = ixgb_nway_reset, + .get_link = ethtool_op_get_link, + .phys_id = ixgb_ethtool_led_blink, + .get_strings = ixgb_get_strings, + .get_stats_count = ixgb_get_stats_count, + .get_regs = ixgb_ethtool_gregs, + .get_regs_len = ixgb_get_regs_len, + .get_eeprom_len = ixgb_get_eeprom_len, + .get_eeprom = ixgb_ethtool_geeprom, + .set_eeprom = ixgb_ethtool_seeprom, + .get_pauseparam = ixgb_ethtool_gpause, + .set_pauseparam = ixgb_ethtool_spause, + .get_ethtool_stats = get_ethtool_stats, + .get_rx_csum = ixgb_get_rx_csum, + .set_rx_csum = ixgb_set_rx_csum, + .get_tx_csum = ixgb_get_tx_csum, + .set_tx_csum = ixgb_set_tx_csum, + .get_sg = ixgb_get_sg, + .set_sg = ixgb_set_sg, +#ifdef NETIF_F_TSO + .get_tso = ixgb_get_tso, + .set_tso = ixgb_set_tso, +#endif +}; diff -puN drivers/net/ixgb/ixgb_main.c~bk-netdev drivers/net/ixgb/ixgb_main.c --- 25/drivers/net/ixgb/ixgb_main.c~bk-netdev 2004-09-15 21:06:53.276644440 -0700 +++ 25-akpm/drivers/net/ixgb/ixgb_main.c 2004-09-15 21:06:53.399625744 -0700 @@ -97,7 +97,6 @@ static boolean_t ixgb_clean_rx_irq(struc static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter); #endif static void ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter); -static int ixgb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); static void ixgb_tx_timeout(struct net_device *dev); static void ixgb_tx_timeout_task(struct net_device *dev); static void ixgb_vlan_rx_register(struct net_device *netdev, @@ -124,7 +123,7 @@ struct notifier_block ixgb_notifier_rebo /* Exported from other modules */ extern void ixgb_check_options(struct ixgb_adapter *adapter); -extern int ixgb_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr); +extern struct ethtool_ops ixgb_ethtool_ops; static struct pci_driver ixgb_driver = { .name = ixgb_driver_name, @@ -372,9 +371,9 @@ ixgb_probe(struct pci_dev *pdev, const s netdev->set_multicast_list = &ixgb_set_multi; netdev->set_mac_address = &ixgb_set_mac; netdev->change_mtu = &ixgb_change_mtu; - netdev->do_ioctl = &ixgb_ioctl; netdev->tx_timeout = &ixgb_tx_timeout; netdev->watchdog_timeo = HZ; + SET_ETHTOOL_OPS(netdev, &ixgb_ethtool_ops); #ifdef CONFIG_IXGB_NAPI netdev->poll = &ixgb_clean; netdev->weight = 64; @@ -1970,25 +1969,6 @@ static void ixgb_alloc_rx_buffers(struct } /** - * ixgb_ioctl - perform a command - e.g: ethtool:get_driver_info. - * @param netdev network interface device structure - * @param ifr data to be used/filled in by the ioctl command - * @param cmd ioctl command to execute - **/ - -static int ixgb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - switch (cmd) { - case SIOCETHTOOL: - return ixgb_ethtool_ioctl(netdev, ifr); - default: - return -EOPNOTSUPP; - } - - return 0; -} - -/** * ixgb_vlan_rx_register - enables or disables vlan tagging/stripping. * * @param netdev network interface device structure diff -puN drivers/net/Kconfig~bk-netdev drivers/net/Kconfig --- 25/drivers/net/Kconfig~bk-netdev 2004-09-15 21:06:53.278644136 -0700 +++ 25-akpm/drivers/net/Kconfig 2004-09-15 21:06:53.367630608 -0700 @@ -2061,6 +2061,15 @@ config R8169_NAPI If in doubt, say N. +config R8169_VLAN + bool "VLAN support" + depends on R8169 && VLAN_8021Q + ---help--- + Say Y here for the r8169 driver to support the functions required + by the kernel 802.1Q code. + + If in doubt, say Y. + config SK98LIN tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support" depends on PCI diff -puN drivers/net/mac8390.c~bk-netdev drivers/net/mac8390.c --- 25/drivers/net/mac8390.c~bk-netdev 2004-09-15 21:06:53.279643984 -0700 +++ 25-akpm/drivers/net/mac8390.c 2004-09-15 21:06:53.399625744 -0700 @@ -42,10 +42,6 @@ #include "8390.h" -#if (LINUX_VERSION_CODE < 0x02030e) -#define net_device device -#endif - #define WD_START_PG 0x00 /* First page of TX buffer */ #define CABLETRON_RX_START_PG 0x00 /* First page of RX buffer */ #define CABLETRON_RX_STOP_PG 0x30 /* Last page +1 of RX ring */ diff -puN drivers/net/meth.c~bk-netdev drivers/net/meth.c --- 25/drivers/net/meth.c~bk-netdev 2004-09-15 21:06:53.280643832 -0700 +++ 25-akpm/drivers/net/meth.c 2004-09-15 21:06:53.400625592 -0700 @@ -368,31 +368,6 @@ static int meth_release(struct net_devic } /* - * Configuration changes (passed on by ifconfig) - */ -static int meth_config(struct net_device *dev, struct ifmap *map) -{ - if (dev->flags & IFF_UP) /* can't act on a running interface */ - return -EBUSY; - - /* Don't allow changing the I/O address */ - if (map->base_addr != dev->base_addr) { - printk(KERN_WARNING "meth: Can't change I/O address\n"); - return -EOPNOTSUPP; - } - - /* Don't allow changing the IRQ */ - if (map->irq != dev->irq) { - printk(KERN_WARNING "meth: Can't change IRQ\n"); - return -EOPNOTSUPP; - } - DPRINTK("Configured\n"); - - /* ignore other fields */ - return 0; -} - -/* * Receive a packet: retrieve, encapsulate and pass over to upper levels */ static void meth_rx(struct net_device* dev, unsigned long int_status) @@ -813,7 +788,6 @@ static struct net_device *meth_init(void dev->open = meth_open; dev->stop = meth_release; - dev->set_config = meth_config; dev->hard_start_xmit = meth_tx; dev->do_ioctl = meth_ioctl; dev->get_stats = meth_stats; diff -puN drivers/net/natsemi.c~bk-netdev drivers/net/natsemi.c --- 25/drivers/net/natsemi.c~bk-netdev 2004-09-15 21:06:53.282643528 -0700 +++ 25-akpm/drivers/net/natsemi.c 2004-09-15 21:06:53.404624984 -0700 @@ -768,6 +768,7 @@ static void enable_wol_mode(struct net_d 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 void move_int_phy(struct net_device *dev, int addr) { @@ -926,6 +927,7 @@ static int __devinit natsemi_probe1 (str #ifdef CONFIG_NET_POLL_CONTROLLER dev->poll_controller = &natsemi_poll_controller; #endif + SET_ETHTOOL_OPS(dev, ðtool_ops); if (mtu) dev->mtu = mtu; @@ -2457,177 +2459,136 @@ static void set_rx_mode(struct net_devic 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; - - 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; + 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); +} - useraddr += offsetof(struct ethtool_regs, data); +static int get_regs_len(struct net_device *dev) +{ + return NATSEMI_REGS_SIZE; +} - spin_lock_irq(&np->lock); - r = netdev_get_regs(dev, regbuf); - spin_unlock_irq(&np->lock); +static int get_eeprom_len(struct net_device *dev) +{ + return NATSEMI_EEPROM_SIZE; +} - 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 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 (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) - return -EFAULT; +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 (eeprom.offset > eeprom.offset+eeprom.len) - return -EINVAL; +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.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 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; +} - useraddr += offsetof(struct ethtool_eeprom, data); +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); +} - spin_lock_irq(&np->lock); - r = netdev_get_eeprom(dev, eebuf); - spin_unlock_irq(&np->lock); +static u32 get_msglevel(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + return np->msg_enable; +} - if (r) - return r; - if (copy_to_user(useraddr, eebuf+eeprom.offset, eeprom.len)) - return -EFAULT; - return 0; - } +static void set_msglevel(struct net_device *dev, u32 val) +{ + struct netdev_private *np = netdev_priv(dev); + np->msg_enable = val; +} +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; +} - return -EOPNOTSUPP; +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; } +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); @@ -2976,8 +2937,6 @@ static int netdev_ioctl(struct net_devic 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; diff -puN drivers/net/ns83820.c~bk-netdev drivers/net/ns83820.c --- 25/drivers/net/ns83820.c~bk-netdev 2004-09-15 21:06:53.284643224 -0700 +++ 25-akpm/drivers/net/ns83820.c 2004-09-15 21:06:53.406624680 -0700 @@ -1192,59 +1192,26 @@ static struct net_device_stats *ns83820_ return &dev->stats; } -static int ns83820_ethtool_ioctl (struct ns83820 *dev, void __user *useraddr) +static void ns83820_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *info) { - u32 ethcmd; - - if (copy_from_user(ðcmd, useraddr, sizeof (ethcmd))) - return -EFAULT; - - switch (ethcmd) { - case ETHTOOL_GDRVINFO: - { - struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; - strcpy(info.driver, "ns83820"); - strcpy(info.version, VERSION); - strcpy(info.bus_info, pci_name(dev->pci_dev)); - if (copy_to_user(useraddr, &info, sizeof (info))) - return -EFAULT; - return 0; - } - - /* get link status */ - case ETHTOOL_GLINK: { - struct ethtool_value edata = { ETHTOOL_GLINK }; - u32 cfg = readl(dev->base + CFG) ^ SPDSTS_POLARITY; - - if (cfg & CFG_LNKSTS) - edata.data = 1; - else - edata.data = 0; - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - - default: - break; - } - - return -EOPNOTSUPP; + struct ns83820 *dev = PRIV(ndev); + strcpy(info->driver, "ns83820"); + strcpy(info->version, VERSION); + strcpy(info->bus_info, pci_name(dev->pci_dev)); } -static int ns83820_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) +static u32 ns83820_get_link(struct net_device *ndev) { struct ns83820 *dev = PRIV(ndev); - - switch(cmd) { - case SIOCETHTOOL: - return ns83820_ethtool_ioctl(dev, rq->ifr_data); - - default: - return -EOPNOTSUPP; - } + u32 cfg = readl(dev->base + CFG) ^ SPDSTS_POLARITY; + return cfg & CFG_LNKSTS ? 1 : 0; } +static struct ethtool_ops ops = { + .get_drvinfo = ns83820_get_drvinfo, + .get_link = ns83820_get_link +}; + static void ns83820_mib_isr(struct ns83820 *dev) { spin_lock(&dev->misc_lock); @@ -1884,7 +1851,7 @@ static int __devinit ns83820_init_one(st ndev->get_stats = ns83820_get_stats; ndev->change_mtu = ns83820_change_mtu; ndev->set_multicast_list = ns83820_set_multicast; - ndev->do_ioctl = ns83820_ioctl; + SET_ETHTOOL_OPS(ndev, &ops); ndev->tx_timeout = ns83820_tx_timeout; ndev->watchdog_timeo = 5 * HZ; diff -puN drivers/net/pcmcia/smc91c92_cs.c~bk-netdev drivers/net/pcmcia/smc91c92_cs.c --- 25/drivers/net/pcmcia/smc91c92_cs.c~bk-netdev 2004-09-15 21:06:53.285643072 -0700 +++ 25-akpm/drivers/net/pcmcia/smc91c92_cs.c 2004-09-15 21:06:53.409624224 -0700 @@ -304,6 +304,7 @@ static void mdio_sync(ioaddr_t addr); static int mdio_read(struct net_device *dev, int phy_id, int loc); static void mdio_write(struct net_device *dev, int phy_id, int loc, int value); static int smc_link_ok(struct net_device *dev); +static struct ethtool_ops ethtool_ops; /*====================================================================== @@ -357,6 +358,7 @@ static dev_link_t *smc91c92_attach(void) dev->open = &smc_open; dev->stop = &smc_close; dev->do_ioctl = &smc_ioctl; + SET_ETHTOOL_OPS(dev, ðtool_ops); #ifdef HAVE_TX_TIMEOUT dev->tx_timeout = smc_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; @@ -2118,131 +2120,130 @@ static int smc_netdev_set_ecmd(struct ne return 0; } -static int smc_ethtool_ioctl (struct net_device *dev, void __user *useraddr) +static int check_if_running(struct net_device *dev) { - u32 ethcmd; - struct smc_private *smc = netdev_priv(dev); - - if (get_user(ethcmd, (u32 __user *)useraddr)) - return -EFAULT; - - switch (ethcmd) { - - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; - strcpy(info.driver, DRV_NAME); - strcpy(info.version, DRV_VERSION); - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; + if (!netif_running(dev)) + return -EINVAL; return 0; - } +} + +static void smc_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); +} - /* get settings */ - case ETHTOOL_GSET: { +static int smc_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct smc_private *smc = netdev_priv(dev); + ioaddr_t ioaddr = dev->base_addr; + u16 saved_bank = inw(ioaddr + BANK_SELECT); int ret; - struct ethtool_cmd ecmd = { ETHTOOL_GSET }; + + SMC_SELECT_BANK(3); spin_lock_irq(&smc->lock); if (smc->cfg & CFG_MII_SELECT) - ret = mii_ethtool_gset(&smc->mii_if, &ecmd); + ret = mii_ethtool_gset(&smc->mii_if, ecmd); else - ret = smc_netdev_get_ecmd(dev, &ecmd); + ret = smc_netdev_get_ecmd(dev, ecmd); spin_unlock_irq(&smc->lock); - if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) - return -EFAULT; + SMC_SELECT_BANK(saved_bank); return ret; - } +} - /* set settings */ - case ETHTOOL_SSET: { +static int smc_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct smc_private *smc = netdev_priv(dev); + ioaddr_t ioaddr = dev->base_addr; + u16 saved_bank = inw(ioaddr + BANK_SELECT); int ret; - struct ethtool_cmd ecmd; - if (copy_from_user(&ecmd, useraddr, sizeof(ecmd))) - return -EFAULT; + + SMC_SELECT_BANK(3); spin_lock_irq(&smc->lock); if (smc->cfg & CFG_MII_SELECT) - ret = mii_ethtool_sset(&smc->mii_if, &ecmd); + ret = mii_ethtool_sset(&smc->mii_if, ecmd); else - ret = smc_netdev_set_ecmd(dev, &ecmd); + ret = smc_netdev_set_ecmd(dev, ecmd); spin_unlock_irq(&smc->lock); + SMC_SELECT_BANK(saved_bank); return ret; - } +} + +static u32 smc_get_link(struct net_device *dev) +{ + struct smc_private *smc = netdev_priv(dev); + ioaddr_t ioaddr = dev->base_addr; + u16 saved_bank = inw(ioaddr + BANK_SELECT); + u32 ret; - /* get link status */ - case ETHTOOL_GLINK: { - struct ethtool_value edata = { ETHTOOL_GLINK }; + SMC_SELECT_BANK(3); spin_lock_irq(&smc->lock); - edata.data = smc_link_ok(dev); + ret = smc_link_ok(dev); spin_unlock_irq(&smc->lock); - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } + SMC_SELECT_BANK(saved_bank); + return ret; +} #ifdef PCMCIA_DEBUG - /* get message-level */ - case ETHTOOL_GMSGLVL: { - struct ethtool_value edata = { ETHTOOL_GMSGLVL }; - edata.data = pc_debug; - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } +static u32 smc_get_msglevel(struct net_device *dev) +{ + return pc_debug; +} - /* set message-level */ - case ETHTOOL_SMSGLVL: { - struct ethtool_value edata; - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - pc_debug = edata.data; - return 0; - } +static void smc_set_msglevel(struct net_device *dev, u32 val) +{ + pc_debug = val; +} #endif - /* restart autonegotiation */ - case ETHTOOL_NWAY_RST: { - if (smc->cfg & CFG_MII_SELECT) - return mii_nway_restart(&smc->mii_if); - else - return -EOPNOTSUPP; - } - - default: - break; - } - return -EOPNOTSUPP; -} +static int smc_nway_reset(struct net_device *dev) +{ + struct smc_private *smc = netdev_priv(dev); + if (smc->cfg & CFG_MII_SELECT) { + ioaddr_t ioaddr = dev->base_addr; + u16 saved_bank = inw(ioaddr + BANK_SELECT); + int res; + + SMC_SELECT_BANK(3); + res = mii_nway_restart(&smc->mii_if); + SMC_SELECT_BANK(saved_bank); + + return res; + } else + return -EOPNOTSUPP; +} + +static struct ethtool_ops ethtool_ops = { + .begin = check_if_running, + .get_drvinfo = smc_get_drvinfo, + .get_settings = smc_get_settings, + .set_settings = smc_set_settings, + .get_link = smc_get_link, +#ifdef PCMCIA_DEBUG + .get_msglevel = smc_get_msglevel, + .set_msglevel = smc_set_msglevel, +#endif + .nway_reset = smc_nway_reset, +}; static int smc_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) { - struct smc_private *smc = netdev_priv(dev); - struct mii_ioctl_data *mii; - int rc = 0; - u_short saved_bank; - ioaddr_t ioaddr = dev->base_addr; - - mii = if_mii(rq); - if (!netif_running(dev)) - return -EINVAL; + struct smc_private *smc = netdev_priv(dev); + struct mii_ioctl_data *mii = if_mii(rq); + int rc = 0; + u16 saved_bank; + ioaddr_t ioaddr = dev->base_addr; - switch (cmd) { - case SIOCETHTOOL: - saved_bank = inw(ioaddr + BANK_SELECT); - SMC_SELECT_BANK(3); - rc = smc_ethtool_ioctl(dev, rq->ifr_data); - SMC_SELECT_BANK(saved_bank); - break; + if (!netif_running(dev)) + return -EINVAL; - default: spin_lock_irq(&smc->lock); saved_bank = inw(ioaddr + BANK_SELECT); SMC_SELECT_BANK(3); rc = generic_mii_ioctl(&smc->mii_if, mii, cmd, NULL); SMC_SELECT_BANK(saved_bank); spin_unlock_irq(&smc->lock); - break; - } - - return rc; + return rc; } static struct pcmcia_driver smc91c92_cs_driver = { diff -puN drivers/net/r8169.c~bk-netdev drivers/net/r8169.c --- 25/drivers/net/r8169.c~bk-netdev 2004-09-15 21:06:53.287642768 -0700 +++ 25-akpm/drivers/net/r8169.c 2004-09-15 21:06:53.414623464 -0700 @@ -6,6 +6,7 @@ History: Feb 4 2002 - created initially by ShuChen . May 20 2002 - Add link status force-mode and TBI mode support. + 2004 - Massive updates. See kernel SCM system for details. ========================================================================= 1. [DEPRECATED: use ethtool instead] The media can be forced in 5 modes. Command: 'insmod r8169 media = SET_MEDIA' @@ -33,6 +34,13 @@ VERSION 1.2 <2002/11/30> - Copy mc_filter setup code from 8139cp (includes an optimization, and avoids set_bit use) +VERSION 1.6LK <2004/04/14> + + - Merge of Realtek's version 1.6 + - Conversion to DMA API + - Suspend/resume + - Endianness + - Misc Rx/Tx bugs */ #include @@ -42,13 +50,17 @@ VERSION 1.2 <2002/11/30> #include #include #include +#include #include +#include +#include +#include #include #include #include -#define RTL8169_VERSION "1.2" +#define RTL8169_VERSION "1.6LK" #define MODULENAME "r8169" #define RTL8169_DRIVER_NAME MODULENAME " Gigabit Ethernet driver " RTL8169_VERSION #define PFX MODULENAME ": " @@ -67,9 +79,11 @@ VERSION 1.2 <2002/11/30> #ifdef CONFIG_R8169_NAPI #define rtl8169_rx_skb netif_receive_skb +#define rtl8169_rx_hwaccel_skb vlan_hwaccel_rx #define rtl8169_rx_quota(count, quota) min(count, quota) #else #define rtl8169_rx_skb netif_rx +#define rtl8169_rx_hwaccel_skb vlan_hwaccel_receive_skb #define rtl8169_rx_quota(count, quota) count #endif @@ -87,9 +101,6 @@ static int multicast_filter_limit = 32; /* MAC address length*/ #define MAC_ADDR_LEN 6 -/* max supported gigabit ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - #define TX_FIFO_THRESH 256 /* In bytes */ #define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ @@ -99,6 +110,7 @@ static int multicast_filter_limit = 32; #define RxPacketMaxSize 0x0800 /* Maximum size supported is 16K-1 */ #define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ +#define R8169_REGS_SIZE 256 #define R8169_NAPI_WEIGHT 64 #define NUM_TX_DESC 64 /* Number of Tx descriptor registers */ #define NUM_RX_DESC 256 /* Number of Rx descriptor registers */ @@ -106,7 +118,6 @@ static int multicast_filter_limit = 32; #define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) #define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) -#define RTL_MIN_IO_SIZE 0x80 #define RTL8169_TX_TIMEOUT (6*HZ) #define RTL8169_PHY_TIMEOUT (10*HZ) @@ -303,26 +314,52 @@ enum RTL8169_register_content { }; enum _DescStatusBit { - OWNbit = 0x80000000, - EORbit = 0x40000000, - FSbit = 0x20000000, - LSbit = 0x10000000, + DescOwn = (1 << 31), /* Descriptor is owned by NIC */ + RingEnd = (1 << 30), /* End of descriptor ring */ + FirstFrag = (1 << 29), /* First segment of a packet */ + LastFrag = (1 << 28), /* Final segment of a packet */ + + /* Tx private */ + IPCS = (1 << 18), /* Calculate IP checksum */ + UDPCS = (1 << 17), /* Calculate UDP/IP checksum */ + TCPCS = (1 << 16), /* Calculate TCP/IP checksum */ + TxVlanTag = (1 << 17), /* Add VLAN tag */ + + /* Rx private */ + PID1 = (1 << 18), /* Protocol ID bit 1/2 */ + PID0 = (1 << 17), /* Protocol ID bit 2/2 */ + +#define RxProtoUDP (PID1) +#define RxProtoTCP (PID0) +#define RxProtoIP (PID1 | PID0) +#define RxProtoMask RxProtoIP + + IPFail = (1 << 16), /* IP checksum failed */ + UDPFail = (1 << 15), /* UDP/IP checksum failed */ + TCPFail = (1 << 14), /* TCP/IP checksum failed */ + RxVlanTag = (1 << 16), /* VLAN tag available */ }; #define RsvdMask 0x3fffc000 struct TxDesc { - u32 status; - u32 vlan_tag; + u32 opts1; + u32 opts2; u64 addr; }; struct RxDesc { - u32 status; - u32 vlan_tag; + u32 opts1; + u32 opts2; u64 addr; }; +struct ring_info { + struct sk_buff *skb; + u32 len; + u8 __pad[sizeof(void *) - sizeof(u32)]; +}; + struct rtl8169_private { void *mmio_addr; /* memory map physical address */ struct pci_dev *pci_dev; /* Index of PCI device */ @@ -340,13 +377,16 @@ struct rtl8169_private { dma_addr_t TxPhyAddr; dma_addr_t RxPhyAddr; struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ - struct sk_buff *Tx_skbuff[NUM_TX_DESC]; /* Tx data buffers */ + struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ + unsigned rx_buf_sz; struct timer_list timer; u16 cp_cmd; u16 intr_mask; int phy_auto_nego_reg; int phy_1000_ctrl_reg; - +#ifdef CONFIG_R8169_VLAN + struct vlan_group *vlgrp; +#endif int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); void (*get_settings)(struct net_device *, struct ethtool_cmd *); void (*phy_reset_enable)(void *); @@ -508,6 +548,11 @@ static void rtl8169_get_drvinfo(struct n strcpy(info->bus_info, pci_name(tp->pci_dev)); } +static int rtl8169_get_regs_len(struct net_device *dev) +{ + return R8169_REGS_SIZE; +} + static int rtl8169_set_speed_tbi(struct net_device *dev, u8 autoneg, u16 speed, u8 duplex) { @@ -598,6 +643,105 @@ static int rtl8169_set_settings(struct n return ret; } +static u32 rtl8169_get_rx_csum(struct net_device *dev) +{ + struct rtl8169_private *tp = netdev_priv(dev); + + return !!(tp->cp_cmd & RxChkSum); +} + +static int rtl8169_set_rx_csum(struct net_device *dev, u32 data) +{ + struct rtl8169_private *tp = netdev_priv(dev); + void *ioaddr = tp->mmio_addr; + unsigned long flags; + + spin_lock_irqsave(&tp->lock, flags); + + if (data) + tp->cp_cmd |= RxChkSum; + else + tp->cp_cmd &= ~RxChkSum; + + RTL_W16(CPlusCmd, tp->cp_cmd); + RTL_R16(CPlusCmd); + + spin_unlock_irqrestore(&tp->lock, flags); + + return 0; +} + +#ifdef CONFIG_R8169_VLAN + +static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, + struct sk_buff *skb) +{ + return (tp->vlgrp && vlan_tx_tag_present(skb)) ? + TxVlanTag | cpu_to_be16(vlan_tx_tag_get(skb)) : 0x00; +} + +static void rtl8169_vlan_rx_register(struct net_device *dev, + struct vlan_group *grp) +{ + struct rtl8169_private *tp = netdev_priv(dev); + void *ioaddr = tp->mmio_addr; + unsigned long flags; + + spin_lock_irqsave(&tp->lock, flags); + tp->vlgrp = grp; + tp->cp_cmd |= RxVlan; + RTL_W16(CPlusCmd, tp->cp_cmd); + RTL_R16(CPlusCmd); + spin_unlock_irqrestore(&tp->lock, flags); +} + +static void rtl8169_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) +{ + struct rtl8169_private *tp = netdev_priv(dev); + void *ioaddr = tp->mmio_addr; + unsigned long flags; + + spin_lock_irqsave(&tp->lock, flags); + tp->cp_cmd &= ~RxVlan; + RTL_W16(CPlusCmd, tp->cp_cmd); + RTL_R16(CPlusCmd); + if (tp->vlgrp) + tp->vlgrp->vlan_devices[vid] = NULL; + spin_unlock_irqrestore(&tp->lock, flags); +} + +static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, + struct sk_buff *skb) +{ + u32 opts2 = desc->opts2; + int ret; + + if (tp->vlgrp && (opts2 & RxVlanTag)) { + rtl8169_rx_hwaccel_skb(skb, tp->vlgrp, + be16_to_cpu(opts2 & 0xffff)); + ret = 0; + } else + ret = -1; + desc->opts2 = 0; + return ret; +} + +#else /* !CONFIG_R8169_VLAN */ + +static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, + struct sk_buff *skb) +{ + return 0; +} + +static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, + struct sk_buff *skb) +{ + return -1; +} + +#endif + static void rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) { struct rtl8169_private *tp = netdev_priv(dev); @@ -671,12 +815,33 @@ static int rtl8169_get_settings(struct n return 0; } +static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, + void *p) +{ + struct rtl8169_private *tp = netdev_priv(dev); + unsigned long flags; + + if (regs->len > R8169_REGS_SIZE) + regs->len = R8169_REGS_SIZE; + + spin_lock_irqsave(&tp->lock, flags); + memcpy_fromio(p, tp->mmio_addr, regs->len); + spin_unlock_irqrestore(&tp->lock, flags); +} static struct ethtool_ops rtl8169_ethtool_ops = { .get_drvinfo = rtl8169_get_drvinfo, + .get_regs_len = rtl8169_get_regs_len, .get_link = ethtool_op_get_link, .get_settings = rtl8169_get_settings, .set_settings = rtl8169_set_settings, + .get_rx_csum = rtl8169_get_rx_csum, + .set_rx_csum = rtl8169_set_rx_csum, + .get_tx_csum = ethtool_op_get_tx_csum, + .set_tx_csum = ethtool_op_set_tx_csum, + .get_sg = ethtool_op_get_sg, + .set_sg = ethtool_op_set_sg, + .get_regs = rtl8169_get_regs, }; static void rtl8169_write_gmii_reg_bit(void *ioaddr, int reg, int bitnum, @@ -907,28 +1072,31 @@ static inline void rtl8169_request_timer add_timer(timer); } +static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev, + void *ioaddr) +{ + iounmap(ioaddr); + pci_release_regions(pdev); + pci_disable_device(pdev); + free_netdev(dev); +} + static int __devinit rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out, void **ioaddr_out) { - void *ioaddr = NULL; + void *ioaddr; struct net_device *dev; struct rtl8169_private *tp; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - int rc, i, acpi_idle_state = 0, pm_cap; - + int rc = -ENOMEM, i, acpi_idle_state = 0, pm_cap; - assert(pdev != NULL); assert(ioaddr_out != NULL); - *ioaddr_out = NULL; - *dev_out = NULL; - // dev zeroed in alloc_etherdev dev = alloc_etherdev(sizeof (*tp)); if (dev == NULL) { printk(KERN_ERR PFX "unable to alloc new ethernet\n"); - return -ENOMEM; + goto err_out; } SET_MODULE_OWNER(dev); @@ -939,9 +1107,13 @@ rtl8169_init_board(struct pci_dev *pdev, rc = pci_enable_device(pdev); if (rc) { printk(KERN_ERR PFX "%s: enable failure\n", pdev->slot_name); - goto err_out; + goto err_out_free_dev; } + rc = pci_set_mwi(pdev); + if (rc < 0) + goto err_out_disable; + /* save power state before pci_enable_device overwrites it */ pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); if (pm_cap) { @@ -952,41 +1124,38 @@ rtl8169_init_board(struct pci_dev *pdev, } else { printk(KERN_ERR PFX "Cannot find PowerManagement capability, aborting.\n"); - goto err_out_free_res; + goto err_out_mwi; } - mmio_start = pci_resource_start(pdev, 1); - mmio_end = pci_resource_end(pdev, 1); - mmio_flags = pci_resource_flags(pdev, 1); - mmio_len = pci_resource_len(pdev, 1); - // make sure PCI base addr 1 is MMIO - if (!(mmio_flags & IORESOURCE_MEM)) { + if (!(pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) { printk(KERN_ERR PFX "region #1 not an MMIO resource, aborting\n"); rc = -ENODEV; - goto err_out_disable; + goto err_out_mwi; } // check for weird/broken PCI region reporting - if (mmio_len < RTL_MIN_IO_SIZE) { + if (pci_resource_len(pdev, 1) < R8169_REGS_SIZE) { printk(KERN_ERR PFX "Invalid PCI region size(s), aborting\n"); rc = -ENODEV; - goto err_out_disable; + goto err_out_mwi; } rc = pci_request_regions(pdev, MODULENAME); if (rc) { printk(KERN_ERR PFX "%s: could not request regions.\n", pdev->slot_name); - goto err_out_disable; + goto err_out_mwi; } tp->cp_cmd = PCIMulRW | RxChkSum; - if ((sizeof(dma_addr_t) > 4) && - !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) + dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; + + if ((sizeof(dma_addr_t) > 4) && !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { tp->cp_cmd |= PCIDAC; - else { + dev->features |= NETIF_F_HIGHDMA; + } else { rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); if (rc < 0) { printk(KERN_ERR PFX "DMA configuration failed.\n"); @@ -994,12 +1163,10 @@ rtl8169_init_board(struct pci_dev *pdev, } } - - // enable PCI bus-mastering pci_set_master(pdev); // ioremap MMIO region - ioaddr = ioremap(mmio_start, mmio_len); + ioaddr = ioremap(pci_resource_start(pdev, 1), R8169_REGS_SIZE); if (ioaddr == NULL) { printk(KERN_ERR PFX "cannot remap MMIO, aborting\n"); rc = -EIO; @@ -1036,26 +1203,35 @@ rtl8169_init_board(struct pci_dev *pdev, } tp->chipset = i; + tp->rx_buf_sz = RX_BUF_SIZE; + *ioaddr_out = ioaddr; *dev_out = dev; - return 0; +out: + return rc; err_out_free_res: pci_release_regions(pdev); +err_out_mwi: + pci_clear_mwi(pdev); + err_out_disable: pci_disable_device(pdev); -err_out: +err_out_free_dev: free_netdev(dev); - return rc; +err_out: + *ioaddr_out = NULL; + *dev_out = NULL; + goto out; } static int __devinit rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *dev = NULL; - struct rtl8169_private *tp = NULL; + struct rtl8169_private *tp; void *ioaddr = NULL; static int board_idx = -1; static int printed_version = 0; @@ -1079,8 +1255,6 @@ rtl8169_init_one(struct pci_dev *pdev, c tp = dev->priv; assert(ioaddr != NULL); - assert(dev != NULL); - assert(tp != NULL); if (RTL_R8(PHYstatus) & TBI_Enable) { tp->set_speed = rtl8169_set_speed_tbi; @@ -1105,18 +1279,26 @@ rtl8169_init_one(struct pci_dev *pdev, c dev->open = rtl8169_open; dev->hard_start_xmit = rtl8169_start_xmit; dev->get_stats = rtl8169_get_stats; - dev->ethtool_ops = &rtl8169_ethtool_ops; + SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops); dev->stop = rtl8169_close; dev->tx_timeout = rtl8169_tx_timeout; dev->set_multicast_list = rtl8169_set_rx_mode; dev->watchdog_timeo = RTL8169_TX_TIMEOUT; dev->irq = pdev->irq; dev->base_addr = (unsigned long) ioaddr; + #ifdef CONFIG_R8169_NAPI dev->poll = rtl8169_poll; dev->weight = R8169_NAPI_WEIGHT; printk(KERN_INFO PFX "NAPI enabled\n"); #endif + +#ifdef CONFIG_R8169_VLAN + dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; + dev->vlan_rx_register = rtl8169_vlan_rx_register; + dev->vlan_rx_kill_vid = rtl8169_vlan_rx_kill_vid; +#endif + tp->intr_mask = 0xffff; tp->pci_dev = pdev; tp->mmio_addr = ioaddr; @@ -1125,10 +1307,7 @@ rtl8169_init_one(struct pci_dev *pdev, c rc = register_netdev(dev); if (rc) { - iounmap(ioaddr); - pci_release_regions(pdev); - pci_disable_device(pdev); - free_netdev(dev); + rtl8169_release_board(pdev, dev, ioaddr); return rc; } @@ -1184,11 +1363,7 @@ rtl8169_remove_one(struct pci_dev *pdev) assert(tp != NULL); unregister_netdev(dev); - iounmap(tp->mmio_addr); - pci_release_regions(pdev); - - pci_disable_device(pdev); - free_netdev(dev); + rtl8169_release_board(pdev, dev, tp->mmio_addr); pci_set_drvdata(pdev, NULL); } @@ -1354,49 +1529,51 @@ rtl8169_hw_start(struct net_device *dev) static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) { desc->addr = 0x0badbadbadbadbadull; - desc->status &= ~cpu_to_le32(OWNbit | RsvdMask); + desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); } -static void rtl8169_free_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff, - struct RxDesc *desc) +static void rtl8169_free_rx_skb(struct rtl8169_private *tp, + struct sk_buff **sk_buff, struct RxDesc *desc) { - pci_unmap_single(pdev, le64_to_cpu(desc->addr), RX_BUF_SIZE, + struct pci_dev *pdev = tp->pci_dev; + + pci_unmap_single(pdev, le64_to_cpu(desc->addr), tp->rx_buf_sz, PCI_DMA_FROMDEVICE); dev_kfree_skb(*sk_buff); *sk_buff = NULL; rtl8169_make_unusable_by_asic(desc); } -static inline void rtl8169_return_to_asic(struct RxDesc *desc) +static inline void rtl8169_return_to_asic(struct RxDesc *desc, int rx_buf_sz) { - desc->status |= cpu_to_le32(OWNbit + RX_BUF_SIZE); + desc->opts1 |= cpu_to_le32(DescOwn + rx_buf_sz); } -static inline void rtl8169_give_to_asic(struct RxDesc *desc, dma_addr_t mapping) +static inline void rtl8169_give_to_asic(struct RxDesc *desc, dma_addr_t mapping, + int rx_buf_sz) { desc->addr = cpu_to_le64(mapping); - desc->status |= cpu_to_le32(OWNbit + RX_BUF_SIZE); + desc->opts1 |= cpu_to_le32(DescOwn + rx_buf_sz); } -static int rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct net_device *dev, - struct sk_buff **sk_buff, struct RxDesc *desc) +static int rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff, + struct RxDesc *desc, int rx_buf_sz) { struct sk_buff *skb; dma_addr_t mapping; int ret = 0; - skb = dev_alloc_skb(RX_BUF_SIZE); + skb = dev_alloc_skb(rx_buf_sz); if (!skb) goto err_out; - skb->dev = dev; skb_reserve(skb, 2); *sk_buff = skb; - mapping = pci_map_single(pdev, skb->tail, RX_BUF_SIZE, + mapping = pci_map_single(pdev, skb->tail, rx_buf_sz, PCI_DMA_FROMDEVICE); - rtl8169_give_to_asic(desc, mapping); + rtl8169_give_to_asic(desc, mapping, rx_buf_sz); out: return ret; @@ -1413,7 +1590,7 @@ static void rtl8169_rx_clear(struct rtl8 for (i = 0; i < NUM_RX_DESC; i++) { if (tp->Rx_skbuff[i]) { - rtl8169_free_rx_skb(tp->pci_dev, tp->Rx_skbuff + i, + rtl8169_free_rx_skb(tp, tp->Rx_skbuff + i, tp->RxDescArray + i); } } @@ -1430,8 +1607,8 @@ static u32 rtl8169_rx_fill(struct rtl816 if (tp->Rx_skbuff[i]) continue; - ret = rtl8169_alloc_rx_skb(tp->pci_dev, dev, tp->Rx_skbuff + i, - tp->RxDescArray + i); + ret = rtl8169_alloc_rx_skb(tp->pci_dev, tp->Rx_skbuff + i, + tp->RxDescArray + i, tp->rx_buf_sz); if (ret < 0) break; } @@ -1440,7 +1617,7 @@ static u32 rtl8169_rx_fill(struct rtl816 static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc) { - desc->status |= cpu_to_le32(EORbit); + desc->opts1 |= cpu_to_le32(RingEnd); } static int rtl8169_init_ring(struct net_device *dev) @@ -1449,10 +1626,8 @@ static int rtl8169_init_ring(struct net_ tp->cur_rx = tp->dirty_rx = 0; tp->cur_tx = tp->dirty_tx = 0; - memset(tp->TxDescArray, 0x0, NUM_TX_DESC * sizeof (struct TxDesc)); - memset(tp->RxDescArray, 0x0, NUM_RX_DESC * sizeof (struct RxDesc)); - memset(tp->Tx_skbuff, 0x0, NUM_TX_DESC * sizeof(struct sk_buff *)); + memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC) @@ -1467,33 +1642,39 @@ err_out: return -ENOMEM; } -static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff, +static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct ring_info *tx_skb, struct TxDesc *desc) { - u32 len = sk_buff[0]->len; + unsigned int len = tx_skb->len; - pci_unmap_single(pdev, le64_to_cpu(desc->addr), - len < ETH_ZLEN ? ETH_ZLEN : len, PCI_DMA_TODEVICE); + pci_unmap_single(pdev, le64_to_cpu(desc->addr), len, PCI_DMA_TODEVICE); + desc->opts2 = 0x00; desc->addr = 0x00; - *sk_buff = NULL; + tx_skb->len = 0; } -static void -rtl8169_tx_clear(struct rtl8169_private *tp) +static void rtl8169_tx_clear(struct rtl8169_private *tp) { - int i; + unsigned int i; - tp->cur_tx = 0; - for (i = 0; i < NUM_TX_DESC; i++) { - struct sk_buff *skb = tp->Tx_skbuff[i]; + for (i = tp->dirty_tx; i < tp->dirty_tx + NUM_TX_DESC; i++) { + unsigned int entry = i % NUM_TX_DESC; + struct ring_info *tx_skb = tp->tx_skb + entry; + unsigned int len = tx_skb->len; - if (skb) { - rtl8169_unmap_tx_skb(tp->pci_dev, tp->Tx_skbuff + i, - tp->TxDescArray + i); - dev_kfree_skb(skb); + if (len) { + struct sk_buff *skb = tx_skb->skb; + + rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, + tp->TxDescArray + entry); + if (skb) { + dev_kfree_skb(skb); + tx_skb->skb = NULL; + } tp->stats.tx_dropped++; } } + tp->cur_tx = tp->dirty_tx = 0; } static void @@ -1523,51 +1704,122 @@ rtl8169_tx_timeout(struct net_device *de netif_wake_queue(dev); } -static int -rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) +static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, + u32 opts1) +{ + struct skb_shared_info *info = skb_shinfo(skb); + unsigned int cur_frag, entry; + struct TxDesc *txd; + + entry = tp->cur_tx; + for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) { + skb_frag_t *frag = info->frags + cur_frag; + dma_addr_t mapping; + u32 status, len; + void *addr; + + entry = (entry + 1) % NUM_TX_DESC; + + txd = tp->TxDescArray + entry; + len = frag->size; + addr = ((void *) page_address(frag->page)) + frag->page_offset; + mapping = pci_map_single(tp->pci_dev, addr, len, PCI_DMA_TODEVICE); + + /* anti gcc 2.95.3 bugware (sic) */ + status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); + + txd->opts1 = cpu_to_le32(status); + txd->addr = cpu_to_le64(mapping); + + tp->tx_skb[entry].len = len; + } + + if (cur_frag) { + tp->tx_skb[entry].skb = skb; + txd->opts1 |= cpu_to_le32(LastFrag); + } + + return cur_frag; +} + +static inline u32 rtl8169_tx_csum(struct sk_buff *skb) +{ + if (skb->ip_summed == CHECKSUM_HW) { + const struct iphdr *ip = skb->nh.iph; + + if (ip->protocol == IPPROTO_TCP) + return IPCS | TCPCS; + else if (ip->protocol == IPPROTO_UDP) + return IPCS | UDPCS; + BUG(); + } + return 0; +} + +static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); + unsigned int frags, entry = tp->cur_tx % NUM_TX_DESC; + struct TxDesc *txd = tp->TxDescArray + entry; void *ioaddr = tp->mmio_addr; - unsigned int entry = tp->cur_tx % NUM_TX_DESC; - u32 len = skb->len; + dma_addr_t mapping; + u32 status, len; + u32 opts1; + + if (unlikely(tp->cur_tx - tp->dirty_tx < skb_shinfo(skb)->nr_frags)) { + netif_stop_queue(dev); + printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n", + dev->name); + return 1; + } + + if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) + goto err_drop; + + opts1 = DescOwn | rtl8169_tx_csum(skb); + + frags = rtl8169_xmit_frags(tp, skb, opts1); + if (frags) { + len = skb_headlen(skb); + opts1 |= FirstFrag; + } else { + len = skb->len; + + if (unlikely(len < ETH_ZLEN)) { + skb = skb_padto(skb, ETH_ZLEN); + if (!skb) + goto err_update_stats; + len = ETH_ZLEN; + } - if (unlikely(skb->len < ETH_ZLEN)) { - skb = skb_padto(skb, ETH_ZLEN); - if (!skb) - goto err_update_stats; - len = ETH_ZLEN; + opts1 |= FirstFrag | LastFrag; + tp->tx_skb[entry].skb = skb; } - - if (!(le32_to_cpu(tp->TxDescArray[entry].status) & OWNbit)) { - dma_addr_t mapping; - u32 status; - mapping = pci_map_single(tp->pci_dev, skb->data, len, - PCI_DMA_TODEVICE); + mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE); - tp->Tx_skbuff[entry] = skb; - tp->TxDescArray[entry].addr = cpu_to_le64(mapping); + tp->tx_skb[entry].len = len; + txd->addr = cpu_to_le64(mapping); + txd->opts2 = rtl8169_tx_vlan_tag(tp, skb); - /* anti gcc 2.95.3 bugware */ - status = OWNbit | FSbit | LSbit | len | - (EORbit * !((entry + 1) % NUM_TX_DESC)); - tp->TxDescArray[entry].status = cpu_to_le32(status); - - RTL_W8(TxPoll, 0x40); //set polling bit + wmb(); - dev->trans_start = jiffies; + /* anti gcc 2.95.3 bugware (sic) */ + status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); + txd->opts1 = cpu_to_le32(status); - tp->cur_tx++; - smp_wmb(); - } else - goto err_drop; + dev->trans_start = jiffies; - if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) { - u32 dirty = tp->dirty_tx; - + tp->cur_tx += frags + 1; + + smp_wmb(); + + RTL_W8(TxPoll, 0x40); //set polling bit + + if (tp->cur_tx - tp->dirty_tx < MAX_SKB_FRAGS) { netif_stop_queue(dev); smp_rmb(); - if (dirty != tp->dirty_tx) + if (tp->cur_tx - tp->dirty_tx >= MAX_SKB_FRAGS) netif_wake_queue(dev); } @@ -1597,22 +1849,24 @@ rtl8169_tx_interrupt(struct net_device * while (tx_left > 0) { unsigned int entry = dirty_tx % NUM_TX_DESC; - struct sk_buff *skb = tp->Tx_skbuff[entry]; + struct ring_info *tx_skb = tp->tx_skb + entry; + u32 len = tx_skb->len; u32 status; rmb(); - status = le32_to_cpu(tp->TxDescArray[entry].status); - if (status & OWNbit) + status = le32_to_cpu(tp->TxDescArray[entry].opts1); + if (status & DescOwn) break; - /* FIXME: is it really accurate for TxErr ? */ - tp->stats.tx_bytes += skb->len >= ETH_ZLEN ? - skb->len : ETH_ZLEN; + tp->stats.tx_bytes += len; tp->stats.tx_packets++; - rtl8169_unmap_tx_skb(tp->pci_dev, tp->Tx_skbuff + entry, - tp->TxDescArray + entry); - dev_kfree_skb_irq(skb); - tp->Tx_skbuff[entry] = NULL; + + rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, tp->TxDescArray + entry); + + if (status & LastFrag) { + dev_kfree_skb_irq(tx_skb->skb); + tx_skb->skb = NULL; + } dirty_tx++; tx_left--; } @@ -1625,9 +1879,21 @@ rtl8169_tx_interrupt(struct net_device * } } +static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc) +{ + u32 opts1 = desc->opts1; + u32 status = opts1 & RxProtoMask; + + if (((status == RxProtoTCP) && !(opts1 & TCPFail)) || + ((status == RxProtoUDP) && !(opts1 & UDPFail)) || + ((status == RxProtoIP) && !(opts1 & IPFail))) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb->ip_summed = CHECKSUM_NONE; +} + static inline int rtl8169_try_rx_copy(struct sk_buff **sk_buff, int pkt_size, - struct RxDesc *desc, - struct net_device *dev) + struct RxDesc *desc, int rx_buf_sz) { int ret = -1; @@ -1636,11 +1902,10 @@ static inline int rtl8169_try_rx_copy(st skb = dev_alloc_skb(pkt_size + 2); if (skb) { - skb->dev = dev; skb_reserve(skb, 2); eth_copy_and_sum(skb, sk_buff[0]->tail, pkt_size, 0); *sk_buff = skb; - rtl8169_return_to_asic(desc); + rtl8169_return_to_asic(desc, rx_buf_sz); ret = 0; } } @@ -1667,9 +1932,9 @@ rtl8169_rx_interrupt(struct net_device * u32 status; rmb(); - status = le32_to_cpu(tp->RxDescArray[entry].status); + status = le32_to_cpu(tp->RxDescArray[entry].opts1); - if (status & OWNbit) + if (status & DescOwn) break; if (status & RxRES) { printk(KERN_INFO "%s: Rx ERROR!!!\n", dev->name); @@ -1685,22 +1950,27 @@ rtl8169_rx_interrupt(struct net_device * void (*pci_action)(struct pci_dev *, dma_addr_t, size_t, int) = pci_dma_sync_single_for_device; - + rtl8169_rx_csum(skb, desc); + pci_dma_sync_single_for_cpu(tp->pci_dev, - le64_to_cpu(desc->addr), RX_BUF_SIZE, + le64_to_cpu(desc->addr), tp->rx_buf_sz, PCI_DMA_FROMDEVICE); - if (rtl8169_try_rx_copy(&skb, pkt_size, desc, dev)) { + if (rtl8169_try_rx_copy(&skb, pkt_size, desc, + tp->rx_buf_sz)) { pci_action = pci_unmap_single; tp->Rx_skbuff[entry] = NULL; } pci_action(tp->pci_dev, le64_to_cpu(desc->addr), - RX_BUF_SIZE, PCI_DMA_FROMDEVICE); + tp->rx_buf_sz, PCI_DMA_FROMDEVICE); + skb->dev = dev; skb_put(skb, pkt_size); skb->protocol = eth_type_trans(skb, dev); - rtl8169_rx_skb(skb); + + if (rtl8169_rx_vlan_skb(tp, desc, skb) < 0) + rtl8169_rx_skb(skb); dev->last_rx = jiffies; tp->stats.rx_bytes += pkt_size; diff -puN drivers/net/sk_mca.c~bk-netdev drivers/net/sk_mca.c --- 25/drivers/net/sk_mca.c~bk-netdev 2004-09-15 21:06:53.288642616 -0700 +++ 25-akpm/drivers/net/sk_mca.c 2004-09-15 21:06:53.416623160 -0700 @@ -972,14 +972,6 @@ static struct net_device_stats *skmca_st return &(priv->stat); } -/* we don't support runtime reconfiguration, since an MCA card can - be unambigously identified by its POS registers. */ - -static int skmca_config(struct net_device *dev, struct ifmap *map) -{ - return 0; -} - /* switch receiver mode. We use the LANCE's multicast filter to prefilter multicast addresses. */ @@ -1147,7 +1139,6 @@ struct net_device * __init skmca_probe(i /* set methods */ dev->open = skmca_open; dev->stop = skmca_close; - dev->set_config = skmca_config; dev->hard_start_xmit = skmca_tx; dev->do_ioctl = NULL; dev->get_stats = skmca_stats; diff -puN drivers/net/starfire.c~bk-netdev drivers/net/starfire.c --- 25/drivers/net/starfire.c~bk-netdev 2004-09-15 21:06:53.290642312 -0700 +++ 25-akpm/drivers/net/starfire.c 2004-09-15 21:06:53.419622704 -0700 @@ -799,12 +799,13 @@ static struct net_device_stats *get_stat static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static int netdev_close(struct net_device *dev); static void netdev_media_change(struct net_device *dev); +static struct ethtool_ops ethtool_ops; #ifdef VLAN_SUPPORT static void netdev_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); spin_lock(&np->lock); if (debug > 2) @@ -816,7 +817,7 @@ static void netdev_vlan_rx_register(stru static void netdev_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); spin_lock(&np->lock); if (debug > 1) @@ -827,7 +828,7 @@ static void netdev_vlan_rx_add_vid(struc static void netdev_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); spin_lock(&np->lock); if (debug > 1) @@ -951,7 +952,7 @@ static int __devinit starfire_init_one(s dev->base_addr = ioaddr; dev->irq = irq; - np = dev->priv; + np = netdev_priv(dev); spin_lock_init(&np->lock); pci_set_drvdata(pdev, dev); @@ -1015,6 +1016,7 @@ static int __devinit starfire_init_one(s dev->get_stats = &get_stats; dev->set_multicast_list = &set_rx_mode; dev->do_ioctl = &netdev_ioctl; + SET_ETHTOOL_OPS(dev, ðtool_ops); if (mtu) dev->mtu = mtu; @@ -1102,7 +1104,7 @@ static void mdio_write(struct net_device static int netdev_open(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); long ioaddr = dev->base_addr; int i, retval; size_t tx_done_q_size, rx_done_q_size, tx_ring_size, rx_ring_size; @@ -1267,7 +1269,7 @@ static int netdev_open(struct net_device static void check_duplex(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); u16 reg0; int silly_count = 1000; @@ -1302,7 +1304,7 @@ static void check_duplex(struct net_devi static void tx_timeout(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); long ioaddr = dev->base_addr; int old_debug; @@ -1332,7 +1334,7 @@ static void tx_timeout(struct net_device /* Initialize the Rx and Tx rings, along with various 'dev' bits. */ static void init_ring(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int i; np->cur_rx = np->cur_tx = np->reap_tx = 0; @@ -1378,7 +1380,7 @@ static void init_ring(struct net_device static int start_tx(struct sk_buff *skb, struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); unsigned int entry; u32 status; int i; @@ -1497,7 +1499,7 @@ static irqreturn_t intr_handler(int irq, int handled = 0; ioaddr = dev->base_addr; - np = dev->priv; + np = netdev_priv(dev); do { u32 intr_status = readl(ioaddr + IntrClear); @@ -1597,7 +1599,7 @@ static irqreturn_t intr_handler(int irq, for clarity, code sharing between NAPI/non-NAPI, and better register allocation. */ static int __netdev_rx(struct net_device *dev, int *quota) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); u32 desc_status; int retcode = 0; @@ -1752,7 +1754,7 @@ static int netdev_poll(struct net_device static void refill_rx_ring(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); struct sk_buff *skb; int entry = -1; @@ -1780,7 +1782,7 @@ static void refill_rx_ring(struct net_de static void netdev_media_change(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); long ioaddr = dev->base_addr; u16 reg0, reg1, reg4, reg5; u32 new_tx_mode; @@ -1855,7 +1857,7 @@ static void netdev_media_change(struct n static void netdev_error(struct net_device *dev, int intr_status) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); /* Came close to underrunning the Tx FIFO, increase threshold. */ if (intr_status & IntrTxDataLow) { @@ -1883,7 +1885,7 @@ static void netdev_error(struct net_devi static struct net_device_stats *get_stats(struct net_device *dev) { long ioaddr = dev->base_addr; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); /* This adapter architecture needs no SMP locks. */ np->stats.tx_bytes = readl(ioaddr + 0x57010); @@ -1917,7 +1919,7 @@ static void set_rx_mode(struct net_devic struct dev_mc_list *mclist; int i; #ifdef VLAN_SUPPORT - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); rx_mode |= VlanMode; if (np->vlgrp) { @@ -1996,106 +1998,89 @@ static void set_rx_mode(struct net_devic writel(rx_mode, ioaddr + RxFilterMode); } +static int check_if_running(struct net_device *dev) +{ + if (!netif_running(dev)) + return -EINVAL; + return 0; +} -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 ethtool_cmd ecmd; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); + strcpy(info->bus_info, PCI_SLOT_NAME(np->pci_dev)); +} - if (copy_from_user(&ecmd, useraddr, sizeof(ecmd))) - return -EFAULT; +static int get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct netdev_private *np = netdev_priv(dev); + spin_lock_irq(&np->lock); + mii_ethtool_gset(&np->mii_if, ecmd); + spin_unlock_irq(&np->lock); + return 0; +} - switch (ecmd.cmd) { - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info; - memset(&info, 0, sizeof(info)); - info.cmd = ecmd.cmd; - strcpy(info.driver, DRV_NAME); - strcpy(info.version, DRV_VERSION); - *info.fw_version = 0; - strcpy(info.bus_info, PCI_SLOT_NAME(np->pci_dev)); - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; - } +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 = mii_ethtool_sset(&np->mii_if, ecmd); + spin_unlock_irq(&np->lock); + check_duplex(dev); + return res; +} - /* get settings */ - case ETHTOOL_GSET: { - struct ethtool_cmd ecmd = { ETHTOOL_GSET }; - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii_if, &ecmd); - spin_unlock_irq(&np->lock); - if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) - return -EFAULT; - 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_if, &ecmd); - spin_unlock_irq(&np->lock); - check_duplex(dev); - return r; - } - /* restart autonegotiation */ - case ETHTOOL_NWAY_RST: { - return mii_nway_restart(&np->mii_if); - } - /* get link status */ - case ETHTOOL_GLINK: { - struct ethtool_value edata = {ETHTOOL_GLINK}; - edata.data = mii_link_ok(&np->mii_if); - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } +static int nway_reset(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + return mii_nway_restart(&np->mii_if); +} - /* 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; - } - default: - return -EOPNOTSUPP; - } +static u32 get_link(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + return mii_link_ok(&np->mii_if); } +static u32 get_msglevel(struct net_device *dev) +{ + return debug; +} + +static void set_msglevel(struct net_device *dev, u32 val) +{ + debug = val; +} + +static struct ethtool_ops ethtool_ops = { + .begin = check_if_running, + .get_drvinfo = get_drvinfo, + .get_settings = get_settings, + .set_settings = set_settings, + .nway_reset = nway_reset, + .get_link = get_link, + .get_msglevel = get_msglevel, + .set_msglevel = set_msglevel, +}; static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); + struct mii_ioctl_data *data = if_mii(rq); int rc; if (!netif_running(dev)) return -EINVAL; - if (cmd == SIOCETHTOOL) - rc = netdev_ethtool_ioctl(dev, rq->ifr_data); + spin_lock_irq(&np->lock); + rc = generic_mii_ioctl(&np->mii_if, data, cmd, NULL); + spin_unlock_irq(&np->lock); - else { - struct mii_ioctl_data *data = if_mii(rq); - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii_if, data, cmd, NULL); - spin_unlock_irq(&np->lock); - - if ((cmd == SIOCSMIIREG) && (data->phy_id == np->phys[0])) - check_duplex(dev); - } + if ((cmd == SIOCSMIIREG) && (data->phy_id == np->phys[0])) + check_duplex(dev); return rc; } @@ -2103,7 +2088,7 @@ static int netdev_ioctl(struct net_devic static int netdev_close(struct net_device *dev) { long ioaddr = dev->base_addr; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int i; netif_stop_queue(dev); @@ -2174,16 +2159,16 @@ static int netdev_close(struct net_devic static void __devexit starfire_remove_one (struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - struct netdev_private *np; + struct netdev_private *np = netdev_priv(dev); if (!dev) BUG(); - np = dev->priv; + unregister_netdev(dev); + if (np->queue_mem) pci_free_consistent(pdev, np->queue_mem_size, np->queue_mem, np->queue_mem_dma); - unregister_netdev(dev); /* XXX: add wakeup code -- requires firmware for MagicPacket */ pci_set_power_state(pdev, 3); /* go to sleep in D3 mode */ diff -puN drivers/net/sundance.c~bk-netdev drivers/net/sundance.c --- 25/drivers/net/sundance.c~bk-netdev 2004-09-15 21:06:53.291642160 -0700 +++ 25-akpm/drivers/net/sundance.c 2004-09-15 21:06:53.422622248 -0700 @@ -511,8 +511,7 @@ static int __set_mac_addr(struct net_dev static struct net_device_stats *get_stats(struct net_device *dev); static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static int netdev_close(struct net_device *dev); - - +static struct ethtool_ops ethtool_ops; static int __devinit sundance_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent) @@ -567,7 +566,7 @@ static int __devinit sundance_probe1 (st dev->base_addr = ioaddr; dev->irq = irq; - np = dev->priv; + np = netdev_priv(dev); np->pci_dev = pdev; np->chip_id = chip_idx; np->msg_enable = (1 << debug) - 1; @@ -600,6 +599,7 @@ static int __devinit sundance_probe1 (st dev->get_stats = &get_stats; dev->set_multicast_list = &set_rx_mode; dev->do_ioctl = &netdev_ioctl; + SET_ETHTOOL_OPS(dev, ðtool_ops); dev->tx_timeout = &tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; dev->change_mtu = &change_mtu; @@ -787,7 +787,7 @@ static void mdio_sync(long mdio_addr) static int mdio_read(struct net_device *dev, int phy_id, int location) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); long mdio_addr = dev->base_addr + MIICtrl; int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; int i, retval = 0; @@ -817,7 +817,7 @@ static int mdio_read(struct net_device * static void mdio_write(struct net_device *dev, int phy_id, int location, int value) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); long mdio_addr = dev->base_addr + MIICtrl; int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value; int i; @@ -846,7 +846,7 @@ static void mdio_write(struct net_device static int netdev_open(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); long ioaddr = dev->base_addr; int i; @@ -916,7 +916,7 @@ static int netdev_open(struct net_device static void check_duplex(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); long ioaddr = dev->base_addr; int mii_lpa = mdio_read(dev, np->phys[0], MII_LPA); int negotiated = mii_lpa & np->mii_if.advertising; @@ -945,7 +945,7 @@ static void check_duplex(struct net_devi static void netdev_timer(unsigned long data) { struct net_device *dev = (struct net_device *)data; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); long ioaddr = dev->base_addr; int next_tick = 10*HZ; @@ -962,7 +962,7 @@ static void netdev_timer(unsigned long d static void tx_timeout(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); long ioaddr = dev->base_addr; unsigned long flag; @@ -1015,7 +1015,7 @@ static void tx_timeout(struct net_device /* Initialize the Rx and Tx rings, along with various 'dev' bits. */ static void init_ring(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int i; np->cur_rx = np->cur_tx = 0; @@ -1058,7 +1058,7 @@ static void init_ring(struct net_device static void tx_poll (unsigned long data) { struct net_device *dev = (struct net_device *)data; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); unsigned head = np->cur_task % TX_RING_SIZE; struct netdev_desc *txdesc = &np->tx_ring[(np->cur_tx - 1) % TX_RING_SIZE]; @@ -1085,7 +1085,7 @@ static void tx_poll (unsigned long data) static int start_tx (struct sk_buff *skb, struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); struct netdev_desc *txdesc; unsigned entry; @@ -1127,7 +1127,7 @@ start_tx (struct sk_buff *skb, struct ne static int reset_tx (struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); long ioaddr = dev->base_addr; struct sk_buff *skb; int i; @@ -1176,7 +1176,7 @@ static irqreturn_t intr_handler(int irq, int handled = 0; ioaddr = dev->base_addr; - np = dev->priv; + np = netdev_priv(dev); do { int intr_status = readw(ioaddr + IntrStatus); @@ -1301,7 +1301,7 @@ static irqreturn_t intr_handler(int irq, static void rx_poll(unsigned long data) { struct net_device *dev = (struct net_device *)data; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int entry = np->cur_rx % RX_RING_SIZE; int boguscnt = np->budget; long ioaddr = dev->base_addr; @@ -1398,7 +1398,7 @@ not_done: static void refill_rx (struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int entry; int cnt = 0; @@ -1429,7 +1429,7 @@ static void refill_rx (struct net_device static void netdev_error(struct net_device *dev, int intr_status) { long ioaddr = dev->base_addr; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); u16 mii_ctl, mii_advertise, mii_lpa; int speed; @@ -1483,7 +1483,7 @@ static void netdev_error(struct net_devi static struct net_device_stats *get_stats(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); long ioaddr = dev->base_addr; int i; @@ -1512,7 +1512,7 @@ static struct net_device_stats *get_stat static void set_rx_mode(struct net_device *dev) { long ioaddr = dev->base_addr; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); u16 mc_filter[4]; /* Multicast hash filter */ u32 rx_mode; int i; @@ -1565,91 +1565,79 @@ static int __set_mac_addr(struct net_dev writew(addr16, dev->base_addr + StationAddr+4); return 0; } - -static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr) +static int check_if_running(struct net_device *dev) { - struct netdev_private *np = dev->priv; - u32 ethcmd; + if (!netif_running(dev)) + return -EINVAL; + return 0; +} - if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) - return -EFAULT; +static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + struct netdev_private *np = netdev_priv(dev); + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); + strcpy(info->bus_info, pci_name(np->pci_dev)); +} - switch (ethcmd) { - /* get constant driver settings/info */ - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; - strcpy(info.driver, DRV_NAME); - strcpy(info.version, DRV_VERSION); - strcpy(info.bus_info, pci_name(np->pci_dev)); - memset(&info.fw_version, 0, sizeof(info.fw_version)); - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; - } +static int get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct netdev_private *np = netdev_priv(dev); + spin_lock_irq(&np->lock); + mii_ethtool_gset(&np->mii_if, ecmd); + spin_unlock_irq(&np->lock); + return 0; +} - /* get media settings */ - case ETHTOOL_GSET: { - struct ethtool_cmd ecmd = { ETHTOOL_GSET }; - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii_if, &ecmd); - spin_unlock_irq(&np->lock); - if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; - } - /* set media 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_if, &ecmd); - spin_unlock_irq(&np->lock); - return r; - } - - /* restart autonegotiation */ - case ETHTOOL_NWAY_RST: { - return mii_nway_restart(&np->mii_if); - } - - /* get link status */ - case ETHTOOL_GLINK: { - struct ethtool_value edata = {ETHTOOL_GLINK}; - edata.data = mii_link_ok(&np->mii_if); - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } +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 = mii_ethtool_sset(&np->mii_if, ecmd); + spin_unlock_irq(&np->lock); + return res; +} - /* 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; - } +static int nway_reset(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + return mii_nway_restart(&np->mii_if); +} + +static u32 get_link(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + return mii_link_ok(&np->mii_if); +} - default: - return -EOPNOTSUPP; +static u32 get_msglevel(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + return np->msg_enable; +} - } +static void set_msglevel(struct net_device *dev, u32 val) +{ + struct netdev_private *np = netdev_priv(dev); + np->msg_enable = val; } +static struct ethtool_ops ethtool_ops = { + .begin = check_if_running, + .get_drvinfo = get_drvinfo, + .get_settings = get_settings, + .set_settings = set_settings, + .nway_reset = nway_reset, + .get_link = get_link, + .get_msglevel = get_msglevel, + .set_msglevel = set_msglevel, +}; + static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int rc; int i; long ioaddr = dev->base_addr; @@ -1657,14 +1645,9 @@ static int netdev_ioctl(struct net_devic if (!netif_running(dev)) return -EINVAL; - if (cmd == SIOCETHTOOL) - rc = netdev_ethtool_ioctl(dev, rq->ifr_data); - - else { - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii_if, if_mii(rq), cmd, NULL); - spin_unlock_irq(&np->lock); - } + spin_lock_irq(&np->lock); + rc = generic_mii_ioctl(&np->mii_if, if_mii(rq), cmd, NULL); + spin_unlock_irq(&np->lock); switch (cmd) { case SIOCDEVPRIVATE: for (i=0; ibase_addr; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); struct sk_buff *skb; int i; @@ -1775,7 +1758,7 @@ static void __devexit sundance_remove1 ( struct net_device *dev = pci_get_drvdata(pdev); if (dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); unregister_netdev(dev); pci_free_consistent(pdev, RX_TOTAL_SIZE, np->rx_ring, diff -puN drivers/net/tulip/de4x5.c~bk-netdev drivers/net/tulip/de4x5.c --- 25/drivers/net/tulip/de4x5.c~bk-netdev 2004-09-15 21:06:53.294641704 -0700 +++ 25-akpm/drivers/net/tulip/de4x5.c 2004-09-15 21:06:53.426621640 -0700 @@ -5089,7 +5089,7 @@ mii_get_phy(struct net_device *dev) lp->useMII = TRUE; /* Search the MII address space for possible PHY devices */ - for (n=0, lp->mii_cnt=0, i=1; !((i==1) && (n==1)); i=(++i)%DE4X5_MAX_MII) { + for (n=0, lp->mii_cnt=0, i=1; !((i==1) && (n==1)); i=(i+1)%DE4X5_MAX_MII) { lp->phy[lp->active].addr = i; if (i==0) n++; /* Count cycles */ while (de4x5_reset_phy(dev)<0) udelay(100);/* Wait for reset */ diff -puN drivers/net/tulip/tulip_core.c~bk-netdev drivers/net/tulip/tulip_core.c --- 25/drivers/net/tulip/tulip_core.c~bk-netdev 2004-09-15 21:06:53.295641552 -0700 +++ 25-akpm/drivers/net/tulip/tulip_core.c 2004-09-15 21:06:53.428621336 -0700 @@ -830,30 +830,18 @@ static struct net_device_stats *tulip_ge } -static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr) +static void tulip_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { struct tulip_private *np = netdev_priv(dev); - u32 ethcmd; - - if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) - return -EFAULT; - - switch (ethcmd) { - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; - strcpy(info.driver, DRV_NAME); - strcpy(info.version, DRV_VERSION); - strcpy(info.bus_info, pci_name(np->pdev)); - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; - } - - } - - return -EOPNOTSUPP; + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); + strcpy(info->bus_info, pci_name(np->pdev)); } +static struct ethtool_ops ops = { + .get_drvinfo = tulip_get_drvinfo +}; + /* Provide ioctl() calls to examine the MII xcvr state. */ static int private_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) { @@ -865,9 +853,6 @@ static int private_ioctl (struct net_dev unsigned int regnum = data->reg_num; switch (cmd) { - case SIOCETHTOOL: - return netdev_ethtool_ioctl(dev, rq->ifr_data); - case SIOCGMIIPHY: /* Get address of MII PHY in use. */ if (tp->mii_cnt) data->phy_id = phy; @@ -1644,6 +1629,7 @@ static int __devinit tulip_init_one (str #ifdef CONFIG_NET_POLL_CONTROLLER dev->poll_controller = &poll_tulip; #endif + SET_ETHTOOL_OPS(dev, &ops); if (register_netdev(dev)) goto err_out_free_ring; diff -puN drivers/net/tulip/xircom_tulip_cb.c~bk-netdev drivers/net/tulip/xircom_tulip_cb.c --- 25/drivers/net/tulip/xircom_tulip_cb.c~bk-netdev 2004-09-15 21:06:53.297641248 -0700 +++ 25-akpm/drivers/net/tulip/xircom_tulip_cb.c 2004-09-15 21:06:53.432620728 -0700 @@ -350,6 +350,7 @@ static struct net_device_stats *xircom_g static int xircom_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static void set_rx_mode(struct net_device *dev); static void check_duplex(struct net_device *dev); +static struct ethtool_ops ops; /* The Xircom cards are picky about when certain bits in CSR6 can be @@ -450,7 +451,7 @@ static void __devinit read_mac_address(s */ static void find_mii_transceivers(struct net_device *dev) { - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); int phy, phy_idx; if (media_cap[tp->default_port] & MediaIsMII) { @@ -505,7 +506,7 @@ static void find_mii_transceivers(struct */ static void transceiver_voodoo(struct net_device *dev) { - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); long ioaddr = dev->base_addr; /* Reset the chip, holding bit 0 set at least 50 PCI cycles. */ @@ -584,7 +585,7 @@ static int __devinit xircom_init_one(str /* Clear the missed-packet counter. */ (volatile int)inl(ioaddr + CSR8); - tp = dev->priv; + tp = netdev_priv(dev); tp->lock = SPIN_LOCK_UNLOCKED; tp->pdev = pdev; @@ -626,6 +627,7 @@ static int __devinit xircom_init_one(str #endif dev->tx_timeout = xircom_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; + SET_ETHTOOL_OPS(dev, &ops); transceiver_voodoo(dev); @@ -749,7 +751,7 @@ static void mdio_write(struct net_device static void xircom_up(struct net_device *dev) { - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); long ioaddr = dev->base_addr; int i; @@ -804,7 +806,7 @@ xircom_up(struct net_device *dev) static int xircom_open(struct net_device *dev) { - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); if (request_irq(dev->irq, &xircom_interrupt, SA_SHIRQ, dev->name, dev)) return -EAGAIN; @@ -818,7 +820,7 @@ xircom_open(struct net_device *dev) static void xircom_tx_timeout(struct net_device *dev) { - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); long ioaddr = dev->base_addr; if (media_cap[dev->if_port] & MediaIsMII) { @@ -870,7 +872,7 @@ static void xircom_tx_timeout(struct net /* Initialize the Rx and Tx rings, along with various 'dev' bits. */ static void xircom_init_ring(struct net_device *dev) { - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); int i; tp->tx_full = 0; @@ -919,7 +921,7 @@ static void xircom_init_ring(struct net_ static int xircom_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); int entry; u32 flag; @@ -971,7 +973,7 @@ xircom_start_xmit(struct sk_buff *skb, s static void xircom_media_change(struct net_device *dev) { - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); long ioaddr = dev->base_addr; u16 reg0, reg1, reg4, reg5; u32 csr6 = inl(ioaddr + CSR6), newcsr6; @@ -1032,7 +1034,7 @@ static void xircom_media_change(struct n static void check_duplex(struct net_device *dev) { - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); u16 reg0; mdio_write(dev, tp->phys[0], MII_BMCR, BMCR_RESET); @@ -1065,7 +1067,7 @@ static void check_duplex(struct net_devi static irqreturn_t xircom_interrupt(int irq, void *dev_instance, struct pt_regs *regs) { struct net_device *dev = dev_instance; - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); long ioaddr = dev->base_addr; int csr5, work_budget = max_interrupt_work; int handled = 0; @@ -1203,7 +1205,7 @@ static irqreturn_t xircom_interrupt(int static int xircom_rx(struct net_device *dev) { - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); int entry = tp->cur_rx % RX_RING_SIZE; int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx; int work_done = 0; @@ -1303,7 +1305,7 @@ static void xircom_down(struct net_device *dev) { long ioaddr = dev->base_addr; - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); /* Disable interrupts by clearing the interrupt mask. */ outl(0, ioaddr + CSR7); @@ -1321,7 +1323,7 @@ static int xircom_close(struct net_device *dev) { long ioaddr = dev->base_addr; - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); int i; if (xircom_debug > 1) @@ -1359,7 +1361,7 @@ xircom_close(struct net_device *dev) static struct net_device_stats *xircom_get_stats(struct net_device *dev) { - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); long ioaddr = dev->base_addr; if (netif_device_present(dev)) @@ -1368,18 +1370,10 @@ static struct net_device_stats *xircom_g return &tp->stats; } - -static int xircom_ethtool_ioctl(struct net_device *dev, void __user *useraddr) +static int xircom_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) { - struct ethtool_cmd ecmd; - struct xircom_private *tp = dev->priv; - - if (copy_from_user(&ecmd, useraddr, sizeof(ecmd))) - return -EFAULT; - - switch (ecmd.cmd) { - case ETHTOOL_GSET: - ecmd.supported = + struct xircom_private *tp = netdev_priv(dev); + ecmd->supported = SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | @@ -1387,98 +1381,90 @@ static int xircom_ethtool_ioctl(struct n SUPPORTED_Autoneg | SUPPORTED_MII; - ecmd.advertising = ADVERTISED_MII; - if (tp->advertising[0] & ADVERTISE_10HALF) - ecmd.advertising |= ADVERTISED_10baseT_Half; - if (tp->advertising[0] & ADVERTISE_10FULL) - ecmd.advertising |= ADVERTISED_10baseT_Full; - if (tp->advertising[0] & ADVERTISE_100HALF) - ecmd.advertising |= ADVERTISED_100baseT_Half; - if (tp->advertising[0] & ADVERTISE_100FULL) - ecmd.advertising |= ADVERTISED_100baseT_Full; - if (tp->autoneg) { - ecmd.advertising |= ADVERTISED_Autoneg; - ecmd.autoneg = AUTONEG_ENABLE; - } else - ecmd.autoneg = AUTONEG_DISABLE; - - ecmd.port = PORT_MII; - ecmd.transceiver = XCVR_INTERNAL; - ecmd.phy_address = tp->phys[0]; - ecmd.speed = tp->speed100 ? SPEED_100 : SPEED_10; - ecmd.duplex = tp->full_duplex ? DUPLEX_FULL : DUPLEX_HALF; - ecmd.maxtxpkt = TX_RING_SIZE / 2; - ecmd.maxrxpkt = 0; + ecmd->advertising = ADVERTISED_MII; + if (tp->advertising[0] & ADVERTISE_10HALF) + ecmd->advertising |= ADVERTISED_10baseT_Half; + if (tp->advertising[0] & ADVERTISE_10FULL) + ecmd->advertising |= ADVERTISED_10baseT_Full; + if (tp->advertising[0] & ADVERTISE_100HALF) + ecmd->advertising |= ADVERTISED_100baseT_Half; + if (tp->advertising[0] & ADVERTISE_100FULL) + ecmd->advertising |= ADVERTISED_100baseT_Full; + if (tp->autoneg) { + ecmd->advertising |= ADVERTISED_Autoneg; + ecmd->autoneg = AUTONEG_ENABLE; + } else + ecmd->autoneg = AUTONEG_DISABLE; - if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; + ecmd->port = PORT_MII; + ecmd->transceiver = XCVR_INTERNAL; + ecmd->phy_address = tp->phys[0]; + ecmd->speed = tp->speed100 ? SPEED_100 : SPEED_10; + ecmd->duplex = tp->full_duplex ? DUPLEX_FULL : DUPLEX_HALF; + ecmd->maxtxpkt = TX_RING_SIZE / 2; + ecmd->maxrxpkt = 0; + return 0; +} - case ETHTOOL_SSET: { - u16 autoneg, speed100, full_duplex; +static int xircom_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct xircom_private *tp = netdev_priv(dev); + u16 autoneg, speed100, full_duplex; - autoneg = (ecmd.autoneg == AUTONEG_ENABLE); - speed100 = (ecmd.speed == SPEED_100); - full_duplex = (ecmd.duplex == DUPLEX_FULL); - - tp->autoneg = autoneg; - if (speed100 != tp->speed100 || - full_duplex != tp->full_duplex) { - tp->speed100 = speed100; - tp->full_duplex = full_duplex; - /* change advertising bits */ - tp->advertising[0] &= ~(ADVERTISE_10HALF | - ADVERTISE_10FULL | - ADVERTISE_100HALF | - ADVERTISE_100FULL | - ADVERTISE_100BASE4); - if (speed100) { - if (full_duplex) - tp->advertising[0] |= ADVERTISE_100FULL; - else - tp->advertising[0] |= ADVERTISE_100HALF; - } else { - if (full_duplex) - tp->advertising[0] |= ADVERTISE_10FULL; - else - tp->advertising[0] |= ADVERTISE_10HALF; - } + autoneg = (ecmd->autoneg == AUTONEG_ENABLE); + speed100 = (ecmd->speed == SPEED_100); + full_duplex = (ecmd->duplex == DUPLEX_FULL); + + tp->autoneg = autoneg; + if (speed100 != tp->speed100 || + full_duplex != tp->full_duplex) { + tp->speed100 = speed100; + tp->full_duplex = full_duplex; + /* change advertising bits */ + tp->advertising[0] &= ~(ADVERTISE_10HALF | + ADVERTISE_10FULL | + ADVERTISE_100HALF | + ADVERTISE_100FULL | + ADVERTISE_100BASE4); + if (speed100) { + if (full_duplex) + tp->advertising[0] |= ADVERTISE_100FULL; + else + tp->advertising[0] |= ADVERTISE_100HALF; + } else { + if (full_duplex) + tp->advertising[0] |= ADVERTISE_10FULL; + else + tp->advertising[0] |= ADVERTISE_10HALF; } - check_duplex(dev); - return 0; - } - - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info; - memset(&info, 0, sizeof(info)); - info.cmd = ecmd.cmd; - strcpy(info.driver, DRV_NAME); - strcpy(info.version, DRV_VERSION); - *info.fw_version = 0; - strcpy(info.bus_info, pci_name(tp->pdev)); - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; } + check_duplex(dev); + return 0; +} - default: - return -EOPNOTSUPP; - } +static void xircom_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + struct xircom_private *tp = netdev_priv(dev); + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); + strcpy(info->bus_info, pci_name(tp->pdev)); } +static struct ethtool_ops ops = { + .get_settings = xircom_get_settings, + .set_settings = xircom_set_settings, + .get_drvinfo = xircom_get_drvinfo, +}; /* Provide ioctl() calls to examine the MII xcvr state. */ static int xircom_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); u16 *data = (u16 *)&rq->ifr_ifru; int phy = tp->phys[0] & 0x1f; unsigned long flags; switch(cmd) { - case SIOCETHTOOL: - return xircom_ethtool_ioctl(dev, rq->ifr_data); - /* Legacy mii-diag interface */ case SIOCGMIIPHY: /* Get address of MII PHY in use. */ if (tp->mii_cnt) @@ -1531,7 +1517,7 @@ static int xircom_ioctl(struct net_devic when re-entered but still correct. */ static void set_rx_mode(struct net_device *dev) { - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); struct dev_mc_list *mclist; long ioaddr = dev->base_addr; int csr6 = inl(ioaddr + CSR6); @@ -1672,7 +1658,7 @@ MODULE_DEVICE_TABLE(pci, xircom_pci_tabl static int xircom_suspend(struct pci_dev *pdev, u32 state) { struct net_device *dev = pci_get_drvdata(pdev); - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); printk(KERN_INFO "xircom_suspend(%s)\n", dev->name); if (tp->open) xircom_down(dev); @@ -1688,7 +1674,7 @@ static int xircom_suspend(struct pci_dev static int xircom_resume(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - struct xircom_private *tp = dev->priv; + struct xircom_private *tp = netdev_priv(dev); printk(KERN_INFO "xircom_resume(%s)\n", dev->name); pci_set_power_state(pdev,0); diff -puN drivers/net/typhoon.c~bk-netdev drivers/net/typhoon.c --- 25/drivers/net/typhoon.c~bk-netdev 2004-09-15 21:06:53.298641096 -0700 +++ 25-akpm/drivers/net/typhoon.c 2004-09-15 21:06:53.435620272 -0700 @@ -688,7 +688,7 @@ out: static void typhoon_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) { - struct typhoon *tp = (struct typhoon *) dev->priv; + struct typhoon *tp = netdev_priv(dev); struct cmd_desc xp_cmd; int err; @@ -726,7 +726,7 @@ typhoon_vlan_rx_register(struct net_devi static void typhoon_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) { - struct typhoon *tp = (struct typhoon *) dev->priv; + struct typhoon *tp = netdev_priv(dev); spin_lock_bh(&tp->state_lock); if(tp->vlgrp) tp->vlgrp->vlan_devices[vid] = NULL; @@ -757,7 +757,7 @@ typhoon_tso_fill(struct sk_buff *skb, st static int typhoon_start_tx(struct sk_buff *skb, struct net_device *dev) { - struct typhoon *tp = (struct typhoon *) dev->priv; + struct typhoon *tp = netdev_priv(dev); struct transmit_ring *txRing; struct tx_desc *txd, *first_txd; dma_addr_t skb_dma; @@ -908,7 +908,7 @@ typhoon_start_tx(struct sk_buff *skb, st static void typhoon_set_rx_mode(struct net_device *dev) { - struct typhoon *tp = (struct typhoon *) dev->priv; + struct typhoon *tp = netdev_priv(dev); struct cmd_desc xp_cmd; u32 mc_filter[2]; u16 filter; @@ -1002,7 +1002,7 @@ typhoon_do_get_stats(struct typhoon *tp) static struct net_device_stats * typhoon_get_stats(struct net_device *dev) { - struct typhoon *tp = (struct typhoon *) dev->priv; + struct typhoon *tp = netdev_priv(dev); struct net_device_stats *stats = &tp->stats; struct net_device_stats *saved = &tp->stats_saved; @@ -1155,90 +1155,55 @@ typhoon_ethtool_sset(struct typhoon *tp, return 0; } -static inline int -typhoon_ethtool_ioctl(struct net_device *dev, void __user *useraddr) +static void typhoon_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - struct typhoon *tp = (struct typhoon *) dev->priv; - u32 ethcmd; - - if(copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) - return -EFAULT; - - switch (ethcmd) { - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; - - typhoon_ethtool_gdrvinfo(tp, &info); - if(copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; - } - case ETHTOOL_GSET: { - struct ethtool_cmd cmd = { ETHTOOL_GSET }; - - typhoon_ethtool_gset(tp, &cmd); - if(copy_to_user(useraddr, &cmd, sizeof(cmd))) - return -EFAULT; - return 0; - } - case ETHTOOL_SSET: { - struct ethtool_cmd cmd; - if(copy_from_user(&cmd, useraddr, sizeof(cmd))) - return -EFAULT; - - return typhoon_ethtool_sset(tp, &cmd); - } - case ETHTOOL_GLINK:{ - struct ethtool_value edata = { ETHTOOL_GLINK }; - - edata.data = netif_carrier_ok(dev) ? 1 : 0; - if(copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - case ETHTOOL_GWOL: { - struct ethtool_wolinfo wol = { ETHTOOL_GWOL }; - - if(tp->wol_events & TYPHOON_WAKE_LINK_EVENT) - wol.wolopts |= WAKE_PHY; - if(tp->wol_events & TYPHOON_WAKE_MAGIC_PKT) - wol.wolopts |= WAKE_MAGIC; - if(copy_to_user(useraddr, &wol, sizeof(wol))) - return -EFAULT; - return 0; - } - case ETHTOOL_SWOL: { - struct ethtool_wolinfo wol; - - if(copy_from_user(&wol, useraddr, sizeof(wol))) - return -EFAULT; - tp->wol_events = 0; - if(wol.wolopts & WAKE_PHY) - tp->wol_events |= TYPHOON_WAKE_LINK_EVENT; - if(wol.wolopts & WAKE_MAGIC) - tp->wol_events |= TYPHOON_WAKE_MAGIC_PKT; - return 0; - } - default: - break; - } + struct typhoon *tp = netdev_priv(dev); + typhoon_ethtool_gdrvinfo(tp, info); +} - return -EOPNOTSUPP; +static int typhoon_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct typhoon *tp = netdev_priv(dev); + typhoon_ethtool_gset(tp, cmd); + return 0; } -static int -typhoon_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +static int typhoon_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - switch (cmd) { - case SIOCETHTOOL: - return typhoon_ethtool_ioctl(dev, ifr->ifr_data); - default: - break; - } + struct typhoon *tp = netdev_priv(dev); + typhoon_ethtool_sset(tp, cmd); + return 0; +} - return -EOPNOTSUPP; +static void typhoon_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct typhoon *tp = netdev_priv(dev); + if (tp->wol_events & TYPHOON_WAKE_LINK_EVENT) + wol->wolopts |= WAKE_PHY; + if (tp->wol_events & TYPHOON_WAKE_MAGIC_PKT) + wol->wolopts |= WAKE_MAGIC; +} + +static int typhoon_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct typhoon *tp = netdev_priv(dev); + tp->wol_events = 0; + if (wol->wolopts & WAKE_PHY) + tp->wol_events |= TYPHOON_WAKE_LINK_EVENT; + if (wol->wolopts & WAKE_MAGIC) + tp->wol_events |= TYPHOON_WAKE_MAGIC_PKT; + return 0; } +static struct ethtool_ops ops = { + .get_drvinfo = typhoon_get_drvinfo, + .get_settings = typhoon_get_settings, + .set_settings = typhoon_set_settings, + .get_link = ethtool_op_get_link, + .get_wol = typhoon_get_wol, + .set_wol = typhoon_set_wol, +}; + static int typhoon_wait_interrupt(unsigned long ioaddr) { @@ -1756,7 +1721,7 @@ typhoon_fill_free_ring(struct typhoon *t static int typhoon_poll(struct net_device *dev, int *total_budget) { - struct typhoon *tp = (struct typhoon *) dev->priv; + struct typhoon *tp = netdev_priv(dev); struct typhoon_indexes *indexes = tp->indexes; int orig_budget = *total_budget; int budget, work_done, done; @@ -2068,7 +2033,7 @@ typhoon_stop_runtime(struct typhoon *tp, static void typhoon_tx_timeout(struct net_device *dev) { - struct typhoon *tp = (struct typhoon *) dev->priv; + struct typhoon *tp = netdev_priv(dev); if(typhoon_reset(dev->base_addr, WaitNoSleep) < 0) { printk(KERN_WARNING "%s: could not reset in tx timeout\n", @@ -2098,7 +2063,7 @@ truely_dead: static int typhoon_open(struct net_device *dev) { - struct typhoon *tp = (struct typhoon *) dev->priv; + struct typhoon *tp = netdev_priv(dev); int err; err = typhoon_wakeup(tp, WaitSleep); @@ -2140,7 +2105,7 @@ out: static int typhoon_close(struct net_device *dev) { - struct typhoon *tp = (struct typhoon *) dev->priv; + struct typhoon *tp = netdev_priv(dev); netif_stop_queue(dev); @@ -2168,7 +2133,7 @@ static int typhoon_resume(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - struct typhoon *tp = (struct typhoon *) dev->priv; + struct typhoon *tp = netdev_priv(dev); /* If we're down, resume when we are upped. */ @@ -2200,7 +2165,7 @@ static int typhoon_suspend(struct pci_dev *pdev, u32 state) { struct net_device *dev = pci_get_drvdata(pdev); - struct typhoon *tp = (struct typhoon *) dev->priv; + struct typhoon *tp = netdev_priv(dev); struct cmd_desc xp_cmd; /* If we're down, we're already suspended. @@ -2366,7 +2331,7 @@ typhoon_init_one(struct pci_dev *pdev, c } dev->irq = pdev->irq; - tp = dev->priv; + tp = netdev_priv(dev); tp->shared = (struct typhoon_shared *) shared; tp->shared_dma = shared_dma; tp->pdev = pdev; @@ -2464,9 +2429,9 @@ typhoon_init_one(struct pci_dev *pdev, c dev->watchdog_timeo = TX_TIMEOUT; dev->get_stats = typhoon_get_stats; dev->set_mac_address = typhoon_set_mac_address; - dev->do_ioctl = typhoon_ioctl; dev->vlan_rx_register = typhoon_vlan_rx_register; dev->vlan_rx_kill_vid = typhoon_vlan_rx_kill_vid; + SET_ETHTOOL_OPS(dev, &ops); /* We can handle scatter gather, up to 16 entries, and * we can do IP checksumming (only version 4, doh...) @@ -2537,7 +2502,7 @@ static void __devexit typhoon_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - struct typhoon *tp = (struct typhoon *) (dev->priv); + struct typhoon *tp = netdev_priv(dev); unregister_netdev(dev); pci_set_power_state(pdev, 0); diff -puN drivers/net/wan/lmc/lmc_main.c~bk-netdev drivers/net/wan/lmc/lmc_main.c --- 25/drivers/net/wan/lmc/lmc_main.c~bk-netdev 2004-09-15 21:06:53.300640792 -0700 +++ 25-akpm/drivers/net/wan/lmc/lmc_main.c 2004-09-15 21:06:53.437619968 -0700 @@ -101,7 +101,6 @@ static int lmc_open(struct net_device *d static int lmc_close(struct net_device *dev); static struct net_device_stats *lmc_get_stats(struct net_device *dev); static irqreturn_t lmc_interrupt(int irq, void *dev_instance, struct pt_regs *regs); -static int lmc_set_config(struct net_device *dev, struct ifmap *map); static void lmc_initcsrs(lmc_softc_t * const sc, lmc_csrptr_t csr_base, size_t csr_size); static void lmc_softreset(lmc_softc_t * const); static void lmc_running_reset(struct net_device *dev); @@ -814,7 +813,6 @@ static void lmc_setup(struct net_device dev->stop = lmc_close; dev->get_stats = lmc_get_stats; dev->do_ioctl = lmc_ioctl; - dev->set_config = lmc_set_config; dev->tx_timeout = lmc_driver_timeout; dev->watchdog_timeo = (HZ); /* 1 second */ @@ -1975,13 +1973,6 @@ static void lmc_softreset (lmc_softc_t * lmc_trace(sc->lmc_device, "lmc_softreset out"); } -static int lmc_set_config(struct net_device *dev, struct ifmap *map) /*fold00*/ -{ - lmc_trace(dev, "lmc_set_config in"); - lmc_trace(dev, "lmc_set_config out"); - return -EOPNOTSUPP; -} - void lmc_gpio_mkinput(lmc_softc_t * const sc, u_int32_t bits) /*fold00*/ { lmc_trace(sc->lmc_device, "lmc_gpio_mkinput in"); diff -puN drivers/net/wireless/airo.c~bk-netdev drivers/net/wireless/airo.c --- 25/drivers/net/wireless/airo.c~bk-netdev 2004-09-15 21:06:53.302640488 -0700 +++ 25-akpm/drivers/net/wireless/airo.c 2004-09-15 21:06:53.443619056 -0700 @@ -1189,6 +1189,7 @@ struct airo_info { struct iw_statistics wstats; // wireless stats unsigned long scan_timestamp; /* Time started to scan */ struct iw_spy_data spy_data; + struct iw_public_data wireless_data; #endif /* WIRELESS_EXT */ #ifdef MICSUPPORT /* MIC stuff */ @@ -2627,8 +2628,7 @@ static void wifi_setup(struct net_device dev->set_mac_address = &airo_set_mac_address; dev->do_ioctl = &airo_ioctl; #ifdef WIRELESS_EXT - dev->get_wireless_stats = airo_get_wireless_stats; - dev->wireless_handlers = (struct iw_handler_def *)&airo_handler_def; + dev->wireless_handlers = &airo_handler_def; #endif /* WIRELESS_EXT */ dev->change_mtu = &airo_change_mtu; dev->open = &airo_open; @@ -2655,6 +2655,9 @@ static struct net_device *init_wifidev(s dev->priv = ethdev->priv; dev->irq = ethdev->irq; dev->base_addr = ethdev->base_addr; +#ifdef WIRELESS_EXT + dev->wireless_data = ethdev->wireless_data; +#endif /* WIRELESS_EXT */ memcpy(dev->dev_addr, ethdev->dev_addr, dev->addr_len); err = register_netdev(dev); if (err<0) { @@ -2734,8 +2737,9 @@ struct net_device *_init_airo_card( unsi dev->set_mac_address = &airo_set_mac_address; dev->do_ioctl = &airo_ioctl; #ifdef WIRELESS_EXT - dev->get_wireless_stats = airo_get_wireless_stats; - dev->wireless_handlers = (struct iw_handler_def *)&airo_handler_def; + dev->wireless_handlers = &airo_handler_def; + ai->wireless_data.spy_data = &ai->spy_data; + dev->wireless_data = &ai->wireless_data; #endif /* WIRELESS_EXT */ dev->change_mtu = &airo_change_mtu; dev->open = &airo_open; @@ -3218,7 +3222,7 @@ badrx: goto exitrx; } } -#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */ +#ifdef WIRELESS_SPY if (apriv->spy_data.spy_number > 0) { char *sa; struct iw_quality wstats; @@ -3238,7 +3242,7 @@ badrx: /* Update spy records */ wireless_spy_update(dev, sa, &wstats); } -#endif /* IW_WIRELESS_SPY */ +#endif /* WIRELESS_SPY */ OUT4500( apriv, EVACK, EV_RX); if (test_bit(FLAG_802_11, &apriv->flags)) { @@ -3468,7 +3472,7 @@ badmic: #else memcpy(buffer, ai->rxfids[0].virtual_host_addr, len); #endif -#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */ +#ifdef WIRELESS_SPY if (ai->spy_data.spy_number > 0) { char *sa; struct iw_quality wstats; @@ -3480,7 +3484,7 @@ badmic: /* Update spy records */ wireless_spy_update(ai->dev, sa, &wstats); } -#endif /* IW_WIRELESS_SPY */ +#endif /* WIRELESS_SPY */ skb->dev = ai->dev; skb->ip_summed = CHECKSUM_NONE; @@ -6506,6 +6510,13 @@ static int airo_get_range(struct net_dev range->avg_qual.level = 176; /* -80 dBm */ range->avg_qual.noise = 0; + /* Event capability (kernel + driver) */ + range->event_capa[0] = (IW_EVENT_CAPA_K_0 | + IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) | + IW_EVENT_CAPA_MASK(SIOCGIWAP) | + IW_EVENT_CAPA_MASK(SIOCGIWSCAN)); + range->event_capa[1] = IW_EVENT_CAPA_K_1; + range->event_capa[4] = IW_EVENT_CAPA_MASK(IWEVTXDROP); return 0; } @@ -6873,9 +6884,15 @@ static int airo_get_scan(struct net_devi while((!rc) && (BSSList.index != 0xffff)) { /* Translate to WE format this entry */ current_ev = airo_translate_scan(dev, current_ev, - extra + IW_SCAN_MAX_DATA, + extra + dwrq->length, &BSSList); + /* Check if there is space for one more entry */ + if((extra + dwrq->length - current_ev) <= IW_EV_ADDR_LEN) { + /* Ask user space to try again with a bigger buffer */ + return -E2BIG; + } + /* Read next entry */ rc = PC4500_readrid(ai, RID_BSSLISTNEXT, &BSSList, sizeof(BSSList), 1); @@ -7011,12 +7028,10 @@ static const struct iw_handler_def airo_ .num_standard = sizeof(airo_handler)/sizeof(iw_handler), .num_private = sizeof(airo_private_handler)/sizeof(iw_handler), .num_private_args = sizeof(airo_private_args)/sizeof(struct iw_priv_args), - .standard = (iw_handler *) airo_handler, - .private = (iw_handler *) airo_private_handler, - .private_args = (struct iw_priv_args *) airo_private_args, - .spy_offset = ((void *) (&((struct airo_info *) NULL)->spy_data) - - (void *) NULL), - + .standard = airo_handler, + .private = airo_private_handler, + .private_args = airo_private_args, + .get_wireless_stats = airo_get_wireless_stats, }; #endif /* WIRELESS_EXT */ diff -puN drivers/net/wireless/netwave_cs.c~bk-netdev drivers/net/wireless/netwave_cs.c --- 25/drivers/net/wireless/netwave_cs.c~bk-netdev 2004-09-15 21:06:53.304640184 -0700 +++ 25-akpm/drivers/net/wireless/netwave_cs.c 2004-09-15 21:06:53.445618752 -0700 @@ -219,7 +219,6 @@ static void netwave_reset(struct net_dev /* Misc device stuff */ static int netwave_open(struct net_device *dev); /* Open the device */ static int netwave_close(struct net_device *dev); /* Close the device */ -static int netwave_config(struct net_device *dev, struct ifmap *map); /* Packet transmission and Packet reception */ static int netwave_start_xmit( struct sk_buff *skb, struct net_device *dev); @@ -482,7 +481,6 @@ static dev_link_t *netwave_attach(void) /* Netwave specific entries in the device structure */ SET_MODULE_OWNER(dev); dev->hard_start_xmit = &netwave_start_xmit; - dev->set_config = &netwave_config; dev->get_stats = &netwave_get_stats; dev->set_multicast_list = &set_multicast_list; /* wireless extensions */ @@ -1289,16 +1287,6 @@ static void netwave_reset(struct net_dev } /* - * Function netwave_config (dev, map) - * - * Configure device, this work is done by netwave_pcmcia_config when a - * card is inserted - */ -static int netwave_config(struct net_device *dev, struct ifmap *map) { - return 0; -} - -/* * Function netwave_hw_xmit (data, len, dev) */ static int netwave_hw_xmit(unsigned char* data, int len, diff -puN drivers/net/wireless/prism54/isl_38xx.c~bk-netdev drivers/net/wireless/prism54/isl_38xx.c --- 25/drivers/net/wireless/prism54/isl_38xx.c~bk-netdev 2004-09-15 21:06:53.305640032 -0700 +++ 25-akpm/drivers/net/wireless/prism54/isl_38xx.c 2004-09-15 21:06:53.446618600 -0700 @@ -133,8 +133,8 @@ isl38xx_trigger_device(int asleep, void readl(device_base + ISL38XX_CTRL_STAT_REG)); udelay(ISL38XX_WRITEIO_DELAY); - if (reg = readl(device_base + ISL38XX_INT_IDENT_REG), - reg == 0xabadface) { + reg = readl(device_base + ISL38XX_INT_IDENT_REG); + if (reg == 0xabadface) { #if VERBOSE > SHOW_ERROR_MESSAGES do_gettimeofday(¤t_time); DEBUG(SHOW_TRACING, @@ -192,10 +192,8 @@ isl38xx_trigger_device(int asleep, void void isl38xx_interface_reset(void *device_base, dma_addr_t host_address) { - u32 reg; - #if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_FUNCTION_CALLS, "isl38xx_interface_reset \n"); + DEBUG(SHOW_FUNCTION_CALLS, "isl38xx_interface_reset\n"); #endif /* load the address of the control block in the device */ @@ -203,8 +201,7 @@ isl38xx_interface_reset(void *device_bas udelay(ISL38XX_WRITEIO_DELAY); /* set the reset bit in the Device Interrupt Register */ - isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_RESET, - ISL38XX_DEV_INT_REG); + isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_RESET, ISL38XX_DEV_INT_REG); udelay(ISL38XX_WRITEIO_DELAY); /* enable the interrupt for detecting initialization */ @@ -212,9 +209,7 @@ isl38xx_interface_reset(void *device_bas /* Note: Do not enable other interrupts here. We want the * device to have come up first 100% before allowing any other * interrupts. */ - reg = ISL38XX_INT_IDENT_INIT; - - isl38xx_w32_flush(device_base, reg, ISL38XX_INT_EN_REG); + isl38xx_w32_flush(device_base, ISL38XX_INT_IDENT_INIT, ISL38XX_INT_EN_REG); udelay(ISL38XX_WRITEIO_DELAY); /* allow complete full reset */ } diff -puN drivers/net/wireless/prism54/isl_38xx.h~bk-netdev drivers/net/wireless/prism54/isl_38xx.h --- 25/drivers/net/wireless/prism54/isl_38xx.h~bk-netdev 2004-09-15 21:06:53.306639880 -0700 +++ 25-akpm/drivers/net/wireless/prism54/isl_38xx.h 2004-09-15 21:06:53.446618600 -0700 @@ -95,6 +95,10 @@ isl38xx_w32_flush(void *base, u32 val, u #define ISL38XX_INT_SOURCES 0x001E /* Control/Status register bits */ +/* Looks like there are other meaningful bits + 0x20004400 seen in normal operation, + 0x200044db at 'timeout waiting for mgmt response' +*/ #define ISL38XX_CTRL_STAT_SLEEPMODE 0x00000200 #define ISL38XX_CTRL_STAT_CLKRUN 0x00800000 #define ISL38XX_CTRL_STAT_RESET 0x10000000 diff -puN drivers/net/wireless/prism54/isl_ioctl.c~bk-netdev drivers/net/wireless/prism54/isl_ioctl.c --- 25/drivers/net/wireless/prism54/isl_ioctl.c~bk-netdev 2004-09-15 21:06:53.308639576 -0700 +++ 25-akpm/drivers/net/wireless/prism54/isl_ioctl.c 2004-09-15 21:06:53.451617840 -0700 @@ -36,38 +36,6 @@ #include /* New driver API */ -static int init_mode = CARD_DEFAULT_IW_MODE; -static int init_channel = CARD_DEFAULT_CHANNEL; -static int init_wep = CARD_DEFAULT_WEP; -static int init_filter = CARD_DEFAULT_FILTER; -static int init_authen = CARD_DEFAULT_AUTHEN; -static int init_dot1x = CARD_DEFAULT_DOT1X; -static int init_conformance = CARD_DEFAULT_CONFORMANCE; -static int init_mlme = CARD_DEFAULT_MLME_MODE; - -module_param(init_mode, int, 0); -MODULE_PARM_DESC(init_mode, - "Set card mode:\n0: Auto\n1: Ad-Hoc\n2: Managed Client (Default)\n3: Master / Access Point\n4: Repeater (Not supported yet)\n5: Secondary (Not supported yet)\n6: Monitor"); - -module_param(init_channel, int, 0); -MODULE_PARM_DESC(init_channel, - "Check `iwpriv ethx channel` for available channels"); - -module_param(init_wep, int, 0); -module_param(init_filter, int, 0); - -module_param(init_authen, int, 0); -MODULE_PARM_DESC(init_authen, - "Authentication method. Can be of seven types:\n0 0x0000: None\n1 0x0001: DOT11_AUTH_OS (Default)\n2 0x0002: DOT11_AUTH_SK\n3 0x0003: DOT11_AUTH_BOTH"); - -module_param(init_dot1x, int, 0); -MODULE_PARM_DESC(init_dot1x, - "\n0: None/not set (Default)\n1: DOT11_DOT1X_AUTHENABLED\n2: DOT11_DOT1X_KEYTXENABLED"); - -module_param(init_mlme, int, 0); -MODULE_PARM_DESC(init_mlme, - "Sets the MAC layer management entity (MLME) mode of operation,\n0: DOT11_MLME_AUTO (Default)\n1: DOT11_MLME_INTERMEDIATE\n2: DOT11_MLME_EXTENDED"); - /** * prism54_mib_mode_helper - MIB change mode helper function * @mib: the &struct islpci_mib object to modify @@ -141,36 +109,34 @@ prism54_mib_mode_helper(islpci_private * void prism54_mib_init(islpci_private *priv) { - u32 t; + u32 channel, authen, wep, filter, dot1x, mlme, conformance, power, mode; struct obj_buffer psm_buffer = { .size = PSM_BUFFER_SIZE, .addr = priv->device_psm_buffer }; - mgt_set(priv, DOT11_OID_CHANNEL, &init_channel); - mgt_set(priv, DOT11_OID_AUTHENABLE, &init_authen); - mgt_set(priv, DOT11_OID_PRIVACYINVOKED, &init_wep); - + channel = CARD_DEFAULT_CHANNEL; + authen = CARD_DEFAULT_AUTHEN; + wep = CARD_DEFAULT_WEP; + filter = CARD_DEFAULT_FILTER; /* (0) Do not filter un-encrypted data */ + dot1x = CARD_DEFAULT_DOT1X; + mlme = CARD_DEFAULT_MLME_MODE; + conformance = CARD_DEFAULT_CONFORMANCE; + power = 127; + mode = CARD_DEFAULT_IW_MODE; + + mgt_set(priv, DOT11_OID_CHANNEL, &channel); + mgt_set(priv, DOT11_OID_AUTHENABLE, &authen); + mgt_set(priv, DOT11_OID_PRIVACYINVOKED, &wep); mgt_set(priv, DOT11_OID_PSMBUFFER, &psm_buffer); - mgt_set(priv, DOT11_OID_EXUNENCRYPTED, &init_filter); - mgt_set(priv, DOT11_OID_DOT1XENABLE, &init_dot1x); - mgt_set(priv, DOT11_OID_MLMEAUTOLEVEL, &init_mlme); - mgt_set(priv, OID_INL_DOT11D_CONFORMANCE, &init_conformance); - - t = 127; - mgt_set(priv, OID_INL_OUTPUTPOWER, &t); - - /* Important: we are setting a default wireless mode and we are - * forcing a valid one, so prism54_mib_mode_helper should just set - * mib values depending on what the wireless mode given is. No need - * for it save old values */ - if (init_mode > IW_MODE_MONITOR || init_mode < IW_MODE_AUTO) { - printk(KERN_DEBUG "%s(): You passed a non-valid init_mode. " - "Using default mode\n", __FUNCTION__); - init_mode = CARD_DEFAULT_IW_MODE; - } + mgt_set(priv, DOT11_OID_EXUNENCRYPTED, &filter); + mgt_set(priv, DOT11_OID_DOT1XENABLE, &dot1x); + mgt_set(priv, DOT11_OID_MLMEAUTOLEVEL, &mlme); + mgt_set(priv, OID_INL_DOT11D_CONFORMANCE, &conformance); + mgt_set(priv, OID_INL_OUTPUTPOWER, &power); + /* This sets all of the mode-dependent values */ - prism54_mib_mode_helper(priv, init_mode); + prism54_mib_mode_helper(priv, mode); } /* this will be executed outside of atomic context thanks to @@ -485,6 +451,15 @@ prism54_get_range(struct net_device *nde /* txpower is supported in dBm's */ range->txpower_capa = IW_TXPOW_DBM; +#if WIRELESS_EXT > 16 + /* Event capability (kernel + driver) */ + range->event_capa[0] = (IW_EVENT_CAPA_K_0 | + IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) | + IW_EVENT_CAPA_MASK(SIOCGIWAP)); + range->event_capa[1] = IW_EVENT_CAPA_K_1; + range->event_capa[4] = IW_EVENT_CAPA_MASK(IWEVCUSTOM); +#endif /* WIRELESS_EXT > 16 */ + if (islpci_get_state(priv) < PRV_STATE_INIT) return 0; @@ -629,8 +604,8 @@ prism54_translate_bss(struct net_device current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, NULL); /* Add frequency. (short) bss->channel is the frequency in MHz */ - iwe.u.freq.m = channel_of_freq(bss->channel); - iwe.u.freq.e = 0; + iwe.u.freq.m = bss->channel; + iwe.u.freq.e = 6; iwe.cmd = SIOCGIWFREQ; current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); @@ -690,19 +665,33 @@ prism54_get_scan(struct net_device *ndev rvalue = mgt_get_request(priv, DOT11_OID_NOISEFLOOR, 0, NULL, &r); noise = r.u; - /* Ask the device for a list of known bss. We can report at most - * IW_MAX_AP=64 to the range struct. But the device won't repport anything - * if you change the value of IWMAX_BSS=24. - */ + /* Ask the device for a list of known bss. + * The old API, using SIOCGIWAPLIST, had a hard limit of IW_MAX_AP=64. + * The new API, using SIOCGIWSCAN, is only limited by the buffer size. + * WE-14->WE-16, the buffer is limited to IW_SCAN_MAX_DATA bytes. + * Starting with WE-17, the buffer can be as big as needed. + * But the device won't repport anything if you change the value + * of IWMAX_BSS=24. */ + rvalue |= mgt_get_request(priv, DOT11_OID_BSSLIST, 0, NULL, &r); bsslist = r.ptr; /* ok now, scan the list and translate its info */ - for (i = 0; i < min(IW_MAX_AP, (int) bsslist->nr); i++) + for (i = 0; i < (int) bsslist->nr; i++) { current_ev = prism54_translate_bss(ndev, current_ev, - extra + IW_SCAN_MAX_DATA, + extra + dwrq->length, &(bsslist->bsslist[i]), noise); +#if WIRELESS_EXT > 16 + /* Check if there is space for one more entry */ + if((extra + dwrq->length - current_ev) <= IW_EV_ADDR_LEN) { + /* Ask user space to try again with a bigger buffer */ + rvalue = -E2BIG; + break; + } +#endif /* WIRELESS_EXT > 16 */ + } + kfree(bsslist); dwrq->length = (current_ev - extra); dwrq->flags = 0; /* todo */ @@ -1746,11 +1735,13 @@ prism54_process_trap_helper(islpci_priva char *data) { struct obj_mlme *mlme = (struct obj_mlme *) data; - size_t len; - u8 *payload, *pos = (u8 *) (mlme + 1); - - len = pos[0] | (pos[1] << 8); /* little endian data length */ - payload = pos + 2; + struct obj_mlmeex *mlmeex = (struct obj_mlmeex *) data; + struct obj_mlmeex *confirm; + u8 wpa_ie[MAX_WPA_IE_LEN]; + int wpa_ie_len; + size_t len = 0; /* u16, better? */ + u8 *payload = 0, *pos = 0; + int ret; /* I think all trapable objects are listed here. * Some oids have a EX version. The difference is that they are emitted @@ -1760,9 +1751,14 @@ prism54_process_trap_helper(islpci_priva * suited. We use the more flexible custom event facility. */ + if (oid >= DOT11_OID_BEACON) { + len = mlmeex->size; + payload = pos = mlmeex->data; + } + /* I fear prism54_process_bss_data won't work with big endian data */ if ((oid == DOT11_OID_BEACON) || (oid == DOT11_OID_PROBE)) - prism54_process_bss_data(priv, oid, mlme->address, + prism54_process_bss_data(priv, oid, mlmeex->address, payload, len); mgt_le_to_cpu(isl_oid[oid].flags & OID_FLAG_TYPE, (void *) mlme); @@ -1822,21 +1818,134 @@ prism54_process_trap_helper(islpci_priva case DOT11_OID_AUTHENTICATEEX: handle_request(priv, mlme, oid); - send_formatted_event(priv, "Authenticate request", mlme, 1); + send_formatted_event(priv, "Authenticate request (ex)", mlme, 1); + + if (priv->iw_mode != IW_MODE_MASTER + && mlmeex->state != DOT11_STATE_AUTHING) + break; + + confirm = kmalloc(sizeof(struct obj_mlmeex) + 6, GFP_ATOMIC); + + if (!confirm) + break; + + memcpy(&confirm->address, mlmeex->address, ETH_ALEN); + printk(KERN_DEBUG "Authenticate from: address:\t%02x:%02x:%02x:%02x:%02x:%02x\n", + mlmeex->address[0], + mlmeex->address[1], + mlmeex->address[2], + mlmeex->address[3], + mlmeex->address[4], + mlmeex->address[5] + ); + confirm->id = -1; /* or mlmeex->id ? */ + confirm->state = 0; /* not used */ + confirm->code = 0; + confirm->size = 6; + confirm->data[0] = 0x00; + confirm->data[1] = 0x00; + confirm->data[2] = 0x02; + confirm->data[3] = 0x00; + confirm->data[4] = 0x00; + confirm->data[5] = 0x00; + + ret = mgt_set_varlen(priv, DOT11_OID_ASSOCIATEEX, confirm, 6); + + kfree(confirm); + if (ret) + return ret; break; case DOT11_OID_DISASSOCIATEEX: - send_formatted_event(priv, "Disassociate request", mlme, 0); + send_formatted_event(priv, "Disassociate request (ex)", mlme, 0); break; case DOT11_OID_ASSOCIATEEX: handle_request(priv, mlme, oid); - send_formatted_event(priv, "Associate request", mlme, 1); + send_formatted_event(priv, "Associate request (ex)", mlme, 1); + + if (priv->iw_mode != IW_MODE_MASTER + && mlmeex->state != DOT11_STATE_AUTHING) + break; + + confirm = kmalloc(sizeof(struct obj_mlmeex), GFP_ATOMIC); + + if (!confirm) + break; + + memcpy(&confirm->address, mlmeex->address, ETH_ALEN); + + confirm->id = ((struct obj_mlmeex *)mlme)->id; + confirm->state = 0; /* not used */ + confirm->code = 0; + + wpa_ie_len = prism54_wpa_ie_get(priv, mlmeex->address, wpa_ie); + + if (!wpa_ie_len) { + printk(KERN_DEBUG "No WPA IE found from " + "address:\t%02x:%02x:%02x:%02x:%02x:%02x\n", + mlmeex->address[0], + mlmeex->address[1], + mlmeex->address[2], + mlmeex->address[3], + mlmeex->address[4], + mlmeex->address[5] + ); + kfree(confirm); + break; + } + + confirm->size = wpa_ie_len; + memcpy(&confirm->data, wpa_ie, wpa_ie_len); + + mgt_set_varlen(priv, oid, confirm, wpa_ie_len); + + kfree(confirm); + break; case DOT11_OID_REASSOCIATEEX: handle_request(priv, mlme, oid); - send_formatted_event(priv, "Reassociate request", mlme, 1); + send_formatted_event(priv, "Reassociate request (ex)", mlme, 1); + + if (priv->iw_mode != IW_MODE_MASTER + && mlmeex->state != DOT11_STATE_ASSOCING) + break; + + confirm = kmalloc(sizeof(struct obj_mlmeex), GFP_ATOMIC); + + if (!confirm) + break; + + memcpy(&confirm->address, mlmeex->address, ETH_ALEN); + + confirm->id = mlmeex->id; + confirm->state = 0; /* not used */ + confirm->code = 0; + + wpa_ie_len = prism54_wpa_ie_get(priv, mlmeex->address, wpa_ie); + + if (!wpa_ie_len) { + printk(KERN_DEBUG "No WPA IE found from " + "address:\t%02x:%02x:%02x:%02x:%02x:%02x\n", + mlmeex->address[0], + mlmeex->address[1], + mlmeex->address[2], + mlmeex->address[3], + mlmeex->address[4], + mlmeex->address[5] + ); + kfree(confirm); + break; + } + + confirm->size = wpa_ie_len; + memcpy(&confirm->data, wpa_ie, wpa_ie_len); + + mgt_set_varlen(priv, oid, confirm, wpa_ie_len); + + kfree(confirm); + break; default: @@ -1879,23 +1988,367 @@ prism54_set_mac_address(struct net_devic return ret; } +/* Note: currently, use hostapd ioctl from the Host AP driver for WPA + * support. This is to be replaced with Linux wireless extensions once they + * get WPA support. */ + +/* Note II: please leave all this together as it will be easier to remove later, + * once wireless extensions add WPA support -mcgrof */ + +/* PRISM54_HOSTAPD ioctl() cmd: */ +enum { + PRISM2_SET_ENCRYPTION = 6, + PRISM2_HOSTAPD_SET_GENERIC_ELEMENT = 12, + PRISM2_HOSTAPD_MLME = 13, + PRISM2_HOSTAPD_SCAN_REQ = 14, +}; + +#define PRISM54_SET_WPA SIOCIWFIRSTPRIV+12 +#define PRISM54_HOSTAPD SIOCIWFIRSTPRIV+25 +#define PRISM54_DROP_UNENCRYPTED SIOCIWFIRSTPRIV+26 + +#define PRISM2_HOSTAPD_MAX_BUF_SIZE 1024 +#define PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \ +((int) (&((struct prism2_hostapd_param *) 0)->u.generic_elem.data)) + +/* Maximum length for algorithm names (-1 for nul termination) + * used in ioctl() */ +#define HOSTAP_CRYPT_ALG_NAME_LEN 16 + +struct prism2_hostapd_param { + u32 cmd; + u8 sta_addr[ETH_ALEN]; + union { + struct { + u8 alg[HOSTAP_CRYPT_ALG_NAME_LEN]; + u32 flags; + u32 err; + u8 idx; + u8 seq[8]; /* sequence counter (set: RX, get: TX) */ + u16 key_len; + u8 key[0]; + } crypt; + struct { + u8 len; + u8 data[0]; + } generic_elem; + struct { +#define MLME_STA_DEAUTH 0 +#define MLME_STA_DISASSOC 1 + u16 cmd; + u16 reason_code; + } mlme; + struct { + u8 ssid_len; + u8 ssid[32]; + } scan_req; + } u; +}; + + +static int +prism2_ioctl_set_encryption(struct net_device *dev, + struct prism2_hostapd_param *param, + int param_len) +{ + islpci_private *priv = netdev_priv(dev); + int rvalue = 0, force = 0; + int authen = DOT11_AUTH_OS, invoke = 0, exunencrypt = 0; + union oid_res_t r; + + /* with the new API, it's impossible to get a NULL pointer. + * New version of iwconfig set the IW_ENCODE_NOKEY flag + * when no key is given, but older versions don't. */ + + if (param->u.crypt.key_len > 0) { + /* we have a key to set */ + int index = param->u.crypt.idx; + int current_index; + struct obj_key key = { DOT11_PRIV_TKIP, 0, "" }; + + /* get the current key index */ + rvalue = mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r); + current_index = r.u; + /* Verify that the key is not marked as invalid */ + if (!(param->u.crypt.flags & IW_ENCODE_NOKEY)) { + key.length = param->u.crypt.key_len > sizeof (param->u.crypt.key) ? + sizeof (param->u.crypt.key) : param->u.crypt.key_len; + memcpy(key.key, param->u.crypt.key, key.length); + if (key.length == 32) + /* we want WPA-PSK */ + key.type = DOT11_PRIV_TKIP; + if ((index < 0) || (index > 3)) + /* no index provided use the current one */ + index = current_index; + + /* now send the key to the card */ + rvalue |= + mgt_set_request(priv, DOT11_OID_DEFKEYX, index, + &key); + } + /* + * If a valid key is set, encryption should be enabled + * (user may turn it off later). + * This is also how "iwconfig ethX key on" works + */ + if ((index == current_index) && (key.length > 0)) + force = 1; + } else { + int index = (param->u.crypt.flags & IW_ENCODE_INDEX) - 1; + if ((index >= 0) && (index <= 3)) { + /* we want to set the key index */ + rvalue |= + mgt_set_request(priv, DOT11_OID_DEFKEYID, 0, + &index); + } else { + if (!param->u.crypt.flags & IW_ENCODE_MODE) { + /* we cannot do anything. Complain. */ + return -EINVAL; + } + } + } + /* now read the flags */ + if (param->u.crypt.flags & IW_ENCODE_DISABLED) { + /* Encoding disabled, + * authen = DOT11_AUTH_OS; + * invoke = 0; + * exunencrypt = 0; */ + } + if (param->u.crypt.flags & IW_ENCODE_OPEN) + /* Encode but accept non-encoded packets. No auth */ + invoke = 1; + if ((param->u.crypt.flags & IW_ENCODE_RESTRICTED) || force) { + /* Refuse non-encoded packets. Auth */ + authen = DOT11_AUTH_BOTH; + invoke = 1; + exunencrypt = 1; + } + /* do the change if requested */ + if ((param->u.crypt.flags & IW_ENCODE_MODE) || force) { + rvalue |= + mgt_set_request(priv, DOT11_OID_AUTHENABLE, 0, &authen); + rvalue |= + mgt_set_request(priv, DOT11_OID_PRIVACYINVOKED, 0, &invoke); + rvalue |= + mgt_set_request(priv, DOT11_OID_EXUNENCRYPTED, 0, + &exunencrypt); + } + return rvalue; +} + +static int +prism2_ioctl_set_generic_element(struct net_device *ndev, + struct prism2_hostapd_param *param, + int param_len) +{ + islpci_private *priv = netdev_priv(ndev); + int max_len, len, alen, ret=0; + struct obj_attachment *attach; + + len = param->u.generic_elem.len; + max_len = param_len - PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN; + if (max_len < 0 || max_len < len) + return -EINVAL; + + alen = sizeof(*attach) + len; + attach = kmalloc(alen, GFP_KERNEL); + if (attach == NULL) + return -ENOMEM; + + memset(attach, 0, alen); +#define WLAN_FC_TYPE_MGMT 0 +#define WLAN_FC_STYPE_ASSOC_REQ 0 +#define WLAN_FC_STYPE_REASSOC_REQ 2 + + /* Note: endianness is covered by mgt_set_varlen */ + + attach->type = (WLAN_FC_TYPE_MGMT << 2) | + (WLAN_FC_STYPE_ASSOC_REQ << 4); + attach->id = -1; + attach->size = len; + memcpy(attach->data, param->u.generic_elem.data, len); + + ret = mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, attach, len); + + if (ret == 0) { + attach->type = (WLAN_FC_TYPE_MGMT << 2) | + (WLAN_FC_STYPE_REASSOC_REQ << 4); + + ret = mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, attach, len); + + if (ret == 0) + printk(KERN_DEBUG "%s: WPA IE Attachment was set\n", + ndev->name); + } + + kfree(attach); + return ret; + +} + +static int +prism2_ioctl_mlme(struct net_device *dev, struct prism2_hostapd_param *param) +{ + return -EOPNOTSUPP; +} + +static int +prism2_ioctl_scan_req(struct net_device *ndev, + struct prism2_hostapd_param *param) +{ + islpci_private *priv = netdev_priv(ndev); + int i, rvalue; + struct obj_bsslist *bsslist; + u32 noise = 0; + char *extra = ""; + char *current_ev = "foo"; + union oid_res_t r; + + if (islpci_get_state(priv) < PRV_STATE_INIT) { + /* device is not ready, fail gently */ + return 0; + } + + /* first get the noise value. We will use it to report the link quality */ + rvalue = mgt_get_request(priv, DOT11_OID_NOISEFLOOR, 0, NULL, &r); + noise = r.u; + + /* Ask the device for a list of known bss. We can report at most + * IW_MAX_AP=64 to the range struct. But the device won't repport anything + * if you change the value of IWMAX_BSS=24. + */ + rvalue |= mgt_get_request(priv, DOT11_OID_BSSLIST, 0, NULL, &r); + bsslist = r.ptr; + + /* ok now, scan the list and translate its info */ + for (i = 0; i < min(IW_MAX_AP, (int) bsslist->nr); i++) + current_ev = prism54_translate_bss(ndev, current_ev, + extra + IW_SCAN_MAX_DATA, + &(bsslist->bsslist[i]), + noise); + kfree(bsslist); + + return rvalue; +} + +static int +prism54_hostapd(struct net_device *ndev, struct iw_point *p) +{ + struct prism2_hostapd_param *param; + int ret = 0; + u32 uwrq; + + printk(KERN_DEBUG "prism54_hostapd - len=%d\n", p->length); + if (p->length < sizeof(struct prism2_hostapd_param) || + p->length > PRISM2_HOSTAPD_MAX_BUF_SIZE || !p->pointer) + return -EINVAL; + + param = (struct prism2_hostapd_param *) kmalloc(p->length, GFP_KERNEL); + if (param == NULL) + return -ENOMEM; + + if (copy_from_user(param, p->pointer, p->length)) { + kfree(param); + return -EFAULT; + } + + switch (param->cmd) { + case PRISM2_SET_ENCRYPTION: + printk(KERN_DEBUG "%s: Caught WPA supplicant set encryption request\n", + ndev->name); + ret = prism2_ioctl_set_encryption(ndev, param, p->length); + break; + case PRISM2_HOSTAPD_SET_GENERIC_ELEMENT: + printk(KERN_DEBUG "%s: Caught WPA supplicant set WPA IE request\n", + ndev->name); + ret = prism2_ioctl_set_generic_element(ndev, param, + p->length); + break; + case PRISM2_HOSTAPD_MLME: + printk(KERN_DEBUG "%s: Caught WPA supplicant MLME request\n", + ndev->name); + ret = prism2_ioctl_mlme(ndev, param); + break; + case PRISM2_HOSTAPD_SCAN_REQ: + printk(KERN_DEBUG "%s: Caught WPA supplicant scan request\n", + ndev->name); + ret = prism2_ioctl_scan_req(ndev, param); + break; + case PRISM54_SET_WPA: + printk(KERN_DEBUG "%s: Caught WPA supplicant wpa init request\n", + ndev->name); + uwrq = 1; + ret = prism54_set_wpa(ndev, NULL, &uwrq, NULL); + break; + case PRISM54_DROP_UNENCRYPTED: + printk(KERN_DEBUG "%s: Caught WPA drop unencrypted request\n", + ndev->name); +#if 0 + uwrq = 0x01; + mgt_set(priv, DOT11_OID_EXUNENCRYPTED, &uwrq); + down_write(&priv->mib_sem); + mgt_commit(priv); + up_write(&priv->mib_sem); +#endif + /* Not necessary, as set_wpa does it, should we just do it here though? */ + ret = 0; + break; + default: + printk(KERN_DEBUG "%s: Caught a WPA supplicant request that is not supported\n", + ndev->name); + ret = -EOPNOTSUPP; + break; + } + + if (ret == 0 && copy_to_user(p->pointer, param, p->length)) + ret = -EFAULT; + + kfree(param); + + return ret; +} + int prism54_set_wpa(struct net_device *ndev, struct iw_request_info *info, __u32 * uwrq, char *extra) { islpci_private *priv = netdev_priv(ndev); + u32 mlme, authen, dot1x, filter, wep; - down_write(&priv->mib_sem); + if (islpci_get_state(priv) < PRV_STATE_INIT) + return 0; + + wep = 1; /* For privacy invoked */ + filter = 1; /* Filter out all unencrypted frames */ + dot1x = 0x01; /* To enable eap filter */ + mlme = DOT11_MLME_EXTENDED; + authen = DOT11_AUTH_OS; /* Only WEP uses _SK and _BOTH */ + down_write(&priv->mib_sem); priv->wpa = *uwrq; - if (priv->wpa) { - u32 l = DOT11_MLME_EXTENDED; - mgt_set(priv, DOT11_OID_MLMEAUTOLEVEL, &l); + + switch (priv->wpa) { + default: + case 0: /* Clears/disables WPA and friends */ + wep = 0; + filter = 0; /* Do not filter un-encrypted data */ + dot1x = 0; + mlme = DOT11_MLME_AUTO; + printk("%s: Disabling WPA\n", ndev->name); + break; + case 2: + case 1: /* WPA */ + printk("%s: Enabling WPA\n", ndev->name); + break; } - /* restart the card with new level. Needed ? */ - mgt_commit(priv); up_write(&priv->mib_sem); + mgt_set_request(priv, DOT11_OID_AUTHENABLE, 0, &authen); + mgt_set_request(priv, DOT11_OID_PRIVACYINVOKED, 0, &wep); + mgt_set_request(priv, DOT11_OID_EXUNENCRYPTED, 0, &filter); + mgt_set_request(priv, DOT11_OID_DOT1XENABLE, 0, &dot1x); + mgt_set_request(priv, DOT11_OID_MLMEAUTOLEVEL, 0, &mlme); + return 0; } @@ -1947,7 +2400,7 @@ prism54_debug_get_oid(struct net_device struct iw_point *data, char *extra) { islpci_private *priv = netdev_priv(ndev); - struct islpci_mgmtframe *response = NULL; + struct islpci_mgmtframe *response; int ret = -EIO; printk("%s: get_oid 0x%08X\n", ndev->name, priv->priv_oid); @@ -1983,7 +2436,7 @@ prism54_debug_set_oid(struct net_device struct iw_point *data, char *extra) { islpci_private *priv = netdev_priv(ndev); - struct islpci_mgmtframe *response = NULL; + struct islpci_mgmtframe *response; int ret = 0, response_op = PIMFOR_OP_ERROR; printk("%s: set_oid 0x%08X\tlen: %d\n", ndev->name, priv->priv_oid, @@ -2256,14 +2709,24 @@ const struct iw_handler_def prism54_hand .standard = (iw_handler *) prism54_handler, .private = (iw_handler *) prism54_private_handler, .private_args = (struct iw_priv_args *) prism54_private_args, +#if WIRELESS_EXT == 16 .spy_offset = offsetof(islpci_private, spy_data), +#endif /* WIRELESS_EXT == 16 */ }; -/* For ioctls that don't work with the new API */ +/* For wpa_supplicant */ int prism54_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) { - + struct iwreq *wrq = (struct iwreq *) rq; + int ret = -1; + switch (cmd) { + case PRISM54_HOSTAPD: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + ret = prism54_hostapd(ndev, &wrq->u.data); + return ret; + } return -EOPNOTSUPP; } diff -puN drivers/net/wireless/prism54/isl_ioctl.h~bk-netdev drivers/net/wireless/prism54/isl_ioctl.h --- 25/drivers/net/wireless/prism54/isl_ioctl.h~bk-netdev 2004-09-15 21:06:53.309639424 -0700 +++ 25-akpm/drivers/net/wireless/prism54/isl_ioctl.h 2004-09-15 21:06:53.452617688 -0700 @@ -48,6 +48,8 @@ size_t prism54_wpa_ie_get(islpci_private int prism54_set_mac_address(struct net_device *, void *); int prism54_ioctl(struct net_device *, struct ifreq *, int); +int prism54_set_wpa(struct net_device *, struct iw_request_info *, + __u32 *, char *); extern const struct iw_handler_def prism54_handler_def; diff -puN drivers/net/wireless/prism54/isl_oid.h~bk-netdev drivers/net/wireless/prism54/isl_oid.h --- 25/drivers/net/wireless/prism54/isl_oid.h~bk-netdev 2004-09-15 21:06:53.311639120 -0700 +++ 25-akpm/drivers/net/wireless/prism54/isl_oid.h 2004-09-15 21:06:53.453617536 -0700 @@ -91,6 +91,14 @@ struct obj_frequencies { u16 mhz[0]; } __attribute__ ((packed)); +struct obj_attachment { + char type; + char reserved; + short id; + short size; + char data[0]; +} __attribute__((packed)); + /* * in case everything's ok, the inlined function below will be * optimized away by the compiler... @@ -472,6 +480,7 @@ enum oid_num_t { #define OID_TYPE_MLMEEX 0x09 #define OID_TYPE_ADDR 0x0A #define OID_TYPE_RAW 0x0B +#define OID_TYPE_ATTACH 0x0C /* OID_TYPE_MLMEEX is special because of a variable size field when sending. * Not yet implemented (not used in driver anyway). diff -puN drivers/net/wireless/prism54/islpci_dev.c~bk-netdev drivers/net/wireless/prism54/islpci_dev.c --- 25/drivers/net/wireless/prism54/islpci_dev.c~bk-netdev 2004-09-15 21:06:53.312638968 -0700 +++ 25-akpm/drivers/net/wireless/prism54/islpci_dev.c 2004-09-15 21:06:53.454617384 -0700 @@ -375,8 +375,6 @@ islpci_open(struct net_device *ndev) u32 rc; islpci_private *priv = netdev_priv(ndev); - printk(KERN_DEBUG "%s: islpci_open()\n", ndev->name); - /* reset data structures, upload firmware and reset device */ rc = islpci_reset(priv,1); if (rc) { @@ -462,8 +460,7 @@ islpci_upload_fw(islpci_private *priv) return rc; } - printk(KERN_DEBUG - "%s: firmware uploaded done, now triggering reset...\n", + printk(KERN_DEBUG "%s: firmware upload complete\n", priv->ndev->name); islpci_set_state(priv, PRV_STATE_POSTBOOT); @@ -499,15 +496,16 @@ islpci_reset_if(islpci_private *priv) /* If we're here it's because our IRQ hasn't yet gone through. * Retry a bit more... */ - printk(KERN_ERR "%s: device soft reset timed out\n", - priv->ndev->name); - + printk(KERN_ERR "%s: reset problem: no 'reset complete' IRQ seen\n", + priv->ndev->name); } finish_wait(&priv->reset_done, &wait); - if(result) + if (result) { + printk(KERN_ERR "%s: islpci_reset_if: failure\n", priv->ndev->name); return result; + } islpci_set_state(priv, PRV_STATE_INIT); @@ -524,6 +522,7 @@ islpci_reset_if(islpci_private *priv) islpci_set_state(priv, PRV_STATE_READY); + printk(KERN_DEBUG "%s: interface reset complete\n", priv->ndev->name); return 0; } @@ -584,18 +583,18 @@ islpci_reset(islpci_private *priv, int r /* now that the data structures are cleaned up, upload * firmware and reset interface */ rc = islpci_upload_fw(priv); - if (rc) + if (rc) { + printk(KERN_ERR "%s: islpci_reset: failure\n", + priv->ndev->name); return rc; + } } /* finally reset interface */ rc = islpci_reset_if(priv); - if (!rc) /* If successful */ - return rc; - - printk(KERN_DEBUG "prism54: Your card/socket may be faulty, or IRQ line too busy :(\n"); + if (rc) + printk(KERN_ERR "prism54: Your card/socket may be faulty, or IRQ line too busy :(\n"); return rc; - } struct net_device_stats * @@ -604,7 +603,7 @@ islpci_statistics(struct net_device *nde islpci_private *priv = netdev_priv(ndev); #if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_FUNCTION_CALLS, "islpci_statistics \n"); + DEBUG(SHOW_FUNCTION_CALLS, "islpci_statistics\n"); #endif return &priv->statistics; @@ -830,6 +829,12 @@ islpci_setup(struct pci_dev *pdev) priv->ndev->type = (priv->iw_mode == IW_MODE_MONITOR) ? priv->monitor_type : ARPHRD_ETHER; +#if WIRELESS_EXT > 16 + /* Add pointers to enable iwspy support. */ + priv->wireless_data.spy_data = &priv->spy_data; + ndev->wireless_data = &priv->wireless_data; +#endif /* WIRELESS_EXT > 16 */ + /* save the start and end address of the PCI memory area */ ndev->mem_start = (unsigned long) priv->device_base; ndev->mem_end = ndev->mem_start + ISL38XX_PCI_MEM_SIZE; diff -puN drivers/net/wireless/prism54/islpci_dev.h~bk-netdev drivers/net/wireless/prism54/islpci_dev.h --- 25/drivers/net/wireless/prism54/islpci_dev.h~bk-netdev 2004-09-15 21:06:53.313638816 -0700 +++ 25-akpm/drivers/net/wireless/prism54/islpci_dev.h 2004-09-15 21:06:53.454617384 -0700 @@ -100,6 +100,10 @@ typedef struct { struct iw_spy_data spy_data; /* iwspy support */ +#if WIRELESS_EXT > 16 + struct iw_public_data wireless_data; +#endif /* WIRELESS_EXT > 16 */ + int monitor_type; /* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_PRISM */ struct islpci_acl acl; diff -puN drivers/net/wireless/prism54/islpci_eth.c~bk-netdev drivers/net/wireless/prism54/islpci_eth.c --- 25/drivers/net/wireless/prism54/islpci_eth.c~bk-netdev 2004-09-15 21:06:53.315638512 -0700 +++ 25-akpm/drivers/net/wireless/prism54/islpci_eth.c 2004-09-15 21:06:53.455617232 -0700 @@ -508,11 +508,12 @@ islpci_eth_tx_timeout(struct net_device /* increment the transmit error counter */ statistics->tx_errors++; + printk(KERN_WARNING "%s: tx_timeout", ndev->name); if (!priv->reset_task_pending) { priv->reset_task_pending = 1; + printk(", scheduling a reset"); netif_stop_queue(ndev); schedule_work(&priv->reset_task); } - - return; + printk("\n"); } diff -puN drivers/net/wireless/prism54/oid_mgt.c~bk-netdev drivers/net/wireless/prism54/oid_mgt.c --- 25/drivers/net/wireless/prism54/oid_mgt.c~bk-netdev 2004-09-15 21:06:53.316638360 -0700 +++ 25-akpm/drivers/net/wireless/prism54/oid_mgt.c 2004-09-15 21:06:53.457616928 -0700 @@ -201,7 +201,8 @@ struct oid_t isl_oid[] = { OID_U32(DOT11_OID_STATIMEOUT, 0x19000000), OID_U32_C(DOT11_OID_MLMEAUTOLEVEL, 0x19000001), OID_U32(DOT11_OID_BSSTIMEOUT, 0x19000002), - OID_UNKNOWN(DOT11_OID_ATTACHMENT, 0x19000003), + [DOT11_OID_ATTACHMENT] = {0x19000003, 0, + sizeof(struct obj_attachment), OID_TYPE_ATTACH}, OID_STRUCT_C(DOT11_OID_PSMBUFFER, 0x19000004, struct obj_buffer, OID_TYPE_BUFFER), @@ -329,6 +330,12 @@ mgt_le_to_cpu(int type, void *data) mlme->size = le16_to_cpu(mlme->size); break; } + case OID_TYPE_ATTACH:{ + struct obj_attachment *attach = data; + attach->id = le16_to_cpu(attach->id); + attach->size = le16_to_cpu(attach->size);; + break; + } case OID_TYPE_SSID: case OID_TYPE_KEY: case OID_TYPE_ADDR: @@ -392,6 +399,12 @@ mgt_cpu_to_le(int type, void *data) mlme->size = cpu_to_le16(mlme->size); break; } + case OID_TYPE_ATTACH:{ + struct obj_attachment *attach = data; + attach->id = cpu_to_le16(attach->id); + attach->size = cpu_to_le16(attach->size);; + break; + } case OID_TYPE_SSID: case OID_TYPE_KEY: case OID_TYPE_ADDR: @@ -465,6 +478,42 @@ mgt_set_request(islpci_private *priv, en return ret; } +/* None of these are cached */ +int +mgt_set_varlen(islpci_private *priv, enum oid_num_t n, void *data, int extra_len) +{ + int ret = 0; + struct islpci_mgmtframe *response; + int response_op = PIMFOR_OP_ERROR; + int dlen; + u32 oid; + + BUG_ON(OID_NUM_LAST <= n); + + dlen = isl_oid[n].size; + oid = isl_oid[n].oid; + + mgt_cpu_to_le(isl_oid[n].flags & OID_FLAG_TYPE, data); + + if (islpci_get_state(priv) >= PRV_STATE_READY) { + ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET, oid, + data, dlen + extra_len, &response); + if (!ret) { + response_op = response->header->operation; + islpci_mgt_release(response); + } + if (ret || response_op == PIMFOR_OP_ERROR) + ret = -EIO; + } else + ret = -EIO; + + /* re-set given data to what it was */ + if (data) + mgt_le_to_cpu(isl_oid[n].flags & OID_FLAG_TYPE, data); + + return ret; +} + int mgt_get_request(islpci_private *priv, enum oid_num_t n, int extra, void *data, union oid_res_t *res) @@ -555,15 +604,18 @@ mgt_commit_list(islpci_private *priv, en u32 oid = t->oid; BUG_ON(data == NULL); while (j <= t->range) { - response = NULL; - ret |= islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET, + int r = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET, oid, data, t->size, &response); if (response) { - ret |= (response->header->operation == - PIMFOR_OP_ERROR); + r |= (response->header->operation == PIMFOR_OP_ERROR); islpci_mgt_release(response); } + if (r) + printk(KERN_ERR "%s: mgt_commit_list: failure. " + "oid=%08x err=%d\n", + priv->ndev->name, oid, r); + ret |= r; j++; oid++; data += t->size; @@ -624,7 +676,7 @@ static enum oid_num_t commit_part2[] = { static int mgt_update_addr(islpci_private *priv) { - struct islpci_mgmtframe *res = NULL; + struct islpci_mgmtframe *res; int ret; ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_GET, @@ -638,9 +690,13 @@ mgt_update_addr(islpci_private *priv) if (res) islpci_mgt_release(res); + if (ret) + printk(KERN_ERR "%s: mgt_update_addr: failure\n", priv->ndev->name); return ret; } +#define VEC_SIZE(a) (sizeof(a)/sizeof(a[0])) + void mgt_commit(islpci_private *priv) { @@ -650,14 +706,10 @@ mgt_commit(islpci_private *priv) if (islpci_get_state(priv) < PRV_STATE_INIT) return; - rvalue = mgt_commit_list(priv, commit_part1, - sizeof (commit_part1) / - sizeof (commit_part1[0])); + rvalue = mgt_commit_list(priv, commit_part1, VEC_SIZE(commit_part1)); if (priv->iw_mode != IW_MODE_MONITOR) - rvalue |= mgt_commit_list(priv, commit_part2, - sizeof (commit_part2) / - sizeof (commit_part2[0])); + rvalue |= mgt_commit_list(priv, commit_part2, VEC_SIZE(commit_part2)); u = OID_INL_MODE; rvalue |= mgt_commit_list(priv, &u, 1); @@ -666,11 +718,44 @@ mgt_commit(islpci_private *priv) if (rvalue) { /* some request have failed. The device might be in an incoherent state. We should reset it ! */ - printk(KERN_DEBUG "%s: mgt_commit has failed. Restart the " - "device \n", priv->ndev->name); + printk(KERN_DEBUG "%s: mgt_commit: failure\n", priv->ndev->name); } } +/* The following OIDs need to be "unlatched": + * + * MEDIUMLIMIT,BEACONPERIOD,DTIMPERIOD,ATIMWINDOW,LISTENINTERVAL + * FREQUENCY,EXTENDEDRATES. + * + * The way to do this is to set ESSID. Note though that they may get + * unlatch before though by setting another OID. */ +void +mgt_unlatch_all(islpci_private *priv) +{ + u32 u; + int rvalue = 0; + + if (islpci_get_state(priv) < PRV_STATE_INIT) + return; + + u = DOT11_OID_SSID; + rvalue = mgt_commit_list(priv, &u, 1); + /* Necessary if in MANUAL RUN mode? */ +#if 0 + u = OID_INL_MODE; + rvalue |= mgt_commit_list(priv, &u, 1); + + u = DOT11_OID_MLMEAUTOLEVEL; + rvalue |= mgt_commit_list(priv, &u, 1); + + u = OID_INL_MODE; + rvalue |= mgt_commit_list(priv, &u, 1); +#endif + + if (rvalue) + printk(KERN_DEBUG "%s: Unlatching OIDs failed\n", priv->ndev->name); +} + /* This will tell you if you are allowed to answer a mlme(ex) request .*/ int @@ -771,6 +856,14 @@ mgt_response_to_str(enum oid_num_t n, un mlme->state, mlme->code, mlme->size); } break; + case OID_TYPE_ATTACH:{ + struct obj_attachment *attach = r->ptr; + return snprintf(str, PRIV_STR_SIZE, + "id=%d\nsize=%d\n", + attach->id, + attach->size); + } + break; case OID_TYPE_SSID:{ struct obj_ssid *ssid = r->ptr; return snprintf(str, PRIV_STR_SIZE, diff -puN drivers/net/wireless/prism54/oid_mgt.h~bk-netdev drivers/net/wireless/prism54/oid_mgt.h --- 25/drivers/net/wireless/prism54/oid_mgt.h~bk-netdev 2004-09-15 21:06:53.318638056 -0700 +++ 25-akpm/drivers/net/wireless/prism54/oid_mgt.h 2004-09-15 21:06:53.457616928 -0700 @@ -36,6 +36,8 @@ int channel_of_freq(int); void mgt_le_to_cpu(int, void *); int mgt_set_request(islpci_private *, enum oid_num_t, int, void *); +int mgt_set_varlen(islpci_private *, enum oid_num_t, void *, int); + int mgt_get_request(islpci_private *, enum oid_num_t, int, void *, union oid_res_t *); @@ -47,6 +49,7 @@ void mgt_set(islpci_private *, enum oid_ void mgt_get(islpci_private *, enum oid_num_t, void *); void mgt_commit(islpci_private *); +void mgt_unlatch_all(islpci_private *); int mgt_mlme_answer(islpci_private *); diff -puN drivers/net/wireless/wavelan.c~bk-netdev drivers/net/wireless/wavelan.c --- 25/drivers/net/wireless/wavelan.c~bk-netdev 2004-09-15 21:06:53.320637752 -0700 +++ 25-akpm/drivers/net/wireless/wavelan.c 2004-09-15 21:06:53.460616472 -0700 @@ -2172,6 +2172,11 @@ static int wavelan_get_range(struct net_ range->num_bitrates = 1; range->bitrate[0] = 2000000; /* 2 Mb/s */ + /* Event capability (kernel + driver) */ + range->event_capa[0] = (IW_EVENT_CAPA_MASK(0x8B02) | + IW_EVENT_CAPA_MASK(0x8B04)); + range->event_capa[1] = IW_EVENT_CAPA_K_1; + /* Disable interrupts and save flags. */ spin_lock_irqsave(&lp->spinlock, flags); @@ -2403,11 +2408,10 @@ static const struct iw_handler_def wavel .num_standard = sizeof(wavelan_handler)/sizeof(iw_handler), .num_private = sizeof(wavelan_private_handler)/sizeof(iw_handler), .num_private_args = sizeof(wavelan_private_args)/sizeof(struct iw_priv_args), - .standard = (iw_handler *) wavelan_handler, - .private = (iw_handler *) wavelan_private_handler, - .private_args = (struct iw_priv_args *) wavelan_private_args, - .spy_offset = ((void *) (&((net_local *) NULL)->spy_data) - - (void *) NULL), + .standard = wavelan_handler, + .private = wavelan_private_handler, + .private_args = wavelan_private_args, + .get_wireless_stats = wavelan_get_wireless_stats, }; /*------------------------------------------------------------------*/ @@ -4191,8 +4195,9 @@ static int __init wavelan_config(struct #endif /* SET_MAC_ADDRESS */ #ifdef WIRELESS_EXT /* if wireless extension exists in the kernel */ - dev->get_wireless_stats = wavelan_get_wireless_stats; - dev->wireless_handlers = (struct iw_handler_def *)&wavelan_handler_def; + dev->wireless_handlers = &wavelan_handler_def; + lp->wireless_data.spy_data = &lp->spy_data; + dev->wireless_data = &lp->wireless_data; #endif dev->mtu = WAVELAN_MTU; diff -puN drivers/net/wireless/wavelan_cs.c~bk-netdev drivers/net/wireless/wavelan_cs.c --- 25/drivers/net/wireless/wavelan_cs.c~bk-netdev 2004-09-15 21:06:53.322637448 -0700 +++ 25-akpm/drivers/net/wireless/wavelan_cs.c 2004-09-15 21:06:53.467615408 -0700 @@ -502,7 +502,7 @@ unsigned char WAVELAN_BEACON_ADDRESS[]= void wv_roam_init(struct net_device *dev) { - net_local *lp= (net_local *)dev->priv; + net_local *lp= netdev_priv(dev); /* Do not remove this unless you have a good reason */ printk(KERN_NOTICE "%s: Warning, you have enabled roaming on" @@ -532,7 +532,7 @@ void wv_roam_init(struct net_device *dev void wv_roam_cleanup(struct net_device *dev) { wavepoint_history *ptr,*old_ptr; - net_local *lp= (net_local *)dev->priv; + net_local *lp= netdev_priv(dev); printk(KERN_DEBUG "WaveLAN: Roaming Disabled on device %s\n",dev->name); @@ -762,7 +762,7 @@ static inline void wl_roam_gather(struct unsigned short nwid=ntohs(beacon->nwid); unsigned short sigqual=stats[2] & MMR_SGNL_QUAL; /* SNR of beacon */ wavepoint_history *wavepoint=NULL; /* WavePoint table entry */ - net_local *lp=(net_local *)dev->priv; /* Device info */ + net_local *lp = netdev_priv(dev); /* Device info */ #ifdef I_NEED_THIS_FEATURE /* Some people don't need this, some other may need it */ @@ -1006,7 +1006,7 @@ read_ringbuf(struct net_device * dev, static inline void wv_82593_reconfig(struct net_device * dev) { - net_local * lp = (net_local *)dev->priv; + net_local * lp = netdev_priv(dev); dev_link_t * link = lp->link; unsigned long flags; @@ -1135,7 +1135,7 @@ static void wv_mmc_show(struct net_device * dev) { ioaddr_t base = dev->base_addr; - net_local * lp = (net_local *)dev->priv; + net_local * lp = netdev_priv(dev); mmr_t m; /* Basic check */ @@ -1224,7 +1224,7 @@ wv_mmc_show(struct net_device * dev) static void wv_ru_show(struct net_device * dev) { - net_local *lp = (net_local *) dev->priv; + net_local *lp = netdev_priv(dev); printk(KERN_DEBUG "##### wavelan i82593 receiver status: #####\n"); printk(KERN_DEBUG "ru: rfp %d stop %d", lp->rfp, lp->stop); @@ -1258,9 +1258,7 @@ wv_dev_show(struct net_device * dev) static void wv_local_show(struct net_device * dev) { - net_local *lp; - - lp = (net_local *)dev->priv; + net_local *lp = netdev_priv(dev); printk(KERN_DEBUG "local:"); /* @@ -1418,7 +1416,7 @@ wavelan_get_stats(struct net_device * de printk(KERN_DEBUG "%s: <>wavelan_get_stats()\n", dev->name); #endif - return(&((net_local *) dev->priv)->stats); + return(&((net_local *)netdev_priv(dev))->stats); } /*------------------------------------------------------------------*/ @@ -1433,7 +1431,7 @@ wavelan_get_stats(struct net_device * de static void wavelan_set_multicast_list(struct net_device * dev) { - net_local * lp = (net_local *) dev->priv; + net_local * lp = netdev_priv(dev); #ifdef DEBUG_IOCTL_TRACE printk(KERN_DEBUG "%s: ->wavelan_set_multicast_list()\n", dev->name); @@ -1550,7 +1548,6 @@ wavelan_set_mac_address(struct net_devic /* * Frequency setting (for hardware able of it) * It's a bit complicated and you don't really want to look into it... - * (called in wavelan_ioctl) */ static inline int wv_set_frequency(u_long base, /* i/o port of the card */ @@ -1826,7 +1823,7 @@ static inline void wl_his_gather(struct net_device * dev, u_char * stats) /* Statistics to gather */ { - net_local * lp = (net_local *) dev->priv; + net_local * lp = netdev_priv(dev); u_char level = stats[0] & MMR_SIGNAL_LVL; int i; @@ -1840,28 +1837,15 @@ wl_his_gather(struct net_device * dev, } #endif /* HISTOGRAM */ -static inline int -wl_netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr) +static void wl_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - u32 ethcmd; - - if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) - return -EFAULT; - - switch (ethcmd) { - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; - - strncpy(info.driver, "wavelan_cs", sizeof(info.driver)-1); - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; - } - } - - return -EOPNOTSUPP; + strncpy(info->driver, "wavelan_cs", sizeof(info->driver)-1); } +static struct ethtool_ops ops = { + .get_drvinfo = wl_get_drvinfo +}; + /*------------------------------------------------------------------*/ /* * Wireless Handler : get protocol name @@ -1885,7 +1869,7 @@ static int wavelan_set_nwid(struct net_d char *extra) { ioaddr_t base = dev->base_addr; - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); psa_t psa; mm_t m; unsigned long flags; @@ -1943,7 +1927,7 @@ static int wavelan_get_nwid(struct net_d union iwreq_data *wrqu, char *extra) { - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); psa_t psa; unsigned long flags; int ret = 0; @@ -1975,7 +1959,7 @@ static int wavelan_set_freq(struct net_d char *extra) { ioaddr_t base = dev->base_addr; - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); unsigned long flags; int ret; @@ -2005,7 +1989,7 @@ static int wavelan_get_freq(struct net_d char *extra) { ioaddr_t base = dev->base_addr; - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); psa_t psa; unsigned long flags; int ret = 0; @@ -2051,7 +2035,7 @@ static int wavelan_set_sens(struct net_d char *extra) { ioaddr_t base = dev->base_addr; - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); psa_t psa; unsigned long flags; int ret = 0; @@ -2086,7 +2070,7 @@ static int wavelan_get_sens(struct net_d union iwreq_data *wrqu, char *extra) { - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); psa_t psa; unsigned long flags; int ret = 0; @@ -2117,7 +2101,7 @@ static int wavelan_set_encode(struct net char *extra) { ioaddr_t base = dev->base_addr; - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); unsigned long flags; psa_t psa; int ret = 0; @@ -2187,7 +2171,7 @@ static int wavelan_get_encode(struct net char *extra) { ioaddr_t base = dev->base_addr; - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); psa_t psa; unsigned long flags; int ret = 0; @@ -2234,7 +2218,7 @@ static int wavelan_set_essid(struct net_ union iwreq_data *wrqu, char *extra) { - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); unsigned long flags; int ret = 0; @@ -2282,7 +2266,7 @@ static int wavelan_get_essid(struct net_ union iwreq_data *wrqu, char *extra) { - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); /* Is the domain ID active ? */ wrqu->data.flags = lp->filter_domains; @@ -2347,7 +2331,7 @@ static int wavelan_set_mode(struct net_d union iwreq_data *wrqu, char *extra) { - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); unsigned long flags; int ret = 0; @@ -2406,7 +2390,7 @@ static int wavelan_get_range(struct net_ char *extra) { ioaddr_t base = dev->base_addr; - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); struct iw_range *range = (struct iw_range *) extra; unsigned long flags; int ret = 0; @@ -2438,6 +2422,12 @@ static int wavelan_get_range(struct net_ range->num_bitrates = 1; range->bitrate[0] = 2000000; /* 2 Mb/s */ + /* Event capability (kernel + driver) */ + range->event_capa[0] = (IW_EVENT_CAPA_MASK(0x8B02) | + IW_EVENT_CAPA_MASK(0x8B04) | + IW_EVENT_CAPA_MASK(0x8B06)); + range->event_capa[1] = IW_EVENT_CAPA_K_1; + /* Disable interrupts and save flags. */ spin_lock_irqsave(&lp->spinlock, flags); @@ -2476,7 +2466,7 @@ static int wavelan_set_qthr(struct net_d char *extra) { ioaddr_t base = dev->base_addr; - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); psa_t psa; unsigned long flags; @@ -2507,7 +2497,7 @@ static int wavelan_get_qthr(struct net_d union iwreq_data *wrqu, char *extra) { - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); psa_t psa; unsigned long flags; @@ -2535,7 +2525,7 @@ static int wavelan_set_roam(struct net_d union iwreq_data *wrqu, char *extra) { - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); unsigned long flags; /* Disable interrupts and save flags. */ @@ -2580,7 +2570,7 @@ static int wavelan_set_histo(struct net_ union iwreq_data *wrqu, char *extra) { - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); /* Check the number of intervals. */ if (wrqu->data.length > 16) { @@ -2623,7 +2613,7 @@ static int wavelan_get_histo(struct net_ union iwreq_data *wrqu, char *extra) { - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ + net_local *lp = netdev_priv(dev); /* Set the number of intervals. */ wrqu->data.length = lp->his_number; @@ -2737,50 +2727,14 @@ static const struct iw_handler_def wavel .num_standard = sizeof(wavelan_handler)/sizeof(iw_handler), .num_private = sizeof(wavelan_private_handler)/sizeof(iw_handler), .num_private_args = sizeof(wavelan_private_args)/sizeof(struct iw_priv_args), - .standard = (iw_handler *) wavelan_handler, - .private = (iw_handler *) wavelan_private_handler, - .private_args = (struct iw_priv_args *) wavelan_private_args, - .spy_offset = ((void *) (&((net_local *) NULL)->spy_data) - - (void *) NULL), + .standard = wavelan_handler, + .private = wavelan_private_handler, + .private_args = wavelan_private_args, + .get_wireless_stats = wavelan_get_wireless_stats, }; /*------------------------------------------------------------------*/ /* - * Perform ioctl : config & info stuff - * This is here that are treated the wireless extensions (iwconfig) - */ -static int -wavelan_ioctl(struct net_device * dev, /* Device on wich the ioctl apply */ - struct ifreq * rq, /* Data passed */ - int cmd) /* Ioctl number */ -{ - int ret = 0; - -#ifdef DEBUG_IOCTL_TRACE - printk(KERN_DEBUG "%s: ->wavelan_ioctl(cmd=0x%X)\n", dev->name, cmd); -#endif - - /* Look what is the request */ - switch(cmd) - { - case SIOCETHTOOL: - ret = wl_netdev_ethtool_ioctl(dev, rq->ifr_data); - break; - - /* ------------------- OTHER IOCTL ------------------- */ - - default: - ret = -EOPNOTSUPP; - } - -#ifdef DEBUG_IOCTL_TRACE - printk(KERN_DEBUG "%s: <-wavelan_ioctl()\n", dev->name); -#endif - return ret; -} - -/*------------------------------------------------------------------*/ -/* * Get wireless statistics * Called by /proc/net/wireless... */ @@ -2788,7 +2742,7 @@ static iw_stats * wavelan_get_wireless_stats(struct net_device * dev) { ioaddr_t base = dev->base_addr; - net_local * lp = (net_local *) dev->priv; + net_local * lp = netdev_priv(dev); mmr_t m; iw_stats * wstats; unsigned long flags; @@ -2913,7 +2867,7 @@ wv_packet_read(struct net_device * dev, int fd_p, int sksize) { - net_local * lp = (net_local *) dev->priv; + net_local * lp = netdev_priv(dev); struct sk_buff * skb; #ifdef DEBUG_RX_TRACE @@ -3015,7 +2969,7 @@ static inline void wv_packet_rcv(struct net_device * dev) { ioaddr_t base = dev->base_addr; - net_local * lp = (net_local *) dev->priv; + net_local * lp = netdev_priv(dev); int newrfp; int rp; int len; @@ -3150,7 +3104,7 @@ wv_packet_write(struct net_device * dev, void * buf, short length) { - net_local * lp = (net_local *) dev->priv; + net_local * lp = netdev_priv(dev); ioaddr_t base = dev->base_addr; unsigned long flags; int clen = length; @@ -3211,7 +3165,7 @@ static int wavelan_packet_xmit(struct sk_buff * skb, struct net_device * dev) { - net_local * lp = (net_local *)dev->priv; + net_local * lp = netdev_priv(dev); unsigned long flags; #ifdef DEBUG_TX_TRACE @@ -3470,7 +3424,7 @@ static int wv_ru_stop(struct net_device * dev) { ioaddr_t base = dev->base_addr; - net_local * lp = (net_local *) dev->priv; + net_local * lp = netdev_priv(dev); unsigned long flags; int status; int spin; @@ -3533,7 +3487,7 @@ static int wv_ru_start(struct net_device * dev) { ioaddr_t base = dev->base_addr; - net_local * lp = (net_local *) dev->priv; + net_local * lp = netdev_priv(dev); unsigned long flags; #ifdef DEBUG_CONFIG_TRACE @@ -3621,7 +3575,7 @@ static int wv_82593_config(struct net_device * dev) { ioaddr_t base = dev->base_addr; - net_local * lp = (net_local *) dev->priv; + net_local * lp = netdev_priv(dev); struct i82593_conf_block cfblk; int ret = TRUE; @@ -3796,7 +3750,7 @@ wv_pcmcia_reset(struct net_device * dev) { int i; conf_reg_t reg = { 0, CS_READ, CISREG_COR, 0 }; - dev_link_t * link = ((net_local *) dev->priv)->link; + dev_link_t * link = ((net_local *)netdev_priv(dev))->link; #ifdef DEBUG_CONFIG_TRACE printk(KERN_DEBUG "%s: ->wv_pcmcia_reset()\n", dev->name); @@ -3856,7 +3810,7 @@ wv_pcmcia_reset(struct net_device * dev) static int wv_hw_config(struct net_device * dev) { - net_local * lp = (net_local *) dev->priv; + net_local * lp = netdev_priv(dev); ioaddr_t base = dev->base_addr; unsigned long flags; int ret = FALSE; @@ -3963,7 +3917,7 @@ wv_hw_config(struct net_device * dev) static inline void wv_hw_reset(struct net_device * dev) { - net_local * lp = (net_local *) dev->priv; + net_local * lp = netdev_priv(dev); #ifdef DEBUG_CONFIG_TRACE printk(KERN_DEBUG "%s: ->wv_hw_reset()\n", dev->name); @@ -4131,8 +4085,8 @@ wv_pcmcia_config(dev_link_t * link) return FALSE; } - strcpy(((net_local *) dev->priv)->node.dev_name, dev->name); - link->dev = &((net_local *) dev->priv)->node; + strcpy(((net_local *) netdev_priv(dev))->node.dev_name, dev->name); + link->dev = &((net_local *) netdev_priv(dev))->node; #ifdef DEBUG_CONFIG_TRACE printk(KERN_DEBUG "<-wv_pcmcia_config()\n"); @@ -4203,7 +4157,7 @@ wavelan_interrupt(int irq, printk(KERN_DEBUG "%s: ->wavelan_interrupt()\n", dev->name); #endif - lp = (net_local *) dev->priv; + lp = netdev_priv(dev); base = dev->base_addr; #ifdef DEBUG_INTERRUPT_INFO @@ -4453,7 +4407,7 @@ wavelan_interrupt(int irq, static void wavelan_watchdog(struct net_device * dev) { - net_local * lp = (net_local *) dev->priv; + net_local * lp = netdev_priv(dev); ioaddr_t base = dev->base_addr; unsigned long flags; int aborted = FALSE; @@ -4528,8 +4482,8 @@ wavelan_watchdog(struct net_device * dev static int wavelan_open(struct net_device * dev) { - dev_link_t * link = ((net_local *) dev->priv)->link; - net_local * lp = (net_local *)dev->priv; + net_local * lp = netdev_priv(dev); + dev_link_t * link = lp->link; ioaddr_t base = dev->base_addr; #ifdef DEBUG_CALLBACK_TRACE @@ -4583,7 +4537,7 @@ wavelan_open(struct net_device * dev) static int wavelan_close(struct net_device * dev) { - dev_link_t * link = ((net_local *) dev->priv)->link; + dev_link_t * link = ((net_local *)netdev_priv(dev))->link; ioaddr_t base = dev->base_addr; #ifdef DEBUG_CALLBACK_TRACE @@ -4686,7 +4640,7 @@ wavelan_attach(void) } link->priv = link->irq.Instance = dev; - lp = dev->priv; + lp = netdev_priv(dev); /* Init specific data */ lp->configured = 0; @@ -4718,11 +4672,12 @@ wavelan_attach(void) /* Set the watchdog timer */ dev->tx_timeout = &wavelan_watchdog; dev->watchdog_timeo = WATCHDOG_JIFFIES; + SET_ETHTOOL_OPS(dev, &ops); #ifdef WIRELESS_EXT /* If wireless extension exist in the kernel */ - dev->wireless_handlers = (struct iw_handler_def *)&wavelan_handler_def; - dev->do_ioctl = wavelan_ioctl; /* old wireless extensions */ - dev->get_wireless_stats = wavelan_get_wireless_stats; + dev->wireless_handlers = &wavelan_handler_def; + lp->wireless_data.spy_data = &lp->spy_data; + dev->wireless_data = &lp->wireless_data; #endif /* Other specific data */ @@ -4820,8 +4775,8 @@ wavelan_detach(dev_link_t * link) if (link->dev) unregister_netdev(dev); link->dev = NULL; - ((net_local *) dev->priv)->link = NULL; - ((net_local *) dev->priv)->dev = NULL; + ((net_local *)netdev_priv(dev))->link = NULL; + ((net_local *)netdev_priv(dev))->dev = NULL; free_netdev(dev); } kfree(link); diff -puN drivers/net/wireless/wavelan_cs.p.h~bk-netdev drivers/net/wireless/wavelan_cs.p.h --- 25/drivers/net/wireless/wavelan_cs.p.h~bk-netdev 2004-09-15 21:06:53.323637296 -0700 +++ 25-akpm/drivers/net/wireless/wavelan_cs.p.h 2004-09-15 21:06:53.469615104 -0700 @@ -629,6 +629,7 @@ struct net_local iw_stats wstats; /* Wireless specific stats */ struct iw_spy_data spy_data; + struct iw_public_data wireless_data; #endif #ifdef HISTOGRAM @@ -725,6 +726,8 @@ static inline void /* ------------------- IOCTL, STATS & RECONFIG ------------------- */ static en_stats * wavelan_get_stats(struct net_device *); /* Give stats /proc/net/dev */ +static iw_stats * + wavelan_get_wireless_stats(struct net_device *); /* ----------------------- PACKET RECEPTION ----------------------- */ static inline int wv_start_of_frame(struct net_device *, /* Seek beggining of current frame */ diff -puN drivers/net/wireless/wavelan.p.h~bk-netdev drivers/net/wireless/wavelan.p.h --- 25/drivers/net/wireless/wavelan.p.h~bk-netdev 2004-09-15 21:06:53.324637144 -0700 +++ 25-akpm/drivers/net/wireless/wavelan.p.h 2004-09-15 21:06:53.461616320 -0700 @@ -510,6 +510,7 @@ struct net_local iw_stats wstats; /* Wireless-specific statistics */ struct iw_spy_data spy_data; + struct iw_public_data wireless_data; #endif #ifdef HISTOGRAM @@ -614,6 +615,8 @@ static inline void /* ------------------- IOCTL, STATS & RECONFIG ------------------- */ static en_stats * wavelan_get_stats(struct net_device *); /* Give stats /proc/net/dev */ +static iw_stats * + wavelan_get_wireless_stats(struct net_device *); static void wavelan_set_multicast_list(struct net_device *); /* ----------------------- PACKET RECEPTION ----------------------- */ diff -puN drivers/net/wireless/wl3501_cs.c~bk-netdev drivers/net/wireless/wl3501_cs.c --- 25/drivers/net/wireless/wl3501_cs.c~bk-netdev 2004-09-15 21:06:53.326636840 -0700 +++ 25-akpm/drivers/net/wireless/wl3501_cs.c 2004-09-15 21:06:53.471614800 -0700 @@ -1487,55 +1487,14 @@ struct iw_statistics *wl3501_get_wireles return wstats; } -static inline int wl3501_ethtool_ioctl(struct net_device *dev, void __user *uaddr) +static void wl3501_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - u32 ethcmd; - int rc = -EFAULT; - - if (copy_from_user(ðcmd, uaddr, sizeof(ethcmd))) - goto out; - - switch (ethcmd) { - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = { .cmd = ETHTOOL_GDRVINFO, }; - - strlcpy(info.driver, wl3501_dev_info, sizeof(info.driver)); - rc = copy_to_user(uaddr, &info, sizeof(info)) ? -EFAULT : 1; - } - default: - rc = -EOPNOTSUPP; - break; - } -out: - return rc; + strlcpy(info->driver, wl3501_dev_info, sizeof(info->driver)); } -/** - * wl3501_ioctl - Perform IOCTL call functions - * @dev - network device - * @ifreq - request - * @cmd - command - * - * Perform IOCTL call functions here. Some are privileged operations and the - * effective uid is checked in those cases. - * - * This part is optional. Needed only if you want to run wlu (unix version). - * - * CAUTION: To prevent interrupted by wl3501_interrupt() and timer-based - * wl3501_hard_start_xmit() from other interrupts, this should be run - * single-threaded. - */ -static int wl3501_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - int rc = -ENODEV; - - if (netif_device_present(dev)) { - rc = -EOPNOTSUPP; - if (cmd == SIOCETHTOOL) - rc = wl3501_ethtool_ioctl(dev, rq->ifr_data); - } - return rc; -} +static struct ethtool_ops ops = { + .get_drvinfo = wl3501_get_drvinfo +}; /** * wl3501_detach - deletes a driver "instance" @@ -2047,8 +2006,8 @@ static dev_link_t *wl3501_attach(void) dev->watchdog_timeo = 5 * HZ; dev->get_stats = wl3501_get_stats; dev->get_wireless_stats = wl3501_get_wireless_stats; - dev->do_ioctl = wl3501_ioctl; dev->wireless_handlers = (struct iw_handler_def *)&wl3501_handler_def; + SET_ETHTOOL_OPS(dev, &ops); netif_stop_queue(dev); link->priv = link->irq.Instance = dev; diff -puN drivers/net/yellowfin.c~bk-netdev drivers/net/yellowfin.c --- 25/drivers/net/yellowfin.c~bk-netdev 2004-09-15 21:06:53.328636536 -0700 +++ 25-akpm/drivers/net/yellowfin.c 2004-09-15 21:06:53.473614496 -0700 @@ -406,6 +406,7 @@ static void yellowfin_error(struct net_d static int yellowfin_close(struct net_device *dev); static struct net_device_stats *yellowfin_get_stats(struct net_device *dev); static void set_rx_mode(struct net_device *dev); +static struct ethtool_ops ethtool_ops; static int __devinit yellowfin_init_one(struct pci_dev *pdev, @@ -440,7 +441,7 @@ static int __devinit yellowfin_init_one( SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); - np = dev->priv; + np = netdev_priv(dev); if (pci_request_regions(pdev, DRV_NAME)) goto err_out_free_netdev; @@ -521,6 +522,7 @@ static int __devinit yellowfin_init_one( dev->get_stats = &yellowfin_get_stats; dev->set_multicast_list = &set_rx_mode; dev->do_ioctl = &netdev_ioctl; + SET_ETHTOOL_OPS(dev, ðtool_ops); dev->tx_timeout = yellowfin_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; @@ -619,7 +621,7 @@ static void mdio_write(long ioaddr, int static int yellowfin_open(struct net_device *dev) { - struct yellowfin_private *yp = dev->priv; + struct yellowfin_private *yp = netdev_priv(dev); long ioaddr = dev->base_addr; int i; @@ -701,7 +703,7 @@ static int yellowfin_open(struct net_dev static void yellowfin_timer(unsigned long data) { struct net_device *dev = (struct net_device *)data; - struct yellowfin_private *yp = dev->priv; + struct yellowfin_private *yp = netdev_priv(dev); long ioaddr = dev->base_addr; int next_tick = 60*HZ; @@ -735,7 +737,7 @@ static void yellowfin_timer(unsigned lon static void yellowfin_tx_timeout(struct net_device *dev) { - struct yellowfin_private *yp = dev->priv; + struct yellowfin_private *yp = netdev_priv(dev); long ioaddr = dev->base_addr; printk(KERN_WARNING "%s: Yellowfin transmit timed out at %d/%d Tx " @@ -772,7 +774,7 @@ static void yellowfin_tx_timeout(struct /* Initialize the Rx and Tx rings, along with various 'dev' bits. */ static void yellowfin_init_ring(struct net_device *dev) { - struct yellowfin_private *yp = dev->priv; + struct yellowfin_private *yp = netdev_priv(dev); int i; yp->tx_full = 0; @@ -855,7 +857,7 @@ static void yellowfin_init_ring(struct n static int yellowfin_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct yellowfin_private *yp = dev->priv; + struct yellowfin_private *yp = netdev_priv(dev); unsigned entry; int len = skb->len; @@ -953,7 +955,7 @@ static irqreturn_t yellowfin_interrupt(i #endif ioaddr = dev->base_addr; - yp = dev->priv; + yp = netdev_priv(dev); spin_lock (&yp->lock); @@ -1095,7 +1097,7 @@ static irqreturn_t yellowfin_interrupt(i for clarity and better register allocation. */ static int yellowfin_rx(struct net_device *dev) { - struct yellowfin_private *yp = dev->priv; + struct yellowfin_private *yp = netdev_priv(dev); int entry = yp->cur_rx % RX_RING_SIZE; int boguscnt = yp->dirty_rx + RX_RING_SIZE - yp->cur_rx; @@ -1239,7 +1241,7 @@ static int yellowfin_rx(struct net_devic static void yellowfin_error(struct net_device *dev, int intr_status) { - struct yellowfin_private *yp = dev->priv; + struct yellowfin_private *yp = netdev_priv(dev); printk(KERN_ERR "%s: Something Wicked happened! %4.4x.\n", dev->name, intr_status); @@ -1253,7 +1255,7 @@ static void yellowfin_error(struct net_d static int yellowfin_close(struct net_device *dev) { long ioaddr = dev->base_addr; - struct yellowfin_private *yp = dev->priv; + struct yellowfin_private *yp = netdev_priv(dev); int i; netif_stop_queue (dev); @@ -1340,7 +1342,7 @@ static int yellowfin_close(struct net_de static struct net_device_stats *yellowfin_get_stats(struct net_device *dev) { - struct yellowfin_private *yp = dev->priv; + struct yellowfin_private *yp = netdev_priv(dev); return &yp->stats; } @@ -1348,7 +1350,7 @@ static struct net_device_stats *yellowfi static void set_rx_mode(struct net_device *dev) { - struct yellowfin_private *yp = dev->priv; + struct yellowfin_private *yp = netdev_priv(dev); long ioaddr = dev->base_addr; u16 cfg_value = inw(ioaddr + Cnfg); @@ -1394,39 +1396,25 @@ static void set_rx_mode(struct net_devic outw(cfg_value | 0x1000, ioaddr + Cnfg); } -static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr) +static void yellowfin_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - struct yellowfin_private *np = dev->priv; - u32 ethcmd; - - if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) - return -EFAULT; - - switch (ethcmd) { - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; - strcpy(info.driver, DRV_NAME); - strcpy(info.version, DRV_VERSION); - strcpy(info.bus_info, pci_name(np->pci_dev)); - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; - } - - } - - return -EOPNOTSUPP; + struct yellowfin_private *np = netdev_priv(dev); + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); + strcpy(info->bus_info, pci_name(np->pci_dev)); } +static struct ethtool_ops ethtool_ops = { + .get_drvinfo = yellowfin_get_drvinfo +}; + static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { - struct yellowfin_private *np = dev->priv; + struct yellowfin_private *np = netdev_priv(dev); long ioaddr = dev->base_addr; struct mii_ioctl_data *data = if_mii(rq); switch(cmd) { - case SIOCETHTOOL: - return netdev_ethtool_ioctl(dev, rq->ifr_data); case SIOCGMIIPHY: /* Get address of MII PHY in use. */ data->phy_id = np->phys[0] & 0x1f; /* Fall Through */ @@ -1466,7 +1454,7 @@ static void __devexit yellowfin_remove_o if (!dev) BUG(); - np = dev->priv; + np = netdev_priv(dev); pci_free_consistent(pdev, STATUS_TOTAL_SIZE, np->tx_status, np->tx_status_dma); diff -puN drivers/usb/gadget/ether.c~bk-netdev drivers/usb/gadget/ether.c --- 25/drivers/usb/gadget/ether.c~bk-netdev 2004-09-15 21:06:53.329636384 -0700 +++ 25-akpm/drivers/usb/gadget/ether.c 2004-09-15 21:06:53.476614040 -0700 @@ -1670,7 +1670,7 @@ eth_disconnect (struct usb_gadget *gadge static int eth_change_mtu (struct net_device *net, int new_mtu) { - struct eth_dev *dev = (struct eth_dev *) net->priv; + struct eth_dev *dev = netdev_priv(net); // FIXME if rndis, don't change while link's live @@ -1685,58 +1685,29 @@ static int eth_change_mtu (struct net_de static struct net_device_stats *eth_get_stats (struct net_device *net) { - return &((struct eth_dev *) net->priv)->stats; + return &((struct eth_dev *)netdev_priv(net))->stats; } -static int eth_ethtool_ioctl (struct net_device *net, void __user *useraddr) +static void eth_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *p) { - struct eth_dev *dev = (struct eth_dev *) net->priv; - u32 cmd; - - if (get_user (cmd, (u32 __user *)useraddr)) - return -EFAULT; - switch (cmd) { - - case ETHTOOL_GDRVINFO: { /* get driver info */ - struct ethtool_drvinfo info; - - memset (&info, 0, sizeof info); - info.cmd = ETHTOOL_GDRVINFO; - strlcpy (info.driver, shortname, sizeof info.driver); - strlcpy (info.version, DRIVER_VERSION, sizeof info.version); - strlcpy (info.fw_version, dev->gadget->name, - sizeof info.fw_version); - strlcpy (info.bus_info, dev->gadget->dev.bus_id, - sizeof info.bus_info); - if (copy_to_user (useraddr, &info, sizeof (info))) - return -EFAULT; - return 0; - } - - case ETHTOOL_GLINK: { /* get link status */ - struct ethtool_value edata = { ETHTOOL_GLINK }; - - edata.data = (dev->gadget->speed != USB_SPEED_UNKNOWN); - if (copy_to_user (useraddr, &edata, sizeof (edata))) - return -EFAULT; - return 0; - } - - } - /* Note that the ethtool user space code requires EOPNOTSUPP */ - return -EOPNOTSUPP; + struct eth_dev *dev = netdev_priv(net); + strlcpy(p->driver, shortname, sizeof p->driver); + strlcpy(p->version, DRIVER_VERSION, sizeof p->version); + strlcpy(p->fw_version, dev->gadget->name, sizeof p->fw_version); + strlcpy (p->bus_info, dev->gadget->dev.bus_id, sizeof p->bus_info); } -static int eth_ioctl (struct net_device *net, struct ifreq *rq, int cmd) +static u32 eth_get_link(struct net_device *net) { - switch (cmd) { - case SIOCETHTOOL: - return eth_ethtool_ioctl(net, rq->ifr_data); - default: - return -EOPNOTSUPP; - } + struct eth_dev *dev = netdev_priv(net); + return dev->gadget->speed != USB_SPEED_UNKNOWN; } +static struct ethtool_ops ops = { + .get_drvinfo = eth_get_drvinfo, + .get_link = eth_get_link +}; + static void defer_kevent (struct eth_dev *dev, int flag) { if (test_and_set_bit (flag, &dev->todo)) @@ -1997,7 +1968,7 @@ static void tx_complete (struct usb_ep * static int eth_start_xmit (struct sk_buff *skb, struct net_device *net) { - struct eth_dev *dev = (struct eth_dev *) net->priv; + struct eth_dev *dev = netdev_priv(net); int length = skb->len; int retval; struct usb_request *req = NULL; @@ -2110,7 +2081,7 @@ static void rndis_control_ack_complete ( static int rndis_control_ack (struct net_device *net) { - struct eth_dev *dev = (struct eth_dev *) net->priv; + struct eth_dev *dev = netdev_priv(net); u32 length; struct usb_request *resp; @@ -2177,7 +2148,7 @@ static void eth_start (struct eth_dev *d static int eth_open (struct net_device *net) { - struct eth_dev *dev = (struct eth_dev *) net->priv; + struct eth_dev *dev = netdev_priv(net); DEBUG (dev, "%s\n", __FUNCTION__); if (netif_carrier_ok (dev->net)) @@ -2187,7 +2158,7 @@ static int eth_open (struct net_device * static int eth_stop (struct net_device *net) { - struct eth_dev *dev = (struct eth_dev *) net->priv; + struct eth_dev *dev = netdev_priv(net); VDEBUG (dev, "%s\n", __FUNCTION__); netif_stop_queue (net); @@ -2474,7 +2445,7 @@ autoconf_fail: net = alloc_etherdev (sizeof *dev); if (!net) return status; - dev = net->priv; + dev = netdev_priv(net); spin_lock_init (&dev->lock); INIT_WORK (&dev->work, eth_work, dev); INIT_LIST_HEAD (&dev->tx_reqs); @@ -2518,7 +2489,7 @@ autoconf_fail: net->stop = eth_stop; // watchdog_timeo, tx_timeout ... // set_multicast_list - net->do_ioctl = eth_ioctl; + SET_ETHTOOL_OPS(net, &ops); /* preallocate control response and buffer */ dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL); diff -puN drivers/usb/net/catc.c~bk-netdev drivers/usb/net/catc.c --- 25/drivers/usb/net/catc.c~bk-netdev 2004-09-15 21:06:53.331636080 -0700 +++ 25-akpm/drivers/usb/net/catc.c 2004-09-15 21:06:53.477613888 -0700 @@ -411,7 +411,7 @@ static void catc_tx_done(struct urb *urb static int catc_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev) { - struct catc *catc = netdev->priv; + struct catc *catc = netdev_priv(netdev); unsigned long flags; char *tx_buf; @@ -442,7 +442,7 @@ static int catc_hard_start_xmit(struct s static void catc_tx_timeout(struct net_device *netdev) { - struct catc *catc = netdev->priv; + struct catc *catc = netdev_priv(netdev); warn("Transmit timed out."); catc->tx_urb->transfer_flags |= URB_ASYNC_UNLINK; @@ -604,7 +604,7 @@ static void catc_stats_timer(unsigned lo static struct net_device_stats *catc_get_stats(struct net_device *netdev) { - struct catc *catc = netdev->priv; + struct catc *catc = netdev_priv(netdev); return &catc->stats; } @@ -622,7 +622,7 @@ static void catc_multicast(unsigned char static void catc_set_multicast_list(struct net_device *netdev) { - struct catc *catc = netdev->priv; + struct catc *catc = netdev_priv(netdev); struct dev_mc_list *mc; u8 broadcast[6]; u8 rx = RxEnable | RxPolarity | RxMultiCast; @@ -664,74 +664,38 @@ static void catc_set_multicast_list(stru } } -/* - * ioctl's - */ -static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr) +void catc_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - struct catc *catc = dev->priv; - 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, driver_name, ETHTOOL_BUSINFO_LEN); - strncpy(info.version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN); - usb_make_path (catc->usbdev, info.bus_info, sizeof info.bus_info); - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; - } - - /* get settings */ - case ETHTOOL_GSET: - if (catc->is_f5u011) { - struct ethtool_cmd ecmd = { ETHTOOL_GSET, - SUPPORTED_10baseT_Half | SUPPORTED_TP, - ADVERTISED_10baseT_Half | ADVERTISED_TP, - SPEED_10, - DUPLEX_HALF, - PORT_TP, - 0, - XCVR_INTERNAL, - AUTONEG_DISABLE, - 1, - 1 - }; - if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; - } else { - return -EOPNOTSUPP; - } + struct catc *catc = netdev_priv(dev); + strncpy(info->driver, driver_name, ETHTOOL_BUSINFO_LEN); + strncpy(info->version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN); + usb_make_path (catc->usbdev, info->bus_info, sizeof info->bus_info); +} + +static int catc_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct catc *catc = netdev_priv(dev); + if (!catc->is_f5u011) + return -EOPNOTSUPP; - /* get link status */ - case ETHTOOL_GLINK: { - struct ethtool_value edata = {ETHTOOL_GLINK}; - edata.data = netif_carrier_ok(dev); - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - } - - return -EOPNOTSUPP; -} - -static int catc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - switch(cmd) { - case SIOCETHTOOL: - return netdev_ethtool_ioctl(dev, rq->ifr_data); - default: - return -EOPNOTSUPP; - } + cmd->supported = SUPPORTED_10baseT_Half | SUPPORTED_TP; + cmd->advertising = ADVERTISED_10baseT_Half | ADVERTISED_TP; + cmd->speed = SPEED_10; + cmd->duplex = DUPLEX_HALF; + cmd->port = PORT_TP; + cmd->phy_address = 0; + cmd->transceiver = XCVR_INTERNAL; + cmd->autoneg = AUTONEG_DISABLE; + cmd->maxtxpkt = 1; + cmd->maxrxpkt = 1; + return 0; } +static struct ethtool_ops ops = { + .get_drvinfo = catc_get_drvinfo, + .get_settings = catc_get_settings, + .get_link = ethtool_op_get_link +}; /* * Open, close. @@ -739,7 +703,7 @@ static int catc_ioctl(struct net_device static int catc_open(struct net_device *netdev) { - struct catc *catc = netdev->priv; + struct catc *catc = netdev_priv(netdev); int status; catc->irq_urb->dev = catc->usbdev; @@ -758,7 +722,7 @@ static int catc_open(struct net_device * static int catc_stop(struct net_device *netdev) { - struct catc *catc = netdev->priv; + struct catc *catc = netdev_priv(netdev); netif_stop_queue(netdev); @@ -791,17 +755,11 @@ static int catc_probe(struct usb_interfa return -EIO; } - catc = kmalloc(sizeof(struct catc), GFP_KERNEL); - if (!catc) + netdev = alloc_etherdev(sizeof(struct catc)); + if (!netdev) return -ENOMEM; - memset(catc, 0, sizeof(struct catc)); - - netdev = alloc_etherdev(0); - if (!netdev) { - kfree(catc); - return -EIO; - } + catc = netdev_priv(netdev); netdev->open = catc_open; netdev->hard_start_xmit = catc_hard_start_xmit; @@ -810,8 +768,7 @@ static int catc_probe(struct usb_interfa netdev->tx_timeout = catc_tx_timeout; netdev->watchdog_timeo = TX_TIMEOUT; netdev->set_multicast_list = catc_set_multicast_list; - netdev->do_ioctl = catc_ioctl; - netdev->priv = catc; + SET_ETHTOOL_OPS(netdev, &ops); catc->usbdev = usbdev; catc->netdev = netdev; @@ -839,7 +796,6 @@ static int catc_probe(struct usb_interfa if (catc->irq_urb) usb_free_urb(catc->irq_urb); free_netdev(netdev); - kfree(catc); return -ENOMEM; } @@ -944,7 +900,6 @@ static int catc_probe(struct usb_interfa usb_free_urb(catc->rx_urb); usb_free_urb(catc->irq_urb); free_netdev(netdev); - kfree(catc); return -EIO; } return 0; @@ -962,7 +917,6 @@ static void catc_disconnect(struct usb_i usb_free_urb(catc->rx_urb); usb_free_urb(catc->irq_urb); free_netdev(catc->netdev); - kfree(catc); } } diff -puN drivers/usb/net/kaweth.c~bk-netdev drivers/usb/net/kaweth.c --- 25/drivers/usb/net/kaweth.c~bk-netdev 2004-09-15 21:06:53.332635928 -0700 +++ 25-akpm/drivers/usb/net/kaweth.c 2004-09-15 21:06:53.479613584 -0700 @@ -710,37 +710,15 @@ static int kaweth_close(struct net_devic return 0; } -static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr) +static void kaweth_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - u32 ethcmd; - if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) - return -EFAULT; - - switch (ethcmd) { - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; - strlcpy(info.driver, driver_name, sizeof(info.driver)); - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; - } - } - - return -EOPNOTSUPP; + strlcpy(info->driver, driver_name, sizeof(info->driver)); } -/**************************************************************** - * kaweth_ioctl - ****************************************************************/ -static int kaweth_ioctl(struct net_device *net, struct ifreq *rq, int cmd) -{ - switch (cmd) { - case SIOCETHTOOL: - return netdev_ethtool_ioctl(net, rq->ifr_data); - } - return -EOPNOTSUPP; -} +static struct ethtool_ops ops = { + .get_drvinfo = kaweth_get_drvinfo +}; /**************************************************************** * kaweth_usb_transmit_complete @@ -1107,11 +1085,11 @@ static int kaweth_probe( kaweth->net->watchdog_timeo = KAWETH_TX_TIMEOUT; kaweth->net->tx_timeout = kaweth_tx_timeout; - kaweth->net->do_ioctl = kaweth_ioctl; kaweth->net->hard_start_xmit = kaweth_start_xmit; kaweth->net->set_multicast_list = kaweth_set_rx_mode; kaweth->net->get_stats = kaweth_netdev_stats; kaweth->net->mtu = le16_to_cpu(kaweth->configuration.segment_size); + SET_ETHTOOL_OPS(kaweth->net, &ops); memset(&kaweth->stats, 0, sizeof(kaweth->stats)); diff -puN drivers/usb/net/pegasus.c~bk-netdev drivers/usb/net/pegasus.c --- 25/drivers/usb/net/pegasus.c~bk-netdev 2004-09-15 21:06:53.333635776 -0700 +++ 25-akpm/drivers/usb/net/pegasus.c 2004-09-15 21:06:53.482613128 -0700 @@ -308,7 +308,7 @@ static int read_mii_word(pegasus_t * peg static int mdio_read(struct net_device *dev, int phy_id, int loc) { - pegasus_t *pegasus = (pegasus_t *) dev->priv; + pegasus_t *pegasus = (pegasus_t *) netdev_priv(dev); int res; read_mii_word(pegasus, phy_id, loc, (u16 *) & res); @@ -338,7 +338,7 @@ static int write_mii_word(pegasus_t * pe static void mdio_write(struct net_device *dev, int phy_id, int loc, int val) { - pegasus_t *pegasus = (pegasus_t *) dev->priv; + pegasus_t *pegasus = (pegasus_t *) netdev_priv(dev); write_mii_word(pegasus, phy_id, loc, val); } @@ -471,7 +471,7 @@ static int enable_net_traffic(struct net { __u16 linkpart; __u8 data[4]; - pegasus_t *pegasus = dev->priv; + pegasus_t *pegasus = netdev_priv(dev); read_mii_word(pegasus, pegasus->phy, MII_LPA, &linkpart); data[0] = 0xc9; @@ -754,11 +754,7 @@ static void intr_callback(struct urb *ur static void pegasus_tx_timeout(struct net_device *net) { - pegasus_t *pegasus = net->priv; - - if (!pegasus) - return; - + pegasus_t *pegasus = netdev_priv(net); warn("%s: Tx timed out.", net->name); pegasus->tx_urb->transfer_flags |= URB_ASYNC_UNLINK; usb_unlink_urb(pegasus->tx_urb); @@ -767,7 +763,7 @@ static void pegasus_tx_timeout(struct ne static int pegasus_start_xmit(struct sk_buff *skb, struct net_device *net) { - pegasus_t *pegasus = net->priv; + pegasus_t *pegasus = netdev_priv(net); int count = ((skb->len + 2) & 0x3f) ? skb->len + 2 : skb->len + 3; int res; __u16 l16 = skb->len; @@ -804,7 +800,7 @@ static int pegasus_start_xmit(struct sk_ static struct net_device_stats *pegasus_netdev_stats(struct net_device *dev) { - return &((pegasus_t *) dev->priv)->stats; + return &((pegasus_t *) netdev_priv(dev))->stats; } static inline void disable_net_traffic(pegasus_t * pegasus) @@ -832,10 +828,9 @@ static inline void get_interrupt_interva static void set_carrier(struct net_device *net) { - pegasus_t *pegasus; + pegasus_t *pegasus = netdev_priv(net); short tmp; - pegasus = net->priv; read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp); if (tmp & BMSR_LSTATUS) netif_carrier_on(net); @@ -890,7 +885,7 @@ static int alloc_urbs(pegasus_t * pegasu static int pegasus_open(struct net_device *net) { - pegasus_t *pegasus = (pegasus_t *) net->priv; + pegasus_t *pegasus = netdev_priv(net); int res; if (pegasus->rx_skb == NULL) @@ -933,7 +928,7 @@ exit: static int pegasus_close(struct net_device *net) { - pegasus_t *pegasus = net->priv; + pegasus_t *pegasus = netdev_priv(net); pegasus->flags &= ~PEGASUS_RUNNING; netif_stop_queue(net); @@ -944,177 +939,120 @@ static int pegasus_close(struct net_devi return 0; } -#ifdef CONFIG_MII -static int pegasus_ethtool_ioctl(struct net_device *dev, void __user *useraddr) -{ - u32 ethcmd; - pegasus_t *pegasus = dev->priv; +void pegasus_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + pegasus_t *pegasus = netdev_priv(dev); + strncpy(info->driver, driver_name, sizeof (info->driver) - 1); + strncpy(info->version, DRIVER_VERSION, sizeof (info->version) - 1); + usb_make_path(pegasus->usb, info->bus_info, sizeof (info->bus_info)); +} - if (copy_from_user(ðcmd, useraddr, sizeof (ethcmd))) - return -EFAULT; +#ifdef CONFIG_MII +static int pegasus_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + pegasus_t *pegasus = netdev_priv(dev); + mii_ethtool_gset(&pegasus->mii, ecmd); + return 0; +} +static int pegasus_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + pegasus_t *pegasus = netdev_priv(dev); + return mii_ethtool_sset(&pegasus->mii, &ecmd); +} - switch (ethcmd) { - /* get driver-specific version/etc. info */ - case ETHTOOL_GDRVINFO:{ - struct ethtool_drvinfo info; - memset (&info, 0, sizeof (info)); - info.cmd = ETHTOOL_GDRVINFO; - strncpy(info.driver, driver_name, - sizeof (info.driver) - 1); - strncpy(info.version, DRIVER_VERSION, - sizeof (info.version) - 1); - usb_make_path(pegasus->usb, info.bus_info, - sizeof (info.bus_info)); - if (copy_to_user(useraddr, &info, sizeof (info))) - return -EFAULT; - return 0; - } +static int pegasus_nway_reset(struct net_device *dev) +{ + pegasus_t *pegasus = netdev_priv(dev); + return mii_nway_restart(&pegasus->mii); +} - /* get settings */ - case ETHTOOL_GSET:{ - struct ethtool_cmd ecmd = { ETHTOOL_GSET }; - mii_ethtool_gset(&pegasus->mii, &ecmd); - if (copy_to_user(useraddr, &ecmd, sizeof (ecmd))) - return -EFAULT; - return 0; - } - /* set settings */ - case ETHTOOL_SSET:{ - int r; - struct ethtool_cmd ecmd; - if (copy_from_user(&ecmd, useraddr, sizeof (ecmd))) - return -EFAULT; - r = mii_ethtool_sset(&pegasus->mii, &ecmd); - return r; - } - /* restart autonegotiation */ - case ETHTOOL_NWAY_RST:{ - return mii_nway_restart(&pegasus->mii); - } +static u32 pegasus_get_link(struct net_device *dev) +{ + pegasus_t *pegasus = netdev_priv(dev); + return mii_link_ok(&pegasus->mii); +} - /* get link status */ - case ETHTOOL_GLINK:{ - struct ethtool_value edata = { ETHTOOL_GLINK }; - edata.data = mii_link_ok(&pegasus->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 = pegasus->msg_enable; FIXME */ - 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; - /* sp->msg_enable = edata.data; FIXME */ - return 0; - } +static u32 pegasus_get_msglevel(struct net_device *dev) +{ + pegasus_t *pegasus = netdev_priv(dev); + /* return pegasus->msg_enable; FIXME */ + return 0; +} - } +static void pegasus_set_msglevel(struct net_device *dev, u32 v) +{ + pegasus_t *pegasus = netdev_priv(dev); + /* pegasus->msg_enable = edata.data; FIXME */ +} - return -EOPNOTSUPP; +static struct ethtool_ops ops = { + .get_drvinfo = pegasus_get_drvinfo, + .get_settings = pegasus_get_settings, + .set_settings = pegasus_set_settings, + .nway_reset = pegasus_nway_reset, + .get_link = pegasus_get_link, + .get_msglevel = pegasus_get_msglevel, + .set_msglevel = pegasus_set_msglevel, +}; -} #else -static int pegasus_ethtool_ioctl(struct net_device *net, void __user *uaddr) -{ - pegasus_t *pegasus; - int cmd; - - pegasus = net->priv; - if (get_user(cmd, (int __user *) uaddr)) - return -EFAULT; - switch (cmd) { - case ETHTOOL_GDRVINFO:{ - struct ethtool_drvinfo info; - memset (&info, 0, sizeof (info)); - info.cmd = ETHTOOL_GDRVINFO; - strncpy(info.driver, driver_name, - sizeof (info.driver) - 1); - strncpy(info.version, DRIVER_VERSION, - sizeof (info.version) - 1); - usb_make_path(pegasus->usb, info.bus_info, - sizeof (info.bus_info)); - if (copy_to_user(uaddr, &info, sizeof (info))) - return -EFAULT; - return 0; - } - case ETHTOOL_GSET:{ - struct ethtool_cmd ecmd; - short lpa, bmcr; - u8 port; - - memset(&ecmd, 0, sizeof (ecmd)); - ecmd.supported = (SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_Autoneg | - SUPPORTED_TP | SUPPORTED_MII); - get_registers(pegasus, Reg7b, 1, &port); - if (port == 0) - ecmd.port = PORT_MII; - else - ecmd.port = PORT_TP; - ecmd.transceiver = XCVR_INTERNAL; - ecmd.phy_address = pegasus->phy; - read_mii_word(pegasus, pegasus->phy, MII_BMCR, &bmcr); - read_mii_word(pegasus, pegasus->phy, MII_LPA, &lpa); - if (bmcr & BMCR_ANENABLE) { - ecmd.autoneg = AUTONEG_ENABLE; - ecmd.speed = lpa & (LPA_100HALF | LPA_100FULL) ? - SPEED_100 : SPEED_10; - if (ecmd.speed == SPEED_100) - ecmd.duplex = lpa & LPA_100FULL ? - DUPLEX_FULL : DUPLEX_HALF; - else - ecmd.duplex = lpa & LPA_10FULL ? - DUPLEX_FULL : DUPLEX_HALF; - } else { - ecmd.autoneg = AUTONEG_DISABLE; - ecmd.speed = bmcr & BMCR_SPEED100 ? - SPEED_100 : SPEED_10; - ecmd.duplex = bmcr & BMCR_FULLDPLX ? - DUPLEX_FULL : DUPLEX_HALF; - } - if (copy_to_user(uaddr, &ecmd, sizeof (ecmd))) - return -EFAULT; - return 0; - } - case ETHTOOL_SSET:{ - return -EOPNOTSUPP; - } - case ETHTOOL_GLINK:{ - struct ethtool_value edata = { ETHTOOL_GLINK }; - edata.data = netif_carrier_ok(net); - if (copy_to_user(uaddr, &edata, sizeof (edata))) - return -EFAULT; - return 0; - } - default: - return -EOPNOTSUPP; +static int pegasus_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + pegasus_t *pegasus = netdev_priv(dev); + short lpa, bmcr; + u8 port; + + ecmd->supported = (SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_Autoneg | + SUPPORTED_TP | SUPPORTED_MII); + get_registers(pegasus, Reg7b, 1, &port); + if (port == 0) + ecmd->port = PORT_MII; + else + ecmd->port = PORT_TP; + ecmd->transceiver = XCVR_INTERNAL; + ecmd->phy_address = pegasus->phy; + read_mii_word(pegasus, pegasus->phy, MII_BMCR, &bmcr); + read_mii_word(pegasus, pegasus->phy, MII_LPA, &lpa); + if (bmcr & BMCR_ANENABLE) { + ecmd->autoneg = AUTONEG_ENABLE; + ecmd->speed = lpa & (LPA_100HALF | LPA_100FULL) ? + SPEED_100 : SPEED_10; + if (ecmd->speed == SPEED_100) + ecmd->duplex = lpa & LPA_100FULL ? + DUPLEX_FULL : DUPLEX_HALF; + else + ecmd->duplex = lpa & LPA_10FULL ? + DUPLEX_FULL : DUPLEX_HALF; + } else { + ecmd->autoneg = AUTONEG_DISABLE; + ecmd->speed = bmcr & BMCR_SPEED100 ? + SPEED_100 : SPEED_10; + ecmd->duplex = bmcr & BMCR_FULLDPLX ? + DUPLEX_FULL : DUPLEX_HALF; } + return 0; } + +static struct ethtool_ops ops = { + .get_drvinfo = pegasus_get_drvinfo, + .get_settings = pegasus_get_settings, + .get_link = ethtool_op_get_link, +}; #endif + static int pegasus_ioctl(struct net_device *net, struct ifreq *rq, int cmd) { __u16 *data = (__u16 *) & rq->ifr_ifru; - pegasus_t *pegasus = net->priv; + pegasus_t *pegasus = netdev_priv(net); int res; switch (cmd) { - case SIOCETHTOOL: - res = pegasus_ethtool_ioctl(net, rq->ifr_data); - break; case SIOCDEVPRIVATE: data[0] = pegasus->phy; case SIOCDEVPRIVATE + 1: @@ -1135,7 +1073,7 @@ static int pegasus_ioctl(struct net_devi static void pegasus_set_multicast(struct net_device *net) { - pegasus_t *pegasus = net->priv; + pegasus_t *pegasus = netdev_priv(net); if (net->flags & IFF_PROMISC) { pegasus->eth_regs[EthCtrl2] |= RX_PROMISCUOUS; @@ -1211,11 +1149,13 @@ static int pegasus_probe(struct usb_inte int res = -ENOMEM; usb_get_dev(dev); - if (!(pegasus = kmalloc(sizeof (struct pegasus), GFP_KERNEL))) { + net = alloc_etherdev(sizeof(struct pegasus)); + if (!net) { err("out of memory allocating device structure"); goto out; } + pegasus = netdev_priv(net); memset(pegasus, 0, sizeof (struct pegasus)); pegasus->dev_index = dev_index; init_waitqueue_head(&pegasus->ctrl_wait); @@ -1223,16 +1163,11 @@ static int pegasus_probe(struct usb_inte if (!alloc_urbs(pegasus)) goto out1; - net = alloc_etherdev(0); - if (!net) - goto out2; - tasklet_init(&pegasus->rx_tl, rx_fixup, (unsigned long) pegasus); pegasus->usb = dev; pegasus->net = net; SET_MODULE_OWNER(net); - net->priv = pegasus; net->open = pegasus_open; net->stop = pegasus_close; net->watchdog_timeo = PEGASUS_TX_TIMEOUT; @@ -1242,6 +1177,7 @@ static int pegasus_probe(struct usb_inte net->set_multicast_list = pegasus_set_multicast; net->get_stats = pegasus_netdev_stats; net->mtu = PEGASUS_MTU; + SET_ETHTOOL_OPS(net, &ops); pegasus->mii.dev = net; pegasus->mii.mdio_read = mdio_read; pegasus->mii.mdio_write = mdio_write; @@ -1254,7 +1190,7 @@ static int pegasus_probe(struct usb_inte if (reset_mac(pegasus)) { err("can't reset MAC"); res = -EIO; - goto out3; + goto out2; } set_ethernet_addr(pegasus); fill_skb_pool(pegasus); @@ -1271,19 +1207,17 @@ static int pegasus_probe(struct usb_inte SET_NETDEV_DEV(net, &intf->dev); res = register_netdev(net); if (res) - goto out4; + goto out3; printk("%s: %s\n", net->name, usb_dev_id[dev_index].name); return 0; -out4: +out3: usb_set_intfdata(intf, NULL); free_skb_pool(pegasus); -out3: - free_netdev(net); out2: free_all_urbs(pegasus); out1: - kfree(pegasus); + free_netdev(net); out: usb_put_dev(dev); return res; @@ -1307,7 +1241,6 @@ static void pegasus_disconnect(struct us if (pegasus->rx_skb) dev_kfree_skb(pegasus->rx_skb); free_netdev(pegasus->net); - kfree(pegasus); } static struct usb_driver pegasus_driver = { diff -puN drivers/usb/net/rtl8150.c~bk-netdev drivers/usb/net/rtl8150.c --- 25/drivers/usb/net/rtl8150.c~bk-netdev 2004-09-15 21:06:53.335635472 -0700 +++ 25-akpm/drivers/usb/net/rtl8150.c 2004-09-15 21:06:53.484612824 -0700 @@ -304,15 +304,12 @@ static inline void set_ethernet_addr(rtl static int rtl8150_set_mac_address(struct net_device *netdev, void *p) { struct sockaddr *addr = p; - rtl8150_t *dev; + rtl8150_t *dev = netdev_priv(netdev); int i; if (netif_running(netdev)) return -EBUSY; - dev = netdev->priv; - if (dev == NULL) { - return -ENODEV; - } + memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); dbg("%s: Setting MAC address to ", netdev->name); for (i = 0; i < 5; i++) @@ -651,16 +648,12 @@ static void disable_net_traffic(rtl8150_ static struct net_device_stats *rtl8150_netdev_stats(struct net_device *dev) { - return &((rtl8150_t *) dev->priv)->stats; + return &((rtl8150_t *)netdev_priv(dev))->stats; } static void rtl8150_tx_timeout(struct net_device *netdev) { - rtl8150_t *dev; - - dev = netdev->priv; - if (!dev) - return; + rtl8150_t *dev = netdev_priv(netdev); warn("%s: Tx timeout.", netdev->name); dev->tx_urb->transfer_flags |= URB_ASYNC_UNLINK; usb_unlink_urb(dev->tx_urb); @@ -669,9 +662,7 @@ static void rtl8150_tx_timeout(struct ne static void rtl8150_set_multicast(struct net_device *netdev) { - rtl8150_t *dev; - - dev = netdev->priv; + rtl8150_t *dev = netdev_priv(netdev); netif_stop_queue(netdev); if (netdev->flags & IFF_PROMISC) { dev->rx_creg |= cpu_to_le16(0x0001); @@ -691,11 +682,10 @@ static void rtl8150_set_multicast(struct static int rtl8150_start_xmit(struct sk_buff *skb, struct net_device *netdev) { - rtl8150_t *dev; + rtl8150_t *dev = netdev_priv(netdev); int count, res; netif_stop_queue(netdev); - dev = netdev->priv; count = (skb->len < 60) ? 60 : skb->len; count = (count & 0x3f) ? count : count + 1; dev->tx_skb = skb; @@ -717,7 +707,7 @@ static int rtl8150_start_xmit(struct sk_ static void set_carrier(struct net_device *netdev) { - rtl8150_t *dev = netdev->priv; + rtl8150_t *dev = netdev_priv(netdev); short tmp; get_registers(dev, CSCR, 2, &tmp); @@ -729,13 +719,9 @@ static void set_carrier(struct net_devic static int rtl8150_open(struct net_device *netdev) { - rtl8150_t *dev; + rtl8150_t *dev = netdev_priv(netdev); int res; - dev = netdev->priv; - if (dev == NULL) { - return -ENODEV; - } if (dev->rx_skb == NULL) dev->rx_skb = pull_skb(dev); if (!dev->rx_skb) @@ -761,13 +747,9 @@ static int rtl8150_open(struct net_devic static int rtl8150_close(struct net_device *netdev) { - rtl8150_t *dev; + rtl8150_t *dev = netdev_priv(netdev); int res = 0; - dev = netdev->priv; - if (!dev) - return -ENODEV; - netif_stop_queue(netdev); if (!test_bit(RTL8150_UNPLUG, &dev->flags)) disable_net_traffic(dev); @@ -776,93 +758,64 @@ static int rtl8150_close(struct net_devi return res; } -static int rtl8150_ethtool_ioctl(struct net_device *netdev, void __user *uaddr) +static void rtl8150_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info) { - rtl8150_t *dev; - int cmd; - - dev = netdev->priv; - if (get_user(cmd, (int __user *) uaddr)) - return -EFAULT; + rtl8150_t *dev = netdev_priv(netdev); - switch (cmd) { - case ETHTOOL_GDRVINFO:{ - struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; - - strncpy(info.driver, driver_name, ETHTOOL_BUSINFO_LEN); - strncpy(info.version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN); - usb_make_path(dev->udev, info.bus_info, sizeof info.bus_info); - if (copy_to_user(uaddr, &info, sizeof(info))) - return -EFAULT; - return 0; - } - case ETHTOOL_GSET:{ - struct ethtool_cmd ecmd; - short lpa, bmcr; - - if (copy_from_user(&ecmd, uaddr, sizeof(ecmd))) - return -EFAULT; - ecmd.supported = (SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_Autoneg | - SUPPORTED_TP | SUPPORTED_MII); - ecmd.port = PORT_TP; - ecmd.transceiver = XCVR_INTERNAL; - ecmd.phy_address = dev->phy; - get_registers(dev, BMCR, 2, &bmcr); - get_registers(dev, ANLP, 2, &lpa); - if (bmcr & BMCR_ANENABLE) { - ecmd.autoneg = AUTONEG_ENABLE; - ecmd.speed = (lpa & (LPA_100HALF | LPA_100FULL)) ? - SPEED_100 : SPEED_10; - if (ecmd.speed == SPEED_100) - ecmd.duplex = (lpa & LPA_100FULL) ? - DUPLEX_FULL : DUPLEX_HALF; - else - ecmd.duplex = (lpa & LPA_10FULL) ? - DUPLEX_FULL : DUPLEX_HALF; - } else { - ecmd.autoneg = AUTONEG_DISABLE; - ecmd.speed = (bmcr & BMCR_SPEED100) ? - SPEED_100 : SPEED_10; - ecmd.duplex = (bmcr & BMCR_FULLDPLX) ? + strncpy(info->driver, driver_name, ETHTOOL_BUSINFO_LEN); + strncpy(info->version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN); + usb_make_path(dev->udev, info->bus_info, sizeof info->bus_info); +} + +static int rtl8150_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) +{ + rtl8150_t *dev = netdev_priv(netdev); + short lpa, bmcr; + + ecmd->supported = (SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_Autoneg | + SUPPORTED_TP | SUPPORTED_MII); + ecmd->port = PORT_TP; + ecmd->transceiver = XCVR_INTERNAL; + ecmd->phy_address = dev->phy; + get_registers(dev, BMCR, 2, &bmcr); + get_registers(dev, ANLP, 2, &lpa); + if (bmcr & BMCR_ANENABLE) { + ecmd->autoneg = AUTONEG_ENABLE; + ecmd->speed = (lpa & (LPA_100HALF | LPA_100FULL)) ? + SPEED_100 : SPEED_10; + if (ecmd->speed == SPEED_100) + ecmd->duplex = (lpa & LPA_100FULL) ? DUPLEX_FULL : DUPLEX_HALF; - } - if (copy_to_user(uaddr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; - } - case ETHTOOL_SSET: - return -ENOTSUPP; - case ETHTOOL_GLINK:{ - struct ethtool_value edata = { ETHTOOL_GLINK }; - - edata.data = netif_carrier_ok(netdev); - if (copy_to_user(uaddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - default: - return -EOPNOTSUPP; + else + ecmd->duplex = (lpa & LPA_10FULL) ? + DUPLEX_FULL : DUPLEX_HALF; + } else { + ecmd->autoneg = AUTONEG_DISABLE; + ecmd->speed = (bmcr & BMCR_SPEED100) ? + SPEED_100 : SPEED_10; + ecmd->duplex = (bmcr & BMCR_FULLDPLX) ? + DUPLEX_FULL : DUPLEX_HALF; } + return 0; } +static struct ethtool_ops ops = { + .get_drvinfo = rtl8150_get_drvinfo, + .get_settings = rtl8150_get_settings, + .get_link = ethtool_op_get_link +}; + static int rtl8150_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) { - rtl8150_t *dev; - u16 *data; - int res; - - dev = netdev->priv; - data = (u16 *) & rq->ifr_ifru; - res = 0; + rtl8150_t *dev = netdev_priv(netdev); + u16 *data = (u16 *) & rq->ifr_ifru; + int res = 0; switch (cmd) { - case SIOCETHTOOL: - res = rtl8150_ethtool_ioctl(netdev, rq->ifr_data); - break; case SIOCDEVPRIVATE: data[0] = dev->phy; case SIOCDEVPRIVATE + 1: @@ -887,23 +840,18 @@ static int rtl8150_probe(struct usb_inte rtl8150_t *dev; struct net_device *netdev; - dev = kmalloc(sizeof(rtl8150_t), GFP_KERNEL); - if (!dev) { + netdev = alloc_etherdev(sizeof(rtl8150_t)); + if (!netdev) { err("Out of memory"); return -ENOMEM; - } else - memset(dev, 0, sizeof(rtl8150_t)); + } + + dev = netdev_priv(netdev); + memset(dev, 0, sizeof(rtl8150_t)); dev->intr_buff = kmalloc(INTBUFSIZE, GFP_KERNEL); if (!dev->intr_buff) { - kfree(dev); - return -ENOMEM; - } - netdev = alloc_etherdev(0); - if (!netdev) { - kfree(dev->intr_buff); - kfree(dev); - err("Oh boy, out of memory again?!?"); + free_netdev(netdev); return -ENOMEM; } @@ -913,7 +861,6 @@ static int rtl8150_probe(struct usb_inte dev->udev = udev; dev->netdev = netdev; SET_MODULE_OWNER(netdev); - netdev->priv = dev; netdev->open = rtl8150_open; netdev->stop = rtl8150_close; netdev->do_ioctl = rtl8150_ioctl; @@ -924,6 +871,7 @@ static int rtl8150_probe(struct usb_inte netdev->set_mac_address = rtl8150_set_mac_address; netdev->get_stats = rtl8150_netdev_stats; netdev->mtu = RTL8150_MTU; + SET_ETHTOOL_OPS(netdev, &ops); dev->intr_interval = 100; /* 100ms */ if (!alloc_all_urbs(dev)) { @@ -954,7 +902,6 @@ out1: out: kfree(dev->intr_buff); free_netdev(netdev); - kfree(dev); return -EIO; } @@ -971,9 +918,8 @@ static void rtl8150_disconnect(struct us free_skb_pool(dev); if (dev->rx_skb) dev_kfree_skb(dev->rx_skb); - free_netdev(dev->netdev); kfree(dev->intr_buff); - kfree(dev); + free_netdev(dev->netdev); } } diff -puN include/linux/netdevice.h~bk-netdev include/linux/netdevice.h --- 25/include/linux/netdevice.h~bk-netdev 2004-09-15 21:06:53.336635320 -0700 +++ 25-akpm/include/linux/netdevice.h 2004-09-15 21:06:53.485612672 -0700 @@ -309,7 +309,9 @@ struct net_device /* List of functions to handle Wireless Extensions (instead of ioctl). * See for details. Jean II */ - struct iw_handler_def * wireless_handlers; + const struct iw_handler_def * wireless_handlers; + /* Instance data managed by the core of Wireless Extensions. */ + struct iw_public_data * wireless_data; struct ethtool_ops *ethtool_ops; diff -puN include/linux/wireless.h~bk-netdev include/linux/wireless.h --- 25/include/linux/wireless.h~bk-netdev 2004-09-15 21:06:53.338635016 -0700 +++ 25-akpm/include/linux/wireless.h 2004-09-15 21:06:53.486612520 -0700 @@ -1,10 +1,10 @@ /* * This file define a set of standard wireless extensions * - * Version : 16 2.4.03 + * Version : 17 21.6.04 * * Authors : Jean Tourrilhes - HPL - - * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved. + * Copyright (c) 1997-2004 Jean Tourrilhes, All Rights Reserved. */ #ifndef _LINUX_WIRELESS_H @@ -47,12 +47,12 @@ * # include/net/iw_handler.h * * Note as well that /proc/net/wireless implementation has now moved in : - * # include/linux/wireless.c + * # net/core/wireless.c * * Wireless Events (2002 -> onward) : * -------------------------------- * Events are defined at the end of this file, and implemented in : - * # include/linux/wireless.c + * # net/core/wireless.c * * Other comments : * -------------- @@ -82,7 +82,7 @@ * (there is some stuff that will be added in the future...) * I just plan to increment with each new version. */ -#define WIRELESS_EXT 16 +#define WIRELESS_EXT 17 /* * Changes : @@ -175,6 +175,13 @@ * - Remove IW_MAX_GET_SPY because conflict with enhanced spy support * - Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy" * - Add IW_ENCODE_TEMP and iw_range->encoding_login_index + * + * V16 to V17 + * ---------- + * - Add flags to frequency -> auto/fixed + * - Document (struct iw_quality *)->updated, add new flags (INVALID) + * - Wireless Event capability in struct iw_range + * - Add support for relative TxPower (yick !) */ /**************************** CONSTANTS ****************************/ @@ -251,7 +258,7 @@ /* -------------------- DEV PRIVATE IOCTL LIST -------------------- */ -/* These 16 ioctl are wireless device private. +/* These 32 ioctl are wireless device private, for 16 commands. * Each driver is free to use them for whatever purpose it chooses, * however the driver *must* export the description of those ioctls * with SIOCGIWPRIV and *must* use arguments as defined below. @@ -266,8 +273,8 @@ * We now have 32 commands, so a bit more space ;-). * Also, all 'odd' commands are only usable by root and don't return the * content of ifr/iwr to user (but you are not obliged to use the set/get - * convention, just use every other two command). - * And I repeat : you are not obliged to use them with iwspy, but you + * convention, just use every other two command). More details in iwpriv.c. + * And I repeat : you are not forced to use them with iwpriv, but you * must be compliant with it. */ @@ -352,6 +359,18 @@ #define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */ #define IW_MODE_MONITOR 6 /* Passive monitor (listen only) */ +/* Statistics flags (bitmask in updated) */ +#define IW_QUAL_QUAL_UPDATED 0x1 /* Value was updated since last read */ +#define IW_QUAL_LEVEL_UPDATED 0x2 +#define IW_QUAL_NOISE_UPDATED 0x4 +#define IW_QUAL_QUAL_INVALID 0x10 /* Driver doesn't provide value */ +#define IW_QUAL_LEVEL_INVALID 0x20 +#define IW_QUAL_NOISE_INVALID 0x40 + +/* Frequency flags */ +#define IW_FREQ_AUTO 0x00 /* Let the driver decides */ +#define IW_FREQ_FIXED 0x01 /* Force a specific value */ + /* Maximum number of size of encoding token available * they are listed in the range structure */ #define IW_MAX_ENCODING_SIZES 8 @@ -390,6 +409,7 @@ #define IW_TXPOW_TYPE 0x00FF /* Type of value */ #define IW_TXPOW_DBM 0x0000 /* Value is in dBm */ #define IW_TXPOW_MWATT 0x0001 /* Value is in mW */ +#define IW_TXPOW_RELATIVE 0x0002 /* Value is in arbitrary units */ #define IW_TXPOW_RANGE 0x1000 /* Range of value between min/max */ /* Retry limits and lifetime flags available */ @@ -418,6 +438,25 @@ /* Max number of char in custom event - use multiple of them if needed */ #define IW_CUSTOM_MAX 256 /* In bytes */ +/* Event capability macros - in (struct iw_range *)->event_capa + * Because we have more than 32 possible events, we use an array of + * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */ +#define IW_EVENT_CAPA_BASE(cmd) ((cmd >= SIOCIWFIRSTPRIV) ? \ + (cmd - SIOCIWFIRSTPRIV + 0x60) : \ + (cmd - SIOCSIWCOMMIT)) +#define IW_EVENT_CAPA_INDEX(cmd) (IW_EVENT_CAPA_BASE(cmd) >> 5) +#define IW_EVENT_CAPA_MASK(cmd) (1 << (IW_EVENT_CAPA_BASE(cmd) & 0x1F)) +/* Event capability constants - event autogenerated by the kernel + * This list is valid for most 802.11 devices, customise as needed... */ +#define IW_EVENT_CAPA_K_0 (IW_EVENT_CAPA_MASK(0x8B04) | \ + IW_EVENT_CAPA_MASK(0x8B06) | \ + IW_EVENT_CAPA_MASK(0x8B1A)) +#define IW_EVENT_CAPA_K_1 (IW_EVENT_CAPA_MASK(0x8B2A)) +/* "Easy" macro to set events in iw_range (less efficient) */ +#define IW_EVENT_CAPA_SET(event_capa, cmd) (event_capa[IW_EVENT_CAPA_INDEX(cmd)] |= IW_EVENT_CAPA_MASK(cmd)) +#define IW_EVENT_CAPA_SET_KERNEL(event_capa) {event_capa[0] |= IW_EVENT_CAPA_K_0; event_capa[1] |= IW_EVENT_CAPA_K_1; } + + /****************************** TYPES ******************************/ /* --------------------------- SUBTYPES --------------------------- */ @@ -456,7 +495,7 @@ struct iw_freq __s32 m; /* Mantissa */ __s16 e; /* Exponent */ __u8 i; /* List index (when in range struct) */ - __u8 pad; /* Unused - just for alignement */ + __u8 flags; /* Flags (fixed/auto) */ }; /* @@ -610,11 +649,12 @@ struct iw_range /* Old Frequency (backward compat - moved lower ) */ __u16 old_num_channels; __u8 old_num_frequency; - /* Filler to keep "version" at the same offset */ - __s32 old_freq[6]; + + /* Wireless event capability bitmasks */ + __u32 event_capa[6]; /* signal level threshold range */ - __s32 sensitivity; + __s32 sensitivity; /* Quality of link & SNR stuff */ /* Quality range (link, level, noise) diff -puN include/net/iw_handler.h~bk-netdev include/net/iw_handler.h --- 25/include/net/iw_handler.h~bk-netdev 2004-09-15 21:06:53.339634864 -0700 +++ 25-akpm/include/net/iw_handler.h 2004-09-15 21:06:53.488612216 -0700 @@ -1,10 +1,10 @@ /* * This file define the new driver API for Wireless Extensions * - * Version : 5 4.12.02 + * Version : 6 21.6.04 * * Authors : Jean Tourrilhes - HPL - - * Copyright (c) 2001-2002 Jean Tourrilhes, All Rights Reserved. + * Copyright (c) 2001-2004 Jean Tourrilhes, All Rights Reserved. */ #ifndef _IW_HANDLER_H @@ -206,7 +206,7 @@ * will be needed... * I just plan to increment with each new version. */ -#define IW_HANDLER_VERSION 5 +#define IW_HANDLER_VERSION 6 /* * Changes : @@ -224,11 +224,18 @@ * V4 to V5 * -------- * - Add new spy support : struct iw_spy_data & prototypes + * + * V5 to V6 + * -------- + * - Change the way we get to spy_data method for added safety + * - Remove spy #ifdef, they are always on -> cleaner code + * - Add IW_DESCR_FLAG_NOMAX flag for very large requests + * - Start migrating get_wireless_stats to struct iw_handler_def */ /**************************** CONSTANTS ****************************/ -/* Enable enhanced spy support. Disable to reduce footprint */ +/* Enhanced spy support available */ #define IW_WIRELESS_SPY #define IW_WIRELESS_THRSPY @@ -258,6 +265,7 @@ #define IW_DESCR_FLAG_EVENT 0x0002 /* Generate an event on SET */ #define IW_DESCR_FLAG_RESTRICT 0x0004 /* GET : request is ROOT only */ /* SET : Omit payload from generated iwevent */ +#define IW_DESCR_FLAG_NOMAX 0x0008 /* GET : no limit on request size */ /* Driver level flags */ #define IW_DESCR_FLAG_WAIT 0x0100 /* Wait for driver event */ @@ -303,31 +311,33 @@ struct iw_handler_def { /* Number of handlers defined (more precisely, index of the * last defined handler + 1) */ - __u16 num_standard; - __u16 num_private; + const __u16 num_standard; + const __u16 num_private; /* Number of private arg description */ - __u16 num_private_args; + const __u16 num_private_args; /* Array of handlers for standard ioctls * We will call dev->wireless_handlers->standard[ioctl - SIOCSIWNAME] */ - iw_handler * standard; + const iw_handler * standard; /* Array of handlers for private ioctls * Will call dev->wireless_handlers->private[ioctl - SIOCIWFIRSTPRIV] */ - iw_handler * private; + const iw_handler * private; /* Arguments of private handler. This one is just a list, so you * can put it in any order you want and should not leave holes... * We will automatically export that to user space... */ - struct iw_priv_args * private_args; + const struct iw_priv_args * private_args; - /* Driver enhanced spy support */ - long spy_offset; /* Spy data offset */ + /* This field will be *removed* in the next version of WE */ + const long spy_offset; /* DO NOT USE */ - /* In the long term, get_wireless_stats will move from - * 'struct net_device' to here, to minimise bloat. */ + /* New location of get_wireless_stats, to de-bloat struct net_device. + * The old pointer in struct net_device will be gradually phased + * out, and drivers are encouraged to use this one... */ + struct iw_statistics* (*get_wireless_stats)(struct net_device *dev); }; /* ---------------------- IOCTL DESCRIPTION ---------------------- */ @@ -374,18 +384,29 @@ struct iw_ioctl_description */ struct iw_spy_data { -#ifdef IW_WIRELESS_SPY /* --- Standard spy support --- */ int spy_number; u_char spy_address[IW_MAX_SPY][ETH_ALEN]; struct iw_quality spy_stat[IW_MAX_SPY]; -#ifdef IW_WIRELESS_THRSPY /* --- Enhanced spy support (event) */ struct iw_quality spy_thr_low; /* Low threshold */ struct iw_quality spy_thr_high; /* High threshold */ u_char spy_thr_under[IW_MAX_SPY]; -#endif /* IW_WIRELESS_THRSPY */ -#endif /* IW_WIRELESS_SPY */ +}; + +/* --------------------- DEVICE WIRELESS DATA --------------------- */ +/* + * This is all the wireless data specific to a device instance that + * is managed by the core of Wireless Extensions. + * We only keep pointer to those structures, so that a driver is free + * to share them between instances. + * This structure should be initialised before registering the device. + * Access to this data follow the same rules as any other struct net_device + * data (i.e. valid as long as struct net_device exist, same locking rules). + */ +struct iw_public_data { + /* Driver enhanced spy support */ + struct iw_spy_data * spy_data; }; /**************************** PROTOTYPES ****************************/ @@ -394,6 +415,9 @@ struct iw_spy_data * Those may be called only within the kernel. */ +/* Data needed by fs/compat_ioctl.c for 32->64 bit conversion */ +extern const char iw_priv_type_size[]; + /* First : function strictly used inside the kernel */ /* Handle /proc/net/wireless, called in net/code/dev.c */ diff -puN net/core/dev.c~bk-netdev net/core/dev.c --- 25/net/core/dev.c~bk-netdev 2004-09-15 21:06:53.341634560 -0700 +++ 25-akpm/net/core/dev.c 2004-09-15 21:06:53.490611912 -0700 @@ -2745,7 +2745,7 @@ int dev_ioctl(unsigned int cmd, void __u /* Follow me in net/core/wireless.c */ ret = wireless_process_ioctl(&ifr, cmd); rtnl_unlock(); - if (!ret && IW_IS_GET(cmd) && + if (IW_IS_GET(cmd) && copy_to_user(arg, &ifr, sizeof(struct ifreq))) ret = -EFAULT; diff -puN net/core/wireless.c~bk-netdev net/core/wireless.c --- 25/net/core/wireless.c~bk-netdev 2004-09-15 21:06:53.343634256 -0700 +++ 25-akpm/net/core/wireless.c 2004-09-15 21:06:53.494611304 -0700 @@ -2,7 +2,7 @@ * This file implement the Wireless Extensions APIs. * * Authors : Jean Tourrilhes - HPL - - * Copyright (c) 1997-2003 Jean Tourrilhes, All Rights Reserved. + * Copyright (c) 1997-2004 Jean Tourrilhes, All Rights Reserved. * * (As all part of the Linux kernel, this file is GPL) */ @@ -48,6 +48,15 @@ * o Add common spy support : iw_handler_set_spy(), wireless_spy_update() * o Add enhanced spy support : iw_handler_set_thrspy() and event. * o Add WIRELESS_EXT version display in /proc/net/wireless + * + * v6 - 18.06.04 - Jean II + * o Change get_spydata() method for added safety + * o Remove spy #ifdef, they are always on -> cleaner code + * o Allow any size GET request is user specifies length > max + * o Start migrating get_wireless_stats to struct iw_handler_def + * o Add wmb() in iw_handler_set_spy() for non-coherent archs/cpus + * Based on patch from Pavel Roskin : + * o Fix kernel data leak to user space in private handler handling */ /***************************** INCLUDES *****************************/ @@ -69,10 +78,6 @@ /**************************** CONSTANTS ****************************/ -/* Enough lenience, let's make sure things are proper... */ -#define WE_STRICT_WRITE /* Check write buffer size */ -/* I'll probably drop both the define and kernel message in the next version */ - /* Debugging stuff */ #undef WE_IOCTL_DEBUG /* Debug IOCTL API */ #undef WE_EVENT_DEBUG /* Debug Event dispatcher */ @@ -186,6 +191,7 @@ static const struct iw_ioctl_description .token_size = sizeof(struct sockaddr) + sizeof(struct iw_quality), .max_tokens = IW_MAX_AP, + .flags = IW_DESCR_FLAG_NOMAX, }, [SIOCSIWSCAN - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, @@ -194,6 +200,7 @@ static const struct iw_ioctl_description .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_SCAN_MAX_DATA, + .flags = IW_DESCR_FLAG_NOMAX, }, [SIOCSIWESSID - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, @@ -296,7 +303,7 @@ static const int standard_event_num = (s sizeof(struct iw_ioctl_description)); /* Size (in bytes) of the various private data types */ -static const char priv_type_size[] = { +const char iw_priv_type_size[] = { 0, /* IW_PRIV_TYPE_NONE */ 1, /* IW_PRIV_TYPE_BYTE */ 1, /* IW_PRIV_TYPE_CHAR */ @@ -363,12 +370,15 @@ static inline iw_handler get_handler(str */ static inline struct iw_statistics *get_wireless_stats(struct net_device *dev) { + /* New location */ + if((dev->wireless_handlers != NULL) && + (dev->wireless_handlers->get_wireless_stats != NULL)) + return dev->wireless_handlers->get_wireless_stats(dev); + + /* Old location, will be phased out in next WE */ return (dev->get_wireless_stats ? dev->get_wireless_stats(dev) : (struct iw_statistics *) NULL); - /* In the future, get_wireless_stats may move from 'struct net_device' - * to 'struct iw_handler_def', to de-bloat struct net_device. - * Definitely worse a thought... */ } /* ---------------------------------------------------------------- */ @@ -403,14 +413,32 @@ static inline int call_commit_handler(st /* ---------------------------------------------------------------- */ /* - * Number of private arguments + * Calculate size of private arguments */ static inline int get_priv_size(__u16 args) { int num = args & IW_PRIV_SIZE_MASK; int type = (args & IW_PRIV_TYPE_MASK) >> 12; - return num * priv_type_size[type]; + return num * iw_priv_type_size[type]; +} + +/* ---------------------------------------------------------------- */ +/* + * Re-calculate the size of private arguments + */ +static inline int adjust_priv_size(__u16 args, + union iwreq_data * wrqu) +{ + int num = wrqu->data.length; + int max = args & IW_PRIV_SIZE_MASK; + int type = (args & IW_PRIV_TYPE_MASK) >> 12; + + /* Make sure the driver doesn't goof up */ + if (max < num) + num = max; + + return num * iw_priv_type_size[type]; } @@ -440,11 +468,14 @@ static __inline__ void wireless_seq_prin seq_printf(seq, "%6s: %04x %3d%c %3d%c %3d%c %6d %6d %6d " "%6d %6d %6d\n", dev->name, stats->status, stats->qual.qual, - stats->qual.updated & 1 ? '.' : ' ', + stats->qual.updated & IW_QUAL_QUAL_UPDATED + ? '.' : ' ', ((__u8) stats->qual.level), - stats->qual.updated & 2 ? '.' : ' ', + stats->qual.updated & IW_QUAL_LEVEL_UPDATED + ? '.' : ' ', ((__u8) stats->qual.noise), - stats->qual.updated & 4 ? '.' : ' ', + stats->qual.updated & IW_QUAL_NOISE_UPDATED + ? '.' : ' ', stats->discard.nwid, stats->discard.code, stats->discard.fragment, stats->discard.retries, stats->discard.misc, stats->miss.beacon); @@ -555,13 +586,15 @@ static inline int ioctl_export_private(s /* Check NULL pointer */ if(iwr->u.data.pointer == NULL) return -EFAULT; -#ifdef WE_STRICT_WRITE + /* Check if there is enough buffer up there */ if(iwr->u.data.length < dev->wireless_handlers->num_private_args) { - printk(KERN_ERR "%s (WE) : Buffer for request SIOCGIWPRIV too small (%d<%d)\n", dev->name, iwr->u.data.length, dev->wireless_handlers->num_private_args); + /* User space can't know in advance how large the buffer + * needs to be. Give it a hint, so that we can support + * any size buffer we want somewhat efficiently... */ + iwr->u.data.length = dev->wireless_handlers->num_private_args; return -E2BIG; } -#endif /* WE_STRICT_WRITE */ /* Set the number of available ioctls. */ iwr->u.data.length = dev->wireless_handlers->num_private_args; @@ -590,7 +623,6 @@ static inline int ioctl_standard_call(st const struct iw_ioctl_description * descr; struct iw_request_info info; int ret = -EINVAL; - int user_size = 0; /* Get the description of the IOCTL */ if((cmd - SIOCIWFIRST) >= standard_ioctl_num) @@ -621,8 +653,14 @@ static inline int ioctl_standard_call(st #endif /* WE_SET_EVENT */ } else { char * extra; + int extra_size; + int user_length = 0; int err; + /* Calculate space needed by arguments. Always allocate + * for max space. Easier, and won't last long... */ + extra_size = descr->max_tokens * descr->token_size; + /* Check what user space is giving us */ if(IW_IS_SET(cmd)) { /* Check NULL pointer */ @@ -639,18 +677,29 @@ static inline int ioctl_standard_call(st if(iwr->u.data.pointer == NULL) return -EFAULT; /* Save user space buffer size for checking */ - user_size = iwr->u.data.length; + user_length = iwr->u.data.length; + + /* Don't check if user_length > max to allow forward + * compatibility. The test user_length < min is + * implied by the test at the end. */ + + /* Support for very large requests */ + if((descr->flags & IW_DESCR_FLAG_NOMAX) && + (user_length > descr->max_tokens)) { + /* Allow userspace to GET more than max so + * we can support any size GET requests. + * There is still a limit : -ENOMEM. */ + extra_size = user_length * descr->token_size; + } } #ifdef WE_IOCTL_DEBUG printk(KERN_DEBUG "%s (WE) : Malloc %d bytes\n", - dev->name, descr->max_tokens * descr->token_size); + dev->name, extra_size); #endif /* WE_IOCTL_DEBUG */ - /* Always allocate for max space. Easier, and won't last - * long... */ - extra = kmalloc(descr->max_tokens * descr->token_size, - GFP_KERNEL); + /* Create the kernel buffer */ + extra = kmalloc(extra_size, GFP_KERNEL); if (extra == NULL) { return -ENOMEM; } @@ -676,14 +725,11 @@ static inline int ioctl_standard_call(st /* If we have something to return to the user */ if (!ret && IW_IS_GET(cmd)) { -#ifdef WE_STRICT_WRITE /* Check if there is enough buffer up there */ - if(user_size < iwr->u.data.length) { - printk(KERN_ERR "%s (WE) : Buffer for request %04X too small (%d<%d)\n", dev->name, cmd, user_size, iwr->u.data.length); + if(user_length < iwr->u.data.length) { kfree(extra); return -E2BIG; } -#endif /* WE_STRICT_WRITE */ err = copy_to_user(iwr->u.data.pointer, extra, iwr->u.data.length * @@ -746,7 +792,7 @@ static inline int ioctl_private_call(str iw_handler handler) { struct iwreq * iwr = (struct iwreq *) ifr; - struct iw_priv_args * descr = NULL; + const struct iw_priv_args * descr = NULL; struct iw_request_info info; int extra_size = 0; int i; @@ -786,7 +832,7 @@ static inline int ioctl_private_call(str ((extra_size + offset) <= IFNAMSIZ)) extra_size = 0; } else { - /* Size of set arguments */ + /* Size of get arguments */ extra_size = get_priv_size(descr->get_args); /* Does it fits in iwr ? */ @@ -816,7 +862,7 @@ static inline int ioctl_private_call(str return -EFAULT; /* Does it fits within bounds ? */ - if(iwr->u.data.length > (descr->set_args & + if(iwr->u.data.length > (descr->get_args & IW_PRIV_SIZE_MASK)) return -E2BIG; } else { @@ -856,6 +902,14 @@ static inline int ioctl_private_call(str /* If we have something to return to the user */ if (!ret && IW_IS_GET(cmd)) { + + /* Adjust for the actual length if it's variable, + * avoid leaking kernel bits outside. */ + if (!(descr->get_args & IW_PRIV_SIZE_FIXED)) { + extra_size = adjust_priv_size(descr->get_args, + &(iwr->u)); + } + err = copy_to_user(iwr->u.data.pointer, extra, extra_size); if (err) @@ -1127,9 +1181,25 @@ void wireless_send_event(struct net_devi * One of the main advantage of centralising spy support here is that * it becomes much easier to improve and extend it without having to touch * the drivers. One example is the addition of the Spy-Threshold events. - * Note : IW_WIRELESS_SPY is defined in iw_handler.h */ +/* ---------------------------------------------------------------- */ +/* + * Return the pointer to the spy data in the driver. + * Because this is called on the Rx path via wireless_spy_update(), + * we want it to be efficient... + */ +static inline struct iw_spy_data * get_spydata(struct net_device *dev) +{ + /* This is the new way */ + if(dev->wireless_data) + return(dev->wireless_data->spy_data); + + /* This is the old way. Doesn't work for multi-headed drivers. + * It will be removed in the next version of WE. */ + return (dev->priv + dev->wireless_handlers->spy_offset); +} + /*------------------------------------------------------------------*/ /* * Standard Wireless Handler : set Spy List @@ -1139,16 +1209,30 @@ int iw_handler_set_spy(struct net_device union iwreq_data * wrqu, char * extra) { -#ifdef IW_WIRELESS_SPY - struct iw_spy_data * spydata = (dev->priv + - dev->wireless_handlers->spy_offset); + struct iw_spy_data * spydata = get_spydata(dev); struct sockaddr * address = (struct sockaddr *) extra; + if(!dev->wireless_data) + /* Help user know that driver needs updating */ + printk(KERN_DEBUG "%s (WE) : Driver using old/buggy spy support, please fix driver !\n", + dev->name); + /* Make sure driver is not buggy or using the old API */ + if(!spydata) + return -EOPNOTSUPP; + /* Disable spy collection while we copy the addresses. - * As we don't disable interrupts, we need to do this to avoid races. - * As we are the only writer, this is good enough. */ + * While we copy addresses, any call to wireless_spy_update() + * will NOP. This is OK, as anyway the addresses are changing. */ spydata->spy_number = 0; + /* We want to operate without locking, because wireless_spy_update() + * most likely will happen in the interrupt handler, and therefore + * have it own locking constraints and needs performance. + * The rtnl_lock() make sure we don't race with the other iw_handlers. + * This make sure wireless_spy_update() "see" that the spy list + * is temporarily disabled. */ + wmb(); + /* Are there are addresses to copy? */ if(wrqu->data.length > 0) { int i; @@ -1174,13 +1258,14 @@ int iw_handler_set_spy(struct net_device spydata->spy_address[i][5]); #endif /* WE_SPY_DEBUG */ } + + /* Make sure above is updated before re-enabling */ + wmb(); + /* Enable addresses */ spydata->spy_number = wrqu->data.length; return 0; -#else /* IW_WIRELESS_SPY */ - return -EOPNOTSUPP; -#endif /* IW_WIRELESS_SPY */ } /*------------------------------------------------------------------*/ @@ -1192,12 +1277,14 @@ int iw_handler_get_spy(struct net_device union iwreq_data * wrqu, char * extra) { -#ifdef IW_WIRELESS_SPY - struct iw_spy_data * spydata = (dev->priv + - dev->wireless_handlers->spy_offset); + struct iw_spy_data * spydata = get_spydata(dev); struct sockaddr * address = (struct sockaddr *) extra; int i; + /* Make sure driver is not buggy or using the old API */ + if(!spydata) + return -EOPNOTSUPP; + wrqu->data.length = spydata->spy_number; /* Copy addresses. */ @@ -1214,9 +1301,6 @@ int iw_handler_get_spy(struct net_device for(i = 0; i < spydata->spy_number; i++) spydata->spy_stat[i].updated = 0; return 0; -#else /* IW_WIRELESS_SPY */ - return -EOPNOTSUPP; -#endif /* IW_WIRELESS_SPY */ } /*------------------------------------------------------------------*/ @@ -1228,11 +1312,13 @@ int iw_handler_set_thrspy(struct net_dev union iwreq_data * wrqu, char * extra) { -#ifdef IW_WIRELESS_THRSPY - struct iw_spy_data * spydata = (dev->priv + - dev->wireless_handlers->spy_offset); + struct iw_spy_data * spydata = get_spydata(dev); struct iw_thrspy * threshold = (struct iw_thrspy *) extra; + /* Make sure driver is not buggy or using the old API */ + if(!spydata) + return -EOPNOTSUPP; + /* Just do it */ memcpy(&(spydata->spy_thr_low), &(threshold->low), 2 * sizeof(struct iw_quality)); @@ -1245,9 +1331,6 @@ int iw_handler_set_thrspy(struct net_dev #endif /* WE_SPY_DEBUG */ return 0; -#else /* IW_WIRELESS_THRSPY */ - return -EOPNOTSUPP; -#endif /* IW_WIRELESS_THRSPY */ } /*------------------------------------------------------------------*/ @@ -1259,22 +1342,20 @@ int iw_handler_get_thrspy(struct net_dev union iwreq_data * wrqu, char * extra) { -#ifdef IW_WIRELESS_THRSPY - struct iw_spy_data * spydata = (dev->priv + - dev->wireless_handlers->spy_offset); + struct iw_spy_data * spydata = get_spydata(dev); struct iw_thrspy * threshold = (struct iw_thrspy *) extra; + /* Make sure driver is not buggy or using the old API */ + if(!spydata) + return -EOPNOTSUPP; + /* Just do it */ memcpy(&(threshold->low), &(spydata->spy_thr_low), 2 * sizeof(struct iw_quality)); return 0; -#else /* IW_WIRELESS_THRSPY */ - return -EOPNOTSUPP; -#endif /* IW_WIRELESS_THRSPY */ } -#ifdef IW_WIRELESS_THRSPY /*------------------------------------------------------------------*/ /* * Prepare and send a Spy Threshold event @@ -1312,7 +1393,6 @@ static void iw_send_thrspy_event(struct /* Send event to user space */ wireless_send_event(dev, SIOCGIWTHRSPY, &wrqu, (char *) &threshold); } -#endif /* IW_WIRELESS_THRSPY */ /* ---------------------------------------------------------------- */ /* @@ -1325,12 +1405,14 @@ void wireless_spy_update(struct net_devi unsigned char * address, struct iw_quality * wstats) { -#ifdef IW_WIRELESS_SPY - struct iw_spy_data * spydata = (dev->priv + - dev->wireless_handlers->spy_offset); + struct iw_spy_data * spydata = get_spydata(dev); int i; int match = -1; + /* Make sure driver is not buggy or using the old API */ + if(!spydata) + return; + #ifdef WE_SPY_DEBUG printk(KERN_DEBUG "wireless_spy_update() : offset %ld, spydata %p, address %02X:%02X:%02X:%02X:%02X:%02X\n", dev->wireless_handlers->spy_offset, spydata, address[0], address[1], address[2], address[3], address[4], address[5]); #endif /* WE_SPY_DEBUG */ @@ -1342,7 +1424,7 @@ void wireless_spy_update(struct net_devi sizeof(struct iw_quality)); match = i; } -#ifdef IW_WIRELESS_THRSPY + /* Generate an event if we cross the spy threshold. * To avoid event storms, we have a simple hysteresis : we generate * event only when we go under the low threshold or above the @@ -1362,8 +1444,6 @@ void wireless_spy_update(struct net_devi } } } -#endif /* IW_WIRELESS_THRSPY */ -#endif /* IW_WIRELESS_SPY */ } EXPORT_SYMBOL(iw_handler_get_spy); diff -puN net/irda/irlan/irlan_client.c~bk-netdev net/irda/irlan/irlan_client.c --- 25/net/irda/irlan/irlan_client.c~bk-netdev 2004-09-15 21:06:53.344634104 -0700 +++ 25-akpm/net/irda/irlan/irlan_client.c 2004-09-15 21:06:53.495611152 -0700 @@ -234,7 +234,7 @@ static void irlan_client_ctrl_disconnect ASSERT(tsap == self->client.tsap_ctrl, return;); /* Remove frames queued on the control channel */ - while ((skb = skb_dequeue(&self->client.txq))) { + while ((skb = skb_dequeue(&self->client.txq)) != NULL) { dev_kfree_skb(skb); } self->client.tx_busy = FALSE; _