aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/intel
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/intel')
-rw-r--r--drivers/net/ethernet/intel/e100.c2
-rw-r--r--drivers/net/ethernet/intel/ice/ice.h5
-rw-r--r--drivers/net/ethernet/intel/ice/ice_adapter.c22
-rw-r--r--drivers/net/ethernet/intel/ice/ice_adapter.h22
-rw-r--r--drivers/net/ethernet/intel/ice/ice_adminq_cmd.h9
-rw-r--r--drivers/net/ethernet/intel/ice/ice_fw_update.c2
-rw-r--r--drivers/net/ethernet/intel/ice/ice_gnss.c4
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ptp.c1455
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ptp.h143
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ptp_consts.h2
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ptp_hw.c125
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ptp_hw.h77
-rw-r--r--drivers/net/ethernet/intel/ice/ice_repr.c8
-rw-r--r--drivers/net/ethernet/intel/ice/ice_sf_eth.c4
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_txrx.h3
15 files changed, 920 insertions, 963 deletions
diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c
index aa139b67a55b..3a5bbda235cb 100644
--- a/drivers/net/ethernet/intel/e100.c
+++ b/drivers/net/ethernet/intel/e100.c
@@ -146,7 +146,7 @@
#include <linux/string.h>
#include <linux/firmware.h>
#include <linux/rtnetlink.h>
-#include <asm/unaligned.h>
+#include <linux/unaligned.h>
#define DRV_NAME "e100"
diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h
index d6f80da30dec..558cda577191 100644
--- a/drivers/net/ethernet/intel/ice/ice.h
+++ b/drivers/net/ethernet/intel/ice/ice.h
@@ -1047,5 +1047,10 @@ static inline void ice_clear_rdma_cap(struct ice_pf *pf)
clear_bit(ICE_FLAG_RDMA_ENA, pf->flags);
}
+static inline enum ice_phy_model ice_get_phy_model(const struct ice_hw *hw)
+{
+ return hw->ptp.phy_model;
+}
+
extern const struct xdp_metadata_ops ice_xdp_md_ops;
#endif /* _ICE_H_ */
diff --git a/drivers/net/ethernet/intel/ice/ice_adapter.c b/drivers/net/ethernet/intel/ice/ice_adapter.c
index ad84d8ad49a6..01a08cfd0090 100644
--- a/drivers/net/ethernet/intel/ice/ice_adapter.c
+++ b/drivers/net/ethernet/intel/ice/ice_adapter.c
@@ -9,12 +9,14 @@
#include <linux/spinlock.h>
#include <linux/xarray.h>
#include "ice_adapter.h"
+#include "ice.h"
static DEFINE_XARRAY(ice_adapters);
static DEFINE_MUTEX(ice_adapters_mutex);
/* PCI bus number is 8 bits. Slot is 5 bits. Domain can have the rest. */
#define INDEX_FIELD_DOMAIN GENMASK(BITS_PER_LONG - 1, 13)
+#define INDEX_FIELD_DEV GENMASK(31, 16)
#define INDEX_FIELD_BUS GENMASK(12, 5)
#define INDEX_FIELD_SLOT GENMASK(4, 0)
@@ -24,9 +26,17 @@ static unsigned long ice_adapter_index(const struct pci_dev *pdev)
WARN_ON(domain > FIELD_MAX(INDEX_FIELD_DOMAIN));
- return FIELD_PREP(INDEX_FIELD_DOMAIN, domain) |
- FIELD_PREP(INDEX_FIELD_BUS, pdev->bus->number) |
- FIELD_PREP(INDEX_FIELD_SLOT, PCI_SLOT(pdev->devfn));
+ switch (pdev->device) {
+ case ICE_DEV_ID_E825C_BACKPLANE:
+ case ICE_DEV_ID_E825C_QSFP:
+ case ICE_DEV_ID_E825C_SFP:
+ case ICE_DEV_ID_E825C_SGMII:
+ return FIELD_PREP(INDEX_FIELD_DEV, pdev->device);
+ default:
+ return FIELD_PREP(INDEX_FIELD_DOMAIN, domain) |
+ FIELD_PREP(INDEX_FIELD_BUS, pdev->bus->number) |
+ FIELD_PREP(INDEX_FIELD_SLOT, PCI_SLOT(pdev->devfn));
+ }
}
static struct ice_adapter *ice_adapter_new(void)
@@ -40,11 +50,17 @@ static struct ice_adapter *ice_adapter_new(void)
spin_lock_init(&adapter->ptp_gltsyn_time_lock);
refcount_set(&adapter->refcount, 1);
+ mutex_init(&adapter->ports.lock);
+ INIT_LIST_HEAD(&adapter->ports.ports);
+
return adapter;
}
static void ice_adapter_free(struct ice_adapter *adapter)
{
+ WARN_ON(!list_empty(&adapter->ports.ports));
+ mutex_destroy(&adapter->ports.lock);
+
kfree(adapter);
}
diff --git a/drivers/net/ethernet/intel/ice/ice_adapter.h b/drivers/net/ethernet/intel/ice/ice_adapter.h
index 9d11014ec02f..e233225848b3 100644
--- a/drivers/net/ethernet/intel/ice/ice_adapter.h
+++ b/drivers/net/ethernet/intel/ice/ice_adapter.h
@@ -4,22 +4,42 @@
#ifndef _ICE_ADAPTER_H_
#define _ICE_ADAPTER_H_
+#include <linux/types.h>
#include <linux/spinlock_types.h>
#include <linux/refcount_types.h>
struct pci_dev;
+struct ice_pf;
+
+/**
+ * struct ice_port_list - data used to store the list of adapter ports
+ *
+ * This structure contains data used to maintain a list of adapter ports
+ *
+ * @ports: list of ports
+ * @lock: protect access to the ports list
+ */
+struct ice_port_list {
+ struct list_head ports;
+ /* To synchronize the ports list operations */
+ struct mutex lock;
+};
/**
* struct ice_adapter - PCI adapter resources shared across PFs
* @ptp_gltsyn_time_lock: Spinlock protecting access to the GLTSYN_TIME
* register of the PTP clock.
* @refcount: Reference count. struct ice_pf objects hold the references.
+ * @ctrl_pf: Control PF of the adapter
+ * @ports: Ports list
*/
struct ice_adapter {
+ refcount_t refcount;
/* For access to the GLTSYN_TIME register */
spinlock_t ptp_gltsyn_time_lock;
- refcount_t refcount;
+ struct ice_pf *ctrl_pf;
+ struct ice_port_list ports;
};
struct ice_adapter *ice_adapter_get(const struct pci_dev *pdev);
diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
index 0be1a98d7cc1..1f01f3501d6b 100644
--- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
+++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
@@ -1742,6 +1742,15 @@ struct ice_aqc_nvm {
};
#define ICE_AQC_NVM_START_POINT 0
+#define ICE_AQC_NVM_SECTOR_UNIT 4096
+#define ICE_AQC_NVM_SDP_AC_PTR_OFFSET 0xD8
+#define ICE_AQC_NVM_SDP_AC_PTR_M GENMASK(14, 0)
+#define ICE_AQC_NVM_SDP_AC_PTR_INVAL 0x7FFF
+#define ICE_AQC_NVM_SDP_AC_PTR_TYPE_M BIT(15)
+#define ICE_AQC_NVM_SDP_AC_SDP_NUM_M GENMASK(2, 0)
+#define ICE_AQC_NVM_SDP_AC_DIR_M BIT(3)
+#define ICE_AQC_NVM_SDP_AC_PIN_M GENMASK(15, 6)
+#define ICE_AQC_NVM_SDP_AC_MAX_SIZE 7
#define ICE_AQC_NVM_TX_TOPO_MOD_ID 0x14B
diff --git a/drivers/net/ethernet/intel/ice/ice_fw_update.c b/drivers/net/ethernet/intel/ice/ice_fw_update.c
index f81db6c107c8..2702a0da5c3e 100644
--- a/drivers/net/ethernet/intel/ice/ice_fw_update.c
+++ b/drivers/net/ethernet/intel/ice/ice_fw_update.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) 2018-2019, Intel Corporation. */
-#include <asm/unaligned.h>
+#include <linux/unaligned.h>
#include <linux/uuid.h>
#include <linux/crc32.h>
#include <linux/pldmfw.h>
diff --git a/drivers/net/ethernet/intel/ice/ice_gnss.c b/drivers/net/ethernet/intel/ice/ice_gnss.c
index c8ea1af51ad3..f02e8ca55375 100644
--- a/drivers/net/ethernet/intel/ice/ice_gnss.c
+++ b/drivers/net/ethernet/intel/ice/ice_gnss.c
@@ -397,8 +397,8 @@ bool ice_gnss_is_gps_present(struct ice_hw *hw)
int err;
u8 data;
- err = ice_read_pca9575_reg_e810t(hw, ICE_PCA9575_P0_IN, &data);
- if (err || !!(data & ICE_E810T_P0_GNSS_PRSNT_N))
+ err = ice_read_pca9575_reg(hw, ICE_PCA9575_P0_IN, &data);
+ if (err || !!(data & ICE_P0_GNSS_PRSNT_N))
return false;
} else {
return false;
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c
index ef2e858f49bb..74de7d8b17ac 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
@@ -4,253 +4,187 @@
#include "ice.h"
#include "ice_lib.h"
#include "ice_trace.h"
+#include "ice_cgu_regs.h"
+
+static const char ice_pin_names[][64] = {
+ "SDP0",
+ "SDP1",
+ "SDP2",
+ "SDP3",
+ "TIME_SYNC",
+ "1PPS"
+};
-#define E810_OUT_PROP_DELAY_NS 1
+static const struct ice_ptp_pin_desc ice_pin_desc_e82x[] = {
+ /* name, gpio */
+ { TIME_SYNC, { 4, -1 }},
+ { ONE_PPS, { -1, 5 }},
+};
-static const struct ptp_pin_desc ice_pin_desc_e810t[] = {
- /* name idx func chan */
- { "GNSS", GNSS, PTP_PF_EXTTS, 0, { 0, } },
- { "SMA1", SMA1, PTP_PF_NONE, 1, { 0, } },
- { "U.FL1", UFL1, PTP_PF_NONE, 1, { 0, } },
- { "SMA2", SMA2, PTP_PF_NONE, 2, { 0, } },
- { "U.FL2", UFL2, PTP_PF_NONE, 2, { 0, } },
+static const struct ice_ptp_pin_desc ice_pin_desc_e825c[] = {
+ /* name, gpio */
+ { SDP0, { 0, 0 }},
+ { SDP1, { 1, 1 }},
+ { SDP2, { 2, 2 }},
+ { SDP3, { 3, 3 }},
+ { TIME_SYNC, { 4, -1 }},
+ { ONE_PPS, { -1, 5 }},
};
-/**
- * ice_get_sma_config_e810t
- * @hw: pointer to the hw struct
- * @ptp_pins: pointer to the ptp_pin_desc struture
- *
- * Read the configuration of the SMA control logic and put it into the
- * ptp_pin_desc structure
- */
-static int
-ice_get_sma_config_e810t(struct ice_hw *hw, struct ptp_pin_desc *ptp_pins)
-{
- u8 data, i;
- int status;
+static const struct ice_ptp_pin_desc ice_pin_desc_e810[] = {
+ /* name, gpio */
+ { SDP0, { 0, 0 }},
+ { SDP1, { 1, 1 }},
+ { SDP2, { 2, 2 }},
+ { SDP3, { 3, 3 }},
+ { ONE_PPS, { -1, 5 }},
+};
- /* Read initial pin state */
- status = ice_read_sma_ctrl_e810t(hw, &data);
- if (status)
- return status;
+static const char ice_pin_names_nvm[][64] = {
+ "GNSS",
+ "SMA1",
+ "U.FL1",
+ "SMA2",
+ "U.FL2",
+};
- /* initialize with defaults */
- for (i = 0; i < NUM_PTP_PINS_E810T; i++) {
- strscpy(ptp_pins[i].name, ice_pin_desc_e810t[i].name,
- sizeof(ptp_pins[i].name));
- ptp_pins[i].index = ice_pin_desc_e810t[i].index;
- ptp_pins[i].func = ice_pin_desc_e810t[i].func;
- ptp_pins[i].chan = ice_pin_desc_e810t[i].chan;
- }
+static const struct ice_ptp_pin_desc ice_pin_desc_e810_sma[] = {
+ /* name, gpio */
+ { GNSS, { 1, -1 }},
+ { SMA1, { 1, 0 }},
+ { UFL1, { -1, 0 }},
+ { SMA2, { 3, 2 }},
+ { UFL2, { 3, -1 }},
+};
- /* Parse SMA1/UFL1 */
- switch (data & ICE_SMA1_MASK_E810T) {
- case ICE_SMA1_MASK_E810T:
- default:
- ptp_pins[SMA1].func = PTP_PF_NONE;
- ptp_pins[UFL1].func = PTP_PF_NONE;
- break;
- case ICE_SMA1_DIR_EN_E810T:
- ptp_pins[SMA1].func = PTP_PF_PEROUT;
- ptp_pins[UFL1].func = PTP_PF_NONE;
- break;
- case ICE_SMA1_TX_EN_E810T:
- ptp_pins[SMA1].func = PTP_PF_EXTTS;
- ptp_pins[UFL1].func = PTP_PF_NONE;
- break;
- case 0:
- ptp_pins[SMA1].func = PTP_PF_EXTTS;
- ptp_pins[UFL1].func = PTP_PF_PEROUT;
- break;
- }
+static struct ice_pf *ice_get_ctrl_pf(struct ice_pf *pf)
+{
+ return !pf->adapter ? NULL : pf->adapter->ctrl_pf;
+}
- /* Parse SMA2/UFL2 */
- switch (data & ICE_SMA2_MASK_E810T) {
- case ICE_SMA2_MASK_E810T:
- default:
- ptp_pins[SMA2].func = PTP_PF_NONE;
- ptp_pins[UFL2].func = PTP_PF_NONE;
- break;
- case (ICE_SMA2_TX_EN_E810T | ICE_SMA2_UFL2_RX_DIS_E810T):
- ptp_pins[SMA2].func = PTP_PF_EXTTS;
- ptp_pins[UFL2].func = PTP_PF_NONE;
- break;
- case (ICE_SMA2_DIR_EN_E810T | ICE_SMA2_UFL2_RX_DIS_E810T):
- ptp_pins[SMA2].func = PTP_PF_PEROUT;
- ptp_pins[UFL2].func = PTP_PF_NONE;
- break;
- case (ICE_SMA2_DIR_EN_E810T | ICE_SMA2_TX_EN_E810T):
- ptp_pins[SMA2].func = PTP_PF_NONE;
- ptp_pins[UFL2].func = PTP_PF_EXTTS;
- break;
- case ICE_SMA2_DIR_EN_E810T:
- ptp_pins[SMA2].func = PTP_PF_PEROUT;
- ptp_pins[UFL2].func = PTP_PF_EXTTS;
- break;
- }
+static struct ice_ptp *ice_get_ctrl_ptp(struct ice_pf *pf)
+{
+ struct ice_pf *ctrl_pf = ice_get_ctrl_pf(pf);
- return 0;
+ return !ctrl_pf ? NULL : &ctrl_pf->ptp;
}
/**
- * ice_ptp_set_sma_config_e810t
- * @hw: pointer to the hw struct
- * @ptp_pins: pointer to the ptp_pin_desc struture
+ * ice_ptp_find_pin_idx - Find pin index in ptp_pin_desc
+ * @pf: Board private structure
+ * @func: Pin function
+ * @chan: GPIO channel
*
- * Set the configuration of the SMA control logic based on the configuration in
- * num_pins parameter
+ * Return: positive pin number when pin is present, -1 otherwise
*/
-static int
-ice_ptp_set_sma_config_e810t(struct ice_hw *hw,
- const struct ptp_pin_desc *ptp_pins)
+static int ice_ptp_find_pin_idx(struct ice_pf *pf, enum ptp_pin_function func,
+ unsigned int chan)
{
- int status;
- u8 data;
+ const struct ptp_clock_info *info = &pf->ptp.info;
+ int i;
- /* SMA1 and UFL1 cannot be set to TX at the same time */
- if (ptp_pins[SMA1].func == PTP_PF_PEROUT &&
- ptp_pins[UFL1].func == PTP_PF_PEROUT)
- return -EINVAL;
+ for (i = 0; i < info->n_pins; i++) {
+ if (info->pin_config[i].func == func &&
+ info->pin_config[i].chan == chan)
+ return i;
+ }
- /* SMA2 and UFL2 cannot be set to RX at the same time */
- if (ptp_pins[SMA2].func == PTP_PF_EXTTS &&
- ptp_pins[UFL2].func == PTP_PF_EXTTS)
- return -EINVAL;
+ return -1;
+}
- /* Read initial pin state value */
- status = ice_read_sma_ctrl_e810t(hw, &data);
- if (status)
- return status;
-
- /* Set the right sate based on the desired configuration */
- data &= ~ICE_SMA1_MASK_E810T;
- if (ptp_pins[SMA1].func == PTP_PF_NONE &&
- ptp_pins[UFL1].func == PTP_PF_NONE) {
- dev_info(ice_hw_to_dev(hw), "SMA1 + U.FL1 disabled");
- data |= ICE_SMA1_MASK_E810T;
- } else if (ptp_pins[SMA1].func == PTP_PF_EXTTS &&
- ptp_pins[UFL1].func == PTP_PF_NONE) {
- dev_info(ice_hw_to_dev(hw), "SMA1 RX");
- data |= ICE_SMA1_TX_EN_E810T;
- } else if (ptp_pins[SMA1].func == PTP_PF_NONE &&
- ptp_pins[UFL1].func == PTP_PF_PEROUT) {
- /* U.FL 1 TX will always enable SMA 1 RX */
- dev_info(ice_hw_to_dev(hw), "SMA1 RX + U.FL1 TX");
- } else if (ptp_pins[SMA1].func == PTP_PF_EXTTS &&
- ptp_pins[UFL1].func == PTP_PF_PEROUT) {
- dev_info(ice_hw_to_dev(hw), "SMA1 RX + U.FL1 TX");
- } else if (ptp_pins[SMA1].func == PTP_PF_PEROUT &&
- ptp_pins[UFL1].func == PTP_PF_NONE) {
- dev_info(ice_hw_to_dev(hw), "SMA1 TX");
- data |= ICE_SMA1_DIR_EN_E810T;
- }
-
- data &= ~ICE_SMA2_MASK_E810T;
- if (ptp_pins[SMA2].func == PTP_PF_NONE &&
- ptp_pins[UFL2].func == PTP_PF_NONE) {
- dev_info(ice_hw_to_dev(hw), "SMA2 + U.FL2 disabled");
- data |= ICE_SMA2_MASK_E810T;
- } else if (ptp_pins[SMA2].func == PTP_PF_EXTTS &&
- ptp_pins[UFL2].func == PTP_PF_NONE) {
- dev_info(ice_hw_to_dev(hw), "SMA2 RX");
- data |= (ICE_SMA2_TX_EN_E810T |
- ICE_SMA2_UFL2_RX_DIS_E810T);
- } else if (ptp_pins[SMA2].func == PTP_PF_NONE &&
- ptp_pins[UFL2].func == PTP_PF_EXTTS) {
- dev_info(ice_hw_to_dev(hw), "UFL2 RX");
- data |= (ICE_SMA2_DIR_EN_E810T | ICE_SMA2_TX_EN_E810T);
- } else if (ptp_pins[SMA2].func == PTP_PF_PEROUT &&
- ptp_pins[UFL2].func == PTP_PF_NONE) {
- dev_info(ice_hw_to_dev(hw), "SMA2 TX");
- data |= (ICE_SMA2_DIR_EN_E810T |
- ICE_SMA2_UFL2_RX_DIS_E810T);
- } else if (ptp_pins[SMA2].func == PTP_PF_PEROUT &&
- ptp_pins[UFL2].func == PTP_PF_EXTTS) {
- dev_info(ice_hw_to_dev(hw), "SMA2 TX + U.FL2 RX");
- data |= ICE_SMA2_DIR_EN_E810T;
- }
-
- return ice_write_sma_ctrl_e810t(hw, data);
-}
-
-/**
- * ice_ptp_set_sma_e810t
- * @info: the driver's PTP info structure
- * @pin: pin index in kernel structure
- * @func: Pin function to be set (PTP_PF_NONE, PTP_PF_EXTTS or PTP_PF_PEROUT)
- *
- * Set the configuration of a single SMA pin
+/**
+ * ice_ptp_update_sma_data - update SMA pins data according to pins setup
+ * @pf: Board private structure
+ * @sma_pins: parsed SMA pins status
+ * @data: SMA data to update
*/
-static int
-ice_ptp_set_sma_e810t(struct ptp_clock_info *info, unsigned int pin,
- enum ptp_pin_function func)
+static void ice_ptp_update_sma_data(struct ice_pf *pf, unsigned int sma_pins[],
+ u8 *data)
{
- struct ptp_pin_desc ptp_pins[NUM_PTP_PINS_E810T];
- struct ice_pf *pf = ptp_info_to_pf(info);
- struct ice_hw *hw = &pf->hw;
- int err;
-
- if (pin < SMA1 || func > PTP_PF_PEROUT)
- return -EOPNOTSUPP;
-
- err = ice_get_sma_config_e810t(hw, ptp_pins);
- if (err)
- return err;
-
- /* Disable the same function on the other pin sharing the channel */
- if (pin == SMA1 && ptp_pins[UFL1].func == func)
- ptp_pins[UFL1].func = PTP_PF_NONE;
- if (pin == UFL1 && ptp_pins[SMA1].func == func)
- ptp_pins[SMA1].func = PTP_PF_NONE;
+ const char *state1, *state2;
- if (pin == SMA2 && ptp_pins[UFL2].func == func)
- ptp_pins[UFL2].func = PTP_PF_NONE;
- if (pin == UFL2 && ptp_pins[SMA2].func == func)
- ptp_pins[SMA2].func = PTP_PF_NONE;
+ /* Set the right state based on the desired configuration.
+ * When bit is set, functionality is disabled.
+ */
+ *data &= ~ICE_ALL_SMA_MASK;
+ if (!sma_pins[UFL1 - 1]) {
+ if (sma_pins[SMA1 - 1] == PTP_PF_EXTTS) {
+ state1 = "SMA1 Rx, U.FL1 disabled";
+ *data |= ICE_SMA1_TX_EN;
+ } else if (sma_pins[SMA1 - 1] == PTP_PF_PEROUT) {
+ state1 = "SMA1 Tx U.FL1 disabled";
+ *data |= ICE_SMA1_DIR_EN;
+ } else {
+ state1 = "SMA1 disabled, U.FL1 disabled";
+ *data |= ICE_SMA1_MASK;
+ }
+ } else {
+ /* U.FL1 Tx will always enable SMA1 Rx */
+ state1 = "SMA1 Rx, U.FL1 Tx";
+ }
- /* Set up new pin function in the temp table */
- ptp_pins[pin].func = func;
+ if (!sma_pins[UFL2 - 1]) {
+ if (sma_pins[SMA2 - 1] == PTP_PF_EXTTS) {
+ state2 = "SMA2 Rx, U.FL2 disabled";
+ *data |= ICE_SMA2_TX_EN | ICE_SMA2_UFL2_RX_DIS;
+ } else if (sma_pins[SMA2 - 1] == PTP_PF_PEROUT) {
+ state2 = "SMA2 Tx, U.FL2 disabled";
+ *data |= ICE_SMA2_DIR_EN | ICE_SMA2_UFL2_RX_DIS;
+ } else {
+ state2 = "SMA2 disabled, U.FL2 disabled";
+ *data |= ICE_SMA2_MASK;
+ }
+ } else {
+ if (!sma_pins[SMA2 - 1]) {
+ state2 = "SMA2 disabled, U.FL2 Rx";
+ *data |= ICE_SMA2_DIR_EN | ICE_SMA2_TX_EN;
+ } else {
+ state2 = "SMA2 Tx, U.FL2 Rx";
+ *data |= ICE_SMA2_DIR_EN;
+ }
+ }
- return ice_ptp_set_sma_config_e810t(hw, ptp_pins);
+ dev_dbg(ice_pf_to_dev(pf), "%s, %s\n", state1, state2);
}
/**
- * ice_verify_pin_e810t
- * @info: the driver's PTP info structure
- * @pin: Pin index
- * @func: Assigned function
- * @chan: Assigned channel
+ * ice_ptp_set_sma_cfg - set the configuration of the SMA control logic
+ * @pf: Board private structure
*
- * Verify if pin supports requested pin function. If the Check pins consistency.
- * Reconfigure the SMA logic attached to the given pin to enable its
- * desired functionality
+ * Return: 0 on success, negative error code otherwise
*/
-static int
-ice_verify_pin_e810t(struct ptp_clock_info *info, unsigned int pin,
- enum ptp_pin_function func, unsigned int chan)
+static int ice_ptp_set_sma_cfg(struct ice_pf *pf)
{
- /* Don't allow channel reassignment */
- if (chan != ice_pin_desc_e810t[pin].chan)
- return -EOPNOTSUPP;
+ const struct ice_ptp_pin_desc *ice_pins = pf->ptp.ice_pin_desc;
+ struct ptp_pin_desc *pins = pf->ptp.pin_desc;
+ unsigned int sma_pins[ICE_SMA_PINS_NUM] = {};
+ int err;
+ u8 data;
- /* Check if functions are properly assigned */
- switch (func) {
- case PTP_PF_NONE:
- break;
- case PTP_PF_EXTTS:
- if (pin == UFL1)
- return -EOPNOTSUPP;
- break;
- case PTP_PF_PEROUT:
- if (pin == UFL2 || pin == GNSS)
- return -EOPNOTSUPP;
- break;
- case PTP_PF_PHYSYNC:
- return -EOPNOTSUPP;
- }
+ /* Read initial pin state value */
+ err = ice_read_sma_ctrl(&pf->hw, &data);
+ if (err)
+ return err;
- return ice_ptp_set_sma_e810t(info, pin, func);
+ /* Get SMA/U.FL pins states */
+ for (int i = 0; i < pf->ptp.info.n_pins; i++)
+ if (pins[i].func) {
+ int name_idx = ice_pins[i].name_idx;
+
+ switch (name_idx) {
+ case SMA1:
+ case UFL1:
+ case SMA2:
+ case UFL2:
+ sma_pins[name_idx - 1] = pins[i].func;
+ break;
+ default:
+ continue;
+ }
+ }
+
+ ice_ptp_update_sma_data(pf, sma_pins, &data);
+ return ice_write_sma_ctrl(&pf->hw, data);
}
/**
@@ -800,8 +734,8 @@ static enum ice_tx_tstamp_work ice_ptp_tx_tstamp_owner(struct ice_pf *pf)
struct ice_ptp_port *port;
unsigned int i;
- mutex_lock(&pf->ptp.ports_owner.lock);
- list_for_each_entry(port, &pf->ptp.ports_owner.ports, list_member) {
+ mutex_lock(&pf->adapter->ports.lock);
+ list_for_each_entry(port, &pf->adapter->ports.ports, list_node) {
struct ice_ptp_tx *tx = &port->tx;
if (!tx || !tx->init)
@@ -809,7 +743,7 @@ static enum ice_tx_tstamp_work ice_ptp_tx_tstamp_owner(struct ice_pf *pf)
ice_ptp_process_tx_tstamp(tx);
}
- mutex_unlock(&pf->ptp.ports_owner.lock);
+ mutex_unlock(&pf->adapter->ports.lock);
for (i = 0; i < ICE_GET_QUAD_NUM(pf->hw.ptp.num_lports); i++) {
u64 tstamp_ready;
@@ -974,7 +908,7 @@ ice_ptp_flush_all_tx_tracker(struct ice_pf *pf)
{
struct ice_ptp_port *port;
- list_for_each_entry(port, &pf->ptp.ports_owner.ports, list_member)
+ list_for_each_entry(port, &pf->adapter->ports.ports, list_node)
ice_ptp_flush_tx_tracker(ptp_port_to_pf(port), &port->tx);
}
@@ -1363,7 +1297,7 @@ ice_ptp_port_phy_stop(struct ice_ptp_port *ptp_port)
mutex_lock(&ptp_port->ps_lock);
- switch (hw->ptp.phy_model) {
+ switch (ice_get_phy_model(hw)) {
case ICE_PHY_ETH56G:
err = ice_stop_phy_timer_eth56g(hw, port, true);
break;
@@ -1409,7 +1343,7 @@ ice_ptp_port_phy_restart(struct ice_ptp_port *ptp_port)
mutex_lock(&ptp_port->ps_lock);
- switch (hw->ptp.phy_model) {
+ switch (ice_get_phy_model(hw)) {
case ICE_PHY_ETH56G:
err = ice_start_phy_timer_eth56g(hw, port);
break;
@@ -1480,8 +1414,7 @@ void ice_ptp_link_change(struct ice_pf *pf, u8 port, bool linkup)
/* Skip HW writes if reset is in progress */
if (pf->hw.reset_ongoing)
return;
-
- switch (hw->ptp.phy_model) {
+ switch (ice_get_phy_model(hw)) {
case ICE_PHY_E810:
/* Do not reconfigure E810 PHY */
return;
@@ -1514,7 +1447,7 @@ static int ice_ptp_cfg_phy_interrupt(struct ice_pf *pf, bool ena, u32 threshold)
ice_ptp_reset_ts_memory(hw);
- switch (hw->ptp.phy_model) {
+ switch (ice_get_phy_model(hw)) {
case ICE_PHY_ETH56G: {
int port;
@@ -1553,7 +1486,7 @@ static int ice_ptp_cfg_phy_interrupt(struct ice_pf *pf, bool ena, u32 threshold)
case ICE_PHY_UNSUP:
default:
dev_warn(dev, "%s: Unexpected PHY model %d\n", __func__,
- hw->ptp.phy_model);
+ ice_get_phy_model(hw));
return -EOPNOTSUPP;
}
}
@@ -1575,10 +1508,10 @@ static void ice_ptp_restart_all_phy(struct ice_pf *pf)
{
struct list_head *entry;
- list_for_each(entry, &pf->ptp.ports_owner.ports) {
+ list_for_each(entry, &pf->adapter->ports.ports) {
struct ice_ptp_port *port = list_entry(entry,
struct ice_ptp_port,
- list_member);
+ list_node);
if (port->link_up)
ice_ptp_port_phy_restart(port);
@@ -1651,33 +1584,41 @@ void ice_ptp_extts_event(struct ice_pf *pf)
/**
* ice_ptp_cfg_extts - Configure EXTTS pin and channel
* @pf: Board private structure
- * @chan: GPIO channel (0-3)
- * @config: desired EXTTS configuration.
- * @store: If set to true, the values will be stored
+ * @rq: External timestamp request
+ * @on: Enable/disable flag
*
* Configure an external timestamp event on the requested channel.
*
- * Return: 0 on success, -EOPNOTUSPP on unsupported flags
+ * Return: 0 on success, negative error code otherwise
*/
-static int ice_ptp_cfg_extts(struct ice_pf *pf, unsigned int chan,
- struct ice_extts_channel *config, bool store)
+static int ice_ptp_cfg_extts(struct ice_pf *pf, struct ptp_extts_request *rq,
+ int on)
{
- u32 func, aux_reg, gpio_reg, irq_reg;
+ u32 aux_reg, gpio_reg, irq_reg;
struct ice_hw *hw = &pf->hw;
+ unsigned int chan, gpio_pin;
+ int pin_desc_idx;
u8 tmr_idx;
/* Reject requests with unsupported flags */
- if (config->flags & ~(PTP_ENABLE_FEATURE |
- PTP_RISING_EDGE |
- PTP_FALLING_EDGE |
- PTP_STRICT_FLAGS))
+
+ if (rq->flags & ~(PTP_ENABLE_FEATURE |
+ PTP_RISING_EDGE |
+ PTP_FALLING_EDGE |
+ PTP_STRICT_FLAGS))
return -EOPNOTSUPP;
tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
+ chan = rq->index;
+
+ pin_desc_idx = ice_ptp_find_pin_idx(pf, PTP_PF_EXTTS, chan);
+ if (pin_desc_idx < 0)
+ return -EIO;
+ gpio_pin = pf->ptp.ice_pin_desc[pin_desc_idx].gpio[0];
irq_reg = rd32(hw, PFINT_OICR_ENA);
- if (config->ena) {
+ if (on) {
/* Enable the interrupt */
irq_reg |= PFINT_OICR_TSYN_EVNT_M;
aux_reg = GLTSYN_AUX_IN_0_INT_ENA_M;
@@ -1686,33 +1627,38 @@ static int ice_ptp_cfg_extts(struct ice_pf *pf, unsigned int chan,
#define GLTSYN_AUX_IN_0_EVNTLVL_FALLING_EDGE BIT(1)
/* set event level to requested edge */
- if (config->flags & PTP_FALLING_EDGE)
+ if (rq->flags & PTP_FALLING_EDGE)
aux_reg |= GLTSYN_AUX_IN_0_EVNTLVL_FALLING_EDGE;
- if (config->flags & PTP_RISING_EDGE)
+ if (rq->flags & PTP_RISING_EDGE)
aux_reg |= GLTSYN_AUX_IN_0_EVNTLVL_RISING_EDGE;
/* Write GPIO CTL reg.
* 0x1 is input sampled by EVENT register(channel)
* + num_in_channels * tmr_idx
*/
- func = 1 + chan + (tmr_idx * 3);
- gpio_reg = FIELD_PREP(GLGEN_GPIO_CTL_PIN_FUNC_M, func);
- pf->ptp.ext_ts_chan |= (1 << chan);
+ gpio_reg = FIELD_PREP(GLGEN_GPIO_CTL_PIN_FUNC_M,
+ 1 + chan + (tmr_idx * 3));
} else {
+ bool last_enabled = true;
+
/* clear the values we set to reset defaults */
aux_reg = 0;
gpio_reg = 0;
- pf->ptp.ext_ts_chan &= ~(1 << chan);
- if (!pf->ptp.ext_ts_chan)
+
+ for (unsigned int i = 0; i < pf->ptp.info.n_ext_ts; i++)
+ if ((pf->ptp.extts_rqs[i].flags &
+ PTP_ENABLE_FEATURE) &&
+ i != chan) {
+ last_enabled = false;
+ }
+
+ if (last_enabled)
irq_reg &= ~PFINT_OICR_TSYN_EVNT_M;
}
wr32(hw, PFINT_OICR_ENA, irq_reg);
wr32(hw, GLTSYN_AUX_IN(chan, tmr_idx), aux_reg);
- wr32(hw, GLGEN_GPIO_CTL(config->gpio_pin), gpio_reg);
-
- if (store)
- memcpy(&pf->ptp.extts_channels[chan], config, sizeof(*config));
+ wr32(hw, GLGEN_GPIO_CTL(gpio_pin), gpio_reg);
return 0;
}
@@ -1723,16 +1669,10 @@ static int ice_ptp_cfg_extts(struct ice_pf *pf, unsigned int chan,
*/
static void ice_ptp_disable_all_extts(struct ice_pf *pf)
{
- struct ice_extts_channel extts_cfg = {};
- int i;
-
- for (i = 0; i < pf->ptp.info.n_ext_ts; i++) {
- if (pf->ptp.extts_channels[i].ena) {
- extts_cfg.gpio_pin = pf->ptp.extts_channels[i].gpio_pin;
- extts_cfg.ena = false;
- ice_ptp_cfg_extts(pf, i, &extts_cfg, false);
- }
- }
+ for (unsigned int i = 0; i < pf->ptp.info.n_ext_ts ; i++)
+ if (pf->ptp.extts_rqs[i].flags & PTP_ENABLE_FEATURE)
+ ice_ptp_cfg_extts(pf, &pf->ptp.extts_rqs[i],
+ false);
synchronize_irq(pf->oicr_irq.virq);
}
@@ -1745,273 +1685,322 @@ static void ice_ptp_disable_all_extts(struct ice_pf *pf)
*/
static void ice_ptp_enable_all_extts(struct ice_pf *pf)
{
- int i;
-
- for (i = 0; i < pf->ptp.info.n_ext_ts; i++) {
- if (pf->ptp.extts_channels[i].ena)
- ice_ptp_cfg_extts(pf, i, &pf->ptp.extts_channels[i],
- false);
- }
+ for (unsigned int i = 0; i < pf->ptp.info.n_ext_ts ; i++)
+ if (pf->ptp.extts_rqs[i].flags & PTP_ENABLE_FEATURE)
+ ice_ptp_cfg_extts(pf, &pf->ptp.extts_rqs[i],
+ true);
}
/**
- * ice_ptp_cfg_clkout - Configure clock to generate periodic wave
- * @pf: Board private structure
- * @chan: GPIO channel (0-3)
- * @config: desired periodic clk configuration. NULL will disable channel
- * @store: If set to true the values will be stored
+ * ice_ptp_write_perout - Write periodic wave parameters to HW
+ * @hw: pointer to the HW struct
+ * @chan: target channel
+ * @gpio_pin: target GPIO pin
+ * @start: target time to start periodic output
+ * @period: target period
*
- * Configure the internal clock generator modules to generate the clock wave of
- * specified period.
+ * Return: 0 on success, negative error code otherwise
*/
-static int ice_ptp_cfg_clkout(struct ice_pf *pf, unsigned int chan,
- struct ice_perout_channel *config, bool store)
+static int ice_ptp_write_perout(struct ice_hw *hw, unsigned int chan,
+ unsigned int gpio_pin, u64 start, u64 period)
{
- u64 current_time, period, start_time, phase;
- struct ice_hw *hw = &pf->hw;
- u32 func, val, gpio_pin;
- u8 tmr_idx;
- if (config && config->flags & ~PTP_PEROUT_PHASE)
- return -EOPNOTSUPP;
-
- tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
+ u8 tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
+ u32 val = 0;
/* 0. Reset mode & out_en in AUX_OUT */
wr32(hw, GLTSYN_AUX_OUT(chan, tmr_idx), 0);
- /* If we're disabling the output, clear out CLKO and TGT and keep
- * output level low
- */
- if (!config || !config->ena) {
- wr32(hw, GLTSYN_CLKO(chan, tmr_idx), 0);
- wr32(hw, GLTSYN_TGT_L(chan, tmr_idx), 0);
- wr32(hw, GLTSYN_TGT_H(chan, tmr_idx), 0);
-
- val = GLGEN_GPIO_CTL_PIN_DIR_M;
- gpio_pin = pf->ptp.perout_channels[chan].gpio_pin;
- wr32(hw, GLGEN_GPIO_CTL(gpio_pin), val);
-
- /* Store the value if requested */
- if (store)
- memset(&pf->ptp.perout_channels[chan], 0,
- sizeof(struct ice_perout_channel));
-
- return 0;
- }
- period = config->period;
- start_time = config->start_time;
- div64_u64_rem(start_time, period, &phase);
- gpio_pin = config->gpio_pin;
+ if (ice_is_e825c(hw)) {
+ int err;
- /* 1. Write clkout with half of required period value */
- if (period & 0x1) {
- dev_err(ice_pf_to_dev(pf), "CLK Period must be an even value\n");
- goto err;
+ /* Enable/disable CGU 1PPS output for E825C */
+ err = ice_cgu_cfg_pps_out(hw, !!period);
+ if (err)
+ return err;
}
+ /* 1. Write perout with half of required period value.
+ * HW toggles output when source clock hits the TGT and then adds
+ * GLTSYN_CLKO value to the target, so it ends up with 50% duty cycle.
+ */
period >>= 1;
- /* For proper operation, the GLTSYN_CLKO must be larger than clock tick
+ /* For proper operation, GLTSYN_CLKO must be larger than clock tick and
+ * period has to fit in 32 bit register.
*/
#define MIN_PULSE 3
- if (period <= MIN_PULSE || period > U32_MAX) {
- dev_err(ice_pf_to_dev(pf), "CLK Period must be > %d && < 2^33",
- MIN_PULSE * 2);
- goto err;
+ if (!!period && (period <= MIN_PULSE || period > U32_MAX)) {
+ dev_err(ice_hw_to_dev(hw), "CLK period ticks must be >= %d && <= 2^32",
+ MIN_PULSE);
+ return -EIO;
}
wr32(hw, GLTSYN_CLKO(chan, tmr_idx), lower_32_bits(period));
- /* Allow time for programming before start_time is hit */
- current_time = ice_ptp_read_src_clk_reg(pf, NULL);
-
- /* if start time is in the past start the timer at the nearest second
- * maintaining phase
- */
- if (start_time < current_time)
- start_time = roundup_u64(current_time, NSEC_PER_SEC) + phase;
-
- if (ice_is_e810(hw))
- start_time -= E810_OUT_PROP_DELAY_NS;
- else
- start_time -= ice_e82x_pps_delay(ice_e82x_time_ref(hw));
-
/* 2. Write TARGET time */
- wr32(hw, GLTSYN_TGT_L(chan, tmr_idx), lower_32_bits(start_time));
- wr32(hw, GLTSYN_TGT_H(chan, tmr_idx), upper_32_bits(start_time));
+ wr32(hw, GLTSYN_TGT_L(chan, tmr_idx), lower_32_bits(start));
+ wr32(hw, GLTSYN_TGT_H(chan, tmr_idx), upper_32_bits(start));
/* 3. Write AUX_OUT register */
- val = GLTSYN_AUX_OUT_0_OUT_ENA_M | GLTSYN_AUX_OUT_0_OUTMOD_M;
+ if (!!period)
+ val = GLTSYN_AUX_OUT_0_OUT_ENA_M | GLTSYN_AUX_OUT_0_OUTMOD_M;
wr32(hw, GLTSYN_AUX_OUT(chan, tmr_idx), val);
/* 4. write GPIO CTL reg */
- func = 8 + chan + (tmr_idx * 4);
- val = GLGEN_GPIO_CTL_PIN_DIR_M |
- FIELD_PREP(GLGEN_GPIO_CTL_PIN_FUNC_M, func);
+ val = GLGEN_GPIO_CTL_PIN_DIR_M;
+ if (!!period)
+ val |= FIELD_PREP(GLGEN_GPIO_CTL_PIN_FUNC_M,
+ 8 + chan + (tmr_idx * 4));
+
wr32(hw, GLGEN_GPIO_CTL(gpio_pin), val);
- /* Store the value if requested */
- if (store) {
- memcpy(&pf->ptp.perout_channels[chan], config,
- sizeof(struct ice_perout_channel));
- pf->ptp.perout_channels[chan].start_time = phase;
+ return 0;
+}
+
+/**
+ * ice_ptp_cfg_perout - Configure clock to generate periodic wave
+ * @pf: Board private structure
+ * @rq: Periodic output request
+ * @on: Enable/disable flag
+ *
+ * Configure the internal clock generator modules to generate the clock wave of
+ * specified period.
+ *
+ * Return: 0 on success, negative error code otherwise
+ */
+static int ice_ptp_cfg_perout(struct ice_pf *pf, struct ptp_perout_request *rq,
+ int on)
+{
+ u64 clk, period, start, phase;
+ struct ice_hw *hw = &pf->hw;
+ unsigned int gpio_pin;
+ int pin_desc_idx;
+
+ if (rq->flags & ~PTP_PEROUT_PHASE)
+ return -EOPNOTSUPP;
+
+ pin_desc_idx = ice_ptp_find_pin_idx(pf, PTP_PF_PEROUT, rq->index);
+ if (pin_desc_idx < 0)
+ return -EIO;
+
+ gpio_pin = pf->ptp.ice_pin_desc[pin_desc_idx].gpio[1];
+ period = rq->period.sec * NSEC_PER_SEC + rq->period.nsec;
+
+ /* If we're disabling the output or period is 0, clear out CLKO and TGT
+ * and keep output level low.
+ */
+ if (!on || !period)
+ return ice_ptp_write_perout(hw, rq->index, gpio_pin, 0, 0);
+
+ if (strncmp(pf->ptp.pin_desc[pin_desc_idx].name, "1PPS", 64) == 0 &&
+ period != NSEC_PER_SEC && hw->ptp.phy_model == ICE_PHY_E82X) {
+ dev_err(ice_pf_to_dev(pf), "1PPS pin supports only 1 s period\n");
+ return -EOPNOTSUPP;
}
- return 0;
-err:
- dev_err(ice_pf_to_dev(pf), "PTP failed to cfg per_clk\n");
- return -EFAULT;
+ if (period & 0x1) {
+ dev_err(ice_pf_to_dev(pf), "CLK Period must be an even value\n");
+ return -EIO;
+ }
+
+ start = rq->start.sec * NSEC_PER_SEC + rq->start.nsec;
+
+ /* If PTP_PEROUT_PHASE is set, rq has phase instead of start time */
+ if (rq->flags & PTP_PEROUT_PHASE)
+ phase = start;
+ else
+ div64_u64_rem(start, period, &phase);
+
+ /* If we have only phase or start time is in the past, start the timer
+ * at the next multiple of period, maintaining phase.
+ */
+ clk = ice_ptp_read_src_clk_reg(pf, NULL);
+ if (rq->flags & PTP_PEROUT_PHASE || start <= clk - ice_prop_delay(hw))
+ start = div64_u64(clk + period - 1, period) * period + phase;
+
+ /* Compensate for propagation delay from the generator to the pin. */
+ start -= ice_prop_delay(hw);
+
+ return ice_ptp_write_perout(hw, rq->index, gpio_pin, start, period);
}
/**
- * ice_ptp_disable_all_clkout - Disable all currently configured outputs
- * @pf: pointer to the PF structure
+ * ice_ptp_disable_all_perout - Disable all currently configured outputs
+ * @pf: Board private structure
*
* Disable all currently configured clock outputs. This is necessary before
- * certain changes to the PTP hardware clock. Use ice_ptp_enable_all_clkout to
+ * certain changes to the PTP hardware clock. Use ice_ptp_enable_all_perout to
* re-enable the clocks again.
*/
-static void ice_ptp_disable_all_clkout(struct ice_pf *pf)
+static void ice_ptp_disable_all_perout(struct ice_pf *pf)
{
- uint i;
-
- for (i = 0; i < pf->ptp.info.n_per_out; i++)
- if (pf->ptp.perout_channels[i].ena)
- ice_ptp_cfg_clkout(pf, i, NULL, false);
+ for (unsigned int i = 0; i < pf->ptp.info.n_per_out; i++)
+ if (pf->ptp.perout_rqs[i].period.sec ||
+ pf->ptp.perout_rqs[i].period.nsec)
+ ice_ptp_cfg_perout(pf, &pf->ptp.perout_rqs[i],
+ false);
}
/**
- * ice_ptp_enable_all_clkout - Enable all configured periodic clock outputs
- * @pf: pointer to the PF structure
+ * ice_ptp_enable_all_perout - Enable all configured periodic clock outputs
+ * @pf: Board private structure
*
* Enable all currently configured clock outputs. Use this after
- * ice_ptp_disable_all_clkout to reconfigure the output signals according to
+ * ice_ptp_disable_all_perout to reconfigure the output signals according to
* their configuration.
*/
-static void ice_ptp_enable_all_clkout(struct ice_pf *pf)
+static void ice_ptp_enable_all_perout(struct ice_pf *pf)
{
- uint i;
-
- for (i = 0; i < pf->ptp.info.n_per_out; i++)
- if (pf->ptp.perout_channels[i].ena)
- ice_ptp_cfg_clkout(pf, i, &pf->ptp.perout_channels[i],
- false);
+ for (unsigned int i = 0; i < pf->ptp.info.n_per_out; i++)
+ if (pf->ptp.perout_rqs[i].period.sec ||
+ pf->ptp.perout_rqs[i].period.nsec)
+ ice_ptp_cfg_perout(pf, &pf->ptp.perout_rqs[i],
+ true);
}
/**
- * ice_ptp_gpio_enable_e810 - Enable/disable ancillary features of PHC
- * @info: the driver's PTP info structure
- * @rq: The requested feature to change
- * @on: Enable/disable flag
+ * ice_ptp_disable_shared_pin - Disable enabled pin that shares GPIO
+ * @pf: Board private structure
+ * @pin: Pin index
+ * @func: Assigned function
+ *
+ * Return: 0 on success, negative error code otherwise
*/
-static int
-ice_ptp_gpio_enable_e810(struct ptp_clock_info *info,
- struct ptp_clock_request *rq, int on)
+static int ice_ptp_disable_shared_pin(struct ice_pf *pf, unsigned int pin,
+ enum ptp_pin_function func)
{
- struct ice_pf *pf = ptp_info_to_pf(info);
- bool sma_pres = false;
- unsigned int chan;
- u32 gpio_pin;
+ unsigned int gpio_pin;
- if (ice_is_feature_supported(pf, ICE_F_SMA_CTRL))
- sma_pres = true;
+ switch (func) {
+ case PTP_PF_PEROUT:
+ gpio_pin = pf->ptp.ice_pin_desc[pin].gpio[1];
+ break;
+ case PTP_PF_EXTTS:
+ gpio_pin = pf->ptp.ice_pin_desc[pin].gpio[0];
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
- switch (rq->type) {
- case PTP_CLK_REQ_PEROUT:
- {
- struct ice_perout_channel clk_cfg = {};
-
- chan = rq->perout.index;
- if (sma_pres) {
- if (chan == ice_pin_desc_e810t[SMA1].chan)
- clk_cfg.gpio_pin = GPIO_20;
- else if (chan == ice_pin_desc_e810t[SMA2].chan)
- clk_cfg.gpio_pin = GPIO_22;
- else
- return -1;
- } else if (ice_is_e810t(&pf->hw)) {
- if (chan == 0)
- clk_cfg.gpio_pin = GPIO_20;
- else
- clk_cfg.gpio_pin = GPIO_22;
- } else if (chan == PPS_CLK_GEN_CHAN) {
- clk_cfg.gpio_pin = PPS_PIN_INDEX;
- } else {
- clk_cfg.gpio_pin = chan;
- }
+ for (unsigned int i = 0; i < pf->ptp.info.n_pins; i++) {
+ struct ptp_pin_desc *pin_desc = &pf->ptp.pin_desc[i];
+ unsigned int chan = pin_desc->chan;
- clk_cfg.flags = rq->perout.flags;
- clk_cfg.period = ((rq->perout.period.sec * NSEC_PER_SEC) +
- rq->perout.period.nsec);
- clk_cfg.start_time = ((rq->perout.start.sec * NSEC_PER_SEC) +
- rq->perout.start.nsec);
- clk_cfg.ena = !!on;
+ /* Skip pin idx from the request */
+ if (i == pin)
+ continue;
- return ice_ptp_cfg_clkout(pf, chan, &clk_cfg, true);
- }
- case PTP_CLK_REQ_EXTTS:
- {
- struct ice_extts_channel extts_cfg = {};
-
- chan = rq->extts.index;
- if (sma_pres) {
- if (chan < ice_pin_desc_e810t[SMA2].chan)
- gpio_pin = GPIO_21;
- else
- gpio_pin = GPIO_23;
- } else if (ice_is_e810t(&pf->hw)) {
- if (chan == 0)
- gpio_pin = GPIO_21;
- else
- gpio_pin = GPIO_23;
- } else {
- gpio_pin = chan;
+ if (pin_desc->func == PTP_PF_PEROUT &&
+ pf->ptp.ice_pin_desc[i].gpio[1] == gpio_pin) {
+ pf->ptp.perout_rqs[chan].period.sec = 0;
+ pf->ptp.perout_rqs[chan].period.nsec = 0;
+ pin_desc->func = PTP_PF_NONE;
+ pin_desc->chan = 0;
+ dev_dbg(ice_pf_to_dev(pf), "Disabling pin %u with shared output GPIO pin %u\n",
+ i, gpio_pin);
+ return ice_ptp_cfg_perout(pf, &pf->ptp.perout_rqs[chan],
+ false);
+ } else if (pf->ptp.pin_desc->func == PTP_PF_EXTTS &&
+ pf->ptp.ice_pin_desc[i].gpio[0] == gpio_pin) {
+ pf->ptp.extts_rqs[chan].flags &= ~PTP_ENABLE_FEATURE;
+ pin_desc->func = PTP_PF_NONE;
+ pin_desc->chan = 0;
+ dev_dbg(ice_pf_to_dev(pf), "Disabling pin %u with shared input GPIO pin %u\n",
+ i, gpio_pin);
+ return ice_ptp_cfg_extts(pf, &pf->ptp.extts_rqs[chan],
+ false);
}
+ }
- extts_cfg.flags = rq->extts.flags;
- extts_cfg.gpio_pin = gpio_pin;
- extts_cfg.ena = !!on;
+ return 0;
+}
- return ice_ptp_cfg_extts(pf, chan, &extts_cfg, true);
- }
+/**
+ * ice_verify_pin - verify if pin supports requested pin function
+ * @info: the driver's PTP info structure
+ * @pin: Pin index
+ * @func: Assigned function
+ * @chan: Assigned channel
+ *
+ * Return: 0 on success, -EOPNOTSUPP when function is not supported.
+ */
+static int ice_verify_pin(struct ptp_clock_info *info, unsigned int pin,
+ enum ptp_pin_function func, unsigned int chan)
+{
+ struct ice_pf *pf = ptp_info_to_pf(info);
+ const struct ice_ptp_pin_desc *pin_desc;
+
+ pin_desc = &pf->ptp.ice_pin_desc[pin];
+
+ /* Is assigned function allowed? */
+ switch (func) {
+ case PTP_PF_EXTTS:
+ if (pin_desc->gpio[0] < 0)
+ return -EOPNOTSUPP;
+ break;
+ case PTP_PF_PEROUT:
+ if (pin_desc->gpio[1] < 0)
+ return -EOPNOTSUPP;
+ break;
+ case PTP_PF_NONE:
+ break;
+ case PTP_PF_PHYSYNC:
default:
return -EOPNOTSUPP;
}
+
+ /* On adapters with SMA_CTRL disable other pins that share same GPIO */
+ if (ice_is_feature_supported(pf, ICE_F_SMA_CTRL)) {
+ ice_ptp_disable_shared_pin(pf, pin, func);
+ pf->ptp.pin_desc[pin].func = func;
+ pf->ptp.pin_desc[pin].chan = chan;
+ return ice_ptp_set_sma_cfg(pf);
+ }
+
+ return 0;
}
/**
- * ice_ptp_gpio_enable_e823 - Enable/disable ancillary features of PHC
- * @info: the driver's PTP info structure
+ * ice_ptp_gpio_enable - Enable/disable ancillary features of PHC
+ * @info: The driver's PTP info structure
* @rq: The requested feature to change
* @on: Enable/disable flag
+ *
+ * Return: 0 on success, negative error code otherwise
*/
-static int ice_ptp_gpio_enable_e823(struct ptp_clock_info *info,
- struct ptp_clock_request *rq, int on)
+static int ice_ptp_gpio_enable(struct ptp_clock_info *info,
+ struct ptp_clock_request *rq, int on)
{
struct ice_pf *pf = ptp_info_to_pf(info);
+ int err;
switch (rq->type) {
- case PTP_CLK_REQ_PPS:
+ case PTP_CLK_REQ_PEROUT:
{
- struct ice_perout_channel clk_cfg = {};
+ struct ptp_perout_request *cached =
+ &pf->ptp.perout_rqs[rq->perout.index];
- clk_cfg.flags = rq->perout.flags;
- clk_cfg.gpio_pin = PPS_PIN_INDEX;
- clk_cfg.period = NSEC_PER_SEC;
- clk_cfg.ena = !!on;
-
- return ice_ptp_cfg_clkout(pf, PPS_CLK_GEN_CHAN, &clk_cfg, true);
+ err = ice_ptp_cfg_perout(pf, &rq->perout, on);
+ if (!err) {
+ *cached = rq->perout;
+ } else {
+ cached->period.sec = 0;
+ cached->period.nsec = 0;
+ }
+ return err;
}
case PTP_CLK_REQ_EXTTS:
{
- struct ice_extts_channel extts_cfg = {};
-
- extts_cfg.flags = rq->extts.flags;
- extts_cfg.gpio_pin = TIME_SYNC_PIN_INDEX;
- extts_cfg.ena = !!on;
+ struct ptp_extts_request *cached =
+ &pf->ptp.extts_rqs[rq->extts.index];
- return ice_ptp_cfg_extts(pf, rq->extts.index, &extts_cfg, true);
+ err = ice_ptp_cfg_extts(pf, &rq->extts, on);
+ if (!err)
+ *cached = rq->extts;
+ else
+ cached->flags &= ~PTP_ENABLE_FEATURE;
+ return err;
}
default:
return -EOPNOTSUPP;
@@ -2059,7 +2048,7 @@ ice_ptp_settime64(struct ptp_clock_info *info, const struct timespec64 *ts)
/* For Vernier mode on E82X, we need to recalibrate after new settime.
* Start with marking timestamps as invalid.
*/
- if (hw->ptp.phy_model == ICE_PHY_E82X) {
+ if (ice_get_phy_model(hw) == ICE_PHY_E82X) {
err = ice_ptp_clear_phy_offset_ready_e82x(hw);
if (err)
dev_warn(ice_pf_to_dev(pf), "Failed to mark timestamps as invalid before settime\n");
@@ -2071,7 +2060,7 @@ ice_ptp_settime64(struct ptp_clock_info *info, const struct timespec64 *ts)
}
/* Disable periodic outputs */
- ice_ptp_disable_all_clkout(pf);
+ ice_ptp_disable_all_perout(pf);
err = ice_ptp_write_init(pf, &ts64);
ice_ptp_unlock(hw);
@@ -2080,10 +2069,10 @@ ice_ptp_settime64(struct ptp_clock_info *info, const struct timespec64 *ts)
ice_ptp_reset_cached_phctime(pf);
/* Reenable periodic outputs */
- ice_ptp_enable_all_clkout(pf);
+ ice_ptp_enable_all_perout(pf);
/* Recalibrate and re-enable timestamp blocks for E822/E823 */
- if (hw->ptp.phy_model == ICE_PHY_E82X)
+ if (ice_get_phy_model(hw) == ICE_PHY_E82X)
ice_ptp_restart_all_phy(pf);
exit:
if (err) {
@@ -2142,12 +2131,12 @@ static int ice_ptp_adjtime(struct ptp_clock_info *info, s64 delta)
}
/* Disable periodic outputs */
- ice_ptp_disable_all_clkout(pf);
+ ice_ptp_disable_all_perout(pf);
err = ice_ptp_write_adj(pf, delta);
/* Reenable periodic outputs */
- ice_ptp_enable_all_clkout(pf);
+ ice_ptp_enable_all_perout(pf);
ice_ptp_unlock(hw);
@@ -2405,20 +2394,41 @@ u64 ice_ptp_get_rx_hwts(const union ice_32b_rx_flex_desc *rx_desc,
}
/**
- * ice_ptp_disable_sma_pins_e810t - Disable E810-T SMA pins
+ * ice_ptp_setup_pin_cfg - setup PTP pin_config structure
+ * @pf: Board private structure
+ */
+static void ice_ptp_setup_pin_cfg(struct ice_pf *pf)
+{
+ for (unsigned int i = 0; i < pf->ptp.info.n_pins; i++) {
+ const struct ice_ptp_pin_desc *desc = &pf->ptp.ice_pin_desc[i];
+ struct ptp_pin_desc *pin = &pf->ptp.pin_desc[i];
+ const char *name = NULL;
+
+ if (!ice_is_feature_supported(pf, ICE_F_SMA_CTRL))
+ name = ice_pin_names[desc->name_idx];
+ else if (desc->name_idx != GPIO_NA)
+ name = ice_pin_names_nvm[desc->name_idx];
+ if (name)
+ strscpy(pin->name, name, sizeof(pin->name));
+
+ pin->index = i;
+ }
+
+ pf->ptp.info.pin_config = pf->ptp.pin_desc;
+}
+
+/**
+ * ice_ptp_disable_pins - Disable PTP pins
* @pf: pointer to the PF structure
- * @info: PTP clock info structure
*
* Disable the OS access to the SMA pins. Called to clear out the OS
- * indications of pin support when we fail to setup the E810-T SMA control
- * register.
+ * indications of pin support when we fail to setup the SMA control register.
*/
-static void
-ice_ptp_disable_sma_pins_e810t(struct ice_pf *pf, struct ptp_clock_info *info)
+static void ice_ptp_disable_pins(struct ice_pf *pf)
{
- struct device *dev = ice_pf_to_dev(pf);
+ struct ptp_clock_info *info = &pf->ptp.info;
- dev_warn(dev, "Failed to configure E810-T SMA pin control\n");
+ dev_warn(ice_pf_to_dev(pf), "Failed to configure PTP pin control\n");
info->enable = NULL;
info->verify = NULL;
@@ -2428,126 +2438,158 @@ ice_ptp_disable_sma_pins_e810t(struct ice_pf *pf, struct ptp_clock_info *info)
}
/**
- * ice_ptp_setup_sma_pins_e810t - Setup the SMA pins
+ * ice_ptp_parse_sdp_entries - update ice_ptp_pin_desc structure from NVM
* @pf: pointer to the PF structure
- * @info: PTP clock info structure
+ * @entries: SDP connection section from NVM
+ * @num_entries: number of valid entries in sdp_entries
+ * @pins: PTP pins array to update
*
- * Finish setting up the SMA pins by allocating pin_config, and setting it up
- * according to the current status of the SMA. On failure, disable all of the
- * extended SMA pin support.
+ * Return: 0 on success, negative error code otherwise.
*/
-static void
-ice_ptp_setup_sma_pins_e810t(struct ice_pf *pf, struct ptp_clock_info *info)
+static int ice_ptp_parse_sdp_entries(struct ice_pf *pf, __le16 *entries,
+ unsigned int num_entries,
+ struct ice_ptp_pin_desc *pins)
{
- struct device *dev = ice_pf_to_dev(pf);
- int err;
+ unsigned int n_pins = 0;
+ unsigned int i;
- /* Allocate memory for kernel pins interface */
- info->pin_config = devm_kcalloc(dev, info->n_pins,
- sizeof(*info->pin_config), GFP_KERNEL);
- if (!info->pin_config) {
- ice_ptp_disable_sma_pins_e810t(pf, info);
- return;
- }
+ /* Setup ice_pin_desc array */
+ for (i = 0; i < ICE_N_PINS_MAX; i++) {
+ pins[i].name_idx = -1;
+ pins[i].gpio[0] = -1;
+ pins[i].gpio[1] = -1;
+ }
+
+ for (i = 0; i < num_entries; i++) {
+ u16 entry = le16_to_cpu(entries[i]);
+ DECLARE_BITMAP(bitmap, GPIO_NA);
+ unsigned int bitmap_idx;
+ bool dir;
+ u16 gpio;
+
+ *bitmap = FIELD_GET(ICE_AQC_NVM_SDP_AC_PIN_M, entry);
+ dir = !!FIELD_GET(ICE_AQC_NVM_SDP_AC_DIR_M, entry);
+ gpio = FIELD_GET(ICE_AQC_NVM_SDP_AC_SDP_NUM_M, entry);
+ for_each_set_bit(bitmap_idx, bitmap, GPIO_NA + 1) {
+ unsigned int idx;
+
+ /* Check if entry's pin bit is valid */
+ if (bitmap_idx >= NUM_PTP_PINS_NVM &&
+ bitmap_idx != GPIO_NA)
+ continue;
- /* Read current SMA status */
- err = ice_get_sma_config_e810t(&pf->hw, info->pin_config);
- if (err)
- ice_ptp_disable_sma_pins_e810t(pf, info);
-}
+ /* Check if pin already exists */
+ for (idx = 0; idx < ICE_N_PINS_MAX; idx++)
+ if (pins[idx].name_idx == bitmap_idx)
+ break;
+
+ if (idx == ICE_N_PINS_MAX) {
+ /* Pin not found, setup its entry and name */
+ idx = n_pins++;
+ pins[idx].name_idx = bitmap_idx;
+ if (bitmap_idx == GPIO_NA)
+ strscpy(pf->ptp.pin_desc[idx].name,
+ ice_pin_names[gpio],
+ sizeof(pf->ptp.pin_desc[idx]
+ .name));
+ }
-/**
- * ice_ptp_setup_pins_e810 - Setup PTP pins in sysfs
- * @pf: pointer to the PF instance
- * @info: PTP clock capabilities
- */
-static void
-ice_ptp_setup_pins_e810(struct ice_pf *pf, struct ptp_clock_info *info)
-{
- if (ice_is_feature_supported(pf, ICE_F_SMA_CTRL)) {
- info->n_ext_ts = N_EXT_TS_E810;
- info->n_per_out = N_PER_OUT_E810T;
- info->n_pins = NUM_PTP_PINS_E810T;
- info->verify = ice_verify_pin_e810t;
-
- /* Complete setup of the SMA pins */
- ice_ptp_setup_sma_pins_e810t(pf, info);
- } else if (ice_is_e810t(&pf->hw)) {
- info->n_ext_ts = N_EXT_TS_NO_SMA_E810T;
- info->n_per_out = N_PER_OUT_NO_SMA_E810T;
- } else {
- info->n_per_out = N_PER_OUT_E810;
- info->n_ext_ts = N_EXT_TS_E810;
+ /* Setup in/out GPIO number */
+ pins[idx].gpio[dir] = gpio;
+ }
}
-}
-/**
- * ice_ptp_setup_pins_e823 - Setup PTP pins in sysfs
- * @pf: pointer to the PF instance
- * @info: PTP clock capabilities
- */
-static void
-ice_ptp_setup_pins_e823(struct ice_pf *pf, struct ptp_clock_info *info)
-{
- info->pps = 1;
- info->n_per_out = 0;
- info->n_ext_ts = 1;
+ for (i = 0; i < n_pins; i++) {
+ dev_dbg(ice_pf_to_dev(pf),
+ "NVM pin entry[%d] : name_idx %d gpio_out %d gpio_in %d\n",
+ i, pins[i].name_idx, pins[i].gpio[1], pins[i].gpio[0]);
+ }
+
+ pf->ptp.info.n_pins = n_pins;
+ return 0;
}
/**
- * ice_ptp_set_funcs_e82x - Set specialized functions for E82x support
+ * ice_ptp_set_funcs_e82x - Set specialized functions for E82X support
* @pf: Board private structure
- * @info: PTP info to fill
*
- * Assign functions to the PTP capabiltiies structure for E82x devices.
+ * Assign functions to the PTP capabilities structure for E82X devices.
* Functions which operate across all device families should be set directly
- * in ice_ptp_set_caps. Only add functions here which are distinct for E82x
+ * in ice_ptp_set_caps. Only add functions here which are distinct for E82X
* devices.
*/
-static void
-ice_ptp_set_funcs_e82x(struct ice_pf *pf, struct ptp_clock_info *info)
+static void ice_ptp_set_funcs_e82x(struct ice_pf *pf)
{
#ifdef CONFIG_ICE_HWTS
if (boot_cpu_has(X86_FEATURE_ART) &&
boot_cpu_has(X86_FEATURE_TSC_KNOWN_FREQ))
- info->getcrosststamp = ice_ptp_getcrosststamp_e82x;
+ pf->ptp.info.getcrosststamp = ice_ptp_getcrosststamp_e82x;
+
#endif /* CONFIG_ICE_HWTS */
+ if (ice_is_e825c(&pf->hw)) {
+ pf->ptp.ice_pin_desc = ice_pin_desc_e825c;
+ pf->ptp.info.n_pins = ICE_PIN_DESC_ARR_LEN(ice_pin_desc_e825c);
+ } else {
+ pf->ptp.ice_pin_desc = ice_pin_desc_e82x;
+ pf->ptp.info.n_pins = ICE_PIN_DESC_ARR_LEN(ice_pin_desc_e82x);
+ }
+ ice_ptp_setup_pin_cfg(pf);
}
/**
* ice_ptp_set_funcs_e810 - Set specialized functions for E810 support
* @pf: Board private structure
- * @info: PTP info to fill
*
* Assign functions to the PTP capabiltiies structure for E810 devices.
* Functions which operate across all device families should be set directly
- * in ice_ptp_set_caps. Only add functions here which are distinct for e810
+ * in ice_ptp_set_caps. Only add functions here which are distinct for E810
* devices.
*/
-static void
-ice_ptp_set_funcs_e810(struct ice_pf *pf, struct ptp_clock_info *info)
+static void ice_ptp_set_funcs_e810(struct ice_pf *pf)
{
- info->enable = ice_ptp_gpio_enable_e810;
- ice_ptp_setup_pins_e810(pf, info);
-}
+ __le16 entries[ICE_AQC_NVM_SDP_AC_MAX_SIZE];
+ struct ice_ptp_pin_desc *desc = NULL;
+ struct ice_ptp *ptp = &pf->ptp;
+ unsigned int num_entries;
+ int err;
-/**
- * ice_ptp_set_funcs_e823 - Set specialized functions for E823 support
- * @pf: Board private structure
- * @info: PTP info to fill
- *
- * Assign functions to the PTP capabiltiies structure for E823 devices.
- * Functions which operate across all device families should be set directly
- * in ice_ptp_set_caps. Only add functions here which are distinct for e823
- * devices.
- */
-static void
-ice_ptp_set_funcs_e823(struct ice_pf *pf, struct ptp_clock_info *info)
-{
- ice_ptp_set_funcs_e82x(pf, info);
+ err = ice_ptp_read_sdp_ac(&pf->hw, entries, &num_entries);
+ if (err) {
+ /* SDP section does not exist in NVM or is corrupted */
+ if (ice_is_feature_supported(pf, ICE_F_SMA_CTRL)) {
+ ptp->ice_pin_desc = ice_pin_desc_e810_sma;
+ ptp->info.n_pins =
+ ICE_PIN_DESC_ARR_LEN(ice_pin_desc_e810_sma);
+ } else {
+ pf->ptp.ice_pin_desc = ice_pin_desc_e810;
+ pf->ptp.info.n_pins =
+ ICE_PIN_DESC_ARR_LEN(ice_pin_desc_e810);
+ err = 0;
+ }
+ } else {
+ desc = devm_kcalloc(ice_pf_to_dev(pf), ICE_N_PINS_MAX,
+ sizeof(struct ice_ptp_pin_desc),
+ GFP_KERNEL);
+ if (!desc)
+ goto err;
+
+ err = ice_ptp_parse_sdp_entries(pf, entries, num_entries, desc);
+ if (err)
+ goto err;
+
+ ptp->ice_pin_desc = (const struct ice_ptp_pin_desc *)desc;
+ }
+
+ ptp->info.pin_config = ptp->pin_desc;
+ ice_ptp_setup_pin_cfg(pf);
- info->enable = ice_ptp_gpio_enable_e823;
- ice_ptp_setup_pins_e823(pf, info);
+ if (ice_is_feature_supported(pf, ICE_F_SMA_CTRL))
+ err = ice_ptp_set_sma_cfg(pf);
+err:
+ if (err) {
+ devm_kfree(ice_pf_to_dev(pf), desc);
+ ice_ptp_disable_pins(pf);
+ }
}
/**
@@ -2567,13 +2609,15 @@ static void ice_ptp_set_caps(struct ice_pf *pf)
info->adjfine = ice_ptp_adjfine;
info->gettimex64 = ice_ptp_gettimex64;
info->settime64 = ice_ptp_settime64;
+ info->n_per_out = GLTSYN_TGT_H_IDX_MAX;
+ info->n_ext_ts = GLTSYN_EVNT_H_IDX_MAX;
+ info->enable = ice_ptp_gpio_enable;
+ info->verify = ice_verify_pin;
if (ice_is_e810(&pf->hw))
- ice_ptp_set_funcs_e810(pf, info);
- else if (ice_is_e823(&pf->hw))
- ice_ptp_set_funcs_e823(pf, info);
+ ice_ptp_set_funcs_e810(pf);
else
- ice_ptp_set_funcs_e82x(pf, info);
+ ice_ptp_set_funcs_e82x(pf);
}
/**
@@ -2775,7 +2819,7 @@ void ice_ptp_prepare_for_reset(struct ice_pf *pf, enum ice_reset_req reset_type)
ice_ptp_release_tx_tracker(pf, &pf->ptp.port.tx);
/* Disable periodic outputs */
- ice_ptp_disable_all_clkout(pf);
+ ice_ptp_disable_all_perout(pf);
src_tmr = ice_get_ptp_src_clock_index(&pf->hw);
@@ -2852,7 +2896,7 @@ static int ice_ptp_rebuild_owner(struct ice_pf *pf)
}
/* Re-enable all periodic outputs and external timestamp events */
- ice_ptp_enable_all_clkout(pf);
+ ice_ptp_enable_all_perout(pf);
ice_ptp_enable_all_extts(pf);
return 0;
@@ -2895,187 +2939,49 @@ err:
dev_err(ice_pf_to_dev(pf), "PTP reset failed %d\n", err);
}
-/**
- * ice_ptp_aux_dev_to_aux_pf - Get auxiliary PF handle for the auxiliary device
- * @aux_dev: auxiliary device to get the auxiliary PF for
- */
-static struct ice_pf *
-ice_ptp_aux_dev_to_aux_pf(struct auxiliary_device *aux_dev)
+static bool ice_is_primary(struct ice_hw *hw)
{
- struct ice_ptp_port *aux_port;
- struct ice_ptp *aux_ptp;
-
- aux_port = container_of(aux_dev, struct ice_ptp_port, aux_dev);
- aux_ptp = container_of(aux_port, struct ice_ptp, port);
-
- return container_of(aux_ptp, struct ice_pf, ptp);
+ return ice_is_e825c(hw) && ice_is_dual(hw) ?
+ !!(hw->dev_caps.nac_topo.mode & ICE_NAC_TOPO_PRIMARY_M) : true;
}
-/**
- * ice_ptp_aux_dev_to_owner_pf - Get PF handle for the auxiliary device
- * @aux_dev: auxiliary device to get the PF for
- */
-static struct ice_pf *
-ice_ptp_aux_dev_to_owner_pf(struct auxiliary_device *aux_dev)
+static int ice_ptp_setup_adapter(struct ice_pf *pf)
{
- struct ice_ptp_port_owner *ports_owner;
- const struct auxiliary_driver *aux_drv;
- struct ice_ptp *owner_ptp;
+ if (!ice_pf_src_tmr_owned(pf) || !ice_is_primary(&pf->hw))
+ return -EPERM;
- if (!aux_dev->dev.driver)
- return NULL;
-
- aux_drv = to_auxiliary_drv(aux_dev->dev.driver);
- ports_owner = container_of(aux_drv, struct ice_ptp_port_owner,
- aux_driver);
- owner_ptp = container_of(ports_owner, struct ice_ptp, ports_owner);
- return container_of(owner_ptp, struct ice_pf, ptp);
-}
-
-/**
- * ice_ptp_auxbus_probe - Probe auxiliary devices
- * @aux_dev: PF's auxiliary device
- * @id: Auxiliary device ID
- */
-static int ice_ptp_auxbus_probe(struct auxiliary_device *aux_dev,
- const struct auxiliary_device_id *id)
-{
- struct ice_pf *owner_pf = ice_ptp_aux_dev_to_owner_pf(aux_dev);
- struct ice_pf *aux_pf = ice_ptp_aux_dev_to_aux_pf(aux_dev);
-
- if (WARN_ON(!owner_pf))
- return -ENODEV;
-
- INIT_LIST_HEAD(&aux_pf->ptp.port.list_member);
- mutex_lock(&owner_pf->ptp.ports_owner.lock);
- list_add(&aux_pf->ptp.port.list_member,
- &owner_pf->ptp.ports_owner.ports);
- mutex_unlock(&owner_pf->ptp.ports_owner.lock);
+ pf->adapter->ctrl_pf = pf;
return 0;
}
-/**
- * ice_ptp_auxbus_remove - Remove auxiliary devices from the bus
- * @aux_dev: PF's auxiliary device
- */
-static void ice_ptp_auxbus_remove(struct auxiliary_device *aux_dev)
+static int ice_ptp_setup_pf(struct ice_pf *pf)
{
- struct ice_pf *owner_pf = ice_ptp_aux_dev_to_owner_pf(aux_dev);
- struct ice_pf *aux_pf = ice_ptp_aux_dev_to_aux_pf(aux_dev);
+ struct ice_ptp *ctrl_ptp = ice_get_ctrl_ptp(pf);
+ struct ice_ptp *ptp = &pf->ptp;
- mutex_lock(&owner_pf->ptp.ports_owner.lock);
- list_del(&aux_pf->ptp.port.list_member);
- mutex_unlock(&owner_pf->ptp.ports_owner.lock);
-}
+ if (WARN_ON(!ctrl_ptp) || ice_get_phy_model(&pf->hw) == ICE_PHY_UNSUP)
+ return -ENODEV;
-/**
- * ice_ptp_auxbus_shutdown
- * @aux_dev: PF's auxiliary device
- */
-static void ice_ptp_auxbus_shutdown(struct auxiliary_device *aux_dev)
-{
- /* Doing nothing here, but handle to auxbus driver must be satisfied */
-}
+ INIT_LIST_HEAD(&ptp->port.list_node);
+ mutex_lock(&pf->adapter->ports.lock);
-/**
- * ice_ptp_auxbus_suspend
- * @aux_dev: PF's auxiliary device
- * @state: power management state indicator
- */
-static int
-ice_ptp_auxbus_suspend(struct auxiliary_device *aux_dev, pm_message_t state)
-{
- /* Doing nothing here, but handle to auxbus driver must be satisfied */
- return 0;
-}
+ list_add(&ptp->port.list_node,
+ &pf->adapter->ports.ports);
+ mutex_unlock(&pf->adapter->ports.lock);
-/**
- * ice_ptp_auxbus_resume
- * @aux_dev: PF's auxiliary device
- */
-static int ice_ptp_auxbus_resume(struct auxiliary_device *aux_dev)
-{
- /* Doing nothing here, but handle to auxbus driver must be satisfied */
return 0;
}
-/**
- * ice_ptp_auxbus_create_id_table - Create auxiliary device ID table
- * @pf: Board private structure
- * @name: auxiliary bus driver name
- */
-static struct auxiliary_device_id *
-ice_ptp_auxbus_create_id_table(struct ice_pf *pf, const char *name)
+static void ice_ptp_cleanup_pf(struct ice_pf *pf)
{
- struct auxiliary_device_id *ids;
-
- /* Second id left empty to terminate the array */
- ids = devm_kcalloc(ice_pf_to_dev(pf), 2,
- sizeof(struct auxiliary_device_id), GFP_KERNEL);
- if (!ids)
- return NULL;
-
- snprintf(ids[0].name, sizeof(ids[0].name), "ice.%s", name);
-
- return ids;
-}
-
-/**
- * ice_ptp_register_auxbus_driver - Register PTP auxiliary bus driver
- * @pf: Board private structure
- */
-static int ice_ptp_register_auxbus_driver(struct ice_pf *pf)
-{
- struct auxiliary_driver *aux_driver;
- struct ice_ptp *ptp;
- struct device *dev;
- char *name;
- int err;
-
- ptp = &pf->ptp;
- dev = ice_pf_to_dev(pf);
- aux_driver = &ptp->ports_owner.aux_driver;
- INIT_LIST_HEAD(&ptp->ports_owner.ports);
- mutex_init(&ptp->ports_owner.lock);
- name = devm_kasprintf(dev, GFP_KERNEL, "ptp_aux_dev_%u_%u_clk%u",
- pf->pdev->bus->number, PCI_SLOT(pf->pdev->devfn),
- ice_get_ptp_src_clock_index(&pf->hw));
- if (!name)
- return -ENOMEM;
-
- aux_driver->name = name;
- aux_driver->shutdown = ice_ptp_auxbus_shutdown;
- aux_driver->suspend = ice_ptp_auxbus_suspend;
- aux_driver->remove = ice_ptp_auxbus_remove;
- aux_driver->resume = ice_ptp_auxbus_resume;
- aux_driver->probe = ice_ptp_auxbus_probe;
- aux_driver->id_table = ice_ptp_auxbus_create_id_table(pf, name);
- if (!aux_driver->id_table)
- return -ENOMEM;
+ struct ice_ptp *ptp = &pf->ptp;
- err = auxiliary_driver_register(aux_driver);
- if (err) {
- devm_kfree(dev, aux_driver->id_table);
- dev_err(dev, "Failed registering aux_driver, name <%s>\n",
- name);
+ if (ice_get_phy_model(&pf->hw) != ICE_PHY_UNSUP) {
+ mutex_lock(&pf->adapter->ports.lock);
+ list_del(&ptp->port.list_node);
+ mutex_unlock(&pf->adapter->ports.lock);
}
-
- return err;
-}
-
-/**
- * ice_ptp_unregister_auxbus_driver - Unregister PTP auxiliary bus driver
- * @pf: Board private structure
- */
-static void ice_ptp_unregister_auxbus_driver(struct ice_pf *pf)
-{
- struct auxiliary_driver *aux_driver = &pf->ptp.ports_owner.aux_driver;
-
- auxiliary_driver_unregister(aux_driver);
- devm_kfree(ice_pf_to_dev(pf), aux_driver->id_table);
-
- mutex_destroy(&pf->ptp.ports_owner.lock);
}
/**
@@ -3087,15 +2993,12 @@ static void ice_ptp_unregister_auxbus_driver(struct ice_pf *pf)
*/
int ice_ptp_clock_index(struct ice_pf *pf)
{
- struct auxiliary_device *aux_dev;
- struct ice_pf *owner_pf;
+ struct ice_ptp *ctrl_ptp = ice_get_ctrl_ptp(pf);
struct ptp_clock *clock;
- aux_dev = &pf->ptp.port.aux_dev;
- owner_pf = ice_ptp_aux_dev_to_owner_pf(aux_dev);
- if (!owner_pf)
+ if (!ctrl_ptp)
return -1;
- clock = owner_pf->ptp.clock;
+ clock = ctrl_ptp->clock;
return clock ? ptp_clock_index(clock) : -1;
}
@@ -3155,15 +3058,7 @@ static int ice_ptp_init_owner(struct ice_pf *pf)
if (err)
goto err_clk;
- err = ice_ptp_register_auxbus_driver(pf);
- if (err) {
- dev_err(ice_pf_to_dev(pf), "Failed to register PTP auxbus driver");
- goto err_aux;
- }
-
return 0;
-err_aux:
- ptp_clock_unregister(pf->ptp.clock);
err_clk:
pf->ptp.clock = NULL;
err_exit:
@@ -3209,7 +3104,7 @@ static int ice_ptp_init_port(struct ice_pf *pf, struct ice_ptp_port *ptp_port)
mutex_init(&ptp_port->ps_lock);
- switch (hw->ptp.phy_model) {
+ switch (ice_get_phy_model(hw)) {
case ICE_PHY_ETH56G:
return ice_ptp_init_tx_eth56g(pf, &ptp_port->tx,
ptp_port->port_num);
@@ -3227,76 +3122,6 @@ static int ice_ptp_init_port(struct ice_pf *pf, struct ice_ptp_port *ptp_port)
}
/**
- * ice_ptp_release_auxbus_device
- * @dev: device that utilizes the auxbus
- */
-static void ice_ptp_release_auxbus_device(struct device *dev)
-{
- /* Doing nothing here, but handle to auxbux device must be satisfied */
-}
-
-/**
- * ice_ptp_create_auxbus_device - Create PTP auxiliary bus device
- * @pf: Board private structure
- */
-static int ice_ptp_create_auxbus_device(struct ice_pf *pf)
-{
- struct auxiliary_device *aux_dev;
- struct ice_ptp *ptp;
- struct device *dev;
- char *name;
- int err;
- u32 id;
-
- ptp = &pf->ptp;
- id = ptp->port.port_num;
- dev = ice_pf_to_dev(pf);
-
- aux_dev = &ptp->port.aux_dev;
-
- name = devm_kasprintf(dev, GFP_KERNEL, "ptp_aux_dev_%u_%u_clk%u",
- pf->pdev->bus->number, PCI_SLOT(pf->pdev->devfn),
- ice_get_ptp_src_clock_index(&pf->hw));
- if (!name)
- return -ENOMEM;
-
- aux_dev->name = name;
- aux_dev->id = id;
- aux_dev->dev.release = ice_ptp_release_auxbus_device;
- aux_dev->dev.parent = dev;
-
- err = auxiliary_device_init(aux_dev);
- if (err)
- goto aux_err;
-
- err = auxiliary_device_add(aux_dev);
- if (err) {
- auxiliary_device_uninit(aux_dev);
- goto aux_err;
- }
-
- return 0;
-aux_err:
- dev_err(dev, "Failed to create PTP auxiliary bus device <%s>\n", name);
- devm_kfree(dev, name);
- return err;
-}
-
-/**
- * ice_ptp_remove_auxbus_device - Remove PTP auxiliary bus device
- * @pf: Board private structure
- */
-static void ice_ptp_remove_auxbus_device(struct ice_pf *pf)
-{
- struct auxiliary_device *aux_dev = &pf->ptp.port.aux_dev;
-
- auxiliary_device_delete(aux_dev);
- auxiliary_device_uninit(aux_dev);
-
- memset(aux_dev, 0, sizeof(*aux_dev));
-}
-
-/**
* ice_ptp_init_tx_interrupt_mode - Initialize device Tx interrupt mode
* @pf: Board private structure
*
@@ -3307,7 +3132,7 @@ static void ice_ptp_remove_auxbus_device(struct ice_pf *pf)
*/
static void ice_ptp_init_tx_interrupt_mode(struct ice_pf *pf)
{
- switch (pf->hw.ptp.phy_model) {
+ switch (ice_get_phy_model(&pf->hw)) {
case ICE_PHY_E82X:
/* E822 based PHY has the clock owner process the interrupt
* for all ports.
@@ -3350,19 +3175,26 @@ void ice_ptp_init(struct ice_pf *pf)
/* If this function owns the clock hardware, it must allocate and
* configure the PTP clock device to represent it.
*/
- if (ice_pf_src_tmr_owned(pf)) {
+ if (ice_pf_src_tmr_owned(pf) && ice_is_primary(hw)) {
+ err = ice_ptp_setup_adapter(pf);
+ if (err)
+ goto err_exit;
err = ice_ptp_init_owner(pf);
if (err)
- goto err;
+ goto err_exit;
}
+ err = ice_ptp_setup_pf(pf);
+ if (err)
+ goto err_exit;
+
ptp->port.port_num = hw->pf_id;
if (ice_is_e825c(hw) && hw->ptp.is_2x50g_muxed_topo)
ptp->port.port_num = hw->pf_id * 2;
err = ice_ptp_init_port(pf, &ptp->port);
if (err)
- goto err;
+ goto err_exit;
/* Start the PHY timestamping block */
ice_ptp_reset_phy_timestamping(pf);
@@ -3370,20 +3202,16 @@ void ice_ptp_init(struct ice_pf *pf)
/* Configure initial Tx interrupt settings */
ice_ptp_cfg_tx_interrupt(pf);
- err = ice_ptp_create_auxbus_device(pf);
- if (err)
- goto err;
-
ptp->state = ICE_PTP_READY;
err = ice_ptp_init_work(pf, ptp);
if (err)
- goto err;
+ goto err_exit;
dev_info(ice_pf_to_dev(pf), "PTP init successful\n");
return;
-err:
+err_exit:
/* If we registered a PTP clock, release it */
if (pf->ptp.clock) {
ptp_clock_unregister(ptp->clock);
@@ -3410,7 +3238,7 @@ void ice_ptp_release(struct ice_pf *pf)
/* Disable timestamping for both Tx and Rx */
ice_ptp_disable_timestamp_mode(pf);
- ice_ptp_remove_auxbus_device(pf);
+ ice_ptp_cleanup_pf(pf);
ice_ptp_release_tx_tracker(pf, &pf->ptp.port.tx);
@@ -3425,14 +3253,11 @@ void ice_ptp_release(struct ice_pf *pf)
pf->ptp.kworker = NULL;
}
- if (ice_pf_src_tmr_owned(pf))
- ice_ptp_unregister_auxbus_driver(pf);
-
if (!pf->ptp.clock)
return;
/* Disable periodic outputs */
- ice_ptp_disable_all_clkout(pf);
+ ice_ptp_disable_all_perout(pf);
ptp_clock_unregister(pf->ptp.clock);
pf->ptp.clock = NULL;
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h
index 2db2257a0fb2..824e73b677a4 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.h
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.h
@@ -9,37 +9,6 @@
#include "ice_ptp_hw.h"
-enum ice_ptp_pin_e810 {
- GPIO_20 = 0,
- GPIO_21,
- GPIO_22,
- GPIO_23,
- NUM_PTP_PIN_E810
-};
-
-enum ice_ptp_pin_e810t {
- GNSS = 0,
- SMA1,
- UFL1,
- SMA2,
- UFL2,
- NUM_PTP_PINS_E810T
-};
-
-struct ice_perout_channel {
- bool ena;
- u32 gpio_pin;
- u32 flags;
- u64 period;
- u64 start_time;
-};
-
-struct ice_extts_channel {
- bool ena;
- u32 gpio_pin;
- u32 flags;
-};
-
/* The ice hardware captures Tx hardware timestamps in the PHY. The timestamp
* is stored in a buffer of registers. Depending on the specific hardware,
* this buffer might be shared across multiple PHY ports.
@@ -169,9 +138,8 @@ struct ice_ptp_tx {
* ready for PTP functionality. It is used to track the port initialization
* and determine when the port's PHY offset is valid.
*
- * @list_member: list member structure of auxiliary device
+ * @list_node: list member structure
* @tx: Tx timestamp tracking for this port
- * @aux_dev: auxiliary device associated with this port
* @ov_work: delayed work task for tracking when PHY offset is valid
* @ps_lock: mutex used to protect the overall PTP PHY start procedure
* @link_up: indicates whether the link is up
@@ -179,9 +147,8 @@ struct ice_ptp_tx {
* @port_num: the port number this structure represents
*/
struct ice_ptp_port {
- struct list_head list_member;
+ struct list_head list_node;
struct ice_ptp_tx tx;
- struct auxiliary_device aux_dev;
struct kthread_delayed_work ov_work;
struct mutex ps_lock; /* protects overall PTP PHY start procedure */
bool link_up;
@@ -195,22 +162,6 @@ enum ice_ptp_tx_interrupt {
ICE_PTP_TX_INTERRUPT_ALL,
};
-/**
- * struct ice_ptp_port_owner - data used to handle the PTP clock owner info
- *
- * This structure contains data necessary for the PTP clock owner to correctly
- * handle the timestamping feature for all attached ports.
- *
- * @aux_driver: the structure carring the auxiliary driver information
- * @ports: list of porst handled by this port owner
- * @lock: protect access to ports list
- */
-struct ice_ptp_port_owner {
- struct auxiliary_driver aux_driver;
- struct list_head ports;
- struct mutex lock;
-};
-
#define GLTSYN_TGT_H_IDX_MAX 4
enum ice_ptp_state {
@@ -221,20 +172,69 @@ enum ice_ptp_state {
ICE_PTP_ERROR,
};
+enum ice_ptp_pin {
+ SDP0 = 0,
+ SDP1,
+ SDP2,
+ SDP3,
+ TIME_SYNC,
+ ONE_PPS
+};
+
+enum ice_ptp_pin_nvm {
+ GNSS = 0,
+ SMA1,
+ UFL1,
+ SMA2,
+ UFL2,
+ NUM_PTP_PINS_NVM,
+ GPIO_NA = 9
+};
+
+/* Per-channel register definitions */
+#define GLTSYN_AUX_OUT(_chan, _idx) (GLTSYN_AUX_OUT_0(_idx) + ((_chan) * 8))
+#define GLTSYN_AUX_IN(_chan, _idx) (GLTSYN_AUX_IN_0(_idx) + ((_chan) * 8))
+#define GLTSYN_CLKO(_chan, _idx) (GLTSYN_CLKO_0(_idx) + ((_chan) * 8))
+#define GLTSYN_TGT_L(_chan, _idx) (GLTSYN_TGT_L_0(_idx) + ((_chan) * 16))
+#define GLTSYN_TGT_H(_chan, _idx) (GLTSYN_TGT_H_0(_idx) + ((_chan) * 16))
+#define GLTSYN_EVNT_L(_chan, _idx) (GLTSYN_EVNT_L_0(_idx) + ((_chan) * 16))
+#define GLTSYN_EVNT_H(_chan, _idx) (GLTSYN_EVNT_H_0(_idx) + ((_chan) * 16))
+#define GLTSYN_EVNT_H_IDX_MAX 3
+
+/* Pin definitions for PTP */
+#define ICE_N_PINS_MAX 6
+#define ICE_SMA_PINS_NUM 4
+#define ICE_PIN_DESC_ARR_LEN(_arr) (sizeof(_arr) / \
+ sizeof(struct ice_ptp_pin_desc))
+
+/**
+ * struct ice_ptp_pin_desc - hardware pin description data
+ * @name_idx: index of the name of pin in ice_pin_names
+ * @gpio: the associated GPIO input and output pins
+ *
+ * Structure describing a PTP-capable GPIO pin that extends ptp_pin_desc array
+ * for the device. Device families have separate sets of available pins with
+ * varying restrictions.
+ */
+struct ice_ptp_pin_desc {
+ int name_idx;
+ int gpio[2];
+};
+
/**
* struct ice_ptp - data used for integrating with CONFIG_PTP_1588_CLOCK
* @state: current state of PTP state machine
* @tx_interrupt_mode: the TX interrupt mode for the PTP clock
* @port: data for the PHY port initialization procedure
- * @ports_owner: data for the auxiliary driver owner
* @work: delayed work function for periodic tasks
* @cached_phc_time: a cached copy of the PHC time for timestamp extension
* @cached_phc_jiffies: jiffies when cached_phc_time was last updated
- * @ext_ts_chan: the external timestamp channel in use
- * @ext_ts_irq: the external timestamp IRQ in use
* @kworker: kwork thread for handling periodic work
- * @perout_channels: periodic output data
- * @extts_channels: channels for external timestamps
+ * @ext_ts_irq: the external timestamp IRQ in use
+ * @pin_desc: structure defining pins
+ * @ice_pin_desc: internal structure describing pin relations
+ * @perout_rqs: cached periodic output requests
+ * @extts_rqs: cached external timestamp requests
* @info: structure defining PTP hardware capabilities
* @clock: pointer to registered PTP clock device
* @tstamp_config: hardware timestamping configuration
@@ -250,15 +250,15 @@ struct ice_ptp {
enum ice_ptp_state state;
enum ice_ptp_tx_interrupt tx_interrupt_mode;
struct ice_ptp_port port;
- struct ice_ptp_port_owner ports_owner;
struct kthread_delayed_work work;
u64 cached_phc_time;
unsigned long cached_phc_jiffies;
- u8 ext_ts_chan;
- u8 ext_ts_irq;
struct kthread_worker *kworker;
- struct ice_perout_channel perout_channels[GLTSYN_TGT_H_IDX_MAX];
- struct ice_extts_channel extts_channels[GLTSYN_TGT_H_IDX_MAX];
+ u8 ext_ts_irq;
+ struct ptp_pin_desc pin_desc[ICE_N_PINS_MAX];
+ const struct ice_ptp_pin_desc *ice_pin_desc;
+ struct ptp_perout_request perout_rqs[GLTSYN_TGT_H_IDX_MAX];
+ struct ptp_extts_request extts_rqs[GLTSYN_EVNT_H_IDX_MAX];
struct ptp_clock_info info;
struct ptp_clock *clock;
struct hwtstamp_config tstamp_config;
@@ -289,27 +289,6 @@ struct ice_ptp {
#define FIFO_EMPTY BIT(2)
#define FIFO_OK 0xFF
#define ICE_PTP_FIFO_NUM_CHECKS 5
-/* Per-channel register definitions */
-#define GLTSYN_AUX_OUT(_chan, _idx) (GLTSYN_AUX_OUT_0(_idx) + ((_chan) * 8))
-#define GLTSYN_AUX_IN(_chan, _idx) (GLTSYN_AUX_IN_0(_idx) + ((_chan) * 8))
-#define GLTSYN_CLKO(_chan, _idx) (GLTSYN_CLKO_0(_idx) + ((_chan) * 8))
-#define GLTSYN_TGT_L(_chan, _idx) (GLTSYN_TGT_L_0(_idx) + ((_chan) * 16))
-#define GLTSYN_TGT_H(_chan, _idx) (GLTSYN_TGT_H_0(_idx) + ((_chan) * 16))
-#define GLTSYN_EVNT_L(_chan, _idx) (GLTSYN_EVNT_L_0(_idx) + ((_chan) * 16))
-#define GLTSYN_EVNT_H(_chan, _idx) (GLTSYN_EVNT_H_0(_idx) + ((_chan) * 16))
-#define GLTSYN_EVNT_H_IDX_MAX 3
-
-/* Pin definitions for PTP PPS out */
-#define PPS_CLK_GEN_CHAN 3
-#define PPS_CLK_SRC_CHAN 2
-#define PPS_PIN_INDEX 5
-#define TIME_SYNC_PIN_INDEX 4
-#define N_EXT_TS_E810 3
-#define N_PER_OUT_E810 4
-#define N_PER_OUT_E810T 3
-#define N_PER_OUT_NO_SMA_E810T 2
-#define N_EXT_TS_NO_SMA_E810T 2
-#define ETH_GLTSYN_ENA(_i) (0x03000348 + ((_i) * 4))
#if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
int ice_ptp_clock_index(struct ice_pf *pf);
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_consts.h b/drivers/net/ethernet/intel/ice/ice_ptp_consts.h
index e6980b94a6c1..585ce200c60f 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp_consts.h
+++ b/drivers/net/ethernet/intel/ice/ice_ptp_consts.h
@@ -334,7 +334,7 @@ struct ice_eth56g_mac_reg_cfg eth56g_mac_cfg[NUM_ICE_ETH56G_LNK_SPD] = {
* reference. See the struct ice_time_ref_info_e82x for information about the
* meaning of each constant.
*/
-const struct ice_time_ref_info_e82x e822_time_ref[NUM_ICE_TIME_REF_FREQ] = {
+const struct ice_time_ref_info_e82x e82x_time_ref[NUM_ICE_TIME_REF_FREQ] = {
/* ICE_TIME_REF_FREQ_25_000 -> 25 MHz */
{
/* pll_freq */
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
index 3a33e6b9b313..da88c6ccfaeb 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
@@ -661,6 +661,29 @@ static int ice_cfg_cgu_pll_e825c(struct ice_hw *hw,
return 0;
}
+#define ICE_ONE_PPS_OUT_AMP_MAX 3
+
+/**
+ * ice_cgu_cfg_pps_out - Configure 1PPS output from CGU
+ * @hw: pointer to the HW struct
+ * @enable: true to enable 1PPS output, false to disable it
+ *
+ * Return: 0 on success, other negative error code when CGU read/write failed
+ */
+int ice_cgu_cfg_pps_out(struct ice_hw *hw, bool enable)
+{
+ union nac_cgu_dword9 dw9;
+ int err;
+
+ err = ice_read_cgu_reg_e82x(hw, NAC_CGU_DWORD9, &dw9.val);
+ if (err)
+ return err;
+
+ dw9.one_pps_out_en = enable;
+ dw9.one_pps_out_amp = enable * ICE_ONE_PPS_OUT_AMP_MAX;
+ return ice_write_cgu_reg_e82x(hw, NAC_CGU_DWORD9, dw9.val);
+}
+
/**
* ice_cfg_cgu_pll_dis_sticky_bits_e82x - disable TS PLL sticky bits
* @hw: pointer to the HW struct
@@ -806,7 +829,7 @@ static u32 ice_ptp_tmr_cmd_to_port_reg(struct ice_hw *hw,
/* Certain hardware families share the same register values for the
* port register and source timer register.
*/
- switch (hw->ptp.phy_model) {
+ switch (ice_get_phy_model(hw)) {
case ICE_PHY_E810:
return ice_ptp_tmr_cmd_to_src_reg(hw, cmd) & TS_CMD_MASK_E810;
default:
@@ -5150,9 +5173,9 @@ ice_get_phy_tx_tstamp_ready_e810(struct ice_hw *hw, u8 port, u64 *tstamp_ready)
return 0;
}
-/* E810T SMA functions
+/* E810 SMA functions
*
- * The following functions operate specifically on E810T hardware and are used
+ * The following functions operate specifically on E810 hardware and are used
* to access the extended GPIOs available.
*/
@@ -5219,14 +5242,14 @@ ice_get_pca9575_handle(struct ice_hw *hw, u16 *pca9575_handle)
}
/**
- * ice_read_sma_ctrl_e810t
+ * ice_read_sma_ctrl
* @hw: pointer to the hw struct
* @data: pointer to data to be read from the GPIO controller
*
* Read the SMA controller state. It is connected to pins 3-7 of Port 1 of the
* PCA9575 expander, so only bits 3-7 in data are valid.
*/
-int ice_read_sma_ctrl_e810t(struct ice_hw *hw, u8 *data)
+int ice_read_sma_ctrl(struct ice_hw *hw, u8 *data)
{
int status;
u16 handle;
@@ -5238,7 +5261,7 @@ int ice_read_sma_ctrl_e810t(struct ice_hw *hw, u8 *data)
*data = 0;
- for (i = ICE_SMA_MIN_BIT_E810T; i <= ICE_SMA_MAX_BIT_E810T; i++) {
+ for (i = ICE_SMA_MIN_BIT; i <= ICE_SMA_MAX_BIT; i++) {
bool pin;
status = ice_aq_get_gpio(hw, handle, i + ICE_PCA9575_P1_OFFSET,
@@ -5252,14 +5275,14 @@ int ice_read_sma_ctrl_e810t(struct ice_hw *hw, u8 *data)
}
/**
- * ice_write_sma_ctrl_e810t
+ * ice_write_sma_ctrl
* @hw: pointer to the hw struct
* @data: data to be written to the GPIO controller
*
* Write the data to the SMA controller. It is connected to pins 3-7 of Port 1
* of the PCA9575 expander, so only bits 3-7 in data are valid.
*/
-int ice_write_sma_ctrl_e810t(struct ice_hw *hw, u8 data)
+int ice_write_sma_ctrl(struct ice_hw *hw, u8 data)
{
int status;
u16 handle;
@@ -5269,7 +5292,7 @@ int ice_write_sma_ctrl_e810t(struct ice_hw *hw, u8 data)
if (status)
return status;
- for (i = ICE_SMA_MIN_BIT_E810T; i <= ICE_SMA_MAX_BIT_E810T; i++) {
+ for (i = ICE_SMA_MIN_BIT; i <= ICE_SMA_MAX_BIT; i++) {
bool pin;
pin = !(data & (1 << i));
@@ -5283,14 +5306,14 @@ int ice_write_sma_ctrl_e810t(struct ice_hw *hw, u8 data)
}
/**
- * ice_read_pca9575_reg_e810t
+ * ice_read_pca9575_reg
* @hw: pointer to the hw struct
* @offset: GPIO controller register offset
* @data: pointer to data to be read from the GPIO controller
*
* Read the register from the GPIO controller
*/
-int ice_read_pca9575_reg_e810t(struct ice_hw *hw, u8 offset, u8 *data)
+int ice_read_pca9575_reg(struct ice_hw *hw, u8 offset, u8 *data)
{
struct ice_aqc_link_topo_addr link_topo;
__le16 addr;
@@ -5314,6 +5337,66 @@ int ice_read_pca9575_reg_e810t(struct ice_hw *hw, u8 offset, u8 *data)
}
/**
+ * ice_ptp_read_sdp_ac - read SDP available connections section from NVM
+ * @hw: pointer to the HW struct
+ * @entries: returns the SDP available connections section from NVM
+ * @num_entries: returns the number of valid entries
+ *
+ * Return: 0 on success, negative error code if NVM read failed or section does
+ * not exist or is corrupted
+ */
+int ice_ptp_read_sdp_ac(struct ice_hw *hw, __le16 *entries, uint *num_entries)
+{
+ __le16 data;
+ u32 offset;
+ int err;
+
+ err = ice_acquire_nvm(hw, ICE_RES_READ);
+ if (err)
+ goto exit;
+
+ /* Read the offset of SDP_AC */
+ offset = ICE_AQC_NVM_SDP_AC_PTR_OFFSET;
+ err = ice_aq_read_nvm(hw, 0, offset, sizeof(data), &data, false, true,
+ NULL);
+ if (err)
+ goto exit;
+
+ /* Check if section exist */
+ offset = FIELD_GET(ICE_AQC_NVM_SDP_AC_PTR_M, le16_to_cpu(data));
+ if (offset == ICE_AQC_NVM_SDP_AC_PTR_INVAL) {
+ err = -EINVAL;
+ goto exit;
+ }
+
+ if (offset & ICE_AQC_NVM_SDP_AC_PTR_TYPE_M) {
+ offset &= ICE_AQC_NVM_SDP_AC_PTR_M;
+ offset *= ICE_AQC_NVM_SECTOR_UNIT;
+ } else {
+ offset *= sizeof(data);
+ }
+
+ /* Skip reading section length and read the number of valid entries */
+ offset += sizeof(data);
+ err = ice_aq_read_nvm(hw, 0, offset, sizeof(data), &data, false, true,
+ NULL);
+ if (err)
+ goto exit;
+ *num_entries = le16_to_cpu(data);
+
+ /* Read SDP configuration section */
+ offset += sizeof(data);
+ err = ice_aq_read_nvm(hw, 0, offset, *num_entries * sizeof(data),
+ entries, false, true, NULL);
+
+exit:
+ if (err)
+ dev_dbg(ice_hw_to_dev(hw), "Failed to configure SDP connection section\n");
+ ice_release_nvm(hw);
+ return err;
+}
+
+/**
* ice_ptp_init_phy_e810 - initialize PHY parameters
* @ptp: pointer to the PTP HW struct
*/
@@ -5419,7 +5502,7 @@ void ice_ptp_init_hw(struct ice_hw *hw)
static int ice_ptp_write_port_cmd(struct ice_hw *hw, u8 port,
enum ice_ptp_tmr_cmd cmd)
{
- switch (hw->ptp.phy_model) {
+ switch (ice_get_phy_model(hw)) {
case ICE_PHY_ETH56G:
return ice_ptp_write_port_cmd_eth56g(hw, port, cmd);
case ICE_PHY_E82X:
@@ -5484,7 +5567,7 @@ static int ice_ptp_port_cmd(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd)
u32 port;
/* PHY models which can program all ports simultaneously */
- switch (hw->ptp.phy_model) {
+ switch (ice_get_phy_model(hw)) {
case ICE_PHY_E810:
return ice_ptp_port_cmd_e810(hw, cmd);
default:
@@ -5563,7 +5646,7 @@ int ice_ptp_init_time(struct ice_hw *hw, u64 time)
/* PHY timers */
/* Fill Rx and Tx ports and send msg to PHY */
- switch (hw->ptp.phy_model) {
+ switch (ice_get_phy_model(hw)) {
case ICE_PHY_ETH56G:
err = ice_ptp_prep_phy_time_eth56g(hw,
(u32)(time & 0xFFFFFFFF));
@@ -5609,7 +5692,7 @@ int ice_ptp_write_incval(struct ice_hw *hw, u64 incval)
wr32(hw, GLTSYN_SHADJ_L(tmr_idx), lower_32_bits(incval));
wr32(hw, GLTSYN_SHADJ_H(tmr_idx), upper_32_bits(incval));
- switch (hw->ptp.phy_model) {
+ switch (ice_get_phy_model(hw)) {
case ICE_PHY_ETH56G:
err = ice_ptp_prep_phy_incval_eth56g(hw, incval);
break;
@@ -5678,7 +5761,7 @@ int ice_ptp_adj_clock(struct ice_hw *hw, s32 adj)
wr32(hw, GLTSYN_SHADJ_L(tmr_idx), 0);
wr32(hw, GLTSYN_SHADJ_H(tmr_idx), adj);
- switch (hw->ptp.phy_model) {
+ switch (ice_get_phy_model(hw)) {
case ICE_PHY_ETH56G:
err = ice_ptp_prep_phy_adj_eth56g(hw, adj);
break;
@@ -5711,7 +5794,7 @@ int ice_ptp_adj_clock(struct ice_hw *hw, s32 adj)
*/
int ice_read_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx, u64 *tstamp)
{
- switch (hw->ptp.phy_model) {
+ switch (ice_get_phy_model(hw)) {
case ICE_PHY_ETH56G:
return ice_read_ptp_tstamp_eth56g(hw, block, idx, tstamp);
case ICE_PHY_E810:
@@ -5741,7 +5824,7 @@ int ice_read_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx, u64 *tstamp)
*/
int ice_clear_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx)
{
- switch (hw->ptp.phy_model) {
+ switch (ice_get_phy_model(hw)) {
case ICE_PHY_ETH56G:
return ice_clear_ptp_tstamp_eth56g(hw, block, idx);
case ICE_PHY_E810:
@@ -5804,7 +5887,7 @@ static int ice_get_pf_c827_idx(struct ice_hw *hw, u8 *idx)
*/
void ice_ptp_reset_ts_memory(struct ice_hw *hw)
{
- switch (hw->ptp.phy_model) {
+ switch (ice_get_phy_model(hw)) {
case ICE_PHY_ETH56G:
ice_ptp_reset_ts_memory_eth56g(hw);
break;
@@ -5833,7 +5916,7 @@ int ice_ptp_init_phc(struct ice_hw *hw)
/* Clear event err indications for auxiliary pins */
(void)rd32(hw, GLTSYN_STAT(src_idx));
- switch (hw->ptp.phy_model) {
+ switch (ice_get_phy_model(hw)) {
case ICE_PHY_ETH56G:
return ice_ptp_init_phc_eth56g(hw);
case ICE_PHY_E810:
@@ -5858,7 +5941,7 @@ int ice_ptp_init_phc(struct ice_hw *hw)
*/
int ice_get_phy_tx_tstamp_ready(struct ice_hw *hw, u8 block, u64 *tstamp_ready)
{
- switch (hw->ptp.phy_model) {
+ switch (ice_get_phy_model(hw)) {
case ICE_PHY_ETH56G:
return ice_get_phy_tx_tstamp_ready_eth56g(hw, block,
tstamp_ready);
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h
index 0852a34ade91..1a61d4826271 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h
+++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h
@@ -316,7 +316,7 @@ ice_cgu_pll_params_e825c e825c_cgu_params[NUM_ICE_TIME_REF_FREQ];
extern const struct ice_phy_reg_info_eth56g eth56g_phy_res[NUM_ETH56G_PHY_RES];
/* Table of constants related to possible TIME_REF sources */
-extern const struct ice_time_ref_info_e82x e822_time_ref[NUM_ICE_TIME_REF_FREQ];
+extern const struct ice_time_ref_info_e82x e82x_time_ref[NUM_ICE_TIME_REF_FREQ];
/* Table of constants for Vernier calibration on E822 */
extern const struct ice_vernier_info_e82x e822_vernier[NUM_ICE_PTP_LNK_SPD];
@@ -326,10 +326,12 @@ extern const struct ice_vernier_info_e82x e822_vernier[NUM_ICE_PTP_LNK_SPD];
*/
#define ICE_E810_PLL_FREQ 812500000
#define ICE_PTP_NOMINAL_INCVAL_E810 0x13b13b13bULL
-#define E810_OUT_PROP_DELAY_NS 1
+#define ICE_E810_OUT_PROP_DELAY_NS 1
+#define ICE_E825C_OUT_PROP_DELAY_NS 11
/* Device agnostic functions */
u8 ice_get_ptp_src_clock_index(struct ice_hw *hw);
+int ice_cgu_cfg_pps_out(struct ice_hw *hw, bool enable);
bool ice_ptp_lock(struct ice_hw *hw);
void ice_ptp_unlock(struct ice_hw *hw);
void ice_ptp_src_cmd(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd);
@@ -358,7 +360,7 @@ void ice_ptp_reset_ts_memory_quad_e82x(struct ice_hw *hw, u8 quad);
*
* Returns the current TIME_REF from the capabilities structure.
*/
-static inline enum ice_time_ref_freq ice_e82x_time_ref(struct ice_hw *hw)
+static inline enum ice_time_ref_freq ice_e82x_time_ref(const struct ice_hw *hw)
{
return hw->func_caps.ts_func_info.time_ref;
}
@@ -379,17 +381,17 @@ ice_set_e82x_time_ref(struct ice_hw *hw, enum ice_time_ref_freq time_ref)
static inline u64 ice_e82x_pll_freq(enum ice_time_ref_freq time_ref)
{
- return e822_time_ref[time_ref].pll_freq;
+ return e82x_time_ref[time_ref].pll_freq;
}
static inline u64 ice_e82x_nominal_incval(enum ice_time_ref_freq time_ref)
{
- return e822_time_ref[time_ref].nominal_incval;
+ return e82x_time_ref[time_ref].nominal_incval;
}
static inline u64 ice_e82x_pps_delay(enum ice_time_ref_freq time_ref)
{
- return e822_time_ref[time_ref].pps_delay;
+ return e82x_time_ref[time_ref].pps_delay;
}
/* E822 Vernier calibration functions */
@@ -400,10 +402,11 @@ int ice_phy_cfg_rx_offset_e82x(struct ice_hw *hw, u8 port);
int ice_phy_cfg_intr_e82x(struct ice_hw *hw, u8 quad, bool ena, u8 threshold);
/* E810 family functions */
-int ice_read_sma_ctrl_e810t(struct ice_hw *hw, u8 *data);
-int ice_write_sma_ctrl_e810t(struct ice_hw *hw, u8 data);
-int ice_read_pca9575_reg_e810t(struct ice_hw *hw, u8 offset, u8 *data);
+int ice_read_sma_ctrl(struct ice_hw *hw, u8 *data);
+int ice_write_sma_ctrl(struct ice_hw *hw, u8 data);
+int ice_read_pca9575_reg(struct ice_hw *hw, u8 offset, u8 *data);
bool ice_is_pca9575_present(struct ice_hw *hw);
+int ice_ptp_read_sdp_ac(struct ice_hw *hw, __le16 *entries, uint *num_entries);
enum dpll_pin_type ice_cgu_get_pin_type(struct ice_hw *hw, u8 pin, bool input);
struct dpll_pin_frequency *
ice_cgu_get_pin_freq_supp(struct ice_hw *hw, u8 pin, bool input, u8 *num);
@@ -431,6 +434,20 @@ int ice_phy_cfg_ptp_1step_eth56g(struct ice_hw *hw, u8 port);
#define ICE_ETH56G_NOMINAL_THRESH4 0x7777
#define ICE_ETH56G_NOMINAL_TX_THRESH 0x6
+static inline u64 ice_prop_delay(const struct ice_hw *hw)
+{
+ switch (hw->ptp.phy_model) {
+ case ICE_PHY_ETH56G:
+ return ICE_E825C_OUT_PROP_DELAY_NS;
+ case ICE_PHY_E810:
+ return ICE_E810_OUT_PROP_DELAY_NS;
+ case ICE_PHY_E82X:
+ return ice_e82x_pps_delay(ice_e82x_time_ref(hw));
+ default:
+ return 0;
+ }
+}
+
/**
* ice_get_base_incval - Get base clock increment value
* @hw: pointer to the HW struct
@@ -451,6 +468,11 @@ static inline u64 ice_get_base_incval(struct ice_hw *hw)
}
}
+static inline bool ice_is_dual(struct ice_hw *hw)
+{
+ return !!(hw->dev_caps.nac_topo.mode & ICE_NAC_TOPO_DUAL_M);
+}
+
#define PFTSYN_SEM_BYTES 4
#define ICE_PTP_CLOCK_INDEX_0 0x00
@@ -688,30 +710,27 @@ static inline u64 ice_get_base_incval(struct ice_hw *hw)
#define LOW_TX_MEMORY_BANK_START 0x03090000
#define HIGH_TX_MEMORY_BANK_START 0x03090004
-/* E810T SMA controller pin control */
-#define ICE_SMA1_DIR_EN_E810T BIT(4)
-#define ICE_SMA1_TX_EN_E810T BIT(5)
-#define ICE_SMA2_UFL2_RX_DIS_E810T BIT(3)
-#define ICE_SMA2_DIR_EN_E810T BIT(6)
-#define ICE_SMA2_TX_EN_E810T BIT(7)
-
-#define ICE_SMA1_MASK_E810T (ICE_SMA1_DIR_EN_E810T | \
- ICE_SMA1_TX_EN_E810T)
-#define ICE_SMA2_MASK_E810T (ICE_SMA2_UFL2_RX_DIS_E810T | \
- ICE_SMA2_DIR_EN_E810T | \
- ICE_SMA2_TX_EN_E810T)
-#define ICE_ALL_SMA_MASK_E810T (ICE_SMA1_MASK_E810T | \
- ICE_SMA2_MASK_E810T)
-
-#define ICE_SMA_MIN_BIT_E810T 3
-#define ICE_SMA_MAX_BIT_E810T 7
+/* SMA controller pin control */
+#define ICE_SMA1_DIR_EN BIT(4)
+#define ICE_SMA1_TX_EN BIT(5)
+#define ICE_SMA2_UFL2_RX_DIS BIT(3)
+#define ICE_SMA2_DIR_EN BIT(6)
+#define ICE_SMA2_TX_EN BIT(7)
+
+#define ICE_SMA1_MASK (ICE_SMA1_DIR_EN | ICE_SMA1_TX_EN)
+#define ICE_SMA2_MASK (ICE_SMA2_UFL2_RX_DIS | ICE_SMA2_DIR_EN | \
+ ICE_SMA2_TX_EN)
+#define ICE_ALL_SMA_MASK (ICE_SMA1_MASK | ICE_SMA2_MASK)
+
+#define ICE_SMA_MIN_BIT 3
+#define ICE_SMA_MAX_BIT 7
#define ICE_PCA9575_P1_OFFSET 8
-/* E810T PCA9575 IO controller registers */
+/* PCA9575 IO controller registers */
#define ICE_PCA9575_P0_IN 0x0
-/* E810T PCA9575 IO controller pin control */
-#define ICE_E810T_P0_GNSS_PRSNT_N BIT(4)
+/* PCA9575 IO controller pin control */
+#define ICE_P0_GNSS_PRSNT_N BIT(4)
/* ETH56G PHY register addresses */
/* Timestamp PHY incval registers */
diff --git a/drivers/net/ethernet/intel/ice/ice_repr.c b/drivers/net/ethernet/intel/ice/ice_repr.c
index 00d4a9125dfa..970a99a52bf1 100644
--- a/drivers/net/ethernet/intel/ice/ice_repr.c
+++ b/drivers/net/ethernet/intel/ice/ice_repr.c
@@ -452,8 +452,8 @@ struct ice_repr *ice_repr_create_vf(struct ice_vf *vf)
return ERR_PTR(-EINVAL);
repr = ice_repr_create(vsi);
- if (!repr)
- return ERR_PTR(-ENOMEM);
+ if (IS_ERR(repr))
+ return repr;
repr->type = ICE_REPR_TYPE_VF;
repr->vf = vf;
@@ -501,8 +501,8 @@ struct ice_repr *ice_repr_create_sf(struct ice_dynamic_port *sf)
{
struct ice_repr *repr = ice_repr_create(sf->vsi);
- if (!repr)
- return ERR_PTR(-ENOMEM);
+ if (IS_ERR(repr))
+ return repr;
repr->type = ICE_REPR_TYPE_SF;
repr->sf = sf;
diff --git a/drivers/net/ethernet/intel/ice/ice_sf_eth.c b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
index d00389c405c4..75d7147e1c01 100644
--- a/drivers/net/ethernet/intel/ice/ice_sf_eth.c
+++ b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
@@ -108,9 +108,9 @@ static int ice_sf_dev_probe(struct auxiliary_device *adev,
vsi->flags = ICE_VSI_FLAG_INIT;
priv = ice_allocate_sf(&adev->dev, pf);
- if (!priv) {
+ if (IS_ERR(priv)) {
dev_err(dev, "Subfunction devlink alloc failed");
- return -ENOMEM;
+ return PTR_ERR(priv);
}
priv->dev = sf_dev;
diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.h b/drivers/net/ethernet/intel/idpf/idpf_txrx.h
index f0537826f840..9c1fe84108ed 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_txrx.h
+++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.h
@@ -438,7 +438,8 @@ struct idpf_q_vector {
__cacheline_group_end_aligned(cold);
};
libeth_cacheline_set_assert(struct idpf_q_vector, 112,
- 424 + 2 * sizeof(struct dim),
+ 24 + sizeof(struct napi_struct) +
+ 2 * sizeof(struct dim),
8 + sizeof(cpumask_var_t));
struct idpf_rx_queue_stats {