summaryrefslogtreecommitdiff
path: root/machine
diff options
context:
space:
mode:
authordavid_yang <[email protected]>2019-12-25 09:38:04 +0800
committeradoyle <[email protected]>2020-05-15 17:06:23 +0000
commit62972a74bd67cc29550b7a13dfd4fc97efd3d813 (patch)
tree209b723913555e0bda24c707821030eb10ab4ff8 /machine
parente1dacbe69336ac9e57571214d72b80b8f81fcf4c (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/INSTALL110
-rw-r--r--machine/accton/accton_ebof/busybox/conf/config9
-rw-r--r--machine/accton/accton_ebof/demo/platform.conf1
-rw-r--r--machine/accton/accton_ebof/installer.conf30
-rw-r--r--machine/accton/accton_ebof/kernel/config8
-rw-r--r--machine/accton/accton_ebof/kernel/platform-ebof.patch114
-rw-r--r--machine/accton/accton_ebof/kernel/series3
-rw-r--r--machine/accton/accton_ebof/machine.make45
-rw-r--r--machine/accton/accton_ebof/rootconf/sysroot-lib-onie/sysinfo-platform12
-rw-r--r--machine/accton/kernel/driver-intel-ixgbe.patch3873
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, &reg_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, &reg_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, &reg_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, &reg_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, &reg_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, &reg_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,
-- &reg_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, &reg_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,
- &reg);
-
-- 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,
++ &reg);
++
+ 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,
- &reg);
-
-- 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,
++ &reg);
++
+ 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,
- &reg);
-
-- 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,
++ &reg);
++
+ 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,
- &reg);
-- 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,
++ &reg);
+
+ 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, &reg);
-
-- 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, &reg);
++
+ 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, &reg);
-
-- 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, &reg);
++
+ 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, &reg);
-- 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,
- &reg);
-- 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,
++ &reg);
+
+ 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,
- &reg);
-- 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,
++ &reg);
+
+ 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,
- &reg);
-- 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,
++ &reg);
+
+ 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, &reg_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, &reg_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, &reg_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,
+ &reg);
+
+ 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,
+ &reg);
-+
+
+- 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, &reg_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, &reg_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, &reg_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, &reg_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, &reg_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, &reg_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, &reg_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,
+- &reg_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, &reg_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, &reg_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, &reg_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, &reg_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, &reg_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, &reg_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, &reg_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,
+- &reg);
+ 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, &reg_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,
+- &reg);
+-
+- 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,
+- &reg);
+ /* 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,
+- &reg);
+- 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, &reg);
+/**
+ * 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, &reg);
+ /* 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, &reg);
+- 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,
+- &reg);
+- 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,
+- &reg);
+- 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,
+- &reg);
+- 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, &reg_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, &reg_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,
-- &reg_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,
+- &reg_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,
}
/**