Merge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue

Tony Nguyen says:

====================
Intel Wired LAN Driver Updates 2025-09-19 (ice, idpf, iavf, ixgbevf, fm10k)

Paul adds support for Earliest TxTime First (ETF) hardware offload
for E830 devices on ice. ETF is configured per-queue using tc-etf Qdisc;
a new Tx flow mechanism utilizes a dedicated timestamp ring alongside
the standard Tx ring. The timestamp ring contains descriptors that
specify when hardware should transmit packets; up to 2048 Tx queues can
be supported.

Additional info: https://lore.kernel.org/intel-wired-lan/20250818132257.21720-1-paul.greenwalt@intel.com/

Dave removes excess cleanup call to ice_lag_move_new_vf_nodes() in error
path.

Milena adds reporting of timestamping statistics to idpf.

Alex changes error variable type for code clarity for iavf and ixgbevf.

Brahmajit Das removes unused parameter from fm10k_unbind_hw_stats_q().

* '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue:
  net: intel: fm10k: Fix parameter idx set but not used
  ixgbevf: fix proper type for error code in ixgbevf_resume()
  iavf: fix proper type for error code in iavf_resume()
  idpf: add HW timestamping statistics
  ice: Remove deprecated ice_lag_move_new_vf_nodes() call
  ice: add E830 Earliest TxTime First Offload support
  ice: move ice_qp_[ena|dis] for reuse
====================

Link: https://patch.msgid.link/20250919175412.653707-1-anthony.l.nguyen@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2025-09-22 16:56:30 -07:00
commit dfff18082a
29 changed files with 989 additions and 264 deletions

View File

@ -447,17 +447,16 @@ void fm10k_update_hw_stats_q(struct fm10k_hw *hw, struct fm10k_hw_stats_q *q,
/**
* fm10k_unbind_hw_stats_q - Unbind the queue counters from their queues
* @q: pointer to the ring of hardware statistics queue
* @idx: index pointing to the start of the ring iteration
* @count: number of queues to iterate over
*
* Function invalidates the index values for the queues so any updates that
* may have happened are ignored and the base for the queue stats is reset.
**/
void fm10k_unbind_hw_stats_q(struct fm10k_hw_stats_q *q, u32 idx, u32 count)
void fm10k_unbind_hw_stats_q(struct fm10k_hw_stats_q *q, u32 count)
{
u32 i;
for (i = 0; i < count; i++, idx++, q++) {
for (i = 0; i < count; i++, q++) {
q->rx_stats_idx = 0;
q->tx_stats_idx = 0;
}

View File

@ -43,6 +43,6 @@ u32 fm10k_read_hw_stats_32b(struct fm10k_hw *hw, u32 addr,
void fm10k_update_hw_stats_q(struct fm10k_hw *hw, struct fm10k_hw_stats_q *q,
u32 idx, u32 count);
#define fm10k_unbind_hw_stats_32b(s) ((s)->base_h = 0)
void fm10k_unbind_hw_stats_q(struct fm10k_hw_stats_q *q, u32 idx, u32 count);
void fm10k_unbind_hw_stats_q(struct fm10k_hw_stats_q *q, u32 count);
s32 fm10k_get_host_state_generic(struct fm10k_hw *hw, bool *host_ready);
#endif /* _FM10K_COMMON_H_ */

View File

@ -1389,7 +1389,7 @@ static void fm10k_rebind_hw_stats_pf(struct fm10k_hw *hw,
fm10k_unbind_hw_stats_32b(&stats->nodesc_drop);
/* Unbind Queue Statistics */
fm10k_unbind_hw_stats_q(stats->q, 0, hw->mac.max_queues);
fm10k_unbind_hw_stats_q(stats->q, hw->mac.max_queues);
/* Reinitialize bases for all stats */
fm10k_update_hw_stats_pf(hw, stats);

View File

@ -465,7 +465,7 @@ static void fm10k_rebind_hw_stats_vf(struct fm10k_hw *hw,
struct fm10k_hw_stats *stats)
{
/* Unbind Queue Statistics */
fm10k_unbind_hw_stats_q(stats->q, 0, hw->mac.max_queues);
fm10k_unbind_hw_stats_q(stats->q, hw->mac.max_queues);
/* Reinitialize bases for all stats */
fm10k_update_hw_stats_vf(hw, stats);

View File

@ -5491,7 +5491,7 @@ static int iavf_resume(struct device *dev_d)
{
struct pci_dev *pdev = to_pci_dev(dev_d);
struct iavf_adapter *adapter;
u32 err;
int err;
adapter = iavf_pdev_to_adapter(pdev);

View File

@ -84,7 +84,11 @@
#define ICE_BAR0 0
#define ICE_REQ_DESC_MULTIPLE 32
#define ICE_MIN_NUM_DESC 64
#define ICE_MAX_NUM_DESC 8160
#define ICE_MAX_NUM_DESC_E810 8160
#define ICE_MAX_NUM_DESC_E830 8096
#define ICE_MAX_NUM_DESC_BY_MAC(hw) ((hw)->mac_type == ICE_MAC_E830 ? \
ICE_MAX_NUM_DESC_E830 : \
ICE_MAX_NUM_DESC_E810)
#define ICE_DFLT_MIN_RX_DESC 512
#define ICE_DFLT_NUM_TX_DESC 256
#define ICE_DFLT_NUM_RX_DESC 2048
@ -200,6 +204,7 @@ enum ice_feature {
ICE_F_SMA_CTRL,
ICE_F_CGU,
ICE_F_GNSS,
ICE_F_TXTIME,
ICE_F_GCS,
ICE_F_ROCE_LAG,
ICE_F_SRIOV_LAG,
@ -575,6 +580,7 @@ struct ice_pf {
DECLARE_BITMAP(misc_thread, ICE_MISC_THREAD_NBITS);
unsigned long *avail_txqs; /* bitmap to track PF Tx queue usage */
unsigned long *avail_rxqs; /* bitmap to track PF Rx queue usage */
unsigned long *txtime_txqs; /* bitmap to track PF Tx Time queue */
unsigned long serv_tmr_period;
unsigned long serv_tmr_prev;
struct timer_list serv_tmr;
@ -748,6 +754,31 @@ static inline void ice_set_ring_xdp(struct ice_tx_ring *ring)
ring->flags |= ICE_TX_FLAGS_RING_XDP;
}
/**
* ice_is_txtime_ena - check if Tx Time is enabled on the Tx ring
* @ring: pointer to Tx ring
*
* Return: true if the Tx ring has Tx Time enabled, false otherwise.
*/
static inline bool ice_is_txtime_ena(const struct ice_tx_ring *ring)
{
struct ice_vsi *vsi = ring->vsi;
struct ice_pf *pf = vsi->back;
return test_bit(ring->q_index, pf->txtime_txqs);
}
/**
* ice_is_txtime_cfg - check if Tx Time is configured on the Tx ring
* @ring: pointer to Tx ring
*
* Return: true if the Tx ring is configured for Tx ring, false otherwise.
*/
static inline bool ice_is_txtime_cfg(const struct ice_tx_ring *ring)
{
return !!(ring->flags & ICE_TX_FLAGS_TXTIME);
}
/**
* ice_get_xp_from_qid - get ZC XSK buffer pool bound to a queue ID
* @vsi: pointer to VSI

View File

@ -33,6 +33,10 @@ typedef struct __packed { u8 buf[ICE_TXQ_CTX_SZ]; } ice_txq_ctx_buf_t;
typedef struct __packed { u8 buf[ICE_TXQ_CTX_FULL_SZ]; } ice_txq_ctx_buf_full_t;
#define ICE_TXTIME_CTX_SZ 25
typedef struct __packed { u8 buf[ICE_TXTIME_CTX_SZ]; } ice_txtime_ctx_buf_t;
/* Queue Shutdown (direct 0x0003) */
struct ice_aqc_q_shutdown {
u8 driver_unloading;
@ -2117,6 +2121,34 @@ struct ice_aqc_add_rdma_qset_data {
struct ice_aqc_add_tx_rdma_qset_entry rdma_qsets[];
};
/* Set Tx Time LAN Queue (indirect 0x0C35) */
struct ice_aqc_set_txtimeqs {
__le16 q_id;
__le16 q_amount;
u8 reserved[4];
__le32 addr_high;
__le32 addr_low;
};
/* This is the descriptor of each queue entry for the Set Tx Time Queue
* command (0x0C35). Only used within struct ice_aqc_set_txtime_qgrp.
*/
struct ice_aqc_set_txtimeqs_perq {
u8 reserved[4];
ice_txtime_ctx_buf_t txtime_ctx;
u8 reserved1[3];
};
/* The format of the command buffer for Set Tx Time Queue (0x0C35)
* is an array of the following structs. Please note that the length of
* each struct ice_aqc_set_txtime_qgrp is variable due to the variable
* number of queues in each group!
*/
struct ice_aqc_set_txtime_qgrp {
u8 reserved[8];
struct ice_aqc_set_txtimeqs_perq txtimeqs[];
};
/* Download Package (indirect 0x0C40) */
/* Also used for Update Package (indirect 0x0C41 and 0x0C42) */
struct ice_aqc_download_pkg {
@ -2614,6 +2646,9 @@ enum ice_adminq_opc {
ice_aqc_opc_cfg_txqs = 0x0C32,
ice_aqc_opc_add_rdma_qset = 0x0C33,
/* Tx Time queue commands */
ice_aqc_opc_set_txtimeqs = 0x0C35,
/* package commands */
ice_aqc_opc_download_pkg = 0x0C40,
ice_aqc_opc_upload_section = 0x0C41,

View File

@ -242,7 +242,8 @@ static void ice_cfg_itr_gran(struct ice_hw *hw)
* @ring: ring to get the absolute queue index
* @tc: traffic class number
*/
static u16 ice_calc_txq_handle(struct ice_vsi *vsi, struct ice_tx_ring *ring, u8 tc)
static u16
ice_calc_txq_handle(const struct ice_vsi *vsi, struct ice_tx_ring *ring, u8 tc)
{
WARN_ONCE(ice_ring_is_xdp(ring) && tc, "XDP ring can't belong to TC other than 0\n");
@ -278,30 +279,20 @@ static void ice_cfg_xps_tx_ring(struct ice_tx_ring *ring)
}
/**
* ice_setup_tx_ctx - setup a struct ice_tlan_ctx instance
* @ring: The Tx ring to configure
* @tlan_ctx: Pointer to the Tx LAN queue context structure to be initialized
* @pf_q: queue index in the PF space
* ice_set_txq_ctx_vmvf - set queue context VM/VF type and number by VSI type
* @ring: the Tx ring to configure
* @vmvf_type: VM/VF type
* @vmvf_num: VM/VF number
*
* Configure the Tx descriptor ring in TLAN context.
* Return: 0 on success and a negative value on error.
*/
static void
ice_setup_tx_ctx(struct ice_tx_ring *ring, struct ice_tlan_ctx *tlan_ctx, u16 pf_q)
static int
ice_set_txq_ctx_vmvf(struct ice_tx_ring *ring, u8 *vmvf_type, u16 *vmvf_num)
{
struct ice_vsi *vsi = ring->vsi;
struct ice_hw *hw = &vsi->back->hw;
struct ice_hw *hw;
tlan_ctx->base = ring->dma >> ICE_TLAN_CTX_BASE_S;
tlan_ctx->port_num = vsi->port_info->lport;
/* Transmit Queue Length */
tlan_ctx->qlen = ring->count;
ice_set_cgd_num(tlan_ctx, ring->dcb_tc);
/* PF number */
tlan_ctx->pf_num = hw->pf_id;
hw = &vsi->back->hw;
/* queue belongs to a specific VSI type
* VF / VM index should be programmed per vmvf_type setting:
@ -314,21 +305,60 @@ ice_setup_tx_ctx(struct ice_tx_ring *ring, struct ice_tlan_ctx *tlan_ctx, u16 pf
case ICE_VSI_CTRL:
case ICE_VSI_PF:
if (ring->ch)
tlan_ctx->vmvf_type = ICE_TLAN_CTX_VMVF_TYPE_VMQ;
*vmvf_type = ICE_TLAN_CTX_VMVF_TYPE_VMQ;
else
tlan_ctx->vmvf_type = ICE_TLAN_CTX_VMVF_TYPE_PF;
*vmvf_type = ICE_TLAN_CTX_VMVF_TYPE_PF;
break;
case ICE_VSI_VF:
/* Firmware expects vmvf_num to be absolute VF ID */
tlan_ctx->vmvf_num = hw->func_caps.vf_base_id + vsi->vf->vf_id;
tlan_ctx->vmvf_type = ICE_TLAN_CTX_VMVF_TYPE_VF;
*vmvf_num = hw->func_caps.vf_base_id + vsi->vf->vf_id;
*vmvf_type = ICE_TLAN_CTX_VMVF_TYPE_VF;
break;
case ICE_VSI_SF:
tlan_ctx->vmvf_type = ICE_TLAN_CTX_VMVF_TYPE_VMQ;
*vmvf_type = ICE_TLAN_CTX_VMVF_TYPE_VMQ;
break;
default:
return;
dev_info(ice_pf_to_dev(vsi->back),
"Unable to set VMVF type for VSI type %d\n",
vsi->type);
return -EINVAL;
}
return 0;
}
/**
* ice_setup_tx_ctx - setup a struct ice_tlan_ctx instance
* @ring: the Tx ring to configure
* @tlan_ctx: pointer to the Tx LAN queue context structure to be initialized
* @pf_q: queue index in the PF space
*
* Configure the Tx descriptor ring in TLAN context.
*
* Return: 0 on success and a negative value on error.
*/
static int
ice_setup_tx_ctx(struct ice_tx_ring *ring, struct ice_tlan_ctx *tlan_ctx, u16 pf_q)
{
struct ice_vsi *vsi = ring->vsi;
struct ice_hw *hw;
int err;
hw = &vsi->back->hw;
tlan_ctx->base = ring->dma >> ICE_TLAN_CTX_BASE_S;
tlan_ctx->port_num = vsi->port_info->lport;
/* Transmit Queue Length */
tlan_ctx->qlen = ring->count;
ice_set_cgd_num(tlan_ctx, ring->dcb_tc);
/* PF number */
tlan_ctx->pf_num = hw->pf_id;
err = ice_set_txq_ctx_vmvf(ring, &tlan_ctx->vmvf_type,
&tlan_ctx->vmvf_num);
if (err)
return err;
/* make sure the context is associated with the right VSI */
if (ring->ch)
@ -355,6 +385,80 @@ ice_setup_tx_ctx(struct ice_tx_ring *ring, struct ice_tlan_ctx *tlan_ctx, u16 pf
* 1: Legacy Host Interface
*/
tlan_ctx->legacy_int = ICE_TX_LEGACY;
return 0;
}
/**
* ice_setup_txtime_ctx - setup a struct ice_txtime_ctx instance
* @ring: the tstamp ring to configure
* @txtime_ctx: pointer to the Tx time queue context structure to be initialized
*
* Return: 0 on success and a negative value on error.
*/
static int
ice_setup_txtime_ctx(const struct ice_tstamp_ring *ring,
struct ice_txtime_ctx *txtime_ctx)
{
struct ice_tx_ring *tx_ring = ring->tx_ring;
struct ice_vsi *vsi = tx_ring->vsi;
struct ice_hw *hw = &vsi->back->hw;
int err;
txtime_ctx->base = ring->dma >> ICE_TXTIME_CTX_BASE_S;
/* Tx time Queue Length */
txtime_ctx->qlen = ring->count;
txtime_ctx->txtime_ena_q = 1;
/* PF number */
txtime_ctx->pf_num = hw->pf_id;
err = ice_set_txq_ctx_vmvf(tx_ring, &txtime_ctx->vmvf_type,
&txtime_ctx->vmvf_num);
if (err)
return err;
/* make sure the context is associated with the right VSI */
if (tx_ring->ch)
txtime_ctx->src_vsi = tx_ring->ch->vsi_num;
else
txtime_ctx->src_vsi = ice_get_hw_vsi_num(hw, vsi->idx);
txtime_ctx->ts_res = ICE_TXTIME_CTX_RESOLUTION_128NS;
txtime_ctx->drbell_mode_32 = ICE_TXTIME_CTX_DRBELL_MODE_32;
txtime_ctx->ts_fetch_prof_id = ICE_TXTIME_CTX_FETCH_PROF_ID_0;
return 0;
}
/**
* ice_calc_ts_ring_count - calculate the number of Tx time stamp descriptors
* @tx_ring: Tx ring to calculate the count for
*
* Return: the number of Tx time stamp descriptors.
*/
u16 ice_calc_ts_ring_count(struct ice_tx_ring *tx_ring)
{
u16 prof = ICE_TXTIME_CTX_FETCH_PROF_ID_0;
struct ice_vsi *vsi = tx_ring->vsi;
struct ice_hw *hw = &vsi->back->hw;
u16 max_fetch_desc = 0, fetch, i;
u32 reg;
for (i = 0; i < ICE_TXTIME_FETCH_PROFILE_CNT; i++) {
reg = rd32(hw, E830_GLTXTIME_FETCH_PROFILE(prof, 0));
fetch = FIELD_GET(E830_GLTXTIME_FETCH_PROFILE_FETCH_TS_DESC_M,
reg);
max_fetch_desc = max(fetch, max_fetch_desc);
}
if (!max_fetch_desc)
max_fetch_desc = ICE_TXTIME_FETCH_TS_DESC_DFLT;
max_fetch_desc = ALIGN(max_fetch_desc, ICE_REQ_DESC_MULTIPLE);
return tx_ring->count + max_fetch_desc;
}
/**
@ -881,14 +985,50 @@ void ice_vsi_free_q_vectors(struct ice_vsi *vsi)
vsi->num_q_vectors = 0;
}
/**
* ice_cfg_tstamp - Configure Tx time stamp queue
* @tx_ring: Tx ring to be configured with timestamping
*
* Return: 0 on success and a negative value on error.
*/
static int
ice_cfg_tstamp(struct ice_tx_ring *tx_ring)
{
DEFINE_RAW_FLEX(struct ice_aqc_set_txtime_qgrp, txtime_qg_buf,
txtimeqs, 1);
u8 txtime_buf_len = struct_size(txtime_qg_buf, txtimeqs, 1);
struct ice_tstamp_ring *tstamp_ring = tx_ring->tstamp_ring;
struct ice_txtime_ctx txtime_ctx = {};
struct ice_vsi *vsi = tx_ring->vsi;
struct ice_pf *pf = vsi->back;
struct ice_hw *hw = &pf->hw;
u16 pf_q = tx_ring->reg_idx;
int err;
err = ice_setup_txtime_ctx(tstamp_ring, &txtime_ctx);
if (err) {
dev_err(ice_pf_to_dev(pf), "Failed to setup Tx time queue context for queue %d, error: %d\n",
pf_q, err);
return err;
}
ice_pack_txtime_ctx(&txtime_ctx,
&txtime_qg_buf->txtimeqs[0].txtime_ctx);
tstamp_ring->tail = hw->hw_addr + E830_GLQTX_TXTIME_DBELL_LSB(pf_q);
return ice_aq_set_txtimeq(hw, pf_q, 1, txtime_qg_buf,
txtime_buf_len, NULL);
}
/**
* ice_vsi_cfg_txq - Configure single Tx queue
* @vsi: the VSI that queue belongs to
* @ring: Tx ring to be configured
* @qg_buf: queue group buffer
*
* Return: 0 on success and a negative value on error.
*/
static int
ice_vsi_cfg_txq(struct ice_vsi *vsi, struct ice_tx_ring *ring,
ice_vsi_cfg_txq(const struct ice_vsi *vsi, struct ice_tx_ring *ring,
struct ice_aqc_add_tx_qgrp *qg_buf)
{
u8 buf_len = struct_size(qg_buf, txqs, 1);
@ -897,15 +1037,20 @@ ice_vsi_cfg_txq(struct ice_vsi *vsi, struct ice_tx_ring *ring,
struct ice_channel *ch = ring->ch;
struct ice_pf *pf = vsi->back;
struct ice_hw *hw = &pf->hw;
u32 pf_q, vsi_idx;
int status;
u16 pf_q;
u8 tc;
/* Configure XPS */
ice_cfg_xps_tx_ring(ring);
pf_q = ring->reg_idx;
ice_setup_tx_ctx(ring, &tlan_ctx, pf_q);
status = ice_setup_tx_ctx(ring, &tlan_ctx, pf_q);
if (status) {
dev_err(ice_pf_to_dev(pf), "Failed to setup Tx context for queue %d, error: %d\n",
pf_q, status);
return status;
}
/* copy context contents into the qg_buf */
qg_buf->txqs[0].txq_id = cpu_to_le16(pf_q);
ice_pack_txq_ctx(&tlan_ctx, &qg_buf->txqs[0].txq_ctx);
@ -925,14 +1070,15 @@ ice_vsi_cfg_txq(struct ice_vsi *vsi, struct ice_tx_ring *ring,
*/
ring->q_handle = ice_calc_txq_handle(vsi, ring, tc);
if (ch)
status = ice_ena_vsi_txq(vsi->port_info, ch->ch_vsi->idx, 0,
ring->q_handle, 1, qg_buf, buf_len,
NULL);
else
status = ice_ena_vsi_txq(vsi->port_info, vsi->idx, tc,
ring->q_handle, 1, qg_buf, buf_len,
NULL);
if (ch) {
tc = 0;
vsi_idx = ch->ch_vsi->idx;
} else {
vsi_idx = vsi->idx;
}
status = ice_ena_vsi_txq(vsi->port_info, vsi_idx, tc, ring->q_handle,
1, qg_buf, buf_len, NULL);
if (status) {
dev_err(ice_pf_to_dev(pf), "Failed to set LAN Tx queue context, error: %d\n",
status);
@ -947,7 +1093,32 @@ ice_vsi_cfg_txq(struct ice_vsi *vsi, struct ice_tx_ring *ring,
if (pf_q == le16_to_cpu(txq->txq_id))
ring->txq_teid = le32_to_cpu(txq->q_teid);
if (ice_is_txtime_ena(ring)) {
status = ice_alloc_setup_tstamp_ring(ring);
if (status) {
dev_err(ice_pf_to_dev(pf),
"Failed to allocate Tx timestamp ring, error: %d\n",
status);
goto err_setup_tstamp;
}
status = ice_cfg_tstamp(ring);
if (status) {
dev_err(ice_pf_to_dev(pf), "Failed to set Tx Time queue context, error: %d\n",
status);
goto err_cfg_tstamp;
}
}
return 0;
err_cfg_tstamp:
ice_free_tx_tstamp_ring(ring);
err_setup_tstamp:
ice_dis_vsi_txq(vsi->port_info, vsi_idx, tc, 1, &ring->q_handle,
&ring->reg_idx, &ring->txq_teid, ICE_NO_RESET,
tlan_ctx.vmvf_num, NULL);
return status;
}
int ice_vsi_cfg_single_txq(struct ice_vsi *vsi, struct ice_tx_ring **tx_rings,
@ -1206,3 +1377,148 @@ ice_fill_txq_meta(const struct ice_vsi *vsi, struct ice_tx_ring *ring,
txq_meta->tc = tc;
}
}
/**
* ice_qp_reset_stats - Resets all stats for rings of given index
* @vsi: VSI that contains rings of interest
* @q_idx: ring index in array
*/
static void ice_qp_reset_stats(struct ice_vsi *vsi, u16 q_idx)
{
struct ice_vsi_stats *vsi_stat;
struct ice_pf *pf;
pf = vsi->back;
if (!pf->vsi_stats)
return;
vsi_stat = pf->vsi_stats[vsi->idx];
if (!vsi_stat)
return;
memset(&vsi_stat->rx_ring_stats[q_idx]->rx_stats, 0,
sizeof(vsi_stat->rx_ring_stats[q_idx]->rx_stats));
memset(&vsi_stat->tx_ring_stats[q_idx]->stats, 0,
sizeof(vsi_stat->tx_ring_stats[q_idx]->stats));
if (vsi->xdp_rings)
memset(&vsi->xdp_rings[q_idx]->ring_stats->stats, 0,
sizeof(vsi->xdp_rings[q_idx]->ring_stats->stats));
}
/**
* ice_qp_clean_rings - Cleans all the rings of a given index
* @vsi: VSI that contains rings of interest
* @q_idx: ring index in array
*/
static void ice_qp_clean_rings(struct ice_vsi *vsi, u16 q_idx)
{
ice_clean_tx_ring(vsi->tx_rings[q_idx]);
if (vsi->xdp_rings)
ice_clean_tx_ring(vsi->xdp_rings[q_idx]);
ice_clean_rx_ring(vsi->rx_rings[q_idx]);
}
/**
* ice_qp_dis - Disables a queue pair
* @vsi: VSI of interest
* @q_idx: ring index in array
*
* Returns 0 on success, negative on failure.
*/
int ice_qp_dis(struct ice_vsi *vsi, u16 q_idx)
{
struct ice_txq_meta txq_meta = { };
struct ice_q_vector *q_vector;
struct ice_tx_ring *tx_ring;
struct ice_rx_ring *rx_ring;
int fail = 0;
int err;
if (q_idx >= vsi->num_rxq || q_idx >= vsi->num_txq)
return -EINVAL;
tx_ring = vsi->tx_rings[q_idx];
rx_ring = vsi->rx_rings[q_idx];
q_vector = rx_ring->q_vector;
synchronize_net();
netif_carrier_off(vsi->netdev);
netif_tx_stop_queue(netdev_get_tx_queue(vsi->netdev, q_idx));
ice_qvec_dis_irq(vsi, rx_ring, q_vector);
ice_qvec_toggle_napi(vsi, q_vector, false);
ice_fill_txq_meta(vsi, tx_ring, &txq_meta);
err = ice_vsi_stop_tx_ring(vsi, ICE_NO_RESET, 0, tx_ring, &txq_meta);
if (!fail)
fail = err;
if (vsi->xdp_rings) {
struct ice_tx_ring *xdp_ring = vsi->xdp_rings[q_idx];
memset(&txq_meta, 0, sizeof(txq_meta));
ice_fill_txq_meta(vsi, xdp_ring, &txq_meta);
err = ice_vsi_stop_tx_ring(vsi, ICE_NO_RESET, 0, xdp_ring,
&txq_meta);
if (!fail)
fail = err;
}
ice_vsi_ctrl_one_rx_ring(vsi, false, q_idx, false);
ice_qp_clean_rings(vsi, q_idx);
ice_qp_reset_stats(vsi, q_idx);
return fail;
}
/**
* ice_qp_ena - Enables a queue pair
* @vsi: VSI of interest
* @q_idx: ring index in array
*
* Returns 0 on success, negative on failure.
*/
int ice_qp_ena(struct ice_vsi *vsi, u16 q_idx)
{
struct ice_q_vector *q_vector;
int fail = 0;
bool link_up;
int err;
err = ice_vsi_cfg_single_txq(vsi, vsi->tx_rings, q_idx);
if (!fail)
fail = err;
if (ice_is_xdp_ena_vsi(vsi)) {
struct ice_tx_ring *xdp_ring = vsi->xdp_rings[q_idx];
err = ice_vsi_cfg_single_txq(vsi, vsi->xdp_rings, q_idx);
if (!fail)
fail = err;
ice_set_ring_xdp(xdp_ring);
ice_tx_xsk_pool(vsi, q_idx);
}
err = ice_vsi_cfg_single_rxq(vsi, q_idx);
if (!fail)
fail = err;
q_vector = vsi->rx_rings[q_idx]->q_vector;
ice_qvec_cfg_msix(vsi, q_vector, q_idx);
err = ice_vsi_ctrl_one_rx_ring(vsi, true, q_idx, true);
if (!fail)
fail = err;
ice_qvec_toggle_napi(vsi, q_vector, true);
ice_qvec_ena_irq(vsi, q_vector);
/* make sure NAPI sees updated ice_{t,x}_ring::xsk_pool */
synchronize_net();
ice_get_link_status(vsi->port_info, &link_up);
if (link_up) {
netif_tx_start_queue(netdev_get_tx_queue(vsi->netdev, q_idx));
netif_carrier_on(vsi->netdev);
}
return fail;
}

View File

@ -32,4 +32,7 @@ ice_vsi_stop_tx_ring(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src,
void
ice_fill_txq_meta(const struct ice_vsi *vsi, struct ice_tx_ring *ring,
struct ice_txq_meta *txq_meta);
int ice_qp_ena(struct ice_vsi *vsi, u16 q_idx);
int ice_qp_dis(struct ice_vsi *vsi, u16 q_idx);
u16 ice_calc_ts_ring_count(struct ice_tx_ring *tx_ring);
#endif /* _ICE_BASE_H_ */

View File

@ -1733,6 +1733,44 @@ int ice_write_txq_ctx(struct ice_hw *hw, struct ice_tlan_ctx *tlan_ctx,
return 0;
}
/* Tx time Queue Context */
static const struct packed_field_u8 ice_txtime_ctx_fields[] = {
/* Field Width LSB */
ICE_CTX_STORE(ice_txtime_ctx, base, 57, 0),
ICE_CTX_STORE(ice_txtime_ctx, pf_num, 3, 57),
ICE_CTX_STORE(ice_txtime_ctx, vmvf_num, 10, 60),
ICE_CTX_STORE(ice_txtime_ctx, vmvf_type, 2, 70),
ICE_CTX_STORE(ice_txtime_ctx, src_vsi, 10, 72),
ICE_CTX_STORE(ice_txtime_ctx, cpuid, 8, 82),
ICE_CTX_STORE(ice_txtime_ctx, tphrd_desc, 1, 90),
ICE_CTX_STORE(ice_txtime_ctx, qlen, 13, 91),
ICE_CTX_STORE(ice_txtime_ctx, timer_num, 1, 104),
ICE_CTX_STORE(ice_txtime_ctx, txtime_ena_q, 1, 105),
ICE_CTX_STORE(ice_txtime_ctx, drbell_mode_32, 1, 106),
ICE_CTX_STORE(ice_txtime_ctx, ts_res, 4, 107),
ICE_CTX_STORE(ice_txtime_ctx, ts_round_type, 2, 111),
ICE_CTX_STORE(ice_txtime_ctx, ts_pacing_slot, 3, 113),
ICE_CTX_STORE(ice_txtime_ctx, merging_ena, 1, 116),
ICE_CTX_STORE(ice_txtime_ctx, ts_fetch_prof_id, 4, 117),
ICE_CTX_STORE(ice_txtime_ctx, ts_fetch_cache_line_aln_thld, 4, 121),
ICE_CTX_STORE(ice_txtime_ctx, tx_pipe_delay_mode, 1, 125),
};
/**
* ice_pack_txtime_ctx - pack Tx time queue context into a HW buffer
* @ctx: the Tx time queue context to pack
* @buf: the HW buffer to pack into
*
* Pack the Tx time queue context from the CPU-friendly unpacked buffer into
* its bit-packed HW layout.
*/
void ice_pack_txtime_ctx(const struct ice_txtime_ctx *ctx,
ice_txtime_ctx_buf_t *buf)
{
pack_fields(buf, sizeof(*buf), ctx, ice_txtime_ctx_fields,
QUIRK_LITTLE_ENDIAN | QUIRK_LSW32_IS_FIRST);
}
/* Sideband Queue command wrappers */
/**
@ -4846,6 +4884,46 @@ ice_aq_add_rdma_qsets(struct ice_hw *hw, u8 num_qset_grps,
return ice_aq_send_cmd(hw, &desc, qset_list, buf_size, cd);
}
/**
* ice_aq_set_txtimeq - set Tx time queues
* @hw: pointer to the hardware structure
* @txtimeq: first Tx time queue id to configure
* @q_count: number of queues to configure
* @txtime_qg: queue group to be set
* @buf_size: size of buffer for indirect command
* @cd: pointer to command details structure or NULL
*
* Set Tx Time queue (0x0C35)
* Return: 0 on success or negative value on failure.
*/
int
ice_aq_set_txtimeq(struct ice_hw *hw, u16 txtimeq, u8 q_count,
struct ice_aqc_set_txtime_qgrp *txtime_qg, u16 buf_size,
struct ice_sq_cd *cd)
{
struct ice_aqc_set_txtimeqs *cmd;
struct libie_aq_desc desc;
u16 size;
if (!txtime_qg || txtimeq > ICE_TXTIME_MAX_QUEUE ||
q_count < 1 || q_count > ICE_SET_TXTIME_MAX_Q_AMOUNT)
return -EINVAL;
size = struct_size(txtime_qg, txtimeqs, q_count);
if (buf_size != size)
return -EINVAL;
cmd = libie_aq_raw(&desc);
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_txtimeqs);
desc.flags |= cpu_to_le16(LIBIE_AQ_FLAG_RD);
cmd->q_id = cpu_to_le16(txtimeq);
cmd->q_amount = cpu_to_le16(q_count);
return ice_aq_send_cmd(hw, &desc, txtime_qg, buf_size, cd);
}
/* End of FW Admin Queue command wrappers */
/**

View File

@ -275,6 +275,12 @@ int ice_replay_vsi(struct ice_hw *hw, u16 vsi_handle);
void ice_replay_post(struct ice_hw *hw);
struct ice_q_ctx *
ice_get_lan_q_ctx(struct ice_hw *hw, u16 vsi_handle, u8 tc, u16 q_handle);
int
ice_aq_set_txtimeq(struct ice_hw *hw, u16 txtimeq, u8 q_count,
struct ice_aqc_set_txtime_qgrp *txtime_qg,
u16 buf_size, struct ice_sq_cd *cd);
void ice_pack_txtime_ctx(const struct ice_txtime_ctx *ctx,
ice_txtime_ctx_buf_t *buf);
int ice_sbq_rw_reg(struct ice_hw *hw, struct ice_sbq_msg_input *in, u16 flag);
int ice_aq_get_cgu_input_pin_measure(struct ice_hw *hw, u8 dpll_idx,
struct ice_cgu_input_measure *meas,

View File

@ -3147,9 +3147,11 @@ ice_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring,
{
struct ice_netdev_priv *np = netdev_priv(netdev);
struct ice_vsi *vsi = np->vsi;
struct ice_hw *hw;
ring->rx_max_pending = ICE_MAX_NUM_DESC;
ring->tx_max_pending = ICE_MAX_NUM_DESC;
hw = &vsi->back->hw;
ring->rx_max_pending = ICE_MAX_NUM_DESC_BY_MAC(hw);
ring->tx_max_pending = ICE_MAX_NUM_DESC_BY_MAC(hw);
if (vsi->tx_rings && vsi->rx_rings) {
ring->rx_pending = vsi->rx_rings[0]->count;
ring->tx_pending = vsi->tx_rings[0]->count;
@ -3177,15 +3179,16 @@ ice_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring,
struct ice_vsi *vsi = np->vsi;
struct ice_pf *pf = vsi->back;
int i, timeout = 50, err = 0;
struct ice_hw *hw = &pf->hw;
u16 new_rx_cnt, new_tx_cnt;
if (ring->tx_pending > ICE_MAX_NUM_DESC ||
if (ring->tx_pending > ICE_MAX_NUM_DESC_BY_MAC(hw) ||
ring->tx_pending < ICE_MIN_NUM_DESC ||
ring->rx_pending > ICE_MAX_NUM_DESC ||
ring->rx_pending > ICE_MAX_NUM_DESC_BY_MAC(hw) ||
ring->rx_pending < ICE_MIN_NUM_DESC) {
netdev_err(netdev, "Descriptors requested (Tx: %d / Rx: %d) out of range [%d-%d] (increment %d)\n",
ring->tx_pending, ring->rx_pending,
ICE_MIN_NUM_DESC, ICE_MAX_NUM_DESC,
ICE_MIN_NUM_DESC, ICE_MAX_NUM_DESC_BY_MAC(hw),
ICE_REQ_DESC_MULTIPLE);
return -EINVAL;
}
@ -3258,6 +3261,7 @@ ice_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring,
tx_rings[i].count = new_tx_cnt;
tx_rings[i].desc = NULL;
tx_rings[i].tx_buf = NULL;
tx_rings[i].tstamp_ring = NULL;
tx_rings[i].tx_tstamps = &pf->ptp.port.tx;
err = ice_setup_tx_ring(&tx_rings[i]);
if (err) {

View File

@ -19,6 +19,7 @@
#define QTX_COMM_HEAD_MAX_INDEX 16383
#define QTX_COMM_HEAD_HEAD_S 0
#define QTX_COMM_HEAD_HEAD_M ICE_M(0x1FFF, 0)
#define E830_GLQTX_TXTIME_DBELL_LSB(_DBQM) (0x002E0000 + ((_DBQM) * 8))
#define PF_FW_ARQBAH 0x00080180
#define PF_FW_ARQBAL 0x00080080
#define PF_FW_ARQH 0x00080380
@ -571,6 +572,8 @@
#define E830_PFPTM_SEM_BUSY_M BIT(0)
#define VFINT_DYN_CTLN(_i) (0x00003800 + ((_i) * 4))
#define VFINT_DYN_CTLN_CLEARPBA_M BIT(1)
#define E830_GLTXTIME_FETCH_PROFILE(_i, _j) (0x002D3500 + ((_i) * 4 + (_j) * 64))
#define E830_GLTXTIME_FETCH_PROFILE_FETCH_TS_DESC_M ICE_M(0x1FF, 0)
#define E830_MBX_PF_IN_FLIGHT_VF_MSGS_THRESH 0x00234000
#define E830_MBX_VF_DEC_TRIG(_VF) (0x00233800 + (_VF) * 4)
#define E830_MBX_VF_IN_FLIGHT_MSGS_AT_PF_CNT(_VF) (0x00233000 + (_VF) * 4)

View File

@ -789,61 +789,6 @@ ice_lag_move_single_vf_nodes(struct ice_lag *lag, u8 oldport, u8 newport,
ice_lag_move_vf_node_tc(lag, oldport, newport, vsi_num, tc);
}
/**
* ice_lag_move_new_vf_nodes - Move Tx scheduling nodes for a VF if required
* @vf: the VF to move Tx nodes for
*
* Called just after configuring new VF queues. Check whether the VF Tx
* scheduling nodes need to be updated to fail over to the active port. If so,
* move them now.
*/
void ice_lag_move_new_vf_nodes(struct ice_vf *vf)
{
struct ice_lag_netdev_list ndlist;
u8 pri_port, act_port;
struct ice_lag *lag;
struct ice_vsi *vsi;
struct ice_pf *pf;
vsi = ice_get_vf_vsi(vf);
if (WARN_ON(!vsi))
return;
if (WARN_ON(vsi->type != ICE_VSI_VF))
return;
pf = vf->pf;
lag = pf->lag;
mutex_lock(&pf->lag_mutex);
if (!lag->bonded)
goto new_vf_unlock;
pri_port = pf->hw.port_info->lport;
act_port = lag->active_port;
if (lag->upper_netdev)
ice_lag_build_netdev_list(lag, &ndlist);
if (lag->bonded && lag->primary && !list_empty(lag->netdev_head)) {
if (lag->bond_aa &&
ice_is_feature_supported(pf, ICE_F_SRIOV_AA_LAG))
ice_lag_aa_failover(lag, ICE_LAGS_IDX, NULL);
if (!lag->bond_aa &&
ice_is_feature_supported(pf, ICE_F_SRIOV_LAG) &&
pri_port != act_port)
ice_lag_move_single_vf_nodes(lag, pri_port, act_port,
vsi->idx);
}
ice_lag_destroy_netdev_list(lag, &ndlist);
new_vf_unlock:
mutex_unlock(&pf->lag_mutex);
}
/**
* ice_lag_move_vf_nodes - move Tx scheduling nodes for all VFs to new port
* @lag: lag info struct

View File

@ -82,7 +82,6 @@ struct ice_lag_work {
} info;
};
void ice_lag_move_new_vf_nodes(struct ice_vf *vf);
void ice_lag_aa_failover(struct ice_lag *lag, u8 dest, struct ice_pf *e_pf);
int ice_init_lag(struct ice_pf *pf);
void ice_deinit_lag(struct ice_pf *pf);

View File

@ -569,4 +569,45 @@ struct ice_tlan_ctx {
u8 pkt_shaper_prof_idx;
};
#define ICE_TXTIME_TX_DESC_IDX_M GENMASK(12, 0)
#define ICE_TXTIME_STAMP_M GENMASK(31, 13)
/* Tx time stamp descriptor */
struct ice_ts_desc {
__le32 tx_desc_idx_tstamp;
};
#define ICE_TS_DESC(R, i) (&(((struct ice_ts_desc *)((R)->desc))[i]))
#define ICE_TXTIME_MAX_QUEUE 2047
#define ICE_SET_TXTIME_MAX_Q_AMOUNT 127
#define ICE_TXTIME_FETCH_TS_DESC_DFLT 8
#define ICE_TXTIME_FETCH_PROFILE_CNT 16
/* Tx Time queue context data */
struct ice_txtime_ctx {
#define ICE_TXTIME_CTX_BASE_S 7
u64 base; /* base is defined in 128-byte units */
u8 pf_num;
u16 vmvf_num;
u8 vmvf_type;
u16 src_vsi;
u8 cpuid;
u8 tphrd_desc;
u16 qlen;
u8 timer_num;
u8 txtime_ena_q;
u8 drbell_mode_32;
#define ICE_TXTIME_CTX_DRBELL_MODE_32 1
u8 ts_res;
#define ICE_TXTIME_CTX_RESOLUTION_128NS 7
u8 ts_round_type;
u8 ts_pacing_slot;
#define ICE_TXTIME_CTX_FETCH_PROF_ID_0 0
u8 merging_ena;
u8 ts_fetch_prof_id;
u8 ts_fetch_cache_line_aln_thld;
u8 tx_pipe_delay_mode;
};
#endif /* _ICE_LAN_TX_RX_H_ */

View File

@ -3950,6 +3950,7 @@ void ice_init_feature_support(struct ice_pf *pf)
if (pf->hw.mac_type == ICE_MAC_E830) {
ice_set_feature_support(pf, ICE_F_MBX_LIMIT);
ice_set_feature_support(pf, ICE_F_GCS);
ice_set_feature_support(pf, ICE_F_TXTIME);
}
}

View File

@ -3969,6 +3969,11 @@ static void ice_deinit_pf(struct ice_pf *pf)
pf->avail_rxqs = NULL;
}
if (pf->txtime_txqs) {
bitmap_free(pf->txtime_txqs);
pf->txtime_txqs = NULL;
}
if (pf->ptp.clock)
ptp_clock_unregister(pf->ptp.clock);
@ -4062,6 +4067,15 @@ static int ice_init_pf(struct ice_pf *pf)
return -ENOMEM;
}
pf->txtime_txqs = bitmap_zalloc(pf->max_pf_txqs, GFP_KERNEL);
if (!pf->txtime_txqs) {
bitmap_free(pf->avail_txqs);
pf->avail_txqs = NULL;
bitmap_free(pf->avail_rxqs);
pf->avail_rxqs = NULL;
return -ENOMEM;
}
mutex_init(&pf->vfs.table_lock);
hash_init(pf->vfs.table);
if (ice_is_feature_supported(pf, ICE_F_MBX_LIMIT))
@ -7484,7 +7498,8 @@ int ice_vsi_open(struct ice_vsi *vsi)
if (err)
goto err_setup_rx;
ice_vsi_cfg_netdev_tc(vsi, vsi->tc_cfg.ena_tc);
if (bitmap_empty(pf->txtime_txqs, pf->max_pf_txqs))
ice_vsi_cfg_netdev_tc(vsi, vsi->tc_cfg.ena_tc);
if (vsi->type == ICE_VSI_PF || vsi->type == ICE_VSI_SF) {
/* Notify the stack of the actual queue counts. */
@ -9273,6 +9288,96 @@ static int ice_setup_tc_mqprio_qdisc(struct net_device *netdev, void *type_data)
return ret;
}
/**
* ice_cfg_txtime - configure Tx Time for the Tx ring
* @tx_ring: pointer to the Tx ring structure
*
* Return: 0 on success, negative value on failure.
*/
static int ice_cfg_txtime(struct ice_tx_ring *tx_ring)
{
int err, timeout = 50;
struct ice_vsi *vsi;
struct device *dev;
struct ice_pf *pf;
u32 queue;
if (!tx_ring)
return -EINVAL;
vsi = tx_ring->vsi;
pf = vsi->back;
while (test_and_set_bit(ICE_CFG_BUSY, pf->state)) {
timeout--;
if (!timeout)
return -EBUSY;
usleep_range(1000, 2000);
}
queue = tx_ring->q_index;
dev = ice_pf_to_dev(pf);
/* Ignore return value, and always attempt to enable queue. */
ice_qp_dis(vsi, queue);
err = ice_qp_ena(vsi, queue);
if (err)
dev_err(dev, "Failed to enable Tx queue %d for TxTime configuration\n",
queue);
clear_bit(ICE_CFG_BUSY, pf->state);
return err;
}
/**
* ice_offload_txtime - set earliest TxTime first
* @netdev: network interface device structure
* @qopt_off: etf queue option offload from the skb to set
*
* Return: 0 on success, negative value on failure.
*/
static int ice_offload_txtime(struct net_device *netdev,
void *qopt_off)
{
struct ice_netdev_priv *np = netdev_priv(netdev);
struct ice_pf *pf = np->vsi->back;
struct tc_etf_qopt_offload *qopt;
struct ice_vsi *vsi = np->vsi;
struct ice_tx_ring *tx_ring;
int ret = 0;
if (!ice_is_feature_supported(pf, ICE_F_TXTIME))
return -EOPNOTSUPP;
qopt = qopt_off;
if (!qopt_off || qopt->queue < 0 || qopt->queue >= vsi->num_txq)
return -EINVAL;
if (qopt->enable)
set_bit(qopt->queue, pf->txtime_txqs);
else
clear_bit(qopt->queue, pf->txtime_txqs);
if (netif_running(vsi->netdev)) {
tx_ring = vsi->tx_rings[qopt->queue];
ret = ice_cfg_txtime(tx_ring);
if (ret)
goto err;
}
netdev_info(netdev, "%s TxTime on queue: %i\n",
str_enable_disable(qopt->enable), qopt->queue);
return 0;
err:
netdev_err(netdev, "Failed to %s TxTime on queue: %i\n",
str_enable_disable(qopt->enable), qopt->queue);
if (qopt->enable)
clear_bit(qopt->queue, pf->txtime_txqs);
return ret;
}
static LIST_HEAD(ice_block_cb_list);
static int
@ -9336,6 +9441,8 @@ ice_setup_tc(struct net_device *netdev, enum tc_setup_type type,
mutex_unlock(&pf->adev_mutex);
}
return err;
case TC_SETUP_QDISC_ETF:
return ice_offload_txtime(netdev, type_data);
default:
return -EOPNOTSUPP;
}

View File

@ -143,6 +143,56 @@ static struct netdev_queue *txring_txq(const struct ice_tx_ring *ring)
return netdev_get_tx_queue(ring->netdev, ring->q_index);
}
/**
* ice_clean_tstamp_ring - clean time stamp ring
* @tx_ring: Tx ring to clean the Time Stamp ring for
*/
static void ice_clean_tstamp_ring(struct ice_tx_ring *tx_ring)
{
struct ice_tstamp_ring *tstamp_ring = tx_ring->tstamp_ring;
u32 size;
if (!tstamp_ring->desc)
return;
size = ALIGN(tstamp_ring->count * sizeof(struct ice_ts_desc),
PAGE_SIZE);
memset(tstamp_ring->desc, 0, size);
tstamp_ring->next_to_use = 0;
}
/**
* ice_free_tstamp_ring - free time stamp resources per queue
* @tx_ring: Tx ring to free the Time Stamp ring for
*/
void ice_free_tstamp_ring(struct ice_tx_ring *tx_ring)
{
struct ice_tstamp_ring *tstamp_ring = tx_ring->tstamp_ring;
u32 size;
if (!tstamp_ring->desc)
return;
ice_clean_tstamp_ring(tx_ring);
size = ALIGN(tstamp_ring->count * sizeof(struct ice_ts_desc),
PAGE_SIZE);
dmam_free_coherent(tx_ring->dev, size, tstamp_ring->desc,
tstamp_ring->dma);
tstamp_ring->desc = NULL;
}
/**
* ice_free_tx_tstamp_ring - free time stamp resources per Tx ring
* @tx_ring: Tx ring to free the Time Stamp ring for
*/
void ice_free_tx_tstamp_ring(struct ice_tx_ring *tx_ring)
{
ice_free_tstamp_ring(tx_ring);
kfree_rcu(tx_ring->tstamp_ring, rcu);
tx_ring->tstamp_ring = NULL;
tx_ring->flags &= ~ICE_TX_FLAGS_TXTIME;
}
/**
* ice_clean_tx_ring - Free any empty Tx buffers
* @tx_ring: ring to be cleaned
@ -181,6 +231,9 @@ void ice_clean_tx_ring(struct ice_tx_ring *tx_ring)
/* cleanup Tx queue statistics */
netdev_tx_reset_queue(txring_txq(tx_ring));
if (ice_is_txtime_cfg(tx_ring))
ice_free_tx_tstamp_ring(tx_ring);
}
/**
@ -331,6 +384,84 @@ static bool ice_clean_tx_irq(struct ice_tx_ring *tx_ring, int napi_budget)
return !!budget;
}
/**
* ice_alloc_tstamp_ring - allocate the Time Stamp ring
* @tx_ring: Tx ring to allocate the Time Stamp ring for
*
* Return: 0 on success, negative on error
*/
static int ice_alloc_tstamp_ring(struct ice_tx_ring *tx_ring)
{
struct ice_tstamp_ring *tstamp_ring;
/* allocate with kzalloc(), free with kfree_rcu() */
tstamp_ring = kzalloc(sizeof(*tstamp_ring), GFP_KERNEL);
if (!tstamp_ring)
return -ENOMEM;
tstamp_ring->tx_ring = tx_ring;
tx_ring->tstamp_ring = tstamp_ring;
tstamp_ring->desc = NULL;
tstamp_ring->count = ice_calc_ts_ring_count(tx_ring);
tx_ring->flags |= ICE_TX_FLAGS_TXTIME;
return 0;
}
/**
* ice_setup_tstamp_ring - allocate the Time Stamp ring
* @tx_ring: Tx ring to set up the Time Stamp ring for
*
* Return: 0 on success, negative on error
*/
static int ice_setup_tstamp_ring(struct ice_tx_ring *tx_ring)
{
struct ice_tstamp_ring *tstamp_ring = tx_ring->tstamp_ring;
struct device *dev = tx_ring->dev;
u32 size;
/* round up to nearest page */
size = ALIGN(tstamp_ring->count * sizeof(struct ice_ts_desc),
PAGE_SIZE);
tstamp_ring->desc = dmam_alloc_coherent(dev, size, &tstamp_ring->dma,
GFP_KERNEL);
if (!tstamp_ring->desc) {
dev_err(dev, "Unable to allocate memory for Time stamp Ring, size=%d\n",
size);
return -ENOMEM;
}
tstamp_ring->next_to_use = 0;
return 0;
}
/**
* ice_alloc_setup_tstamp_ring - Allocate and setup the Time Stamp ring
* @tx_ring: Tx ring to allocate and setup the Time Stamp ring for
*
* Return: 0 on success, negative on error
*/
int ice_alloc_setup_tstamp_ring(struct ice_tx_ring *tx_ring)
{
struct device *dev = tx_ring->dev;
int err;
err = ice_alloc_tstamp_ring(tx_ring);
if (err) {
dev_err(dev, "Unable to allocate Time stamp ring for Tx ring %d\n",
tx_ring->q_index);
return err;
}
err = ice_setup_tstamp_ring(tx_ring);
if (err) {
dev_err(dev, "Unable to setup Time stamp ring for Tx ring %d\n",
tx_ring->q_index);
ice_free_tx_tstamp_ring(tx_ring);
return err;
}
return 0;
}
/**
* ice_setup_tx_ring - Allocate the Tx descriptors
* @tx_ring: the Tx ring to set up
@ -1822,10 +1953,46 @@ ice_tx_map(struct ice_tx_ring *tx_ring, struct ice_tx_buf *first,
/* notify HW of packet */
kick = __netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount,
netdev_xmit_more());
if (kick)
/* notify HW of packet */
writel(i, tx_ring->tail);
if (!kick)
return;
if (ice_is_txtime_cfg(tx_ring)) {
struct ice_tstamp_ring *tstamp_ring = tx_ring->tstamp_ring;
u32 tstamp_count = tstamp_ring->count;
u32 j = tstamp_ring->next_to_use;
struct ice_ts_desc *ts_desc;
struct timespec64 ts;
u32 tstamp;
ts = ktime_to_timespec64(first->skb->tstamp);
tstamp = ts.tv_nsec >> ICE_TXTIME_CTX_RESOLUTION_128NS;
ts_desc = ICE_TS_DESC(tstamp_ring, j);
ts_desc->tx_desc_idx_tstamp = ice_build_tstamp_desc(i, tstamp);
j++;
if (j == tstamp_count) {
u32 fetch = tstamp_count - tx_ring->count;
j = 0;
/* To prevent an MDD, when wrapping the tstamp ring
* create additional TS descriptors equal to the number
* of the fetch TS descriptors value. HW will merge the
* TS descriptors with the same timestamp value into a
* single descriptor.
*/
for (; j < fetch; j++) {
ts_desc = ICE_TS_DESC(tstamp_ring, j);
ts_desc->tx_desc_idx_tstamp =
ice_build_tstamp_desc(i, tstamp);
}
}
tstamp_ring->next_to_use = j;
writel_relaxed(j, tstamp_ring->tail);
} else {
writel_relaxed(i, tx_ring->tail);
}
return;
dma_error:

View File

@ -310,6 +310,16 @@ enum ice_dynamic_itr {
#define ICE_TX_LEGACY 1
/* descriptor ring, associated with a VSI */
struct ice_tstamp_ring {
struct ice_tx_ring *tx_ring; /* Backreference to associated Tx ring */
dma_addr_t dma; /* physical address of ring */
struct rcu_head rcu; /* to avoid race on free */
u8 __iomem *tail;
void *desc;
u16 next_to_use;
u16 count;
} ____cacheline_internodealigned_in_smp;
struct ice_rx_ring {
/* CL1 - 1st cacheline starts here */
void *desc; /* Descriptor ring memory */
@ -402,9 +412,11 @@ struct ice_tx_ring {
spinlock_t tx_lock;
u32 txq_teid; /* Added Tx queue TEID */
/* CL4 - 4th cacheline starts here */
struct ice_tstamp_ring *tstamp_ring;
#define ICE_TX_FLAGS_RING_XDP BIT(0)
#define ICE_TX_FLAGS_RING_VLAN_L2TAG1 BIT(1)
#define ICE_TX_FLAGS_RING_VLAN_L2TAG2 BIT(2)
#define ICE_TX_FLAGS_TXTIME BIT(3)
u8 flags;
u8 dcb_tc; /* Traffic class of ring */
u16 quanta_prof_id;
@ -500,6 +512,7 @@ void ice_clean_tx_ring(struct ice_tx_ring *tx_ring);
void ice_clean_rx_ring(struct ice_rx_ring *rx_ring);
int ice_setup_tx_ring(struct ice_tx_ring *tx_ring);
int ice_setup_rx_ring(struct ice_rx_ring *rx_ring);
int ice_alloc_setup_tstamp_ring(struct ice_tx_ring *tx_ring);
void ice_free_tx_ring(struct ice_tx_ring *tx_ring);
void ice_free_rx_ring(struct ice_rx_ring *rx_ring);
int ice_napi_poll(struct napi_struct *napi, int budget);
@ -508,4 +521,6 @@ ice_prgm_fdir_fltr(struct ice_vsi *vsi, struct ice_fltr_desc *fdir_desc,
u8 *raw_packet);
void ice_clean_ctrl_tx_irq(struct ice_tx_ring *tx_ring);
void ice_clean_ctrl_rx_irq(struct ice_rx_ring *rx_ring);
void ice_free_tx_tstamp_ring(struct ice_tx_ring *tx_ring);
void ice_free_tstamp_ring(struct ice_tx_ring *tx_ring);
#endif /* _ICE_TXRX_H_ */

View File

@ -53,6 +53,20 @@ ice_build_ctob(u64 td_cmd, u64 td_offset, unsigned int size, u64 td_tag)
(td_tag << ICE_TXD_QW1_L2TAG1_S));
}
/**
* ice_build_tstamp_desc - build Tx time stamp descriptor
* @tx_desc: Tx LAN descriptor index
* @tstamp: time stamp
*
* Return: Tx time stamp descriptor
*/
static inline __le32
ice_build_tstamp_desc(u16 tx_desc, u32 tstamp)
{
return cpu_to_le32(FIELD_PREP(ICE_TXTIME_TX_DESC_IDX_M, tx_desc) |
FIELD_PREP(ICE_TXTIME_STAMP_M, tstamp));
}
/**
* ice_get_vlan_tci - get VLAN TCI from Rx flex descriptor
* @rx_desc: Rx 32b flex descriptor with RXDID=2

View File

@ -18,53 +18,13 @@ static struct xdp_buff **ice_xdp_buf(struct ice_rx_ring *rx_ring, u32 idx)
return &rx_ring->xdp_buf[idx];
}
/**
* ice_qp_reset_stats - Resets all stats for rings of given index
* @vsi: VSI that contains rings of interest
* @q_idx: ring index in array
*/
static void ice_qp_reset_stats(struct ice_vsi *vsi, u16 q_idx)
{
struct ice_vsi_stats *vsi_stat;
struct ice_pf *pf;
pf = vsi->back;
if (!pf->vsi_stats)
return;
vsi_stat = pf->vsi_stats[vsi->idx];
if (!vsi_stat)
return;
memset(&vsi_stat->rx_ring_stats[q_idx]->rx_stats, 0,
sizeof(vsi_stat->rx_ring_stats[q_idx]->rx_stats));
memset(&vsi_stat->tx_ring_stats[q_idx]->stats, 0,
sizeof(vsi_stat->tx_ring_stats[q_idx]->stats));
if (vsi->xdp_rings)
memset(&vsi->xdp_rings[q_idx]->ring_stats->stats, 0,
sizeof(vsi->xdp_rings[q_idx]->ring_stats->stats));
}
/**
* ice_qp_clean_rings - Cleans all the rings of a given index
* @vsi: VSI that contains rings of interest
* @q_idx: ring index in array
*/
static void ice_qp_clean_rings(struct ice_vsi *vsi, u16 q_idx)
{
ice_clean_tx_ring(vsi->tx_rings[q_idx]);
if (vsi->xdp_rings)
ice_clean_tx_ring(vsi->xdp_rings[q_idx]);
ice_clean_rx_ring(vsi->rx_rings[q_idx]);
}
/**
* ice_qvec_toggle_napi - Enables/disables NAPI for a given q_vector
* @vsi: VSI that has netdev
* @q_vector: q_vector that has NAPI context
* @enable: true for enable, false for disable
*/
static void
void
ice_qvec_toggle_napi(struct ice_vsi *vsi, struct ice_q_vector *q_vector,
bool enable)
{
@ -83,7 +43,7 @@ ice_qvec_toggle_napi(struct ice_vsi *vsi, struct ice_q_vector *q_vector,
* @rx_ring: Rx ring that will have its IRQ disabled
* @q_vector: queue vector
*/
static void
void
ice_qvec_dis_irq(struct ice_vsi *vsi, struct ice_rx_ring *rx_ring,
struct ice_q_vector *q_vector)
{
@ -113,7 +73,7 @@ ice_qvec_dis_irq(struct ice_vsi *vsi, struct ice_rx_ring *rx_ring,
* @q_vector: queue vector
* @qid: queue index
*/
static void
void
ice_qvec_cfg_msix(struct ice_vsi *vsi, struct ice_q_vector *q_vector, u16 qid)
{
u16 reg_idx = q_vector->reg_idx;
@ -143,7 +103,7 @@ ice_qvec_cfg_msix(struct ice_vsi *vsi, struct ice_q_vector *q_vector, u16 qid)
* @vsi: the VSI that contains queue vector
* @q_vector: queue vector
*/
static void ice_qvec_ena_irq(struct ice_vsi *vsi, struct ice_q_vector *q_vector)
void ice_qvec_ena_irq(struct ice_vsi *vsi, struct ice_q_vector *q_vector)
{
struct ice_pf *pf = vsi->back;
struct ice_hw *hw = &pf->hw;
@ -153,111 +113,6 @@ static void ice_qvec_ena_irq(struct ice_vsi *vsi, struct ice_q_vector *q_vector)
ice_flush(hw);
}
/**
* ice_qp_dis - Disables a queue pair
* @vsi: VSI of interest
* @q_idx: ring index in array
*
* Returns 0 on success, negative on failure.
*/
static int ice_qp_dis(struct ice_vsi *vsi, u16 q_idx)
{
struct ice_txq_meta txq_meta = { };
struct ice_q_vector *q_vector;
struct ice_tx_ring *tx_ring;
struct ice_rx_ring *rx_ring;
int fail = 0;
int err;
if (q_idx >= vsi->num_rxq || q_idx >= vsi->num_txq)
return -EINVAL;
tx_ring = vsi->tx_rings[q_idx];
rx_ring = vsi->rx_rings[q_idx];
q_vector = rx_ring->q_vector;
synchronize_net();
netif_carrier_off(vsi->netdev);
netif_tx_stop_queue(netdev_get_tx_queue(vsi->netdev, q_idx));
ice_qvec_dis_irq(vsi, rx_ring, q_vector);
ice_qvec_toggle_napi(vsi, q_vector, false);
ice_fill_txq_meta(vsi, tx_ring, &txq_meta);
err = ice_vsi_stop_tx_ring(vsi, ICE_NO_RESET, 0, tx_ring, &txq_meta);
if (!fail)
fail = err;
if (vsi->xdp_rings) {
struct ice_tx_ring *xdp_ring = vsi->xdp_rings[q_idx];
memset(&txq_meta, 0, sizeof(txq_meta));
ice_fill_txq_meta(vsi, xdp_ring, &txq_meta);
err = ice_vsi_stop_tx_ring(vsi, ICE_NO_RESET, 0, xdp_ring,
&txq_meta);
if (!fail)
fail = err;
}
ice_vsi_ctrl_one_rx_ring(vsi, false, q_idx, false);
ice_qp_clean_rings(vsi, q_idx);
ice_qp_reset_stats(vsi, q_idx);
return fail;
}
/**
* ice_qp_ena - Enables a queue pair
* @vsi: VSI of interest
* @q_idx: ring index in array
*
* Returns 0 on success, negative on failure.
*/
static int ice_qp_ena(struct ice_vsi *vsi, u16 q_idx)
{
struct ice_q_vector *q_vector;
int fail = 0;
bool link_up;
int err;
err = ice_vsi_cfg_single_txq(vsi, vsi->tx_rings, q_idx);
if (!fail)
fail = err;
if (ice_is_xdp_ena_vsi(vsi)) {
struct ice_tx_ring *xdp_ring = vsi->xdp_rings[q_idx];
err = ice_vsi_cfg_single_txq(vsi, vsi->xdp_rings, q_idx);
if (!fail)
fail = err;
ice_set_ring_xdp(xdp_ring);
ice_tx_xsk_pool(vsi, q_idx);
}
err = ice_vsi_cfg_single_rxq(vsi, q_idx);
if (!fail)
fail = err;
q_vector = vsi->rx_rings[q_idx]->q_vector;
ice_qvec_cfg_msix(vsi, q_vector, q_idx);
err = ice_vsi_ctrl_one_rx_ring(vsi, true, q_idx, true);
if (!fail)
fail = err;
ice_qvec_toggle_napi(vsi, q_vector, true);
ice_qvec_ena_irq(vsi, q_vector);
/* make sure NAPI sees updated ice_{t,x}_ring::xsk_pool */
synchronize_net();
ice_get_link_status(vsi->port_info, &link_up);
if (link_up) {
netif_tx_start_queue(netdev_get_tx_queue(vsi->netdev, q_idx));
netif_carrier_on(vsi->netdev);
}
return fail;
}
/**
* ice_xsk_pool_disable - disable a buffer pool region
* @vsi: Current VSI

View File

@ -23,6 +23,13 @@ void ice_xsk_clean_rx_ring(struct ice_rx_ring *rx_ring);
void ice_xsk_clean_xdp_ring(struct ice_tx_ring *xdp_ring);
bool ice_xmit_zc(struct ice_tx_ring *xdp_ring, struct xsk_buff_pool *xsk_pool);
int ice_realloc_zc_buf(struct ice_vsi *vsi, bool zc);
void ice_qvec_cfg_msix(struct ice_vsi *vsi, struct ice_q_vector *q_vector,
u16 qid);
void ice_qvec_toggle_napi(struct ice_vsi *vsi, struct ice_q_vector *q_vector,
bool enable);
void ice_qvec_ena_irq(struct ice_vsi *vsi, struct ice_q_vector *q_vector);
void ice_qvec_dis_irq(struct ice_vsi *vsi, struct ice_rx_ring *rx_ring,
struct ice_q_vector *q_vector);
#else
static inline bool ice_xmit_zc(struct ice_tx_ring __always_unused *xdp_ring,
struct xsk_buff_pool __always_unused *xsk_pool)
@ -75,5 +82,20 @@ ice_realloc_zc_buf(struct ice_vsi __always_unused *vsi,
{
return 0;
}
static inline void
ice_qvec_cfg_msix(struct ice_vsi *vsi, struct ice_q_vector *q_vector,
u16 qid) { }
static inline void
ice_qvec_toggle_napi(struct ice_vsi *vsi, struct ice_q_vector *q_vector,
bool enable) { }
static inline void
ice_qvec_ena_irq(struct ice_vsi *vsi, struct ice_q_vector *q_vector) { }
static inline void
ice_qvec_dis_irq(struct ice_vsi *vsi, struct ice_rx_ring *rx_ring,
struct ice_q_vector *q_vector) { }
#endif /* CONFIG_XDP_SOCKETS */
#endif /* !_ICE_XSK_H_ */

View File

@ -54,7 +54,7 @@ static bool ice_vc_isvalid_ring_len(u16 ring_len)
{
return ring_len == 0 ||
(ring_len >= ICE_MIN_NUM_DESC &&
ring_len <= ICE_MAX_NUM_DESC &&
ring_len <= ICE_MAX_NUM_DESC_E810 &&
!(ring_len % ICE_REQ_DESC_MULTIPLE));
}
@ -906,8 +906,6 @@ int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg)
ice_lag_complete_vf_reset(pf->lag, act_prt);
mutex_unlock(&pf->lag_mutex);
ice_lag_move_new_vf_nodes(vf);
/* send the response to the VF */
return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_VSI_QUEUES,
VIRTCHNL_STATUS_ERR_PARAM, NULL, 0);

View File

@ -256,6 +256,21 @@ enum idpf_vport_flags {
IDPF_VPORT_FLAGS_NBITS,
};
/**
* struct idpf_tstamp_stats - Tx timestamp statistics
* @stats_sync: See struct u64_stats_sync
* @packets: Number of packets successfully timestamped by the hardware
* @discarded: Number of Tx skbs discarded due to cached PHC
* being too old to correctly extend timestamp
* @flushed: Number of Tx skbs flushed due to interface closed
*/
struct idpf_tstamp_stats {
struct u64_stats_sync stats_sync;
u64_stats_t packets;
u64_stats_t discarded;
u64_stats_t flushed;
};
struct idpf_port_stats {
struct u64_stats_sync stats_sync;
u64_stats_t rx_hw_csum_err;
@ -328,6 +343,7 @@ struct idpf_fsteer_fltr {
* @tx_tstamp_caps: Capabilities negotiated for Tx timestamping
* @tstamp_config: The Tx tstamp config
* @tstamp_task: Tx timestamping task
* @tstamp_stats: Tx timestamping statistics
*/
struct idpf_vport {
u16 num_txq;
@ -386,6 +402,7 @@ struct idpf_vport {
struct idpf_ptp_vport_tx_tstamp_caps *tx_tstamp_caps;
struct kernel_hwtstamp_config tstamp_config;
struct work_struct tstamp_task;
struct idpf_tstamp_stats tstamp_stats;
};
/**

View File

@ -1685,6 +1685,61 @@ static int idpf_get_ts_info(struct net_device *netdev,
return err;
}
/**
* idpf_get_ts_stats - Collect HW tstamping statistics
* @netdev: network interface device structure
* @ts_stats: HW timestamping stats structure
*
* Collect HW timestamping statistics including successfully timestamped
* packets, discarded due to illegal values, flushed during releasing PTP and
* skipped due to lack of the free index.
*/
static void idpf_get_ts_stats(struct net_device *netdev,
struct ethtool_ts_stats *ts_stats)
{
struct idpf_netdev_priv *np = netdev_priv(netdev);
struct idpf_vport *vport;
unsigned int start;
idpf_vport_ctrl_lock(netdev);
vport = idpf_netdev_to_vport(netdev);
do {
start = u64_stats_fetch_begin(&vport->tstamp_stats.stats_sync);
ts_stats->pkts = u64_stats_read(&vport->tstamp_stats.packets);
ts_stats->lost = u64_stats_read(&vport->tstamp_stats.flushed);
ts_stats->err = u64_stats_read(&vport->tstamp_stats.discarded);
} while (u64_stats_fetch_retry(&vport->tstamp_stats.stats_sync, start));
if (np->state != __IDPF_VPORT_UP)
goto exit;
for (u16 i = 0; i < vport->num_txq_grp; i++) {
struct idpf_txq_group *txq_grp = &vport->txq_grps[i];
for (u16 j = 0; j < txq_grp->num_txq; j++) {
struct idpf_tx_queue *txq = txq_grp->txqs[j];
struct idpf_tx_queue_stats *stats;
u64 ts;
if (!txq)
continue;
stats = &txq->q_stats;
do {
start = u64_stats_fetch_begin(&txq->stats_sync);
ts = u64_stats_read(&stats->tstamp_skipped);
} while (u64_stats_fetch_retry(&txq->stats_sync,
start));
ts_stats->lost += ts;
}
}
exit:
idpf_vport_ctrl_unlock(netdev);
}
static const struct ethtool_ops idpf_ethtool_ops = {
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
ETHTOOL_COALESCE_USE_ADAPTIVE,
@ -1711,6 +1766,7 @@ static const struct ethtool_ops idpf_ethtool_ops = {
.set_ringparam = idpf_set_ringparam,
.get_link_ksettings = idpf_get_link_ksettings,
.get_ts_info = idpf_get_ts_info,
.get_ts_stats = idpf_get_ts_stats,
};
/**

View File

@ -618,8 +618,13 @@ u64 idpf_ptp_extend_ts(struct idpf_vport *vport, u64 in_tstamp)
discard_time = ptp->cached_phc_jiffies + 2 * HZ;
if (time_is_before_jiffies(discard_time))
if (time_is_before_jiffies(discard_time)) {
u64_stats_update_begin(&vport->tstamp_stats.stats_sync);
u64_stats_inc(&vport->tstamp_stats.discarded);
u64_stats_update_end(&vport->tstamp_stats.stats_sync);
return 0;
}
return idpf_ptp_tstamp_extend_32b_to_64b(ptp->cached_phc_time,
lower_32_bits(in_tstamp));
@ -853,10 +858,14 @@ static void idpf_ptp_release_vport_tstamp(struct idpf_vport *vport)
/* Remove list with latches in use */
head = &vport->tx_tstamp_caps->latches_in_use;
u64_stats_update_begin(&vport->tstamp_stats.stats_sync);
list_for_each_entry_safe(ptp_tx_tstamp, tmp, head, list_member) {
u64_stats_inc(&vport->tstamp_stats.flushed);
list_del(&ptp_tx_tstamp->list_member);
kfree(ptp_tx_tstamp);
}
u64_stats_update_end(&vport->tstamp_stats.stats_sync);
spin_unlock_bh(&vport->tx_tstamp_caps->latches_lock);

View File

@ -521,6 +521,10 @@ idpf_ptp_get_tstamp_value(struct idpf_vport *vport,
list_add(&ptp_tx_tstamp->list_member,
&tx_tstamp_caps->latches_free);
u64_stats_update_begin(&vport->tstamp_stats.stats_sync);
u64_stats_inc(&vport->tstamp_stats.packets);
u64_stats_update_end(&vport->tstamp_stats.stats_sync);
return 0;
}

View File

@ -4323,7 +4323,7 @@ static int ixgbevf_resume(struct device *dev_d)
struct pci_dev *pdev = to_pci_dev(dev_d);
struct net_device *netdev = pci_get_drvdata(pdev);
struct ixgbevf_adapter *adapter = netdev_priv(netdev);
u32 err;
int err;
adapter->hw.hw_addr = adapter->io_addr;
smp_mb__before_atomic();