Commit 4600cdf9 authored by Piotr Kwapulinski's avatar Piotr Kwapulinski Committed by Tony Nguyen
Browse files

ixgbe: Enable link management in E610 device



Add high level link management support for E610 device. Enable the
following features:
- driver load
- bring up network interface
- IP address assignment
- pass traffic
- show statistics (e.g. via ethtool)
- disable network interface
- driver unload

Co-developed-by: default avatarCarolyn Wyborny <carolyn.wyborny@intel.com>
Signed-off-by: default avatarCarolyn Wyborny <carolyn.wyborny@intel.com>
Co-developed-by: default avatarJedrzej Jagielski <jedrzej.jagielski@intel.com>
Signed-off-by: default avatarJedrzej Jagielski <jedrzej.jagielski@intel.com>
Reviewed-by: default avatarJan Glaza <jan.glaza@intel.com>
Reviewed-by: default avatarSimon Horman <horms@kernel.org>
Tested-by: default avatarBharath R <bharath.r@intel.com>
Signed-off-by: default avatarPiotr Kwapulinski <piotr.kwapulinski@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent 34b41577
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright(c) 1999 - 2018 Intel Corporation. */
/* Copyright(c) 1999 - 2024 Intel Corporation. */

#ifndef _IXGBE_H_
#define _IXGBE_H_
@@ -20,6 +20,7 @@
#include "ixgbe_type.h"
#include "ixgbe_common.h"
#include "ixgbe_dcb.h"
#include "ixgbe_e610.h"
#if IS_ENABLED(CONFIG_FCOE)
#define IXGBE_FCOE
#include "ixgbe_fcoe.h"
@@ -173,6 +174,7 @@ enum ixgbe_tx_flags {
#define VMDQ_P(p)   ((p) + adapter->ring_feature[RING_F_VMDQ].offset)
#define IXGBE_82599_VF_DEVICE_ID        0x10ED
#define IXGBE_X540_VF_DEVICE_ID         0x1515
#define IXGBE_E610_VF_DEVICE_ID		0x57AD

#define UPDATE_VF_COUNTER_32bit(reg, last_counter, counter)	\
	{							\
@@ -654,6 +656,7 @@ struct ixgbe_adapter {
#define IXGBE_FLAG2_RSS_FIELD_IPV6_UDP		BIT(9)
#define IXGBE_FLAG2_PTP_PPS_ENABLED		BIT(10)
#define IXGBE_FLAG2_PHY_INTERRUPT		BIT(11)
#define IXGBE_FLAG2_FW_ASYNC_EVENT		BIT(12)
#define IXGBE_FLAG2_VLAN_PROMISC		BIT(13)
#define IXGBE_FLAG2_EEE_CAPABLE			BIT(14)
#define IXGBE_FLAG2_EEE_ENABLED			BIT(15)
@@ -661,6 +664,9 @@ struct ixgbe_adapter {
#define IXGBE_FLAG2_IPSEC_ENABLED		BIT(17)
#define IXGBE_FLAG2_VF_IPSEC_ENABLED		BIT(18)
#define IXGBE_FLAG2_AUTO_DISABLE_VF		BIT(19)
#define IXGBE_FLAG2_PHY_FW_LOAD_FAILED		BIT(20)
#define IXGBE_FLAG2_NO_MEDIA			BIT(21)
#define IXGBE_FLAG2_MOD_POWER_UNSUPPORTED	BIT(22)

	/* Tx fast path data */
	int num_tx_queues;
@@ -793,6 +799,7 @@ struct ixgbe_adapter {
	u32 vferr_refcount;
	struct ixgbe_mac_addr *mac_table;
	struct kobject *info_kobj;
	u16 lse_mask;
#ifdef CONFIG_IXGBE_HWMON
	struct hwmon_buff *ixgbe_hwmon_buff;
#endif /* CONFIG_IXGBE_HWMON */
@@ -849,6 +856,7 @@ static inline u8 ixgbe_max_rss_indices(struct ixgbe_adapter *adapter)
	case ixgbe_mac_X550:
	case ixgbe_mac_X550EM_x:
	case ixgbe_mac_x550em_a:
	case ixgbe_mac_e610:
		return IXGBE_MAX_RSS_INDICES_X550;
	default:
		return 0;
@@ -874,6 +882,7 @@ enum ixgbe_state_t {
	__IXGBE_PTP_RUNNING,
	__IXGBE_PTP_TX_IN_PROGRESS,
	__IXGBE_RESET_REQUESTED,
	__IXGBE_PHY_INIT_COMPLETE,
};

struct ixgbe_cb {
@@ -896,6 +905,7 @@ enum ixgbe_boards {
	board_x550em_x_fw,
	board_x550em_a,
	board_x550em_a_fw,
	board_e610,
};

extern const struct ixgbe_info ixgbe_82598_info;
@@ -906,6 +916,7 @@ extern const struct ixgbe_info ixgbe_X550EM_x_info;
extern const struct ixgbe_info ixgbe_x550em_x_fw_info;
extern const struct ixgbe_info ixgbe_x550em_a_info;
extern const struct ixgbe_info ixgbe_x550em_a_fw_info;
extern const struct ixgbe_info ixgbe_e610_info;
#ifdef CONFIG_IXGBE_DCB
extern const struct dcbnl_rtnl_ops ixgbe_dcbnl_ops;
#endif
+2 −1
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 1999 - 2018 Intel Corporation. */
/* Copyright(c) 1999 - 2024 Intel Corporation. */

#include <linux/pci.h>
#include <linux/delay.h>
@@ -1615,6 +1615,7 @@ int ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw *hw,
	case ixgbe_mac_X550:
	case ixgbe_mac_X550EM_x:
	case ixgbe_mac_x550em_a:
	case ixgbe_mac_e610:
		IXGBE_WRITE_REG(hw, IXGBE_FDIRSCTPM, ~fdirtcpm);
		break;
	default:
+16 −3
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 1999 - 2018 Intel Corporation. */
/* Copyright(c) 1999 - 2024 Intel Corporation. */

#include <linux/pci.h>
#include <linux/delay.h>
@@ -58,6 +58,7 @@ bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
		switch (hw->device_id) {
		case IXGBE_DEV_ID_X550EM_A_SFP:
		case IXGBE_DEV_ID_X550EM_A_SFP_N:
		case IXGBE_DEV_ID_E610_SFP:
			supported = false;
			break;
		default:
@@ -88,6 +89,8 @@ bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
		case IXGBE_DEV_ID_X550EM_A_10G_T:
		case IXGBE_DEV_ID_X550EM_A_1G_T:
		case IXGBE_DEV_ID_X550EM_A_1G_T_L:
		case IXGBE_DEV_ID_E610_10G_T:
		case IXGBE_DEV_ID_E610_2_5G_T:
			supported = true;
			break;
		default:
@@ -469,9 +472,14 @@ int ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw)
		}
	}

	if (hw->mac.type == ixgbe_mac_X550 || hw->mac.type == ixgbe_mac_X540) {
	if (hw->mac.type == ixgbe_mac_X550 ||
	    hw->mac.type == ixgbe_mac_X540 ||
	    hw->mac.type == ixgbe_mac_e610) {
		if (hw->phy.id == 0)
			hw->phy.ops.identify(hw);
	}

	if (hw->mac.type == ixgbe_mac_X550 || hw->mac.type == ixgbe_mac_X540) {
		hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECL, MDIO_MMD_PCS, &i);
		hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECH, MDIO_MMD_PCS, &i);
		hw->phy.ops.read_reg(hw, IXGBE_LDPCECL, MDIO_MMD_PCS, &i);
@@ -2922,6 +2930,10 @@ u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw)
		pcie_offset = IXGBE_PCIE_MSIX_82599_CAPS;
		max_msix_count = IXGBE_MAX_MSIX_VECTORS_82599;
		break;
	case ixgbe_mac_e610:
		pcie_offset = IXGBE_PCIE_MSIX_E610_CAPS;
		max_msix_count = IXGBE_MAX_MSIX_VECTORS_82599;
		break;
	default:
		return 1;
	}
@@ -3370,7 +3382,8 @@ int ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
		*speed = IXGBE_LINK_SPEED_1GB_FULL;
		break;
	case IXGBE_LINKS_SPEED_100_82599:
		if ((hw->mac.type >= ixgbe_mac_X550) &&
		if ((hw->mac.type >= ixgbe_mac_X550 ||
		     hw->mac.type == ixgbe_mac_e610) &&
		    (links_reg & IXGBE_LINKS_SPEED_NON_STD))
			*speed = IXGBE_LINK_SPEED_5GB_FULL;
		else
+2 −1
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 1999 - 2018 Intel Corporation. */
/* Copyright(c) 1999 - 2024 Intel Corporation. */

#include "ixgbe.h"
#include <linux/dcbnl.h>
@@ -154,6 +154,7 @@ static void ixgbe_dcbnl_get_perm_hw_addr(struct net_device *netdev,
	case ixgbe_mac_82599EB:
	case ixgbe_mac_X540:
	case ixgbe_mac_X550:
	case ixgbe_mac_e610:
		for (j = 0; j < netdev->addr_len; j++, i++)
			perm_addr[i] = adapter->hw.mac.san_addr[j];
		break;
+165 −0
Original line number Diff line number Diff line
@@ -3,8 +3,10 @@

#include "ixgbe_common.h"
#include "ixgbe_e610.h"
#include "ixgbe_x550.h"
#include "ixgbe_type.h"
#include "ixgbe_x540.h"
#include "ixgbe_mbx.h"
#include "ixgbe_phy.h"

/**
@@ -2491,3 +2493,166 @@ int ixgbe_validate_eeprom_checksum_e610(struct ixgbe_hw *hw, u16 *checksum_val)

	return err;
}

/**
 * ixgbe_reset_hw_e610 - Perform hardware reset
 * @hw: pointer to hardware structure
 *
 * Resets the hardware by resetting the transmit and receive units, masks
 * and clears all interrupts, and performs a reset.
 *
 * Return: the exit code of the operation.
 */
int ixgbe_reset_hw_e610(struct ixgbe_hw *hw)
{
	u32 swfw_mask = hw->phy.phy_semaphore_mask;
	u32 ctrl, i;
	int err;

	/* Call adapter stop to disable tx/rx and clear interrupts */
	err = hw->mac.ops.stop_adapter(hw);
	if (err)
		goto reset_hw_out;

	/* Flush pending Tx transactions. */
	ixgbe_clear_tx_pending(hw);

	hw->phy.ops.init(hw);
mac_reset_top:
	err = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
	if (err)
		return -EBUSY;
	ctrl = IXGBE_CTRL_RST;
	ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL);
	IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
	IXGBE_WRITE_FLUSH(hw);
	hw->mac.ops.release_swfw_sync(hw, swfw_mask);

	/* Poll for reset bit to self-clear indicating reset is complete */
	for (i = 0; i < 10; i++) {
		udelay(1);
		ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
		if (!(ctrl & IXGBE_CTRL_RST_MASK))
			break;
	}

	if (ctrl & IXGBE_CTRL_RST_MASK) {
		struct ixgbe_adapter *adapter = container_of(hw, struct ixgbe_adapter,
							     hw);

		err = -EIO;
		netdev_err(adapter->netdev, "Reset polling failed to complete.");
	}

	/* Double resets are required for recovery from certain error
	 * conditions. Between resets, it is necessary to stall to allow time
	 * for any pending HW events to complete.
	 */
	msleep(100);
	if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
		hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
		goto mac_reset_top;
	}

	/* Set the Rx packet buffer size. */
	IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0), GENMASK(18, 17));

	/* Store the permanent mac address */
	hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);

	/* Maximum number of Receive Address Registers. */
#define IXGBE_MAX_NUM_RAR		128

	/* Store MAC address from RAR0, clear receive address registers, and
	 * clear the multicast table.  Also reset num_rar_entries to the
	 * maximum number of Receive Address Registers, since we modify this
	 * value when programming the SAN MAC address.
	 */
	hw->mac.num_rar_entries = IXGBE_MAX_NUM_RAR;
	hw->mac.ops.init_rx_addrs(hw);

	/* Initialize bus function number */
	hw->mac.ops.set_lan_id(hw);

reset_hw_out:
	return err;
}

static const struct ixgbe_mac_operations mac_ops_e610 = {
	.init_hw			= ixgbe_init_hw_generic,
	.start_hw			= ixgbe_start_hw_X540,
	.clear_hw_cntrs			= ixgbe_clear_hw_cntrs_generic,
	.enable_rx_dma			= ixgbe_enable_rx_dma_generic,
	.get_mac_addr			= ixgbe_get_mac_addr_generic,
	.get_device_caps		= ixgbe_get_device_caps_generic,
	.stop_adapter			= ixgbe_stop_adapter_generic,
	.set_lan_id			= ixgbe_set_lan_id_multi_port_pcie,
	.set_rxpba			= ixgbe_set_rxpba_generic,
	.check_link			= ixgbe_check_link_e610,
	.blink_led_start		= ixgbe_blink_led_start_X540,
	.blink_led_stop			= ixgbe_blink_led_stop_X540,
	.set_rar			= ixgbe_set_rar_generic,
	.clear_rar			= ixgbe_clear_rar_generic,
	.set_vmdq			= ixgbe_set_vmdq_generic,
	.set_vmdq_san_mac		= ixgbe_set_vmdq_san_mac_generic,
	.clear_vmdq			= ixgbe_clear_vmdq_generic,
	.init_rx_addrs			= ixgbe_init_rx_addrs_generic,
	.update_mc_addr_list		= ixgbe_update_mc_addr_list_generic,
	.enable_mc			= ixgbe_enable_mc_generic,
	.disable_mc			= ixgbe_disable_mc_generic,
	.clear_vfta			= ixgbe_clear_vfta_generic,
	.set_vfta			= ixgbe_set_vfta_generic,
	.fc_enable			= ixgbe_fc_enable_generic,
	.set_fw_drv_ver			= ixgbe_set_fw_drv_ver_x550,
	.init_uta_tables		= ixgbe_init_uta_tables_generic,
	.set_mac_anti_spoofing		= ixgbe_set_mac_anti_spoofing,
	.set_vlan_anti_spoofing		= ixgbe_set_vlan_anti_spoofing,
	.set_source_address_pruning	=
				ixgbe_set_source_address_pruning_x550,
	.set_ethertype_anti_spoofing	=
				ixgbe_set_ethertype_anti_spoofing_x550,
	.disable_rx_buff		= ixgbe_disable_rx_buff_generic,
	.enable_rx_buff			= ixgbe_enable_rx_buff_generic,
	.enable_rx			= ixgbe_enable_rx_generic,
	.disable_rx			= ixgbe_disable_rx_e610,
	.led_on				= ixgbe_led_on_generic,
	.led_off			= ixgbe_led_off_generic,
	.init_led_link_act		= ixgbe_init_led_link_act_generic,
	.reset_hw			= ixgbe_reset_hw_e610,
	.get_media_type			= ixgbe_get_media_type_e610,
	.setup_link			= ixgbe_setup_link_e610,
	.get_link_capabilities		= ixgbe_get_link_capabilities_e610,
	.get_bus_info			= ixgbe_get_bus_info_generic,
	.acquire_swfw_sync		= ixgbe_acquire_swfw_sync_X540,
	.release_swfw_sync		= ixgbe_release_swfw_sync_X540,
	.init_swfw_sync			= ixgbe_init_swfw_sync_X540,
	.prot_autoc_read		= prot_autoc_read_generic,
	.prot_autoc_write		= prot_autoc_write_generic,
	.setup_fc			= ixgbe_setup_fc_e610,
	.fc_autoneg			= ixgbe_fc_autoneg_e610,
};

static const struct ixgbe_phy_operations phy_ops_e610 = {
	.init				= ixgbe_init_phy_ops_e610,
	.identify			= ixgbe_identify_phy_e610,
	.identify_sfp			= ixgbe_identify_module_e610,
	.setup_link_speed		= ixgbe_setup_phy_link_speed_generic,
	.setup_link			= ixgbe_setup_phy_link_e610,
	.enter_lplu			= ixgbe_enter_lplu_e610,
};

static const struct ixgbe_eeprom_operations eeprom_ops_e610 = {
	.read				= ixgbe_read_ee_aci_e610,
	.read_buffer			= ixgbe_read_ee_aci_buffer_e610,
	.validate_checksum		= ixgbe_validate_eeprom_checksum_e610,
};

const struct ixgbe_info ixgbe_e610_info = {
	.mac			= ixgbe_mac_e610,
	.get_invariants		= ixgbe_get_invariants_X540,
	.mac_ops		= &mac_ops_e610,
	.eeprom_ops		= &eeprom_ops_e610,
	.phy_ops		= &phy_ops_e610,
	.mbx_ops		= &mbx_ops_generic,
	.mvals			= ixgbe_mvals_x550em_a,
};
Loading