Commit 908a658e authored by Jeb J. Cramer's avatar Jeb J. Cramer Committed by Jeff Garzik

[E1000] Added 82541 & 82547 support

* Added support for 82541 and 82547 gigabit ethernet adapters
parent 5f3529cc
...@@ -1904,6 +1904,7 @@ config E1000 ...@@ -1904,6 +1904,7 @@ config E1000
82544 PRO/1000 XF Server Adapter A50484-xxx 82544 PRO/1000 XF Server Adapter A50484-xxx
82544 PRO/1000 T Desktop Adapter A62947-xxx 82544 PRO/1000 T Desktop Adapter A62947-xxx
82540 PRO/1000 MT Desktop Adapter A78408-xxx 82540 PRO/1000 MT Desktop Adapter A78408-xxx
82541 PRO/1000 MT Desktop Adapter C91016-xxx
82545 PRO/1000 MT Server Adapter A92165-xxx 82545 PRO/1000 MT Server Adapter A92165-xxx
82546 PRO/1000 MT Dual Port Server Adapter A92111-xxx 82546 PRO/1000 MT Dual Port Server Adapter A92111-xxx
82545 PRO/1000 MF Server Adapter A91622-xxx 82545 PRO/1000 MF Server Adapter A91622-xxx
......
...@@ -95,6 +95,15 @@ struct e1000_adapter; ...@@ -95,6 +95,15 @@ struct e1000_adapter;
#define E1000_RXBUFFER_8192 8192 #define E1000_RXBUFFER_8192 8192
#define E1000_RXBUFFER_16384 16384 #define E1000_RXBUFFER_16384 16384
/* SmartSpeed delimiters */
#define E1000_SMARTSPEED_DOWNSHIFT 3
#define E1000_SMARTSPEED_MAX 15
/* Packet Buffer allocations */
#define E1000_TX_FIFO_SIZE_SHIFT 0xA
#define E1000_TX_HEAD_ADDR_SHIFT 7
#define E1000_PBA_TX_MASK 0xFFFF0000
/* Flow Control High-Watermark: 43464 bytes */ /* Flow Control High-Watermark: 43464 bytes */
#define E1000_FC_HIGH_THRESH 0xA9C8 #define E1000_FC_HIGH_THRESH 0xA9C8
...@@ -109,9 +118,6 @@ struct e1000_adapter; ...@@ -109,9 +118,6 @@ struct e1000_adapter;
/* How many Rx Buffers do we bundle into one write to the hardware ? */ /* How many Rx Buffers do we bundle into one write to the hardware ? */
#define E1000_RX_BUFFER_WRITE 16 #define E1000_RX_BUFFER_WRITE 16
#define E1000_JUMBO_PBA 0x00000028
#define E1000_DEFAULT_PBA 0x00000030
#define AUTO_ALL_MODES 0 #define AUTO_ALL_MODES 0
#define E1000_EEPROM_APME 4 #define E1000_EEPROM_APME 4
...@@ -155,6 +161,7 @@ struct e1000_desc_ring { ...@@ -155,6 +161,7 @@ struct e1000_desc_ring {
/* board specific private data structure */ /* board specific private data structure */
struct e1000_adapter { struct e1000_adapter {
struct timer_list tx_fifo_stall_timer;
struct timer_list watchdog_timer; struct timer_list watchdog_timer;
struct timer_list phy_info_timer; struct timer_list phy_info_timer;
struct vlan_group *vlgrp; struct vlan_group *vlgrp;
...@@ -163,6 +170,7 @@ struct e1000_adapter { ...@@ -163,6 +170,7 @@ struct e1000_adapter {
uint32_t rx_buffer_len; uint32_t rx_buffer_len;
uint32_t part_num; uint32_t part_num;
uint32_t wol; uint32_t wol;
uint32_t smartspeed;
uint16_t link_speed; uint16_t link_speed;
uint16_t link_duplex; uint16_t link_duplex;
spinlock_t stats_lock; spinlock_t stats_lock;
...@@ -178,6 +186,10 @@ struct e1000_adapter { ...@@ -178,6 +186,10 @@ struct e1000_adapter {
uint32_t tx_int_delay; uint32_t tx_int_delay;
uint32_t tx_abs_int_delay; uint32_t tx_abs_int_delay;
int max_data_per_txd; int max_data_per_txd;
uint32_t tx_fifo_head;
uint32_t tx_head_addr;
uint32_t tx_fifo_size;
atomic_t tx_fifo_stall;
/* RX */ /* RX */
struct e1000_desc_ring rx_ring; struct e1000_desc_ring rx_ring;
......
...@@ -145,16 +145,6 @@ e1000_ethtool_sset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd) ...@@ -145,16 +145,6 @@ e1000_ethtool_sset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd)
return 0; return 0;
} }
static inline int
e1000_eeprom_size(struct e1000_hw *hw)
{
if((hw->mac_type > e1000_82544) &&
(E1000_READ_REG(hw, EECD) & E1000_EECD_SIZE))
return 512;
else
return 128;
}
static void static void
e1000_ethtool_gdrvinfo(struct e1000_adapter *adapter, e1000_ethtool_gdrvinfo(struct e1000_adapter *adapter,
struct ethtool_drvinfo *drvinfo) struct ethtool_drvinfo *drvinfo)
...@@ -166,7 +156,7 @@ e1000_ethtool_gdrvinfo(struct e1000_adapter *adapter, ...@@ -166,7 +156,7 @@ e1000_ethtool_gdrvinfo(struct e1000_adapter *adapter,
drvinfo->n_stats = E1000_STATS_LEN; drvinfo->n_stats = E1000_STATS_LEN;
#define E1000_REGS_LEN 32 #define E1000_REGS_LEN 32
drvinfo->regdump_len = E1000_REGS_LEN * sizeof(uint32_t); drvinfo->regdump_len = E1000_REGS_LEN * sizeof(uint32_t);
drvinfo->eedump_len = e1000_eeprom_size(&adapter->hw); drvinfo->eedump_len = adapter->hw.eeprom.word_size * 2;
} }
static void static void
...@@ -200,9 +190,8 @@ e1000_ethtool_geeprom(struct e1000_adapter *adapter, ...@@ -200,9 +190,8 @@ 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 max_len, first_word, last_word; int first_word, last_word;
int ret_val = 0; int ret_val = 0;
int i;
if(eeprom->len == 0) { if(eeprom->len == 0) {
ret_val = -EINVAL; ret_val = -EINVAL;
...@@ -211,22 +200,28 @@ e1000_ethtool_geeprom(struct e1000_adapter *adapter, ...@@ -211,22 +200,28 @@ e1000_ethtool_geeprom(struct e1000_adapter *adapter,
eeprom->magic = hw->vendor_id | (hw->device_id << 16); eeprom->magic = hw->vendor_id | (hw->device_id << 16);
max_len = e1000_eeprom_size(hw);
if(eeprom->offset > eeprom->offset + eeprom->len) { if(eeprom->offset > eeprom->offset + eeprom->len) {
ret_val = -EINVAL; ret_val = -EINVAL;
goto geeprom_error; goto geeprom_error;
} }
if((eeprom->offset + eeprom->len) > max_len) if((eeprom->offset + eeprom->len) > (hw->eeprom.word_size * 2))
eeprom->len = (max_len - eeprom->offset); eeprom->len = ((hw->eeprom.word_size * 2) - eeprom->offset);
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;
for(i = 0; i <= (last_word - first_word); i++) if(hw->eeprom.type == e1000_eeprom_spi)
e1000_read_eeprom(hw, first_word + i, &eeprom_buff[i]); ret_val = e1000_read_eeprom(hw, first_word,
last_word - first_word + 1,
eeprom_buff);
else {
uint16_t i;
for (i = 0; i < last_word - first_word + 1; i++)
if((ret_val = e1000_read_eeprom(hw, first_word + i, 1,
&eeprom_buff[i])))
break;
}
geeprom_error: geeprom_error:
return ret_val; return ret_val;
} }
...@@ -237,9 +232,8 @@ e1000_ethtool_seeprom(struct e1000_adapter *adapter, ...@@ -237,9 +232,8 @@ e1000_ethtool_seeprom(struct e1000_adapter *adapter,
{ {
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
uint16_t *eeprom_buff; uint16_t *eeprom_buff;
int max_len, first_word, last_word;
void *ptr; void *ptr;
int i; int max_len, first_word, last_word, ret_val = 0;
if(eeprom->len == 0) if(eeprom->len == 0)
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -247,7 +241,7 @@ e1000_ethtool_seeprom(struct e1000_adapter *adapter, ...@@ -247,7 +241,7 @@ e1000_ethtool_seeprom(struct e1000_adapter *adapter,
if(eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) if(eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
return -EFAULT; return -EFAULT;
max_len = e1000_eeprom_size(hw); max_len = hw->eeprom.word_size * 2;
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);
...@@ -263,30 +257,31 @@ e1000_ethtool_seeprom(struct e1000_adapter *adapter, ...@@ -263,30 +257,31 @@ e1000_ethtool_seeprom(struct e1000_adapter *adapter,
if(eeprom->offset & 1) { if(eeprom->offset & 1) {
/* need read/modify/write of first changed EEPROM word */ /* need read/modify/write of first changed EEPROM word */
/* only the second byte of the word is being modified */ /* only the second byte of the word is being modified */
e1000_read_eeprom(hw, first_word, &eeprom_buff[0]); ret_val = e1000_read_eeprom(hw, first_word, 1,
&eeprom_buff[0]);
ptr++; ptr++;
} }
if((eeprom->offset + eeprom->len) & 1) { if(((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) {
/* need read/modify/write of last changed EEPROM word */ /* need read/modify/write of last changed EEPROM word */
/* only the first byte of the word is being modified */ /* only the first byte of the word is being modified */
e1000_read_eeprom(hw, last_word, ret_val = e1000_read_eeprom(hw, last_word, 1,
&eeprom_buff[last_word - first_word]); &eeprom_buff[last_word - first_word]);
} }
if(copy_from_user(ptr, user_data, eeprom->len)) { if((ret_val != 0) || copy_from_user(ptr, user_data, eeprom->len)) {
kfree(eeprom_buff); ret_val = -EFAULT;
return -EFAULT; goto seeprom_error;
} }
for(i = 0; i <= (last_word - first_word); i++) ret_val = e1000_write_eeprom(hw, first_word,
e1000_write_eeprom(hw, first_word + i, eeprom_buff[i]); last_word - first_word + 1, eeprom_buff);
/* Update the checksum over the first part of the EEPROM if needed */ /* Update the checksum over the first part of the EEPROM if needed */
if(first_word <= EEPROM_CHECKSUM_REG) if((ret_val == 0) && first_word <= EEPROM_CHECKSUM_REG)
e1000_update_eeprom_checksum(hw); e1000_update_eeprom_checksum(hw);
seeprom_error:
kfree(eeprom_buff); kfree(eeprom_buff);
return ret_val;
return 0;
} }
static void static void
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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