diff options
Diffstat (limited to 'drivers/net/ethernet/intel/ixgbe')
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe.h | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_common.c | 16 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 84 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 7 |
5 files changed, 94 insertions, 18 deletions
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index 6c4d693be08d..a8368d5cf686 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -497,7 +497,8 @@ struct ixgbe_adapter { u64 rsc_total_count; u64 rsc_total_flush; u32 wol; - u16 eeprom_version; + u16 eeprom_verh; + u16 eeprom_verl; u16 eeprom_cap; int node; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c index e02e911057de..ef2afefb0cd4 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c @@ -1305,6 +1305,8 @@ static struct ixgbe_mac_operations mac_ops_82598 = { static struct ixgbe_eeprom_operations eeprom_ops_82598 = { .init_params = &ixgbe_init_eeprom_params_generic, .read = &ixgbe_read_eerd_generic, + .write = &ixgbe_write_eeprom_generic, + .write_buffer = &ixgbe_write_eeprom_buffer_bit_bang_generic, .read_buffer = &ixgbe_read_eerd_buffer_generic, .calc_checksum = &ixgbe_calc_eeprom_checksum_generic, .validate_checksum = &ixgbe_validate_eeprom_checksum_generic, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index 35fa444556b3..834f044be4c3 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -3341,7 +3341,7 @@ static u8 ixgbe_calculate_checksum(u8 *buffer, u32 length) * Communicates with the manageability block. On success return 0 * else return IXGBE_ERR_HOST_INTERFACE_COMMAND. **/ -static s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u8 *buffer, +static s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer, u32 length) { u32 hicr, i; @@ -3374,7 +3374,7 @@ static s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u8 *buffer, */ for (i = 0; i < dword_len; i++) IXGBE_WRITE_REG_ARRAY(hw, IXGBE_FLEX_MNG, - i, *((u32 *)buffer + i)); + i, cpu_to_le32(buffer[i])); /* Setting this bit tells the ARC that a new command is pending. */ IXGBE_WRITE_REG(hw, IXGBE_HICR, hicr | IXGBE_HICR_C); @@ -3398,9 +3398,10 @@ static s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u8 *buffer, dword_len = hdr_size >> 2; /* first pull in the header so we know the buffer length */ - for (i = 0; i < dword_len; i++) - *((u32 *)buffer + i) = - IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, i); + for (i = 0; i < dword_len; i++) { + buffer[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, i); + le32_to_cpus(&buffer[i]); + } /* If there is any thing in data position pull it in */ buf_len = ((struct ixgbe_hic_hdr *)buffer)->buf_len; @@ -3418,8 +3419,7 @@ static s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u8 *buffer, /* Pull in the rest of the buffer (i is where we left off)*/ for (; i < buf_len; i++) - *((u32 *)buffer + i) = - IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, i); + buffer[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, i); out: return ret_val; @@ -3465,7 +3465,7 @@ s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min, fw_cmd.pad2 = 0; for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) { - ret_val = ixgbe_host_interface_command(hw, (u8 *)&fw_cmd, + ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd, sizeof(fw_cmd)); if (ret_val != 0) continue; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c index e102ff6fb08d..70d58c3849b0 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c @@ -814,26 +814,97 @@ static int ixgbe_get_eeprom(struct net_device *netdev, return ret_val; } +static int ixgbe_set_eeprom(struct net_device *netdev, + struct ethtool_eeprom *eeprom, u8 *bytes) +{ + struct ixgbe_adapter *adapter = netdev_priv(netdev); + struct ixgbe_hw *hw = &adapter->hw; + u16 *eeprom_buff; + void *ptr; + int max_len, first_word, last_word, ret_val = 0; + u16 i; + + if (eeprom->len == 0) + return -EINVAL; + + if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) + return -EINVAL; + + max_len = hw->eeprom.word_size * 2; + + first_word = eeprom->offset >> 1; + last_word = (eeprom->offset + eeprom->len - 1) >> 1; + eeprom_buff = kmalloc(max_len, GFP_KERNEL); + if (!eeprom_buff) + return -ENOMEM; + + ptr = 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 + */ + ret_val = hw->eeprom.ops.read(hw, first_word, &eeprom_buff[0]); + if (ret_val) + goto err; + + 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 + */ + ret_val = hw->eeprom.ops.read(hw, last_word, + &eeprom_buff[last_word - first_word]); + if (ret_val) + goto err; + } + + /* Device's eeprom is always little-endian, word addressable */ + for (i = 0; i < last_word - first_word + 1; i++) + le16_to_cpus(&eeprom_buff[i]); + + memcpy(ptr, bytes, eeprom->len); + + for (i = 0; i < last_word - first_word + 1; i++) + cpu_to_le16s(&eeprom_buff[i]); + + ret_val = hw->eeprom.ops.write_buffer(hw, first_word, + last_word - first_word + 1, + eeprom_buff); + + /* Update the checksum */ + if (ret_val == 0) + hw->eeprom.ops.update_checksum(hw); + +err: + kfree(eeprom_buff); + return ret_val; +} + static void ixgbe_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) { struct ixgbe_adapter *adapter = netdev_priv(netdev); char firmware_version[32]; + u32 nvm_track_id; strncpy(drvinfo->driver, ixgbe_driver_name, sizeof(drvinfo->driver) - 1); strncpy(drvinfo->version, ixgbe_driver_version, sizeof(drvinfo->version) - 1); - snprintf(firmware_version, sizeof(firmware_version), "%d.%d-%d", - (adapter->eeprom_version & 0xF000) >> 12, - (adapter->eeprom_version & 0x0FF0) >> 4, - adapter->eeprom_version & 0x000F); + nvm_track_id = (adapter->eeprom_verh << 16) | + adapter->eeprom_verl; + snprintf(firmware_version, sizeof(firmware_version), "0x%08x", + nvm_track_id); strncpy(drvinfo->fw_version, firmware_version, - sizeof(drvinfo->fw_version)); + sizeof(drvinfo->fw_version) - 1); strncpy(drvinfo->bus_info, pci_name(adapter->pdev), - sizeof(drvinfo->bus_info)); + sizeof(drvinfo->bus_info) - 1); drvinfo->n_stats = IXGBE_STATS_LEN; drvinfo->testinfo_len = IXGBE_TEST_LEN; drvinfo->regdump_len = ixgbe_get_regs_len(netdev); @@ -2524,6 +2595,7 @@ static const struct ethtool_ops ixgbe_ethtool_ops = { .get_link = ethtool_op_get_link, .get_eeprom_len = ixgbe_get_eeprom_len, .get_eeprom = ixgbe_get_eeprom, + .set_eeprom = ixgbe_set_eeprom, .get_ringparam = ixgbe_get_ringparam, .set_ringparam = ixgbe_set_ringparam, .get_pauseparam = ixgbe_get_pauseparam, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index fb7d8842a362..8075d11b4cde 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -7640,6 +7640,10 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, } device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); + /* save off EEPROM version number */ + hw->eeprom.ops.read(hw, 0x2e, &adapter->eeprom_verh); + hw->eeprom.ops.read(hw, 0x2d, &adapter->eeprom_verl); + /* pick up the PCI bus settings for reporting later */ hw->mac.ops.get_bus_info(hw); @@ -7672,9 +7676,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, "is required.\n"); } - /* save off EEPROM version number */ - hw->eeprom.ops.read(hw, 0x29, &adapter->eeprom_version); - /* reset the hardware with the new settings */ err = hw->mac.ops.start_hw(hw); |