Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 121968
b: refs/heads/master
c: c4900be
h: refs/heads/master
v: v3
  • Loading branch information
Donald Skidmore authored and David S. Miller committed Nov 21, 2008
1 parent af21e71 commit 3a45f5f
Show file tree
Hide file tree
Showing 7 changed files with 551 additions and 8 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 859ee3c43812051e21816c6d6d4cc04fb7ce9b2e
refs/heads/master: c4900be053d376dfe4f603d000aa5e4c60745dec
5 changes: 4 additions & 1 deletion trunk/drivers/net/ixgbe/ixgbe.h
Original file line number Diff line number Diff line change
Expand Up @@ -311,12 +311,15 @@ struct ixgbe_adapter {
unsigned long link_check_timeout;

struct work_struct watchdog_task;
struct work_struct sfp_task;
struct timer_list sfp_timer;
};

enum ixbge_state_t {
__IXGBE_TESTING,
__IXGBE_RESETTING,
__IXGBE_DOWN
__IXGBE_DOWN,
__IXGBE_SFP_MODULE_NOT_FOUND
};

enum ixgbe_boards {
Expand Down
160 changes: 158 additions & 2 deletions trunk/drivers/net/ixgbe/ixgbe_82598.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,17 @@ static s32 ixgbe_setup_copper_link_speed_82598(struct ixgbe_hw *hw,
ixgbe_link_speed speed,
bool autoneg,
bool autoneg_wait_to_complete);
static s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset,
u8 *eeprom_data);

/**
*/
static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw)
{
struct ixgbe_mac_info *mac = &hw->mac;
struct ixgbe_phy_info *phy = &hw->phy;
s32 ret_val = 0;
u16 list_offset, data_offset;

/* Call PHY identify routine to get the phy type */
ixgbe_identify_phy_generic(hw);
Expand All @@ -64,6 +68,27 @@ static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw)
phy->ops.get_firmware_version =
&ixgbe_get_phy_firmware_version_tnx;
break;
case ixgbe_phy_nl:
phy->ops.reset = &ixgbe_reset_phy_nl;

/* Call SFP+ identify routine to get the SFP+ module type */
ret_val = phy->ops.identify_sfp(hw);
if (ret_val != 0)
goto out;
else if (hw->phy.sfp_type == ixgbe_sfp_type_unknown) {
ret_val = IXGBE_ERR_SFP_NOT_SUPPORTED;
goto out;
}

/* Check to see if SFP+ module is supported */
ret_val = ixgbe_get_sfp_init_sequence_offsets(hw,
&list_offset,
&data_offset);
if (ret_val != 0) {
ret_val = IXGBE_ERR_SFP_NOT_SUPPORTED;
goto out;
}
break;
default:
break;
}
Expand All @@ -82,7 +107,8 @@ static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw)
mac->max_rx_queues = IXGBE_82598_MAX_RX_QUEUES;
mac->max_tx_queues = IXGBE_82598_MAX_TX_QUEUES;

return 0;
out:
return ret_val;
}

/**
Expand Down Expand Up @@ -191,7 +217,10 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw)
case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
case IXGBE_DEV_ID_82598EB_CX4:
case IXGBE_DEV_ID_82598_CX4_DUAL_PORT:
case IXGBE_DEV_ID_82598_DA_DUAL_PORT:
case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM:
case IXGBE_DEV_ID_82598EB_XF_LR:
case IXGBE_DEV_ID_82598EB_SFP_LOM:
media_type = ixgbe_media_type_fiber;
break;
case IXGBE_DEV_ID_82598AT:
Expand Down Expand Up @@ -399,6 +428,46 @@ static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw,
{
u32 links_reg;
u32 i;
u16 link_reg, adapt_comp_reg;

/*
* SERDES PHY requires us to read link status from register 0xC79F.
* Bit 0 set indicates link is up/ready; clear indicates link down.
* 0xC00C is read to check that the XAUI lanes are active. Bit 0
* clear indicates active; set indicates inactive.
*/
if (hw->phy.type == ixgbe_phy_nl) {
hw->phy.ops.read_reg(hw, 0xC79F, IXGBE_TWINAX_DEV, &link_reg);
hw->phy.ops.read_reg(hw, 0xC79F, IXGBE_TWINAX_DEV, &link_reg);
hw->phy.ops.read_reg(hw, 0xC00C, IXGBE_TWINAX_DEV,
&adapt_comp_reg);
if (link_up_wait_to_complete) {
for (i = 0; i < IXGBE_LINK_UP_TIME; i++) {
if ((link_reg & 1) &&
((adapt_comp_reg & 1) == 0)) {
*link_up = true;
break;
} else {
*link_up = false;
}
msleep(100);
hw->phy.ops.read_reg(hw, 0xC79F,
IXGBE_TWINAX_DEV,
&link_reg);
hw->phy.ops.read_reg(hw, 0xC00C,
IXGBE_TWINAX_DEV,
&adapt_comp_reg);
}
} else {
if ((link_reg & 1) && ((adapt_comp_reg & 1) == 0))
*link_up = true;
else
*link_up = false;
}

if (*link_up == false)
goto out;
}

links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
if (link_up_wait_to_complete) {
Expand All @@ -424,6 +493,7 @@ static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw,
else
*speed = IXGBE_LINK_SPEED_1GB_FULL;

out:
return 0;
}

Expand Down Expand Up @@ -858,6 +928,69 @@ s32 ixgbe_write_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 val)
return 0;
}

/**
* ixgbe_read_i2c_eeprom_82598 - Read 8 bit EEPROM word of an SFP+ module
* over I2C interface through an intermediate phy.
* @hw: pointer to hardware structure
* @byte_offset: EEPROM byte offset to read
* @eeprom_data: value read
*
* Performs byte read operation to SFP module's EEPROM over I2C interface.
**/
s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset,
u8 *eeprom_data)
{
s32 status = 0;
u16 sfp_addr = 0;
u16 sfp_data = 0;
u16 sfp_stat = 0;
u32 i;

if (hw->phy.type == ixgbe_phy_nl) {
/*
* phy SDA/SCL registers are at addresses 0xC30A to
* 0xC30D. These registers are used to talk to the SFP+
* module's EEPROM through the SDA/SCL (I2C) interface.
*/
sfp_addr = (IXGBE_I2C_EEPROM_DEV_ADDR << 8) + byte_offset;
sfp_addr = (sfp_addr | IXGBE_I2C_EEPROM_READ_MASK);
hw->phy.ops.write_reg(hw,
IXGBE_MDIO_PMA_PMD_SDA_SCL_ADDR,
IXGBE_MDIO_PMA_PMD_DEV_TYPE,
sfp_addr);

/* Poll status */
for (i = 0; i < 100; i++) {
hw->phy.ops.read_reg(hw,
IXGBE_MDIO_PMA_PMD_SDA_SCL_STAT,
IXGBE_MDIO_PMA_PMD_DEV_TYPE,
&sfp_stat);
sfp_stat = sfp_stat & IXGBE_I2C_EEPROM_STATUS_MASK;
if (sfp_stat != IXGBE_I2C_EEPROM_STATUS_IN_PROGRESS)
break;
msleep(10);
}

if (sfp_stat != IXGBE_I2C_EEPROM_STATUS_PASS) {
hw_dbg(hw, "EEPROM read did not pass.\n");
status = IXGBE_ERR_SFP_NOT_PRESENT;
goto out;
}

/* Read data */
hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_PMD_SDA_SCL_DATA,
IXGBE_MDIO_PMA_PMD_DEV_TYPE, &sfp_data);

*eeprom_data = (u8)(sfp_data >> 8);
} else {
status = IXGBE_ERR_PHY;
goto out;
}

out:
return status;
}

/**
* ixgbe_get_supported_physical_layer_82598 - Returns physical layer type
* @hw: pointer to hardware structure
Expand All @@ -873,8 +1006,12 @@ s32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw)
case IXGBE_DEV_ID_82598_CX4_DUAL_PORT:
physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4;
break;
case IXGBE_DEV_ID_82598_DA_DUAL_PORT:
physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU;
break;
case IXGBE_DEV_ID_82598AF_DUAL_PORT:
case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM:
physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
break;
case IXGBE_DEV_ID_82598EB_XF_LR:
Expand All @@ -884,6 +1021,24 @@ s32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw)
physical_layer = (IXGBE_PHYSICAL_LAYER_10GBASE_T |
IXGBE_PHYSICAL_LAYER_1000BASE_T);
break;
case IXGBE_DEV_ID_82598EB_SFP_LOM:
hw->phy.ops.identify_sfp(hw);

switch (hw->phy.sfp_type) {
case ixgbe_sfp_type_da_cu:
physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU;
break;
case ixgbe_sfp_type_sr:
physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
break;
case ixgbe_sfp_type_lr:
physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
break;
default:
physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
break;
}
break;

default:
physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
Expand Down Expand Up @@ -935,12 +1090,13 @@ static struct ixgbe_eeprom_operations eeprom_ops_82598 = {

static struct ixgbe_phy_operations phy_ops_82598 = {
.identify = &ixgbe_identify_phy_generic,
/* .identify_sfp = &ixgbe_identify_sfp_module_generic, */
.identify_sfp = &ixgbe_identify_sfp_module_generic,
.reset = &ixgbe_reset_phy_generic,
.read_reg = &ixgbe_read_phy_reg_generic,
.write_reg = &ixgbe_write_phy_reg_generic,
.setup_link = &ixgbe_setup_phy_link_generic,
.setup_link_speed = &ixgbe_setup_phy_link_speed_generic,
.read_i2c_eeprom = &ixgbe_read_i2c_eeprom_82598,
};

struct ixgbe_info ixgbe_82598_info = {
Expand Down
Loading

0 comments on commit 3a45f5f

Please sign in to comment.