ixgb_ethtool.c
来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 722 行 · 第 1/2 页
C
722 行
static intixgb_ethtool_seeprom(struct ixgb_adapter *adapter, struct ethtool_eeprom *eeprom, void __user *user_data){ struct ixgb_hw *hw = &adapter->hw; uint16_t eeprom_buff[256]; int i, max_len, first_word, last_word; void *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; if (eeprom->offset & 1) { /* need read/modify/write of first changed EEPROM word */ /* only the second byte of the word is being modified */ eeprom_buff[0] = ixgb_read_eeprom(hw, first_word); ptr++; } if ((eeprom->offset + eeprom->len) & 1) { /* need read/modify/write of last changed EEPROM word */ /* only the first byte of the word is being modified */ eeprom_buff[last_word - first_word] = ixgb_read_eeprom(hw, last_word); } if (copy_from_user(ptr, user_data, eeprom->len)) return -EFAULT; for (i = 0; i <= (last_word - first_word); i++) ixgb_write_eeprom(hw, first_word + i, eeprom_buff[i]); /* Update the checksum over the first part of the EEPROM if needed */ if (first_word <= EEPROM_CHECKSUM_REG) ixgb_update_eeprom_checksum(hw); return 0;}/* toggle LED 4 times per second = 2 "blinks" per second */#define IXGB_ID_INTERVAL (HZ/4)/* bit defines for adapter->led_status */#define IXGB_LED_ON 0static void ixgb_led_blink_callback(unsigned long data){ struct ixgb_adapter *adapter = (struct ixgb_adapter *)data; if (test_and_change_bit(IXGB_LED_ON, &adapter->led_status)) ixgb_led_off(&adapter->hw); else ixgb_led_on(&adapter->hw); mod_timer(&adapter->blink_timer, jiffies + IXGB_ID_INTERVAL);}static intixgb_ethtool_led_blink(struct ixgb_adapter *adapter, struct ethtool_value *id){ if (!adapter->blink_timer.function) { init_timer(&adapter->blink_timer); adapter->blink_timer.function = ixgb_led_blink_callback; adapter->blink_timer.data = (unsigned long)adapter; } mod_timer(&adapter->blink_timer, jiffies); set_current_state(TASK_INTERRUPTIBLE); if (id->data) schedule_timeout(id->data * HZ); else schedule_timeout(MAX_SCHEDULE_TIMEOUT); del_timer_sync(&adapter->blink_timer); ixgb_led_off(&adapter->hw); clear_bit(IXGB_LED_ON, &adapter->led_status); return 0;}int ixgb_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr){ 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; 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; return 0; }#ifdef NETIF_F_TSO case ETHTOOL_GTSO:{ struct ethtool_value edata = { ETHTOOL_GTSO }; 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; return 0; }#endif default: return -EOPNOTSUPP; }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?