diff options
| author | david_yang <[email protected]> | 2019-12-25 09:38:04 +0800 |
|---|---|---|
| committer | adoyle <[email protected]> | 2020-05-15 17:06:23 +0000 |
| commit | 62972a74bd67cc29550b7a13dfd4fc97efd3d813 (patch) | |
| tree | 209b723913555e0bda24c707821030eb10ab4ff8 /machine | |
| parent | e1dacbe69336ac9e57571214d72b80b8f81fcf4c (diff) | |
Accton EBOF: add to support ONIE
The machine has 24x200GbE Fabric ports on
Marvell Falcon 98CX8520 switch ASIC.
CPU module is Intel Denverton C3558.
Signed-off-by: David Yang <[email protected]>
Signed-off-by: Alex Doyle <[email protected]>
Diffstat (limited to 'machine')
| -rw-r--r-- | machine/accton/accton_ebof/INSTALL | 110 | ||||
| -rw-r--r-- | machine/accton/accton_ebof/busybox/conf/config | 9 | ||||
| -rw-r--r-- | machine/accton/accton_ebof/demo/platform.conf | 1 | ||||
| -rw-r--r-- | machine/accton/accton_ebof/installer.conf | 30 | ||||
| -rw-r--r-- | machine/accton/accton_ebof/kernel/config | 8 | ||||
| -rw-r--r-- | machine/accton/accton_ebof/kernel/platform-ebof.patch | 114 | ||||
| -rw-r--r-- | machine/accton/accton_ebof/kernel/series | 3 | ||||
| -rw-r--r-- | machine/accton/accton_ebof/machine.make | 45 | ||||
| -rw-r--r-- | machine/accton/accton_ebof/rootconf/sysroot-lib-onie/sysinfo-platform | 12 | ||||
| -rw-r--r-- | machine/accton/kernel/driver-intel-ixgbe.patch | 3873 |
10 files changed, 2448 insertions, 1757 deletions
diff --git a/machine/accton/accton_ebof/INSTALL b/machine/accton/accton_ebof/INSTALL new file mode 100644 index 00000000..f58ec44e --- /dev/null +++ b/machine/accton/accton_ebof/INSTALL @@ -0,0 +1,110 @@ +============================== +Installing ONIE on Accton EBOF +============================== + +Cross-Compiling ONIE +==================== + +Change directories to ``build-config`` to compile ONIE. + +To compile ONIE first change directories to ``build-config`` and then +type ``"make MACHINEROOT=../machine/accton MACHINE=accton_ebof all"``. +For example:: + + $ cd build-config + $ make -j4 MACHINEROOT=../machine/accton MACHINE=accton_ebof all + +When complete, the ONIE binaries are located in +``build/images``:: + +-rw-rw-r-- 1 8217496 Sep 17 14:24 accton_ebof-r0.initrd +-rw-rw-r-- 1 3445024 Sep 17 14:23 accton_ebof-r0.vmlinuz +-rw-rw-r-- 1 25952256 Sep 17 14:25 onie-recovery-x86_64-accton_ebof-r0.iso +-rw-rw-r-- 1 11695991 Sep 17 14:24 onie-updater-x86_64-accton_ebof-r0 + +accton_ebof-r0.vmlinuz -- This is the ONIE kernel image + +accton_ebof-r0.initrd -- This is the ONIE initramfs (filesystem) + +onie-recovery-x86_64-accton_ebof-r0.iso -- This is the ONIE recovery +ISO image. This image can be used to create a bootable USB memory stick +for installing/recovery ONIE. + +onie-updater-x86_64-accton_ebof-r0 -- This is the ONIE self-update +image. This image is a self-extracting archive used for installing ONIE. + +Installing ONIE on a Blank Machine +================================== + +To install ONIE on a new machine, you can use the recovery ISO image to +create a bootable USB memory stick. + +Creating bootable USB stick +--------------------------- + +Use ``dd`` to copy the .iso image to a USB stick and boot from that:: + + dd if=<machine>.iso of=/dev/sdX bs=10M + +You can find the correct ``/dev/sdX`` by inspecing the ``dmesg`` +output after inserting the USB stick into your work station. + +Booting from USB stick +---------------------- + +To enable booting from USB in the BIOS: + +1. Insert the USB stick + +2. Power on the switch and enter the BIOS configuration + +3. Set the hard drive boot order: + + In "Boot Option #1" select the device that corresponds to your + device:: + + Boot-->Boot Option Priorities-->Boot Option #1 + + If the device name is not listed in "Boot Option #1", please + check the priorities in the hard drive boot order:: + + Boot-->Hard Drive BBS Priorities-->Boot Option #1 + + Taking ``JetFlashTranscend 8GB 8.07`` as an example, the boot + order will look like following:: + + Boot Option Priorities + Boot Option #1 [JetFlashTranscend 8...] + Boot Option #2 [ATP ATP IG eUSB 1100] + Boot Option #3 [IBA GE Slot 00A0 v1543] + Boot Option #4 [UEFI: Built-in EFI ...] + +4. Save and Exit the BIOS configuration + +5. After several seconds, you should see: + + GNU GRUB version 2.02~beta2+e4a1fe391 + + +----------------------------------------------------------------------------+ + |*ONIE: Rescue | + | ONIE: Embed ONIE | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +----------------------------------------------------------------------------+ + + Use the ^ and v keys to select which entry is highlighted. + Press enter to boot the selected OS, `e' to edit the commands + before booting or `c' for a command-line. + + - Choose ``ONIE: Embed ONIE`` for creating a fresh partition layout and + installing ONIE automatically. All data on the mass storage will be + erased. + - Choose ``ONIE: Rescue`` for entering ONIE recovery command-line shell. diff --git a/machine/accton/accton_ebof/busybox/conf/config b/machine/accton/accton_ebof/busybox/conf/config new file mode 100644 index 00000000..73e8351f --- /dev/null +++ b/machine/accton/accton_ebof/busybox/conf/config @@ -0,0 +1,9 @@ +CONFIG_SYS_EEPROM=y +CONFIG_SYS_EEPROM_DEVICE_I2C=y +CONFIG_SYS_EEPROM_I2C_DEVICE="/dev/i2c-1" +CONFIG_SYS_EEPROM_I2C_ADDR=0x57 +CONFIG_SYS_EEPROM_I2C_MEM_ADDR_BITS=8 +CONFIG_SYS_EEPROM_I2C_WRITE_2B_DELAY=5000 +CONFIG_SYS_EEPROM_OFFSET=0 +CONFIG_SYS_EEPROM_SIZE=256 +CONFIG_SYS_EEPROM_MAX_SIZE=256 diff --git a/machine/accton/accton_ebof/demo/platform.conf b/machine/accton/accton_ebof/demo/platform.conf new file mode 100644 index 00000000..b19b76f0 --- /dev/null +++ b/machine/accton/accton_ebof/demo/platform.conf @@ -0,0 +1 @@ +# ebof specific info diff --git a/machine/accton/accton_ebof/installer.conf b/machine/accton/accton_ebof/installer.conf new file mode 100644 index 00000000..84576516 --- /dev/null +++ b/machine/accton/accton_ebof/installer.conf @@ -0,0 +1,30 @@ +# Accton ebof ONIE installer configuration + +description="Accton, ebof" + +mass_dev="storage-not-found" +discover_mass_storage() +{ + mass_bus="$1" + for i in sda sdb sdc sdd ; do + if $(ls -l /sys/block/$i/device 2>/dev/null | grep -q "$mass_bus") ; then + mass_dev="/dev/$i" + return 0 + fi + done + return 1 +} + +# Default ONIE block device +install_device_platform() +{ + discover_mass_storage "target0:0:0" + ret=$? + echo "$mass_dev" + return $ret +} + +# Local Variables: +# mode: shell-script +# eval: (sh-set-shell "/bin/sh" t nil) +# End: diff --git a/machine/accton/accton_ebof/kernel/config b/machine/accton/accton_ebof/kernel/config new file mode 100644 index 00000000..29f22680 --- /dev/null +++ b/machine/accton/accton_ebof/kernel/config @@ -0,0 +1,8 @@ +CONFIG_IGB=y +CONFIG_I2C_I801=y +CONFIG_I2C_ISMT=y +# CONFIG_DCB is not set +CONFIG_IXGBE=y +CONFIG_IXGBE_HWMON=y +# CONFIG_E1000 is not set +# CONFIG_E1000E is not set diff --git a/machine/accton/accton_ebof/kernel/platform-ebof.patch b/machine/accton/accton_ebof/kernel/platform-ebof.patch new file mode 100644 index 00000000..dc0a5801 --- /dev/null +++ b/machine/accton/accton_ebof/kernel/platform-ebof.patch @@ -0,0 +1,114 @@ +changes for ebof board + +diff --git a/drivers/net/ethernet/intel/intel-igb/e1000_api.c b/drivers/net/ethernet/intel/intel-igb/e1000_api.c +index 2e4444f..b0fa862 100644 +--- a/drivers/net/ethernet/intel/intel-igb/e1000_api.c ++++ b/drivers/net/ethernet/intel/intel-igb/e1000_api.c +@@ -86,6 +86,7 @@ s32 e1000_init_nvm_params(struct e1000_hw *hw) + s32 e1000_init_phy_params(struct e1000_hw *hw) + { + s32 ret_val = E1000_SUCCESS; ++ return E1000_SUCCESS; + + if (hw->phy.ops.init_params) { + ret_val = hw->phy.ops.init_params(hw); +@@ -436,6 +437,7 @@ s32 e1000_reset_hw(struct e1000_hw *hw) + **/ + s32 e1000_init_hw(struct e1000_hw *hw) + { ++ return E1000_SUCCESS; + if (hw->mac.ops.init_hw) + return hw->mac.ops.init_hw(hw); + +diff --git a/drivers/net/ethernet/intel/intel-igb/igb_main.c b/drivers/net/ethernet/intel/intel-igb/igb_main.c +index 466ea85..6c9d242 100644 +--- a/drivers/net/ethernet/intel/intel-igb/igb_main.c ++++ b/drivers/net/ethernet/intel/intel-igb/igb_main.c +@@ -4724,6 +4724,7 @@ bool igb_has_link(struct igb_adapter *adapter) + { + struct e1000_hw *hw = &adapter->hw; + bool link_active = FALSE; ++ return true; + + /* get_link_status is set on LSC (link status) interrupt or + * rx sequence error interrupt. get_link_status will stay +diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +index f45caae..a1c5b74 100644 +--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c ++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +@@ -7105,6 +7105,46 @@ static int ixgbe_open(struct net_device *netdev) + #elif defined(HAVE_VXLAN_RX_OFFLOAD) + vxlan_get_rx_port(netdev); + #endif /* HAVE_UDP_ENC_RX_OFFLOAD */ ++ ++ if (adapter->hw.device_id == IXGBE_DEV_ID_X550EM_A_SGMII_L) { ++ struct ixgbe_hw ext_hw; ++ struct ixgbe_hw *hw_p = &ext_hw; ++ memcpy(hw_p, &adapter->hw, sizeof(struct ixgbe_hw)); ++ hw_p->phy.addr = 0x09; ++ hw_p->phy.ops.write_reg(hw_p, 0x00, 0x00, 0x104A); ++ msec_delay(50); ++ hw_p->phy.addr = 0x05; ++ hw_p->phy.ops.write_reg(hw_p, 0x1A, 0x1A, 0xA100); ++ msec_delay(50); ++ hw_p->phy.addr = 0x04; ++ hw_p->phy.ops.write_reg(hw_p, 0x1A, 0x1A, 0xFC80); ++ msec_delay(50); ++ hw_p->phy.addr = 0x04; ++ hw_p->phy.ops.write_reg(hw_p, 0x00, 0x00, 0x100A); ++ msec_delay(50); ++ hw_p->phy.addr = 0x05; ++ hw_p->phy.ops.write_reg(hw_p, 0x1A, 0x1A, 0x0A02); ++ msec_delay(50); ++ hw_p->phy.addr = 0x04; ++ hw_p->phy.ops.write_reg(hw_p, 0x1A, 0x1A, 0xFC82); ++ msec_delay(50); ++ hw_p->phy.addr = 0x1C; ++ hw_p->phy.ops.write_reg(hw_p, 0x19, 0x19, 0x2000); ++ msec_delay(50); ++ hw_p->phy.addr = 0x1C; ++ hw_p->phy.ops.write_reg(hw_p, 0x18, 0x18, 0x8284); ++ msec_delay(50); ++ hw_p->phy.addr = 0x1C; ++ hw_p->phy.ops.write_reg(hw_p, 0x19, 0x19, 0x9340); ++ msec_delay(50); ++ hw_p->phy.addr = 0x1C; ++ hw_p->phy.ops.write_reg(hw_p, 0x18, 0x18, 0x8684); ++ msec_delay(50); ++ hw_p->phy.addr = 0x04; ++ hw_p->phy.ops.write_reg(hw_p, 0x04, 0x04, 0x007F); ++ msec_delay(50); ++ } ++ + return IXGBE_SUCCESS; + + err_set_queues: +diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +index 2b366d9..07552ce 100644 +--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c ++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +@@ -584,8 +584,6 @@ static s32 ixgbe_identify_phy_fw(struct ixgbe_hw *hw) + hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM; + + hw->phy.type = ixgbe_phy_fw; +- hw->phy.ops.read_reg = NULL; +- hw->phy.ops.write_reg = NULL; + return ixgbe_get_phy_id_fw(hw); + } + +@@ -2364,10 +2362,11 @@ s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw) + switch (hw->device_id) { + case IXGBE_DEV_ID_X550EM_A_1G_T: + case IXGBE_DEV_ID_X550EM_A_1G_T_L: +- phy->ops.read_reg_mdi = NULL; +- phy->ops.write_reg_mdi = NULL; +- hw->phy.ops.read_reg = NULL; +- hw->phy.ops.write_reg = NULL; ++ case IXGBE_DEV_ID_X550EM_A_SGMII_L: ++ phy->ops.read_reg_mdi = ixgbe_read_phy_reg_mdi_22; ++ phy->ops.write_reg_mdi = ixgbe_write_phy_reg_mdi_22; ++ hw->phy.ops.read_reg = ixgbe_read_phy_reg_x550a; ++ hw->phy.ops.write_reg = ixgbe_write_phy_reg_x550a; + phy->ops.check_overtemp = ixgbe_check_overtemp_fw; + if (hw->bus.lan_id) + hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY1_SM; diff --git a/machine/accton/accton_ebof/kernel/series b/machine/accton/accton_ebof/kernel/series new file mode 100644 index 00000000..2f37b2a4 --- /dev/null +++ b/machine/accton/accton_ebof/kernel/series @@ -0,0 +1,3 @@ +driver-intel-igb.patch +driver-intel-ixgbe.patch +platform-ebof.patch diff --git a/machine/accton/accton_ebof/machine.make b/machine/accton/accton_ebof/machine.make new file mode 100644 index 00000000..9afd67e8 --- /dev/null +++ b/machine/accton/accton_ebof/machine.make @@ -0,0 +1,45 @@ +# Accton EBOF + +# Vendor's version number can be defined here. +# Available variable is 'VENDOR_VERSION'. +# e.g., +# VENDOR_VERSION = .00.01 + +ONIE_ARCH ?= x86_64 +SWITCH_ASIC_VENDOR = mvl + +VENDOR_REV ?= 0 + +# Translate hardware revision to ONIE hardware revision +ifeq ($(VENDOR_REV),0) + MACHINE_REV = 0 +else + $(warning Unknown VENDOR_REV '$(VENDOR_REV)' for MACHINE '$(MACHINE)') + $(error Unknown VENDOR_REV) +endif + +# Vendor ID -- IANA Private Enterprise Number: +# http://www.iana.org/assignments/enterprise-numbers +# Accton Technology Corporation IANA number +VENDOR_ID = 259 + +SKIP_ETHMGMT_MACS = yes +EXTRA_CMDLINE_LINUX = acpi=off + +UEFI_ENABLE = yes +PXE_EFI64_ENABLE = yes + +# Console parameters +CONSOLE_DEV = 0 + +# Set Linux kernel version +LINUX_VERSION = 4.9 +LINUX_MINOR_VERSION = 95 + +GCC_VERSION = 4.9.2 + +#------------------------------------------------------------------------------- +# +# Local Variables: +# mode: makefile-gmake +# End: diff --git a/machine/accton/accton_ebof/rootconf/sysroot-lib-onie/sysinfo-platform b/machine/accton/accton_ebof/rootconf/sysroot-lib-onie/sysinfo-platform new file mode 100644 index 00000000..f5b4b43e --- /dev/null +++ b/machine/accton/accton_ebof/rootconf/sysroot-lib-onie/sysinfo-platform @@ -0,0 +1,12 @@ + +# Use the contents of /sys/class/net/eth0/address + +get_ethaddr() +{ + [ -r /sys/class/net/eth0/address ] && cat /sys/class/net/eth0/address +} + +# Local Variables: +# mode: shell-script +# eval: (sh-set-shell "/bin/sh" t nil) +# End: diff --git a/machine/accton/kernel/driver-intel-ixgbe.patch b/machine/accton/kernel/driver-intel-ixgbe.patch index 65adac37..f19abc5b 100644 --- a/machine/accton/kernel/driver-intel-ixgbe.patch +++ b/machine/accton/kernel/driver-intel-ixgbe.patch @@ -50306,7 +50306,7 @@ index e21cd48..4427c92 100644 +s32 ixgbe_blink_led_stop_X540(struct ixgbe_hw *hw, u32 index); +#endif /* _IXGBE_X540_H_ */ diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c -index 77a60aa..ad9df6e 100644 +index 77a60aa..2b366d9 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -1,62 +1,95 @@ @@ -50684,7 +50684,7 @@ index 77a60aa..ad9df6e 100644 goto out; } -@@ -249,1018 +292,1257 @@ static void ixgbe_check_cs4227(struct ixgbe_hw *hw) +@@ -249,2045 +292,3538 @@ static void ixgbe_check_cs4227(struct ixgbe_hw *hw) ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH, IXGBE_CS4227_RESET_PENDING); hw->mac.ops.release_swfw_sync(hw, swfw_mask); @@ -50729,6 +50729,101 @@ index 77a60aa..ad9df6e 100644 + IXGBE_WRITE_FLUSH(hw); +} + ++ /** ++ * ixgbe_read_phy_reg_mdi_22 - Read from a clause 22 PHY register without lock ++ * @hw: pointer to hardware structure ++ * @reg_addr: 32 bit address of PHY register to read ++ * @dev_type: always unused ++ * @phy_data: Pointer to read data from PHY register ++ */ ++STATIC s32 ixgbe_read_phy_reg_mdi_22(struct ixgbe_hw *hw, u32 reg_addr, ++ u32 dev_type, u16 *phy_data) ++{ ++ u32 i, data, command; ++ UNREFERENCED_1PARAMETER(dev_type); ++ ++ ++ //hw->phy.addr=0x09; ++ /* Setup and write the read command */ ++ command = (reg_addr << IXGBE_MSCA_DEV_TYPE_SHIFT) | ++ (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) | ++ IXGBE_MSCA_OLD_PROTOCOL | IXGBE_MSCA_READ_AUTOINC | ++ IXGBE_MSCA_MDI_COMMAND; ++ ++ IXGBE_WRITE_REG(hw, IXGBE_MSCA, command); ++ ++ /* Check every 10 usec to see if the access completed. ++ * The MDI Command bit will clear when the operation is ++ * complete ++ */ ++ for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { ++ usec_delay(10); ++ ++ command = IXGBE_READ_REG(hw, IXGBE_MSCA); ++ if (!(command & IXGBE_MSCA_MDI_COMMAND)) ++ break; ++ } ++ ++ if (command & IXGBE_MSCA_MDI_COMMAND) { ++ ERROR_REPORT1(IXGBE_ERROR_POLLING, ++ "PHY read command did not complete.\n"); ++ return IXGBE_ERR_PHY; ++ } ++ ++ /* Read operation is complete. Get the data from MSRWD */ ++ data = IXGBE_READ_REG(hw, IXGBE_MSRWD); ++ data >>= IXGBE_MSRWD_READ_DATA_SHIFT; ++ *phy_data = (u16)data; ++ ++ return IXGBE_SUCCESS; ++} ++ ++/** ++ * ixgbe_write_phy_reg_mdi_22 - Write to a clause 22 PHY register without lock ++ * @hw: pointer to hardware structure ++ * @reg_addr: 32 bit PHY register to write ++ * @dev_type: always unused ++ * @phy_data: Data to write to the PHY register ++ */ ++STATIC s32 ixgbe_write_phy_reg_mdi_22(struct ixgbe_hw *hw, u32 reg_addr, ++ u32 dev_type, u16 phy_data) ++{ ++ u32 i, command; ++ UNREFERENCED_1PARAMETER(dev_type); ++ ++ //hw->phy.addr = 0x09; ++ /* Put the data in the MDI single read and write data register*/ ++ IXGBE_WRITE_REG(hw, IXGBE_MSRWD, (u32)phy_data); ++ ++ /* Setup and write the write command */ ++ command = (reg_addr << IXGBE_MSCA_DEV_TYPE_SHIFT) | ++ (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) | ++ IXGBE_MSCA_OLD_PROTOCOL | IXGBE_MSCA_WRITE | ++ IXGBE_MSCA_MDI_COMMAND; ++ ++ IXGBE_WRITE_REG(hw, IXGBE_MSCA, command); ++ ++ /* Check every 10 usec to see if the access completed. ++ * The MDI Command bit will clear when the operation is ++ * complete ++ */ ++ for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { ++ usec_delay(10); ++ ++ command = IXGBE_READ_REG(hw, IXGBE_MSCA); ++ if (!(command & IXGBE_MSCA_MDI_COMMAND)) ++ break; ++ } ++ ++ if (command & IXGBE_MSCA_MDI_COMMAND) { ++ ERROR_REPORT1(IXGBE_ERROR_POLLING, ++ "PHY write cmd didn't complete\n"); ++ return IXGBE_ERR_PHY; ++ } ++ ++ return IXGBE_SUCCESS; ++} ++ +/** + * ixgbe_identify_phy_x550em - Get PHY type based on device id + * @hw: pointer to hardware structure @@ -50976,20 +51071,13 @@ index 77a60aa..ad9df6e 100644 + setup[0] = FW_PHY_ACT_FORCE_LINK_DOWN_OFF; + return ixgbe_fw_phy_activity(hw, FW_PHY_ACT_FORCE_LINK_DOWN, &setup); +} -+ + +- return 0; +STATIC s32 ixgbe_read_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr, + u32 device_type, u16 *phy_data) +{ + UNREFERENCED_4PARAMETER(*hw, reg_addr, device_type, *phy_data); + return IXGBE_NOT_IMPLEMENTED; -+} - -- return 0; -+STATIC s32 ixgbe_write_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr, -+ u32 device_type, u16 phy_data) -+{ -+ UNREFERENCED_4PARAMETER(*hw, reg_addr, device_type, phy_data); -+ return IXGBE_NOT_IMPLEMENTED; } -/** ixgbe_read_iosf_sb_reg_x550 - Writes a value to specified register of the @@ -50998,6 +51086,13 @@ index 77a60aa..ad9df6e 100644 - * @reg_addr: 32 bit PHY register to write - * @device_type: 3 bit device type - * @phy_data: Pointer to read data from the register ++STATIC s32 ixgbe_write_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr, ++ u32 device_type, u16 phy_data) ++{ ++ UNREFERENCED_4PARAMETER(*hw, reg_addr, device_type, phy_data); ++ return IXGBE_NOT_IMPLEMENTED; ++} ++ +/** + * ixgbe_read_i2c_combined_generic - Perform I2C read combined operation + * @hw: pointer to the hardware structure @@ -51353,7 +51448,9 @@ index 77a60aa..ad9df6e 100644 - struct ixgbe_hic_internal_phy_resp rsp; - } hic; - s32 status; -- ++ struct ixgbe_mac_info *mac = &hw->mac; ++ s32 ret_val; + - memset(&hic, 0, sizeof(hic)); - hic.cmd.hdr.cmd = FW_INT_PHY_REQ_CMD; - hic.cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN; @@ -51361,20 +51458,15 @@ index 77a60aa..ad9df6e 100644 - hic.cmd.port_number = hw->bus.lan_id; - hic.cmd.command_type = FW_INT_PHY_REQ_READ; - hic.cmd.address = cpu_to_be16(reg_addr); -+ struct ixgbe_mac_info *mac = &hw->mac; -+ s32 ret_val; ++ DEBUGFUNC("ixgbe_init_ops_X550EM_a"); - status = ixgbe_host_interface_command(hw, &hic.cmd, sizeof(hic.cmd), - IXGBE_HI_COMMAND_TIMEOUT, true); -+ DEBUGFUNC("ixgbe_init_ops_X550EM_a"); - -- /* Extract the register value from the response. */ -- *data = be32_to_cpu(hic.rsp.read_data); + /* Start with generic X550EM init */ + ret_val = ixgbe_init_ops_X550EM(hw); -- return status; --} +- /* Extract the register value from the response. */ +- *data = be32_to_cpu(hic.rsp.read_data); + if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII || + hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII_L) { + mac->ops.read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550; @@ -51386,19 +51478,7 @@ index 77a60aa..ad9df6e 100644 + mac->ops.acquire_swfw_sync = ixgbe_acquire_swfw_sync_X550a; + mac->ops.release_swfw_sync = ixgbe_release_swfw_sync_X550a; --/** ixgbe_read_ee_hostif_data_X550 - Read EEPROM word using a host interface -- * command assuming that the semaphore is already obtained. -- * @hw: pointer to hardware structure -- * @offset: offset of word in the EEPROM to read -- * @data: word read from the EEPROM -- * -- * Reads a 16 bit word from the EEPROM using the hostif. -- **/ --static s32 ixgbe_read_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset, -- u16 *data) --{ -- s32 status; -- struct ixgbe_hic_read_shadow_ram buffer; +- return status; + switch (mac->ops.get_media_type(hw)) { + case ixgbe_media_type_fiber: + mac->ops.setup_fc = NULL; @@ -51411,11 +51491,7 @@ index 77a60aa..ad9df6e 100644 + default: + break; + } - -- buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; -- buffer.hdr.req.buf_lenh = 0; -- buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; -- buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; ++ + switch (hw->device_id) { + case IXGBE_DEV_ID_X550EM_A_1G_T: + case IXGBE_DEV_ID_X550EM_A_1G_T_L: @@ -51429,18 +51505,10 @@ index 77a60aa..ad9df6e 100644 + default: + break; + } - -- /* convert offset from words to bytes */ -- buffer.address = cpu_to_be32(offset * 2); -- /* one word */ -- buffer.length = cpu_to_be16(sizeof(u16)); ++ + return ret_val; +} - -- status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer), -- IXGBE_HI_COMMAND_TIMEOUT, false); -- if (status) -- return status; ++ +/** +* ixgbe_init_ops_X550EM_x - Inits func ptrs and MAC type +* @hw: pointer to hardware structure @@ -51453,9 +51521,7 @@ index 77a60aa..ad9df6e 100644 + struct ixgbe_mac_info *mac = &hw->mac; + struct ixgbe_link_info *link = &hw->link; + s32 ret_val; - -- *data = (u16)IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, -- FW_NVM_DATA_OFFSET); ++ + DEBUGFUNC("ixgbe_init_ops_X550EM_x"); + + /* Start with generic X550EM init */ @@ -51477,66 +51543,180 @@ index 77a60aa..ad9df6e 100644 + mac->ops.setup_eee = NULL; + mac->ops.init_led_link_act = NULL; + } ++ ++ return ret_val; + } + +-/** ixgbe_read_ee_hostif_data_X550 - Read EEPROM word using a host interface +- * command assuming that the semaphore is already obtained. ++/** ++ * ixgbe_dmac_config_X550 + * @hw: pointer to hardware structure +- * @offset: offset of word in the EEPROM to read +- * @data: word read from the EEPROM + * +- * Reads a 16 bit word from the EEPROM using the hostif. ++ * Configure DMA coalescing. If enabling dmac, dmac is activated. ++ * When disabling dmac, dmac enable dmac bit is cleared. + **/ +-static s32 ixgbe_read_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset, +- u16 *data) ++s32 ixgbe_dmac_config_X550(struct ixgbe_hw *hw) + { +- s32 status; +- struct ixgbe_hic_read_shadow_ram buffer; ++ u32 reg, high_pri_tc; + +- buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; +- buffer.hdr.req.buf_lenh = 0; +- buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; +- buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; ++ DEBUGFUNC("ixgbe_dmac_config_X550"); + +- /* convert offset from words to bytes */ +- buffer.address = cpu_to_be32(offset * 2); +- /* one word */ +- buffer.length = cpu_to_be16(sizeof(u16)); ++ /* Disable DMA coalescing before configuring */ ++ reg = IXGBE_READ_REG(hw, IXGBE_DMACR); ++ reg &= ~IXGBE_DMACR_DMAC_EN; ++ IXGBE_WRITE_REG(hw, IXGBE_DMACR, reg); + +- status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer), +- IXGBE_HI_COMMAND_TIMEOUT, false); +- if (status) +- return status; ++ /* Disable DMA Coalescing if the watchdog timer is 0 */ ++ if (!hw->mac.dmac_config.watchdog_timer) ++ goto out; ++ ++ ixgbe_dmac_config_tcs_X550(hw); + +- *data = (u16)IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, +- FW_NVM_DATA_OFFSET); ++ /* Configure DMA Coalescing Control Register */ ++ reg = IXGBE_READ_REG(hw, IXGBE_DMACR); - return 0; -+ return ret_val; ++ /* Set the watchdog timer in units of 40.96 usec */ ++ reg &= ~IXGBE_DMACR_DMACWT_MASK; ++ reg |= (hw->mac.dmac_config.watchdog_timer * 100) / 4096; ++ ++ reg &= ~IXGBE_DMACR_HIGH_PRI_TC_MASK; ++ /* If fcoe is enabled, set high priority traffic class */ ++ if (hw->mac.dmac_config.fcoe_en) { ++ high_pri_tc = 1 << hw->mac.dmac_config.fcoe_tc; ++ reg |= ((high_pri_tc << IXGBE_DMACR_HIGH_PRI_TC_SHIFT) & ++ IXGBE_DMACR_HIGH_PRI_TC_MASK); ++ } ++ reg |= IXGBE_DMACR_EN_MNG_IND; ++ ++ /* Enable DMA coalescing after configuration */ ++ reg |= IXGBE_DMACR_DMAC_EN; ++ IXGBE_WRITE_REG(hw, IXGBE_DMACR, reg); ++ ++out: ++ return IXGBE_SUCCESS; } -/** ixgbe_read_ee_hostif_buffer_X550- Read EEPROM word(s) using hostif +/** -+ * ixgbe_dmac_config_X550 ++ * ixgbe_dmac_config_tcs_X550 * @hw: pointer to hardware structure - * @offset: offset of word in the EEPROM to read - * @words: number of words - * @data: word(s) read from the EEPROM * - * Reads a 16 bit word(s) from the EEPROM using the hostif. -+ * Configure DMA coalescing. If enabling dmac, dmac is activated. -+ * When disabling dmac, dmac enable dmac bit is cleared. ++ * Configure DMA coalescing threshold per TC. The dmac enable bit must ++ * be cleared before configuring. **/ -static s32 ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw *hw, - u16 offset, u16 words, u16 *data) -+s32 ixgbe_dmac_config_X550(struct ixgbe_hw *hw) ++s32 ixgbe_dmac_config_tcs_X550(struct ixgbe_hw *hw) { - struct ixgbe_hic_read_shadow_ram buffer; - u32 current_word = 0; - u16 words_to_read; - s32 status; - u32 i; -+ u32 reg, high_pri_tc; ++ u32 tc, reg, pb_headroom, rx_pb_size, maxframe_size_kb; - /* Take semaphore for the entire operation. */ - status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM); - if (status) { - hw_dbg(hw, "EEPROM read buffer - semaphore failed\n"); - return status; -- } -+ DEBUGFUNC("ixgbe_dmac_config_X550"); ++ DEBUGFUNC("ixgbe_dmac_config_tcs_X550"); ++ ++ /* Configure DMA coalescing enabled */ ++ switch (hw->mac.dmac_config.link_speed) { ++ case IXGBE_LINK_SPEED_10_FULL: ++ case IXGBE_LINK_SPEED_100_FULL: ++ pb_headroom = IXGBE_DMACRXT_100M; ++ break; ++ case IXGBE_LINK_SPEED_1GB_FULL: ++ pb_headroom = IXGBE_DMACRXT_1G; ++ break; ++ default: ++ pb_headroom = IXGBE_DMACRXT_10G; ++ break; + } - while (words) { - if (words > FW_MAX_READ_BUFFER_SIZE / 2) - words_to_read = FW_MAX_READ_BUFFER_SIZE / 2; - else - words_to_read = words; -+ /* Disable DMA coalescing before configuring */ -+ reg = IXGBE_READ_REG(hw, IXGBE_DMACR); -+ reg &= ~IXGBE_DMACR_DMAC_EN; -+ IXGBE_WRITE_REG(hw, IXGBE_DMACR, reg); ++ maxframe_size_kb = ((IXGBE_READ_REG(hw, IXGBE_MAXFRS) >> ++ IXGBE_MHADD_MFS_SHIFT) / 1024); ++ ++ /* Set the per Rx packet buffer receive threshold */ ++ for (tc = 0; tc < IXGBE_DCB_MAX_TRAFFIC_CLASS; tc++) { ++ reg = IXGBE_READ_REG(hw, IXGBE_DMCTH(tc)); ++ reg &= ~IXGBE_DMCTH_DMACRXT_MASK; ++ ++ if (tc < hw->mac.dmac_config.num_tcs) { ++ /* Get Rx PB size */ ++ rx_pb_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(tc)); ++ rx_pb_size = (rx_pb_size & IXGBE_RXPBSIZE_MASK) >> ++ IXGBE_RXPBSIZE_SHIFT; ++ ++ /* Calculate receive buffer threshold in kilobytes */ ++ if (rx_pb_size > pb_headroom) ++ rx_pb_size = rx_pb_size - pb_headroom; ++ else ++ rx_pb_size = 0; ++ ++ /* Minimum of MFS shall be set for DMCTH */ ++ reg |= (rx_pb_size > maxframe_size_kb) ? ++ rx_pb_size : maxframe_size_kb; ++ } ++ IXGBE_WRITE_REG(hw, IXGBE_DMCTH(tc), reg); ++ } ++ return IXGBE_SUCCESS; ++} - buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; - buffer.hdr.req.buf_lenh = 0; - buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; - buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; -+ /* Disable DMA Coalescing if the watchdog timer is 0 */ -+ if (!hw->mac.dmac_config.watchdog_timer) -+ goto out; ++/** ++ * ixgbe_dmac_update_tcs_X550 ++ * @hw: pointer to hardware structure ++ * ++ * Disables dmac, updates per TC settings, and then enables dmac. ++ **/ ++s32 ixgbe_dmac_update_tcs_X550(struct ixgbe_hw *hw) ++{ ++ u32 reg; - /* convert offset from words to bytes */ - buffer.address = cpu_to_be32((offset + current_word) * 2); - buffer.length = cpu_to_be16(words_to_read * 2); - buffer.pad2 = 0; - buffer.pad3 = 0; -+ ixgbe_dmac_config_tcs_X550(hw); ++ DEBUGFUNC("ixgbe_dmac_update_tcs_X550"); - status = ixgbe_host_interface_command(hw, &buffer, - sizeof(buffer), @@ -51546,16 +51726,16 @@ index 77a60aa..ad9df6e 100644 - hw_dbg(hw, "Host interface command failed\n"); - goto out; - } -+ /* Configure DMA Coalescing Control Register */ ++ /* Disable DMA coalescing before configuring */ + reg = IXGBE_READ_REG(hw, IXGBE_DMACR); ++ reg &= ~IXGBE_DMACR_DMAC_EN; ++ IXGBE_WRITE_REG(hw, IXGBE_DMACR, reg); - for (i = 0; i < words_to_read; i++) { - u32 reg = IXGBE_FLEX_MNG + (FW_NVM_DATA_OFFSET << 2) + - 2 * i; - u32 value = IXGBE_READ_REG(hw, reg); -+ /* Set the watchdog timer in units of 40.96 usec */ -+ reg &= ~IXGBE_DMACR_DMACWT_MASK; -+ reg |= (hw->mac.dmac_config.watchdog_timer * 100) / 4096; ++ ixgbe_dmac_config_tcs_X550(hw); - data[current_word] = (u16)(value & 0xffff); - current_word++; @@ -51567,20 +51747,13 @@ index 77a60aa..ad9df6e 100644 - } - } - words -= words_to_read; -+ reg &= ~IXGBE_DMACR_HIGH_PRI_TC_MASK; -+ /* If fcoe is enabled, set high priority traffic class */ -+ if (hw->mac.dmac_config.fcoe_en) { -+ high_pri_tc = 1 << hw->mac.dmac_config.fcoe_tc; -+ reg |= ((high_pri_tc << IXGBE_DMACR_HIGH_PRI_TC_SHIFT) & -+ IXGBE_DMACR_HIGH_PRI_TC_MASK); - } -+ reg |= IXGBE_DMACR_EN_MNG_IND; -+ +- } + /* Enable DMA coalescing after configuration */ ++ reg = IXGBE_READ_REG(hw, IXGBE_DMACR); + reg |= IXGBE_DMACR_DMAC_EN; + IXGBE_WRITE_REG(hw, IXGBE_DMACR, reg); - out: +-out: - hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); - return status; + return IXGBE_SUCCESS; @@ -51588,29 +51761,31 @@ index 77a60aa..ad9df6e 100644 -/** ixgbe_checksum_ptr_x550 - Checksum one pointer region +/** -+ * ixgbe_dmac_config_tcs_X550 ++ * ixgbe_init_eeprom_params_X550 - Initialize EEPROM params * @hw: pointer to hardware structure - * @ptr: pointer offset in eeprom - * @size: size of section pointed by ptr, if 0 first word will be used as size - * @csum: address of checksum to update * - * Returns error status for any failure -+ * Configure DMA coalescing threshold per TC. The dmac enable bit must -+ * be cleared before configuring. ++ * Initializes the EEPROM parameters ixgbe_eeprom_info within the ++ * ixgbe_hw struct in order to set up EEPROM access. **/ -static s32 ixgbe_checksum_ptr_x550(struct ixgbe_hw *hw, u16 ptr, - u16 size, u16 *csum, u16 *buffer, - u32 buffer_size) -+s32 ixgbe_dmac_config_tcs_X550(struct ixgbe_hw *hw) ++s32 ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw) { - u16 buf[256]; - s32 status; - u16 length, bufsz, i, start; - u16 *local_buffer; -+ u32 tc, reg, pb_headroom, rx_pb_size, maxframe_size_kb; ++ struct ixgbe_eeprom_info *eeprom = &hw->eeprom; ++ u32 eec; ++ u16 eeprom_size; - bufsz = sizeof(buf) / sizeof(buf[0]); -+ DEBUGFUNC("ixgbe_dmac_config_tcs_X550"); ++ DEBUGFUNC("ixgbe_init_eeprom_params_X550"); - /* Read a chunk at the pointer location */ - if (!buffer) { @@ -51618,53 +51793,16 @@ index 77a60aa..ad9df6e 100644 - if (status) { - hw_dbg(hw, "Failed to read EEPROM image\n"); - return status; -+ /* Configure DMA coalescing enabled */ -+ switch (hw->mac.dmac_config.link_speed) { -+ case IXGBE_LINK_SPEED_10_FULL: -+ case IXGBE_LINK_SPEED_100_FULL: -+ pb_headroom = IXGBE_DMACRXT_100M; -+ break; -+ case IXGBE_LINK_SPEED_1GB_FULL: -+ pb_headroom = IXGBE_DMACRXT_1G; -+ break; -+ default: -+ pb_headroom = IXGBE_DMACRXT_10G; -+ break; -+ } -+ -+ maxframe_size_kb = ((IXGBE_READ_REG(hw, IXGBE_MAXFRS) >> -+ IXGBE_MHADD_MFS_SHIFT) / 1024); -+ -+ /* Set the per Rx packet buffer receive threshold */ -+ for (tc = 0; tc < IXGBE_DCB_MAX_TRAFFIC_CLASS; tc++) { -+ reg = IXGBE_READ_REG(hw, IXGBE_DMCTH(tc)); -+ reg &= ~IXGBE_DMCTH_DMACRXT_MASK; -+ -+ if (tc < hw->mac.dmac_config.num_tcs) { -+ /* Get Rx PB size */ -+ rx_pb_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(tc)); -+ rx_pb_size = (rx_pb_size & IXGBE_RXPBSIZE_MASK) >> -+ IXGBE_RXPBSIZE_SHIFT; -+ -+ /* Calculate receive buffer threshold in kilobytes */ -+ if (rx_pb_size > pb_headroom) -+ rx_pb_size = rx_pb_size - pb_headroom; -+ else -+ rx_pb_size = 0; -+ -+ /* Minimum of MFS shall be set for DMCTH */ -+ reg |= (rx_pb_size > maxframe_size_kb) ? -+ rx_pb_size : maxframe_size_kb; - } +- } - local_buffer = buf; - } else { - if (buffer_size < ptr) - return IXGBE_ERR_PARAM; - local_buffer = &buffer[ptr]; -+ IXGBE_WRITE_REG(hw, IXGBE_DMCTH(tc), reg); - } -+ return IXGBE_SUCCESS; -+} +- } ++ if (eeprom->type == ixgbe_eeprom_uninitialized) { ++ eeprom->semaphore_delay = 10; ++ eeprom->type = ixgbe_flash; - if (size) { - start = 0; @@ -51672,38 +51810,30 @@ index 77a60aa..ad9df6e 100644 - } else { - start = 1; - length = local_buffer[0]; -+/** -+ * ixgbe_dmac_update_tcs_X550 -+ * @hw: pointer to hardware structure -+ * -+ * Disables dmac, updates per TC settings, and then enables dmac. -+ **/ -+s32 ixgbe_dmac_update_tcs_X550(struct ixgbe_hw *hw) -+{ -+ u32 reg; ++ eec = IXGBE_READ_REG(hw, IXGBE_EEC); ++ eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> ++ IXGBE_EEC_SIZE_SHIFT); ++ eeprom->word_size = 1 << (eeprom_size + ++ IXGBE_EEPROM_WORD_SIZE_SHIFT); - /* Skip pointer section if length is invalid. */ - if (length == 0xFFFF || length == 0 || - (ptr + length) >= hw->eeprom.word_size) - return 0; -- } -+ DEBUGFUNC("ixgbe_dmac_update_tcs_X550"); ++ DEBUGOUT2("Eeprom params: type = %d, size = %d\n", ++ eeprom->type, eeprom->word_size); + } - if (buffer && ((u32)start + (u32)length > buffer_size)) - return IXGBE_ERR_PARAM; -+ /* Disable DMA coalescing before configuring */ -+ reg = IXGBE_READ_REG(hw, IXGBE_DMACR); -+ reg &= ~IXGBE_DMACR_DMAC_EN; -+ IXGBE_WRITE_REG(hw, IXGBE_DMACR, reg); - +- - for (i = start; length; i++, length--) { - if (i == bufsz && !buffer) { - ptr += bufsz; - i = 0; - if (length < bufsz) - bufsz = length; -+ ixgbe_dmac_config_tcs_X550(hw); - +- - /* Read a chunk at the pointer location */ - status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, - bufsz, buf); @@ -51715,41 +51845,34 @@ index 77a60aa..ad9df6e 100644 - *csum += local_buffer[i]; - } - return 0; -+ /* Enable DMA coalescing after configuration */ -+ reg = IXGBE_READ_REG(hw, IXGBE_DMACR); -+ reg |= IXGBE_DMACR_DMAC_EN; -+ IXGBE_WRITE_REG(hw, IXGBE_DMACR, reg); -+ + return IXGBE_SUCCESS; } -/** ixgbe_calc_checksum_X550 - Calculates and returns the checksum -+/** -+ * ixgbe_init_eeprom_params_X550 - Initialize EEPROM params - * @hw: pointer to hardware structure +- * @hw: pointer to hardware structure - * @buffer: pointer to buffer containing calculated checksum - * @buffer_size: size of buffer - * +- * - * Returns a negative error code on error, or the 16-bit checksum -+ * Initializes the EEPROM parameters ixgbe_eeprom_info within the -+ * ixgbe_hw struct in order to set up EEPROM access. ++/** ++ * ixgbe_set_source_address_pruning_X550 - Enable/Disbale source address pruning ++ * @hw: pointer to hardware structure ++ * @enable: enable or disable source address pruning ++ * @pool: Rx pool to set source address pruning for **/ -static s32 ixgbe_calc_checksum_X550(struct ixgbe_hw *hw, u16 *buffer, - u32 buffer_size) -+s32 ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw) ++void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw, bool enable, ++ unsigned int pool) { - u16 eeprom_ptrs[IXGBE_EEPROM_LAST_WORD + 1]; - u16 *local_buffer; - s32 status; - u16 checksum = 0; - u16 pointer, i, size; -+ struct ixgbe_eeprom_info *eeprom = &hw->eeprom; -+ u32 eec; -+ u16 eeprom_size; - +- - hw->eeprom.ops.init_params(hw); -+ DEBUGFUNC("ixgbe_init_eeprom_params_X550"); - +- - if (!buffer) { - /* Read pointer area */ - status = ixgbe_read_ee_hostif_buffer_X550(hw, 0, @@ -51765,49 +51888,27 @@ index 77a60aa..ad9df6e 100644 - return IXGBE_ERR_PARAM; - local_buffer = buffer; - } -+ if (eeprom->type == ixgbe_eeprom_uninitialized) { -+ eeprom->semaphore_delay = 10; -+ eeprom->type = ixgbe_flash; - +- - /* For X550 hardware include 0x0-0x41 in the checksum, skip the - * checksum word itself - */ - for (i = 0; i <= IXGBE_EEPROM_LAST_WORD; i++) - if (i != IXGBE_EEPROM_CHECKSUM) - checksum += local_buffer[i]; -+ eec = IXGBE_READ_REG(hw, IXGBE_EEC); -+ eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> -+ IXGBE_EEC_SIZE_SHIFT); -+ eeprom->word_size = 1 << (eeprom_size + -+ IXGBE_EEPROM_WORD_SIZE_SHIFT); - +- - /* Include all data from pointers 0x3, 0x6-0xE. This excludes the - * FW, PHY module, and PCIe Expansion/Option ROM pointers. - */ - for (i = IXGBE_PCIE_ANALOG_PTR_X550; i < IXGBE_FW_PTR; i++) { - if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR) - continue; -+ DEBUGOUT2("Eeprom params: type = %d, size = %d\n", -+ eeprom->type, eeprom->word_size); -+ } - +- - pointer = local_buffer[i]; -+ return IXGBE_SUCCESS; -+} - +- - /* Skip pointer section if the pointer is invalid. */ - if (pointer == 0xFFFF || pointer == 0 || - pointer >= hw->eeprom.word_size) - continue; -+/** -+ * ixgbe_set_source_address_pruning_X550 - Enable/Disbale source address pruning -+ * @hw: pointer to hardware structure -+ * @enable: enable or disable source address pruning -+ * @pool: Rx pool to set source address pruning for -+ **/ -+void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw, bool enable, -+ unsigned int pool) -+{ + u64 pfflp; - switch (i) { @@ -51859,155 +51960,116 @@ index 77a60aa..ad9df6e 100644 + bool enable, int vf) { - return ixgbe_calc_checksum_X550(hw, NULL, 0); +-} + int vf_target_reg = vf >> 3; + int vf_target_shift = vf % 8 + IXGBE_SPOOF_ETHERTYPEAS_SHIFT; + u32 pfvfspoof; -+ -+ DEBUGFUNC("ixgbe_set_ethertype_anti_spoofing_X550"); -+ -+ pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); -+ if (enable) -+ pfvfspoof |= (1 << vf_target_shift); -+ else -+ pfvfspoof &= ~(1 << vf_target_shift); -+ -+ IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); - } -/** ixgbe_read_ee_hostif_X550 - Read EEPROM word using a host interface command - * @hw: pointer to hardware structure - * @offset: offset of word in the EEPROM to read - * @data: word read from the EEPROM -+/** -+ * ixgbe_iosf_wait - Wait for IOSF command completion -+ * @hw: pointer to hardware structure -+ * @ctrl: pointer to location to receive final IOSF control value - * +- * - * Reads a 16 bit word from the EEPROM using the hostif. -+ * Returns failing status on timeout -+ * -+ * Note: ctrl can be NULL if the IOSF control register value is not needed - **/ +- **/ -static s32 ixgbe_read_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 *data) -+STATIC s32 ixgbe_iosf_wait(struct ixgbe_hw *hw, u32 *ctrl) - { +-{ - s32 status = 0; -+ u32 i, command = 0; ++ DEBUGFUNC("ixgbe_set_ethertype_anti_spoofing_X550"); - if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) { - status = ixgbe_read_ee_hostif_data_X550(hw, offset, data); - hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); - } else { - status = IXGBE_ERR_SWFW_SYNC; -+ /* Check every 10 usec to see if the address cycle completed. -+ * The SB IOSF BUSY bit will clear when the operation is -+ * complete -+ */ -+ for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { -+ command = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL); -+ if ((command & IXGBE_SB_IOSF_CTRL_BUSY) == 0) -+ break; -+ usec_delay(10); -+ } -+ if (ctrl) -+ *ctrl = command; -+ if (i == IXGBE_MDIO_COMMAND_TIMEOUT) { -+ ERROR_REPORT1(IXGBE_ERROR_POLLING, "Wait timed out\n"); -+ return IXGBE_ERR_PHY; - } +- } ++ pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); ++ if (enable) ++ pfvfspoof |= (1 << vf_target_shift); ++ else ++ pfvfspoof &= ~(1 << vf_target_shift); - return status; -+ return IXGBE_SUCCESS; ++ IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); } -/** ixgbe_validate_eeprom_checksum_X550 - Validate EEPROM checksum -+/** -+ * ixgbe_write_iosf_sb_reg_x550 - Writes a value to specified register -+ * of the IOSF device - * @hw: pointer to hardware structure +- * @hw: pointer to hardware structure - * @checksum_val: calculated checksum -- * ++/** ++ * ixgbe_iosf_wait - Wait for IOSF command completion ++ * @hw: pointer to hardware structure ++ * @ctrl: pointer to location to receive final IOSF control value + * - * Performs checksum calculation and validates the EEPROM checksum. If the - * caller does not need checksum_val, the value can be NULL. -+ * @reg_addr: 32 bit PHY register to write -+ * @device_type: 3 bit device type -+ * @data: Data to write to the register ++ * Returns failing status on timeout ++ * ++ * Note: ctrl can be NULL if the IOSF control register value is not needed **/ -static s32 ixgbe_validate_eeprom_checksum_X550(struct ixgbe_hw *hw, - u16 *checksum_val) -+s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, -+ u32 device_type, u32 data) ++STATIC s32 ixgbe_iosf_wait(struct ixgbe_hw *hw, u32 *ctrl) { - s32 status; - u16 checksum; - u16 read_checksum = 0; -+ u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; -+ u32 command, error; -+ s32 ret; ++ u32 i, command = 0; - /* 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 -- */ ++ /* Check every 10 usec to see if the address cycle completed. ++ * The SB IOSF BUSY bit will clear when the operation is ++ * complete + */ - status = hw->eeprom.ops.read(hw, 0, &checksum); - if (status) { - hw_dbg(hw, "EEPROM read failed\n"); - return status; -- } -+ ret = ixgbe_acquire_swfw_semaphore(hw, gssr); -+ if (ret != IXGBE_SUCCESS) -+ return ret; - ++ for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { ++ command = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL); ++ if ((command & IXGBE_SB_IOSF_CTRL_BUSY) == 0) ++ break; ++ usec_delay(10); + } +- - status = hw->eeprom.ops.calc_checksum(hw); - if (status < 0) - return status; -+ ret = ixgbe_iosf_wait(hw, NULL); -+ if (ret != IXGBE_SUCCESS) -+ goto out; - +- - checksum = (u16)(status & 0xffff); -+ command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | -+ (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); - +- - status = ixgbe_read_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, - &read_checksum); - if (status) - return status; -+ /* Write IOSF control register */ -+ IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); - +- - /* Verify read checksum from EEPROM is the same as - * calculated checksum - */ - if (read_checksum != checksum) { - status = IXGBE_ERR_EEPROM_CHECKSUM; - hw_dbg(hw, "Invalid EEPROM checksum"); -- } -+ /* Write IOSF data register */ -+ IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA, data); ++ if (ctrl) ++ *ctrl = command; ++ if (i == IXGBE_MDIO_COMMAND_TIMEOUT) { ++ ERROR_REPORT1(IXGBE_ERROR_POLLING, "Wait timed out\n"); ++ return IXGBE_ERR_PHY; + } - /* If the user cares, return the calculated checksum */ - if (checksum_val) - *checksum_val = checksum; -+ ret = ixgbe_iosf_wait(hw, &command); - +- - return status; -+ if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { -+ error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> -+ IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; -+ ERROR_REPORT2(IXGBE_ERROR_POLLING, -+ "Failed to write, error %x\n", error); -+ ret = IXGBE_ERR_PHY; -+ } -+ -+out: -+ ixgbe_release_swfw_semaphore(hw, gssr); -+ return ret; ++ return IXGBE_SUCCESS; } -/** ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif +/** -+ * ixgbe_read_iosf_sb_reg_x550 - Reads specified register of the IOSF device ++ * ixgbe_write_iosf_sb_reg_x550 - Writes a value to specified register ++ * of the IOSF device * @hw: pointer to hardware structure - * @offset: offset of word in the EEPROM to write - * @data: word write to the EEPROM @@ -52015,12 +52077,12 @@ index 77a60aa..ad9df6e 100644 - * Write a 16 bit word to the EEPROM using the hostif. + * @reg_addr: 32 bit PHY register to write + * @device_type: 3 bit device type -+ * @data: Pointer to read data from the register ++ * @data: Data to write to the register **/ -static s32 ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset, - u16 data) -+s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, -+ u32 device_type, u32 *data) ++s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, ++ u32 device_type, u32 data) { - s32 status; - struct ixgbe_hic_write_shadow_ram buffer; @@ -52070,47 +52132,91 @@ index 77a60aa..ad9df6e 100644 - } else { - hw_dbg(hw, "write ee hostif failed to get semaphore"); - status = IXGBE_ERR_SWFW_SYNC; ++ /* Write IOSF data register */ ++ IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA, data); ++ + ret = ixgbe_iosf_wait(hw, &command); + + if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { + error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> + IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; + ERROR_REPORT2(IXGBE_ERROR_POLLING, -+ "Failed to read, error %x\n", error); ++ "Failed to write, error %x\n", error); + ret = IXGBE_ERR_PHY; } - return status; -+ if (ret == IXGBE_SUCCESS) -+ *data = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA); -+ +out: + ixgbe_release_swfw_semaphore(hw, gssr); + return ret; } -/** ixgbe_update_flash_X550 - Instruct HW to copy EEPROM to Flash device -- * @hw: pointer to hardware structure ++/** ++ * ixgbe_read_iosf_sb_reg_x550 - Reads specified register of the IOSF device + * @hw: pointer to hardware structure - * - * Issue a shadow RAM dump to FW to copy EEPROM from shadow RAM to the flash. -- **/ ++ * @reg_addr: 32 bit PHY register to write ++ * @device_type: 3 bit device type ++ * @data: Pointer to read data from the register + **/ -static s32 ixgbe_update_flash_X550(struct ixgbe_hw *hw) -+/** -+ * ixgbe_get_phy_token - Get the token for shared phy access -+ * @hw: Pointer to hardware structure -+ */ -+ -+s32 ixgbe_get_phy_token(struct ixgbe_hw *hw) ++s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, ++ u32 device_type, u32 *data) { - s32 status = 0; - union ixgbe_hic_hdr2 buffer; -+ struct ixgbe_hic_phy_token_req token_cmd; -+ s32 status; ++ u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; ++ u32 command, error; ++ s32 ret; - buffer.req.cmd = FW_SHADOW_RAM_DUMP_CMD; - buffer.req.buf_lenh = 0; - buffer.req.buf_lenl = FW_SHADOW_RAM_DUMP_LEN; - buffer.req.checksum = FW_DEFAULT_CHECKSUM; ++ ret = ixgbe_acquire_swfw_semaphore(hw, gssr); ++ if (ret != IXGBE_SUCCESS) ++ return ret; ++ ++ ret = ixgbe_iosf_wait(hw, NULL); ++ if (ret != IXGBE_SUCCESS) ++ goto out; ++ ++ command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | ++ (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); ++ ++ /* Write IOSF control register */ ++ IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); ++ ++ ret = ixgbe_iosf_wait(hw, &command); ++ ++ if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { ++ error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> ++ IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; ++ ERROR_REPORT2(IXGBE_ERROR_POLLING, ++ "Failed to read, error %x\n", error); ++ ret = IXGBE_ERR_PHY; ++ } ++ ++ if (ret == IXGBE_SUCCESS) ++ *data = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA); ++ ++out: ++ ixgbe_release_swfw_semaphore(hw, gssr); ++ return ret; ++} ++ ++/** ++ * ixgbe_get_phy_token - Get the token for shared phy access ++ * @hw: Pointer to hardware structure ++ */ ++ ++s32 ixgbe_get_phy_token(struct ixgbe_hw *hw) ++{ ++ struct ixgbe_hic_phy_token_req token_cmd; ++ s32 status; ++ + token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD; + token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN; + token_cmd.hdr.cmd_or_resp.cmd_resv = 0; @@ -52134,35 +52240,21 @@ index 77a60aa..ad9df6e 100644 + token_cmd.hdr.cmd_or_resp.ret_status); + return IXGBE_ERR_FW_RESP_INVALID; + } - -- status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer), -- IXGBE_HI_COMMAND_TIMEOUT, false); -- return status; ++ + DEBUGOUT("Returning IXGBE_ERR_TOKEN_RETRY\n"); + return IXGBE_ERR_TOKEN_RETRY; - } - - /** -- * ixgbe_get_bus_info_X550em - Set PCI bus info -- * @hw: pointer to hardware structure -- * -- * Sets bus link width and speed to unknown because X550em is -- * not a PCI device. -- **/ --static s32 ixgbe_get_bus_info_X550em(struct ixgbe_hw *hw) ++} ++ ++/** + * ixgbe_put_phy_token - Put the token for shared phy access + * @hw: Pointer to hardware structure + */ + +s32 ixgbe_put_phy_token(struct ixgbe_hw *hw) - { -- hw->bus.type = ixgbe_bus_type_internal; -- hw->bus.width = ixgbe_bus_width_unknown; -- hw->bus.speed = ixgbe_bus_speed_unknown; ++{ + struct ixgbe_hic_phy_token_req token_cmd; + s32 status; - -- hw->mac.ops.set_lan_id(hw); ++ + token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD; + token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN; + token_cmd.hdr.cmd_or_resp.cmd_resv = 0; @@ -52178,15 +52270,11 @@ index 77a60aa..ad9df6e 100644 + return status; + if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK) + return IXGBE_SUCCESS; - -- return 0; ++ + DEBUGOUT("Put PHY Token host interface command failed"); + return IXGBE_ERR_FW_RESP_INVALID; - } - --/** ixgbe_disable_rx_x550 - Disable RX unit -- * -- * Enables the Rx DMA unit for x550 ++} ++ +/** + * ixgbe_write_iosf_sb_reg_x550a - Writes a value to specified register + * of the IOSF device @@ -52194,32 +52282,14 @@ index 77a60aa..ad9df6e 100644 + * @reg_addr: 32 bit PHY register to write + * @device_type: 3 bit device type + * @data: Data to write to the register - **/ --static void ixgbe_disable_rx_x550(struct ixgbe_hw *hw) ++ **/ +s32 ixgbe_write_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, + u32 device_type, u32 data) - { -- u32 rxctrl, pfdtxgswc; ++{ + struct ixgbe_hic_internal_phy_req write_cmd; - s32 status; -- struct ixgbe_hic_disable_rxen fw_cmd; -- -- rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); -- if (rxctrl & IXGBE_RXCTRL_RXEN) { -- pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); -- if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) { -- pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN; -- IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); -- hw->mac.set_lben = true; -- } else { -- hw->mac.set_lben = false; -- } ++ s32 status; + UNREFERENCED_1PARAMETER(device_type); - -- fw_cmd.hdr.cmd = FW_DISABLE_RXEN_CMD; -- fw_cmd.hdr.buf_len = FW_DISABLE_RXEN_LEN; -- fw_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; -- fw_cmd.port_number = hw->bus.lan_id; ++ + memset(&write_cmd, 0, sizeof(write_cmd)); + write_cmd.hdr.cmd = FW_INT_PHY_REQ_CMD; + write_cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN; @@ -52229,64 +52299,33 @@ index 77a60aa..ad9df6e 100644 + write_cmd.address = IXGBE_CPU_TO_BE16(reg_addr); + write_cmd.write_data = IXGBE_CPU_TO_BE32(data); -- status = ixgbe_host_interface_command(hw, &fw_cmd, -- sizeof(struct ixgbe_hic_disable_rxen), -- IXGBE_HI_COMMAND_TIMEOUT, true); +- status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer), + status = ixgbe_host_interface_command(hw, (u32 *)&write_cmd, + sizeof(write_cmd), -+ IXGBE_HI_COMMAND_TIMEOUT, false); - -- /* If we fail - disable RX using register write */ -- if (status) { -- rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); -- if (rxctrl & IXGBE_RXCTRL_RXEN) { -- rxctrl &= ~IXGBE_RXCTRL_RXEN; -- IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl); -- } -- } -- } -+ return status; + IXGBE_HI_COMMAND_TIMEOUT, false); ++ + return status; } --/** ixgbe_update_eeprom_checksum_X550 - Updates the EEPROM checksum and flash -+/** + /** +- * ixgbe_get_bus_info_X550em - Set PCI bus info +- * @hw: pointer to hardware structure + * ixgbe_read_iosf_sb_reg_x550a - Reads specified register of the IOSF device - * @hw: pointer to hardware structure -- * -- * After writing EEPROM to shadow RAM using EEWR register, software calculates -- * checksum and updates the EEPROM and instructs the hardware to update -- * the flash. ++ * @hw: pointer to hardware structure + * @reg_addr: 32 bit PHY register to write + * @device_type: 3 bit device type + * @data: Pointer to read data from the register - **/ --static s32 ixgbe_update_eeprom_checksum_X550(struct ixgbe_hw *hw) ++ **/ +s32 ixgbe_read_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, + u32 device_type, u32 *data) - { ++{ + union { + struct ixgbe_hic_internal_phy_req cmd; + struct ixgbe_hic_internal_phy_resp rsp; + } hic; - s32 status; -- u16 checksum = 0; -- -- /* 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 -- */ -- status = ixgbe_read_ee_hostif_X550(hw, 0, &checksum); -- if (status) { -- hw_dbg(hw, "EEPROM read failed\n"); -- return status; -- } -- -- status = ixgbe_calc_eeprom_checksum_X550(hw); -- if (status < 0) -- return status; ++ s32 status; + UNREFERENCED_1PARAMETER(device_type); - -- checksum = (u16)(status & 0xffff); ++ + memset(&hic, 0, sizeof(hic)); + hic.cmd.hdr.cmd = FW_INT_PHY_REQ_CMD; + hic.cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN; @@ -52294,120 +52333,102 @@ index 77a60aa..ad9df6e 100644 + hic.cmd.port_number = hw->bus.lan_id; + hic.cmd.command_type = FW_INT_PHY_REQ_READ; + hic.cmd.address = IXGBE_CPU_TO_BE16(reg_addr); - -- status = ixgbe_write_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, -- checksum); -- if (status) -- return status; ++ + status = ixgbe_host_interface_command(hw, (u32 *)&hic.cmd, + sizeof(hic.cmd), + IXGBE_HI_COMMAND_TIMEOUT, true); - -- status = ixgbe_update_flash_X550(hw); ++ + /* Extract the register value from the response. */ + *data = IXGBE_BE32_TO_CPU(hic.rsp.read_data); - - return status; - } - --/** ixgbe_write_ee_hostif_buffer_X550 - Write EEPROM word(s) using hostif ++ ++ return status; ++} ++ +/** + * ixgbe_disable_mdd_X550 - * @hw: pointer to hardware structure -- * @offset: offset of word in the EEPROM to write -- * @words: number of words -- * @data: word(s) write to the EEPROM ++ * @hw: pointer to hardware structure * -- * -- * Write a 16 bit word(s) to the EEPROM using the hostif. +- * Sets bus link width and speed to unknown because X550em is +- * not a PCI device. + * Disable malicious driver detection **/ --static s32 ixgbe_write_ee_hostif_buffer_X550(struct ixgbe_hw *hw, -- u16 offset, u16 words, -- u16 *data) +-static s32 ixgbe_get_bus_info_X550em(struct ixgbe_hw *hw) +void ixgbe_disable_mdd_X550(struct ixgbe_hw *hw) { -- s32 status = 0; -- u32 i = 0; -- -- /* Take semaphore for the entire operation. */ -- status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM); -- if (status) { -- hw_dbg(hw, "EEPROM write buffer - semaphore failed\n"); -- return status; -- } +- hw->bus.type = ixgbe_bus_type_internal; +- hw->bus.width = ixgbe_bus_width_unknown; +- hw->bus.speed = ixgbe_bus_speed_unknown; + u32 reg; -- for (i = 0; i < words; i++) { -- status = ixgbe_write_ee_hostif_data_X550(hw, offset + i, -- data[i]); -- if (status) { -- hw_dbg(hw, "Eeprom buffered write failed\n"); -- break; -- } -- } +- hw->mac.ops.set_lan_id(hw); + DEBUGFUNC("ixgbe_disable_mdd_X550"); - -- hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); ++ + /* Disable MDD for TX DMA and interrupt */ + reg = IXGBE_READ_REG(hw, IXGBE_DMATXCTL); + reg &= ~(IXGBE_DMATXCTL_MDP_EN | IXGBE_DMATXCTL_MBINTEN); + IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, reg); -- return status; +- return 0; + /* Disable MDD for RX and interrupt */ + reg = IXGBE_READ_REG(hw, IXGBE_RDRXCTL); + reg &= ~(IXGBE_RDRXCTL_MDP_EN | IXGBE_RDRXCTL_MBINTEN); + IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, reg); } --/** ixgbe_write_iosf_sb_reg_x550 - Writes a value to specified register of the -- * IOSF device -- * +-/** ixgbe_disable_rx_x550 - Disable RX unit +/** + * ixgbe_enable_mdd_X550 - * @hw: pointer to hardware structure -- * @reg_addr: 32 bit PHY register to write -- * @device_type: 3 bit device type -- * @data: Data to write to the register -+ * ++ * @hw: pointer to hardware structure + * +- * Enables the Rx DMA unit for x550 + * Enable malicious driver detection **/ --static s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, -- u32 device_type, u32 data) +-static void ixgbe_disable_rx_x550(struct ixgbe_hw *hw) +void ixgbe_enable_mdd_X550(struct ixgbe_hw *hw) { -- u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; -- u32 command, error; -- s32 ret; -- -- ret = hw->mac.ops.acquire_swfw_sync(hw, gssr); -- if (ret) -- return ret; +- u32 rxctrl, pfdtxgswc; +- s32 status; +- struct ixgbe_hic_disable_rxen fw_cmd; + u32 reg; -- ret = ixgbe_iosf_wait(hw, NULL); -- if (ret) -- goto out; +- rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); +- if (rxctrl & IXGBE_RXCTRL_RXEN) { +- pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); +- if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) { +- pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN; +- IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); +- hw->mac.set_lben = true; +- } else { +- hw->mac.set_lben = false; +- } + DEBUGFUNC("ixgbe_enable_mdd_X550"); -- command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | -- (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); +- fw_cmd.hdr.cmd = FW_DISABLE_RXEN_CMD; +- fw_cmd.hdr.buf_len = FW_DISABLE_RXEN_LEN; +- fw_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; +- fw_cmd.port_number = hw->bus.lan_id; + /* Enable MDD for TX DMA and interrupt */ + reg = IXGBE_READ_REG(hw, IXGBE_DMATXCTL); + reg |= (IXGBE_DMATXCTL_MDP_EN | IXGBE_DMATXCTL_MBINTEN); + IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, reg); -- /* Write IOSF control register */ -- IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); +- status = ixgbe_host_interface_command(hw, &fw_cmd, +- sizeof(struct ixgbe_hic_disable_rxen), +- IXGBE_HI_COMMAND_TIMEOUT, true); + /* Enable MDD for RX and interrupt */ + reg = IXGBE_READ_REG(hw, IXGBE_RDRXCTL); + reg |= (IXGBE_RDRXCTL_MDP_EN | IXGBE_RDRXCTL_MBINTEN); + IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, reg); +} -- /* Write IOSF data register */ -- IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA, data); +- /* If we fail - disable RX using register write */ +- if (status) { +- rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); +- if (rxctrl & IXGBE_RXCTRL_RXEN) { +- rxctrl &= ~IXGBE_RXCTRL_RXEN; +- IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl); +- } +- } +/** + * ixgbe_restore_mdd_vf_X550 + * @hw: pointer to hardware structure @@ -52418,15 +52439,9 @@ index 77a60aa..ad9df6e 100644 +void ixgbe_restore_mdd_vf_X550(struct ixgbe_hw *hw, u32 vf) +{ + u32 idx, reg, num_qs, start_q, bitmask; - -- ret = ixgbe_iosf_wait(hw, &command); ++ + DEBUGFUNC("ixgbe_restore_mdd_vf_X550"); - -- if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { -- error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> -- IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; -- hw_dbg(hw, "Failed to write, error %x\n", error); -- return IXGBE_ERR_PHY; ++ + /* Map VF to queues */ + reg = IXGBE_READ_REG(hw, IXGBE_MRQC); + switch (reg & IXGBE_MRQC_MRQE_MASK) { @@ -52444,10 +52459,6 @@ index 77a60aa..ad9df6e 100644 + bitmask = 0x00000003; + break; } -- --out: -- hw->mac.ops.release_swfw_sync(hw, gssr); -- return ret; + start_q = vf * num_qs; + + /* Release vf's queues by clearing WQBR_TX and WQBR_RX (RW1C) */ @@ -52458,179 +52469,90 @@ index 77a60aa..ad9df6e 100644 + IXGBE_WRITE_REG(hw, IXGBE_WQBR_RX(idx), reg); } --/** ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode. +-/** ixgbe_update_eeprom_checksum_X550 - Updates the EEPROM checksum and flash +/** + * ixgbe_mdd_event_X550 * @hw: pointer to hardware structure -- * @speed: the link speed to force + * @vf_bitmap: vf bitmap of malicious vfs * -- * Configures the integrated KR PHY to use iXFI mode. Used to connect an -- * internal and external PHY at a specific speed, without autonegotiation. +- * After writing EEPROM to shadow RAM using EEWR register, software calculates +- * checksum and updates the EEPROM and instructs the hardware to update +- * the flash. + * Handle malicious driver detection event. **/ --static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed) +-static s32 ixgbe_update_eeprom_checksum_X550(struct ixgbe_hw *hw) +void ixgbe_mdd_event_X550(struct ixgbe_hw *hw, u32 *vf_bitmap) { - s32 status; -- u32 reg_val; -- -- /* Disable AN and force speed to 10G Serial. */ -- status = ixgbe_read_iosf_sb_reg_x550(hw, -- IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), -- IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); -- if (status) -- return status; +- u16 checksum = 0; + u32 wqbr; + u32 i, j, reg, q, shift, vf, idx; -- reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; -- reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; +- /* 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 +- */ +- status = ixgbe_read_ee_hostif_X550(hw, 0, &checksum); +- if (status) { +- hw_dbg(hw, "EEPROM read failed\n"); +- return status; + DEBUGFUNC("ixgbe_mdd_event_X550"); - -- /* Select forced link speed for internal PHY. */ -- switch (*speed) { -- case IXGBE_LINK_SPEED_10GB_FULL: -- reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G; ++ + /* figure out pool size for mapping to vf's */ + reg = IXGBE_READ_REG(hw, IXGBE_MRQC); + switch (reg & IXGBE_MRQC_MRQE_MASK) { + case IXGBE_MRQC_VMDQRT8TCEN: + shift = 3; /* 16 VFs / pools */ - break; -- case IXGBE_LINK_SPEED_1GB_FULL: -- reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; ++ break; + case IXGBE_MRQC_VMDQRSS32EN: + case IXGBE_MRQC_VMDQRT4TCEN: + shift = 2; /* 32 VFs / pools */ - break; - default: -- /* Other link speeds are not supported by internal KR PHY. */ -- return IXGBE_ERR_LINK_SETUP; ++ break; ++ default: + shift = 1; /* 64 VFs / pools */ + break; } -- status = ixgbe_write_iosf_sb_reg_x550(hw, -- IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), -- IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); -- if (status) -- return status; -- -- /* Disable training protocol FSM. */ -- status = ixgbe_read_iosf_sb_reg_x550(hw, -- IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), -- IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); -- if (status) -- return status; -- -- reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_CONV_WO_PROTOCOL; -- status = ixgbe_write_iosf_sb_reg_x550(hw, -- IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), -- IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); -- if (status) -- return status; -- -- /* Disable Flex from training TXFFE. */ -- status = ixgbe_read_iosf_sb_reg_x550(hw, -- IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), -- IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); -- if (status) -- return status; -- -- reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; -- reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; -- reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; -- status = ixgbe_write_iosf_sb_reg_x550(hw, -- IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), -- IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); -- if (status) -- return status; -- -- status = ixgbe_read_iosf_sb_reg_x550(hw, -- IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), -- IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); -- if (status) +- status = ixgbe_calc_eeprom_checksum_X550(hw); +- if (status < 0) - return status; + /* Read WQBR_TX and WQBR_RX and check for malicious queues */ + for (i = 0; i < 4; i++) { + wqbr = IXGBE_READ_REG(hw, IXGBE_WQBR_TX(i)); + wqbr |= IXGBE_READ_REG(hw, IXGBE_WQBR_RX(i)); -- reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; -- reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; -- reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; -- status = ixgbe_write_iosf_sb_reg_x550(hw, -- IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), -- IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); -- if (status) -- return status; +- checksum = (u16)(status & 0xffff); + if (!wqbr) + continue; - -- /* Enable override for coefficients. */ -- status = ixgbe_read_iosf_sb_reg_x550(hw, -- IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), -- IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); -- if (status) -- return status; ++ + /* Get malicious queue */ + for (j = 0; j < 32 && wqbr; j++) { - -- reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_OVRRD_EN; -- reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CZERO_EN; -- reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CPLUS1_OVRRD_EN; -- reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CMINUS1_OVRRD_EN; -- status = ixgbe_write_iosf_sb_reg_x550(hw, -- IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), -- IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); -- if (status) -- return status; ++ + if (!(wqbr & (1 << j))) + continue; - -- /* Toggle port SW reset by AN reset. */ -- status = ixgbe_read_iosf_sb_reg_x550(hw, -- IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), -- IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); -- if (status) -- return status; ++ + /* Get queue from bitmask */ + q = j + (i * 32); - -- reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; -- status = ixgbe_write_iosf_sb_reg_x550(hw, -- IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), -- IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); ++ + /* Map queue to vf */ + vf = (q >> shift); - -- return status; ++ + /* Set vf bit in vf_bitmap */ + idx = vf / 32; + vf_bitmap[idx] |= (1 << (vf % 32)); + wqbr &= ~(1 << j); + } + } - } - - /** -- * ixgbe_supported_sfp_modules_X550em - Check if SFP module type is supported ++} ++ ++/** + * ixgbe_get_media_type_X550em - Get media type - * @hw: pointer to hardware structure -- * @linear: true if SFP module is linear ++ * @hw: pointer to hardware structure + * + * Returns the media type (fiber, copper, backplane) - */ --static s32 ixgbe_supported_sfp_modules_X550em(struct ixgbe_hw *hw, bool *linear) ++ */ +enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw) - { -- switch (hw->phy.sfp_type) { -- case ixgbe_sfp_type_not_present: -- return IXGBE_ERR_SFP_NOT_PRESENT; -- case ixgbe_sfp_type_da_cu_core0: -- case ixgbe_sfp_type_da_cu_core1: -- *linear = true; ++{ + enum ixgbe_media_type media_type; + + DEBUGFUNC("ixgbe_get_media_type_X550em"); @@ -52687,330 +52609,138 @@ index 77a60aa..ad9df6e 100644 + case ixgbe_sfp_type_da_cu_core0: + case ixgbe_sfp_type_da_cu_core1: + *linear = true; - break; - case ixgbe_sfp_type_srlr_core0: - case ixgbe_sfp_type_srlr_core1: -@@ -1279,305 +1561,179 @@ static s32 ixgbe_supported_sfp_modules_X550em(struct ixgbe_hw *hw, bool *linear) - return IXGBE_ERR_SFP_NOT_SUPPORTED; - } - -- return 0; ++ break; ++ case ixgbe_sfp_type_srlr_core0: ++ case ixgbe_sfp_type_srlr_core1: ++ case ixgbe_sfp_type_da_act_lmt_core0: ++ case ixgbe_sfp_type_da_act_lmt_core1: ++ case ixgbe_sfp_type_1g_sx_core0: ++ case ixgbe_sfp_type_1g_sx_core1: ++ case ixgbe_sfp_type_1g_lx_core0: ++ case ixgbe_sfp_type_1g_lx_core1: ++ *linear = false; ++ break; ++ case ixgbe_sfp_type_unknown: ++ case ixgbe_sfp_type_1g_cu_core0: ++ case ixgbe_sfp_type_1g_cu_core1: ++ default: ++ return IXGBE_ERR_SFP_NOT_SUPPORTED; ++ } ++ + return IXGBE_SUCCESS; - } - - /** -- * ixgbe_setup_mac_link_sfp_x550em - Configure the KR PHY for SFP. ++} ++ ++/** + * ixgbe_identify_sfp_module_X550em - Identifies SFP modules - * @hw: pointer to hardware structure - * -- * Configures the extern PHY and the integrated KR PHY for SFP support. -- */ --static s32 --ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw, -- ixgbe_link_speed speed, -- __always_unused bool autoneg_wait_to_complete) ++ * @hw: pointer to hardware structure ++ * + * Searches for and identifies the SFP module and assigns appropriate PHY type. + **/ +s32 ixgbe_identify_sfp_module_X550em(struct ixgbe_hw *hw) - { - s32 status; -- u16 slice, value; -- bool setup_linear = false; ++{ ++ s32 status; + bool linear; - -- /* Check if SFP module is supported and linear */ -- status = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); ++ + DEBUGFUNC("ixgbe_identify_sfp_module_X550em"); - -- /* If no SFP module present, then return success. Return success since -- * there is no reason to configure CS4227 and SFP not present error is -- * not accepted in the setup MAC link flow. -- */ -- if (status == IXGBE_ERR_SFP_NOT_PRESENT) -- return 0; ++ + status = ixgbe_identify_module_generic(hw); - -- if (status) ++ + if (status != IXGBE_SUCCESS) - return status; - -- if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) { -- /* Configure CS4227 LINE side to 10G SR. */ -- slice = IXGBE_CS4227_LINE_SPARE22_MSB + (hw->bus.lan_id << 12); -- value = IXGBE_CS4227_SPEED_10G; -- status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, -- slice, value); -- if (status) -- goto i2c_err; -- -- slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12); -- value = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1; -- status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, -- slice, value); -- if (status) -- goto i2c_err; -- -- /* Configure CS4227 for HOST connection rate then type. */ -- slice = IXGBE_CS4227_HOST_SPARE22_MSB + (hw->bus.lan_id << 12); -- value = speed & IXGBE_LINK_SPEED_10GB_FULL ? -- IXGBE_CS4227_SPEED_10G : IXGBE_CS4227_SPEED_1G; -- status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, -- slice, value); -- if (status) -- goto i2c_err; -- -- slice = IXGBE_CS4227_HOST_SPARE24_LSB + (hw->bus.lan_id << 12); -- if (setup_linear) -- value = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1; -- else -- value = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1; -- status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, -- slice, value); -- if (status) -- goto i2c_err; -- -- /* Setup XFI internal link. */ -- status = ixgbe_setup_ixfi_x550em(hw, &speed); -- if (status) { -- hw_dbg(hw, "setup_ixfi failed with %d\n", status); -- return status; -- } -- } else { -- /* Configure internal PHY for KR/KX. */ -- status = ixgbe_setup_kr_speed_x550em(hw, speed); -- if (status) { -- hw_dbg(hw, "setup_kr_speed failed with %d\n", status); -- return status; -- } -- -- /* Configure CS4227 LINE side to proper mode. */ -- slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12); -- if (setup_linear) -- value = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1; -- else -- value = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1; -- status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, -- slice, value); -- if (status) -- goto i2c_err; -- } -- -- return 0; ++ return status; ++ + /* Check if SFP module is supported */ + status = ixgbe_supported_sfp_modules_X550em(hw, &linear); - --i2c_err: -- hw_dbg(hw, "combined i2c access failed with %d\n", status); - return status; - } - - /** -- * ixgbe_setup_mac_link_sfp_n - Setup internal PHY for native SFP -- * @hw: pointer to hardware structure -- * -- * Configure the the integrated PHY for native SFP support. ++ ++ return status; ++} ++ ++/** + * ixgbe_setup_sfp_modules_X550em - Setup MAC link ops + * @hw: pointer to hardware structure - */ --static s32 --ixgbe_setup_mac_link_sfp_n(struct ixgbe_hw *hw, ixgbe_link_speed speed, -- __always_unused bool autoneg_wait_to_complete) ++ */ +s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw) - { -- bool setup_linear = false; -- u32 reg_phy_int; -- s32 rc; -- -- /* Check if SFP module is supported and linear */ -- rc = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); -- -- /* If no SFP module present, then return success. Return success since -- * SFP not present error is not excepted in the setup MAC link flow. -- */ -- if (rc == IXGBE_ERR_SFP_NOT_PRESENT) -- return 0; ++{ + s32 status; + bool linear; - -- if (!rc) -- return rc; ++ + DEBUGFUNC("ixgbe_setup_sfp_modules_X550em"); - -- /* Configure internal PHY for native SFI */ -- rc = hw->mac.ops.read_iosf_sb_reg(hw, -- IXGBE_KRM_AN_CNTL_8(hw->bus.lan_id), -- IXGBE_SB_IOSF_TARGET_KR_PHY, -- ®_phy_int); -- if (rc) -- return rc; ++ + /* Check if SFP module is supported */ + status = ixgbe_supported_sfp_modules_X550em(hw, &linear); - -- if (setup_linear) { -- reg_phy_int &= ~IXGBE_KRM_AN_CNTL_8_LIMITING; -- reg_phy_int |= IXGBE_KRM_AN_CNTL_8_LINEAR; -- } else { -- reg_phy_int |= IXGBE_KRM_AN_CNTL_8_LIMITING; -- reg_phy_int &= ~IXGBE_KRM_AN_CNTL_8_LINEAR; -- } ++ + if (status != IXGBE_SUCCESS) + return status; - -- rc = hw->mac.ops.write_iosf_sb_reg(hw, -- IXGBE_KRM_AN_CNTL_8(hw->bus.lan_id), -- IXGBE_SB_IOSF_TARGET_KR_PHY, -- reg_phy_int); -- if (rc) -- return rc; ++ + ixgbe_init_mac_link_ops_X550em(hw); + hw->phy.ops.reset = NULL; - -- /* Setup XFI/SFI internal link */ -- return ixgbe_setup_ixfi_x550em(hw, &speed); ++ + return IXGBE_SUCCESS; - } - - /** -- * ixgbe_setup_mac_link_sfp_x550a - Setup internal PHY for SFP -- * @hw: pointer to hardware structure -- * -- * Configure the the integrated PHY for SFP support. -- */ --static s32 --ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw, ixgbe_link_speed speed, -- __always_unused bool autoneg_wait_to_complete) ++} ++ ++/** +* ixgbe_restart_an_internal_phy_x550em - restart autonegotiation for the +* internal PHY +* @hw: pointer to hardware structure +**/ +STATIC s32 ixgbe_restart_an_internal_phy_x550em(struct ixgbe_hw *hw) - { -- u32 reg_slice, slice_offset; -- bool setup_linear = false; -- u16 reg_phy_ext; -- s32 rc; ++{ + s32 status; + u32 link_ctrl; - -- /* Check if SFP module is supported and linear */ -- rc = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); ++ + /* Restart auto-negotiation. */ + status = hw->mac.ops.read_iosf_sb_reg(hw, + IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, &link_ctrl); - -- /* If no SFP module present, then return success. Return success since -- * SFP not present error is not excepted in the setup MAC link flow. -- */ -- if (rc == IXGBE_ERR_SFP_NOT_PRESENT) -- return 0; ++ + if (status) { + DEBUGOUT("Auto-negotiation did not complete\n"); + return status; + } - -- if (!rc) -- return rc; ++ + link_ctrl |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; + status = hw->mac.ops.write_iosf_sb_reg(hw, + IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, link_ctrl); - -- /* Configure internal PHY for KR/KX. */ -- ixgbe_setup_kr_speed_x550em(hw, speed); ++ + if (hw->mac.type == ixgbe_mac_X550EM_a) { + u32 flx_mask_st20; - -- if (hw->phy.mdio.prtad == MDIO_PRTAD_NONE) -- return IXGBE_ERR_PHY_ADDR_INVALID; ++ + /* Indicate to FW that AN restart has been asserted */ + status = hw->mac.ops.read_iosf_sb_reg(hw, + IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_mask_st20); - -- /* Get external PHY device id */ -- rc = hw->phy.ops.read_reg(hw, IXGBE_CS4227_GLOBAL_ID_MSB, -- IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext); -- if (rc) -- return rc; ++ + if (status) { + DEBUGOUT("Auto-negotiation did not complete\n"); + return status; + } - -- /* When configuring quad port CS4223, the MAC instance is part -- * of the slice offset. -- */ -- if (reg_phy_ext == IXGBE_CS4223_PHY_ID) -- slice_offset = (hw->bus.lan_id + -- (hw->bus.instance_id << 1)) << 12; -- else -- slice_offset = hw->bus.lan_id << 12; ++ + flx_mask_st20 |= IXGBE_KRM_PMD_FLX_MASK_ST20_FW_AN_RESTART; + status = hw->mac.ops.write_iosf_sb_reg(hw, + IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, flx_mask_st20); + } - -- /* Configure CS4227/CS4223 LINE side to proper mode. */ -- reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + slice_offset; -- if (setup_linear) -- reg_phy_ext = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1; -- else -- reg_phy_ext = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1; -- return hw->phy.ops.write_reg(hw, reg_slice, IXGBE_MDIO_ZERO_DEV_TYPE, -- reg_phy_ext); ++ + return status; - } - - /** -- * ixgbe_setup_mac_link_t_X550em - Sets the auto advertised link speed ++} ++ ++/** + * ixgbe_setup_sgmii - Set up link for sgmii - * @hw: pointer to hardware structure -- * @speed: new link speed -- * @autoneg_wait_to_complete: true when waiting for completion is needed -- * -- * Setup internal/external PHY link speed based on link speed, then set -- * external PHY auto advertised link speed. -- * -- * Returns error status for any failure -- **/ --static s32 ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw *hw, -- ixgbe_link_speed speed, -- bool autoneg_wait) ++ * @hw: pointer to hardware structure + */ +STATIC s32 ixgbe_setup_sgmii(struct ixgbe_hw *hw, ixgbe_link_speed speed, + bool autoneg_wait) - { -- s32 status; -- ixgbe_link_speed force_speed; -- -- /* Setup internal/external PHY link speed to iXFI (10G), unless -- * only 1G is auto advertised then setup KX link. -- */ -- if (speed & IXGBE_LINK_SPEED_10GB_FULL) -- force_speed = IXGBE_LINK_SPEED_10GB_FULL; -- else -- force_speed = IXGBE_LINK_SPEED_1GB_FULL; -- -- /* If internal link mode is XFI, then setup XFI internal link. */ -- if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) { -- status = ixgbe_setup_ixfi_x550em(hw, &force_speed); ++{ + struct ixgbe_mac_info *mac = &hw->mac; + u32 lval, sval, flx_val; + s32 rc; - -- if (status) -- return status; -- } ++ + rc = mac->ops.read_iosf_sb_reg(hw, + IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, &lval); + if (rc) + return rc; - -- return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait); --} ++ + lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; + lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; + lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN; @@ -53021,30 +52751,13 @@ index 77a60aa..ad9df6e 100644 + IXGBE_SB_IOSF_TARGET_KR_PHY, lval); + if (rc) + return rc; - --/** ixgbe_check_link_t_X550em - Determine link and speed status -- * @hw: pointer to hardware structure -- * @speed: pointer to link speed -- * @link_up: true when link is up -- * @link_up_wait_to_complete: bool used to wait for link up or not -- * -- * Check that both the MAC and X557 external PHY have link. -- **/ --static s32 ixgbe_check_link_t_X550em(struct ixgbe_hw *hw, -- ixgbe_link_speed *speed, -- bool *link_up, -- bool link_up_wait_to_complete) --{ -- u32 status; -- u16 autoneg_status; ++ + rc = mac->ops.read_iosf_sb_reg(hw, + IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, &sval); + if (rc) + return rc; - -- if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper) -- return IXGBE_ERR_CONFIG; ++ + sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D; + sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D; + rc = mac->ops.write_iosf_sb_reg(hw, @@ -53052,93 +52765,77 @@ index 77a60aa..ad9df6e 100644 + IXGBE_SB_IOSF_TARGET_KR_PHY, sval); + if (rc) + return rc; - -- status = ixgbe_check_mac_link_generic(hw, speed, link_up, -- link_up_wait_to_complete); ++ + rc = mac->ops.read_iosf_sb_reg(hw, + IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val); + if (rc) + return rc; - -- /* If check link fails or MAC link is not up, then return */ -- if (status || !(*link_up)) -- return status; ++ + flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; + flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G; + flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; + flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; + flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; - -- /* MAC link is up, so check external PHY link. -- * Read this twice back to back to indicate current status. -- */ -- status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, -- IXGBE_MDIO_AUTO_NEG_DEV_TYPE, -- &autoneg_status); -- if (status) -- return status; ++ + rc = mac->ops.write_iosf_sb_reg(hw, + IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val); + if (rc) + return rc; - -- /* If external PHY link is not up, then indicate link not up */ -- if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS)) -- *link_up = false; ++ + rc = ixgbe_restart_an_internal_phy_x550em(hw); + if (rc) + return rc; - -- return 0; ++ + return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait); - } - - /** -- * ixgbe_setup_sgmii - Set up link for sgmii ++} ++ ++/** + * ixgbe_setup_sgmii_fw - Set up link for internal PHY SGMII auto-negotiation - * @hw: pointer to hardware structure - */ --static s32 --ixgbe_setup_sgmii(struct ixgbe_hw *hw, __always_unused ixgbe_link_speed speed, -- __always_unused bool autoneg_wait_to_complete) ++ * @hw: pointer to hardware structure ++ */ +STATIC s32 ixgbe_setup_sgmii_fw(struct ixgbe_hw *hw, ixgbe_link_speed speed, + bool autoneg_wait) - { - struct ixgbe_mac_info *mac = &hw->mac; -- u32 lval, sval; ++{ ++ struct ixgbe_mac_info *mac = &hw->mac; + u32 lval, sval, flx_val; - s32 rc; - - rc = mac->ops.read_iosf_sb_reg(hw, -@@ -1590,7 +1746,7 @@ ixgbe_setup_sgmii(struct ixgbe_hw *hw, __always_unused ixgbe_link_speed speed, - lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; - lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN; - lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN; -- lval |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; ++ s32 rc; ++ ++ rc = mac->ops.read_iosf_sb_reg(hw, ++ IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), ++ IXGBE_SB_IOSF_TARGET_KR_PHY, &lval); ++ if (rc) ++ return rc; ++ ++ lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; ++ lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; ++ lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN; ++ lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN; + lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; - rc = mac->ops.write_iosf_sb_reg(hw, - IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), - IXGBE_SB_IOSF_TARGET_KR_PHY, lval); -@@ -1603,32 +1759,54 @@ ixgbe_setup_sgmii(struct ixgbe_hw *hw, __always_unused ixgbe_link_speed speed, - if (rc) - return rc; - -- sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D; -- sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D; ++ rc = mac->ops.write_iosf_sb_reg(hw, ++ IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), ++ IXGBE_SB_IOSF_TARGET_KR_PHY, lval); ++ if (rc) ++ return rc; ++ ++ rc = mac->ops.read_iosf_sb_reg(hw, ++ IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), ++ IXGBE_SB_IOSF_TARGET_KR_PHY, &sval); ++ if (rc) ++ return rc; ++ + sval &= ~IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D; + sval &= ~IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D; - rc = mac->ops.write_iosf_sb_reg(hw, - IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), - IXGBE_SB_IOSF_TARGET_KR_PHY, sval); - if (rc) - return rc; - -- lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; - rc = mac->ops.write_iosf_sb_reg(hw, - IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), - IXGBE_SB_IOSF_TARGET_KR_PHY, lval); ++ rc = mac->ops.write_iosf_sb_reg(hw, ++ IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), ++ IXGBE_SB_IOSF_TARGET_KR_PHY, sval); ++ if (rc) ++ return rc; ++ ++ rc = mac->ops.write_iosf_sb_reg(hw, ++ IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), ++ IXGBE_SB_IOSF_TARGET_KR_PHY, lval); + if (rc) + return rc; + @@ -53159,57 +52856,45 @@ index 77a60aa..ad9df6e 100644 + IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val); + if (rc) + return rc; - -- return rc; ++ + rc = ixgbe_restart_an_internal_phy_x550em(hw); + + return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait); - } - --/** ixgbe_init_mac_link_ops_X550em - init mac link function pointers ++} ++ +/** + * ixgbe_init_mac_link_ops_X550em - init mac link function pointers - * @hw: pointer to hardware structure -- **/ --static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw) ++ * @hw: pointer to hardware structure + */ +void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw) - { - struct ixgbe_mac_info *mac = &hw->mac; - -- mac->ops.setup_fc = ixgbe_setup_fc_x550em; ++{ ++ struct ixgbe_mac_info *mac = &hw->mac; ++ + DEBUGFUNC("ixgbe_init_mac_link_ops_X550em"); - -- switch (mac->ops.get_media_type(hw)) { ++ + switch (hw->mac.ops.get_media_type(hw)) { - case ixgbe_media_type_fiber: - /* CS4227 does not support autoneg, so disable the laser control - * functions for SFP+ fiber -@@ -1637,27 +1815,35 @@ static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw) - mac->ops.enable_tx_laser = NULL; - mac->ops.flap_tx_laser = NULL; - mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber; -- switch (hw->device_id) { -- case IXGBE_DEV_ID_X550EM_A_SFP_N: -- mac->ops.setup_mac_link = ixgbe_setup_mac_link_sfp_n; -- break; -- case IXGBE_DEV_ID_X550EM_A_SFP: ++ case ixgbe_media_type_fiber: ++ /* CS4227 does not support autoneg, so disable the laser control ++ * functions for SFP+ fiber ++ */ ++ mac->ops.disable_tx_laser = NULL; ++ mac->ops.enable_tx_laser = NULL; ++ mac->ops.flap_tx_laser = NULL; ++ mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber; + mac->ops.set_rate_select_speed = + ixgbe_set_soft_rate_select_speed; + + if ((hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP_N) || + (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP)) - mac->ops.setup_mac_link = - ixgbe_setup_mac_link_sfp_x550a; -- break; -- default: ++ mac->ops.setup_mac_link = ++ ixgbe_setup_mac_link_sfp_x550a; + else - mac->ops.setup_mac_link = - ixgbe_setup_mac_link_sfp_x550em; ++ mac->ops.setup_mac_link = ++ ixgbe_setup_mac_link_sfp_x550em; + break; + case ixgbe_media_type_copper: + if (hw->device_id == IXGBE_DEV_ID_X550EM_X_1G_T) - break; ++ break; + if (hw->mac.type == ixgbe_mac_X550EM_a) { + if (hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T || + hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L) { @@ -53223,88 +52908,58 @@ index 77a60aa..ad9df6e 100644 + } else { + mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em; + mac->ops.check_link = ixgbe_check_link_t_X550em; - } -- mac->ops.set_rate_select_speed = -- ixgbe_set_soft_rate_select_speed; - break; -- case ixgbe_media_type_copper: -- mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em; -- mac->ops.setup_fc = ixgbe_setup_fc_generic; -- mac->ops.check_link = ixgbe_check_link_t_X550em; -- return; - case ixgbe_media_type_backplane: - if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII || - hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII_L) -@@ -1668,43 +1854,37 @@ static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw) - } - } - --/** ixgbe_setup_sfp_modules_X550em - Setup SFP module -- * @hw: pointer to hardware structure ++ } ++ break; ++ case ixgbe_media_type_backplane: ++ if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII || ++ hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII_L) ++ mac->ops.setup_link = ixgbe_setup_sgmii; ++ break; ++ default: ++ break; ++ } ++} ++ +/** + * ixgbe_get_link_capabilities_x550em - Determines link capabilities + * @hw: pointer to hardware structure + * @speed: pointer to link speed + * @autoneg: true when autoneg or autotry is enabled - */ --static s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw) ++ */ +s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw, + ixgbe_link_speed *speed, + bool *autoneg) - { -- s32 status; -- bool linear; -- -- /* Check if SFP module is supported */ -- status = ixgbe_supported_sfp_modules_X550em(hw, &linear); -- if (status) -- return status; -- -- ixgbe_init_mac_link_ops_X550em(hw); -- hw->phy.ops.reset = NULL; ++{ + DEBUGFUNC("ixgbe_get_link_capabilities_X550em"); - -- return 0; --} ++ + if (hw->phy.type == ixgbe_phy_fw) { + *autoneg = true; + *speed = hw->phy.speeds_supported; + return 0; + } - --/** ixgbe_get_link_capabilities_x550em - Determines link capabilities -- * @hw: pointer to hardware structure -- * @speed: pointer to link speed -- * @autoneg: true when autoneg or autotry is enabled -- **/ --static s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw, -- ixgbe_link_speed *speed, -- bool *autoneg) --{ - /* SFP */ - if (hw->phy.media_type == ixgbe_media_type_fiber) { + - /* CS4227 SFP must not enable auto-negotiation */ - *autoneg = false; - ++ /* SFP */ ++ if (hw->phy.media_type == ixgbe_media_type_fiber) { ++ ++ /* CS4227 SFP must not enable auto-negotiation */ ++ *autoneg = false; ++ + /* Check if 1G SFP module. */ - if (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 || -- hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1) { ++ if (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 || + hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1 + || hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 || + hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1) { - *speed = IXGBE_LINK_SPEED_1GB_FULL; -- return 0; ++ *speed = IXGBE_LINK_SPEED_1GB_FULL; + return IXGBE_SUCCESS; - } - - /* Link capabilities are based on SFP */ -@@ -1714,26 +1894,49 @@ static s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw, - else - *speed = IXGBE_LINK_SPEED_10GB_FULL; - } else { -- *speed = IXGBE_LINK_SPEED_10GB_FULL | -- IXGBE_LINK_SPEED_1GB_FULL; ++ } ++ ++ /* Link capabilities are based on SFP */ ++ if (hw->phy.multispeed_fiber) ++ *speed = IXGBE_LINK_SPEED_10GB_FULL | ++ IXGBE_LINK_SPEED_1GB_FULL; ++ else ++ *speed = IXGBE_LINK_SPEED_10GB_FULL; ++ } else { + switch (hw->phy.type) { + case ixgbe_phy_ext_1g_t: + case ixgbe_phy_sgmii: @@ -53329,127 +52984,122 @@ index 77a60aa..ad9df6e 100644 + IXGBE_LINK_SPEED_1GB_FULL; + break; + } - *autoneg = true; - } -- return 0; ++ *autoneg = true; ++ } + + return IXGBE_SUCCESS; - } - - /** - * ixgbe_get_lasi_ext_t_x550em - Determime external Base T PHY interrupt cause - * @hw: pointer to hardware structure - * @lsc: pointer to boolean flag which indicates whether external Base T -- * PHY interrupt is lsc ++} ++ ++/** ++ * ixgbe_get_lasi_ext_t_x550em - Determime external Base T PHY interrupt cause ++ * @hw: pointer to hardware structure ++ * @lsc: pointer to boolean flag which indicates whether external Base T + * PHY interrupt is lsc - * - * Determime if external Base T PHY interrupt cause is high temperature - * failure alarm or link status change. - * - * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature - * failure alarm, else return PHY access status. -- **/ --static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc) ++ * ++ * Determime if external Base T PHY interrupt cause is high temperature ++ * failure alarm or link status change. ++ * ++ * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature ++ * failure alarm, else return PHY access status. + */ +STATIC s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc) - { - u32 status; - u16 reg; -@@ -1745,7 +1948,8 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc) - IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, - ®); - -- if (status || !(reg & IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN)) ++{ ++ u32 status; ++ u16 reg; ++ ++ *lsc = false; ++ ++ /* Vendor alarm triggered */ ++ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, ++ IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ++ ®); ++ + if (status != IXGBE_SUCCESS || + !(reg & IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN)) - return status; - - /* Vendor Auto-Neg alarm triggered or Global alarm 1 triggered */ -@@ -1753,8 +1957,9 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc) - IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, - ®); - -- if (status || !(reg & (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | -- IXGBE_MDIO_GLOBAL_ALARM_1_INT))) ++ return status; ++ ++ /* Vendor Auto-Neg alarm triggered or Global alarm 1 triggered */ ++ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG, ++ IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ++ ®); ++ + if (status != IXGBE_SUCCESS || + !(reg & (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | + IXGBE_MDIO_GLOBAL_ALARM_1_INT))) - return status; - - /* Global alarm triggered */ -@@ -1762,7 +1967,7 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc) - IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, - ®); - -- if (status) ++ return status; ++ ++ /* Global alarm triggered */ ++ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_ALARM_1, ++ IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ++ ®); ++ + if (status != IXGBE_SUCCESS) - return status; - - /* If high temperature failure, then return over temp error and exit */ -@@ -1770,13 +1975,13 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc) - /* power down the PHY in case the PHY FW didn't already */ - ixgbe_set_copper_phy_power(hw, false); - return IXGBE_ERR_OVERTEMP; -- } -- if (reg & IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT) { ++ return status; ++ ++ /* If high temperature failure, then return over temp error and exit */ ++ if (reg & IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL) { ++ /* power down the PHY in case the PHY FW didn't already */ ++ ixgbe_set_copper_phy_power(hw, false); ++ return IXGBE_ERR_OVERTEMP; + } else if (reg & IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT) { - /* device fault alarm triggered */ - status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_FAULT_MSG, - IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, - ®); -- if (status) ++ /* device fault alarm triggered */ ++ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_FAULT_MSG, ++ IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ++ ®); + + if (status != IXGBE_SUCCESS) - return status; - - /* if device fault was due to high temp alarm handle and exit */ -@@ -1791,21 +1996,22 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc) - status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); - -- if (status || !(reg & IXGBE_MDIO_GLOBAL_STD_ALM2_INT)) ++ return status; ++ ++ /* if device fault was due to high temp alarm handle and exit */ ++ if (reg == IXGBE_MDIO_GLOBAL_FAULT_MSG_HI_TMP) { ++ /* power down the PHY in case the PHY FW didn't */ ++ ixgbe_set_copper_phy_power(hw, false); ++ return IXGBE_ERR_OVERTEMP; ++ } ++ } ++ ++ /* Vendor alarm 2 triggered */ ++ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, ++ IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); ++ + if (status != IXGBE_SUCCESS || + !(reg & IXGBE_MDIO_GLOBAL_STD_ALM2_INT)) - return status; - - /* link connect/disconnect event occurred */ - status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); - -- if (status) ++ return status; ++ ++ /* link connect/disconnect event occurred */ ++ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2, ++ IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); ++ + if (status != IXGBE_SUCCESS) - return status; - - /* Indicate LSC */ - if (reg & IXGBE_MDIO_AUTO_NEG_VEN_LSC) - *lsc = true; - -- return 0; ++ return status; ++ ++ /* Indicate LSC */ ++ if (reg & IXGBE_MDIO_AUTO_NEG_VEN_LSC) ++ *lsc = true; ++ + return IXGBE_SUCCESS; - } - - /** -@@ -1816,8 +2022,8 @@ static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc) - * Base T PHY - * - * Returns PHY access status -- **/ --static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw) ++} ++ ++/** ++ * ixgbe_enable_lasi_ext_t_x550em - Enable external Base T PHY interrupts ++ * @hw: pointer to hardware structure ++ * ++ * Enable link status change and temperature failure alarm for the external ++ * Base T PHY ++ * ++ * Returns PHY access status + */ +STATIC s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw) - { - u32 status; - u16 reg; -@@ -1827,23 +2033,39 @@ static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw) - status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc); - - /* Enable link status change alarm */ -- status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, -- IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); -- if (status) -- return status; - -- reg |= IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN; ++{ ++ u32 status; ++ u16 reg; ++ bool lsc; ++ ++ /* Clear interrupt flags */ ++ status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc); ++ ++ /* Enable link status change alarm */ ++ + /* Enable the LASI interrupts on X552 devices to receive notifications + * of the link configurations of the external PHY and correspondingly + * support the configuration of the internal iXFI link, since iXFI does @@ -53465,11 +53115,7 @@ index 77a60aa..ad9df6e 100644 + + if (status != IXGBE_SUCCESS) + return status; - -- status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, -- IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg); -- if (status) -- return status; ++ + reg |= IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN; + + status = hw->phy.ops.write_reg(hw, @@ -53479,156 +53125,118 @@ index 77a60aa..ad9df6e 100644 + if (status != IXGBE_SUCCESS) + return status; + } - - /* Enable high temperature failure and global fault alarms */ - status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, - IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, - ®); -- if (status) ++ ++ /* Enable high temperature failure and global fault alarms */ ++ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, ++ IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ++ ®); + + if (status != IXGBE_SUCCESS) - return status; - - reg |= (IXGBE_MDIO_GLOBAL_INT_HI_TEMP_EN | -@@ -1852,14 +2074,16 @@ static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw) - status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, - IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, - reg); -- if (status) ++ return status; ++ ++ reg |= (IXGBE_MDIO_GLOBAL_INT_HI_TEMP_EN | ++ IXGBE_MDIO_GLOBAL_INT_DEV_FAULT_EN); ++ ++ status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, ++ IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ++ reg); + + if (status != IXGBE_SUCCESS) - return status; - - /* Enable vendor Auto-Neg alarm and Global Interrupt Mask 1 alarm */ - status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, - IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, - ®); -- if (status) ++ return status; ++ ++ /* Enable vendor Auto-Neg alarm and Global Interrupt Mask 1 alarm */ ++ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, ++ IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ++ ®); + + if (status != IXGBE_SUCCESS) - return status; - - reg |= (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | -@@ -1868,14 +2092,16 @@ static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw) - status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, - IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, - reg); -- if (status) ++ return status; ++ ++ reg |= (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | ++ IXGBE_MDIO_GLOBAL_ALARM_1_INT); ++ ++ status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, ++ IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ++ reg); + + if (status != IXGBE_SUCCESS) - return status; - - /* Enable chip-wide vendor alarm */ - status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, - IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, - ®); -- if (status) ++ return status; ++ ++ /* Enable chip-wide vendor alarm */ ++ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, ++ IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ++ ®); + + if (status != IXGBE_SUCCESS) - return status; - - reg |= IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN; -@@ -1888,40 +2114,13 @@ static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw) - } - - /** -- * ixgbe_handle_lasi_ext_t_x550em - Handle external Base T PHY interrupt -- * @hw: pointer to hardware structure -- * -- * Handle external Base T PHY interrupt. If high temperature -- * failure alarm then return error, else if link status change -- * then setup internal/external PHY link -- * -- * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature -- * failure alarm, else return PHY access status. -- **/ --static s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw) --{ -- struct ixgbe_phy_info *phy = &hw->phy; -- bool lsc; -- u32 status; -- -- status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc); -- if (status) -- return status; -- -- if (lsc && phy->ops.setup_internal_link) -- return phy->ops.setup_internal_link(hw); -- -- return 0; --} -- --/** -- * ixgbe_setup_kr_speed_x550em - Configure the KR PHY for link speed. -- * @hw: pointer to hardware structure -- * @speed: link speed ++ return status; ++ ++ reg |= IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN; ++ ++ status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, ++ IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, ++ reg); ++ ++ return status; ++} ++ ++/** + * ixgbe_setup_kr_speed_x550em - Configure the KR PHY for link speed. + * @hw: pointer to hardware structure + * @speed: link speed - * -- * Configures the integrated KR PHY. ++ * + * Configures the integrated KR PHY. - **/ --static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw, ++ **/ +STATIC s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw, - ixgbe_link_speed speed) - { - s32 status; -@@ -1945,349 +2144,1591 @@ static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw, - if (speed & IXGBE_LINK_SPEED_1GB_FULL) - reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX; - -- /* Restart auto-negotiation. */ -- reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; - status = hw->mac.ops.write_iosf_sb_reg(hw, - IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), - IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); - -- return status; --} ++ ixgbe_link_speed speed) ++{ ++ s32 status; ++ u32 reg_val; ++ ++ status = hw->mac.ops.read_iosf_sb_reg(hw, ++ IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), ++ IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); ++ if (status) ++ return status; ++ ++ reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; ++ reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR | ++ IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX); ++ ++ /* Advertise 10G support. */ ++ if (speed & IXGBE_LINK_SPEED_10GB_FULL) ++ reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR; ++ ++ /* Advertise 1G support. */ ++ if (speed & IXGBE_LINK_SPEED_1GB_FULL) ++ reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX; ++ ++ status = hw->mac.ops.write_iosf_sb_reg(hw, ++ IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), ++ IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); ++ + if (hw->mac.type == ixgbe_mac_X550EM_a) { + /* Set lane mode to KR auto negotiation */ + status = hw->mac.ops.read_iosf_sb_reg(hw, + IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); - --/** ixgbe_setup_kx4_x550em - Configure the KX4 PHY. -- * @hw: pointer to hardware structure -- * -- * Configures the integrated KX4 PHY. -- **/ --static s32 ixgbe_setup_kx4_x550em(struct ixgbe_hw *hw) --{ -- s32 status; -- u32 reg_val; ++ + if (status) + return status; - -- status = hw->mac.ops.read_iosf_sb_reg(hw, IXGBE_KX4_LINK_CNTL_1, -- IXGBE_SB_IOSF_TARGET_KX4_PCS0 + -- hw->bus.lan_id, ®_val); -- if (status) -- return status; ++ + reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; + reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN; + reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; + reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; + reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; - -- reg_val &= ~(IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4 | -- IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX); ++ + status = hw->mac.ops.write_iosf_sb_reg(hw, + IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); + } - -- reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_ENABLE; ++ + return ixgbe_restart_an_internal_phy_x550em(hw); +} - -- /* Advertise 10G support. */ -- if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) -- reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4; ++ +/** + * ixgbe_reset_phy_fw - Reset firmware-controlled PHYs + * @hw: pointer to hardware structure @@ -53637,47 +53245,31 @@ index 77a60aa..ad9df6e 100644 +{ + u32 store[FW_PHY_ACT_DATA_COUNT] = { 0 }; + s32 rc; - -- /* Advertise 1G support. */ -- if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) -- reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX; ++ + if (hw->phy.reset_disable || ixgbe_check_reset_blocked(hw)) + return IXGBE_SUCCESS; - -- /* Restart auto-negotiation. */ -- reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_RESTART; -- status = hw->mac.ops.write_iosf_sb_reg(hw, IXGBE_KX4_LINK_CNTL_1, -- IXGBE_SB_IOSF_TARGET_KX4_PCS0 + -- hw->bus.lan_id, reg_val); ++ + rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_PHY_SW_RESET, &store); + if (rc) + return rc; + memset(store, 0, sizeof(store)); - -- return status; ++ + rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_INIT_PHY, &store); + if (rc) + return rc; + + return ixgbe_setup_fw_link(hw); - } - - /** -- * ixgbe_setup_kr_x550em - Configure the KR PHY ++} ++ ++/** + * ixgbe_check_overtemp_fw - Check firmware-controlled PHYs for overtemp - * @hw: pointer to hardware structure -- **/ --static s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw) ++ * @hw: pointer to hardware structure + */ +static s32 ixgbe_check_overtemp_fw(struct ixgbe_hw *hw) - { -- /* leave link alone for 2.5G */ -- if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_2_5GB_FULL) -- return 0; ++{ + u32 store[FW_PHY_ACT_DATA_COUNT] = { 0 }; + s32 rc; - -- return ixgbe_setup_kr_speed_x550em(hw, hw->phy.autoneg_advertised); ++ + rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_LINK_INFO, &store); + if (rc) + return rc; @@ -53687,45 +53279,22 @@ index 77a60aa..ad9df6e 100644 + return IXGBE_ERR_OVERTEMP; + } + return IXGBE_SUCCESS; - } - --/** ixgbe_ext_phy_t_x550em_get_link - Get ext phy link status -- * @hw: address of hardware structure -- * @link_up: address of boolean to indicate link status ++} ++ +/** + * ixgbe_read_mng_if_sel_x550em - Read NW_MNG_IF_SEL register + * @hw: pointer to hardware structure - * -- * Returns error code if unable to get link status. ++ * + * Read NW_MNG_IF_SEL register and save field values, and check for valid field + * values. - **/ --static s32 ixgbe_ext_phy_t_x550em_get_link(struct ixgbe_hw *hw, bool *link_up) ++ **/ +STATIC s32 ixgbe_read_mng_if_sel_x550em(struct ixgbe_hw *hw) - { -- u32 ret; -- u16 autoneg_status; -- -- *link_up = false; -- -- /* read this twice back to back to indicate current status */ -- ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, -- IXGBE_MDIO_AUTO_NEG_DEV_TYPE, -- &autoneg_status); -- if (ret) -- return ret; -- -- ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, -- IXGBE_MDIO_AUTO_NEG_DEV_TYPE, -- &autoneg_status); -- if (ret) -- return ret; ++{ + /* Save NW management interface connected on board. This is used + * to determine internal PHY mode. + */ + hw->phy.nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL); - -- *link_up = !!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS); ++ + /* If X552 (X550EM_a) and MDIO is connected to external PHY, then set + * PHY address. This register field was has only been used for X552. + */ @@ -53735,47 +53304,25 @@ index 77a60aa..ad9df6e 100644 + IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD) >> + IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT; + } - -- return 0; ++ + return IXGBE_SUCCESS; - } - --/** ixgbe_setup_internal_phy_t_x550em - Configure KR PHY to X557 link -- * @hw: point to hardware structure -- * -- * Configures the link between the integrated KR PHY and the external X557 PHY -- * The driver will call this function when it gets a link status change -- * interrupt from the X557 PHY. This function configures the link speed -- * between the PHYs to match the link speed of the BASE-T link. ++} ++ +/** + * ixgbe_init_phy_ops_X550em - PHY/SFP specific init + * @hw: pointer to hardware structure - * -- * A return of a non-zero value indicates an error, and the base driver should -- * not report link up. -- **/ --static s32 ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw) ++ * + * Initialize any function pointers that were not able to be + * set during init_shared_code because the PHY/SFP type was + * not known. Perform the SFP init if necessary. + */ +s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw) - { -- ixgbe_link_speed force_speed; -- bool link_up; -- u32 status; -- u16 speed; ++{ + struct ixgbe_phy_info *phy = &hw->phy; + s32 ret_val; - -- if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper) -- return IXGBE_ERR_CONFIG; ++ + DEBUGFUNC("ixgbe_init_phy_ops_X550em"); - -- if (hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE) { -- speed = IXGBE_LINK_SPEED_10GB_FULL | -- IXGBE_LINK_SPEED_1GB_FULL; -- return ixgbe_setup_kr_speed_x550em(hw, speed); ++ + hw->mac.ops.set_lan_id(hw); + ixgbe_read_mng_if_sel_x550em(hw); + @@ -53783,12 +53330,8 @@ index 77a60aa..ad9df6e 100644 + phy->phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; + ixgbe_setup_mux_ctl(hw); + phy->ops.identify_sfp = ixgbe_identify_sfp_module_X550em; - } - -- /* If link is not up, then there is no setup necessary so return */ -- status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); -- if (status) -- return status; ++ } ++ + switch (hw->device_id) { + case IXGBE_DEV_ID_X550EM_A_1G_T: + case IXGBE_DEV_ID_X550EM_A_1G_T_L: @@ -53801,9 +53344,7 @@ index 77a60aa..ad9df6e 100644 + hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY1_SM; + else + hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY0_SM; - -- if (!link_up) -- return 0; ++ + break; + case IXGBE_DEV_ID_X550EM_A_10G_T: + case IXGBE_DEV_ID_X550EM_A_SFP: @@ -53824,29 +53365,18 @@ index 77a60aa..ad9df6e 100644 + default: + break; + } - -- status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, -- IXGBE_MDIO_AUTO_NEG_DEV_TYPE, -- &speed); -- if (status) -- return status; ++ + /* Identify the PHY or SFP module */ + ret_val = phy->ops.identify(hw); + if (ret_val == IXGBE_ERR_SFP_NOT_SUPPORTED || + ret_val == IXGBE_ERR_PHY_ADDR_INVALID) + return ret_val; - -- /* If link is not still up, then no setup is necessary so return */ -- status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); -- if (status) -- return status; ++ + /* Setup function pointers based on detected hardware */ + ixgbe_init_mac_link_ops_X550em(hw); + if (phy->sfp_type != ixgbe_sfp_type_unknown) + phy->ops.reset = NULL; - -- if (!link_up) -- return 0; ++ + /* Set functions pointers based on phy type */ + switch (hw->phy.type) { + case ixgbe_phy_x550em_kx4: @@ -53876,52 +53406,35 @@ index 77a60aa..ad9df6e 100644 + */ + phy->ops.setup_internal_link = + ixgbe_setup_internal_phy_t_x550em; - -- /* clear everything but the speed and duplex bits */ -- speed &= IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK; ++ + /* setup SW LPLU only for first revision of X550EM_x */ + if ((hw->mac.type == ixgbe_mac_X550EM_x) && + !(IXGBE_FUSES0_REV_MASK & + IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0)))) + phy->ops.enter_lplu = ixgbe_enter_lplu_t_x550em; - -- switch (speed) { -- case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_FULL: -- force_speed = IXGBE_LINK_SPEED_10GB_FULL; ++ + phy->ops.handle_lasi = ixgbe_handle_lasi_ext_t_x550em; + phy->ops.reset = ixgbe_reset_phy_t_X550em; - break; -- case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB_FULL: -- force_speed = IXGBE_LINK_SPEED_1GB_FULL; ++ break; + case ixgbe_phy_sgmii: + phy->ops.setup_link = NULL; + break; + case ixgbe_phy_fw: + phy->ops.setup_link = ixgbe_setup_fw_link; + phy->ops.reset = ixgbe_reset_phy_fw; - break; - default: -- /* Internal PHY does not support anything else */ -- return IXGBE_ERR_INVALID_LINK_SETTINGS; + break; - } -- -- return ixgbe_setup_ixfi_x550em(hw, &force_speed); ++ default: ++ break; ++ } + return ret_val; - } - --/** ixgbe_reset_phy_t_X550em - Performs X557 PHY reset and enables LASI ++} ++ +/** + * ixgbe_set_mdio_speed - Set MDIO clock speed - * @hw: pointer to hardware structure -- **/ --static s32 ixgbe_reset_phy_t_X550em(struct ixgbe_hw *hw) ++ * @hw: pointer to hardware structure + */ +STATIC void ixgbe_set_mdio_speed(struct ixgbe_hw *hw) - { -- s32 status; -- -- status = ixgbe_reset_phy_generic(hw); ++{ + u32 hlreg0; + + switch (hw->device_id) { @@ -53980,19 +53493,17 @@ index 77a60aa..ad9df6e 100644 + + /* PHY ops must be identified and initialized prior to reset */ + status = hw->phy.ops.init(hw); - - if (status) ++ ++ if (status) + DEBUGOUT1("Failed to initialize PHY ops, STATUS = %d\n", + status); + + if (status == IXGBE_ERR_SFP_NOT_SUPPORTED || + status == IXGBE_ERR_PHY_ADDR_INVALID) { + DEBUGOUT("Returning from reset HW due to PHY init failure\n"); - return status; ++ return status; + } - -- /* Configure Link Status Alarm and Temperature Threshold interrupts */ -- return ixgbe_enable_lasi_ext_t_x550em(hw); ++ + /* start the external PHY */ + if (hw->phy.type == ixgbe_phy_x550em_ext_t) { + status = ixgbe_init_ext_t_x550em(hw); @@ -54077,33 +53588,65 @@ index 77a60aa..ad9df6e 100644 + hw->mac.ops.init_rx_addrs(hw); + + ixgbe_set_mdio_speed(hw); -+ + +- status = ixgbe_write_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, +- checksum); +- if (status) +- return status; + if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP) + ixgbe_setup_mux_ctl(hw); -+ + +- status = ixgbe_update_flash_X550(hw); + if (status != IXGBE_SUCCESS) + DEBUGOUT1("Reset HW failed, STATUS = %d\n", status); -+ -+ return status; -+} -+ + + return status; + } + +-/** ixgbe_write_ee_hostif_buffer_X550 - Write EEPROM word(s) using hostif +- * @hw: pointer to hardware structure +- * @offset: offset of word in the EEPROM to write +- * @words: number of words +- * @data: word(s) write to the EEPROM +- * +- * +- * Write a 16 bit word(s) to the EEPROM using the hostif. +- **/ +-static s32 ixgbe_write_ee_hostif_buffer_X550(struct ixgbe_hw *hw, +- u16 offset, u16 words, +- u16 *data) +/** + * ixgbe_init_ext_t_x550em - Start (unstall) the external Base T PHY. + * @hw: pointer to hardware structure + */ +s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw) -+{ + { +- s32 status = 0; +- u32 i = 0; + u32 status; + u16 reg; -+ + +- /* Take semaphore for the entire operation. */ +- status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM); +- if (status) { +- hw_dbg(hw, "EEPROM write buffer - semaphore failed\n"); + status = hw->phy.ops.read_reg(hw, + IXGBE_MDIO_TX_VENDOR_ALARMS_3, + IXGBE_MDIO_PMA_PMD_DEV_TYPE, + ®); + + if (status != IXGBE_SUCCESS) -+ return status; -+ + return status; +- } + +- for (i = 0; i < words; i++) { +- status = ixgbe_write_ee_hostif_data_X550(hw, offset + i, +- data[i]); +- if (status) { +- hw_dbg(hw, "Eeprom buffered write failed\n"); +- break; +- } +- } + /* If PHY FW reset completed bit is set then this is the first + * SW instance after a power on so the PHY FW must be un-stalled. + */ @@ -54112,7 +53655,8 @@ index 77a60aa..ad9df6e 100644 + IXGBE_MDIO_GLOBAL_RES_PR_10, + IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, + ®); -+ + +- hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); + if (status != IXGBE_SUCCESS) + return status; + @@ -54126,26 +53670,45 @@ index 77a60aa..ad9df6e 100644 + if (status != IXGBE_SUCCESS) + return status; + } -+ -+ return status; -+} -+ + + return status; + } + +-/** ixgbe_write_iosf_sb_reg_x550 - Writes a value to specified register of the +- * IOSF device +- * +/** + * ixgbe_setup_kr_x550em - Configure the KR PHY. -+ * @hw: pointer to hardware structure -+ **/ + * @hw: pointer to hardware structure +- * @reg_addr: 32 bit PHY register to write +- * @device_type: 3 bit device type +- * @data: Data to write to the register + **/ +-static s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, +- u32 device_type, u32 data) +s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw) -+{ + { +- u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; +- u32 command, error; +- s32 ret; + /* leave link alone for 2.5G */ + if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_2_5GB_FULL) + return IXGBE_SUCCESS; -+ + +- ret = hw->mac.ops.acquire_swfw_sync(hw, gssr); +- if (ret) +- return ret; + if (ixgbe_check_reset_blocked(hw)) + return 0; -+ + +- ret = ixgbe_iosf_wait(hw, NULL); +- if (ret) +- goto out; + return ixgbe_setup_kr_speed_x550em(hw, hw->phy.autoneg_advertised); +} -+ + +- command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | +- (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); +/** + * ixgbe_setup_mac_link_sfp_x550em - Setup internal/external the PHY for SFP + * @hw: pointer to hardware structure @@ -54160,23 +53723,37 @@ index 77a60aa..ad9df6e 100644 + u16 reg_slice, reg_val; + bool setup_linear = false; + UNREFERENCED_1PARAMETER(autoneg_wait_to_complete); -+ + +- /* Write IOSF control register */ +- IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); + /* Check if SFP module is supported and linear */ + ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); -+ + +- /* Write IOSF data register */ +- IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA, data); + /* If no SFP module present, then return success. Return success since + * there is no reason to configure CS4227 and SFP not present error is + * not excepted in the setup MAC link flow. + */ + if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT) + return IXGBE_SUCCESS; -+ + +- ret = ixgbe_iosf_wait(hw, &command); + if (ret_val != IXGBE_SUCCESS) + return ret_val; -+ + +- if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { +- error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> +- IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; +- hw_dbg(hw, "Failed to write, error %x\n", error); +- return IXGBE_ERR_PHY; +- } + /* Configure internal PHY for KR/KX. */ + ixgbe_setup_kr_speed_x550em(hw, speed); -+ + +-out: +- hw->mac.ops.release_swfw_sync(hw, gssr); +- return ret; + /* Configure CS4227 LINE side to proper mode. */ + reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + + (hw->bus.lan_id << 12); @@ -54187,125 +53764,414 @@ index 77a60aa..ad9df6e 100644 + ret_val = hw->link.ops.write_link(hw, hw->link.addr, reg_slice, + reg_val); + return ret_val; -+} -+ + } + +-/** ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode. +/** + * ixgbe_setup_sfi_x550a - Configure the internal PHY for native SFI mode -+ * @hw: pointer to hardware structure -+ * @speed: the link speed to force -+ * + * @hw: pointer to hardware structure + * @speed: the link speed to force + * +- * Configures the integrated KR PHY to use iXFI mode. Used to connect an +- * internal and external PHY at a specific speed, without autonegotiation. + * Configures the integrated PHY for native SFI mode. Used to connect the + * internal PHY directly to an SFP cage, without autonegotiation. -+ **/ + **/ +-static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed) +STATIC s32 ixgbe_setup_sfi_x550a(struct ixgbe_hw *hw, ixgbe_link_speed *speed) -+{ + { + struct ixgbe_mac_info *mac = &hw->mac; -+ s32 status; -+ u32 reg_val; -+ + s32 status; + u32 reg_val; + +- /* Disable AN and force speed to 10G Serial. */ +- status = ixgbe_read_iosf_sb_reg_x550(hw, +- IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), +- IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); +- if (status) + /* Disable all AN and force speed to 10G Serial. */ + status = mac->ops.read_iosf_sb_reg(hw, + IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); + if (status != IXGBE_SUCCESS) -+ return status; -+ + return status; + +- reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; +- reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; + reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; + reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; + reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; + reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; -+ -+ /* Select forced link speed for internal PHY. */ -+ switch (*speed) { -+ case IXGBE_LINK_SPEED_10GB_FULL: + + /* Select forced link speed for internal PHY. */ + switch (*speed) { + case IXGBE_LINK_SPEED_10GB_FULL: +- reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G; + reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_10G; -+ break; -+ case IXGBE_LINK_SPEED_1GB_FULL: + break; + case IXGBE_LINK_SPEED_1GB_FULL: +- reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; + reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G; -+ break; -+ default: + break; + default: +- /* Other link speeds are not supported by internal KR PHY. */ + /* Other link speeds are not supported by internal PHY. */ -+ return IXGBE_ERR_LINK_SETUP; -+ } -+ + return IXGBE_ERR_LINK_SETUP; + } + +- status = ixgbe_write_iosf_sb_reg_x550(hw, +- IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), +- IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); +- if (status) +- return status; +- +- /* Disable training protocol FSM. */ +- status = ixgbe_read_iosf_sb_reg_x550(hw, +- IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), +- IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); +- if (status) +- return status; +- +- reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_CONV_WO_PROTOCOL; +- status = ixgbe_write_iosf_sb_reg_x550(hw, +- IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), +- IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); +- if (status) +- return status; +- +- /* Disable Flex from training TXFFE. */ +- status = ixgbe_read_iosf_sb_reg_x550(hw, +- IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), +- IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); +- if (status) +- return status; +- +- reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; +- reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; +- reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; +- status = ixgbe_write_iosf_sb_reg_x550(hw, +- IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), +- IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); +- if (status) +- return status; +- +- status = ixgbe_read_iosf_sb_reg_x550(hw, +- IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), +- IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); +- if (status) +- return status; +- +- reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; +- reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; +- reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; +- status = ixgbe_write_iosf_sb_reg_x550(hw, +- IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), +- IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); +- if (status) +- return status; +- +- /* Enable override for coefficients. */ +- status = ixgbe_read_iosf_sb_reg_x550(hw, +- IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), +- IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); +- if (status) +- return status; +- +- reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_OVRRD_EN; +- reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CZERO_EN; +- reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CPLUS1_OVRRD_EN; +- reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CMINUS1_OVRRD_EN; +- status = ixgbe_write_iosf_sb_reg_x550(hw, +- IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), + status = mac->ops.write_iosf_sb_reg(hw, + IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), -+ IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); -+ -+ /* Toggle port SW reset by AN reset. */ + IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); +- if (status) +- return status; + + /* Toggle port SW reset by AN reset. */ +- status = ixgbe_read_iosf_sb_reg_x550(hw, +- IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), +- IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); +- if (status) +- return status; +- +- reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; +- status = ixgbe_write_iosf_sb_reg_x550(hw, +- IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), +- IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); + status = ixgbe_restart_an_internal_phy_x550em(hw); -+ -+ return status; -+} -+ -+/** + + return status; + } + + /** +- * ixgbe_supported_sfp_modules_X550em - Check if SFP module type is supported +- * @hw: pointer to hardware structure +- * @linear: true if SFP module is linear +- */ +-static s32 ixgbe_supported_sfp_modules_X550em(struct ixgbe_hw *hw, bool *linear) +-{ +- switch (hw->phy.sfp_type) { +- case ixgbe_sfp_type_not_present: +- return IXGBE_ERR_SFP_NOT_PRESENT; +- case ixgbe_sfp_type_da_cu_core0: +- case ixgbe_sfp_type_da_cu_core1: +- *linear = true; +- break; +- case ixgbe_sfp_type_srlr_core0: +- case ixgbe_sfp_type_srlr_core1: +- case ixgbe_sfp_type_da_act_lmt_core0: +- case ixgbe_sfp_type_da_act_lmt_core1: +- case ixgbe_sfp_type_1g_sx_core0: +- case ixgbe_sfp_type_1g_sx_core1: +- case ixgbe_sfp_type_1g_lx_core0: +- case ixgbe_sfp_type_1g_lx_core1: +- *linear = false; +- break; +- case ixgbe_sfp_type_unknown: +- case ixgbe_sfp_type_1g_cu_core0: +- case ixgbe_sfp_type_1g_cu_core1: +- default: +- return IXGBE_ERR_SFP_NOT_SUPPORTED; +- } +- +- return 0; +-} +- +-/** +- * ixgbe_setup_mac_link_sfp_x550em - Configure the KR PHY for SFP. + * ixgbe_setup_mac_link_sfp_x550a - Setup internal PHY for SFP -+ * @hw: pointer to hardware structure -+ * + * @hw: pointer to hardware structure + * +- * Configures the extern PHY and the integrated KR PHY for SFP support. +- */ +-static s32 +-ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw, +- ixgbe_link_speed speed, +- __always_unused bool autoneg_wait_to_complete) +-{ +- s32 status; +- u16 slice, value; +- bool setup_linear = false; +- +- /* Check if SFP module is supported and linear */ +- status = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); +- +- /* If no SFP module present, then return success. Return success since +- * there is no reason to configure CS4227 and SFP not present error is +- * not accepted in the setup MAC link flow. +- */ +- if (status == IXGBE_ERR_SFP_NOT_PRESENT) +- return 0; +- +- if (status) +- return status; +- +- if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) { +- /* Configure CS4227 LINE side to 10G SR. */ +- slice = IXGBE_CS4227_LINE_SPARE22_MSB + (hw->bus.lan_id << 12); +- value = IXGBE_CS4227_SPEED_10G; +- status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, +- slice, value); +- if (status) +- goto i2c_err; +- +- slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12); +- value = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1; +- status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, +- slice, value); +- if (status) +- goto i2c_err; +- +- /* Configure CS4227 for HOST connection rate then type. */ +- slice = IXGBE_CS4227_HOST_SPARE22_MSB + (hw->bus.lan_id << 12); +- value = speed & IXGBE_LINK_SPEED_10GB_FULL ? +- IXGBE_CS4227_SPEED_10G : IXGBE_CS4227_SPEED_1G; +- status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, +- slice, value); +- if (status) +- goto i2c_err; +- +- slice = IXGBE_CS4227_HOST_SPARE24_LSB + (hw->bus.lan_id << 12); +- if (setup_linear) +- value = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1; +- else +- value = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1; +- status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, +- slice, value); +- if (status) +- goto i2c_err; +- +- /* Setup XFI internal link. */ +- status = ixgbe_setup_ixfi_x550em(hw, &speed); +- if (status) { +- hw_dbg(hw, "setup_ixfi failed with %d\n", status); +- return status; +- } +- } else { +- /* Configure internal PHY for KR/KX. */ +- status = ixgbe_setup_kr_speed_x550em(hw, speed); +- if (status) { +- hw_dbg(hw, "setup_kr_speed failed with %d\n", status); +- return status; +- } +- +- /* Configure CS4227 LINE side to proper mode. */ +- slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12); +- if (setup_linear) +- value = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1; +- else +- value = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1; +- status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, +- slice, value); +- if (status) +- goto i2c_err; +- } +- +- return 0; +- +-i2c_err: +- hw_dbg(hw, "combined i2c access failed with %d\n", status); +- return status; +-} +- +-/** +- * ixgbe_setup_mac_link_sfp_n - Setup internal PHY for native SFP +- * @hw: pointer to hardware structure +- * +- * Configure the the integrated PHY for native SFP support. +- */ +-static s32 +-ixgbe_setup_mac_link_sfp_n(struct ixgbe_hw *hw, ixgbe_link_speed speed, +- __always_unused bool autoneg_wait_to_complete) + * Configure the the integrated PHY for SFP support. + **/ +s32 ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw, + ixgbe_link_speed speed, + bool autoneg_wait_to_complete) -+{ + { + s32 ret_val; + u16 reg_phy_ext; -+ bool setup_linear = false; + bool setup_linear = false; +- u32 reg_phy_int; +- s32 rc; + u32 reg_slice, reg_phy_int, slice_offset; + + UNREFERENCED_1PARAMETER(autoneg_wait_to_complete); -+ -+ /* Check if SFP module is supported and linear */ + + /* Check if SFP module is supported and linear */ +- rc = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); + ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); -+ -+ /* If no SFP module present, then return success. Return success since -+ * SFP not present error is not excepted in the setup MAC link flow. -+ */ + + /* If no SFP module present, then return success. Return success since + * SFP not present error is not excepted in the setup MAC link flow. + */ +- if (rc == IXGBE_ERR_SFP_NOT_PRESENT) +- return 0; +- +- if (!rc) +- return rc; + if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT) + return IXGBE_SUCCESS; -+ + +- /* Configure internal PHY for native SFI */ +- rc = hw->mac.ops.read_iosf_sb_reg(hw, +- IXGBE_KRM_AN_CNTL_8(hw->bus.lan_id), +- IXGBE_SB_IOSF_TARGET_KR_PHY, +- ®_phy_int); +- if (rc) +- return rc; + if (ret_val != IXGBE_SUCCESS) + return ret_val; -+ + +- if (setup_linear) { +- reg_phy_int &= ~IXGBE_KRM_AN_CNTL_8_LIMITING; +- reg_phy_int |= IXGBE_KRM_AN_CNTL_8_LINEAR; +- } else { +- reg_phy_int |= IXGBE_KRM_AN_CNTL_8_LIMITING; +- reg_phy_int &= ~IXGBE_KRM_AN_CNTL_8_LINEAR; +- } + if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP_N) { + /* Configure internal PHY for native SFI based on module type */ + ret_val = hw->mac.ops.read_iosf_sb_reg(hw, + IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, ®_phy_int); -+ + +- rc = hw->mac.ops.write_iosf_sb_reg(hw, +- IXGBE_KRM_AN_CNTL_8(hw->bus.lan_id), +- IXGBE_SB_IOSF_TARGET_KR_PHY, +- reg_phy_int); +- if (rc) +- return rc; + if (ret_val != IXGBE_SUCCESS) + return ret_val; -+ + +- /* Setup XFI/SFI internal link */ +- return ixgbe_setup_ixfi_x550em(hw, &speed); +-} + reg_phy_int &= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_DA; + if (!setup_linear) + reg_phy_int |= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_SR; -+ + +-/** +- * ixgbe_setup_mac_link_sfp_x550a - Setup internal PHY for SFP +- * @hw: pointer to hardware structure +- * +- * Configure the the integrated PHY for SFP support. +- */ +-static s32 +-ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw, ixgbe_link_speed speed, +- __always_unused bool autoneg_wait_to_complete) +-{ +- u32 reg_slice, slice_offset; +- bool setup_linear = false; +- u16 reg_phy_ext; +- s32 rc; + ret_val = hw->mac.ops.write_iosf_sb_reg(hw, + IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, reg_phy_int); -+ + +- /* Check if SFP module is supported and linear */ +- rc = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); + if (ret_val != IXGBE_SUCCESS) + return ret_val; -+ + +- /* If no SFP module present, then return success. Return success since +- * SFP not present error is not excepted in the setup MAC link flow. +- */ +- if (rc == IXGBE_ERR_SFP_NOT_PRESENT) +- return 0; + /* Setup SFI internal link. */ + ret_val = ixgbe_setup_sfi_x550a(hw, &speed); + } else { + /* Configure internal PHY for KR/KX. */ + ixgbe_setup_kr_speed_x550em(hw, speed); -+ + +- if (!rc) +- return rc; + if (hw->phy.addr == 0x0 || hw->phy.addr == 0xFFFF) { + /* Find Address */ + DEBUGOUT("Invalid NW_MNG_IF_SEL.MDIO_PHY_ADD value\n"); + return IXGBE_ERR_PHY_ADDR_INVALID; + } -+ + +- /* Configure internal PHY for KR/KX. */ +- ixgbe_setup_kr_speed_x550em(hw, speed); + /* Get external PHY SKU id */ + ret_val = hw->phy.ops.read_reg(hw, IXGBE_CS4227_EFUSE_PDF_SKU, + IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext); -+ + +- if (hw->phy.mdio.prtad == MDIO_PRTAD_NONE) +- return IXGBE_ERR_PHY_ADDR_INVALID; + if (ret_val != IXGBE_SUCCESS) + return ret_val; -+ + +- /* Get external PHY device id */ +- rc = hw->phy.ops.read_reg(hw, IXGBE_CS4227_GLOBAL_ID_MSB, +- IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext); +- if (rc) +- return rc; + /* When configuring quad port CS4223, the MAC instance is part + * of the slice offset. + */ @@ -54314,33 +54180,93 @@ index 77a60aa..ad9df6e 100644 + (hw->bus.instance_id << 1)) << 12; + else + slice_offset = hw->bus.lan_id << 12; -+ + +- /* When configuring quad port CS4223, the MAC instance is part +- * of the slice offset. +- */ +- if (reg_phy_ext == IXGBE_CS4223_PHY_ID) +- slice_offset = (hw->bus.lan_id + +- (hw->bus.instance_id << 1)) << 12; +- else +- slice_offset = hw->bus.lan_id << 12; + /* Configure CS4227/CS4223 LINE side to proper mode. */ + reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + slice_offset; -+ + +- /* Configure CS4227/CS4223 LINE side to proper mode. */ +- reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + slice_offset; +- if (setup_linear) +- reg_phy_ext = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1; +- else +- reg_phy_ext = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1; +- return hw->phy.ops.write_reg(hw, reg_slice, IXGBE_MDIO_ZERO_DEV_TYPE, +- reg_phy_ext); +-} + ret_val = hw->phy.ops.read_reg(hw, reg_slice, + IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext); -+ + +-/** +- * ixgbe_setup_mac_link_t_X550em - Sets the auto advertised link speed +- * @hw: pointer to hardware structure +- * @speed: new link speed +- * @autoneg_wait_to_complete: true when waiting for completion is needed +- * +- * Setup internal/external PHY link speed based on link speed, then set +- * external PHY auto advertised link speed. +- * +- * Returns error status for any failure +- **/ +-static s32 ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw *hw, +- ixgbe_link_speed speed, +- bool autoneg_wait) +-{ +- s32 status; +- ixgbe_link_speed force_speed; + if (ret_val != IXGBE_SUCCESS) + return ret_val; -+ + +- /* Setup internal/external PHY link speed to iXFI (10G), unless +- * only 1G is auto advertised then setup KX link. +- */ +- if (speed & IXGBE_LINK_SPEED_10GB_FULL) +- force_speed = IXGBE_LINK_SPEED_10GB_FULL; +- else +- force_speed = IXGBE_LINK_SPEED_1GB_FULL; + reg_phy_ext &= ~((IXGBE_CS4227_EDC_MODE_CX1 << 1) | + (IXGBE_CS4227_EDC_MODE_SR << 1)); -+ + +- /* If internal link mode is XFI, then setup XFI internal link. */ +- if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) { +- status = ixgbe_setup_ixfi_x550em(hw, &force_speed); + if (setup_linear) + reg_phy_ext = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1; + else + reg_phy_ext = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1; + ret_val = hw->phy.ops.write_reg(hw, reg_slice, + IXGBE_MDIO_ZERO_DEV_TYPE, reg_phy_ext); -+ + +- if (status) +- return status; + /* Flush previous write with a read */ + ret_val = hw->phy.ops.read_reg(hw, reg_slice, + IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext); -+ } + } +- +- return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait); + return ret_val; -+} -+ + } + +-/** ixgbe_check_link_t_X550em - Determine link and speed status +- * @hw: pointer to hardware structure +- * @speed: pointer to link speed +- * @link_up: true when link is up +- * @link_up_wait_to_complete: bool used to wait for link up or not +- * +- * Check that both the MAC and X557 external PHY have link. +- **/ +-static s32 ixgbe_check_link_t_X550em(struct ixgbe_hw *hw, +- ixgbe_link_speed *speed, +- bool *link_up, +- bool link_up_wait_to_complete) +/** + * ixgbe_setup_ixfi_x550em_x - MAC specific iXFI configuration + * @hw: pointer to hardware structure @@ -54348,24 +54274,45 @@ index 77a60aa..ad9df6e 100644 + * iXfI configuration needed for ixgbe_mac_X550EM_x devices. + **/ +STATIC s32 ixgbe_setup_ixfi_x550em_x(struct ixgbe_hw *hw) -+{ + { +- u32 status; +- u16 autoneg_status; +- +- if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper) +- return IXGBE_ERR_CONFIG; +- +- status = ixgbe_check_mac_link_generic(hw, speed, link_up, +- link_up_wait_to_complete); + struct ixgbe_mac_info *mac = &hw->mac; + s32 status; + u32 reg_val; -+ + +- /* If check link fails or MAC link is not up, then return */ +- if (status || !(*link_up)) + /* Disable training protocol FSM. */ + status = mac->ops.read_iosf_sb_reg(hw, + IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); + if (status != IXGBE_SUCCESS) -+ return status; + return status; +- +- /* MAC link is up, so check external PHY link. +- * Read this twice back to back to indicate current status. +- */ +- status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, +- IXGBE_MDIO_AUTO_NEG_DEV_TYPE, +- &autoneg_status); +- if (status) + reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_CONV_WO_PROTOCOL; + status = mac->ops.write_iosf_sb_reg(hw, + IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); + if (status != IXGBE_SUCCESS) -+ return status; -+ + return status; + +- /* If external PHY link is not up, then indicate link not up */ +- if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS)) +- *link_up = false; + /* Disable Flex from training TXFFE. */ + status = mac->ops.read_iosf_sb_reg(hw, + IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), @@ -54393,7 +54340,8 @@ index 77a60aa..ad9df6e 100644 + IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); + if (status != IXGBE_SUCCESS) + return status; -+ + +- return 0; + /* Enable override for coefficients. */ + status = mac->ops.read_iosf_sb_reg(hw, + IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), @@ -54408,9 +54356,15 @@ index 77a60aa..ad9df6e 100644 + IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); + return status; -+} -+ -+/** + } + + /** +- * ixgbe_setup_sgmii - Set up link for sgmii +- * @hw: pointer to hardware structure +- */ +-static s32 +-ixgbe_setup_sgmii(struct ixgbe_hw *hw, __always_unused ixgbe_link_speed speed, +- __always_unused bool autoneg_wait_to_complete) + * ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode. + * @hw: pointer to hardware structure + * @speed: the link speed to force @@ -54419,25 +54373,53 @@ index 77a60aa..ad9df6e 100644 + * internal and external PHY at a specific speed, without autonegotiation. + **/ +STATIC s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed) -+{ -+ struct ixgbe_mac_info *mac = &hw->mac; + { + struct ixgbe_mac_info *mac = &hw->mac; +- u32 lval, sval; +- s32 rc; + s32 status; + u32 reg_val; -+ + +- rc = mac->ops.read_iosf_sb_reg(hw, +- IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), +- IXGBE_SB_IOSF_TARGET_KR_PHY, &lval); +- if (rc) +- return rc; + /* iXFI is only supported with X552 */ + if (mac->type != ixgbe_mac_X550EM_x) + return IXGBE_ERR_LINK_SETUP; -+ + +- lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; +- lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; +- lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN; +- lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN; +- lval |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; +- rc = mac->ops.write_iosf_sb_reg(hw, + /* Disable AN and force speed to 10G Serial. */ + status = mac->ops.read_iosf_sb_reg(hw, -+ IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), + IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), +- IXGBE_SB_IOSF_TARGET_KR_PHY, lval); +- if (rc) +- return rc; + IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); + if (status != IXGBE_SUCCESS) + return status; -+ + +- rc = mac->ops.read_iosf_sb_reg(hw, +- IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), +- IXGBE_SB_IOSF_TARGET_KR_PHY, &sval); +- if (rc) +- return rc; + reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; + reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; -+ + +- sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D; +- sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D; +- rc = mac->ops.write_iosf_sb_reg(hw, +- IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), +- IXGBE_SB_IOSF_TARGET_KR_PHY, sval); +- if (rc) +- return rc; + /* Select forced link speed for internal PHY. */ + switch (*speed) { + case IXGBE_LINK_SPEED_10GB_FULL: @@ -54450,13 +54432,17 @@ index 77a60aa..ad9df6e 100644 + /* Other link speeds are not supported by internal KR PHY. */ + return IXGBE_ERR_LINK_SETUP; + } -+ + +- lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; +- rc = mac->ops.write_iosf_sb_reg(hw, + status = mac->ops.write_iosf_sb_reg(hw, -+ IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), + IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), +- IXGBE_SB_IOSF_TARGET_KR_PHY, lval); + IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); + if (status != IXGBE_SUCCESS) + return status; -+ + +- return rc; + /* Additional configuration needed for x550em_x */ + if (hw->mac.type == ixgbe_mac_X550EM_x) { + status = ixgbe_setup_ixfi_x550em_x(hw); @@ -54468,8 +54454,12 @@ index 77a60aa..ad9df6e 100644 + status = ixgbe_restart_an_internal_phy_x550em(hw); + + return status; -+} -+ + } + +-/** ixgbe_init_mac_link_ops_X550em - init mac link function pointers +- * @hw: pointer to hardware structure +- **/ +-static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw) +/** + * ixgbe_ext_phy_t_x550em_get_link - Get ext phy link status + * @hw: address of hardware structure @@ -54478,12 +54468,52 @@ index 77a60aa..ad9df6e 100644 + * Returns error code if unable to get link status. + */ +STATIC s32 ixgbe_ext_phy_t_x550em_get_link(struct ixgbe_hw *hw, bool *link_up) -+{ + { +- struct ixgbe_mac_info *mac = &hw->mac; + u32 ret; + u16 autoneg_status; -+ + +- mac->ops.setup_fc = ixgbe_setup_fc_x550em; + *link_up = false; -+ + +- switch (mac->ops.get_media_type(hw)) { +- case ixgbe_media_type_fiber: +- /* CS4227 does not support autoneg, so disable the laser control +- * functions for SFP+ fiber +- */ +- mac->ops.disable_tx_laser = NULL; +- mac->ops.enable_tx_laser = NULL; +- mac->ops.flap_tx_laser = NULL; +- mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber; +- switch (hw->device_id) { +- case IXGBE_DEV_ID_X550EM_A_SFP_N: +- mac->ops.setup_mac_link = ixgbe_setup_mac_link_sfp_n; +- break; +- case IXGBE_DEV_ID_X550EM_A_SFP: +- mac->ops.setup_mac_link = +- ixgbe_setup_mac_link_sfp_x550a; +- break; +- default: +- mac->ops.setup_mac_link = +- ixgbe_setup_mac_link_sfp_x550em; +- break; +- } +- mac->ops.set_rate_select_speed = +- ixgbe_set_soft_rate_select_speed; +- break; +- case ixgbe_media_type_copper: +- mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em; +- mac->ops.setup_fc = ixgbe_setup_fc_generic; +- mac->ops.check_link = ixgbe_check_link_t_X550em; +- return; +- case ixgbe_media_type_backplane: +- if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII || +- hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII_L) +- mac->ops.setup_link = ixgbe_setup_sgmii; +- break; +- default: +- break; +- } + /* read this twice back to back to indicate current status */ + ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, @@ -54500,8 +54530,10 @@ index 77a60aa..ad9df6e 100644 + *link_up = !!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS); + + return IXGBE_SUCCESS; -+} -+ + } + +-/** ixgbe_setup_sfp_modules_X550em - Setup SFP module +- * @hw: pointer to hardware structure +/** + * ixgbe_setup_internal_phy_t_x550em - Configure KR PHY to X557 link + * @hw: point to hardware structure @@ -54513,34 +54545,62 @@ index 77a60aa..ad9df6e 100644 + * + * A return of a non-zero value indicates an error, and the base driver should + * not report link up. -+ */ + */ +-static s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw) +s32 ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw) -+{ + { +- s32 status; +- bool linear; + ixgbe_link_speed force_speed; + bool link_up; + u32 status; + u16 speed; -+ + +- /* Check if SFP module is supported */ +- status = ixgbe_supported_sfp_modules_X550em(hw, &linear); +- if (status) +- return status; + if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper) + return IXGBE_ERR_CONFIG; -+ + +- ixgbe_init_mac_link_ops_X550em(hw); +- hw->phy.ops.reset = NULL; + if (hw->mac.type == ixgbe_mac_X550EM_x && + !(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) { + /* If link is down, there is no setup necessary so return */ + status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); + if (status != IXGBE_SUCCESS) + return status; -+ + +- return 0; +-} + if (!link_up) + return IXGBE_SUCCESS; -+ + +-/** ixgbe_get_link_capabilities_x550em - Determines link capabilities +- * @hw: pointer to hardware structure +- * @speed: pointer to link speed +- * @autoneg: true when autoneg or autotry is enabled +- **/ +-static s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw, +- ixgbe_link_speed *speed, +- bool *autoneg) +-{ +- /* SFP */ +- if (hw->phy.media_type == ixgbe_media_type_fiber) { +- /* CS4227 SFP must not enable auto-negotiation */ +- *autoneg = false; + status = hw->phy.ops.read_reg(hw, + IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + &speed); + if (status != IXGBE_SUCCESS) + return status; -+ + +- if (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 || +- hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1) { +- *speed = IXGBE_LINK_SPEED_1GB_FULL; +- return 0; + /* If link is still down - no setup is required so return */ + status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); + if (status != IXGBE_SUCCESS) @@ -54561,33 +54621,71 @@ index 77a60aa..ad9df6e 100644 + default: + /* Internal PHY does not support anything else */ + return IXGBE_ERR_INVALID_LINK_SETTINGS; -+ } -+ + } + +- /* Link capabilities are based on SFP */ +- if (hw->phy.multispeed_fiber) +- *speed = IXGBE_LINK_SPEED_10GB_FULL | +- IXGBE_LINK_SPEED_1GB_FULL; +- else +- *speed = IXGBE_LINK_SPEED_10GB_FULL; + return ixgbe_setup_ixfi_x550em(hw, &force_speed); -+ } else { + } else { +- *speed = IXGBE_LINK_SPEED_10GB_FULL | +- IXGBE_LINK_SPEED_1GB_FULL; +- *autoneg = true; + speed = IXGBE_LINK_SPEED_10GB_FULL | + IXGBE_LINK_SPEED_1GB_FULL; + return ixgbe_setup_kr_speed_x550em(hw, speed); -+ } -+} -+ -+/** + } +- return 0; + } + + /** +- * ixgbe_get_lasi_ext_t_x550em - Determime external Base T PHY interrupt cause +- * @hw: pointer to hardware structure +- * @lsc: pointer to boolean flag which indicates whether external Base T +- * PHY interrupt is lsc +- * +- * Determime if external Base T PHY interrupt cause is high temperature +- * failure alarm or link status change. + * ixgbe_setup_phy_loopback_x550em - Configure the KR PHY for loopback. + * @hw: pointer to hardware structure -+ * + * +- * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature +- * failure alarm, else return PHY access status. + * Configures the integrated KR PHY to use internal loopback mode. -+ **/ + **/ +-static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc) +s32 ixgbe_setup_phy_loopback_x550em(struct ixgbe_hw *hw) -+{ + { +- u32 status; +- u16 reg; +- +- *lsc = false; +- +- /* Vendor alarm triggered */ +- status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, +- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, +- ®); + s32 status; + u32 reg_val; -+ + +- if (status || !(reg & IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN)) + /* Disable AN and force speed to 10G Serial. */ + status = hw->mac.ops.read_iosf_sb_reg(hw, + IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); + if (status != IXGBE_SUCCESS) -+ return status; + return status; +- +- /* Vendor Auto-Neg alarm triggered or Global alarm 1 triggered */ +- status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG, +- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, +- ®); +- +- if (status || !(reg & (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | +- IXGBE_MDIO_GLOBAL_ALARM_1_INT))) + reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; + reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; + reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G; @@ -54595,8 +54693,12 @@ index 77a60aa..ad9df6e 100644 + IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); + if (status != IXGBE_SUCCESS) -+ return status; -+ + return status; + +- /* Global alarm triggered */ +- status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_ALARM_1, +- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, +- ®); + /* Set near-end loopback clocks. */ + status = hw->mac.ops.read_iosf_sb_reg(hw, + IXGBE_KRM_PORT_CAR_GEN_CTRL(hw->bus.lan_id), @@ -54610,7 +54712,8 @@ index 77a60aa..ad9df6e 100644 + IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); + if (status != IXGBE_SUCCESS) + return status; -+ + +- if (status) + /* Set loopback enable. */ + status = hw->mac.ops.read_iosf_sb_reg(hw, + IXGBE_KRM_PMD_DFX_BURNIN(hw->bus.lan_id), @@ -54622,8 +54725,21 @@ index 77a60aa..ad9df6e 100644 + IXGBE_KRM_PMD_DFX_BURNIN(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); + if (status != IXGBE_SUCCESS) -+ return status; -+ + return status; + +- /* If high temperature failure, then return over temp error and exit */ +- if (reg & IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL) { +- /* power down the PHY in case the PHY FW didn't already */ +- ixgbe_set_copper_phy_power(hw, false); +- return IXGBE_ERR_OVERTEMP; +- } +- if (reg & IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT) { +- /* device fault alarm triggered */ +- status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_FAULT_MSG, +- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, +- ®); +- if (status) +- return status; + /* Training bypass. */ + status = hw->mac.ops.read_iosf_sb_reg(hw, + IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), @@ -54634,10 +54750,20 @@ index 77a60aa..ad9df6e 100644 + status = hw->mac.ops.write_iosf_sb_reg(hw, + IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), + IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); -+ + +- /* if device fault was due to high temp alarm handle and exit */ +- if (reg == IXGBE_MDIO_GLOBAL_FAULT_MSG_HI_TMP) { +- /* power down the PHY in case the PHY FW didn't */ +- ixgbe_set_copper_phy_power(hw, false); +- return IXGBE_ERR_OVERTEMP; +- } +- } + return status; +} -+ + +- /* Vendor alarm 2 triggered */ +- status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, +- IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); +/** + * ixgbe_read_ee_hostif_X550 - Read EEPROM word using a host interface command + * assuming that the semaphore is already obtained. @@ -54652,93 +54778,144 @@ index 77a60aa..ad9df6e 100644 + const u32 mask = IXGBE_GSSR_SW_MNG_SM | IXGBE_GSSR_EEP_SM; + struct ixgbe_hic_read_shadow_ram buffer; + s32 status; -+ + +- if (status || !(reg & IXGBE_MDIO_GLOBAL_STD_ALM2_INT)) +- return status; + DEBUGFUNC("ixgbe_read_ee_hostif_X550"); + buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; + buffer.hdr.req.buf_lenh = 0; + buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; + buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; -+ + +- /* link connect/disconnect event occurred */ +- status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2, +- IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); + /* convert offset from words to bytes */ + buffer.address = IXGBE_CPU_TO_BE32(offset * 2); + /* one word */ + buffer.length = IXGBE_CPU_TO_BE16(sizeof(u16)); + buffer.pad2 = 0; + buffer.pad3 = 0; -+ + + status = hw->mac.ops.acquire_swfw_sync(hw, mask); -+ if (status) -+ return status; -+ + if (status) + return status; + +- /* Indicate LSC */ +- if (reg & IXGBE_MDIO_AUTO_NEG_VEN_LSC) +- *lsc = true; + status = ixgbe_hic_unlocked(hw, (u32 *)&buffer, sizeof(buffer), + IXGBE_HI_COMMAND_TIMEOUT); + if (!status) { + *data = (u16)IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, + FW_NVM_DATA_OFFSET); + } -+ + +- return 0; + hw->mac.ops.release_swfw_sync(hw, mask); + return status; -+} -+ -+/** + } + + /** +- * ixgbe_enable_lasi_ext_t_x550em - Enable external Base T PHY interrupts +- * @hw: pointer to hardware structure +- * +- * Enable link status change and temperature failure alarm for the external +- * Base T PHY + * ixgbe_read_ee_hostif_buffer_X550- Read EEPROM word(s) using hostif + * @hw: pointer to hardware structure + * @offset: offset of word in the EEPROM to read + * @words: number of words + * @data: word(s) read from the EEPROM -+ * + * +- * Returns PHY access status + * Reads a 16 bit word(s) from the EEPROM using the hostif. -+ **/ + **/ +-static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw) +s32 ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw *hw, + u16 offset, u16 words, u16 *data) -+{ + { +- u32 status; +- u16 reg; +- bool lsc; + const u32 mask = IXGBE_GSSR_SW_MNG_SM | IXGBE_GSSR_EEP_SM; + struct ixgbe_hic_read_shadow_ram buffer; + u32 current_word = 0; + u16 words_to_read; + s32 status; + u32 i; -+ + +- /* Clear interrupt flags */ +- status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc); + DEBUGFUNC("ixgbe_read_ee_hostif_buffer_X550"); -+ + +- /* Enable link status change alarm */ +- status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, +- IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); +- if (status) + /* Take semaphore for the entire operation. */ + status = hw->mac.ops.acquire_swfw_sync(hw, mask); + if (status) { + DEBUGOUT("EEPROM read buffer - semaphore failed\n"); -+ return status; + return status; + } -+ + +- reg |= IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN; + while (words) { + if (words > FW_MAX_READ_BUFFER_SIZE / 2) + words_to_read = FW_MAX_READ_BUFFER_SIZE / 2; + else + words_to_read = words; -+ + +- status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, +- IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg); +- if (status) +- return status; + buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; + buffer.hdr.req.buf_lenh = 0; + buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; + buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; -+ + +- /* Enable high temperature failure and global fault alarms */ +- status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, +- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, +- ®); +- if (status) +- return status; + /* convert offset from words to bytes */ + buffer.address = IXGBE_CPU_TO_BE32((offset + current_word) * 2); + buffer.length = IXGBE_CPU_TO_BE16(words_to_read * 2); + buffer.pad2 = 0; + buffer.pad3 = 0; -+ + +- reg |= (IXGBE_MDIO_GLOBAL_INT_HI_TEMP_EN | +- IXGBE_MDIO_GLOBAL_INT_DEV_FAULT_EN); + status = ixgbe_hic_unlocked(hw, (u32 *)&buffer, sizeof(buffer), + IXGBE_HI_COMMAND_TIMEOUT); -+ + +- status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, +- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, +- reg); +- if (status) +- return status; + if (status) { + DEBUGOUT("Host interface command failed\n"); + goto out; + } -+ + +- /* Enable vendor Auto-Neg alarm and Global Interrupt Mask 1 alarm */ +- status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, +- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, +- ®); +- if (status) +- return status; + for (i = 0; i < words_to_read; i++) { + u32 reg = IXGBE_FLEX_MNG + (FW_NVM_DATA_OFFSET << 2) + + 2 * i; + u32 value = IXGBE_READ_REG(hw, reg); -+ + +- reg |= (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | +- IXGBE_MDIO_GLOBAL_ALARM_1_INT); + data[current_word] = (u16)(value & 0xffff); + current_word++; + i++; @@ -54750,12 +54927,23 @@ index 77a60aa..ad9df6e 100644 + } + words -= words_to_read; + } -+ + +- status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, +- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, +- reg); +- if (status) +- return status; +out: + hw->mac.ops.release_swfw_sync(hw, mask); + return status; +} -+ + +- /* Enable chip-wide vendor alarm */ +- status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, +- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, +- ®); +- if (status) +- return status; +/** + * ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif + * @hw: pointer to hardware structure @@ -54769,9 +54957,13 @@ index 77a60aa..ad9df6e 100644 +{ + s32 status; + struct ixgbe_hic_write_shadow_ram buffer; -+ + +- reg |= IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN; + DEBUGFUNC("ixgbe_write_ee_hostif_data_X550"); -+ + +- status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, +- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, +- reg); + buffer.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD; + buffer.hdr.req.buf_lenh = 0; + buffer.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN; @@ -54785,25 +54977,42 @@ index 77a60aa..ad9df6e 100644 + status = ixgbe_host_interface_command(hw, (u32 *)&buffer, + sizeof(buffer), + IXGBE_HI_COMMAND_TIMEOUT, false); -+ -+ return status; -+} -+ -+/** + + return status; + } + + /** +- * ixgbe_handle_lasi_ext_t_x550em - Handle external Base T PHY interrupt +- * @hw: pointer to hardware structure +- * +- * Handle external Base T PHY interrupt. If high temperature +- * failure alarm then return error, else if link status change +- * then setup internal/external PHY link + * ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif + * @hw: pointer to hardware structure + * @offset: offset of word in the EEPROM to write + * @data: word write to the EEPROM -+ * + * +- * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature +- * failure alarm, else return PHY access status. + * Write a 16 bit word to the EEPROM using the hostif. -+ **/ + **/ +-static s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw) +s32 ixgbe_write_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, + u16 data) -+{ + { +- struct ixgbe_phy_info *phy = &hw->phy; +- bool lsc; +- u32 status; + s32 status = IXGBE_SUCCESS; -+ + +- status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc); +- if (status) +- return status; + DEBUGFUNC("ixgbe_write_ee_hostif_X550"); -+ + +- if (lsc && phy->ops.setup_internal_link) +- return phy->ops.setup_internal_link(hw); + if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == + IXGBE_SUCCESS) { + status = ixgbe_write_ee_hostif_data_X550(hw, offset, data); @@ -54812,70 +55021,111 @@ index 77a60aa..ad9df6e 100644 + DEBUGOUT("write ee hostif failed to get semaphore"); + status = IXGBE_ERR_SWFW_SYNC; + } -+ + +- return 0; + return status; -+} -+ -+/** + } + + /** +- * ixgbe_setup_kr_speed_x550em - Configure the KR PHY for link speed. +- * @hw: pointer to hardware structure +- * @speed: link speed + * ixgbe_write_ee_hostif_buffer_X550 - Write EEPROM word(s) using hostif + * @hw: pointer to hardware structure + * @offset: offset of word in the EEPROM to write + * @words: number of words + * @data: word(s) write to the EEPROM -+ * + * +- * Configures the integrated KR PHY. + * Write a 16 bit word(s) to the EEPROM using the hostif. -+ **/ + **/ +-static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw, +- ixgbe_link_speed speed) +s32 ixgbe_write_ee_hostif_buffer_X550(struct ixgbe_hw *hw, + u16 offset, u16 words, u16 *data) -+{ + { +- s32 status; +- u32 reg_val; + s32 status = IXGBE_SUCCESS; + u32 i = 0; -+ + +- status = hw->mac.ops.read_iosf_sb_reg(hw, +- IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), +- IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); +- if (status) +- return status; + DEBUGFUNC("ixgbe_write_ee_hostif_buffer_X550"); -+ + +- reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; +- reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR | +- IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX); + /* Take semaphore for the entire operation. */ + status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM); + if (status != IXGBE_SUCCESS) { + DEBUGOUT("EEPROM write buffer - semaphore failed\n"); + goto out; + } -+ + +- /* Advertise 10G support. */ +- if (speed & IXGBE_LINK_SPEED_10GB_FULL) +- reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR; + for (i = 0; i < words; i++) { + status = ixgbe_write_ee_hostif_data_X550(hw, offset + i, + data[i]); -+ + +- /* Advertise 1G support. */ +- if (speed & IXGBE_LINK_SPEED_1GB_FULL) +- reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX; + if (status != IXGBE_SUCCESS) { + DEBUGOUT("Eeprom buffered write failed\n"); + break; + } + } -+ + +- /* Restart auto-negotiation. */ +- reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; +- status = hw->mac.ops.write_iosf_sb_reg(hw, +- IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), +- IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); + hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); +out: -+ -+ return status; -+} -+ + + return status; + } + +-/** ixgbe_setup_kx4_x550em - Configure the KX4 PHY. +- * @hw: pointer to hardware structure +/** + * ixgbe_checksum_ptr_x550 - Checksum one pointer region + * @hw: pointer to hardware structure + * @ptr: pointer offset in eeprom + * @size: size of section pointed by ptr, if 0 first word will be used as size + * @csum: address of checksum to update -+ * + * +- * Configures the integrated KX4 PHY. +- **/ +-static s32 ixgbe_setup_kx4_x550em(struct ixgbe_hw *hw) + * Returns error status for any failure + */ +STATIC s32 ixgbe_checksum_ptr_x550(struct ixgbe_hw *hw, u16 ptr, + u16 size, u16 *csum, u16 *buffer, + u32 buffer_size) -+{ + { + u16 buf[256]; -+ s32 status; + s32 status; +- u32 reg_val; + u16 length, bufsz, i, start; + u16 *local_buffer; -+ + +- status = hw->mac.ops.read_iosf_sb_reg(hw, IXGBE_KX4_LINK_CNTL_1, +- IXGBE_SB_IOSF_TARGET_KX4_PCS0 + +- hw->bus.lan_id, ®_val); +- if (status) +- return status; + bufsz = sizeof(buf) / sizeof(buf[0]); -+ + +- reg_val &= ~(IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4 | +- IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX); + /* Read a chunk at the pointer location */ + if (!buffer) { + status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, bufsz, buf); @@ -54889,30 +55139,43 @@ index 77a60aa..ad9df6e 100644 + return IXGBE_ERR_PARAM; + local_buffer = &buffer[ptr]; + } -+ + +- reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_ENABLE; + if (size) { + start = 0; + length = size; + } else { + start = 1; + length = local_buffer[0]; -+ + +- /* Advertise 10G support. */ +- if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) +- reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4; + /* Skip pointer section if length is invalid. */ + if (length == 0xFFFF || length == 0 || + (ptr + length) >= hw->eeprom.word_size) + return IXGBE_SUCCESS; + } -+ + +- /* Advertise 1G support. */ +- if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) +- reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX; + if (buffer && ((u32)start + (u32)length > buffer_size)) + return IXGBE_ERR_PARAM; -+ + +- /* Restart auto-negotiation. */ +- reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_RESTART; +- status = hw->mac.ops.write_iosf_sb_reg(hw, IXGBE_KX4_LINK_CNTL_1, +- IXGBE_SB_IOSF_TARGET_KX4_PCS0 + +- hw->bus.lan_id, reg_val); + for (i = start; length; i++, length--) { + if (i == bufsz && !buffer) { + ptr += bufsz; + i = 0; + if (length < bufsz) + bufsz = length; -+ + +- return status; + /* Read a chunk at the pointer location */ + status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, + bufsz, buf); @@ -54924,28 +55187,47 @@ index 77a60aa..ad9df6e 100644 + *csum += local_buffer[i]; + } + return IXGBE_SUCCESS; -+} -+ -+/** + } + + /** +- * ixgbe_setup_kr_x550em - Configure the KR PHY +- * @hw: pointer to hardware structure + * ixgbe_calc_checksum_X550 - Calculates and returns the checksum + * @hw: pointer to hardware structure + * @buffer: pointer to buffer containing calculated checksum + * @buffer_size: size of buffer + * + * Returns a negative error code on error, or the 16-bit checksum -+ **/ + **/ +-static s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw) +s32 ixgbe_calc_checksum_X550(struct ixgbe_hw *hw, u16 *buffer, u32 buffer_size) -+{ + { +- /* leave link alone for 2.5G */ +- if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_2_5GB_FULL) +- return 0; + u16 eeprom_ptrs[IXGBE_EEPROM_LAST_WORD + 1]; + u16 *local_buffer; + s32 status; + u16 checksum = 0; + u16 pointer, i, size; -+ + +- return ixgbe_setup_kr_speed_x550em(hw, hw->phy.autoneg_advertised); +-} + DEBUGFUNC("ixgbe_calc_eeprom_checksum_X550"); -+ + +-/** ixgbe_ext_phy_t_x550em_get_link - Get ext phy link status +- * @hw: address of hardware structure +- * @link_up: address of boolean to indicate link status +- * +- * Returns error code if unable to get link status. +- **/ +-static s32 ixgbe_ext_phy_t_x550em_get_link(struct ixgbe_hw *hw, bool *link_up) +-{ +- u32 ret; +- u16 autoneg_status; + hw->eeprom.ops.init_params(hw); -+ + +- *link_up = false; + if (!buffer) { + /* Read pointer area */ + status = ixgbe_read_ee_hostif_buffer_X550(hw, 0, @@ -54961,7 +55243,13 @@ index 77a60aa..ad9df6e 100644 + return IXGBE_ERR_PARAM; + local_buffer = buffer; + } -+ + +- /* read this twice back to back to indicate current status */ +- ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, +- IXGBE_MDIO_AUTO_NEG_DEV_TYPE, +- &autoneg_status); +- if (ret) +- return ret; + /* + * For X550 hardware include 0x0-0x41 in the checksum, skip the + * checksum word itself @@ -54969,7 +55257,12 @@ index 77a60aa..ad9df6e 100644 + for (i = 0; i <= IXGBE_EEPROM_LAST_WORD; i++) + if (i != IXGBE_EEPROM_CHECKSUM) + checksum += local_buffer[i]; -+ + +- ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, +- IXGBE_MDIO_AUTO_NEG_DEV_TYPE, +- &autoneg_status); +- if (ret) +- return ret; + /* + * Include all data from pointers 0x3, 0x6-0xE. This excludes the + * FW, PHY module, and PCIe Expansion/Option ROM pointers. @@ -54977,7 +55270,8 @@ index 77a60aa..ad9df6e 100644 + for (i = IXGBE_PCIE_ANALOG_PTR_X550; i < IXGBE_FW_PTR; i++) { + if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR) + continue; -+ + +- *link_up = !!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS); + pointer = local_buffer[i]; + + /* Skip pointer section if the pointer is invalid. */ @@ -55003,51 +55297,64 @@ index 77a60aa..ad9df6e 100644 + if (status) + return status; + } -+ + +- return 0; + checksum = (u16)IXGBE_EEPROM_SUM - checksum; + + return (s32)checksum; -+} -+ + } + +-/** ixgbe_setup_internal_phy_t_x550em - Configure KR PHY to X557 link +- * @hw: point to hardware structure +- * +- * Configures the link between the integrated KR PHY and the external X557 PHY +- * The driver will call this function when it gets a link status change +- * interrupt from the X557 PHY. This function configures the link speed +- * between the PHYs to match the link speed of the BASE-T link. +/** + * ixgbe_calc_eeprom_checksum_X550 - Calculates and returns the checksum + * @hw: pointer to hardware structure -+ * + * +- * A return of a non-zero value indicates an error, and the base driver should +- * not report link up. + * Returns a negative error code on error, or the 16-bit checksum -+ **/ + **/ +-static s32 ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw) +s32 ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw) -+{ + { +- ixgbe_link_speed force_speed; +- bool link_up; +- u32 status; +- u16 speed; + return ixgbe_calc_checksum_X550(hw, NULL, 0); - } ++} - /** -- * ixgbe_led_on_t_x550em - Turns on the software controllable LEDs. +- if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper) +- return IXGBE_ERR_CONFIG; ++/** + * ixgbe_validate_eeprom_checksum_X550 - Validate EEPROM checksum - * @hw: pointer to hardware structure -- * @led_idx: led number to turn on ++ * @hw: pointer to hardware structure + * @checksum_val: calculated checksum + * + * Performs checksum calculation and validates the EEPROM checksum. If the + * caller does not need checksum_val, the value can be NULL. - **/ --static s32 ixgbe_led_on_t_x550em(struct ixgbe_hw *hw, u32 led_idx) ++ **/ +s32 ixgbe_validate_eeprom_checksum_X550(struct ixgbe_hw *hw, u16 *checksum_val) - { -- u16 phy_data; ++{ + s32 status; + u16 checksum; + u16 read_checksum = 0; -- if (led_idx >= IXGBE_X557_MAX_LED_INDEX) -- return IXGBE_ERR_PARAM; +- if (hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE) { +- speed = IXGBE_LINK_SPEED_10GB_FULL | +- IXGBE_LINK_SPEED_1GB_FULL; +- return ixgbe_setup_kr_speed_x550em(hw, speed); +- } + DEBUGFUNC("ixgbe_validate_eeprom_checksum_X550"); -- /* To turn on the LED, set mode to ON. */ -- hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, -- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &phy_data); -- phy_data |= IXGBE_X557_LED_MANUAL_SET_MASK; -- hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, -- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, phy_data); +- /* If link is not up, then there is no setup necessary so return */ +- status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); +- if (status) + /* 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 @@ -55055,38 +55362,45 @@ index 77a60aa..ad9df6e 100644 + status = hw->eeprom.ops.read(hw, 0, &checksum); + if (status) { + DEBUGOUT("EEPROM read failed\n"); -+ return status; + return status; + } -- return 0; --} +- if (!link_up) +- return 0; +- +- status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, +- IXGBE_MDIO_AUTO_NEG_DEV_TYPE, +- &speed); +- if (status) + status = hw->eeprom.ops.calc_checksum(hw); + if (status < 0) -+ return status; + return status; --/** -- * ixgbe_led_off_t_x550em - Turns off the software controllable LEDs. -- * @hw: pointer to hardware structure -- * @led_idx: led number to turn off -- **/ --static s32 ixgbe_led_off_t_x550em(struct ixgbe_hw *hw, u32 led_idx) --{ -- u16 phy_data; +- /* If link is not still up, then no setup is necessary so return */ +- status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); + checksum = (u16)(status & 0xffff); - -- if (led_idx >= IXGBE_X557_MAX_LED_INDEX) -- return IXGBE_ERR_PARAM; ++ + status = ixgbe_read_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, + &read_checksum); -+ if (status) -+ return status; + if (status) + return status; -- /* To turn on the LED, set mode to ON. */ -- hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, -- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &phy_data); -- phy_data &= ~IXGBE_X557_LED_MANUAL_SET_MASK; -- hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, -- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, phy_data); +- if (!link_up) +- return 0; +- +- /* clear everything but the speed and duplex bits */ +- speed &= IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK; +- +- switch (speed) { +- case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_FULL: +- force_speed = IXGBE_LINK_SPEED_10GB_FULL; +- break; +- case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB_FULL: +- force_speed = IXGBE_LINK_SPEED_1GB_FULL; +- break; +- default: +- /* Internal PHY does not support anything else */ +- return IXGBE_ERR_INVALID_LINK_SETTINGS; + /* Verify read checksum from EEPROM is the same as + * calculated checksum + */ @@ -55094,43 +55408,35 @@ index 77a60aa..ad9df6e 100644 + status = IXGBE_ERR_EEPROM_CHECKSUM; + ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE, + "Invalid EEPROM checksum"); -+ } -+ + } + +- return ixgbe_setup_ixfi_x550em(hw, &force_speed); + /* If the user cares, return the calculated checksum */ + if (checksum_val) + *checksum_val = checksum; - -- return 0; ++ + return status; } --/** ixgbe_get_lcd_x550em - Determine lowest common denominator +-/** ixgbe_reset_phy_t_X550em - Performs X557 PHY reset and enables LASI - * @hw: pointer to hardware structure -- * @lcd_speed: pointer to lowest common link speed +/** + * ixgbe_update_eeprom_checksum_X550 - Updates the EEPROM checksum and flash + * @hw: pointer to hardware structure - * -- * Determine lowest common link speed with link partner. ++ * + * After writing EEPROM to shadow RAM using EEWR register, software calculates + * checksum and updates the EEPROM and instructs the hardware to update + * the flash. **/ --static s32 ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw, -- ixgbe_link_speed *lcd_speed) +-static s32 ixgbe_reset_phy_t_X550em(struct ixgbe_hw *hw) +s32 ixgbe_update_eeprom_checksum_X550(struct ixgbe_hw *hw) { -- u16 an_lp_status; s32 status; -- u16 word = hw->eeprom.ctrl_word_3; + u16 checksum = 0; -- *lcd_speed = IXGBE_LINK_SPEED_UNKNOWN; +- status = ixgbe_reset_phy_generic(hw); + DEBUGFUNC("ixgbe_update_eeprom_checksum_X550"); -- status = hw->phy.ops.read_reg(hw, IXGBE_AUTO_NEG_LP_STATUS, -- IXGBE_MDIO_AUTO_NEG_DEV_TYPE, -- &an_lp_status); - if (status) + /* 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 @@ -55142,93 +55448,113 @@ index 77a60aa..ad9df6e 100644 return status; + } -- /* If link partner advertised 1G, return 1G */ -- if (an_lp_status & IXGBE_AUTO_NEG_LP_1000BASE_CAP) { -- *lcd_speed = IXGBE_LINK_SPEED_1GB_FULL; +- /* Configure Link Status Alarm and Temperature Threshold interrupts */ +- return ixgbe_enable_lasi_ext_t_x550em(hw); +-} + status = ixgbe_calc_eeprom_checksum_X550(hw); + if (status < 0) - return status; -- } ++ return status; -- /* If 10G disabled for LPLU via NVM D10GMP, then return no valid LCD */ -- if ((hw->bus.lan_id && (word & NVM_INIT_CTRL_3_D10GMP_PORT1)) || -- (word & NVM_INIT_CTRL_3_D10GMP_PORT0)) +-/** +- * ixgbe_led_on_t_x550em - Turns on the software controllable LEDs. +- * @hw: pointer to hardware structure +- * @led_idx: led number to turn on +- **/ +-static s32 ixgbe_led_on_t_x550em(struct ixgbe_hw *hw, u32 led_idx) +-{ +- u16 phy_data; + checksum = (u16)(status & 0xffff); -+ + +- if (led_idx >= IXGBE_X557_MAX_LED_INDEX) +- return IXGBE_ERR_PARAM; + status = ixgbe_write_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, + checksum); + if (status) - return status; ++ return status; -- /* Link partner not capable of lower speeds, return 10G */ -- *lcd_speed = IXGBE_LINK_SPEED_10GB_FULL; +- /* To turn on the LED, set mode to ON. */ +- hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, +- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &phy_data); +- phy_data |= IXGBE_X557_LED_MANUAL_SET_MASK; +- hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, +- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, phy_data); + status = ixgbe_update_flash_X550(hw); -+ - return status; + +- return 0; ++ return status; } /** -- * ixgbe_setup_fc_x550em - Set up flow control -- * @hw: pointer to hardware structure -- */ --static s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *hw) +- * ixgbe_led_off_t_x550em - Turns off the software controllable LEDs. + * ixgbe_update_flash_X550 - Instruct HW to copy EEPROM to Flash device -+ * @hw: pointer to hardware structure + * @hw: pointer to hardware structure +- * @led_idx: led number to turn off + * + * Issue a shadow RAM dump to FW to copy EEPROM from shadow RAM to the flash. -+ **/ + **/ +-static s32 ixgbe_led_off_t_x550em(struct ixgbe_hw *hw, u32 led_idx) +s32 ixgbe_update_flash_X550(struct ixgbe_hw *hw) { -- bool pause, asm_dir; -- u32 reg_val; -- s32 rc; +- u16 phy_data; + s32 status = IXGBE_SUCCESS; + union ixgbe_hic_hdr2 buffer; -- /* Validate the requested mode */ -- if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { -- hw_err(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); -- return IXGBE_ERR_INVALID_LINK_SETTINGS; -- } +- if (led_idx >= IXGBE_X557_MAX_LED_INDEX) +- return IXGBE_ERR_PARAM; + DEBUGFUNC("ixgbe_update_flash_X550"); -- /* 10gig parts do not have a word in the EEPROM to determine the -- * default flow control setting, so we explicitly set it to full. -- */ -- if (hw->fc.requested_mode == ixgbe_fc_default) -- hw->fc.requested_mode = ixgbe_fc_full; +- /* To turn on the LED, set mode to ON. */ +- hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, +- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &phy_data); +- phy_data &= ~IXGBE_X557_LED_MANUAL_SET_MASK; +- hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, +- IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, phy_data); + buffer.req.cmd = FW_SHADOW_RAM_DUMP_CMD; + buffer.req.buf_lenh = 0; + buffer.req.buf_lenl = FW_SHADOW_RAM_DUMP_LEN; + buffer.req.checksum = FW_DEFAULT_CHECKSUM; - -- /* Determine PAUSE and ASM_DIR bits. */ -- switch (hw->fc.requested_mode) { -- case ixgbe_fc_none: -- pause = false; -- asm_dir = false; ++ + status = ixgbe_host_interface_command(hw, (u32 *)&buffer, + sizeof(buffer), + IXGBE_HI_COMMAND_TIMEOUT, false); -+ + +- return 0; + return status; -+} -+ + } + +-/** ixgbe_get_lcd_x550em - Determine lowest common denominator +/** + * ixgbe_get_supported_physical_layer_X550em - Returns physical layer type -+ * @hw: pointer to hardware structure -+ * + * @hw: pointer to hardware structure +- * @lcd_speed: pointer to lowest common link speed + * +- * Determine lowest common link speed with link partner. + * Determines physical layer capabilities of the current configuration. -+ **/ + **/ +-static s32 ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw, +- ixgbe_link_speed *lcd_speed) +u64 ixgbe_get_supported_physical_layer_X550em(struct ixgbe_hw *hw) -+{ + { +- u16 an_lp_status; +- s32 status; +- u16 word = hw->eeprom.ctrl_word_3; + u64 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; + u16 ext_ability = 0; -+ + +- *lcd_speed = IXGBE_LINK_SPEED_UNKNOWN; + DEBUGFUNC("ixgbe_get_supported_physical_layer_X550em"); -+ + +- status = hw->phy.ops.read_reg(hw, IXGBE_AUTO_NEG_LP_STATUS, +- IXGBE_MDIO_AUTO_NEG_DEV_TYPE, +- &an_lp_status); +- if (status) +- return status; + hw->phy.ops.identify(hw); -+ + +- /* If link partner advertised 1G, return 1G */ +- if (an_lp_status & IXGBE_AUTO_NEG_LP_1000BASE_CAP) { +- *lcd_speed = IXGBE_LINK_SPEED_1GB_FULL; +- return status; + switch (hw->phy.type) { + case ixgbe_phy_x550em_kr: + if (hw->mac.type == ixgbe_mac_X550EM_a) { @@ -55248,27 +55574,11 @@ index 77a60aa..ad9df6e 100644 + case ixgbe_phy_x550em_xfi: + physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KR | + IXGBE_PHYSICAL_LAYER_1000BASE_KX; - break; -- case ixgbe_fc_tx_pause: -- pause = false; -- asm_dir = true; ++ break; + case ixgbe_phy_x550em_kx4: + physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KX4 | + IXGBE_PHYSICAL_LAYER_1000BASE_KX; - break; -- case ixgbe_fc_rx_pause: -- /* Rx Flow control is enabled and Tx Flow control is -- * disabled by software override. Since there really -- * isn't a way to advertise that we are capable of RX -- * Pause ONLY, we will advertise that we support both -- * symmetric and asymmetric Rx PAUSE, as such we fall -- * through to the fc_full statement. Later, we will -- * disable the adapter's ability to send PAUSE frames. -- */ -- /* Fallthrough */ -- case ixgbe_fc_full: -- pause = true; -- asm_dir = true; ++ break; + case ixgbe_phy_x550em_ext_t: + hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY, + IXGBE_MDIO_PMA_PMD_DEV_TYPE, @@ -55291,49 +55601,98 @@ index 77a60aa..ad9df6e 100644 + break; + case ixgbe_phy_ext_1g_t: + physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T; - break; - default: -- hw_err(hw, "Flow control param set incorrectly\n"); -- return IXGBE_ERR_CONFIG; ++ break; ++ default: + break; } -- if (hw->device_id != IXGBE_DEV_ID_X550EM_X_KR && -- hw->device_id != IXGBE_DEV_ID_X550EM_A_KR && -- hw->device_id != IXGBE_DEV_ID_X550EM_A_KR_L) -- return 0; +- /* If 10G disabled for LPLU via NVM D10GMP, then return no valid LCD */ +- if ((hw->bus.lan_id && (word & NVM_INIT_CTRL_3_D10GMP_PORT1)) || +- (word & NVM_INIT_CTRL_3_D10GMP_PORT0)) +- return status; + if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) + physical_layer = ixgbe_get_supported_phy_sfp_layer_generic(hw); -- rc = hw->mac.ops.read_iosf_sb_reg(hw, -- IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), -- IXGBE_SB_IOSF_TARGET_KR_PHY, -- ®_val); -- if (rc) -- return rc; +- /* Link partner not capable of lower speeds, return 10G */ +- *lcd_speed = IXGBE_LINK_SPEED_10GB_FULL; +- return status; + return physical_layer; -+} -+ -+/** + } + + /** +- * ixgbe_setup_fc_x550em - Set up flow control + * ixgbe_get_bus_info_x550em - Set PCI bus info -+ * @hw: pointer to hardware structure + * @hw: pointer to hardware structure +- */ +-static s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *hw) + * + * Sets bus link width and speed to unknown because X550em is + * not a PCI device. + **/ +s32 ixgbe_get_bus_info_X550em(struct ixgbe_hw *hw) -+{ -+ + { +- bool pause, asm_dir; +- u32 reg_val; +- s32 rc; + +- /* Validate the requested mode */ +- if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { +- hw_err(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); +- return IXGBE_ERR_INVALID_LINK_SETTINGS; +- } + DEBUGFUNC("ixgbe_get_bus_info_x550em"); -+ + +- /* 10gig parts do not have a word in the EEPROM to determine the +- * default flow control setting, so we explicitly set it to full. +- */ +- if (hw->fc.requested_mode == ixgbe_fc_default) +- hw->fc.requested_mode = ixgbe_fc_full; + hw->bus.width = ixgbe_bus_width_unknown; + hw->bus.speed = ixgbe_bus_speed_unknown; -+ + +- /* Determine PAUSE and ASM_DIR bits. */ +- switch (hw->fc.requested_mode) { +- case ixgbe_fc_none: +- pause = false; +- asm_dir = false; +- break; +- case ixgbe_fc_tx_pause: +- pause = false; +- asm_dir = true; +- break; +- case ixgbe_fc_rx_pause: +- /* Rx Flow control is enabled and Tx Flow control is +- * disabled by software override. Since there really +- * isn't a way to advertise that we are capable of RX +- * Pause ONLY, we will advertise that we support both +- * symmetric and asymmetric Rx PAUSE, as such we fall +- * through to the fc_full statement. Later, we will +- * disable the adapter's ability to send PAUSE frames. +- */ +- /* Fallthrough */ +- case ixgbe_fc_full: +- pause = true; +- asm_dir = true; +- break; +- default: +- hw_err(hw, "Flow control param set incorrectly\n"); +- return IXGBE_ERR_CONFIG; +- } + hw->mac.ops.set_lan_id(hw); -+ + +- if (hw->device_id != IXGBE_DEV_ID_X550EM_X_KR && +- hw->device_id != IXGBE_DEV_ID_X550EM_A_KR && +- hw->device_id != IXGBE_DEV_ID_X550EM_A_KR_L) +- return 0; + return IXGBE_SUCCESS; +} -+ + +- rc = hw->mac.ops.read_iosf_sb_reg(hw, +- IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), +- IXGBE_SB_IOSF_TARGET_KR_PHY, +- ®_val); +- if (rc) +- return rc; +/** + * ixgbe_disable_rx_x550 - Disable RX unit + * @@ -55408,7 +55767,7 @@ index 77a60aa..ad9df6e 100644 { u16 an_10g_cntl_reg, autoneg_reg, speed; s32 status; -@@ -2295,45 +3736,52 @@ static s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw) +@@ -2295,45 +3831,52 @@ static s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw) u32 save_autoneg; bool link_up; @@ -55474,7 +55833,7 @@ index 77a60aa..ad9df6e 100644 return ixgbe_set_copper_phy_power(hw, false); /* clear everything but the speed bits */ -@@ -2350,20 +3798,23 @@ static s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw) +@@ -2350,20 +3893,23 @@ static s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw) status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM, IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg); @@ -55506,7 +55865,7 @@ index 77a60aa..ad9df6e 100644 return status; save_autoneg = hw->phy.autoneg_advertised; -@@ -2378,353 +3829,363 @@ static s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw) +@@ -2378,353 +3924,363 @@ static s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw) } /** @@ -55932,8 +56291,7 @@ index 77a60aa..ad9df6e 100644 + hw->fc.current_mode = hw->fc.requested_mode; } +} - -- msleep(50); ++ +/** + * ixgbe_fc_autoneg_fiber_x550em_a - passthrough FC settings + * @hw: pointer to hardware structure @@ -55945,9 +56303,7 @@ index 77a60aa..ad9df6e 100644 + hw->fc.current_mode = hw->fc.requested_mode; +} -- /* Double resets are required for recovery from certain error -- * clear the multicast table. Also reset num_rar_entries to 128, -- * since we modify this value when programming the SAN MAC address. +- msleep(50); +/** + * ixgbe_fc_autoneg_sgmii_x550em_a - Enable flow control IEEE clause 37 + * @hw: pointer to hardware structure @@ -55960,7 +56316,10 @@ index 77a60aa..ad9df6e 100644 + u32 info[FW_PHY_ACT_DATA_COUNT] = { 0 }; + ixgbe_link_speed speed; + bool link_up; -+ + +- /* Double resets are required for recovery from certain error +- * clear the multicast table. Also reset num_rar_entries to 128, +- * since we modify this value when programming the SAN MAC address. + /* AN should have completed when the cable was plugged in. + * Look for reasons to bail out. Bail out if: + * - FC autoneg is disabled, or if @@ -56146,7 +56505,7 @@ index 77a60aa..ad9df6e 100644 } /** -@@ -2732,7 +4193,7 @@ static void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw, +@@ -2732,7 +4288,7 @@ static void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw, * @hw: pointer to hardware structure * @state: set mux if 1, clear if 0 */ @@ -56155,7 +56514,7 @@ index 77a60aa..ad9df6e 100644 { u32 esdp; -@@ -2748,16 +4209,18 @@ static void ixgbe_set_mux(struct ixgbe_hw *hw, u8 state) +@@ -2748,16 +4304,18 @@ static void ixgbe_set_mux(struct ixgbe_hw *hw, u8 state) } /** @@ -56180,7 +56539,7 @@ index 77a60aa..ad9df6e 100644 status = ixgbe_acquire_swfw_sync_X540(hw, mask); if (status) return status; -@@ -2765,18 +4228,20 @@ static s32 ixgbe_acquire_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask) +@@ -2765,18 +4323,20 @@ static s32 ixgbe_acquire_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask) if (mask & IXGBE_GSSR_I2C_MASK) ixgbe_set_mux(hw, 1); @@ -56208,7 +56567,7 @@ index 77a60aa..ad9df6e 100644 if (mask & IXGBE_GSSR_I2C_MASK) ixgbe_set_mux(hw, 0); -@@ -2784,51 +4249,68 @@ static void ixgbe_release_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask) +@@ -2784,51 +4344,68 @@ static void ixgbe_release_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask) } /** @@ -56295,7 +56654,7 @@ index 77a60aa..ad9df6e 100644 if (mask & IXGBE_GSSR_TOKEN_SM) ixgbe_put_phy_token(hw); -@@ -2837,20 +4319,22 @@ static void ixgbe_release_swfw_sync_x550em_a(struct ixgbe_hw *hw, u32 mask) +@@ -2837,20 +4414,22 @@ static void ixgbe_release_swfw_sync_x550em_a(struct ixgbe_hw *hw, u32 mask) } /** @@ -56329,7 +56688,7 @@ index 77a60aa..ad9df6e 100644 if (hw->mac.ops.acquire_swfw_sync(hw, mask)) return IXGBE_ERR_SWFW_SYNC; -@@ -2863,233 +4347,272 @@ static s32 ixgbe_read_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, +@@ -2863,233 +4442,272 @@ static s32 ixgbe_read_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, } /** |
