Commit bfc417dc authored by Scott Feldman's avatar Scott Feldman Committed by David S. Miller

[netdrvr e1000] ethtool eeprom buffer dynamic allocation,

rather than large static allocation on the stack
parent 76e33674
...@@ -209,17 +209,23 @@ e1000_ethtool_geeprom(struct e1000_adapter *adapter, ...@@ -209,17 +209,23 @@ e1000_ethtool_geeprom(struct e1000_adapter *adapter,
struct ethtool_eeprom *eeprom, uint16_t *eeprom_buff) struct ethtool_eeprom *eeprom, uint16_t *eeprom_buff)
{ {
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
int i, max_len, first_word, last_word; int max_len, first_word, last_word;
int ret_val = 0;
int i;
if(eeprom->len == 0) if(eeprom->len == 0) {
return -EINVAL; ret_val = -EINVAL;
goto geeprom_error;
}
eeprom->magic = hw->vendor_id | (hw->device_id << 16); eeprom->magic = hw->vendor_id | (hw->device_id << 16);
max_len = e1000_eeprom_size(hw); max_len = e1000_eeprom_size(hw);
if(eeprom->offset > eeprom->offset + eeprom->len) if(eeprom->offset > eeprom->offset + eeprom->len) {
return -EINVAL; ret_val = -EINVAL;
goto geeprom_error;
}
if((eeprom->offset + eeprom->len) > max_len) if((eeprom->offset + eeprom->len) > max_len)
eeprom->len = (max_len - eeprom->offset); eeprom->len = (max_len - eeprom->offset);
...@@ -230,7 +236,8 @@ e1000_ethtool_geeprom(struct e1000_adapter *adapter, ...@@ -230,7 +236,8 @@ e1000_ethtool_geeprom(struct e1000_adapter *adapter,
for(i = 0; i <= (last_word - first_word); i++) for(i = 0; i <= (last_word - first_word); i++)
e1000_read_eeprom(hw, first_word + i, &eeprom_buff[i]); e1000_read_eeprom(hw, first_word + i, &eeprom_buff[i]);
return 0; geeprom_error:
return ret_val;
} }
static int static int
...@@ -238,9 +245,10 @@ e1000_ethtool_seeprom(struct e1000_adapter *adapter, ...@@ -238,9 +245,10 @@ e1000_ethtool_seeprom(struct e1000_adapter *adapter,
struct ethtool_eeprom *eeprom, void *user_data) struct ethtool_eeprom *eeprom, void *user_data)
{ {
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
uint16_t eeprom_buff[256]; uint16_t *eeprom_buff;
int i, max_len, first_word, last_word; int max_len, first_word, last_word;
void *ptr; void *ptr;
int i;
if(eeprom->len == 0) if(eeprom->len == 0)
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -255,6 +263,10 @@ e1000_ethtool_seeprom(struct e1000_adapter *adapter, ...@@ -255,6 +263,10 @@ e1000_ethtool_seeprom(struct e1000_adapter *adapter,
first_word = eeprom->offset >> 1; first_word = eeprom->offset >> 1;
last_word = (eeprom->offset + eeprom->len - 1) >> 1; last_word = (eeprom->offset + eeprom->len - 1) >> 1;
eeprom_buff = kmalloc(max_len, GFP_KERNEL);
if(eeprom_buff == NULL)
return -ENOMEM;
ptr = (void *)eeprom_buff; ptr = (void *)eeprom_buff;
if(eeprom->offset & 1) { if(eeprom->offset & 1) {
...@@ -269,8 +281,10 @@ e1000_ethtool_seeprom(struct e1000_adapter *adapter, ...@@ -269,8 +281,10 @@ e1000_ethtool_seeprom(struct e1000_adapter *adapter,
e1000_read_eeprom(hw, last_word, e1000_read_eeprom(hw, last_word,
&eeprom_buff[last_word - first_word]); &eeprom_buff[last_word - first_word]);
} }
if(copy_from_user(ptr, user_data, eeprom->len)) if(copy_from_user(ptr, user_data, eeprom->len)) {
kfree(eeprom_buff);
return -EFAULT; return -EFAULT;
}
for(i = 0; i <= (last_word - first_word); i++) for(i = 0; i <= (last_word - first_word); i++)
e1000_write_eeprom(hw, first_word + i, eeprom_buff[i]); e1000_write_eeprom(hw, first_word + i, eeprom_buff[i]);
...@@ -279,6 +293,8 @@ e1000_ethtool_seeprom(struct e1000_adapter *adapter, ...@@ -279,6 +293,8 @@ e1000_ethtool_seeprom(struct e1000_adapter *adapter,
if(first_word <= EEPROM_CHECKSUM_REG) if(first_word <= EEPROM_CHECKSUM_REG)
e1000_update_eeprom_checksum(hw); e1000_update_eeprom_checksum(hw);
kfree(eeprom_buff);
return 0; return 0;
} }
...@@ -493,26 +509,40 @@ e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr) ...@@ -493,26 +509,40 @@ e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr)
} }
case ETHTOOL_GEEPROM: { case ETHTOOL_GEEPROM: {
struct ethtool_eeprom eeprom = {ETHTOOL_GEEPROM}; struct ethtool_eeprom eeprom = {ETHTOOL_GEEPROM};
uint16_t eeprom_buff[256]; uint16_t *eeprom_buff;
void *ptr; void *ptr;
int err; int max_len, err = 0;
if(copy_from_user(&eeprom, addr, sizeof(eeprom))) max_len = e1000_eeprom_size(&adapter->hw);
return -EFAULT;
if((err = e1000_ethtool_geeprom(adapter, eeprom_buff = kmalloc(max_len, GFP_KERNEL);
&eeprom, eeprom_buff)))
return err;
if(copy_to_user(addr, &eeprom, sizeof(eeprom))) if(eeprom_buff == NULL)
return -EFAULT; return -ENOMEM;
if(copy_from_user(&eeprom, addr, sizeof(eeprom))) {
err = -EFAULT;
goto err_geeprom_ioctl;
}
if((err = e1000_ethtool_geeprom(adapter, &eeprom,
eeprom_buff)))
goto err_geeprom_ioctl;
if(copy_to_user(addr, &eeprom, sizeof(eeprom))) {
err = -EFAULT;
goto err_geeprom_ioctl;
}
addr += offsetof(struct ethtool_eeprom, data); addr += offsetof(struct ethtool_eeprom, data);
ptr = ((void *)eeprom_buff) + (eeprom.offset & 1); ptr = ((void *)eeprom_buff) + (eeprom.offset & 1);
if(copy_to_user(addr, ptr, eeprom.len)) if(copy_to_user(addr, ptr, eeprom.len))
return -EFAULT; err = -EFAULT;
return 0;
err_geeprom_ioctl:
kfree(eeprom_buff);
return err;
} }
case ETHTOOL_SEEPROM: { case ETHTOOL_SEEPROM: {
struct ethtool_eeprom eeprom; struct ethtool_eeprom eeprom;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment