Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 352511
b: refs/heads/master
c: 71858ac
h: refs/heads/master
i:
  352509: fcaf698
  352507: f6cf758
  352503: 0744a28
  352495: 9fe1826
  352479: 1d77c0d
  352447: 89efcc5
  352383: 5291ac2
  352255: 8f9982f
v: v3
  • Loading branch information
Aurélien Guillaume authored and Jeff Kirsher committed Feb 16, 2013
1 parent 58798a2 commit b38dfb9
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 51d0420b0ad9f0a9972165fef551628bcc95ee87
refs/heads/master: 71858acbe5c38e82554d92d041741ea949e46b99
1 change: 1 addition & 0 deletions trunk/drivers/net/ethernet/intel/ixgbe/ixgbe.h
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,7 @@ enum ixgbe_state_t {
__IXGBE_DOWN,
__IXGBE_SERVICE_SCHED,
__IXGBE_IN_SFP_INIT,
__IXGBE_READ_I2C,
};

struct ixgbe_cb {
Expand Down
114 changes: 114 additions & 0 deletions trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include <linux/uaccess.h>

#include "ixgbe.h"
#include "ixgbe_phy.h"


#define IXGBE_ALL_RAR_ENTRIES 16
Expand Down Expand Up @@ -2839,6 +2840,117 @@ static int ixgbe_set_channels(struct net_device *dev,
return ixgbe_setup_tc(dev, netdev_get_num_tc(dev));
}

static int ixgbe_get_module_info(struct net_device *dev,
struct ethtool_modinfo *modinfo)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_hw *hw = &adapter->hw;
u32 status;
u8 sff8472_rev, addr_mode;
int ret_val = 0;
bool page_swap = false;

/* avoid concurent i2c reads */
while (test_bit(__IXGBE_IN_SFP_INIT, &adapter->state))
msleep(100);

/* used by the service task */
set_bit(__IXGBE_READ_I2C, &adapter->state);

/* Check whether we support SFF-8472 or not */
status = hw->phy.ops.read_i2c_eeprom(hw,
IXGBE_SFF_SFF_8472_COMP,
&sff8472_rev);
if (status != 0) {
ret_val = -EIO;
goto err_out;
}

/* addressing mode is not supported */
status = hw->phy.ops.read_i2c_eeprom(hw,
IXGBE_SFF_SFF_8472_SWAP,
&addr_mode);
if (status != 0) {
ret_val = -EIO;
goto err_out;
}

if (addr_mode & IXGBE_SFF_ADDRESSING_MODE) {
e_err(drv, "Address change required to access page 0xA2, but not supported. Please report the module type to the driver maintainers.\n");
page_swap = true;
}

if (sff8472_rev == IXGBE_SFF_SFF_8472_UNSUP || page_swap) {
/* We have a SFP, but it does not support SFF-8472 */
modinfo->type = ETH_MODULE_SFF_8079;
modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
} else {
/* We have a SFP which supports a revision of SFF-8472. */
modinfo->type = ETH_MODULE_SFF_8472;
modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
}

err_out:
clear_bit(__IXGBE_READ_I2C, &adapter->state);
return ret_val;
}

static int ixgbe_get_module_eeprom(struct net_device *dev,
struct ethtool_eeprom *ee,
u8 *data)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ixgbe_hw *hw = &adapter->hw;
u32 status = IXGBE_ERR_PHY_ADDR_INVALID;
u8 databyte = 0xFF;
int i = 0;
int ret_val = 0;

/* ixgbe_get_module_info is called before this function in all
* cases, so we do not need any checks we already do above,
* and can trust ee->len to be a known value.
*/

while (test_bit(__IXGBE_IN_SFP_INIT, &adapter->state))
msleep(100);
set_bit(__IXGBE_READ_I2C, &adapter->state);

/* Read the first block, SFF-8079 */
for (i = 0; i < ETH_MODULE_SFF_8079_LEN; i++) {
status = hw->phy.ops.read_i2c_eeprom(hw, i, &databyte);
if (status != 0) {
/* Error occured while reading module */
ret_val = -EIO;
goto err_out;
}
data[i] = databyte;
}

/* If the second block is requested, check if SFF-8472 is supported. */
if (ee->len == ETH_MODULE_SFF_8472_LEN) {
if (data[IXGBE_SFF_SFF_8472_COMP] == IXGBE_SFF_SFF_8472_UNSUP)
return -EOPNOTSUPP;

/* Read the second block, SFF-8472 */
for (i = ETH_MODULE_SFF_8079_LEN;
i < ETH_MODULE_SFF_8472_LEN; i++) {
status = hw->phy.ops.read_i2c_sff8472(hw,
i - ETH_MODULE_SFF_8079_LEN, &databyte);
if (status != 0) {
/* Error occured while reading module */
ret_val = -EIO;
goto err_out;
}
data[i] = databyte;
}
}

err_out:
clear_bit(__IXGBE_READ_I2C, &adapter->state);

return ret_val;
}

static const struct ethtool_ops ixgbe_ethtool_ops = {
.get_settings = ixgbe_get_settings,
.set_settings = ixgbe_set_settings,
Expand Down Expand Up @@ -2870,6 +2982,8 @@ static const struct ethtool_ops ixgbe_ethtool_ops = {
.get_channels = ixgbe_get_channels,
.set_channels = ixgbe_set_channels,
.get_ts_info = ixgbe_get_ts_info,
.get_module_info = ixgbe_get_module_info,
.get_module_eeprom = ixgbe_get_module_eeprom,
};

void ixgbe_set_ethtool_ops(struct net_device *netdev)
Expand Down
4 changes: 4 additions & 0 deletions trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -5709,6 +5709,10 @@ static void ixgbe_sfp_detection_subtask(struct ixgbe_adapter *adapter)
!(adapter->flags2 & IXGBE_FLAG2_SFP_NEEDS_RESET))
return;

/* concurent i2c reads are not supported */
if (test_bit(__IXGBE_READ_I2C, &adapter->state))
return;

/* someone else is in init, wait until next service event */
if (test_and_set_bit(__IXGBE_IN_SFP_INIT, &adapter->state))
return;
Expand Down

0 comments on commit b38dfb9

Please sign in to comment.