mirror of
https://github.com/torvalds/linux.git
synced 2026-06-02 03:24:19 +02:00
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:
commit
dfff18082a
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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_ */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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_ */
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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_ */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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_ */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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_ */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user