Commit 8ca783ab authored by Don Skidmore's avatar Don Skidmore Committed by David S. Miller
Browse files

ixgbe: fix 82598 SFP initialization after driver load.



If we loaded the driver with out a SFP module plugged in it would
leave it in a state that make it later unable to link when a module
was plugged in.  This patch corrects that by:

ixgbe_probe() - moving the check for IXGBE_ERR_SFP_NOT_PRESENT from
after get_invariants() to after reset_hw() as now reset_hw() is
where this condition will be indentified.

ixgbe_reset_hw_82598() - Enable this function to now return
IXGBE_ERR_SFP_NOT_PRESENT.

ixgbe_identify_sfp_module_generic() - This where the lack of SFP
module is detected.  Modifications are added to allow a different
return value for modules that just haven't been plugged in yet.

Other functions were updated to allow correct logging.

Signed-off-by: default avatarDon Skidmore <donald.c.skidmore@intel.com>
Signed-off-by: default avatarPeter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f7c86a32
Loading
Loading
Loading
Loading
+10 −2
Original line number Diff line number Diff line
@@ -698,6 +698,7 @@ static s32 ixgbe_setup_copper_link_speed_82598(struct ixgbe_hw *hw,
static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw)
{
	s32 status = 0;
	s32 phy_status = 0;
	u32 ctrl;
	u32 gheccr;
	u32 i;
@@ -745,13 +746,17 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw)
		/* PHY ops must be identified and initialized prior to reset */

		/* Init PHY and function pointers, perform SFP setup */
		status = hw->phy.ops.init(hw);
		if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
		phy_status = hw->phy.ops.init(hw);
		if (phy_status == IXGBE_ERR_SFP_NOT_SUPPORTED)
			goto reset_hw_out;
		else if (phy_status == IXGBE_ERR_SFP_NOT_PRESENT)
			goto no_phy_reset;


		hw->phy.ops.reset(hw);
	}

no_phy_reset:
	/*
	 * Prevent the PCI-E bus from from hanging by disabling PCI-E master
	 * access and verify no pending requests before reset
@@ -811,6 +816,9 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw)
	hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);

reset_hw_out:
	if (phy_status)
		status = phy_status;

	return status;
}

+17 −16
Original line number Diff line number Diff line
@@ -2599,7 +2599,10 @@ int ixgbe_up(struct ixgbe_adapter *adapter)
void ixgbe_reset(struct ixgbe_adapter *adapter)
{
	struct ixgbe_hw *hw = &adapter->hw;
	if (hw->mac.ops.init_hw(hw))
	int err;

	err = hw->mac.ops.init_hw(hw);
	if (err && (err != IXGBE_ERR_SFP_NOT_PRESENT))
		dev_err(&adapter->pdev->dev, "Hardware Error\n");

	/* reprogram the RAR[0] in case user changed it. */
@@ -5167,20 +5170,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
	INIT_WORK(&adapter->sfp_config_module_task,
	          ixgbe_sfp_config_module_task);

	err = ii->get_invariants(hw);
	if (err == IXGBE_ERR_SFP_NOT_PRESENT) {
		/* start a kernel thread to watch for a module to arrive */
		set_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
		mod_timer(&adapter->sfp_timer,
		          round_jiffies(jiffies + (2 * HZ)));
		err = 0;
	} else if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
		DPRINTK(PROBE, ERR, "failed to load because an "
		        "unsupported SFP+ module type was detected.\n");
		goto err_hw_init;
	} else if (err) {
		goto err_hw_init;
	}
	ii->get_invariants(hw);

	/* setup the private structure */
	err = ixgbe_sw_init(adapter);
@@ -5200,7 +5190,18 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,

	/* reset_hw fills in the perm_addr as well */
	err = hw->mac.ops.reset_hw(hw);
	if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
	if (err == IXGBE_ERR_SFP_NOT_PRESENT &&
	    hw->mac.type == ixgbe_mac_82598EB) {
		/*
		 * Start a kernel thread to watch for a module to arrive.
		 * Only do this for 82598, since 82599 will generate
		 * interrupts on module arrival.
		 */
		set_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
		mod_timer(&adapter->sfp_timer,
			  round_jiffies(jiffies + (2 * HZ)));
		err = 0;
	} else if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
		dev_err(&adapter->pdev->dev, "failed to load because an "
		        "unsupported SFP+ module type was detected.\n");
		goto err_sw_init;
+12 −1
Original line number Diff line number Diff line
@@ -530,11 +530,22 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
	u8 cable_tech = 0;
	u16 enforce_sfp = 0;

	if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_fiber) {
		hw->phy.sfp_type = ixgbe_sfp_type_not_present;
		status = IXGBE_ERR_SFP_NOT_PRESENT;
		goto out;
	}

	status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_IDENTIFIER,
	                                     &identifier);

	if (status == IXGBE_ERR_SFP_NOT_PRESENT) {
	if (status == IXGBE_ERR_SFP_NOT_PRESENT || status == IXGBE_ERR_I2C) {
		status = IXGBE_ERR_SFP_NOT_PRESENT;
		hw->phy.sfp_type = ixgbe_sfp_type_not_present;
		if (hw->phy.type != ixgbe_phy_nl) {
			hw->phy.id = 0;
			hw->phy.type = ixgbe_phy_unknown;
		}
		goto out;
	}