igb: Add Support for new i210/i211 devices.
This patch adds new initialization functions and device support for i210 and i211 devices. Signed-off-by: Carolyn Wyborny <carolyn.wyborny@intel.com> Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
		
							parent
							
								
									da02cde1c1
								
							
						
					
					
						commit
						f96a8a0b78
					
				| @ -33,6 +33,7 @@ | ||||
| obj-$(CONFIG_IGB) += igb.o | ||||
| 
 | ||||
| igb-objs := igb_main.o igb_ethtool.o e1000_82575.o \
 | ||||
| 	    e1000_mac.o e1000_nvm.o e1000_phy.o e1000_mbx.o | ||||
| 	    e1000_mac.o e1000_nvm.o e1000_phy.o e1000_mbx.o \
 | ||||
| 	    e1000_i210.o | ||||
| 
 | ||||
| igb-$(CONFIG_IGB_PTP) += igb_ptp.o | ||||
|  | ||||
| @ -36,6 +36,7 @@ | ||||
| 
 | ||||
| #include "e1000_mac.h" | ||||
| #include "e1000_82575.h" | ||||
| #include "e1000_i210.h" | ||||
| 
 | ||||
| static s32  igb_get_invariants_82575(struct e1000_hw *); | ||||
| static s32  igb_acquire_phy_82575(struct e1000_hw *); | ||||
| @ -98,6 +99,8 @@ static bool igb_sgmii_uses_mdio_82575(struct e1000_hw *hw) | ||||
| 		break; | ||||
| 	case e1000_82580: | ||||
| 	case e1000_i350: | ||||
| 	case e1000_i210: | ||||
| 	case e1000_i211: | ||||
| 		reg = rd32(E1000_MDICNFG); | ||||
| 		ext_mdio = !!(reg & E1000_MDICNFG_EXT_MDIO); | ||||
| 		break; | ||||
| @ -152,6 +155,17 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) | ||||
| 	case E1000_DEV_ID_I350_SGMII: | ||||
| 		mac->type = e1000_i350; | ||||
| 		break; | ||||
| 	case E1000_DEV_ID_I210_COPPER: | ||||
| 	case E1000_DEV_ID_I210_COPPER_OEM1: | ||||
| 	case E1000_DEV_ID_I210_COPPER_IT: | ||||
| 	case E1000_DEV_ID_I210_FIBER: | ||||
| 	case E1000_DEV_ID_I210_SERDES: | ||||
| 	case E1000_DEV_ID_I210_SGMII: | ||||
| 		mac->type = e1000_i210; | ||||
| 		break; | ||||
| 	case E1000_DEV_ID_I211_COPPER: | ||||
| 		mac->type = e1000_i211; | ||||
| 		break; | ||||
| 	default: | ||||
| 		return -E1000_ERR_MAC_INIT; | ||||
| 		break; | ||||
| @ -184,26 +198,44 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) | ||||
| 	/* Set mta register count */ | ||||
| 	mac->mta_reg_count = 128; | ||||
| 	/* Set rar entry count */ | ||||
| 	mac->rar_entry_count = E1000_RAR_ENTRIES_82575; | ||||
| 	if (mac->type == e1000_82576) | ||||
| 	switch (mac->type) { | ||||
| 	case e1000_82576: | ||||
| 		mac->rar_entry_count = E1000_RAR_ENTRIES_82576; | ||||
| 	if (mac->type == e1000_82580) | ||||
| 		break; | ||||
| 	case e1000_82580: | ||||
| 		mac->rar_entry_count = E1000_RAR_ENTRIES_82580; | ||||
| 	if (mac->type == e1000_i350) | ||||
| 		break; | ||||
| 	case e1000_i350: | ||||
| 	case e1000_i210: | ||||
| 	case e1000_i211: | ||||
| 		mac->rar_entry_count = E1000_RAR_ENTRIES_I350; | ||||
| 		break; | ||||
| 	default: | ||||
| 		mac->rar_entry_count = E1000_RAR_ENTRIES_82575; | ||||
| 		break; | ||||
| 	} | ||||
| 	/* reset */ | ||||
| 	if (mac->type >= e1000_82580) | ||||
| 		mac->ops.reset_hw = igb_reset_hw_82580; | ||||
| 	else | ||||
| 		mac->ops.reset_hw = igb_reset_hw_82575; | ||||
| 
 | ||||
| 	if (mac->type >= e1000_i210) { | ||||
| 		mac->ops.acquire_swfw_sync = igb_acquire_swfw_sync_i210; | ||||
| 		mac->ops.release_swfw_sync = igb_release_swfw_sync_i210; | ||||
| 	} else { | ||||
| 		mac->ops.acquire_swfw_sync = igb_acquire_swfw_sync_82575; | ||||
| 		mac->ops.release_swfw_sync = igb_release_swfw_sync_82575; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Set if part includes ASF firmware */ | ||||
| 	mac->asf_firmware_present = true; | ||||
| 	/* Set if manageability features are enabled. */ | ||||
| 	mac->arc_subsystem_valid = | ||||
| 		(rd32(E1000_FWSM) & E1000_FWSM_MODE_MASK) | ||||
| 			? true : false; | ||||
| 	/* enable EEE on i350 parts */ | ||||
| 	if (mac->type == e1000_i350) | ||||
| 	/* enable EEE on i350 parts and later parts */ | ||||
| 	if (mac->type >= e1000_i350) | ||||
| 		dev_spec->eee_disable = false; | ||||
| 	else | ||||
| 		dev_spec->eee_disable = true; | ||||
| @ -215,26 +247,6 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) | ||||
| 
 | ||||
| 	/* NVM initialization */ | ||||
| 	eecd = rd32(E1000_EECD); | ||||
| 
 | ||||
| 	nvm->opcode_bits        = 8; | ||||
| 	nvm->delay_usec         = 1; | ||||
| 	switch (nvm->override) { | ||||
| 	case e1000_nvm_override_spi_large: | ||||
| 		nvm->page_size    = 32; | ||||
| 		nvm->address_bits = 16; | ||||
| 		break; | ||||
| 	case e1000_nvm_override_spi_small: | ||||
| 		nvm->page_size    = 8; | ||||
| 		nvm->address_bits = 8; | ||||
| 		break; | ||||
| 	default: | ||||
| 		nvm->page_size    = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; | ||||
| 		nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8; | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	nvm->type = e1000_nvm_eeprom_spi; | ||||
| 
 | ||||
| 	size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >> | ||||
| 		     E1000_EECD_SIZE_EX_SHIFT); | ||||
| 
 | ||||
| @ -244,6 +256,33 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) | ||||
| 	 */ | ||||
| 	size += NVM_WORD_SIZE_BASE_SHIFT; | ||||
| 
 | ||||
| 	nvm->word_size = 1 << size; | ||||
| 	if (hw->mac.type < e1000_i210) { | ||||
| 		nvm->opcode_bits        = 8; | ||||
| 		nvm->delay_usec         = 1; | ||||
| 		switch (nvm->override) { | ||||
| 		case e1000_nvm_override_spi_large: | ||||
| 			nvm->page_size    = 32; | ||||
| 			nvm->address_bits = 16; | ||||
| 			break; | ||||
| 		case e1000_nvm_override_spi_small: | ||||
| 			nvm->page_size    = 8; | ||||
| 			nvm->address_bits = 8; | ||||
| 			break; | ||||
| 		default: | ||||
| 			nvm->page_size    = eecd | ||||
| 				& E1000_EECD_ADDR_BITS ? 32 : 8; | ||||
| 			nvm->address_bits = eecd | ||||
| 				& E1000_EECD_ADDR_BITS ? 16 : 8; | ||||
| 			break; | ||||
| 		} | ||||
| 		if (nvm->word_size == (1 << 15)) | ||||
| 			nvm->page_size = 128; | ||||
| 
 | ||||
| 		nvm->type = e1000_nvm_eeprom_spi; | ||||
| 	} else | ||||
| 		nvm->type = e1000_nvm_flash_hw; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Check for invalid size | ||||
| 	 */ | ||||
| @ -251,32 +290,60 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) | ||||
| 		pr_notice("The NVM size is not valid, defaulting to 32K\n"); | ||||
| 		size = 15; | ||||
| 	} | ||||
| 	nvm->word_size = 1 << size; | ||||
| 	if (nvm->word_size == (1 << 15)) | ||||
| 		nvm->page_size = 128; | ||||
| 
 | ||||
| 	/* NVM Function Pointers */ | ||||
| 	nvm->ops.acquire = igb_acquire_nvm_82575; | ||||
| 	if (nvm->word_size < (1 << 15)) | ||||
| 		nvm->ops.read = igb_read_nvm_eerd; | ||||
| 	else | ||||
| 		nvm->ops.read = igb_read_nvm_spi; | ||||
| 
 | ||||
| 	nvm->ops.release = igb_release_nvm_82575; | ||||
| 	switch (hw->mac.type) { | ||||
| 	case e1000_82580: | ||||
| 		nvm->ops.validate = igb_validate_nvm_checksum_82580; | ||||
| 		nvm->ops.update = igb_update_nvm_checksum_82580; | ||||
| 		nvm->ops.acquire = igb_acquire_nvm_82575; | ||||
| 		nvm->ops.release = igb_release_nvm_82575; | ||||
| 		if (nvm->word_size < (1 << 15)) | ||||
| 			nvm->ops.read = igb_read_nvm_eerd; | ||||
| 		else | ||||
| 			nvm->ops.read = igb_read_nvm_spi; | ||||
| 		nvm->ops.write = igb_write_nvm_spi; | ||||
| 		break; | ||||
| 	case e1000_i350: | ||||
| 		nvm->ops.validate = igb_validate_nvm_checksum_i350; | ||||
| 		nvm->ops.update = igb_update_nvm_checksum_i350; | ||||
| 		nvm->ops.acquire = igb_acquire_nvm_82575; | ||||
| 		nvm->ops.release = igb_release_nvm_82575; | ||||
| 		if (nvm->word_size < (1 << 15)) | ||||
| 			nvm->ops.read = igb_read_nvm_eerd; | ||||
| 		else | ||||
| 			nvm->ops.read = igb_read_nvm_spi; | ||||
| 		nvm->ops.write = igb_write_nvm_spi; | ||||
| 		break; | ||||
| 	case e1000_i210: | ||||
| 		nvm->ops.validate = igb_validate_nvm_checksum_i210; | ||||
| 		nvm->ops.update   = igb_update_nvm_checksum_i210; | ||||
| 		nvm->ops.acquire = igb_acquire_nvm_i210; | ||||
| 		nvm->ops.release = igb_release_nvm_i210; | ||||
| 		nvm->ops.read    = igb_read_nvm_srrd_i210; | ||||
| 		nvm->ops.valid_led_default = igb_valid_led_default_i210; | ||||
| 		break; | ||||
| 	case e1000_i211: | ||||
| 		nvm->ops.acquire  = igb_acquire_nvm_i210; | ||||
| 		nvm->ops.release  = igb_release_nvm_i210; | ||||
| 		nvm->ops.read     = igb_read_nvm_i211; | ||||
| 		nvm->ops.valid_led_default = igb_valid_led_default_i210; | ||||
| 		nvm->ops.validate = NULL; | ||||
| 		nvm->ops.update   = NULL; | ||||
| 		nvm->ops.write    = NULL; | ||||
| 		break; | ||||
| 	default: | ||||
| 		nvm->ops.validate = igb_validate_nvm_checksum; | ||||
| 		nvm->ops.update = igb_update_nvm_checksum; | ||||
| 		nvm->ops.acquire = igb_acquire_nvm_82575; | ||||
| 		nvm->ops.release = igb_release_nvm_82575; | ||||
| 		if (nvm->word_size < (1 << 15)) | ||||
| 			nvm->ops.read = igb_read_nvm_eerd; | ||||
| 		else | ||||
| 			nvm->ops.read = igb_read_nvm_spi; | ||||
| 		nvm->ops.write = igb_write_nvm_spi; | ||||
| 		break; | ||||
| 	} | ||||
| 	nvm->ops.write = igb_write_nvm_spi; | ||||
| 
 | ||||
| 	/* if part supports SR-IOV then initialize mailbox parameters */ | ||||
| 	switch (mac->type) { | ||||
| @ -314,9 +381,13 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) | ||||
| 	if (igb_sgmii_active_82575(hw) && !igb_sgmii_uses_mdio_82575(hw)) { | ||||
| 		phy->ops.read_reg   = igb_read_phy_reg_sgmii_82575; | ||||
| 		phy->ops.write_reg  = igb_write_phy_reg_sgmii_82575; | ||||
| 	} else if (hw->mac.type >= e1000_82580) { | ||||
| 	} else if ((hw->mac.type == e1000_82580) | ||||
| 		|| (hw->mac.type == e1000_i350)) { | ||||
| 		phy->ops.read_reg   = igb_read_phy_reg_82580; | ||||
| 		phy->ops.write_reg  = igb_write_phy_reg_82580; | ||||
| 	} else if (hw->phy.type >= e1000_phy_i210) { | ||||
| 		phy->ops.read_reg   = igb_read_phy_reg_gs40g; | ||||
| 		phy->ops.write_reg  = igb_write_phy_reg_gs40g; | ||||
| 	} else { | ||||
| 		phy->ops.read_reg   = igb_read_phy_reg_igp; | ||||
| 		phy->ops.write_reg  = igb_write_phy_reg_igp; | ||||
| @ -345,6 +416,14 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) | ||||
| 		else | ||||
| 			phy->ops.get_cable_length = igb_get_cable_length_m88; | ||||
| 
 | ||||
| 		if (phy->id == I210_I_PHY_ID) { | ||||
| 			phy->ops.get_cable_length = | ||||
| 					 igb_get_cable_length_m88_gen2; | ||||
| 			phy->ops.set_d0_lplu_state = | ||||
| 					igb_set_d0_lplu_state_82580; | ||||
| 			phy->ops.set_d3_lplu_state = | ||||
| 					igb_set_d3_lplu_state_82580; | ||||
| 		} | ||||
| 		phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_m88; | ||||
| 		break; | ||||
| 	case IGP03E1000_E_PHY_ID: | ||||
| @ -364,6 +443,15 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) | ||||
| 		phy->ops.set_d0_lplu_state  = igb_set_d0_lplu_state_82580; | ||||
| 		phy->ops.set_d3_lplu_state  = igb_set_d3_lplu_state_82580; | ||||
| 		break; | ||||
| 	case I210_I_PHY_ID: | ||||
| 		phy->type                   = e1000_phy_i210; | ||||
| 		phy->ops.get_phy_info       = igb_get_phy_info_m88; | ||||
| 		phy->ops.check_polarity     = igb_check_polarity_m88; | ||||
| 		phy->ops.get_cable_length   = igb_get_cable_length_m88_gen2; | ||||
| 		phy->ops.set_d0_lplu_state  = igb_set_d0_lplu_state_82580; | ||||
| 		phy->ops.set_d3_lplu_state  = igb_set_d3_lplu_state_82580; | ||||
| 		phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_m88; | ||||
| 		break; | ||||
| 	default: | ||||
| 		return -E1000_ERR_PHY; | ||||
| 	} | ||||
| @ -389,7 +477,7 @@ static s32 igb_acquire_phy_82575(struct e1000_hw *hw) | ||||
| 	else if (hw->bus.func == E1000_FUNC_3) | ||||
| 		mask = E1000_SWFW_PHY3_SM; | ||||
| 
 | ||||
| 	return igb_acquire_swfw_sync_82575(hw, mask); | ||||
| 	return hw->mac.ops.acquire_swfw_sync(hw, mask); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
| @ -410,7 +498,7 @@ static void igb_release_phy_82575(struct e1000_hw *hw) | ||||
| 	else if (hw->bus.func == E1000_FUNC_3) | ||||
| 		mask = E1000_SWFW_PHY3_SM; | ||||
| 
 | ||||
| 	igb_release_swfw_sync_82575(hw, mask); | ||||
| 	hw->mac.ops.release_swfw_sync(hw, mask); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
| @ -514,6 +602,8 @@ static s32 igb_get_phy_id_82575(struct e1000_hw *hw) | ||||
| 			break; | ||||
| 		case e1000_82580: | ||||
| 		case e1000_i350: | ||||
| 		case e1000_i210: | ||||
| 		case e1000_i211: | ||||
| 			mdic = rd32(E1000_MDICNFG); | ||||
| 			mdic &= E1000_MDICNFG_PHY_MASK; | ||||
| 			phy->addr = mdic >> E1000_MDICNFG_PHY_SHIFT; | ||||
| @ -780,14 +870,14 @@ static s32 igb_acquire_nvm_82575(struct e1000_hw *hw) | ||||
| { | ||||
| 	s32 ret_val; | ||||
| 
 | ||||
| 	ret_val = igb_acquire_swfw_sync_82575(hw, E1000_SWFW_EEP_SM); | ||||
| 	ret_val = hw->mac.ops.acquire_swfw_sync(hw, E1000_SWFW_EEP_SM); | ||||
| 	if (ret_val) | ||||
| 		goto out; | ||||
| 
 | ||||
| 	ret_val = igb_acquire_nvm(hw); | ||||
| 
 | ||||
| 	if (ret_val) | ||||
| 		igb_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM); | ||||
| 		hw->mac.ops.release_swfw_sync(hw, E1000_SWFW_EEP_SM); | ||||
| 
 | ||||
| out: | ||||
| 	return ret_val; | ||||
| @ -803,7 +893,7 @@ out: | ||||
| static void igb_release_nvm_82575(struct e1000_hw *hw) | ||||
| { | ||||
| 	igb_release_nvm(hw); | ||||
| 	igb_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM); | ||||
| 	hw->mac.ops.release_swfw_sync(hw, E1000_SWFW_EEP_SM); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
| @ -1174,7 +1264,6 @@ static s32 igb_init_hw_82575(struct e1000_hw *hw) | ||||
| 	 * is no link. | ||||
| 	 */ | ||||
| 	igb_clear_hw_cntrs_82575(hw); | ||||
| 
 | ||||
| 	return ret_val; | ||||
| } | ||||
| 
 | ||||
| @ -1211,6 +1300,7 @@ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw) | ||||
| 		} | ||||
| 	} | ||||
| 	switch (hw->phy.type) { | ||||
| 	case e1000_phy_i210: | ||||
| 	case e1000_phy_m88: | ||||
| 		if (hw->phy.id == I347AT4_E_PHY_ID || | ||||
| 		    hw->phy.id == M88E1112_E_PHY_ID) | ||||
| @ -1851,7 +1941,7 @@ static s32 igb_reset_hw_82580(struct e1000_hw *hw) | ||||
| 
 | ||||
| 	/* Determine whether or not a global dev reset is requested */ | ||||
| 	if (global_device_reset && | ||||
| 		igb_acquire_swfw_sync_82575(hw, swmbsw_mask)) | ||||
| 		hw->mac.ops.acquire_swfw_sync(hw, swmbsw_mask)) | ||||
| 			global_device_reset = false; | ||||
| 
 | ||||
| 	if (global_device_reset && | ||||
| @ -1897,7 +1987,7 @@ static s32 igb_reset_hw_82580(struct e1000_hw *hw) | ||||
| 
 | ||||
| 	/* Release semaphore */ | ||||
| 	if (global_device_reset) | ||||
| 		igb_release_swfw_sync_82575(hw, swmbsw_mask); | ||||
| 		hw->mac.ops.release_swfw_sync(hw, swmbsw_mask); | ||||
| 
 | ||||
| 	return ret_val; | ||||
| } | ||||
|  | ||||
| @ -55,10 +55,11 @@ extern void igb_rx_fifo_flush_82575(struct e1000_hw *hw); | ||||
| #define E1000_SRRCTL_DROP_EN                            0x80000000 | ||||
| #define E1000_SRRCTL_TIMESTAMP                          0x40000000 | ||||
| 
 | ||||
| 
 | ||||
| #define E1000_MRQC_ENABLE_RSS_4Q            0x00000002 | ||||
| #define E1000_MRQC_ENABLE_VMDQ              0x00000003 | ||||
| #define E1000_MRQC_ENABLE_VMDQ_RSS_2Q       0x00000005 | ||||
| #define E1000_MRQC_RSS_FIELD_IPV4_UDP       0x00400000 | ||||
| #define E1000_MRQC_ENABLE_VMDQ_RSS_2Q       0x00000005 | ||||
| #define E1000_MRQC_RSS_FIELD_IPV6_UDP       0x00800000 | ||||
| #define E1000_MRQC_RSS_FIELD_IPV6_UDP_EX    0x01000000 | ||||
| 
 | ||||
|  | ||||
| @ -458,6 +458,7 @@ | ||||
| #define E1000_ERR_INVALID_ARGUMENT  16 | ||||
| #define E1000_ERR_NO_SPACE          17 | ||||
| #define E1000_ERR_NVM_PBA_SECTION   18 | ||||
| #define E1000_ERR_INVM_VALUE_NOT_FOUND	19 | ||||
| 
 | ||||
| /* Loop limit on how long we wait for auto-negotiation to complete */ | ||||
| #define COPPER_LINK_UP_LIMIT              10 | ||||
| @ -595,6 +596,25 @@ | ||||
| #define E1000_EECD_AUTO_RD          0x00000200  /* NVM Auto Read done */ | ||||
| #define E1000_EECD_SIZE_EX_MASK     0x00007800  /* NVM Size */ | ||||
| #define E1000_EECD_SIZE_EX_SHIFT     11 | ||||
| #define E1000_EECD_FLUPD_I210		0x00800000 /* Update FLASH */ | ||||
| #define E1000_EECD_FLUDONE_I210		0x04000000 /* Update FLASH done*/ | ||||
| #define E1000_FLUDONE_ATTEMPTS		20000 | ||||
| #define E1000_EERD_EEWR_MAX_COUNT	512 /* buffered EEPROM words rw */ | ||||
| #define E1000_I210_FIFO_SEL_RX		0x00 | ||||
| #define E1000_I210_FIFO_SEL_TX_QAV(_i)	(0x02 + (_i)) | ||||
| #define E1000_I210_FIFO_SEL_TX_LEGACY	E1000_I210_FIFO_SEL_TX_QAV(0) | ||||
| #define E1000_I210_FIFO_SEL_BMC2OS_TX	0x06 | ||||
| #define E1000_I210_FIFO_SEL_BMC2OS_RX	0x01 | ||||
| #define E1000_EECD_FLUPD_I210		0x00800000 /* Update FLASH */ | ||||
| #define E1000_EECD_FLUDONE_I210		0x04000000 /* Update FLASH done*/ | ||||
| #define E1000_FLUDONE_ATTEMPTS		20000 | ||||
| #define E1000_EERD_EEWR_MAX_COUNT	512 /* buffered EEPROM words rw */ | ||||
| #define E1000_I210_FIFO_SEL_RX		0x00 | ||||
| #define E1000_I210_FIFO_SEL_TX_QAV(_i)	(0x02 + (_i)) | ||||
| #define E1000_I210_FIFO_SEL_TX_LEGACY	E1000_I210_FIFO_SEL_TX_QAV(0) | ||||
| #define E1000_I210_FIFO_SEL_BMC2OS_TX	0x06 | ||||
| #define E1000_I210_FIFO_SEL_BMC2OS_RX	0x01 | ||||
| 
 | ||||
| 
 | ||||
| /* Offset to data in NVM read/write registers */ | ||||
| #define E1000_NVM_RW_REG_DATA   16 | ||||
| @ -613,6 +633,16 @@ | ||||
| #define NVM_CHECKSUM_REG           0x003F | ||||
| #define NVM_COMPATIBILITY_REG_3    0x0003 | ||||
| #define NVM_COMPATIBILITY_BIT_MASK 0x8000 | ||||
| #define NVM_MAC_ADDR               0x0000 | ||||
| #define NVM_SUB_DEV_ID             0x000B | ||||
| #define NVM_SUB_VEN_ID             0x000C | ||||
| #define NVM_DEV_ID                 0x000D | ||||
| #define NVM_VEN_ID                 0x000E | ||||
| #define NVM_INIT_CTRL_2            0x000F | ||||
| #define NVM_INIT_CTRL_4            0x0013 | ||||
| #define NVM_LED_1_CFG              0x001C | ||||
| #define NVM_LED_0_2_CFG            0x001F | ||||
| 
 | ||||
| 
 | ||||
| #define E1000_NVM_CFG_DONE_PORT_0  0x040000 /* MNG config cycle done */ | ||||
| #define E1000_NVM_CFG_DONE_PORT_1  0x080000 /* ...for second port */ | ||||
| @ -639,6 +669,7 @@ | ||||
| 
 | ||||
| #define NVM_PBA_OFFSET_0           8 | ||||
| #define NVM_PBA_OFFSET_1           9 | ||||
| #define NVM_RESERVED_WORD		0xFFFF | ||||
| #define NVM_PBA_PTR_GUARD          0xFAFA | ||||
| #define NVM_WORD_SIZE_BASE_SHIFT   6 | ||||
| 
 | ||||
| @ -696,6 +727,7 @@ | ||||
| #define I82580_I_PHY_ID      0x015403A0 | ||||
| #define I350_I_PHY_ID        0x015403B0 | ||||
| #define M88_VENDOR           0x0141 | ||||
| #define I210_I_PHY_ID        0x01410C00 | ||||
| 
 | ||||
| /* M88E1000 Specific Registers */ | ||||
| #define M88E1000_PHY_SPEC_CTRL     0x10  /* PHY Specific Control Register */ | ||||
| @ -815,6 +847,7 @@ | ||||
| #define E1000_IPCNFG_EEE_100M_AN     0x00000004  /* EEE Enable 100M AN */ | ||||
| #define E1000_EEER_TX_LPI_EN         0x00010000  /* EEE Tx LPI Enable */ | ||||
| #define E1000_EEER_RX_LPI_EN         0x00020000  /* EEE Rx LPI Enable */ | ||||
| #define E1000_EEER_FRC_AN            0x10000000 /* Enable EEE in loopback */ | ||||
| #define E1000_EEER_LPI_FC            0x00040000  /* EEE Enable on FC */ | ||||
| 
 | ||||
| /* SerDes Control */ | ||||
|  | ||||
| @ -63,6 +63,13 @@ struct e1000_hw; | ||||
| #define E1000_DEV_ID_I350_FIBER               0x1522 | ||||
| #define E1000_DEV_ID_I350_SERDES              0x1523 | ||||
| #define E1000_DEV_ID_I350_SGMII               0x1524 | ||||
| #define E1000_DEV_ID_I210_COPPER		0x1533 | ||||
| #define E1000_DEV_ID_I210_COPPER_OEM1		0x1534 | ||||
| #define E1000_DEV_ID_I210_COPPER_IT		0x1535 | ||||
| #define E1000_DEV_ID_I210_FIBER			0x1536 | ||||
| #define E1000_DEV_ID_I210_SERDES		0x1537 | ||||
| #define E1000_DEV_ID_I210_SGMII			0x1538 | ||||
| #define E1000_DEV_ID_I211_COPPER		0x1539 | ||||
| 
 | ||||
| #define E1000_REVISION_2 2 | ||||
| #define E1000_REVISION_4 4 | ||||
| @ -83,6 +90,8 @@ enum e1000_mac_type { | ||||
| 	e1000_82576, | ||||
| 	e1000_82580, | ||||
| 	e1000_i350, | ||||
| 	e1000_i210, | ||||
| 	e1000_i211, | ||||
| 	e1000_num_macs  /* List is 1-based, so subtract 1 for true count. */ | ||||
| }; | ||||
| 
 | ||||
| @ -117,6 +126,7 @@ enum e1000_phy_type { | ||||
| 	e1000_phy_igp_3, | ||||
| 	e1000_phy_ife, | ||||
| 	e1000_phy_82580, | ||||
| 	e1000_phy_i210, | ||||
| }; | ||||
| 
 | ||||
| enum e1000_bus_type { | ||||
| @ -313,6 +323,9 @@ struct e1000_mac_operations { | ||||
| 	void (*rar_set)(struct e1000_hw *, u8 *, u32); | ||||
| 	s32  (*read_mac_addr)(struct e1000_hw *); | ||||
| 	s32  (*get_speed_and_duplex)(struct e1000_hw *, u16 *, u16 *); | ||||
| 	s32  (*acquire_swfw_sync)(struct e1000_hw *, u16); | ||||
| 	void (*release_swfw_sync)(struct e1000_hw *, u16); | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| struct e1000_phy_operations { | ||||
| @ -338,6 +351,7 @@ struct e1000_nvm_operations { | ||||
| 	s32  (*write)(struct e1000_hw *, u16, u16, u16 *); | ||||
| 	s32  (*update)(struct e1000_hw *); | ||||
| 	s32  (*validate)(struct e1000_hw *); | ||||
| 	s32  (*valid_led_default)(struct e1000_hw *, u16 *); | ||||
| }; | ||||
| 
 | ||||
| struct e1000_info { | ||||
|  | ||||
							
								
								
									
										603
									
								
								drivers/net/ethernet/intel/igb/e1000_i210.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										603
									
								
								drivers/net/ethernet/intel/igb/e1000_i210.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,603 @@ | ||||
| /*******************************************************************************
 | ||||
| 
 | ||||
|   Intel(R) Gigabit Ethernet Linux driver | ||||
|   Copyright(c) 2007-2012 Intel Corporation. | ||||
| 
 | ||||
|   This program is free software; you can redistribute it and/or modify it | ||||
|   under the terms and conditions of the GNU General Public License, | ||||
|   version 2, as published by the Free Software Foundation. | ||||
| 
 | ||||
|   This program is distributed in the hope it will be useful, but WITHOUT | ||||
|   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||||
|   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for | ||||
|   more details. | ||||
| 
 | ||||
|   You should have received a copy of the GNU General Public License along with | ||||
|   this program; if not, write to the Free Software Foundation, Inc., | ||||
|   51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
| 
 | ||||
|   The full GNU General Public License is included in this distribution in | ||||
|   the file called "COPYING". | ||||
| 
 | ||||
|   Contact Information: | ||||
|   e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> | ||||
|   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||||
| 
 | ||||
| ******************************************************************************/ | ||||
| 
 | ||||
| /* e1000_i210
 | ||||
|  * e1000_i211 | ||||
|  */ | ||||
| 
 | ||||
| #include <linux/types.h> | ||||
| #include <linux/if_ether.h> | ||||
| 
 | ||||
| #include "e1000_hw.h" | ||||
| #include "e1000_i210.h" | ||||
| 
 | ||||
| static s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw); | ||||
| static void igb_put_hw_semaphore_i210(struct e1000_hw *hw); | ||||
| static s32 igb_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words, | ||||
| 				u16 *data); | ||||
| static s32 igb_pool_flash_update_done_i210(struct e1000_hw *hw); | ||||
| 
 | ||||
| /**
 | ||||
|  *  igb_acquire_nvm_i210 - Request for access to EEPROM | ||||
|  *  @hw: pointer to the HW structure | ||||
|  * | ||||
|  *  Acquire the necessary semaphores for exclusive access to the EEPROM. | ||||
|  *  Set the EEPROM access request bit and wait for EEPROM access grant bit. | ||||
|  *  Return successful if access grant bit set, else clear the request for | ||||
|  *  EEPROM access and return -E1000_ERR_NVM (-1). | ||||
|  **/ | ||||
| s32 igb_acquire_nvm_i210(struct e1000_hw *hw) | ||||
| { | ||||
| 	return igb_acquire_swfw_sync_i210(hw, E1000_SWFW_EEP_SM); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  *  igb_release_nvm_i210 - Release exclusive access to EEPROM | ||||
|  *  @hw: pointer to the HW structure | ||||
|  * | ||||
|  *  Stop any current commands to the EEPROM and clear the EEPROM request bit, | ||||
|  *  then release the semaphores acquired. | ||||
|  **/ | ||||
| void igb_release_nvm_i210(struct e1000_hw *hw) | ||||
| { | ||||
| 	igb_release_swfw_sync_i210(hw, E1000_SWFW_EEP_SM); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  *  igb_acquire_swfw_sync_i210 - Acquire SW/FW semaphore | ||||
|  *  @hw: pointer to the HW structure | ||||
|  *  @mask: specifies which semaphore to acquire | ||||
|  * | ||||
|  *  Acquire the SW/FW semaphore to access the PHY or NVM.  The mask | ||||
|  *  will also specify which port we're acquiring the lock for. | ||||
|  **/ | ||||
| s32 igb_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask) | ||||
| { | ||||
| 	u32 swfw_sync; | ||||
| 	u32 swmask = mask; | ||||
| 	u32 fwmask = mask << 16; | ||||
| 	s32 ret_val = E1000_SUCCESS; | ||||
| 	s32 i = 0, timeout = 200; /* FIXME: find real value to use here */ | ||||
| 
 | ||||
| 	while (i < timeout) { | ||||
| 		if (igb_get_hw_semaphore_i210(hw)) { | ||||
| 			ret_val = -E1000_ERR_SWFW_SYNC; | ||||
| 			goto out; | ||||
| 		} | ||||
| 
 | ||||
| 		swfw_sync = rd32(E1000_SW_FW_SYNC); | ||||
| 		if (!(swfw_sync & fwmask)) | ||||
| 			break; | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * Firmware currently using resource (fwmask) | ||||
| 		 */ | ||||
| 		igb_put_hw_semaphore_i210(hw); | ||||
| 		mdelay(5); | ||||
| 		i++; | ||||
| 	} | ||||
| 
 | ||||
| 	if (i == timeout) { | ||||
| 		hw_dbg("Driver can't access resource, SW_FW_SYNC timeout.\n"); | ||||
| 		ret_val = -E1000_ERR_SWFW_SYNC; | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	swfw_sync |= swmask; | ||||
| 	wr32(E1000_SW_FW_SYNC, swfw_sync); | ||||
| 
 | ||||
| 	igb_put_hw_semaphore_i210(hw); | ||||
| out: | ||||
| 	return ret_val; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  *  igb_release_swfw_sync_i210 - Release SW/FW semaphore | ||||
|  *  @hw: pointer to the HW structure | ||||
|  *  @mask: specifies which semaphore to acquire | ||||
|  * | ||||
|  *  Release the SW/FW semaphore used to access the PHY or NVM.  The mask | ||||
|  *  will also specify which port we're releasing the lock for. | ||||
|  **/ | ||||
| void igb_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask) | ||||
| { | ||||
| 	u32 swfw_sync; | ||||
| 
 | ||||
| 	while (igb_get_hw_semaphore_i210(hw) != E1000_SUCCESS) | ||||
| 		; /* Empty */ | ||||
| 
 | ||||
| 	swfw_sync = rd32(E1000_SW_FW_SYNC); | ||||
| 	swfw_sync &= ~mask; | ||||
| 	wr32(E1000_SW_FW_SYNC, swfw_sync); | ||||
| 
 | ||||
| 	igb_put_hw_semaphore_i210(hw); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  *  igb_get_hw_semaphore_i210 - Acquire hardware semaphore | ||||
|  *  @hw: pointer to the HW structure | ||||
|  * | ||||
|  *  Acquire the HW semaphore to access the PHY or NVM | ||||
|  **/ | ||||
| static s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw) | ||||
| { | ||||
| 	u32 swsm; | ||||
| 	s32 ret_val = E1000_SUCCESS; | ||||
| 	s32 timeout = hw->nvm.word_size + 1; | ||||
| 	s32 i = 0; | ||||
| 
 | ||||
| 	/* Get the FW semaphore. */ | ||||
| 	for (i = 0; i < timeout; i++) { | ||||
| 		swsm = rd32(E1000_SWSM); | ||||
| 		wr32(E1000_SWSM, swsm | E1000_SWSM_SWESMBI); | ||||
| 
 | ||||
| 		/* Semaphore acquired if bit latched */ | ||||
| 		if (rd32(E1000_SWSM) & E1000_SWSM_SWESMBI) | ||||
| 			break; | ||||
| 
 | ||||
| 		udelay(50); | ||||
| 	} | ||||
| 
 | ||||
| 	if (i == timeout) { | ||||
| 		/* Release semaphores */ | ||||
| 		igb_put_hw_semaphore(hw); | ||||
| 		hw_dbg("Driver can't access the NVM\n"); | ||||
| 		ret_val = -E1000_ERR_NVM; | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| out: | ||||
| 	return ret_val; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  *  igb_put_hw_semaphore_i210 - Release hardware semaphore | ||||
|  *  @hw: pointer to the HW structure | ||||
|  * | ||||
|  *  Release hardware semaphore used to access the PHY or NVM | ||||
|  **/ | ||||
| static void igb_put_hw_semaphore_i210(struct e1000_hw *hw) | ||||
| { | ||||
| 	u32 swsm; | ||||
| 
 | ||||
| 	swsm = rd32(E1000_SWSM); | ||||
| 
 | ||||
| 	swsm &= ~E1000_SWSM_SWESMBI; | ||||
| 
 | ||||
| 	wr32(E1000_SWSM, swsm); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  *  igb_read_nvm_srrd_i210 - Reads Shadow Ram using EERD register | ||||
|  *  @hw: pointer to the HW structure | ||||
|  *  @offset: offset of word in the Shadow Ram to read | ||||
|  *  @words: number of words to read | ||||
|  *  @data: word read from the Shadow Ram | ||||
|  * | ||||
|  *  Reads a 16 bit word from the Shadow Ram using the EERD register. | ||||
|  *  Uses necessary synchronization semaphores. | ||||
|  **/ | ||||
| s32 igb_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words, | ||||
| 			     u16 *data) | ||||
| { | ||||
| 	s32 status = E1000_SUCCESS; | ||||
| 	u16 i, count; | ||||
| 
 | ||||
| 	/* We cannot hold synchronization semaphores for too long,
 | ||||
| 	 * because of forceful takeover procedure. However it is more efficient | ||||
| 	 * to read in bursts than synchronizing access for each word. */ | ||||
| 	for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) { | ||||
| 		count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ? | ||||
| 			E1000_EERD_EEWR_MAX_COUNT : (words - i); | ||||
| 		if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { | ||||
| 			status = igb_read_nvm_eerd(hw, offset, count, | ||||
| 						     data + i); | ||||
| 			hw->nvm.ops.release(hw); | ||||
| 		} else { | ||||
| 			status = E1000_ERR_SWFW_SYNC; | ||||
| 		} | ||||
| 
 | ||||
| 		if (status != E1000_SUCCESS) | ||||
| 			break; | ||||
| 	} | ||||
| 
 | ||||
| 	return status; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  *  igb_write_nvm_srwr_i210 - Write to Shadow RAM using EEWR | ||||
|  *  @hw: pointer to the HW structure | ||||
|  *  @offset: offset within the Shadow RAM to be written to | ||||
|  *  @words: number of words to write | ||||
|  *  @data: 16 bit word(s) to be written to the Shadow RAM | ||||
|  * | ||||
|  *  Writes data to Shadow RAM at offset using EEWR register. | ||||
|  * | ||||
|  *  If e1000_update_nvm_checksum is not called after this function , the | ||||
|  *  data will not be committed to FLASH and also Shadow RAM will most likely | ||||
|  *  contain an invalid checksum. | ||||
|  * | ||||
|  *  If error code is returned, data and Shadow RAM may be inconsistent - buffer | ||||
|  *  partially written. | ||||
|  **/ | ||||
| s32 igb_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words, | ||||
| 			      u16 *data) | ||||
| { | ||||
| 	s32 status = E1000_SUCCESS; | ||||
| 	u16 i, count; | ||||
| 
 | ||||
| 	/* We cannot hold synchronization semaphores for too long,
 | ||||
| 	 * because of forceful takeover procedure. However it is more efficient | ||||
| 	 * to write in bursts than synchronizing access for each word. */ | ||||
| 	for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) { | ||||
| 		count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ? | ||||
| 			E1000_EERD_EEWR_MAX_COUNT : (words - i); | ||||
| 		if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { | ||||
| 			status = igb_write_nvm_srwr(hw, offset, count, | ||||
| 						      data + i); | ||||
| 			hw->nvm.ops.release(hw); | ||||
| 		} else { | ||||
| 			status = E1000_ERR_SWFW_SYNC; | ||||
| 		} | ||||
| 
 | ||||
| 		if (status != E1000_SUCCESS) | ||||
| 			break; | ||||
| 	} | ||||
| 
 | ||||
| 	return status; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  *  igb_write_nvm_srwr - Write to Shadow Ram using EEWR | ||||
|  *  @hw: pointer to the HW structure | ||||
|  *  @offset: offset within the Shadow Ram to be written to | ||||
|  *  @words: number of words to write | ||||
|  *  @data: 16 bit word(s) to be written to the Shadow Ram | ||||
|  * | ||||
|  *  Writes data to Shadow Ram at offset using EEWR register. | ||||
|  * | ||||
|  *  If igb_update_nvm_checksum is not called after this function , the | ||||
|  *  Shadow Ram will most likely contain an invalid checksum. | ||||
|  **/ | ||||
| static s32 igb_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words, | ||||
| 				u16 *data) | ||||
| { | ||||
| 	struct e1000_nvm_info *nvm = &hw->nvm; | ||||
| 	u32 i, k, eewr = 0; | ||||
| 	u32 attempts = 100000; | ||||
| 	s32 ret_val = E1000_SUCCESS; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * A check for invalid values:  offset too large, too many words, | ||||
| 	 * too many words for the offset, and not enough words. | ||||
| 	 */ | ||||
| 	if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || | ||||
| 	    (words == 0)) { | ||||
| 		hw_dbg("nvm parameter(s) out of bounds\n"); | ||||
| 		ret_val = -E1000_ERR_NVM; | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	for (i = 0; i < words; i++) { | ||||
| 		eewr = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) | | ||||
| 			(data[i] << E1000_NVM_RW_REG_DATA) | | ||||
| 			E1000_NVM_RW_REG_START; | ||||
| 
 | ||||
| 		wr32(E1000_SRWR, eewr); | ||||
| 
 | ||||
| 		for (k = 0; k < attempts; k++) { | ||||
| 			if (E1000_NVM_RW_REG_DONE & | ||||
| 			    rd32(E1000_SRWR)) { | ||||
| 				ret_val = E1000_SUCCESS; | ||||
| 				break; | ||||
| 			} | ||||
| 			udelay(5); | ||||
| 	} | ||||
| 
 | ||||
| 		if (ret_val != E1000_SUCCESS) { | ||||
| 			hw_dbg("Shadow RAM write EEWR timed out\n"); | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| out: | ||||
| 	return ret_val; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  *  igb_read_nvm_i211 - Read NVM wrapper function for I211 | ||||
|  *  @hw: pointer to the HW structure | ||||
|  *  @address: the word address (aka eeprom offset) to read | ||||
|  *  @data: pointer to the data read | ||||
|  * | ||||
|  *  Wrapper function to return data formerly found in the NVM. | ||||
|  **/ | ||||
| s32 igb_read_nvm_i211(struct e1000_hw *hw, u16 offset, u16 words, | ||||
| 			       u16 *data) | ||||
| { | ||||
| 	s32 ret_val = E1000_SUCCESS; | ||||
| 
 | ||||
| 	/* Only the MAC addr is required to be present in the iNVM */ | ||||
| 	switch (offset) { | ||||
| 	case NVM_MAC_ADDR: | ||||
| 		ret_val = igb_read_invm_i211(hw, offset, &data[0]); | ||||
| 		ret_val |= igb_read_invm_i211(hw, offset+1, &data[1]); | ||||
| 		ret_val |= igb_read_invm_i211(hw, offset+2, &data[2]); | ||||
| 		if (ret_val != E1000_SUCCESS) | ||||
| 			hw_dbg("MAC Addr not found in iNVM\n"); | ||||
| 		break; | ||||
| 	case NVM_ID_LED_SETTINGS: | ||||
| 	case NVM_INIT_CTRL_2: | ||||
| 	case NVM_INIT_CTRL_4: | ||||
| 	case NVM_LED_1_CFG: | ||||
| 	case NVM_LED_0_2_CFG: | ||||
| 		igb_read_invm_i211(hw, offset, data); | ||||
| 		break; | ||||
| 	case NVM_COMPAT: | ||||
| 		*data = ID_LED_DEFAULT_I210; | ||||
| 		break; | ||||
| 	case NVM_SUB_DEV_ID: | ||||
| 		*data = hw->subsystem_device_id; | ||||
| 		break; | ||||
| 	case NVM_SUB_VEN_ID: | ||||
| 		*data = hw->subsystem_vendor_id; | ||||
| 		break; | ||||
| 	case NVM_DEV_ID: | ||||
| 		*data = hw->device_id; | ||||
| 		break; | ||||
| 	case NVM_VEN_ID: | ||||
| 		*data = hw->vendor_id; | ||||
| 		break; | ||||
| 	default: | ||||
| 		hw_dbg("NVM word 0x%02x is not mapped.\n", offset); | ||||
| 		*data = NVM_RESERVED_WORD; | ||||
| 		break; | ||||
| 	} | ||||
| 	return ret_val; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  *  igb_read_invm_i211 - Reads OTP | ||||
|  *  @hw: pointer to the HW structure | ||||
|  *  @address: the word address (aka eeprom offset) to read | ||||
|  *  @data: pointer to the data read | ||||
|  * | ||||
|  *  Reads 16-bit words from the OTP. Return error when the word is not | ||||
|  *  stored in OTP. | ||||
|  **/ | ||||
| s32 igb_read_invm_i211(struct e1000_hw *hw, u16 address, u16 *data) | ||||
| { | ||||
| 	s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND; | ||||
| 	u32 invm_dword; | ||||
| 	u16 i; | ||||
| 	u8 record_type, word_address; | ||||
| 
 | ||||
| 	for (i = 0; i < E1000_INVM_SIZE; i++) { | ||||
| 		invm_dword = rd32(E1000_INVM_DATA_REG(i)); | ||||
| 		/* Get record type */ | ||||
| 		record_type = INVM_DWORD_TO_RECORD_TYPE(invm_dword); | ||||
| 		if (record_type == E1000_INVM_UNINITIALIZED_STRUCTURE) | ||||
| 			break; | ||||
| 		if (record_type == E1000_INVM_CSR_AUTOLOAD_STRUCTURE) | ||||
| 			i += E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS; | ||||
| 		if (record_type == E1000_INVM_RSA_KEY_SHA256_STRUCTURE) | ||||
| 			i += E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS; | ||||
| 		if (record_type == E1000_INVM_WORD_AUTOLOAD_STRUCTURE) { | ||||
| 			word_address = INVM_DWORD_TO_WORD_ADDRESS(invm_dword); | ||||
| 			if (word_address == (u8)address) { | ||||
| 				*data = INVM_DWORD_TO_WORD_DATA(invm_dword); | ||||
| 				hw_dbg("Read INVM Word 0x%02x = %x", | ||||
| 					  address, *data); | ||||
| 				status = E1000_SUCCESS; | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	if (status != E1000_SUCCESS) | ||||
| 		hw_dbg("Requested word 0x%02x not found in OTP\n", address); | ||||
| 	return status; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  *  igb_validate_nvm_checksum_i210 - Validate EEPROM checksum | ||||
|  *  @hw: pointer to the HW structure | ||||
|  * | ||||
|  *  Calculates the EEPROM checksum by reading/adding each word of the EEPROM | ||||
|  *  and then verifies that the sum of the EEPROM is equal to 0xBABA. | ||||
|  **/ | ||||
| s32 igb_validate_nvm_checksum_i210(struct e1000_hw *hw) | ||||
| { | ||||
| 	s32 status = E1000_SUCCESS; | ||||
| 	s32 (*read_op_ptr)(struct e1000_hw *, u16, u16, u16 *); | ||||
| 
 | ||||
| 	if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * Replace the read function with semaphore grabbing with | ||||
| 		 * the one that skips this for a while. | ||||
| 		 * We have semaphore taken already here. | ||||
| 		 */ | ||||
| 		read_op_ptr = hw->nvm.ops.read; | ||||
| 		hw->nvm.ops.read = igb_read_nvm_eerd; | ||||
| 
 | ||||
| 		status = igb_validate_nvm_checksum(hw); | ||||
| 
 | ||||
| 		/* Revert original read operation. */ | ||||
| 		hw->nvm.ops.read = read_op_ptr; | ||||
| 
 | ||||
| 		hw->nvm.ops.release(hw); | ||||
| 	} else { | ||||
| 		status = E1000_ERR_SWFW_SYNC; | ||||
| 	} | ||||
| 
 | ||||
| 	return status; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  *  igb_update_nvm_checksum_i210 - Update EEPROM checksum | ||||
|  *  @hw: pointer to the HW structure | ||||
|  * | ||||
|  *  Updates the EEPROM checksum by reading/adding each word of the EEPROM | ||||
|  *  up to the checksum.  Then calculates the EEPROM checksum and writes the | ||||
|  *  value to the EEPROM. Next commit EEPROM data onto the Flash. | ||||
|  **/ | ||||
| s32 igb_update_nvm_checksum_i210(struct e1000_hw *hw) | ||||
| { | ||||
| 	s32 ret_val = E1000_SUCCESS; | ||||
| 	u16 checksum = 0; | ||||
| 	u16 i, nvm_data; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Read the first word from the EEPROM. If this times out or fails, do | ||||
| 	 * not continue or we could be in for a very long wait while every | ||||
| 	 * EEPROM read fails | ||||
| 	 */ | ||||
| 	ret_val = igb_read_nvm_eerd(hw, 0, 1, &nvm_data); | ||||
| 	if (ret_val != E1000_SUCCESS) { | ||||
| 		hw_dbg("EEPROM read failed\n"); | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) { | ||||
| 		/*
 | ||||
| 		 * Do not use hw->nvm.ops.write, hw->nvm.ops.read | ||||
| 		 * because we do not want to take the synchronization | ||||
| 		 * semaphores twice here. | ||||
| 		 */ | ||||
| 
 | ||||
| 		for (i = 0; i < NVM_CHECKSUM_REG; i++) { | ||||
| 			ret_val = igb_read_nvm_eerd(hw, i, 1, &nvm_data); | ||||
| 			if (ret_val) { | ||||
| 				hw->nvm.ops.release(hw); | ||||
| 				hw_dbg("NVM Read Error while updating checksum.\n"); | ||||
| 				goto out; | ||||
| 			} | ||||
| 			checksum += nvm_data; | ||||
| 		} | ||||
| 		checksum = (u16) NVM_SUM - checksum; | ||||
| 		ret_val = igb_write_nvm_srwr(hw, NVM_CHECKSUM_REG, 1, | ||||
| 						&checksum); | ||||
| 		if (ret_val != E1000_SUCCESS) { | ||||
| 			hw->nvm.ops.release(hw); | ||||
| 			hw_dbg("NVM Write Error while updating checksum.\n"); | ||||
| 			goto out; | ||||
| 		} | ||||
| 
 | ||||
| 		hw->nvm.ops.release(hw); | ||||
| 
 | ||||
| 		ret_val = igb_update_flash_i210(hw); | ||||
| 	} else { | ||||
| 		ret_val = -E1000_ERR_SWFW_SYNC; | ||||
| 	} | ||||
| out: | ||||
| 	return ret_val; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  *  igb_update_flash_i210 - Commit EEPROM to the flash | ||||
|  *  @hw: pointer to the HW structure | ||||
|  * | ||||
|  **/ | ||||
| s32 igb_update_flash_i210(struct e1000_hw *hw) | ||||
| { | ||||
| 	s32 ret_val = E1000_SUCCESS; | ||||
| 	u32 flup; | ||||
| 
 | ||||
| 	ret_val = igb_pool_flash_update_done_i210(hw); | ||||
| 	if (ret_val == -E1000_ERR_NVM) { | ||||
| 		hw_dbg("Flash update time out\n"); | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	flup = rd32(E1000_EECD) | E1000_EECD_FLUPD_I210; | ||||
| 	wr32(E1000_EECD, flup); | ||||
| 
 | ||||
| 	ret_val = igb_pool_flash_update_done_i210(hw); | ||||
| 	if (ret_val == E1000_SUCCESS) | ||||
| 		hw_dbg("Flash update complete\n"); | ||||
| 	else | ||||
| 		hw_dbg("Flash update time out\n"); | ||||
| 
 | ||||
| out: | ||||
| 	return ret_val; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  *  igb_pool_flash_update_done_i210 - Pool FLUDONE status. | ||||
|  *  @hw: pointer to the HW structure | ||||
|  * | ||||
|  **/ | ||||
| s32 igb_pool_flash_update_done_i210(struct e1000_hw *hw) | ||||
| { | ||||
| 	s32 ret_val = -E1000_ERR_NVM; | ||||
| 	u32 i, reg; | ||||
| 
 | ||||
| 	for (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) { | ||||
| 		reg = rd32(E1000_EECD); | ||||
| 		if (reg & E1000_EECD_FLUDONE_I210) { | ||||
| 			ret_val = E1000_SUCCESS; | ||||
| 			break; | ||||
| 		} | ||||
| 		udelay(5); | ||||
| 	} | ||||
| 
 | ||||
| 	return ret_val; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  *  igb_valid_led_default_i210 - Verify a valid default LED config | ||||
|  *  @hw: pointer to the HW structure | ||||
|  *  @data: pointer to the NVM (EEPROM) | ||||
|  * | ||||
|  *  Read the EEPROM for the current default LED configuration.  If the | ||||
|  *  LED configuration is not valid, set to a valid LED configuration. | ||||
|  **/ | ||||
| s32 igb_valid_led_default_i210(struct e1000_hw *hw, u16 *data) | ||||
| { | ||||
| 	s32 ret_val; | ||||
| 
 | ||||
| 	ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); | ||||
| 	if (ret_val) { | ||||
| 		hw_dbg("NVM Read Error\n"); | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) { | ||||
| 		switch (hw->phy.media_type) { | ||||
| 		case e1000_media_type_internal_serdes: | ||||
| 			*data = ID_LED_DEFAULT_I210_SERDES; | ||||
| 			break; | ||||
| 		case e1000_media_type_copper: | ||||
| 		default: | ||||
| 			*data = ID_LED_DEFAULT_I210; | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| out: | ||||
| 	return ret_val; | ||||
| } | ||||
							
								
								
									
										76
									
								
								drivers/net/ethernet/intel/igb/e1000_i210.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								drivers/net/ethernet/intel/igb/e1000_i210.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,76 @@ | ||||
| /*******************************************************************************
 | ||||
| 
 | ||||
|   Intel(R) Gigabit Ethernet Linux driver | ||||
|   Copyright(c) 2007-2012 Intel Corporation. | ||||
| 
 | ||||
|   This program is free software; you can redistribute it and/or modify it | ||||
|   under the terms and conditions of the GNU General Public License, | ||||
|   version 2, as published by the Free Software Foundation. | ||||
| 
 | ||||
|   This program is distributed in the hope it will be useful, but WITHOUT | ||||
|   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||||
|   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for | ||||
|   more details. | ||||
| 
 | ||||
|   You should have received a copy of the GNU General Public License along with | ||||
|   this program; if not, write to the Free Software Foundation, Inc., | ||||
|   51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
| 
 | ||||
|   The full GNU General Public License is included in this distribution in | ||||
|   the file called "COPYING". | ||||
| 
 | ||||
|   Contact Information: | ||||
|   e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> | ||||
|   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||||
| 
 | ||||
| *******************************************************************************/ | ||||
| 
 | ||||
| #ifndef _E1000_I210_H_ | ||||
| #define _E1000_I210_H_ | ||||
| 
 | ||||
| extern s32 igb_update_flash_i210(struct e1000_hw *hw); | ||||
| extern s32 igb_update_nvm_checksum_i210(struct e1000_hw *hw); | ||||
| extern s32 igb_validate_nvm_checksum_i210(struct e1000_hw *hw); | ||||
| extern s32 igb_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, | ||||
| 			      u16 words, u16 *data); | ||||
| extern s32 igb_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, | ||||
| 			     u16 words, u16 *data); | ||||
| extern s32 igb_read_invm_i211(struct e1000_hw *hw, u16 address, u16 *data); | ||||
| extern s32 igb_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask); | ||||
| extern void igb_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask); | ||||
| extern s32 igb_acquire_nvm_i210(struct e1000_hw *hw); | ||||
| extern void igb_release_nvm_i210(struct e1000_hw *hw); | ||||
| extern s32 igb_valid_led_default_i210(struct e1000_hw *hw, u16 *data); | ||||
| extern s32 igb_read_nvm_i211(struct e1000_hw *hw, u16 offset, u16 words, | ||||
| 			       u16 *data); | ||||
| 
 | ||||
| #define E1000_STM_OPCODE		0xDB00 | ||||
| #define E1000_EEPROM_FLASH_SIZE_WORD	0x11 | ||||
| 
 | ||||
| #define INVM_DWORD_TO_RECORD_TYPE(invm_dword) \ | ||||
| 	(u8)((invm_dword) & 0x7) | ||||
| #define INVM_DWORD_TO_WORD_ADDRESS(invm_dword) \ | ||||
| 	(u8)(((invm_dword) & 0x0000FE00) >> 9) | ||||
| #define INVM_DWORD_TO_WORD_DATA(invm_dword) \ | ||||
| 	(u16)(((invm_dword) & 0xFFFF0000) >> 16) | ||||
| 
 | ||||
| enum E1000_INVM_STRUCTURE_TYPE { | ||||
| 	E1000_INVM_UNINITIALIZED_STRUCTURE		= 0x00, | ||||
| 	E1000_INVM_WORD_AUTOLOAD_STRUCTURE		= 0x01, | ||||
| 	E1000_INVM_CSR_AUTOLOAD_STRUCTURE		= 0x02, | ||||
| 	E1000_INVM_PHY_REGISTER_AUTOLOAD_STRUCTURE	= 0x03, | ||||
| 	E1000_INVM_RSA_KEY_SHA256_STRUCTURE		= 0x04, | ||||
| 	E1000_INVM_INVALIDATED_STRUCTURE		= 0x0F, | ||||
| }; | ||||
| 
 | ||||
| #define E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS	8 | ||||
| #define E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS	1 | ||||
| 
 | ||||
| #define ID_LED_DEFAULT_I210		((ID_LED_OFF1_ON2  << 8) | \ | ||||
| 					 (ID_LED_OFF1_OFF2 <<  4) | \ | ||||
| 					 (ID_LED_DEF1_DEF2)) | ||||
| #define ID_LED_DEFAULT_I210_SERDES	((ID_LED_DEF1_DEF2 << 8) | \ | ||||
| 					 (ID_LED_DEF1_DEF2 <<  4) | \ | ||||
| 					 (ID_LED_DEF1_DEF2)) | ||||
| 
 | ||||
| #endif | ||||
| @ -658,6 +658,7 @@ s32 igb_setup_link(struct e1000_hw *hw) | ||||
| 	ret_val = igb_set_fc_watermarks(hw); | ||||
| 
 | ||||
| out: | ||||
| 
 | ||||
| 	return ret_val; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -710,4 +710,3 @@ s32 igb_update_nvm_checksum(struct e1000_hw *hw) | ||||
| out: | ||||
| 	return ret_val; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -35,6 +35,7 @@ static s32  igb_phy_setup_autoneg(struct e1000_hw *hw); | ||||
| static void igb_phy_force_speed_duplex_setup(struct e1000_hw *hw, | ||||
| 					       u16 *phy_ctrl); | ||||
| static s32  igb_wait_autoneg(struct e1000_hw *hw); | ||||
| static s32  igb_set_master_slave_mode(struct e1000_hw *hw); | ||||
| 
 | ||||
| /* Cable length tables */ | ||||
| static const u16 e1000_m88_cable_length_table[] = | ||||
| @ -570,6 +571,11 @@ s32 igb_copper_link_setup_m88(struct e1000_hw *hw) | ||||
| 		hw_dbg("Error committing the PHY changes\n"); | ||||
| 		goto out; | ||||
| 	} | ||||
| 	if (phy->type == e1000_phy_i210) { | ||||
| 		ret_val = igb_set_master_slave_mode(hw); | ||||
| 		if (ret_val) | ||||
| 			return ret_val; | ||||
| 	} | ||||
| 
 | ||||
| out: | ||||
| 	return ret_val; | ||||
| @ -1213,12 +1219,22 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw) | ||||
| 			goto out; | ||||
| 
 | ||||
| 		if (!link) { | ||||
| 			if (hw->phy.type != e1000_phy_m88 || | ||||
| 			    hw->phy.id == I347AT4_E_PHY_ID || | ||||
| 			    hw->phy.id == M88E1112_E_PHY_ID) { | ||||
| 				hw_dbg("Link taking longer than expected.\n"); | ||||
| 			} else { | ||||
| 			bool reset_dsp = true; | ||||
| 
 | ||||
| 			switch (hw->phy.id) { | ||||
| 			case I347AT4_E_PHY_ID: | ||||
| 			case M88E1112_E_PHY_ID: | ||||
| 			case I210_I_PHY_ID: | ||||
| 				reset_dsp = false; | ||||
| 				break; | ||||
| 			default: | ||||
| 				if (hw->phy.type != e1000_phy_m88) | ||||
| 					reset_dsp = false; | ||||
| 				break; | ||||
| 			} | ||||
| 			if (!reset_dsp) | ||||
| 				hw_dbg("Link taking longer than expected.\n"); | ||||
| 			else { | ||||
| 				/*
 | ||||
| 				 * We didn't get link. | ||||
| 				 * Reset the DSP and cross our fingers. | ||||
| @ -1243,7 +1259,8 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw) | ||||
| 
 | ||||
| 	if (hw->phy.type != e1000_phy_m88 || | ||||
| 	    hw->phy.id == I347AT4_E_PHY_ID || | ||||
| 	    hw->phy.id == M88E1112_E_PHY_ID) | ||||
| 	    hw->phy.id == M88E1112_E_PHY_ID || | ||||
| 	    hw->phy.id == I210_I_PHY_ID) | ||||
| 		goto out; | ||||
| 
 | ||||
| 	ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); | ||||
| @ -1441,6 +1458,7 @@ s32 igb_check_downshift(struct e1000_hw *hw) | ||||
| 	u16 phy_data, offset, mask; | ||||
| 
 | ||||
| 	switch (phy->type) { | ||||
| 	case e1000_phy_i210: | ||||
| 	case e1000_phy_m88: | ||||
| 	case e1000_phy_gg82563: | ||||
| 		offset	= M88E1000_PHY_SPEC_STATUS; | ||||
| @ -1476,7 +1494,7 @@ out: | ||||
|  * | ||||
|  *  Polarity is determined based on the PHY specific status register. | ||||
|  **/ | ||||
| static s32 igb_check_polarity_m88(struct e1000_hw *hw) | ||||
| s32 igb_check_polarity_m88(struct e1000_hw *hw) | ||||
| { | ||||
| 	struct e1000_phy_info *phy = &hw->phy; | ||||
| 	s32 ret_val; | ||||
| @ -1665,6 +1683,7 @@ s32 igb_get_cable_length_m88_gen2(struct e1000_hw *hw) | ||||
| 	u16 phy_data, phy_data2, index, default_page, is_cm; | ||||
| 
 | ||||
| 	switch (hw->phy.id) { | ||||
| 	case I210_I_PHY_ID: | ||||
| 	case I347AT4_E_PHY_ID: | ||||
| 		/* Remember the original page select and set it to 7 */ | ||||
| 		ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT, | ||||
| @ -2129,10 +2148,16 @@ s32 igb_phy_init_script_igp3(struct e1000_hw *hw) | ||||
| void igb_power_up_phy_copper(struct e1000_hw *hw) | ||||
| { | ||||
| 	u16 mii_reg = 0; | ||||
| 	u16 power_reg = 0; | ||||
| 
 | ||||
| 	/* The PHY will retain its settings across a power down/up cycle */ | ||||
| 	hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg); | ||||
| 	mii_reg &= ~MII_CR_POWER_DOWN; | ||||
| 	if (hw->phy.type == e1000_phy_i210) { | ||||
| 		hw->phy.ops.read_reg(hw, GS40G_COPPER_SPEC, &power_reg); | ||||
| 		power_reg &= ~GS40G_CS_POWER_DOWN; | ||||
| 		hw->phy.ops.write_reg(hw, GS40G_COPPER_SPEC, power_reg); | ||||
| 	} | ||||
| 	hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg); | ||||
| } | ||||
| 
 | ||||
| @ -2146,10 +2171,18 @@ void igb_power_up_phy_copper(struct e1000_hw *hw) | ||||
| void igb_power_down_phy_copper(struct e1000_hw *hw) | ||||
| { | ||||
| 	u16 mii_reg = 0; | ||||
| 	u16 power_reg = 0; | ||||
| 
 | ||||
| 	/* The PHY will retain its settings across a power down/up cycle */ | ||||
| 	hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg); | ||||
| 	mii_reg |= MII_CR_POWER_DOWN; | ||||
| 
 | ||||
| 	/* i210 Phy requires an additional bit for power up/down */ | ||||
| 	if (hw->phy.type == e1000_phy_i210) { | ||||
| 		hw->phy.ops.read_reg(hw, GS40G_COPPER_SPEC, &power_reg); | ||||
| 		power_reg |= GS40G_CS_POWER_DOWN; | ||||
| 		hw->phy.ops.write_reg(hw, GS40G_COPPER_SPEC, power_reg); | ||||
| 	} | ||||
| 	hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg); | ||||
| 	msleep(1); | ||||
| } | ||||
| @ -2345,3 +2378,103 @@ s32 igb_get_cable_length_82580(struct e1000_hw *hw) | ||||
| out: | ||||
| 	return ret_val; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  *  igb_write_phy_reg_gs40g - Write GS40G PHY register | ||||
|  *  @hw: pointer to the HW structure | ||||
|  *  @offset: lower half is register offset to write to | ||||
|  *     upper half is page to use. | ||||
|  *  @data: data to write at register offset | ||||
|  * | ||||
|  *  Acquires semaphore, if necessary, then writes the data to PHY register | ||||
|  *  at the offset.  Release any acquired semaphores before exiting. | ||||
|  **/ | ||||
| s32 igb_write_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 data) | ||||
| { | ||||
| 	s32 ret_val; | ||||
| 	u16 page = offset >> GS40G_PAGE_SHIFT; | ||||
| 
 | ||||
| 	offset = offset & GS40G_OFFSET_MASK; | ||||
| 	ret_val = hw->phy.ops.acquire(hw); | ||||
| 	if (ret_val) | ||||
| 		return ret_val; | ||||
| 
 | ||||
| 	ret_val = igb_write_phy_reg_mdic(hw, GS40G_PAGE_SELECT, page); | ||||
| 	if (ret_val) | ||||
| 		goto release; | ||||
| 	ret_val = igb_write_phy_reg_mdic(hw, offset, data); | ||||
| 
 | ||||
| release: | ||||
| 	hw->phy.ops.release(hw); | ||||
| 	return ret_val; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  *  igb_read_phy_reg_gs40g - Read GS40G  PHY register | ||||
|  *  @hw: pointer to the HW structure | ||||
|  *  @offset: lower half is register offset to read to | ||||
|  *     upper half is page to use. | ||||
|  *  @data: data to read at register offset | ||||
|  * | ||||
|  *  Acquires semaphore, if necessary, then reads the data in the PHY register | ||||
|  *  at the offset.  Release any acquired semaphores before exiting. | ||||
|  **/ | ||||
| s32 igb_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data) | ||||
| { | ||||
| 	s32 ret_val; | ||||
| 	u16 page = offset >> GS40G_PAGE_SHIFT; | ||||
| 
 | ||||
| 	offset = offset & GS40G_OFFSET_MASK; | ||||
| 	ret_val = hw->phy.ops.acquire(hw); | ||||
| 	if (ret_val) | ||||
| 		return ret_val; | ||||
| 
 | ||||
| 	ret_val = igb_write_phy_reg_mdic(hw, GS40G_PAGE_SELECT, page); | ||||
| 	if (ret_val) | ||||
| 		goto release; | ||||
| 	ret_val = igb_read_phy_reg_mdic(hw, offset, data); | ||||
| 
 | ||||
| release: | ||||
| 	hw->phy.ops.release(hw); | ||||
| 	return ret_val; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  *  igb_set_master_slave_mode - Setup PHY for Master/slave mode | ||||
|  *  @hw: pointer to the HW structure | ||||
|  * | ||||
|  *  Sets up Master/slave mode | ||||
|  **/ | ||||
| static s32 igb_set_master_slave_mode(struct e1000_hw *hw) | ||||
| { | ||||
| 	s32 ret_val; | ||||
| 	u16 phy_data; | ||||
| 
 | ||||
| 	/* Resolve Master/Slave mode */ | ||||
| 	ret_val = hw->phy.ops.read_reg(hw, PHY_1000T_CTRL, &phy_data); | ||||
| 	if (ret_val) | ||||
| 		return ret_val; | ||||
| 
 | ||||
| 	/* load defaults for future use */ | ||||
| 	hw->phy.original_ms_type = (phy_data & CR_1000T_MS_ENABLE) ? | ||||
| 				   ((phy_data & CR_1000T_MS_VALUE) ? | ||||
| 				    e1000_ms_force_master : | ||||
| 				    e1000_ms_force_slave) : e1000_ms_auto; | ||||
| 
 | ||||
| 	switch (hw->phy.ms_type) { | ||||
| 	case e1000_ms_force_master: | ||||
| 		phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE); | ||||
| 		break; | ||||
| 	case e1000_ms_force_slave: | ||||
| 		phy_data |= CR_1000T_MS_ENABLE; | ||||
| 		phy_data &= ~(CR_1000T_MS_VALUE); | ||||
| 		break; | ||||
| 	case e1000_ms_auto: | ||||
| 		phy_data &= ~CR_1000T_MS_ENABLE; | ||||
| 		/* fall-through */ | ||||
| 	default: | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	return hw->phy.ops.write_reg(hw, PHY_1000T_CTRL, phy_data); | ||||
| } | ||||
|  | ||||
| @ -73,6 +73,9 @@ s32  igb_copper_link_setup_82580(struct e1000_hw *hw); | ||||
| s32  igb_get_phy_info_82580(struct e1000_hw *hw); | ||||
| s32  igb_phy_force_speed_duplex_82580(struct e1000_hw *hw); | ||||
| s32  igb_get_cable_length_82580(struct e1000_hw *hw); | ||||
| s32  igb_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data); | ||||
| s32  igb_write_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 data); | ||||
| s32  igb_check_polarity_m88(struct e1000_hw *hw); | ||||
| 
 | ||||
| /* IGP01E1000 Specific Registers */ | ||||
| #define IGP01E1000_PHY_PORT_CONFIG        0x10 /* Port Config */ | ||||
| @ -140,4 +143,16 @@ s32  igb_get_cable_length_82580(struct e1000_hw *hw); | ||||
| 
 | ||||
| #define E1000_CABLE_LENGTH_UNDEFINED      0xFF | ||||
| 
 | ||||
| /* GS40G - I210 PHY defines */ | ||||
| #define GS40G_PAGE_SELECT		0x16 | ||||
| #define GS40G_PAGE_SHIFT		16 | ||||
| #define GS40G_OFFSET_MASK		0xFFFF | ||||
| #define GS40G_PAGE_2			0x20000 | ||||
| #define GS40G_MAC_REG2			0x15 | ||||
| #define GS40G_MAC_LB			0x4140 | ||||
| #define GS40G_MAC_SPEED_1G		0X0006 | ||||
| #define GS40G_COPPER_SPEC		0x0010 | ||||
| #define GS40G_CS_POWER_DOWN		0x0002 | ||||
| #define GS40G_LINE_LB			0x4000 | ||||
| 
 | ||||
| #endif | ||||
|  | ||||
| @ -352,4 +352,18 @@ | ||||
| #define E1000_O2BGPTC   0x08FE4 /* OS2BMC packets received by BMC */ | ||||
| #define E1000_O2BSPC    0x0415C /* OS2BMC packets transmitted by host */ | ||||
| 
 | ||||
| #define E1000_SRWR		0x12018  /* Shadow Ram Write Register - RW */ | ||||
| #define E1000_I210_FLMNGCTL	0x12038 | ||||
| #define E1000_I210_FLMNGDATA	0x1203C | ||||
| #define E1000_I210_FLMNGCNT	0x12040 | ||||
| 
 | ||||
| #define E1000_I210_FLSWCTL	0x12048 | ||||
| #define E1000_I210_FLSWDATA	0x1204C | ||||
| #define E1000_I210_FLSWCNT	0x12050 | ||||
| 
 | ||||
| #define E1000_I210_FLA		0x1201C | ||||
| 
 | ||||
| #define E1000_INVM_DATA_REG(_n)	(0x12120 + 4*(_n)) | ||||
| #define E1000_INVM_SIZE		64 /* Number of INVM Data Registers */ | ||||
| 
 | ||||
| #endif | ||||
|  | ||||
| @ -65,10 +65,13 @@ struct igb_adapter; | ||||
| #define MAX_Q_VECTORS                      8 | ||||
| 
 | ||||
| /* Transmit and receive queues */ | ||||
| #define IGB_MAX_RX_QUEUES                  (adapter->vfs_allocated_count ? 2 : \ | ||||
|                                            (hw->mac.type > e1000_82575 ? 8 : 4)) | ||||
| #define IGB_MAX_RX_QUEUES		((adapter->vfs_allocated_count ? 2 : \ | ||||
| 					(hw->mac.type > e1000_82575 ? 8 : 4))) | ||||
| #define IGB_MAX_RX_QUEUES_I210             4 | ||||
| #define IGB_MAX_RX_QUEUES_I211             2 | ||||
| #define IGB_MAX_TX_QUEUES                  16 | ||||
| 
 | ||||
| #define IGB_MAX_TX_QUEUES_I210             4 | ||||
| #define IGB_MAX_TX_QUEUES_I211             2 | ||||
| #define IGB_MAX_VF_MC_ENTRIES              30 | ||||
| #define IGB_MAX_VF_FUNCTIONS               8 | ||||
| #define IGB_MAX_VFTA_ENTRIES               128 | ||||
|  | ||||
| @ -552,10 +552,13 @@ static void igb_get_regs(struct net_device *netdev, | ||||
| 	regs_buff[548] = rd32(E1000_TDFT); | ||||
| 	regs_buff[549] = rd32(E1000_TDFHS); | ||||
| 	regs_buff[550] = rd32(E1000_TDFPC); | ||||
| 	regs_buff[551] = adapter->stats.o2bgptc; | ||||
| 	regs_buff[552] = adapter->stats.b2ospc; | ||||
| 	regs_buff[553] = adapter->stats.o2bspc; | ||||
| 	regs_buff[554] = adapter->stats.b2ogprc; | ||||
| 
 | ||||
| 	if (hw->mac.type > e1000_82580) { | ||||
| 		regs_buff[551] = adapter->stats.o2bgptc; | ||||
| 		regs_buff[552] = adapter->stats.b2ospc; | ||||
| 		regs_buff[553] = adapter->stats.o2bspc; | ||||
| 		regs_buff[554] = adapter->stats.b2ogprc; | ||||
| 	} | ||||
| 
 | ||||
| 	if (hw->mac.type != e1000_82576) | ||||
| 		return; | ||||
| @ -660,6 +663,9 @@ static int igb_set_eeprom(struct net_device *netdev, | ||||
| 	if (eeprom->len == 0) | ||||
| 		return -EOPNOTSUPP; | ||||
| 
 | ||||
| 	if (hw->mac.type == e1000_i211) | ||||
| 		return -EOPNOTSUPP; | ||||
| 
 | ||||
| 	if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) | ||||
| 		return -EFAULT; | ||||
| 
 | ||||
| @ -887,6 +893,36 @@ struct igb_reg_test { | ||||
| #define TABLE64_TEST_LO	5 | ||||
| #define TABLE64_TEST_HI	6 | ||||
| 
 | ||||
| /* i210 reg test */ | ||||
| static struct igb_reg_test reg_test_i210[] = { | ||||
| 	{ E1000_FCAL,	   0x100, 1,  PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, | ||||
| 	{ E1000_FCAH,	   0x100, 1,  PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF }, | ||||
| 	{ E1000_FCT,	   0x100, 1,  PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF }, | ||||
| 	{ E1000_RDBAL(0),  0x100, 4,  PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, | ||||
| 	{ E1000_RDBAH(0),  0x100, 4,  PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, | ||||
| 	{ E1000_RDLEN(0),  0x100, 4,  PATTERN_TEST, 0x000FFF80, 0x000FFFFF }, | ||||
| 	/* RDH is read-only for i210, only test RDT. */ | ||||
| 	{ E1000_RDT(0),	   0x100, 4,  PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, | ||||
| 	{ E1000_FCRTH,	   0x100, 1,  PATTERN_TEST, 0x0000FFF0, 0x0000FFF0 }, | ||||
| 	{ E1000_FCTTV,	   0x100, 1,  PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, | ||||
| 	{ E1000_TIPG,	   0x100, 1,  PATTERN_TEST, 0x3FFFFFFF, 0x3FFFFFFF }, | ||||
| 	{ E1000_TDBAL(0),  0x100, 4,  PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, | ||||
| 	{ E1000_TDBAH(0),  0x100, 4,  PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, | ||||
| 	{ E1000_TDLEN(0),  0x100, 4,  PATTERN_TEST, 0x000FFF80, 0x000FFFFF }, | ||||
| 	{ E1000_TDT(0),	   0x100, 4,  PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, | ||||
| 	{ E1000_RCTL,	   0x100, 1,  SET_READ_TEST, 0xFFFFFFFF, 0x00000000 }, | ||||
| 	{ E1000_RCTL,	   0x100, 1,  SET_READ_TEST, 0x04CFB0FE, 0x003FFFFB }, | ||||
| 	{ E1000_RCTL,	   0x100, 1,  SET_READ_TEST, 0x04CFB0FE, 0xFFFFFFFF }, | ||||
| 	{ E1000_TCTL,	   0x100, 1,  SET_READ_TEST, 0xFFFFFFFF, 0x00000000 }, | ||||
| 	{ E1000_RA,	   0, 16, TABLE64_TEST_LO, | ||||
| 						0xFFFFFFFF, 0xFFFFFFFF }, | ||||
| 	{ E1000_RA,	   0, 16, TABLE64_TEST_HI, | ||||
| 						0x900FFFFF, 0xFFFFFFFF }, | ||||
| 	{ E1000_MTA,	   0, 128, TABLE32_TEST, | ||||
| 						0xFFFFFFFF, 0xFFFFFFFF }, | ||||
| 	{ 0, 0, 0, 0, 0 } | ||||
| }; | ||||
| 
 | ||||
| /* i350 reg test */ | ||||
| static struct igb_reg_test reg_test_i350[] = { | ||||
| 	{ E1000_FCAL,	   0x100, 1,  PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, | ||||
| @ -1109,6 +1145,11 @@ static int igb_reg_test(struct igb_adapter *adapter, u64 *data) | ||||
| 		test = reg_test_i350; | ||||
| 		toggle = 0x7FEFF3FF; | ||||
| 		break; | ||||
| 	case e1000_i210: | ||||
| 	case e1000_i211: | ||||
| 		test = reg_test_i210; | ||||
| 		toggle = 0x7FEFF3FF; | ||||
| 		break; | ||||
| 	case e1000_82580: | ||||
| 		test = reg_test_82580; | ||||
| 		toggle = 0x7FEFF3FF; | ||||
| @ -1190,23 +1231,13 @@ static int igb_reg_test(struct igb_adapter *adapter, u64 *data) | ||||
| 
 | ||||
| static int igb_eeprom_test(struct igb_adapter *adapter, u64 *data) | ||||
| { | ||||
| 	u16 temp; | ||||
| 	u16 checksum = 0; | ||||
| 	u16 i; | ||||
| 
 | ||||
| 	*data = 0; | ||||
| 	/* Read and add up the contents of the EEPROM */ | ||||
| 	for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { | ||||
| 		if ((adapter->hw.nvm.ops.read(&adapter->hw, i, 1, &temp)) < 0) { | ||||
| 			*data = 1; | ||||
| 			break; | ||||
| 		} | ||||
| 		checksum += temp; | ||||
| 	} | ||||
| 
 | ||||
| 	/* If Checksum is not Correct return error else test passed */ | ||||
| 	if ((checksum != (u16) NVM_SUM) && !(*data)) | ||||
| 		*data = 2; | ||||
| 	/* Validate eeprom on all parts but i211 */ | ||||
| 	if (adapter->hw.mac.type != e1000_i211) { | ||||
| 		if (adapter->hw.nvm.ops.validate(&adapter->hw) < 0) | ||||
| 			*data = 2; | ||||
| 	} | ||||
| 
 | ||||
| 	return *data; | ||||
| } | ||||
| @ -1272,6 +1303,8 @@ static int igb_intr_test(struct igb_adapter *adapter, u64 *data) | ||||
| 		ics_mask = 0x77DCFED5; | ||||
| 		break; | ||||
| 	case e1000_i350: | ||||
| 	case e1000_i210: | ||||
| 	case e1000_i211: | ||||
| 		ics_mask = 0x77DCFED5; | ||||
| 		break; | ||||
| 	default: | ||||
| @ -1438,23 +1471,35 @@ static int igb_integrated_phy_loopback(struct igb_adapter *adapter) | ||||
| { | ||||
| 	struct e1000_hw *hw = &adapter->hw; | ||||
| 	u32 ctrl_reg = 0; | ||||
| 	u16 phy_reg = 0; | ||||
| 
 | ||||
| 	hw->mac.autoneg = false; | ||||
| 
 | ||||
| 	if (hw->phy.type == e1000_phy_m88) { | ||||
| 	switch (hw->phy.type) { | ||||
| 	case e1000_phy_m88: | ||||
| 		/* Auto-MDI/MDIX Off */ | ||||
| 		igb_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, 0x0808); | ||||
| 		/* reset to update Auto-MDI/MDIX */ | ||||
| 		igb_write_phy_reg(hw, PHY_CONTROL, 0x9140); | ||||
| 		/* autoneg off */ | ||||
| 		igb_write_phy_reg(hw, PHY_CONTROL, 0x8140); | ||||
| 	} else if (hw->phy.type == e1000_phy_82580) { | ||||
| 		break; | ||||
| 	case e1000_phy_82580: | ||||
| 		/* enable MII loopback */ | ||||
| 		igb_write_phy_reg(hw, I82580_PHY_LBK_CTRL, 0x8041); | ||||
| 		break; | ||||
| 	case e1000_phy_i210: | ||||
| 		/* set loopback speed in PHY */ | ||||
| 		igb_read_phy_reg(hw, (GS40G_PAGE_SELECT & GS40G_PAGE_2), | ||||
| 					&phy_reg); | ||||
| 		phy_reg |= GS40G_MAC_SPEED_1G; | ||||
| 		igb_write_phy_reg(hw, (GS40G_PAGE_SELECT & GS40G_PAGE_2), | ||||
| 					phy_reg); | ||||
| 		ctrl_reg = rd32(E1000_CTRL_EXT); | ||||
| 	default: | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	ctrl_reg = rd32(E1000_CTRL); | ||||
| 
 | ||||
| 	/* force 1000, set loopback */ | ||||
| 	igb_write_phy_reg(hw, PHY_CONTROL, 0x4140); | ||||
| 
 | ||||
| @ -1467,7 +1512,7 @@ static int igb_integrated_phy_loopback(struct igb_adapter *adapter) | ||||
| 		     E1000_CTRL_FD |	 /* Force Duplex to FULL */ | ||||
| 		     E1000_CTRL_SLU);	 /* Set link up enable bit */ | ||||
| 
 | ||||
| 	if (hw->phy.type == e1000_phy_m88) | ||||
| 	if ((hw->phy.type == e1000_phy_m88) || (hw->phy.type == e1000_phy_i210)) | ||||
| 		ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */ | ||||
| 
 | ||||
| 	wr32(E1000_CTRL, ctrl_reg); | ||||
| @ -1475,7 +1520,7 @@ static int igb_integrated_phy_loopback(struct igb_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 (hw->phy.type == e1000_phy_m88) | ||||
| 	if ((hw->phy.type == e1000_phy_m88) || (hw->phy.type == e1000_phy_i210)) | ||||
| 		igb_phy_disable_receiver(adapter); | ||||
| 
 | ||||
| 	udelay(500); | ||||
| @ -1740,6 +1785,14 @@ static int igb_loopback_test(struct igb_adapter *adapter, u64 *data) | ||||
| 		*data = 0; | ||||
| 		goto out; | ||||
| 	} | ||||
| 	if ((adapter->hw.mac.type == e1000_i210) | ||||
| 		|| (adapter->hw.mac.type == e1000_i210)) { | ||||
| 		dev_err(&adapter->pdev->dev, | ||||
| 			"Loopback test not supported " | ||||
| 			"on this part at this time.\n"); | ||||
| 		*data = 0; | ||||
| 		goto out; | ||||
| 	} | ||||
| 	*data = igb_setup_desc_rings(adapter); | ||||
| 	if (*data) | ||||
| 		goto out; | ||||
|  | ||||
| @ -75,6 +75,11 @@ static const struct e1000_info *igb_info_tbl[] = { | ||||
| }; | ||||
| 
 | ||||
| static DEFINE_PCI_DEVICE_TABLE(igb_pci_tbl) = { | ||||
| 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I211_COPPER), board_82575 }, | ||||
| 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_COPPER), board_82575 }, | ||||
| 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_FIBER), board_82575 }, | ||||
| 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_SERDES), board_82575 }, | ||||
| 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_SGMII), board_82575 }, | ||||
| 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_COPPER), board_82575 }, | ||||
| 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_FIBER), board_82575 }, | ||||
| 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_SERDES), board_82575 }, | ||||
| @ -641,6 +646,8 @@ static void igb_cache_ring_register(struct igb_adapter *adapter) | ||||
| 	case e1000_82575: | ||||
| 	case e1000_82580: | ||||
| 	case e1000_i350: | ||||
| 	case e1000_i210: | ||||
| 	case e1000_i211: | ||||
| 	default: | ||||
| 		for (; i < adapter->num_rx_queues; i++) | ||||
| 			adapter->rx_ring[i]->reg_idx = rbase_offset + i; | ||||
| @ -727,8 +734,11 @@ static int igb_alloc_queues(struct igb_adapter *adapter) | ||||
| 		if (adapter->hw.mac.type >= e1000_82576) | ||||
| 			set_bit(IGB_RING_FLAG_RX_SCTP_CSUM, &ring->flags); | ||||
| 
 | ||||
| 		/* On i350, loopback VLAN packets have the tag byte-swapped. */ | ||||
| 		if (adapter->hw.mac.type == e1000_i350) | ||||
| 		/*
 | ||||
| 		 * On i350, i210, and i211, loopback VLAN packets | ||||
| 		 * have the tag byte-swapped. | ||||
| 		 * */ | ||||
| 		if (adapter->hw.mac.type >= e1000_i350) | ||||
| 			set_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &ring->flags); | ||||
| 
 | ||||
| 		adapter->rx_ring[i] = ring; | ||||
| @ -822,6 +832,8 @@ static void igb_assign_vector(struct igb_q_vector *q_vector, int msix_vector) | ||||
| 		break; | ||||
| 	case e1000_82580: | ||||
| 	case e1000_i350: | ||||
| 	case e1000_i210: | ||||
| 	case e1000_i211: | ||||
| 		/*
 | ||||
| 		 * On 82580 and newer adapters the scheme is similar to 82576 | ||||
| 		 * however instead of ordering column-major we have things | ||||
| @ -888,6 +900,8 @@ static void igb_configure_msix(struct igb_adapter *adapter) | ||||
| 	case e1000_82576: | ||||
| 	case e1000_82580: | ||||
| 	case e1000_i350: | ||||
| 	case e1000_i210: | ||||
| 	case e1000_i211: | ||||
| 		/* Turn on MSI-X capability first, or our settings
 | ||||
| 		 * won't stick.  And it will take days to debug. */ | ||||
| 		wr32(E1000_GPIE, E1000_GPIE_MSIX_MODE | | ||||
| @ -1034,6 +1048,11 @@ static int igb_set_interrupt_capability(struct igb_adapter *adapter) | ||||
| 	if (!(adapter->flags & IGB_FLAG_QUEUE_PAIRS)) | ||||
| 		numvecs += adapter->num_tx_queues; | ||||
| 
 | ||||
| 	/* i210 and i211 can only have 4 MSIX vectors for rx/tx queues. */ | ||||
| 	if ((adapter->hw.mac.type == e1000_i210) | ||||
| 		|| (adapter->hw.mac.type == e1000_i211)) | ||||
| 		numvecs = 4; | ||||
| 
 | ||||
| 	/* store the number of vectors reserved for queues */ | ||||
| 	adapter->num_q_vectors = numvecs; | ||||
| 
 | ||||
| @ -1041,6 +1060,7 @@ static int igb_set_interrupt_capability(struct igb_adapter *adapter) | ||||
| 	numvecs++; | ||||
| 	adapter->msix_entries = kcalloc(numvecs, sizeof(struct msix_entry), | ||||
| 					GFP_KERNEL); | ||||
| 
 | ||||
| 	if (!adapter->msix_entries) | ||||
| 		goto msi_only; | ||||
| 
 | ||||
| @ -1631,6 +1651,8 @@ void igb_reset(struct igb_adapter *adapter) | ||||
| 		pba &= E1000_RXPBS_SIZE_MASK_82576; | ||||
| 		break; | ||||
| 	case e1000_82575: | ||||
| 	case e1000_i210: | ||||
| 	case e1000_i211: | ||||
| 	default: | ||||
| 		pba = E1000_PBA_34K; | ||||
| 		break; | ||||
| @ -1826,7 +1848,7 @@ static int __devinit igb_probe(struct pci_dev *pdev, | ||||
| 	 */ | ||||
| 	if (pdev->is_virtfn) { | ||||
| 		WARN(1, KERN_ERR "%s (%hx:%hx) should not be a VF!\n", | ||||
| 		     pci_name(pdev), pdev->vendor, pdev->device); | ||||
| 			pci_name(pdev), pdev->vendor, pdev->device); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| @ -1980,11 +2002,16 @@ static int __devinit igb_probe(struct pci_dev *pdev, | ||||
| 	 * known good starting state */ | ||||
| 	hw->mac.ops.reset_hw(hw); | ||||
| 
 | ||||
| 	/* make sure the NVM is good */ | ||||
| 	if (hw->nvm.ops.validate(hw) < 0) { | ||||
| 		dev_err(&pdev->dev, "The NVM Checksum Is Not Valid\n"); | ||||
| 		err = -EIO; | ||||
| 		goto err_eeprom; | ||||
| 	/*
 | ||||
| 	 * make sure the NVM is good , i211 parts have special NVM that | ||||
| 	 * doesn't contain a checksum | ||||
| 	 */ | ||||
| 	if (hw->mac.type != e1000_i211) { | ||||
| 		if (hw->nvm.ops.validate(hw) < 0) { | ||||
| 			dev_err(&pdev->dev, "The NVM Checksum Is Not Valid\n"); | ||||
| 			err = -EIO; | ||||
| 			goto err_eeprom; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/* copy the MAC address out of the NVM */ | ||||
| @ -2118,6 +2145,8 @@ static int __devinit igb_probe(struct pci_dev *pdev, | ||||
| 		adapter->num_rx_queues, adapter->num_tx_queues); | ||||
| 	switch (hw->mac.type) { | ||||
| 	case e1000_i350: | ||||
| 	case e1000_i210: | ||||
| 	case e1000_i211: | ||||
| 		igb_set_eee_i350(hw); | ||||
| 		break; | ||||
| 	default: | ||||
| @ -2244,9 +2273,14 @@ static void __devinit igb_probe_vfs(struct igb_adapter * adapter) | ||||
| { | ||||
| #ifdef CONFIG_PCI_IOV | ||||
| 	struct pci_dev *pdev = adapter->pdev; | ||||
| 	struct e1000_hw *hw = &adapter->hw; | ||||
| 	int old_vfs = igb_find_enabled_vfs(adapter); | ||||
| 	int i; | ||||
| 
 | ||||
| 	/* Virtualization features not supported on i210 family. */ | ||||
| 	if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211)) | ||||
| 		return; | ||||
| 
 | ||||
| 	if (old_vfs) { | ||||
| 		dev_info(&pdev->dev, "%d pre-allocated VFs found - override " | ||||
| 			 "max_vfs setting of %d\n", old_vfs, max_vfs); | ||||
| @ -2258,6 +2292,7 @@ static void __devinit igb_probe_vfs(struct igb_adapter * adapter) | ||||
| 
 | ||||
| 	adapter->vf_data = kcalloc(adapter->vfs_allocated_count, | ||||
| 				sizeof(struct vf_data_storage), GFP_KERNEL); | ||||
| 
 | ||||
| 	/* if allocation failed then we do not support SR-IOV */ | ||||
| 	if (!adapter->vf_data) { | ||||
| 		adapter->vfs_allocated_count = 0; | ||||
| @ -2332,11 +2367,28 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter) | ||||
| 		} else | ||||
| 			adapter->vfs_allocated_count = max_vfs; | ||||
| 		break; | ||||
| 	case e1000_i210: | ||||
| 	case e1000_i211: | ||||
| 		adapter->vfs_allocated_count = 0; | ||||
| 		break; | ||||
| 	default: | ||||
| 		break; | ||||
| 	} | ||||
| #endif /* CONFIG_PCI_IOV */ | ||||
| 	adapter->rss_queues = min_t(u32, IGB_MAX_RX_QUEUES, num_online_cpus()); | ||||
| 	switch (hw->mac.type) { | ||||
| 	case e1000_i210: | ||||
| 		adapter->rss_queues = min_t(u32, IGB_MAX_RX_QUEUES_I210, | ||||
| 			num_online_cpus()); | ||||
| 		break; | ||||
| 	case e1000_i211: | ||||
| 		adapter->rss_queues = min_t(u32, IGB_MAX_RX_QUEUES_I211, | ||||
| 			num_online_cpus()); | ||||
| 		break; | ||||
| 	default: | ||||
| 		adapter->rss_queues = min_t(u32, IGB_MAX_RX_QUEUES, | ||||
| 		num_online_cpus()); | ||||
| 		break; | ||||
| 	} | ||||
| 	/* i350 cannot do RSS and SR-IOV at the same time */ | ||||
| 	if (hw->mac.type == e1000_i350 && adapter->vfs_allocated_count) | ||||
| 		adapter->rss_queues = 1; | ||||
| @ -2366,7 +2418,7 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter) | ||||
| 	/* Explicitly disable IRQ since the NIC can be in any state. */ | ||||
| 	igb_irq_disable(adapter); | ||||
| 
 | ||||
| 	if (hw->mac.type == e1000_i350) | ||||
| 	if (hw->mac.type >= e1000_i350) | ||||
| 		adapter->flags &= ~IGB_FLAG_DMAC; | ||||
| 
 | ||||
| 	set_bit(__IGB_DOWN, &adapter->state); | ||||
| @ -2819,6 +2871,17 @@ static void igb_setup_mrqc(struct igb_adapter *adapter) | ||||
| 
 | ||||
| 	/* Don't need to set TUOFL or IPOFL, they default to 1 */ | ||||
| 	wr32(E1000_RXCSUM, rxcsum); | ||||
| 	/*
 | ||||
| 	 * Generate RSS hash based on TCP port numbers and/or | ||||
| 	 * IPv4/v6 src and dst addresses since UDP cannot be | ||||
| 	 * hashed reliably due to IP fragmentation | ||||
| 	 */ | ||||
| 
 | ||||
| 	mrqc = E1000_MRQC_RSS_FIELD_IPV4 | | ||||
| 	       E1000_MRQC_RSS_FIELD_IPV4_TCP | | ||||
| 	       E1000_MRQC_RSS_FIELD_IPV6 | | ||||
| 	       E1000_MRQC_RSS_FIELD_IPV6_TCP | | ||||
| 	       E1000_MRQC_RSS_FIELD_IPV6_TCP_EX; | ||||
| 
 | ||||
| 	/* If VMDq is enabled then we set the appropriate mode for that, else
 | ||||
| 	 * we default to RSS so that an RSS hash is calculated per packet even | ||||
| @ -2834,25 +2897,15 @@ static void igb_setup_mrqc(struct igb_adapter *adapter) | ||||
| 			wr32(E1000_VT_CTL, vtctl); | ||||
| 		} | ||||
| 		if (adapter->rss_queues > 1) | ||||
| 			mrqc = E1000_MRQC_ENABLE_VMDQ_RSS_2Q; | ||||
| 			mrqc |= E1000_MRQC_ENABLE_VMDQ_RSS_2Q; | ||||
| 		else | ||||
| 			mrqc = E1000_MRQC_ENABLE_VMDQ; | ||||
| 			mrqc |= E1000_MRQC_ENABLE_VMDQ; | ||||
| 	} else { | ||||
| 		mrqc = E1000_MRQC_ENABLE_RSS_4Q; | ||||
| 		if (hw->mac.type != e1000_i211) | ||||
| 			mrqc |= E1000_MRQC_ENABLE_RSS_4Q; | ||||
| 	} | ||||
| 	igb_vmm_control(adapter); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Generate RSS hash based on TCP port numbers and/or | ||||
| 	 * IPv4/v6 src and dst addresses since UDP cannot be | ||||
| 	 * hashed reliably due to IP fragmentation | ||||
| 	 */ | ||||
| 	mrqc |= E1000_MRQC_RSS_FIELD_IPV4 | | ||||
| 		E1000_MRQC_RSS_FIELD_IPV4_TCP | | ||||
| 		E1000_MRQC_RSS_FIELD_IPV6 | | ||||
| 		E1000_MRQC_RSS_FIELD_IPV6_TCP | | ||||
| 		E1000_MRQC_RSS_FIELD_IPV6_TCP_EX; | ||||
| 
 | ||||
| 	wr32(E1000_MRQC, mrqc); | ||||
| } | ||||
| 
 | ||||
| @ -3454,7 +3507,7 @@ static void igb_set_rx_mode(struct net_device *netdev) | ||||
| 	 * we will have issues with VLAN tag stripping not being done for frames | ||||
| 	 * that are only arriving because we are the default pool | ||||
| 	 */ | ||||
| 	if (hw->mac.type < e1000_82576) | ||||
| 	if ((hw->mac.type < e1000_82576) || (hw->mac.type > e1000_i350)) | ||||
| 		return; | ||||
| 
 | ||||
| 	vmolr |= rd32(E1000_VMOLR(vfn)) & | ||||
| @ -3551,7 +3604,7 @@ static bool igb_thermal_sensor_event(struct e1000_hw *hw, u32 event) | ||||
| 	bool ret = false; | ||||
| 	u32 ctrl_ext, thstat; | ||||
| 
 | ||||
| 	/* check for thermal sensor event on i350, copper only */ | ||||
| 	/* check for thermal sensor event on i350 copper only */ | ||||
| 	if (hw->mac.type == e1000_i350) { | ||||
| 		thstat = rd32(E1000_THSTAT); | ||||
| 		ctrl_ext = rd32(E1000_CTRL_EXT); | ||||
| @ -7027,6 +7080,8 @@ static void igb_vmm_control(struct igb_adapter *adapter) | ||||
| 
 | ||||
| 	switch (hw->mac.type) { | ||||
| 	case e1000_82575: | ||||
| 	case e1000_i210: | ||||
| 	case e1000_i211: | ||||
| 	default: | ||||
| 		/* replication is not supported for 82575 */ | ||||
| 		return; | ||||
|  | ||||
| @ -262,6 +262,8 @@ void igb_ptp_init(struct igb_adapter *adapter) | ||||
| 	struct e1000_hw *hw = &adapter->hw; | ||||
| 
 | ||||
| 	switch (hw->mac.type) { | ||||
| 	case e1000_i210: | ||||
| 	case e1000_i211: | ||||
| 	case e1000_i350: | ||||
| 	case e1000_82580: | ||||
| 		adapter->caps.owner	= THIS_MODULE; | ||||
| @ -362,6 +364,8 @@ void igb_systim_to_hwtstamp(struct igb_adapter *adapter, | ||||
| 	unsigned long flags; | ||||
| 
 | ||||
| 	switch (adapter->hw.mac.type) { | ||||
| 	case e1000_i210: | ||||
| 	case e1000_i211: | ||||
| 	case e1000_i350: | ||||
| 	case e1000_82580: | ||||
| 	case e1000_82576: | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user