Skip to content

Commit

Permalink
ixgbe: add support for quad-port x520 adapter
Browse files Browse the repository at this point in the history
This is a x520 based quad-port (4x10Gbps) NIC with a single QSFP+
connector.  Changes were required to our identify functions due to
different eeprom address which is also included here.

Signed-off-by: Don Skidmore <donald.c.skidmore@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
  • Loading branch information
Don Skidmore authored and Jeff Kirsher committed Jul 31, 2013
1 parent 674c18b commit 8f58332
Show file tree
Hide file tree
Showing 6 changed files with 358 additions and 17 deletions.
2 changes: 1 addition & 1 deletion drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
Original file line number Diff line number Diff line change
Expand Up @@ -1331,7 +1331,7 @@ 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_module_generic,
.init = &ixgbe_init_phy_ops_82598,
.reset = &ixgbe_reset_phy_generic,
.read_reg = &ixgbe_read_phy_reg_generic,
Expand Down
147 changes: 145 additions & 2 deletions drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw,
ixgbe_link_speed speed,
bool autoneg_wait_to_complete);
static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw);
static s32 ixgbe_read_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
u8 dev_addr, u8 *data);
static s32 ixgbe_write_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
u8 dev_addr, u8 data);

static bool ixgbe_mng_enabled(struct ixgbe_hw *hw)
{
Expand Down Expand Up @@ -219,6 +223,25 @@ static s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw)
struct ixgbe_mac_info *mac = &hw->mac;
struct ixgbe_phy_info *phy = &hw->phy;
s32 ret_val = 0;
u32 esdp;

if (hw->device_id == IXGBE_DEV_ID_82599_QSFP_SF_QP) {
/* Store flag indicating I2C bus access control unit. */
hw->phy.qsfp_shared_i2c_bus = true;

/* Initialize access to QSFP+ I2C bus */
esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
esdp |= IXGBE_ESDP_SDP0_DIR;
esdp &= ~IXGBE_ESDP_SDP1_DIR;
esdp &= ~IXGBE_ESDP_SDP0;
esdp &= ~IXGBE_ESDP_SDP0_NATIVE;
esdp &= ~IXGBE_ESDP_SDP1_NATIVE;
IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
IXGBE_WRITE_FLUSH(hw);

phy->ops.read_i2c_byte = &ixgbe_read_i2c_byte_82599;
phy->ops.write_i2c_byte = &ixgbe_write_i2c_byte_82599;
}

/* Identify the PHY or SFP module */
ret_val = phy->ops.identify(hw);
Expand Down Expand Up @@ -397,6 +420,9 @@ static enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw)
case IXGBE_DEV_ID_82599_LS:
media_type = ixgbe_media_type_fiber_lco;
break;
case IXGBE_DEV_ID_82599_QSFP_SF_QP:
media_type = ixgbe_media_type_fiber_qsfp;
break;
default:
media_type = ixgbe_media_type_unknown;
break;
Expand Down Expand Up @@ -1951,7 +1977,7 @@ static s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw)
if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_copper)
goto out;
else
status = ixgbe_identify_sfp_module_generic(hw);
status = ixgbe_identify_module_generic(hw);
}

/* Set PHY type none if no PHY detected */
Expand Down Expand Up @@ -2057,10 +2083,12 @@ static u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw)
switch (hw->phy.type) {
case ixgbe_phy_sfp_passive_tyco:
case ixgbe_phy_sfp_passive_unknown:
case ixgbe_phy_qsfp_passive_unknown:
physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU;
break;
case ixgbe_phy_sfp_ftl_active:
case ixgbe_phy_sfp_active_unknown:
case ixgbe_phy_qsfp_active_unknown:
physical_layer = IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA;
break;
case ixgbe_phy_sfp_avago:
Expand All @@ -2078,6 +2106,15 @@ static u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw)
else if (comp_codes_1g & IXGBE_SFF_1GBASET_CAPABLE)
physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_T;
break;
case ixgbe_phy_qsfp_intel:
case ixgbe_phy_qsfp_unknown:
hw->phy.ops.read_i2c_eeprom(hw,
IXGBE_SFF_QSFP_10GBE_COMP, &comp_codes_10g);
if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)
physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)
physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
break;
default:
break;
}
Expand Down Expand Up @@ -2315,6 +2352,112 @@ s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw)
return ret_val;
}

/**
* ixgbe_read_i2c_byte_82599 - Reads 8 bit word over I2C
* @hw: pointer to hardware structure
* @byte_offset: byte offset to read
* @data: value read
*
* Performs byte read operation to SFP module's EEPROM over I2C interface at
* a specified device address.
**/
static s32 ixgbe_read_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
u8 dev_addr, u8 *data)
{
u32 esdp;
s32 status;
s32 timeout = 200;

if (hw->phy.qsfp_shared_i2c_bus == true) {
/* Acquire I2C bus ownership. */
esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
esdp |= IXGBE_ESDP_SDP0;
IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
IXGBE_WRITE_FLUSH(hw);

while (timeout) {
esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
if (esdp & IXGBE_ESDP_SDP1)
break;

usleep_range(5000, 10000);
timeout--;
}

if (!timeout) {
hw_dbg(hw, "Driver can't access resource, acquiring I2C bus timeout.\n");
status = IXGBE_ERR_I2C;
goto release_i2c_access;
}
}

status = ixgbe_read_i2c_byte_generic(hw, byte_offset, dev_addr, data);

release_i2c_access:
if (hw->phy.qsfp_shared_i2c_bus == true) {
/* Release I2C bus ownership. */
esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
esdp &= ~IXGBE_ESDP_SDP0;
IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
IXGBE_WRITE_FLUSH(hw);
}

return status;
}

/**
* ixgbe_write_i2c_byte_82599 - Writes 8 bit word over I2C
* @hw: pointer to hardware structure
* @byte_offset: byte offset to write
* @data: value to write
*
* Performs byte write operation to SFP module's EEPROM over I2C interface at
* a specified device address.
**/
static s32 ixgbe_write_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
u8 dev_addr, u8 data)
{
u32 esdp;
s32 status;
s32 timeout = 200;

if (hw->phy.qsfp_shared_i2c_bus == true) {
/* Acquire I2C bus ownership. */
esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
esdp |= IXGBE_ESDP_SDP0;
IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
IXGBE_WRITE_FLUSH(hw);

while (timeout) {
esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
if (esdp & IXGBE_ESDP_SDP1)
break;

usleep_range(5000, 10000);
timeout--;
}

if (!timeout) {
hw_dbg(hw, "Driver can't access resource, acquiring I2C bus timeout.\n");
status = IXGBE_ERR_I2C;
goto release_i2c_access;
}
}

status = ixgbe_write_i2c_byte_generic(hw, byte_offset, dev_addr, data);

release_i2c_access:
if (hw->phy.qsfp_shared_i2c_bus == true) {
/* Release I2C bus ownership. */
esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
esdp &= ~IXGBE_ESDP_SDP0;
IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
IXGBE_WRITE_FLUSH(hw);
}

return status;
}

static struct ixgbe_mac_operations mac_ops_82599 = {
.init_hw = &ixgbe_init_hw_generic,
.reset_hw = &ixgbe_reset_hw_82599,
Expand Down Expand Up @@ -2379,7 +2522,7 @@ static struct ixgbe_eeprom_operations eeprom_ops_82599 = {

static struct ixgbe_phy_operations phy_ops_82599 = {
.identify = &ixgbe_identify_phy_82599,
.identify_sfp = &ixgbe_identify_sfp_module_generic,
.identify_sfp = &ixgbe_identify_module_generic,
.init = &ixgbe_init_phy_ops_82599,
.reset = &ixgbe_reset_phy_generic,
.read_reg = &ixgbe_read_phy_reg_generic,
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ static DEFINE_PCI_DEVICE_TABLE(ixgbe_pci_tbl) = {
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540T), board_X540 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_SF2), board_82599 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_LS), board_82599 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_QSFP_SF_QP), board_82599 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599EN_SFP), board_82599 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_SF_QP), board_82599 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540T1), board_X540 },
Expand Down Expand Up @@ -208,6 +209,7 @@ static inline bool ixgbe_pcie_from_parent(struct ixgbe_hw *hw)
{
switch (hw->device_id) {
case IXGBE_DEV_ID_82599_SFP_SF_QP:
case IXGBE_DEV_ID_82599_QSFP_SF_QP:
return true;
default:
return false;
Expand Down Expand Up @@ -7347,6 +7349,7 @@ static inline int ixgbe_enumerate_functions(struct ixgbe_adapter *adapter)
*/
switch (hw->device_id) {
case IXGBE_DEV_ID_82599_SFP_SF_QP:
case IXGBE_DEV_ID_82599_QSFP_SF_QP:
physfns = 4;
break;
default:
Expand Down
Loading

0 comments on commit 8f58332

Please sign in to comment.