summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-05-04 13:54:50 -0700
committerDavid S. Miller <davem@davemloft.net>2011-05-04 13:54:50 -0700
commit5a412ad7f4c95bb5b756aa12b52646e857e7c75d (patch)
treecff969a08da663077938e41bdeaa43855e00d4d9
parent301102cc832f9f3e24c5748705f152eaa7c307f6 (diff)
parent6716344c521bb585c1b89987c918d4b83b81adbe (diff)
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/jkirsher/net-next-2.6
-rw-r--r--drivers/net/e100.c2
-rw-r--r--drivers/net/igb/e1000_82575.c8
-rw-r--r--drivers/net/igbvf/ethtool.c6
-rw-r--r--drivers/net/ixgb/ixgb.h3
-rw-r--r--drivers/net/ixgb/ixgb_ethtool.c46
-rw-r--r--drivers/net/ixgbe/ixgbe_82598.c1
-rw-r--r--drivers/net/ixgbe/ixgbe_82599.c38
-rw-r--r--drivers/net/ixgbe/ixgbe_common.c440
-rw-r--r--drivers/net/ixgbe/ixgbe_common.h8
-rw-r--r--drivers/net/ixgbe/ixgbe_ethtool.c115
-rw-r--r--drivers/net/ixgbe/ixgbe_main.c7
-rw-r--r--drivers/net/ixgbe/ixgbe_phy.c10
-rw-r--r--drivers/net/ixgbe/ixgbe_type.h7
-rw-r--r--drivers/net/ixgbe/ixgbe_x540.c69
14 files changed, 559 insertions, 201 deletions
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index c810cda3bf1..29f812dc109 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -1512,7 +1512,7 @@ static int e100_phy_init(struct nic *nic)
static int e100_hw_init(struct nic *nic)
{
- int err;
+ int err = 0;
e100_hw_reset(nic);
diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c
index 0cd41c49bc1..0f563c8c5ff 100644
--- a/drivers/net/igb/e1000_82575.c
+++ b/drivers/net/igb/e1000_82575.c
@@ -244,6 +244,14 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
*/
size += NVM_WORD_SIZE_BASE_SHIFT;
+ /*
+ * Check for invalid size
+ */
+ if ((hw->mac.type == e1000_82576) && (size > 15)) {
+ printk("igb: The NVM size is not valid, "
+ "defaulting to 32K.\n");
+ size = 15;
+ }
nvm->word_size = 1 << size;
if (nvm->word_size == (1 << 15))
nvm->page_size = 128;
diff --git a/drivers/net/igbvf/ethtool.c b/drivers/net/igbvf/ethtool.c
index 112ae15b2d4..b0b14d63dfb 100644
--- a/drivers/net/igbvf/ethtool.c
+++ b/drivers/net/igbvf/ethtool.c
@@ -391,11 +391,6 @@ static int igbvf_set_wol(struct net_device *netdev,
return -EOPNOTSUPP;
}
-static int igbvf_phys_id(struct net_device *netdev, u32 data)
-{
- return 0;
-}
-
static int igbvf_get_coalesce(struct net_device *netdev,
struct ethtool_coalesce *ec)
{
@@ -527,7 +522,6 @@ static const struct ethtool_ops igbvf_ethtool_ops = {
.self_test = igbvf_diag_test,
.get_sset_count = igbvf_get_sset_count,
.get_strings = igbvf_get_strings,
- .phys_id = igbvf_phys_id,
.get_ethtool_stats = igbvf_get_ethtool_stats,
.get_coalesce = igbvf_get_coalesce,
.set_coalesce = igbvf_set_coalesce,
diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h
index 8f3df044e81..49e8408f05f 100644
--- a/drivers/net/ixgb/ixgb.h
+++ b/drivers/net/ixgb/ixgb.h
@@ -157,9 +157,6 @@ struct ixgb_adapter {
u16 link_duplex;
struct work_struct tx_timeout_task;
- struct timer_list blink_timer;
- unsigned long led_status;
-
/* TX */
struct ixgb_desc_ring tx_ring ____cacheline_aligned_in_smp;
unsigned int restart_queue;
diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c
index 5f224c387e0..6da890b9534 100644
--- a/drivers/net/ixgb/ixgb_ethtool.c
+++ b/drivers/net/ixgb/ixgb_ethtool.c
@@ -611,45 +611,23 @@ err_setup_rx:
return err;
}
-/* 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 0
-
-static 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 int
-ixgb_phys_id(struct net_device *netdev, u32 data)
+ixgb_set_phys_id(struct net_device *netdev, enum ethtool_phys_id_state state)
{
struct ixgb_adapter *adapter = netdev_priv(netdev);
- if (!data)
- data = INT_MAX;
-
- 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;
- }
+ switch (state) {
+ case ETHTOOL_ID_ACTIVE:
+ return 2;
- mod_timer(&adapter->blink_timer, jiffies);
+ case ETHTOOL_ID_ON:
+ ixgb_led_on(&adapter->hw);
+ break;
- msleep_interruptible(data * 1000);
- del_timer_sync(&adapter->blink_timer);
- ixgb_led_off(&adapter->hw);
- clear_bit(IXGB_LED_ON, &adapter->led_status);
+ case ETHTOOL_ID_OFF:
+ case ETHTOOL_ID_INACTIVE:
+ ixgb_led_off(&adapter->hw);
+ }
return 0;
}
@@ -767,7 +745,7 @@ static const struct ethtool_ops ixgb_ethtool_ops = {
.set_msglevel = ixgb_set_msglevel,
.set_tso = ixgb_set_tso,
.get_strings = ixgb_get_strings,
- .phys_id = ixgb_phys_id,
+ .set_phys_id = ixgb_set_phys_id,
.get_sset_count = ixgb_get_sset_count,
.get_ethtool_stats = ixgb_get_ethtool_stats,
.get_flags = ethtool_op_get_flags,
diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c
index 7a64f50435c..8179e5060a1 100644
--- a/drivers/net/ixgbe/ixgbe_82598.c
+++ b/drivers/net/ixgbe/ixgbe_82598.c
@@ -1281,6 +1281,7 @@ 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,
+ .read_buffer = &ixgbe_read_eerd_buffer_generic,
.calc_checksum = &ixgbe_calc_eeprom_checksum_generic,
.validate_checksum = &ixgbe_validate_eeprom_checksum_generic,
.update_checksum = &ixgbe_update_eeprom_checksum_generic,
diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c
index d1cda36507f..dba5ca6e35c 100644
--- a/drivers/net/ixgbe/ixgbe_82599.c
+++ b/drivers/net/ixgbe/ixgbe_82599.c
@@ -110,7 +110,6 @@ static s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
ret_val = ixgbe_get_sfp_init_sequence_offsets(hw, &list_offset,
&data_offset);
-
if (ret_val != 0)
goto setup_sfp_out;
@@ -130,7 +129,7 @@ static s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
}
/* Release the semaphore */
- ixgbe_release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
+ hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
/*
* Delay obtaining semaphore again to allow FW access,
* semaphore_delay is in ms usleep_range needs us.
@@ -2065,6 +2064,39 @@ out:
}
/**
+ * ixgbe_read_eeprom_buffer_82599 - Read EEPROM word(s) using
+ * fastest available method
+ *
+ * @hw: pointer to hardware structure
+ * @offset: offset of word in EEPROM to read
+ * @words: number of words
+ * @data: word(s) read from the EEPROM
+ *
+ * Retrieves 16 bit word(s) read from EEPROM
+ **/
+static s32 ixgbe_read_eeprom_buffer_82599(struct ixgbe_hw *hw, u16 offset,
+ u16 words, u16 *data)
+{
+ struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
+ s32 ret_val = IXGBE_ERR_CONFIG;
+
+ /*
+ * If EEPROM is detected and can be addressed using 14 bits,
+ * use EERD otherwise use bit bang
+ */
+ if ((eeprom->type == ixgbe_eeprom_spi) &&
+ (offset + (words - 1) <= IXGBE_EERD_MAX_ADDR))
+ ret_val = ixgbe_read_eerd_buffer_generic(hw, offset, words,
+ data);
+ else
+ ret_val = ixgbe_read_eeprom_buffer_bit_bang_generic(hw, offset,
+ words,
+ data);
+
+ return ret_val;
+}
+
+/**
* ixgbe_read_eeprom_82599 - Read EEPROM word using
* fastest available method
*
@@ -2140,7 +2172,9 @@ static struct ixgbe_mac_operations mac_ops_82599 = {
static struct ixgbe_eeprom_operations eeprom_ops_82599 = {
.init_params = &ixgbe_init_eeprom_params_generic,
.read = &ixgbe_read_eeprom_82599,
+ .read_buffer = &ixgbe_read_eeprom_buffer_82599,
.write = &ixgbe_write_eeprom_generic,
+ .write_buffer = &ixgbe_write_eeprom_buffer_bit_bang_generic,
.calc_checksum = &ixgbe_calc_eeprom_checksum_generic,
.validate_checksum = &ixgbe_validate_eeprom_checksum_generic,
.update_checksum = &ixgbe_update_eeprom_checksum_generic,
diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c
index cb2e8e18dd3..c4730cd39b2 100644
--- a/drivers/net/ixgbe/ixgbe_common.c
+++ b/drivers/net/ixgbe/ixgbe_common.c
@@ -55,6 +55,12 @@ static s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm);
static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num);
static s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg);
+static s32 ixgbe_read_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset,
+ u16 words, u16 *data);
+static s32 ixgbe_write_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset,
+ u16 words, u16 *data);
+static s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw,
+ u16 offset);
/**
* ixgbe_start_hw_generic - Prepare hardware for Tx/Rx
@@ -585,6 +591,8 @@ s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw)
/* Set default semaphore delay to 10ms which is a well
* tested value */
eeprom->semaphore_delay = 10;
+ /* Clear EEPROM page size, it will be initialized as needed */
+ eeprom->word_page_size = 0;
/*
* Check for EEPROM present first.
@@ -617,26 +625,78 @@ s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw)
}
/**
- * ixgbe_write_eeprom_generic - Writes 16 bit value to EEPROM
+ * ixgbe_write_eeprom_buffer_bit_bang_generic - Write EEPROM using bit-bang
* @hw: pointer to hardware structure
- * @offset: offset within the EEPROM to be written to
- * @data: 16 bit word to be written to the EEPROM
+ * @offset: offset within the EEPROM to write
+ * @words: number of words
+ * @data: 16 bit word(s) to write to EEPROM
*
- * If ixgbe_eeprom_update_checksum is not called after this function, the
- * EEPROM will most likely contain an invalid checksum.
+ * Reads 16 bit word(s) from EEPROM through bit-bang method
**/
-s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data)
+s32 ixgbe_write_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
+ u16 words, u16 *data)
{
- s32 status;
- u8 write_opcode = IXGBE_EEPROM_WRITE_OPCODE_SPI;
+ s32 status = 0;
+ u16 i, count;
hw->eeprom.ops.init_params(hw);
- if (offset >= hw->eeprom.word_size) {
+ if (words == 0) {
+ status = IXGBE_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
+
+ if (offset + words > hw->eeprom.word_size) {
status = IXGBE_ERR_EEPROM;
goto out;
}
+ /*
+ * The EEPROM page size cannot be queried from the chip. We do lazy
+ * initialization. It is worth to do that when we write large buffer.
+ */
+ if ((hw->eeprom.word_page_size == 0) &&
+ (words > IXGBE_EEPROM_PAGE_SIZE_MAX))
+ ixgbe_detect_eeprom_page_size_generic(hw, offset);
+
+ /*
+ * We cannot hold synchronization semaphores for too long
+ * to avoid other entity starvation. However it is more efficient
+ * to read in bursts than synchronizing access for each word.
+ */
+ for (i = 0; i < words; i += IXGBE_EEPROM_RD_BUFFER_MAX_COUNT) {
+ count = (words - i) / IXGBE_EEPROM_RD_BUFFER_MAX_COUNT > 0 ?
+ IXGBE_EEPROM_RD_BUFFER_MAX_COUNT : (words - i);
+ status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset + i,
+ count, &data[i]);
+
+ if (status != 0)
+ break;
+ }
+
+out:
+ return status;
+}
+
+/**
+ * ixgbe_write_eeprom_buffer_bit_bang - Writes 16 bit word(s) to EEPROM
+ * @hw: pointer to hardware structure
+ * @offset: offset within the EEPROM to be written to
+ * @words: number of word(s)
+ * @data: 16 bit word(s) to be written to the EEPROM
+ *
+ * If ixgbe_eeprom_update_checksum is not called after this function, the
+ * EEPROM will most likely contain an invalid checksum.
+ **/
+static s32 ixgbe_write_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset,
+ u16 words, u16 *data)
+{
+ s32 status;
+ u16 word;
+ u16 page_size;
+ u16 i;
+ u8 write_opcode = IXGBE_EEPROM_WRITE_OPCODE_SPI;
+
/* Prepare the EEPROM for writing */
status = ixgbe_acquire_eeprom(hw);
@@ -648,62 +708,147 @@ s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data)
}
if (status == 0) {
- ixgbe_standby_eeprom(hw);
+ for (i = 0; i < words; i++) {
+ ixgbe_standby_eeprom(hw);
- /* Send the WRITE ENABLE command (8 bit opcode ) */
- ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_WREN_OPCODE_SPI,
- IXGBE_EEPROM_OPCODE_BITS);
+ /* Send the WRITE ENABLE command (8 bit opcode ) */
+ ixgbe_shift_out_eeprom_bits(hw,
+ IXGBE_EEPROM_WREN_OPCODE_SPI,
+ IXGBE_EEPROM_OPCODE_BITS);
- ixgbe_standby_eeprom(hw);
+ ixgbe_standby_eeprom(hw);
- /*
- * Some SPI eeproms use the 8th address bit embedded in the
- * opcode
- */
- if ((hw->eeprom.address_bits == 8) && (offset >= 128))
- write_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI;
+ /*
+ * Some SPI eeproms use the 8th address bit embedded
+ * in the opcode
+ */
+ if ((hw->eeprom.address_bits == 8) &&
+ ((offset + i) >= 128))
+ write_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI;
+
+ /* Send the Write command (8-bit opcode + addr) */
+ ixgbe_shift_out_eeprom_bits(hw, write_opcode,
+ IXGBE_EEPROM_OPCODE_BITS);
+ ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2),
+ hw->eeprom.address_bits);
+
+ page_size = hw->eeprom.word_page_size;
+
+ /* Send the data in burst via SPI*/
+ do {
+ word = data[i];
+ word = (word >> 8) | (word << 8);
+ ixgbe_shift_out_eeprom_bits(hw, word, 16);
+
+ if (page_size == 0)
+ break;
+
+ /* do not wrap around page */
+ if (((offset + i) & (page_size - 1)) ==
+ (page_size - 1))
+ break;
+ } while (++i < words);
+
+ ixgbe_standby_eeprom(hw);
+ usleep_range(10000, 20000);
+ }
+ /* Done with writing - release the EEPROM */
+ ixgbe_release_eeprom(hw);
+ }
- /* Send the Write command (8-bit opcode + addr) */
- ixgbe_shift_out_eeprom_bits(hw, write_opcode,
- IXGBE_EEPROM_OPCODE_BITS);
- ixgbe_shift_out_eeprom_bits(hw, (u16)(offset*2),
- hw->eeprom.address_bits);
+ return status;
+}
- /* Send the data */
- data = (data >> 8) | (data << 8);
- ixgbe_shift_out_eeprom_bits(hw, data, 16);
- ixgbe_standby_eeprom(hw);
+/**
+ * ixgbe_write_eeprom_generic - Writes 16 bit value to EEPROM
+ * @hw: pointer to hardware structure
+ * @offset: offset within the EEPROM to be written to
+ * @data: 16 bit word to be written to the EEPROM
+ *
+ * If ixgbe_eeprom_update_checksum is not called after this function, the
+ * EEPROM will most likely contain an invalid checksum.
+ **/
+s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data)
+{
+ s32 status;
- /* Done with writing - release the EEPROM */
- ixgbe_release_eeprom(hw);
+ hw->eeprom.ops.init_params(hw);
+
+ if (offset >= hw->eeprom.word_size) {
+ status = IXGBE_ERR_EEPROM;
+ goto out;
}
+ status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset, 1, &data);
+
out:
return status;
}
/**
- * ixgbe_read_eeprom_bit_bang_generic - Read EEPROM word using bit-bang
+ * ixgbe_read_eeprom_buffer_bit_bang_generic - Read EEPROM using bit-bang
* @hw: pointer to hardware structure
* @offset: offset within the EEPROM to be read
- * @data: read 16 bit value from EEPROM
+ * @words: number of word(s)
+ * @data: read 16 bit words(s) from EEPROM
*
- * Reads 16 bit value from EEPROM through bit-bang method
+ * Reads 16 bit word(s) from EEPROM through bit-bang method
**/
-s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
- u16 *data)
+s32 ixgbe_read_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
+ u16 words, u16 *data)
{
- s32 status;
- u16 word_in;
- u8 read_opcode = IXGBE_EEPROM_READ_OPCODE_SPI;
+ s32 status = 0;
+ u16 i, count;
hw->eeprom.ops.init_params(hw);
- if (offset >= hw->eeprom.word_size) {
+ if (words == 0) {
+ status = IXGBE_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
+
+ if (offset + words > hw->eeprom.word_size) {
status = IXGBE_ERR_EEPROM;
goto out;
}
+ /*
+ * We cannot hold synchronization semaphores for too long
+ * to avoid other entity starvation. However it is more efficient
+ * to read in bursts than synchronizing access for each word.
+ */
+ for (i = 0; i < words; i += IXGBE_EEPROM_RD_BUFFER_MAX_COUNT) {
+ count = (words - i) / IXGBE_EEPROM_RD_BUFFER_MAX_COUNT > 0 ?
+ IXGBE_EEPROM_RD_BUFFER_MAX_COUNT : (words - i);
+
+ status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset + i,
+ count, &data[i]);
+
+ if (status != 0)
+ break;
+ }
+
+out:
+ return status;
+}
+
+/**
+ * ixgbe_read_eeprom_buffer_bit_bang - Read EEPROM using bit-bang
+ * @hw: pointer to hardware structure
+ * @offset: offset within the EEPROM to be read
+ * @words: number of word(s)
+ * @data: read 16 bit word(s) from EEPROM
+ *
+ * Reads 16 bit word(s) from EEPROM through bit-bang method
+ **/
+static s32 ixgbe_read_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset,
+ u16 words, u16 *data)
+{
+ s32 status;
+ u16 word_in;
+ u8 read_opcode = IXGBE_EEPROM_READ_OPCODE_SPI;
+ u16 i;
+
/* Prepare the EEPROM for reading */
status = ixgbe_acquire_eeprom(hw);
@@ -715,104 +860,208 @@ s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
}
if (status == 0) {
- ixgbe_standby_eeprom(hw);
+ for (i = 0; i < words; i++) {
+ ixgbe_standby_eeprom(hw);
+ /*
+ * Some SPI eeproms use the 8th address bit embedded
+ * in the opcode
+ */
+ if ((hw->eeprom.address_bits == 8) &&
+ ((offset + i) >= 128))
+ read_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI;
+
+ /* Send the READ command (opcode + addr) */
+ ixgbe_shift_out_eeprom_bits(hw, read_opcode,
+ IXGBE_EEPROM_OPCODE_BITS);
+ ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2),
+ hw->eeprom.address_bits);
+
+ /* Read the data. */
+ word_in = ixgbe_shift_in_eeprom_bits(hw, 16);
+ data[i] = (word_in >> 8) | (word_in << 8);
+ }
- /*
- * Some SPI eeproms use the 8th address bit embedded in the
- * opcode
- */
- if ((hw->eeprom.address_bits == 8) && (offset >= 128))
- read_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI;
+ /* End this read operation */
+ ixgbe_release_eeprom(hw);
+ }
- /* Send the READ command (opcode + addr) */
- ixgbe_shift_out_eeprom_bits(hw, read_opcode,
- IXGBE_EEPROM_OPCODE_BITS);
- ixgbe_shift_out_eeprom_bits(hw, (u16)(offset*2),
- hw->eeprom.address_bits);
+ return status;
+}
- /* Read the data. */
- word_in = ixgbe_shift_in_eeprom_bits(hw, 16);
- *data = (word_in >> 8) | (word_in << 8);
+/**
+ * ixgbe_read_eeprom_bit_bang_generic - Read EEPROM word using bit-bang
+ * @hw: pointer to hardware structure
+ * @offset: offset within the EEPROM to be read
+ * @data: read 16 bit value from EEPROM
+ *
+ * Reads 16 bit value from EEPROM through bit-bang method
+ **/
+s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
+ u16 *data)
+{
+ s32 status;
- /* End this read operation */
- ixgbe_release_eeprom(hw);
+ hw->eeprom.ops.init_params(hw);
+
+ if (offset >= hw->eeprom.word_size) {
+ status = IXGBE_ERR_EEPROM;
+ goto out;
}
+ status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data);
+
out:
return status;
}
/**
- * ixgbe_read_eerd_generic - Read EEPROM word using EERD
+ * ixgbe_read_eerd_buffer_generic - Read EEPROM word(s) using EERD
* @hw: pointer to hardware structure
- * @offset: offset of word in the EEPROM to read
- * @data: word read from the EEPROM
+ * @offset: offset of word in the EEPROM to read
+ * @words: number of word(s)
+ * @data: 16 bit word(s) from the EEPROM
*
- * Reads a 16 bit word from the EEPROM using the EERD register.
+ * Reads a 16 bit word(s) from the EEPROM using the EERD register.
**/
-s32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data)
+s32 ixgbe_read_eerd_buffer_generic(struct ixgbe_hw *hw, u16 offset,
+ u16 words, u16 *data)
{
u32 eerd;
- s32 status;
+ s32 status = 0;
+ u32 i;
hw->eeprom.ops.init_params(hw);
+ if (words == 0) {
+ status = IXGBE_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
+
if (offset >= hw->eeprom.word_size) {
status = IXGBE_ERR_EEPROM;
goto out;
}
- eerd = (offset << IXGBE_EEPROM_RW_ADDR_SHIFT) +
- IXGBE_EEPROM_RW_REG_START;
+ for (i = 0; i < words; i++) {
+ eerd = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) +
+ IXGBE_EEPROM_RW_REG_START;
- IXGBE_WRITE_REG(hw, IXGBE_EERD, eerd);
- status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_READ);
+ IXGBE_WRITE_REG(hw, IXGBE_EERD, eerd);
+ status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_READ);
- if (status == 0)
- *data = (IXGBE_READ_REG(hw, IXGBE_EERD) >>
- IXGBE_EEPROM_RW_REG_DATA);
- else
- hw_dbg(hw, "Eeprom read timed out\n");
+ if (status == 0) {
+ data[i] = (IXGBE_READ_REG(hw, IXGBE_EERD) >>
+ IXGBE_EEPROM_RW_REG_DATA);
+ } else {
+ hw_dbg(hw, "Eeprom read timed out\n");
+ goto out;
+ }
+ }
+out:
+ return status;
+}
+/**
+ * ixgbe_detect_eeprom_page_size_generic - Detect EEPROM page size
+ * @hw: pointer to hardware structure
+ * @offset: offset within the EEPROM to be used as a scratch pad
+ *
+ * Discover EEPROM page size by writing marching data at given offset.
+ * This function is called only when we are writing a new large buffer
+ * at given offset so the data would be overwritten anyway.
+ **/
+static s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw,
+ u16 offset)
+{
+ u16 data[IXGBE_EEPROM_PAGE_SIZE_MAX];
+ s32 status = 0;
+ u16 i;
+
+ for (i = 0; i < IXGBE_EEPROM_PAGE_SIZE_MAX; i++)
+ data[i] = i;
+
+ hw->eeprom.word_page_size = IXGBE_EEPROM_PAGE_SIZE_MAX;
+ status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset,
+ IXGBE_EEPROM_PAGE_SIZE_MAX, data);
+ hw->eeprom.word_page_size = 0;
+ if (status != 0)
+ goto out;
+
+ status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data);
+ if (status != 0)
+ goto out;
+
+ /*
+ * When writing in burst more than the actual page size
+ * EEPROM address wraps around current page.
+ */
+ hw->eeprom.word_page_size = IXGBE_EEPROM_PAGE_SIZE_MAX - data[0];
+
+ hw_dbg(hw, "Detected EEPROM page size = %d words.",
+ hw->eeprom.word_page_size);
out:
return status;
}
/**
- * ixgbe_write_eewr_generic - Write EEPROM word using EEWR
+ * ixgbe_read_eerd_generic - Read EEPROM word using EERD
+ * @hw: pointer to hardware structure
+ * @offset: offset of word in the EEPROM to read
+ * @data: word read from the EEPROM
+ *
+ * Reads a 16 bit word from the EEPROM using the EERD register.
+ **/
+s32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data)
+{
+ return ixgbe_read_eerd_buffer_generic(hw, offset, 1, data);
+}
+
+/**
+ * ixgbe_write_eewr_buffer_generic - Write EEPROM word(s) using EEWR
* @hw: pointer to hardware structure
* @offset: offset of word in the EEPROM to write
- * @data: word write to the EEPROM
+ * @words: number of words
+ * @data: word(s) write to the EEPROM
*
- * Write a 16 bit word to the EEPROM using the EEWR register.
+ * Write a 16 bit word(s) to the EEPROM using the EEWR register.
**/
-s32 ixgbe_write_eewr_generic(struct ixgbe_hw *hw, u16 offset, u16 data)
+s32 ixgbe_write_eewr_buffer_generic(struct ixgbe_hw *hw, u16 offset,
+ u16 words, u16 *data)
{
u32 eewr;
- s32 status;
+ s32 status = 0;
+ u16 i;
hw->eeprom.ops.init_params(hw);
+ if (words == 0) {
+ status = IXGBE_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
+
if (offset >= hw->eeprom.word_size) {
status = IXGBE_ERR_EEPROM;
goto out;
}
- eewr = (offset << IXGBE_EEPROM_RW_ADDR_SHIFT) |
- (data << IXGBE_EEPROM_RW_REG_DATA) | IXGBE_EEPROM_RW_REG_START;
+ for (i = 0; i < words; i++) {
+ eewr = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) |
+ (data[i] << IXGBE_EEPROM_RW_REG_DATA) |
+ IXGBE_EEPROM_RW_REG_START;
- status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE);
- if (status != 0) {
- hw_dbg(hw, "Eeprom write EEWR timed out\n");
- goto out;
- }
+ status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE);
+ if (status != 0) {
+ hw_dbg(hw, "Eeprom write EEWR timed out\n");
+ goto out;
+ }
- IXGBE_WRITE_REG(hw, IXGBE_EEWR, eewr);
+ IXGBE_WRITE_REG(hw, IXGBE_EEWR, eewr);
- status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE);
- if (status != 0) {
- hw_dbg(hw, "Eeprom write EEWR timed out\n");
- goto out;
+ status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE);
+ if (status != 0) {
+ hw_dbg(hw, "Eeprom write EEWR timed out\n");
+ goto out;
+ }
}
out:
@@ -820,6 +1069,19 @@ out:
}
/**
+ * ixgbe_write_eewr_generic - Write EEPROM word using EEWR
+ * @hw: pointer to hardware structure
+ * @offset: offset of word in the EEPROM to write
+ * @data: word write to the EEPROM
+ *
+ * Write a 16 bit word to the EEPROM using the EEWR register.
+ **/
+s32 ixgbe_write_eewr_generic(struct ixgbe_hw *hw, u16 offset, u16 data)
+{
+ return ixgbe_write_eewr_buffer_generic(hw, offset, 1, &data);
+}
+
+/**
* ixgbe_poll_eerd_eewr_done - Poll EERD read or EEWR write status
* @hw: pointer to hardware structure
* @ee_reg: EEPROM flag for polling
diff --git a/drivers/net/ixgbe/ixgbe_common.h b/drivers/net/ixgbe/ixgbe_common.h
index e850adbb32a..46be83cfb50 100644
--- a/drivers/net/ixgbe/ixgbe_common.h
+++ b/drivers/net/ixgbe/ixgbe_common.h
@@ -49,10 +49,18 @@ s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index);
s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw);
s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data);
+s32 ixgbe_write_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
+ u16 words, u16 *data);
s32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data);
+s32 ixgbe_read_eerd_buffer_generic(struct ixgbe_hw *hw, u16 offset,
+ u16 words, u16 *data);
s32 ixgbe_write_eewr_generic(struct ixgbe_hw *hw, u16 offset, u16 data);
+s32 ixgbe_write_eewr_buffer_generic(struct ixgbe_hw *hw, u16 offset,
+ u16 words, u16 *data);
s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
u16 *data);
+s32 ixgbe_read_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
+ u16 words, u16 *data);
u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw);
s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw,
u16 *checksum_val);
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index bcba057b510..f2efa324535 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -847,11 +847,8 @@ static int ixgbe_get_eeprom(struct net_device *netdev,
if (!eeprom_buff)
return -ENOMEM;
- for (i = 0; i < eeprom_len; i++) {
- if ((ret_val = hw->eeprom.ops.read(hw, first_word + i,
- &eeprom_buff[i])))
- break;
- }
+ ret_val = hw->eeprom.ops.read_buffer(hw, first_word, eeprom_len,
+ eeprom_buff);
/* Device's eeprom is always little-endian, word addressable */
for (i = 0; i < eeprom_len; i++)
@@ -1236,46 +1233,62 @@ static const struct ixgbe_reg_test reg_test_82598[] = {
{ 0, 0, 0, 0 }
};
-static const u32 register_test_patterns[] = {
- 0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF
-};
-
-#define REG_PATTERN_TEST(R, M, W) \
-{ \
- u32 pat, val, before; \
- for (pat = 0; pat < ARRAY_SIZE(register_test_patterns); pat++) { \
- before = readl(adapter->hw.hw_addr + R); \
- writel((register_test_patterns[pat] & W), \
- (adapter->hw.hw_addr + R)); \
- val = readl(adapter->hw.hw_addr + R); \
- if (val != (register_test_patterns[pat] & W & M)) { \
- e_err(drv, "pattern test reg %04X failed: got " \
- "0x%08X expected 0x%08X\n", \
- R, val, (register_test_patterns[pat] & W & M)); \
- *data = R; \
- writel(before, adapter->hw.hw_addr + R); \
- return 1; \
- } \
- writel(before, adapter->hw.hw_addr + R); \
- } \
+static bool reg_pattern_test(struct ixgbe_adapter *adapter, u64 *data, int reg,
+ u32 mask, u32 write)
+{
+ u32 pat, val, before;
+ static const u32 test_pattern[] = {
+ 0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};
+
+ for (pat = 0; pat < ARRAY_SIZE(test_pattern); pat++) {
+ before = readl(adapter->hw.hw_addr + reg);
+ writel((test_pattern[pat] & write),
+ (adapter->hw.hw_addr + reg));
+ val = readl(adapter->hw.hw_addr + reg);
+ if (val != (test_pattern[pat] & write & mask)) {
+ e_err(drv, "pattern test reg %04X failed: got "
+ "0x%08X expected 0x%08X\n",
+ reg, val, (test_pattern[pat] & write & mask));
+ *data = reg;
+ writel(before, adapter->hw.hw_addr + reg);
+ return 1;
+ }
+ writel(before, adapter->hw.hw_addr + reg);
+ }
+ return 0;
}
-#define REG_SET_AND_CHECK(R, M, W) \
-{ \
- u32 val, before; \
- before = readl(adapter->hw.hw_addr + R); \
- writel((W & M), (adapter->hw.hw_addr + R)); \
- val = readl(adapter->hw.hw_addr + R); \
- if ((W & M) != (val & M)) { \
- e_err(drv, "set/check reg %04X test failed: got 0x%08X " \
- "expected 0x%08X\n", R, (val & M), (W & M)); \
- *data = R; \
- writel(before, (adapter->hw.hw_addr + R)); \
- return 1; \
- } \
- writel(before, (adapter->hw.hw_addr + R)); \
+static bool reg_set_and_check(struct ixgbe_adapter *adapter, u64 *data, int reg,
+ u32 mask, u32 write)
+{
+ u32 val, before;
+ before = readl(adapter->hw.hw_addr + reg);
+ writel((write & mask), (adapter->hw.hw_addr + reg));
+ val = readl(adapter->hw.hw_addr + reg);
+ if ((write & mask) != (val & mask)) {
+ e_err(drv, "set/check reg %04X test failed: got 0x%08X "
+ "expected 0x%08X\n", reg, (val & mask), (write & mask));
+ *data = reg;
+ writel(before, (adapter->hw.hw_addr + reg));
+ return 1;
+ }
+ writel(before, (adapter->hw.hw_addr + reg));
+ return 0;
}
+#define REG_PATTERN_TEST(reg, mask, write) \
+ do { \
+ if (reg_pattern_test(adapter, data, reg, mask, write)) \
+ return 1; \
+ } while (0) \
+
+
+#define REG_SET_AND_CHECK(reg, mask, write) \
+ do { \
+ if (reg_set_and_check(adapter, data, reg, mask, write)) \
+ return 1; \
+ } while (0) \
+
static int ixgbe_reg_test(struct ixgbe_adapter *adapter, u64 *data)
{
const struct ixgbe_reg_test *test;
@@ -1326,13 +1339,13 @@ static int ixgbe_reg_test(struct ixgbe_adapter *adapter, u64 *data)
switch (test->test_type) {
case PATTERN_TEST:
REG_PATTERN_TEST(test->reg + (i * 0x40),
- test->mask,
- test->write);
+ test->mask,
+ test->write);
break;
case SET_READ_TEST:
REG_SET_AND_CHECK(test->reg + (i * 0x40),
- test->mask,
- test->write);
+ test->mask,
+ test->write);
break;
case WRITE_NO_TEST:
writel(test->write,
@@ -1341,18 +1354,18 @@ static int ixgbe_reg_test(struct ixgbe_adapter *adapter, u64 *data)
break;
case TABLE32_TEST:
REG_PATTERN_TEST(test->reg + (i * 4),
- test->mask,
- test->write);
+ test->mask,
+ test->write);
break;
case TABLE64_TEST_LO:
REG_PATTERN_TEST(test->reg + (i * 8),
- test->mask,
- test->write);
+ test->mask,
+ test->write);
break;
case TABLE64_TEST_HI:
REG_PATTERN_TEST((test->reg + 4) + (i * 8),
- test->mask,
- test->write);
+ test->mask,
+ test->write);
break;
}
}
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 9160811c6d7..eebb1921c66 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -3862,9 +3862,10 @@ static void ixgbe_setup_gpie(struct ixgbe_adapter *adapter)
if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE)
gpie |= IXGBE_SDP1_GPIEN;
- if (hw->mac.type == ixgbe_mac_82599EB)
+ if (hw->mac.type == ixgbe_mac_82599EB) {
gpie |= IXGBE_SDP1_GPIEN;
gpie |= IXGBE_SDP2_GPIEN;
+ }
IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
}
@@ -7468,8 +7469,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
/* print bus type/speed/width info */
e_dev_info("(PCI Express:%s:%s) %pM\n",
- (hw->bus.speed == ixgbe_bus_speed_5000 ? "5.0Gb/s" :
- hw->bus.speed == ixgbe_bus_speed_2500 ? "2.5Gb/s" :
+ (hw->bus.speed == ixgbe_bus_speed_5000 ? "5.0GT/s" :
+ hw->bus.speed == ixgbe_bus_speed_2500 ? "2.5GT/s" :
"Unknown"),
(hw->bus.width == ixgbe_bus_width_pcie_x8 ? "Width x8" :
hw->bus.width == ixgbe_bus_width_pcie_x4 ? "Width x4" :
diff --git a/drivers/net/ixgbe/ixgbe_phy.c b/drivers/net/ixgbe/ixgbe_phy.c
index edcaaebd72b..735f686c3b3 100644
--- a/drivers/net/ixgbe/ixgbe_phy.c
+++ b/drivers/net/ixgbe/ixgbe_phy.c
@@ -1222,7 +1222,7 @@ s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
swfw_mask = IXGBE_GSSR_PHY0_SM;
do {
- if (ixgbe_acquire_swfw_sync(hw, swfw_mask) != 0) {
+ if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) != 0) {
status = IXGBE_ERR_SWFW_SYNC;
goto read_byte_out;
}
@@ -1269,7 +1269,7 @@ s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
break;
fail:
- ixgbe_release_swfw_sync(hw, swfw_mask);
+ hw->mac.ops.release_swfw_sync(hw, swfw_mask);
msleep(100);
ixgbe_i2c_bus_clear(hw);
retry++;
@@ -1280,7 +1280,7 @@ fail:
} while (retry < max_retry);
- ixgbe_release_swfw_sync(hw, swfw_mask);
+ hw->mac.ops.release_swfw_sync(hw, swfw_mask);
read_byte_out:
return status;
@@ -1308,7 +1308,7 @@ s32 ixgbe_write_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
else
swfw_mask = IXGBE_GSSR_PHY0_SM;
- if (ixgbe_acquire_swfw_sync(hw, swfw_mask) != 0) {
+ if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) != 0) {
status = IXGBE_ERR_SWFW_SYNC;
goto write_byte_out;
}
@@ -1352,7 +1352,7 @@ fail:
hw_dbg(hw, "I2C byte write error.\n");
} while (retry < max_retry);
- ixgbe_release_swfw_sync(hw, swfw_mask);
+ hw->mac.ops.release_swfw_sync(hw, swfw_mask);
write_byte_out:
return status;
diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h
index fab9737c0d6..b1d523ca4d8 100644
--- a/drivers/net/ixgbe/ixgbe_type.h
+++ b/drivers/net/ixgbe/ixgbe_type.h
@@ -1668,6 +1668,10 @@
#define IXGBE_ETH_LENGTH_OF_ADDRESS 6
+#define IXGBE_EEPROM_PAGE_SIZE_MAX 128
+#define IXGBE_EEPROM_RD_BUFFER_MAX_COUNT 512 /* EEPROM words # read in burst */
+#define IXGBE_EEPROM_WR_BUFFER_MAX_COUNT 256 /* EEPROM words # wr in burst */
+
#ifndef IXGBE_EEPROM_GRANT_ATTEMPTS
#define IXGBE_EEPROM_GRANT_ATTEMPTS 1000 /* EEPROM # attempts to gain grant */
#endif
@@ -2563,7 +2567,9 @@ typedef u8* (*ixgbe_mc_addr_itr) (struct ixgbe_hw *hw, u8 **mc_addr_ptr,
struct ixgbe_eeprom_operations {
s32 (*init_params)(struct ixgbe_hw *);
s32 (*read)(struct ixgbe_hw *, u16, u16 *);
+ s32 (*read_buffer)(struct ixgbe_hw *, u16, u16, u16 *);
s32 (*write)(struct ixgbe_hw *, u16, u16);
+ s32 (*write_buffer)(struct ixgbe_hw *, u16, u16, u16 *);
s32 (*validate_checksum)(struct ixgbe_hw *, u16 *);
s32 (*update_checksum)(struct ixgbe_hw *);
u16 (*calc_checksum)(struct ixgbe_hw *);
@@ -2649,6 +2655,7 @@ struct ixgbe_eeprom_info {
u32 semaphore_delay;
u16 word_size;
u16 address_bits;
+ u16 word_page_size;
};
#define IXGBE_FLAGS_DOUBLE_RESET_REQUIRED 0x01
diff --git a/drivers/net/ixgbe/ixgbe_x540.c b/drivers/net/ixgbe/ixgbe_x540.c
index 75c6465db89..4ed687be2fe 100644
--- a/drivers/net/ixgbe/ixgbe_x540.c
+++ b/drivers/net/ixgbe/ixgbe_x540.c
@@ -304,21 +304,49 @@ static s32 ixgbe_init_eeprom_params_X540(struct ixgbe_hw *hw)
}
/**
- * ixgbe_read_eerd_X540 - Read EEPROM word using EERD
- * @hw: pointer to hardware structure
- * @offset: offset of word in the EEPROM to read
- * @data: word read from the EERPOM
+ * ixgbe_read_eerd_X540- Read EEPROM word using EERD
+ * @hw: pointer to hardware structure
+ * @offset: offset of word in the EEPROM to read
+ * @data: word read from the EEPROM
+ *
+ * Reads a 16 bit word from the EEPROM using the EERD register.
**/
static s32 ixgbe_read_eerd_X540(struct ixgbe_hw *hw, u16 offset, u16 *data)
{
- s32 status;
+ s32 status = 0;
- if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0)
+ if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
+ 0)
status = ixgbe_read_eerd_generic(hw, offset, data);
else
status = IXGBE_ERR_SWFW_SYNC;
- ixgbe_release_swfw_sync_X540(hw, IXGBE_GSSR_EEP_SM);
+ hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
+ return status;
+}
+
+/**
+ * ixgbe_read_eerd_buffer_X540 - Read EEPROM word(s) using EERD
+ * @hw: pointer to hardware structure
+ * @offset: offset of word in the EEPROM to read
+ * @words: number of words
+ * @data: word(s) read from the EEPROM
+ *
+ * Reads a 16 bit word(s) from the EEPROM using the EERD register.
+ **/
+static s32 ixgbe_read_eerd_buffer_X540(struct ixgbe_hw *hw,
+ u16 offset, u16 words, u16 *data)
+{
+ s32 status = 0;
+
+ if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
+ 0)
+ status = ixgbe_read_eerd_buffer_generic(hw, offset,
+ words, data);
+ else
+ status = IXGBE_ERR_SWFW_SYNC;
+
+ hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
return status;
}
@@ -344,6 +372,31 @@ static s32 ixgbe_write_eewr_X540(struct ixgbe_hw *hw, u16 offset, u16 data)
}
/**
+ * ixgbe_write_eewr_buffer_X540 - Write EEPROM word(s) using EEWR
+ * @hw: pointer to hardware structure
+ * @offset: offset of word in the EEPROM to write
+ * @words: number of words
+ * @data: word(s) write to the EEPROM
+ *
+ * Write a 16 bit word(s) to the EEPROM using the EEWR register.
+ **/
+static s32 ixgbe_write_eewr_buffer_X540(struct ixgbe_hw *hw,
+ u16 offset, u16 words, u16 *data)
+{
+ s32 status = 0;
+
+ if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
+ 0)
+ status = ixgbe_write_eewr_buffer_generic(hw, offset,
+ words, data);
+ else
+ status = IXGBE_ERR_SWFW_SYNC;
+
+ hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
+ return status;
+}
+
+/**
* ixgbe_calc_eeprom_checksum_X540 - Calculates and returns the checksum
*
* This function does not use synchronization for EERD and EEWR. It can
@@ -851,7 +904,9 @@ static struct ixgbe_mac_operations mac_ops_X540 = {
static struct ixgbe_eeprom_operations eeprom_ops_X540 = {
.init_params = &ixgbe_init_eeprom_params_X540,
.read = &ixgbe_read_eerd_X540,
+ .read_buffer = &ixgbe_read_eerd_buffer_X540,
.write = &ixgbe_write_eewr_X540,
+ .write_buffer = &ixgbe_write_eewr_buffer_X540,
.calc_checksum = &ixgbe_calc_eeprom_checksum_X540,
.validate_checksum = &ixgbe_validate_eeprom_checksum_X540,
.update_checksum = &ixgbe_update_eeprom_checksum_X540,