static int e1000_set_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, uint8_t *bytes) { struct e1000_adapter *adapter = netdev->priv; struct e1000_hw *hw = &adapter->hw; uint16_t *eeprom_buff; void *ptr; int max_len, first_word, last_word, ret_val = 0; uint16_t i; if(eeprom->len == 0) return -EOPNOTSUPP; if(eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) return -EFAULT; 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 = (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 */ ret_val = e1000_read_eeprom(hw, first_word, 1, &eeprom_buff[0]); ptr++; } if(((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) { /* need read/modify/write of last changed EEPROM word */ /* only the first byte of the word is being modified */ ret_val = e1000_read_eeprom(hw, last_word, 1, &eeprom_buff[last_word - first_word]); } /* 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++) eeprom_buff[i] = cpu_to_le16(eeprom_buff[i]); ret_val = e1000_write_eeprom(hw, first_word, last_word - first_word + 1, eeprom_buff); /* Update the checksum over the first part of the EEPROM if needed */ if((ret_val == 0) && first_word <= EEPROM_CHECKSUM_REG) e1000_update_eeprom_checksum(hw); kfree(eeprom_buff); return ret_val; }
static int e1000_ethtool_seeprom(struct e1000_adapter *adapter, struct ethtool_eeprom *eeprom, void *user_data) { struct e1000_hw *hw = &adapter->hw; uint16_t *eeprom_buff; void *ptr; int max_len, first_word, last_word, ret_val = 0; if(eeprom->len == 0) return -EOPNOTSUPP; if(eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) return -EFAULT; max_len = hw->eeprom.word_size * 2; 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; eeprom_buff = kmalloc(max_len, GFP_KERNEL); if(!eeprom_buff) return -ENOMEM; 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 */ ret_val = e1000_read_eeprom(hw, first_word, 1, &eeprom_buff[0]); ptr++; } if(((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) { /* need read/modify/write of last changed EEPROM word */ /* only the first byte of the word is being modified */ ret_val = e1000_read_eeprom(hw, last_word, 1, &eeprom_buff[last_word - first_word]); } if((ret_val != 0) || copy_from_user(ptr, user_data, eeprom->len)) { ret_val = -EFAULT; goto seeprom_error; } ret_val = e1000_write_eeprom(hw, first_word, last_word - first_word + 1, eeprom_buff); /* Update the checksum over the first part of the EEPROM if needed */ if((ret_val == 0) && first_word <= EEPROM_CHECKSUM_REG) e1000_update_eeprom_checksum(hw); seeprom_error: kfree(eeprom_buff); return ret_val; }