Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 318a94d6 authored by Jeff Kirsher's avatar Jeff Kirsher Committed by Jeff Garzik
Browse files

e1000e: reorganize PHY and flow control interface



This reorganization moves the PHY status into a separate
struct. Flow Control setup is moved into this struct as well
and frame size away from here into the adapter struct where its
inly use is.

The post-link-up code is now a separate function and moved out
of the watchdog function itself. This allows us to track the
es2lan restart issue a bit easier.

Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: default avatarBruce Allan <bruce.w.allan@intel.com>
Signed-off-by: default avatarJesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: default avatarAuke Kok <auke-jan.h.kok@intel.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent e2de3eb6
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -75,7 +75,7 @@ static s32 e1000_init_phy_params_82571(struct e1000_hw *hw)
	struct e1000_phy_info *phy = &hw->phy;
	s32 ret_val;

	if (hw->media_type != e1000_media_type_copper) {
	if (hw->phy.media_type != e1000_media_type_copper) {
		phy->type = e1000_phy_none;
		return 0;
	}
@@ -195,16 +195,16 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter)
	case E1000_DEV_ID_82571EB_FIBER:
	case E1000_DEV_ID_82572EI_FIBER:
	case E1000_DEV_ID_82571EB_QUAD_FIBER:
		hw->media_type = e1000_media_type_fiber;
		hw->phy.media_type = e1000_media_type_fiber;
		break;
	case E1000_DEV_ID_82571EB_SERDES:
	case E1000_DEV_ID_82572EI_SERDES:
	case E1000_DEV_ID_82571EB_SERDES_DUAL:
	case E1000_DEV_ID_82571EB_SERDES_QUAD:
		hw->media_type = e1000_media_type_internal_serdes;
		hw->phy.media_type = e1000_media_type_internal_serdes;
		break;
	default:
		hw->media_type = e1000_media_type_copper;
		hw->phy.media_type = e1000_media_type_copper;
		break;
	}

@@ -216,7 +216,7 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter)
	mac->arc_subsystem_valid = (er32(FWSM) & E1000_FWSM_MODE_MASK) ? 1 : 0;

	/* check for link */
	switch (hw->media_type) {
	switch (hw->phy.media_type) {
	case e1000_media_type_copper:
		func->setup_physical_interface = e1000_setup_copper_link_82571;
		func->check_for_link = e1000e_check_for_copper_link;
@@ -1015,7 +1015,7 @@ static s32 e1000_setup_link_82571(struct e1000_hw *hw)
	 * set it to full.
	 */
	if (hw->mac.type == e1000_82573)
		hw->mac.fc = e1000_fc_full;
		hw->fc.type = e1000_fc_full;

	return e1000e_setup_link(hw);
}
+4 −1
Original line number Diff line number Diff line
@@ -234,6 +234,8 @@ struct e1000_adapter {

	unsigned int rx_ps_pages;
	u16 rx_ps_bsize0;
	u32 max_frame_size;
	u32 min_frame_size;

	/* OS defined structs */
	struct net_device *netdev;
@@ -258,7 +260,7 @@ struct e1000_adapter {
	u32 wol;
	u32 pba;

	u8 fc_autoneg;
	bool fc_autoneg;

	unsigned long led_status;

@@ -305,6 +307,7 @@ struct e1000_info {
#define FLAG_MSI_ENABLED                  (1 << 27)
#define FLAG_RX_CSUM_ENABLED              (1 << 28)
#define FLAG_TSO_FORCE                    (1 << 29)
#define FLAG_RX_RESTART_NOW               (1 << 30)

#define E1000_RX_DESC_PS(R, i)	    \
	(&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
+7 −7
Original line number Diff line number Diff line
@@ -119,7 +119,7 @@ static s32 e1000_init_phy_params_80003es2lan(struct e1000_hw *hw)
	struct e1000_phy_info *phy = &hw->phy;
	s32 ret_val;

	if (hw->media_type != e1000_media_type_copper) {
	if (hw->phy.media_type != e1000_media_type_copper) {
		phy->type	= e1000_phy_none;
		return 0;
	}
@@ -198,10 +198,10 @@ static s32 e1000_init_mac_params_80003es2lan(struct e1000_adapter *adapter)
	/* Set media type */
	switch (adapter->pdev->device) {
	case E1000_DEV_ID_80003ES2LAN_SERDES_DPT:
		hw->media_type = e1000_media_type_internal_serdes;
		hw->phy.media_type = e1000_media_type_internal_serdes;
		break;
	default:
		hw->media_type = e1000_media_type_copper;
		hw->phy.media_type = e1000_media_type_copper;
		break;
	}

@@ -213,7 +213,7 @@ static s32 e1000_init_mac_params_80003es2lan(struct e1000_adapter *adapter)
	mac->arc_subsystem_valid = (er32(FWSM) & E1000_FWSM_MODE_MASK) ? 1 : 0;

	/* check for link */
	switch (hw->media_type) {
	switch (hw->phy.media_type) {
	case e1000_media_type_copper:
		func->setup_physical_interface = e1000_setup_copper_link_80003es2lan;
		func->check_for_link = e1000e_check_for_copper_link;
@@ -591,7 +591,7 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)

	udelay(1);

	if (hw->phy.wait_for_link) {
	if (hw->phy.autoneg_wait_to_complete) {
		hw_dbg(hw, "Waiting for forced speed/duplex link "
			 "on GG82563 phy.\n");

@@ -682,7 +682,7 @@ static s32 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed,
{
	s32 ret_val;

	if (hw->media_type == e1000_media_type_copper) {
	if (hw->phy.media_type == e1000_media_type_copper) {
		ret_val = e1000e_get_speed_and_duplex_copper(hw,
								    speed,
								    duplex);
@@ -854,7 +854,7 @@ static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw)
	/* Transmit Arbitration Control 0 */
	reg = er32(TARC0);
	reg &= ~(0xF << 27); /* 30:27 */
	if (hw->media_type != e1000_media_type_copper)
	if (hw->phy.media_type != e1000_media_type_copper)
		reg &= ~(1 << 20);
	ew32(TARC0, reg);

+33 −31
Original line number Diff line number Diff line
@@ -111,7 +111,7 @@ static int e1000_get_settings(struct net_device *netdev,
	struct e1000_hw *hw = &adapter->hw;
	u32 status;

	if (hw->media_type == e1000_media_type_copper) {
	if (hw->phy.media_type == e1000_media_type_copper) {

		ecmd->supported = (SUPPORTED_10baseT_Half |
				   SUPPORTED_10baseT_Full |
@@ -165,7 +165,7 @@ static int e1000_get_settings(struct net_device *netdev,
		ecmd->duplex = -1;
	}

	ecmd->autoneg = ((hw->media_type == e1000_media_type_fiber) ||
	ecmd->autoneg = ((hw->phy.media_type == e1000_media_type_fiber) ||
			 hw->mac.autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE;
	return 0;
}
@@ -187,7 +187,7 @@ static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx)
	mac->autoneg = 0;

	/* Fiber NICs only allow 1000 gbps Full duplex */
	if ((adapter->hw.media_type == e1000_media_type_fiber) &&
	if ((adapter->hw.phy.media_type == e1000_media_type_fiber) &&
		spddplx != (SPEED_1000 + DUPLEX_FULL)) {
		ndev_err(adapter->netdev, "Unsupported Speed/Duplex "
			 "configuration\n");
@@ -241,7 +241,7 @@ static int e1000_set_settings(struct net_device *netdev,

	if (ecmd->autoneg == AUTONEG_ENABLE) {
		hw->mac.autoneg = 1;
		if (hw->media_type == e1000_media_type_fiber)
		if (hw->phy.media_type == e1000_media_type_fiber)
			hw->phy.autoneg_advertised = ADVERTISED_1000baseT_Full |
						     ADVERTISED_FIBRE |
						     ADVERTISED_Autoneg;
@@ -250,6 +250,8 @@ static int e1000_set_settings(struct net_device *netdev,
						     ADVERTISED_TP |
						     ADVERTISED_Autoneg;
		ecmd->advertising = hw->phy.autoneg_advertised;
		if (adapter->fc_autoneg)
			hw->fc.original_type = e1000_fc_default;
	} else {
		if (e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)) {
			clear_bit(__E1000_RESETTING, &adapter->state);
@@ -279,11 +281,11 @@ static void e1000_get_pauseparam(struct net_device *netdev,
	pause->autoneg =
		(adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE);

	if (hw->mac.fc == e1000_fc_rx_pause) {
	if (hw->fc.type == e1000_fc_rx_pause) {
		pause->rx_pause = 1;
	} else if (hw->mac.fc == e1000_fc_tx_pause) {
	} else if (hw->fc.type == e1000_fc_tx_pause) {
		pause->tx_pause = 1;
	} else if (hw->mac.fc == e1000_fc_full) {
	} else if (hw->fc.type == e1000_fc_full) {
		pause->rx_pause = 1;
		pause->tx_pause = 1;
	}
@@ -302,18 +304,18 @@ static int e1000_set_pauseparam(struct net_device *netdev,
		msleep(1);

	if (pause->rx_pause && pause->tx_pause)
		hw->mac.fc = e1000_fc_full;
		hw->fc.type = e1000_fc_full;
	else if (pause->rx_pause && !pause->tx_pause)
		hw->mac.fc = e1000_fc_rx_pause;
		hw->fc.type = e1000_fc_rx_pause;
	else if (!pause->rx_pause && pause->tx_pause)
		hw->mac.fc = e1000_fc_tx_pause;
		hw->fc.type = e1000_fc_tx_pause;
	else if (!pause->rx_pause && !pause->tx_pause)
		hw->mac.fc = e1000_fc_none;
		hw->fc.type = e1000_fc_none;

	hw->mac.original_fc = hw->mac.fc;
	hw->fc.original_type = hw->fc.type;

	if (adapter->fc_autoneg == AUTONEG_ENABLE) {
		hw->mac.fc = e1000_fc_default;
		hw->fc.type = e1000_fc_default;
		if (netif_running(adapter->netdev)) {
			e1000e_down(adapter);
			e1000e_up(adapter);
@@ -321,7 +323,7 @@ static int e1000_set_pauseparam(struct net_device *netdev,
			e1000e_reset(adapter);
		}
	} else {
		retval = ((hw->media_type == e1000_media_type_fiber) ?
		retval = ((hw->phy.media_type == e1000_media_type_fiber) ?
			  hw->mac.ops.setup_link(hw) : e1000e_force_mac_fc(hw));
	}

@@ -1187,21 +1189,21 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
	u32 ctrl_reg = 0;
	u32 stat_reg = 0;

	adapter->hw.mac.autoneg = 0;
	hw->mac.autoneg = 0;

	if (adapter->hw.phy.type == e1000_phy_m88) {
	if (hw->phy.type == e1000_phy_m88) {
		/* Auto-MDI/MDIX Off */
		e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, 0x0808);
		/* reset to update Auto-MDI/MDIX */
		e1e_wphy(hw, PHY_CONTROL, 0x9140);
		/* autoneg off */
		e1e_wphy(hw, PHY_CONTROL, 0x8140);
	} else if (adapter->hw.phy.type == e1000_phy_gg82563)
	} else if (hw->phy.type == e1000_phy_gg82563)
		e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, 0x1CC);

	ctrl_reg = er32(CTRL);

	if (adapter->hw.phy.type == e1000_phy_ife) {
	if (hw->phy.type == e1000_phy_ife) {
		/* force 100, set loopback */
		e1e_wphy(hw, PHY_CONTROL, 0x6100);

@@ -1224,8 +1226,8 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
			     E1000_CTRL_FD);	 /* Force Duplex to FULL */
	}

	if (adapter->hw.media_type == e1000_media_type_copper &&
	   adapter->hw.phy.type == e1000_phy_m88) {
	if (hw->phy.media_type == e1000_media_type_copper &&
	    hw->phy.type == e1000_phy_m88) {
		ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */
	} else {
		/*
@@ -1243,7 +1245,7 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
	 * Disable the receiver on the PHY so when a cable is plugged in, the
	 * PHY does not begin to autoneg when a cable is reconnected to the NIC.
	 */
	if (adapter->hw.phy.type == e1000_phy_m88)
	if (hw->phy.type == e1000_phy_m88)
		e1000_phy_disable_receiver(adapter);

	udelay(500);
@@ -1333,8 +1335,8 @@ static int e1000_setup_loopback_test(struct e1000_adapter *adapter)
	struct e1000_hw *hw = &adapter->hw;
	u32 rctl;

	if (hw->media_type == e1000_media_type_fiber ||
	    hw->media_type == e1000_media_type_internal_serdes) {
	if (hw->phy.media_type == e1000_media_type_fiber ||
	    hw->phy.media_type == e1000_media_type_internal_serdes) {
		switch (hw->mac.type) {
		case e1000_80003es2lan:
			return e1000_set_es2lan_mac_loopback(adapter);
@@ -1349,7 +1351,7 @@ static int e1000_setup_loopback_test(struct e1000_adapter *adapter)
			ew32(RCTL, rctl);
			return 0;
		}
	} else if (hw->media_type == e1000_media_type_copper) {
	} else if (hw->phy.media_type == e1000_media_type_copper) {
		return e1000_integrated_phy_loopback(adapter);
	}

@@ -1368,8 +1370,8 @@ static void e1000_loopback_cleanup(struct e1000_adapter *adapter)

	switch (hw->mac.type) {
	case e1000_80003es2lan:
		if (hw->media_type == e1000_media_type_fiber ||
		    hw->media_type == e1000_media_type_internal_serdes) {
		if (hw->phy.media_type == e1000_media_type_fiber ||
		    hw->phy.media_type == e1000_media_type_internal_serdes) {
			/* restore CTRL_EXT, stealing space from tx_fifo_head */
			ew32(CTRL_EXT, adapter->tx_fifo_head);
			adapter->tx_fifo_head = 0;
@@ -1377,8 +1379,8 @@ static void e1000_loopback_cleanup(struct e1000_adapter *adapter)
		/* fall through */
	case e1000_82571:
	case e1000_82572:
		if (hw->media_type == e1000_media_type_fiber ||
		    hw->media_type == e1000_media_type_internal_serdes) {
		if (hw->phy.media_type == e1000_media_type_fiber ||
		    hw->phy.media_type == e1000_media_type_internal_serdes) {
#define E1000_SERDES_LB_OFF 0x400
			ew32(SCTL, E1000_SERDES_LB_OFF);
			msleep(10);
@@ -1528,7 +1530,7 @@ static int e1000_link_test(struct e1000_adapter *adapter, u64 *data)
	struct e1000_hw *hw = &adapter->hw;

	*data = 0;
	if (hw->media_type == e1000_media_type_internal_serdes) {
	if (hw->phy.media_type == e1000_media_type_internal_serdes) {
		int i = 0;
		hw->mac.serdes_has_link = 0;

@@ -1624,9 +1626,9 @@ static void e1000_diag_test(struct net_device *netdev,
		adapter->hw.mac.autoneg = autoneg;

		/* force this routine to wait until autoneg complete/timeout */
		adapter->hw.phy.wait_for_link = 1;
		adapter->hw.phy.autoneg_wait_to_complete = 1;
		e1000e_reset(adapter);
		adapter->hw.phy.wait_for_link = 0;
		adapter->hw.phy.autoneg_wait_to_complete = 0;

		clear_bit(__E1000_TESTING, &adapter->state);
		if (if_running)
+15 −11
Original line number Diff line number Diff line
@@ -400,7 +400,7 @@ enum e1000_rev_polarity{
	e1000_rev_polarity_undefined = 0xFF
};

enum e1000_fc_mode {
enum e1000_fc_type {
	e1000_fc_none = 0,
	e1000_fc_rx_pause,
	e1000_fc_tx_pause,
@@ -727,16 +727,12 @@ struct e1000_mac_info {
	u8 perm_addr[6];

	enum e1000_mac_type type;
	enum e1000_fc_mode  fc;
	enum e1000_fc_mode  original_fc;

	u32 collision_delta;
	u32 ledctl_default;
	u32 ledctl_mode1;
	u32 ledctl_mode2;
	u32 max_frame_size;
	u32 mc_filter_type;
	u32 min_frame_size;
	u32 tx_packet_delta;
	u32 txcw;

@@ -747,9 +743,6 @@ struct e1000_mac_info {
	u16 ifs_step_size;
	u16 mta_reg_count;
	u16 rar_entry_count;
	u16 fc_high_water;
	u16 fc_low_water;
	u16 fc_pause_time;

	u8  forced_speed_duplex;

@@ -779,6 +772,8 @@ struct e1000_phy_info {
	u32 reset_delay_us; /* in usec */
	u32 revision;

	enum e1000_media_type media_type;

	u16 autoneg_advertised;
	u16 autoneg_mask;
	u16 cable_length;
@@ -791,7 +786,7 @@ struct e1000_phy_info {
	bool is_mdix;
	bool polarity_correction;
	bool speed_downgraded;
	bool wait_for_link;
	bool autoneg_wait_to_complete;
};

struct e1000_nvm_info {
@@ -816,6 +811,16 @@ struct e1000_bus_info {
	u16 func;
};

struct e1000_fc_info {
	u32 high_water;          /* Flow control high-water mark */
	u32 low_water;           /* Flow control low-water mark */
	u16 pause_time;          /* Flow control pause timer */
	bool send_xon;           /* Flow control send XON */
	bool strict_ieee;        /* Strict IEEE mode */
	enum e1000_fc_type type; /* Type of flow control */
	enum e1000_fc_type original_type;
};

struct e1000_dev_spec_82571 {
	bool laa_is_present;
	bool alt_mac_addr_is_present;
@@ -840,6 +845,7 @@ struct e1000_hw {
	u8 __iomem *flash_address;

	struct e1000_mac_info  mac;
	struct e1000_fc_info   fc;
	struct e1000_phy_info  phy;
	struct e1000_nvm_info  nvm;
	struct e1000_bus_info  bus;
@@ -849,8 +855,6 @@ struct e1000_hw {
		struct e1000_dev_spec_82571	e82571;
		struct e1000_dev_spec_ich8lan	ich8lan;
	} dev_spec;

	enum e1000_media_type media_type;
};

#ifdef DEBUG
Loading