- struct ixgb_adapter *adapter = netdev->priv;
- void __user *addr = ifr->ifr_data;
- uint32_t cmd;
-
- if (get_user(cmd, (uint32_t __user *) addr))
- return -EFAULT;
-
- 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;