forked from Minki/linux
ice: Configure VSIs for Tx/Rx
This patch configures the VSIs to be able to send and receive packets by doing the following: 1) Initialize flexible parser to extract and include certain fields in the Rx descriptor. 2) Add Tx queues by programming the Tx queue context (implemented in ice_vsi_cfg_txqs). Note that adding the queues also enables (starts) the queues. 3) Add Rx queues by programming Rx queue context (implemented in ice_vsi_cfg_rxqs). Note that this only adds queues but doesn't start them. The rings will be started by calling ice_vsi_start_rx_rings on interface up. 4) Configure interrupts for VSI queues. 5) Implement ice_open and ice_stop. Signed-off-by: Anirudh Venkataramanan <anirudh.venkataramanan@intel.com> Tested-by: Tony Brelinski <tonyx.brelinski@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
parent
9daf8208dd
commit
cdedef59de
@ -12,4 +12,5 @@ ice-y := ice_main.o \
|
||||
ice_common.o \
|
||||
ice_nvm.o \
|
||||
ice_switch.o \
|
||||
ice_sched.o
|
||||
ice_sched.o \
|
||||
ice_txrx.o
|
||||
|
@ -11,8 +11,10 @@
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/cpumask.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/aer.h>
|
||||
@ -43,6 +45,8 @@
|
||||
#define ICE_VSI_MAP_SCATTER 1
|
||||
#define ICE_MAX_SCATTER_TXQS 16
|
||||
#define ICE_MAX_SCATTER_RXQS 16
|
||||
#define ICE_Q_WAIT_RETRY_LIMIT 10
|
||||
#define ICE_Q_WAIT_MAX_RETRY (5 * ICE_Q_WAIT_RETRY_LIMIT)
|
||||
#define ICE_RES_VALID_BIT 0x8000
|
||||
#define ICE_RES_MISC_VEC_ID (ICE_RES_VALID_BIT - 1)
|
||||
#define ICE_INVAL_Q_INDEX 0xffff
|
||||
@ -56,6 +60,14 @@
|
||||
(((val) << ICE_AQ_VSI_UP_TABLE_UP##i##_S) & \
|
||||
ICE_AQ_VSI_UP_TABLE_UP##i##_M)
|
||||
|
||||
#define ICE_RX_DESC(R, i) (&(((union ice_32b_rx_flex_desc *)((R)->desc))[i]))
|
||||
|
||||
#define ice_for_each_txq(vsi, i) \
|
||||
for ((i) = 0; (i) < (vsi)->num_txq; (i)++)
|
||||
|
||||
#define ice_for_each_rxq(vsi, i) \
|
||||
for ((i) = 0; (i) < (vsi)->num_rxq; (i)++)
|
||||
|
||||
struct ice_tc_info {
|
||||
u16 qoffset;
|
||||
u16 qcount;
|
||||
@ -96,6 +108,9 @@ struct ice_vsi {
|
||||
struct ice_ring **rx_rings; /* rx ring array */
|
||||
struct ice_ring **tx_rings; /* tx ring array */
|
||||
struct ice_q_vector **q_vectors; /* q_vector array */
|
||||
|
||||
irqreturn_t (*irq_handler)(int irq, void *data);
|
||||
|
||||
DECLARE_BITMAP(state, __ICE_STATE_NBITS);
|
||||
int num_q_vectors;
|
||||
int base_vector;
|
||||
@ -106,8 +121,14 @@ struct ice_vsi {
|
||||
/* Interrupt thresholds */
|
||||
u16 work_lmt;
|
||||
|
||||
u16 max_frame;
|
||||
u16 rx_buf_len;
|
||||
|
||||
struct ice_aqc_vsi_props info; /* VSI properties */
|
||||
|
||||
bool irqs_ready;
|
||||
bool current_isup; /* Sync 'link up' logging */
|
||||
|
||||
/* queue information */
|
||||
u8 tx_mapping_mode; /* ICE_MAP_MODE_[CONTIG|SCATTER] */
|
||||
u8 rx_mapping_mode; /* ICE_MAP_MODE_[CONTIG|SCATTER] */
|
||||
@ -128,9 +149,11 @@ struct ice_q_vector {
|
||||
struct napi_struct napi;
|
||||
struct ice_ring_container rx;
|
||||
struct ice_ring_container tx;
|
||||
struct irq_affinity_notify affinity_notify;
|
||||
u16 v_idx; /* index in the vsi->q_vector array. */
|
||||
u8 num_ring_tx; /* total number of tx rings in vector */
|
||||
u8 num_ring_rx; /* total number of rx rings in vector */
|
||||
char name[ICE_INT_NAME_STR_LEN];
|
||||
} ____cacheline_internodealigned_in_smp;
|
||||
|
||||
enum ice_pf_flags {
|
||||
@ -178,10 +201,14 @@ struct ice_netdev_priv {
|
||||
/**
|
||||
* ice_irq_dynamic_ena - Enable default interrupt generation settings
|
||||
* @hw: pointer to hw struct
|
||||
* @vsi: pointer to vsi struct, can be NULL
|
||||
* @q_vector: pointer to q_vector, can be NULL
|
||||
*/
|
||||
static inline void ice_irq_dynamic_ena(struct ice_hw *hw)
|
||||
static inline void ice_irq_dynamic_ena(struct ice_hw *hw, struct ice_vsi *vsi,
|
||||
struct ice_q_vector *q_vector)
|
||||
{
|
||||
u32 vector = ((struct ice_pf *)hw->back)->oicr_idx;
|
||||
u32 vector = (vsi && q_vector) ? vsi->base_vector + q_vector->v_idx :
|
||||
((struct ice_pf *)hw->back)->oicr_idx;
|
||||
int itr = ICE_ITR_NONE;
|
||||
u32 val;
|
||||
|
||||
@ -190,7 +217,10 @@ static inline void ice_irq_dynamic_ena(struct ice_hw *hw)
|
||||
*/
|
||||
val = GLINT_DYN_CTL_INTENA_M | GLINT_DYN_CTL_CLEARPBA_M |
|
||||
(itr << GLINT_DYN_CTL_ITR_INDX_S);
|
||||
|
||||
if (vsi)
|
||||
if (test_bit(__ICE_DOWN, vsi->state))
|
||||
return;
|
||||
wr32(hw, GLINT_DYN_CTL(vector), val);
|
||||
}
|
||||
|
||||
#endif /* _ICE_H_ */
|
||||
|
@ -968,6 +968,87 @@ struct ice_aqc_nvm {
|
||||
__le32 addr_low;
|
||||
};
|
||||
|
||||
/* Add TX LAN Queues (indirect 0x0C30) */
|
||||
struct ice_aqc_add_txqs {
|
||||
u8 num_qgrps;
|
||||
u8 reserved[3];
|
||||
__le32 reserved1;
|
||||
__le32 addr_high;
|
||||
__le32 addr_low;
|
||||
};
|
||||
|
||||
/* This is the descriptor of each queue entry for the Add TX LAN Queues
|
||||
* command (0x0C30). Only used within struct ice_aqc_add_tx_qgrp.
|
||||
*/
|
||||
struct ice_aqc_add_txqs_perq {
|
||||
__le16 txq_id;
|
||||
u8 rsvd[2];
|
||||
__le32 q_teid;
|
||||
u8 txq_ctx[22];
|
||||
u8 rsvd2[2];
|
||||
struct ice_aqc_txsched_elem info;
|
||||
};
|
||||
|
||||
/* The format of the command buffer for Add TX LAN Queues (0x0C30)
|
||||
* is an array of the following structs. Please note that the length of
|
||||
* each struct ice_aqc_add_tx_qgrp is variable due
|
||||
* to the variable number of queues in each group!
|
||||
*/
|
||||
struct ice_aqc_add_tx_qgrp {
|
||||
__le32 parent_teid;
|
||||
u8 num_txqs;
|
||||
u8 rsvd[3];
|
||||
struct ice_aqc_add_txqs_perq txqs[1];
|
||||
};
|
||||
|
||||
/* Disable TX LAN Queues (indirect 0x0C31) */
|
||||
struct ice_aqc_dis_txqs {
|
||||
u8 cmd_type;
|
||||
#define ICE_AQC_Q_DIS_CMD_S 0
|
||||
#define ICE_AQC_Q_DIS_CMD_M (0x3 << ICE_AQC_Q_DIS_CMD_S)
|
||||
#define ICE_AQC_Q_DIS_CMD_NO_FUNC_RESET (0 << ICE_AQC_Q_DIS_CMD_S)
|
||||
#define ICE_AQC_Q_DIS_CMD_VM_RESET BIT(ICE_AQC_Q_DIS_CMD_S)
|
||||
#define ICE_AQC_Q_DIS_CMD_VF_RESET (2 << ICE_AQC_Q_DIS_CMD_S)
|
||||
#define ICE_AQC_Q_DIS_CMD_PF_RESET (3 << ICE_AQC_Q_DIS_CMD_S)
|
||||
#define ICE_AQC_Q_DIS_CMD_SUBSEQ_CALL BIT(2)
|
||||
#define ICE_AQC_Q_DIS_CMD_FLUSH_PIPE BIT(3)
|
||||
u8 num_entries;
|
||||
__le16 vmvf_and_timeout;
|
||||
#define ICE_AQC_Q_DIS_VMVF_NUM_S 0
|
||||
#define ICE_AQC_Q_DIS_VMVF_NUM_M (0x3FF << ICE_AQC_Q_DIS_VMVF_NUM_S)
|
||||
#define ICE_AQC_Q_DIS_TIMEOUT_S 10
|
||||
#define ICE_AQC_Q_DIS_TIMEOUT_M (0x3F << ICE_AQC_Q_DIS_TIMEOUT_S)
|
||||
__le32 blocked_cgds;
|
||||
__le32 addr_high;
|
||||
__le32 addr_low;
|
||||
};
|
||||
|
||||
/* The buffer for Disable TX LAN Queues (indirect 0x0C31)
|
||||
* contains the following structures, arrayed one after the
|
||||
* other.
|
||||
* Note: Since the q_id is 16 bits wide, if the
|
||||
* number of queues is even, then 2 bytes of alignment MUST be
|
||||
* added before the start of the next group, to allow correct
|
||||
* alignment of the parent_teid field.
|
||||
*/
|
||||
struct ice_aqc_dis_txq_item {
|
||||
__le32 parent_teid;
|
||||
u8 num_qs;
|
||||
u8 rsvd;
|
||||
/* The length of the q_id array varies according to num_qs */
|
||||
__le16 q_id[1];
|
||||
/* This only applies from F8 onward */
|
||||
#define ICE_AQC_Q_DIS_BUF_ELEM_TYPE_S 15
|
||||
#define ICE_AQC_Q_DIS_BUF_ELEM_TYPE_LAN_Q \
|
||||
(0 << ICE_AQC_Q_DIS_BUF_ELEM_TYPE_S)
|
||||
#define ICE_AQC_Q_DIS_BUF_ELEM_TYPE_RDMA_QSET \
|
||||
(1 << ICE_AQC_Q_DIS_BUF_ELEM_TYPE_S)
|
||||
};
|
||||
|
||||
struct ice_aqc_dis_txq {
|
||||
struct ice_aqc_dis_txq_item qgrps[1];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ice_aq_desc - Admin Queue (AQ) descriptor
|
||||
* @flags: ICE_AQ_FLAG_* flags
|
||||
@ -1008,6 +1089,8 @@ struct ice_aq_desc {
|
||||
struct ice_aqc_query_txsched_res query_sched_res;
|
||||
struct ice_aqc_add_move_delete_elem add_move_delete_elem;
|
||||
struct ice_aqc_nvm nvm;
|
||||
struct ice_aqc_add_txqs add_txqs;
|
||||
struct ice_aqc_dis_txqs dis_txqs;
|
||||
struct ice_aqc_add_get_update_free_vsi vsi_cmd;
|
||||
struct ice_aqc_alloc_free_res_cmd sw_res_ctrl;
|
||||
struct ice_aqc_get_link_status get_link_status;
|
||||
@ -1088,6 +1171,9 @@ enum ice_adminq_opc {
|
||||
/* NVM commands */
|
||||
ice_aqc_opc_nvm_read = 0x0701,
|
||||
|
||||
/* TX queue handling commands/events */
|
||||
ice_aqc_opc_add_txqs = 0x0C30,
|
||||
ice_aqc_opc_dis_txqs = 0x0C31,
|
||||
};
|
||||
|
||||
#endif /* _ICE_ADMINQ_CMD_H_ */
|
||||
|
@ -7,6 +7,25 @@
|
||||
|
||||
#define ICE_PF_RESET_WAIT_COUNT 200
|
||||
|
||||
#define ICE_NIC_FLX_ENTRY(hw, mdid, idx) \
|
||||
wr32((hw), GLFLXP_RXDID_FLX_WRD_##idx(ICE_RXDID_FLEX_NIC), \
|
||||
((ICE_RX_OPC_MDID << \
|
||||
GLFLXP_RXDID_FLX_WRD_##idx##_RXDID_OPCODE_S) & \
|
||||
GLFLXP_RXDID_FLX_WRD_##idx##_RXDID_OPCODE_M) | \
|
||||
(((mdid) << GLFLXP_RXDID_FLX_WRD_##idx##_PROT_MDID_S) & \
|
||||
GLFLXP_RXDID_FLX_WRD_##idx##_PROT_MDID_M))
|
||||
|
||||
#define ICE_NIC_FLX_FLG_ENTRY(hw, flg_0, flg_1, flg_2, flg_3, idx) \
|
||||
wr32((hw), GLFLXP_RXDID_FLAGS(ICE_RXDID_FLEX_NIC, idx), \
|
||||
(((flg_0) << GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_S) & \
|
||||
GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_M) | \
|
||||
(((flg_1) << GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_1_S) & \
|
||||
GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_1_M) | \
|
||||
(((flg_2) << GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_2_S) & \
|
||||
GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_2_M) | \
|
||||
(((flg_3) << GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_3_S) & \
|
||||
GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_3_M))
|
||||
|
||||
/**
|
||||
* ice_set_mac_type - Sets MAC type
|
||||
* @hw: pointer to the HW structure
|
||||
@ -258,6 +277,33 @@ ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse,
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_init_flex_parser - initialize rx flex parser
|
||||
* @hw: pointer to the hardware structure
|
||||
*
|
||||
* Function to initialize flex descriptors
|
||||
*/
|
||||
static void ice_init_flex_parser(struct ice_hw *hw)
|
||||
{
|
||||
u8 idx = 0;
|
||||
|
||||
ICE_NIC_FLX_ENTRY(hw, ICE_RX_MDID_HASH_LOW, 0);
|
||||
ICE_NIC_FLX_ENTRY(hw, ICE_RX_MDID_HASH_HIGH, 1);
|
||||
ICE_NIC_FLX_ENTRY(hw, ICE_RX_MDID_FLOW_ID_LOWER, 2);
|
||||
ICE_NIC_FLX_ENTRY(hw, ICE_RX_MDID_FLOW_ID_HIGH, 3);
|
||||
ICE_NIC_FLX_FLG_ENTRY(hw, ICE_RXFLG_PKT_FRG, ICE_RXFLG_UDP_GRE,
|
||||
ICE_RXFLG_PKT_DSI, ICE_RXFLG_FIN, idx++);
|
||||
ICE_NIC_FLX_FLG_ENTRY(hw, ICE_RXFLG_SYN, ICE_RXFLG_RST,
|
||||
ICE_RXFLG_PKT_DSI, ICE_RXFLG_PKT_DSI, idx++);
|
||||
ICE_NIC_FLX_FLG_ENTRY(hw, ICE_RXFLG_PKT_DSI, ICE_RXFLG_PKT_DSI,
|
||||
ICE_RXFLG_EVLAN_x8100, ICE_RXFLG_EVLAN_x9100,
|
||||
idx++);
|
||||
ICE_NIC_FLX_FLG_ENTRY(hw, ICE_RXFLG_VLAN_x8100, ICE_RXFLG_TNL_VLAN,
|
||||
ICE_RXFLG_TNL_MAC, ICE_RXFLG_TNL0, idx++);
|
||||
ICE_NIC_FLX_FLG_ENTRY(hw, ICE_RXFLG_TNL1, ICE_RXFLG_TNL2,
|
||||
ICE_RXFLG_PKT_DSI, ICE_RXFLG_PKT_DSI, idx);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_init_fltr_mgmt_struct - initializes filter management list and locks
|
||||
* @hw: pointer to the hw struct
|
||||
@ -431,6 +477,8 @@ enum ice_status ice_init_hw(struct ice_hw *hw)
|
||||
if (status)
|
||||
goto err_unroll_fltr_mgmt_struct;
|
||||
|
||||
ice_init_flex_parser(hw);
|
||||
|
||||
return 0;
|
||||
|
||||
err_unroll_fltr_mgmt_struct:
|
||||
@ -597,6 +645,114 @@ enum ice_status ice_reset(struct ice_hw *hw, enum ice_reset_req req)
|
||||
return ice_check_reset(hw);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_copy_rxq_ctx_to_hw
|
||||
* @hw: pointer to the hardware structure
|
||||
* @ice_rxq_ctx: pointer to the rxq context
|
||||
* @rxq_index: the index of the rx queue
|
||||
*
|
||||
* Copies rxq context from dense structure to hw register space
|
||||
*/
|
||||
static enum ice_status
|
||||
ice_copy_rxq_ctx_to_hw(struct ice_hw *hw, u8 *ice_rxq_ctx, u32 rxq_index)
|
||||
{
|
||||
u8 i;
|
||||
|
||||
if (!ice_rxq_ctx)
|
||||
return ICE_ERR_BAD_PTR;
|
||||
|
||||
if (rxq_index > QRX_CTRL_MAX_INDEX)
|
||||
return ICE_ERR_PARAM;
|
||||
|
||||
/* Copy each dword separately to hw */
|
||||
for (i = 0; i < ICE_RXQ_CTX_SIZE_DWORDS; i++) {
|
||||
wr32(hw, QRX_CONTEXT(i, rxq_index),
|
||||
*((u32 *)(ice_rxq_ctx + (i * sizeof(u32)))));
|
||||
|
||||
ice_debug(hw, ICE_DBG_QCTX, "qrxdata[%d]: %08X\n", i,
|
||||
*((u32 *)(ice_rxq_ctx + (i * sizeof(u32)))));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* LAN Rx Queue Context */
|
||||
static const struct ice_ctx_ele ice_rlan_ctx_info[] = {
|
||||
/* Field Width LSB */
|
||||
ICE_CTX_STORE(ice_rlan_ctx, head, 13, 0),
|
||||
ICE_CTX_STORE(ice_rlan_ctx, cpuid, 8, 13),
|
||||
ICE_CTX_STORE(ice_rlan_ctx, base, 57, 32),
|
||||
ICE_CTX_STORE(ice_rlan_ctx, qlen, 13, 89),
|
||||
ICE_CTX_STORE(ice_rlan_ctx, dbuf, 7, 102),
|
||||
ICE_CTX_STORE(ice_rlan_ctx, hbuf, 5, 109),
|
||||
ICE_CTX_STORE(ice_rlan_ctx, dtype, 2, 114),
|
||||
ICE_CTX_STORE(ice_rlan_ctx, dsize, 1, 116),
|
||||
ICE_CTX_STORE(ice_rlan_ctx, crcstrip, 1, 117),
|
||||
ICE_CTX_STORE(ice_rlan_ctx, l2tsel, 1, 119),
|
||||
ICE_CTX_STORE(ice_rlan_ctx, hsplit_0, 4, 120),
|
||||
ICE_CTX_STORE(ice_rlan_ctx, hsplit_1, 2, 124),
|
||||
ICE_CTX_STORE(ice_rlan_ctx, showiv, 1, 127),
|
||||
ICE_CTX_STORE(ice_rlan_ctx, rxmax, 14, 174),
|
||||
ICE_CTX_STORE(ice_rlan_ctx, tphrdesc_ena, 1, 193),
|
||||
ICE_CTX_STORE(ice_rlan_ctx, tphwdesc_ena, 1, 194),
|
||||
ICE_CTX_STORE(ice_rlan_ctx, tphdata_ena, 1, 195),
|
||||
ICE_CTX_STORE(ice_rlan_ctx, tphhead_ena, 1, 196),
|
||||
ICE_CTX_STORE(ice_rlan_ctx, lrxqthresh, 3, 198),
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
/**
|
||||
* ice_write_rxq_ctx
|
||||
* @hw: pointer to the hardware structure
|
||||
* @rlan_ctx: pointer to the rxq context
|
||||
* @rxq_index: the index of the rx queue
|
||||
*
|
||||
* Converts rxq context from sparse to dense structure and then writes
|
||||
* it to hw register space
|
||||
*/
|
||||
enum ice_status
|
||||
ice_write_rxq_ctx(struct ice_hw *hw, struct ice_rlan_ctx *rlan_ctx,
|
||||
u32 rxq_index)
|
||||
{
|
||||
u8 ctx_buf[ICE_RXQ_CTX_SZ] = { 0 };
|
||||
|
||||
ice_set_ctx((u8 *)rlan_ctx, ctx_buf, ice_rlan_ctx_info);
|
||||
return ice_copy_rxq_ctx_to_hw(hw, ctx_buf, rxq_index);
|
||||
}
|
||||
|
||||
/* LAN Tx Queue Context */
|
||||
const struct ice_ctx_ele ice_tlan_ctx_info[] = {
|
||||
/* Field Width LSB */
|
||||
ICE_CTX_STORE(ice_tlan_ctx, base, 57, 0),
|
||||
ICE_CTX_STORE(ice_tlan_ctx, port_num, 3, 57),
|
||||
ICE_CTX_STORE(ice_tlan_ctx, cgd_num, 5, 60),
|
||||
ICE_CTX_STORE(ice_tlan_ctx, pf_num, 3, 65),
|
||||
ICE_CTX_STORE(ice_tlan_ctx, vmvf_num, 10, 68),
|
||||
ICE_CTX_STORE(ice_tlan_ctx, vmvf_type, 2, 78),
|
||||
ICE_CTX_STORE(ice_tlan_ctx, src_vsi, 10, 80),
|
||||
ICE_CTX_STORE(ice_tlan_ctx, tsyn_ena, 1, 90),
|
||||
ICE_CTX_STORE(ice_tlan_ctx, alt_vlan, 1, 92),
|
||||
ICE_CTX_STORE(ice_tlan_ctx, cpuid, 8, 93),
|
||||
ICE_CTX_STORE(ice_tlan_ctx, wb_mode, 1, 101),
|
||||
ICE_CTX_STORE(ice_tlan_ctx, tphrd_desc, 1, 102),
|
||||
ICE_CTX_STORE(ice_tlan_ctx, tphrd, 1, 103),
|
||||
ICE_CTX_STORE(ice_tlan_ctx, tphwr_desc, 1, 104),
|
||||
ICE_CTX_STORE(ice_tlan_ctx, cmpq_id, 9, 105),
|
||||
ICE_CTX_STORE(ice_tlan_ctx, qnum_in_func, 14, 114),
|
||||
ICE_CTX_STORE(ice_tlan_ctx, itr_notification_mode, 1, 128),
|
||||
ICE_CTX_STORE(ice_tlan_ctx, adjust_prof_id, 6, 129),
|
||||
ICE_CTX_STORE(ice_tlan_ctx, qlen, 13, 135),
|
||||
ICE_CTX_STORE(ice_tlan_ctx, quanta_prof_idx, 4, 148),
|
||||
ICE_CTX_STORE(ice_tlan_ctx, tso_ena, 1, 152),
|
||||
ICE_CTX_STORE(ice_tlan_ctx, tso_qnum, 11, 153),
|
||||
ICE_CTX_STORE(ice_tlan_ctx, legacy_int, 1, 164),
|
||||
ICE_CTX_STORE(ice_tlan_ctx, drop_ena, 1, 165),
|
||||
ICE_CTX_STORE(ice_tlan_ctx, cache_prof_idx, 2, 166),
|
||||
ICE_CTX_STORE(ice_tlan_ctx, pkt_shaper_prof_idx, 3, 168),
|
||||
ICE_CTX_STORE(ice_tlan_ctx, int_q_state, 110, 171),
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
/**
|
||||
* ice_debug_cq
|
||||
* @hw: pointer to the hardware structure
|
||||
@ -1104,3 +1260,449 @@ void ice_clear_pxe_mode(struct ice_hw *hw)
|
||||
if (ice_check_sq_alive(hw, &hw->adminq))
|
||||
ice_aq_clear_pxe_mode(hw);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_aq_add_lan_txq
|
||||
* @hw: pointer to the hardware structure
|
||||
* @num_qgrps: Number of added queue groups
|
||||
* @qg_list: list of queue groups to be added
|
||||
* @buf_size: size of buffer for indirect command
|
||||
* @cd: pointer to command details structure or NULL
|
||||
*
|
||||
* Add Tx LAN queue (0x0C30)
|
||||
*
|
||||
* NOTE:
|
||||
* Prior to calling add Tx LAN queue:
|
||||
* Initialize the following as part of the Tx queue context:
|
||||
* Completion queue ID if the queue uses Completion queue, Quanta profile,
|
||||
* Cache profile and Packet shaper profile.
|
||||
*
|
||||
* After add Tx LAN queue AQ command is completed:
|
||||
* Interrupts should be associated with specific queues,
|
||||
* Association of Tx queue to Doorbell queue is not part of Add LAN Tx queue
|
||||
* flow.
|
||||
*/
|
||||
static enum ice_status
|
||||
ice_aq_add_lan_txq(struct ice_hw *hw, u8 num_qgrps,
|
||||
struct ice_aqc_add_tx_qgrp *qg_list, u16 buf_size,
|
||||
struct ice_sq_cd *cd)
|
||||
{
|
||||
u16 i, sum_header_size, sum_q_size = 0;
|
||||
struct ice_aqc_add_tx_qgrp *list;
|
||||
struct ice_aqc_add_txqs *cmd;
|
||||
struct ice_aq_desc desc;
|
||||
|
||||
cmd = &desc.params.add_txqs;
|
||||
|
||||
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_txqs);
|
||||
|
||||
if (!qg_list)
|
||||
return ICE_ERR_PARAM;
|
||||
|
||||
if (num_qgrps > ICE_LAN_TXQ_MAX_QGRPS)
|
||||
return ICE_ERR_PARAM;
|
||||
|
||||
sum_header_size = num_qgrps *
|
||||
(sizeof(*qg_list) - sizeof(*qg_list->txqs));
|
||||
|
||||
list = qg_list;
|
||||
for (i = 0; i < num_qgrps; i++) {
|
||||
struct ice_aqc_add_txqs_perq *q = list->txqs;
|
||||
|
||||
sum_q_size += list->num_txqs * sizeof(*q);
|
||||
list = (struct ice_aqc_add_tx_qgrp *)(q + list->num_txqs);
|
||||
}
|
||||
|
||||
if (buf_size != (sum_header_size + sum_q_size))
|
||||
return ICE_ERR_PARAM;
|
||||
|
||||
desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
|
||||
|
||||
cmd->num_qgrps = num_qgrps;
|
||||
|
||||
return ice_aq_send_cmd(hw, &desc, qg_list, buf_size, cd);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_aq_dis_lan_txq
|
||||
* @hw: pointer to the hardware structure
|
||||
* @num_qgrps: number of groups in the list
|
||||
* @qg_list: the list of groups to disable
|
||||
* @buf_size: the total size of the qg_list buffer in bytes
|
||||
* @cd: pointer to command details structure or NULL
|
||||
*
|
||||
* Disable LAN Tx queue (0x0C31)
|
||||
*/
|
||||
static enum ice_status
|
||||
ice_aq_dis_lan_txq(struct ice_hw *hw, u8 num_qgrps,
|
||||
struct ice_aqc_dis_txq_item *qg_list, u16 buf_size,
|
||||
struct ice_sq_cd *cd)
|
||||
{
|
||||
struct ice_aqc_dis_txqs *cmd;
|
||||
struct ice_aq_desc desc;
|
||||
u16 i, sz = 0;
|
||||
|
||||
cmd = &desc.params.dis_txqs;
|
||||
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_dis_txqs);
|
||||
|
||||
if (!qg_list)
|
||||
return ICE_ERR_PARAM;
|
||||
|
||||
if (num_qgrps > ICE_LAN_TXQ_MAX_QGRPS)
|
||||
return ICE_ERR_PARAM;
|
||||
desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
|
||||
cmd->num_entries = num_qgrps;
|
||||
|
||||
for (i = 0; i < num_qgrps; ++i) {
|
||||
/* Calculate the size taken up by the queue IDs in this group */
|
||||
sz += qg_list[i].num_qs * sizeof(qg_list[i].q_id);
|
||||
|
||||
/* Add the size of the group header */
|
||||
sz += sizeof(qg_list[i]) - sizeof(qg_list[i].q_id);
|
||||
|
||||
/* If the num of queues is even, add 2 bytes of padding */
|
||||
if ((qg_list[i].num_qs % 2) == 0)
|
||||
sz += 2;
|
||||
}
|
||||
|
||||
if (buf_size != sz)
|
||||
return ICE_ERR_PARAM;
|
||||
|
||||
return ice_aq_send_cmd(hw, &desc, qg_list, buf_size, cd);
|
||||
}
|
||||
|
||||
/* End of FW Admin Queue command wrappers */
|
||||
|
||||
/**
|
||||
* ice_write_byte - write a byte to a packed context structure
|
||||
* @src_ctx: the context structure to read from
|
||||
* @dest_ctx: the context to be written to
|
||||
* @ce_info: a description of the struct to be filled
|
||||
*/
|
||||
static void ice_write_byte(u8 *src_ctx, u8 *dest_ctx,
|
||||
const struct ice_ctx_ele *ce_info)
|
||||
{
|
||||
u8 src_byte, dest_byte, mask;
|
||||
u8 *from, *dest;
|
||||
u16 shift_width;
|
||||
|
||||
/* copy from the next struct field */
|
||||
from = src_ctx + ce_info->offset;
|
||||
|
||||
/* prepare the bits and mask */
|
||||
shift_width = ce_info->lsb % 8;
|
||||
mask = (u8)(BIT(ce_info->width) - 1);
|
||||
|
||||
src_byte = *from;
|
||||
src_byte &= mask;
|
||||
|
||||
/* shift to correct alignment */
|
||||
mask <<= shift_width;
|
||||
src_byte <<= shift_width;
|
||||
|
||||
/* get the current bits from the target bit string */
|
||||
dest = dest_ctx + (ce_info->lsb / 8);
|
||||
|
||||
memcpy(&dest_byte, dest, sizeof(dest_byte));
|
||||
|
||||
dest_byte &= ~mask; /* get the bits not changing */
|
||||
dest_byte |= src_byte; /* add in the new bits */
|
||||
|
||||
/* put it all back */
|
||||
memcpy(dest, &dest_byte, sizeof(dest_byte));
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_write_word - write a word to a packed context structure
|
||||
* @src_ctx: the context structure to read from
|
||||
* @dest_ctx: the context to be written to
|
||||
* @ce_info: a description of the struct to be filled
|
||||
*/
|
||||
static void ice_write_word(u8 *src_ctx, u8 *dest_ctx,
|
||||
const struct ice_ctx_ele *ce_info)
|
||||
{
|
||||
u16 src_word, mask;
|
||||
__le16 dest_word;
|
||||
u8 *from, *dest;
|
||||
u16 shift_width;
|
||||
|
||||
/* copy from the next struct field */
|
||||
from = src_ctx + ce_info->offset;
|
||||
|
||||
/* prepare the bits and mask */
|
||||
shift_width = ce_info->lsb % 8;
|
||||
mask = BIT(ce_info->width) - 1;
|
||||
|
||||
/* don't swizzle the bits until after the mask because the mask bits
|
||||
* will be in a different bit position on big endian machines
|
||||
*/
|
||||
src_word = *(u16 *)from;
|
||||
src_word &= mask;
|
||||
|
||||
/* shift to correct alignment */
|
||||
mask <<= shift_width;
|
||||
src_word <<= shift_width;
|
||||
|
||||
/* get the current bits from the target bit string */
|
||||
dest = dest_ctx + (ce_info->lsb / 8);
|
||||
|
||||
memcpy(&dest_word, dest, sizeof(dest_word));
|
||||
|
||||
dest_word &= ~(cpu_to_le16(mask)); /* get the bits not changing */
|
||||
dest_word |= cpu_to_le16(src_word); /* add in the new bits */
|
||||
|
||||
/* put it all back */
|
||||
memcpy(dest, &dest_word, sizeof(dest_word));
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_write_dword - write a dword to a packed context structure
|
||||
* @src_ctx: the context structure to read from
|
||||
* @dest_ctx: the context to be written to
|
||||
* @ce_info: a description of the struct to be filled
|
||||
*/
|
||||
static void ice_write_dword(u8 *src_ctx, u8 *dest_ctx,
|
||||
const struct ice_ctx_ele *ce_info)
|
||||
{
|
||||
u32 src_dword, mask;
|
||||
__le32 dest_dword;
|
||||
u8 *from, *dest;
|
||||
u16 shift_width;
|
||||
|
||||
/* copy from the next struct field */
|
||||
from = src_ctx + ce_info->offset;
|
||||
|
||||
/* prepare the bits and mask */
|
||||
shift_width = ce_info->lsb % 8;
|
||||
|
||||
/* if the field width is exactly 32 on an x86 machine, then the shift
|
||||
* operation will not work because the SHL instructions count is masked
|
||||
* to 5 bits so the shift will do nothing
|
||||
*/
|
||||
if (ce_info->width < 32)
|
||||
mask = BIT(ce_info->width) - 1;
|
||||
else
|
||||
mask = (u32)~0;
|
||||
|
||||
/* don't swizzle the bits until after the mask because the mask bits
|
||||
* will be in a different bit position on big endian machines
|
||||
*/
|
||||
src_dword = *(u32 *)from;
|
||||
src_dword &= mask;
|
||||
|
||||
/* shift to correct alignment */
|
||||
mask <<= shift_width;
|
||||
src_dword <<= shift_width;
|
||||
|
||||
/* get the current bits from the target bit string */
|
||||
dest = dest_ctx + (ce_info->lsb / 8);
|
||||
|
||||
memcpy(&dest_dword, dest, sizeof(dest_dword));
|
||||
|
||||
dest_dword &= ~(cpu_to_le32(mask)); /* get the bits not changing */
|
||||
dest_dword |= cpu_to_le32(src_dword); /* add in the new bits */
|
||||
|
||||
/* put it all back */
|
||||
memcpy(dest, &dest_dword, sizeof(dest_dword));
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_write_qword - write a qword to a packed context structure
|
||||
* @src_ctx: the context structure to read from
|
||||
* @dest_ctx: the context to be written to
|
||||
* @ce_info: a description of the struct to be filled
|
||||
*/
|
||||
static void ice_write_qword(u8 *src_ctx, u8 *dest_ctx,
|
||||
const struct ice_ctx_ele *ce_info)
|
||||
{
|
||||
u64 src_qword, mask;
|
||||
__le64 dest_qword;
|
||||
u8 *from, *dest;
|
||||
u16 shift_width;
|
||||
|
||||
/* copy from the next struct field */
|
||||
from = src_ctx + ce_info->offset;
|
||||
|
||||
/* prepare the bits and mask */
|
||||
shift_width = ce_info->lsb % 8;
|
||||
|
||||
/* if the field width is exactly 64 on an x86 machine, then the shift
|
||||
* operation will not work because the SHL instructions count is masked
|
||||
* to 6 bits so the shift will do nothing
|
||||
*/
|
||||
if (ce_info->width < 64)
|
||||
mask = BIT_ULL(ce_info->width) - 1;
|
||||
else
|
||||
mask = (u64)~0;
|
||||
|
||||
/* don't swizzle the bits until after the mask because the mask bits
|
||||
* will be in a different bit position on big endian machines
|
||||
*/
|
||||
src_qword = *(u64 *)from;
|
||||
src_qword &= mask;
|
||||
|
||||
/* shift to correct alignment */
|
||||
mask <<= shift_width;
|
||||
src_qword <<= shift_width;
|
||||
|
||||
/* get the current bits from the target bit string */
|
||||
dest = dest_ctx + (ce_info->lsb / 8);
|
||||
|
||||
memcpy(&dest_qword, dest, sizeof(dest_qword));
|
||||
|
||||
dest_qword &= ~(cpu_to_le64(mask)); /* get the bits not changing */
|
||||
dest_qword |= cpu_to_le64(src_qword); /* add in the new bits */
|
||||
|
||||
/* put it all back */
|
||||
memcpy(dest, &dest_qword, sizeof(dest_qword));
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_set_ctx - set context bits in packed structure
|
||||
* @src_ctx: pointer to a generic non-packed context structure
|
||||
* @dest_ctx: pointer to memory for the packed structure
|
||||
* @ce_info: a description of the structure to be transformed
|
||||
*/
|
||||
enum ice_status
|
||||
ice_set_ctx(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info)
|
||||
{
|
||||
int f;
|
||||
|
||||
for (f = 0; ce_info[f].width; f++) {
|
||||
/* We have to deal with each element of the FW response
|
||||
* using the correct size so that we are correct regardless
|
||||
* of the endianness of the machine.
|
||||
*/
|
||||
switch (ce_info[f].size_of) {
|
||||
case sizeof(u8):
|
||||
ice_write_byte(src_ctx, dest_ctx, &ce_info[f]);
|
||||
break;
|
||||
case sizeof(u16):
|
||||
ice_write_word(src_ctx, dest_ctx, &ce_info[f]);
|
||||
break;
|
||||
case sizeof(u32):
|
||||
ice_write_dword(src_ctx, dest_ctx, &ce_info[f]);
|
||||
break;
|
||||
case sizeof(u64):
|
||||
ice_write_qword(src_ctx, dest_ctx, &ce_info[f]);
|
||||
break;
|
||||
default:
|
||||
return ICE_ERR_INVAL_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_ena_vsi_txq
|
||||
* @pi: port information structure
|
||||
* @vsi_id: VSI id
|
||||
* @tc: tc number
|
||||
* @num_qgrps: Number of added queue groups
|
||||
* @buf: list of queue groups to be added
|
||||
* @buf_size: size of buffer for indirect command
|
||||
* @cd: pointer to command details structure or NULL
|
||||
*
|
||||
* This function adds one lan q
|
||||
*/
|
||||
enum ice_status
|
||||
ice_ena_vsi_txq(struct ice_port_info *pi, u16 vsi_id, u8 tc, u8 num_qgrps,
|
||||
struct ice_aqc_add_tx_qgrp *buf, u16 buf_size,
|
||||
struct ice_sq_cd *cd)
|
||||
{
|
||||
struct ice_aqc_txsched_elem_data node = { 0 };
|
||||
struct ice_sched_node *parent;
|
||||
enum ice_status status;
|
||||
struct ice_hw *hw;
|
||||
|
||||
if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
|
||||
return ICE_ERR_CFG;
|
||||
|
||||
if (num_qgrps > 1 || buf->num_txqs > 1)
|
||||
return ICE_ERR_MAX_LIMIT;
|
||||
|
||||
hw = pi->hw;
|
||||
|
||||
mutex_lock(&pi->sched_lock);
|
||||
|
||||
/* find a parent node */
|
||||
parent = ice_sched_get_free_qparent(pi, vsi_id, tc,
|
||||
ICE_SCHED_NODE_OWNER_LAN);
|
||||
if (!parent) {
|
||||
status = ICE_ERR_PARAM;
|
||||
goto ena_txq_exit;
|
||||
}
|
||||
buf->parent_teid = parent->info.node_teid;
|
||||
node.parent_teid = parent->info.node_teid;
|
||||
/* Mark that the values in the "generic" section as valid. The default
|
||||
* value in the "generic" section is zero. This means that :
|
||||
* - Scheduling mode is Bytes Per Second (BPS), indicated by Bit 0.
|
||||
* - 0 priority among siblings, indicated by Bit 1-3.
|
||||
* - WFQ, indicated by Bit 4.
|
||||
* - 0 Adjustment value is used in PSM credit update flow, indicated by
|
||||
* Bit 5-6.
|
||||
* - Bit 7 is reserved.
|
||||
* Without setting the generic section as valid in valid_sections, the
|
||||
* Admin Q command will fail with error code ICE_AQ_RC_EINVAL.
|
||||
*/
|
||||
buf->txqs[0].info.valid_sections = ICE_AQC_ELEM_VALID_GENERIC;
|
||||
|
||||
/* add the lan q */
|
||||
status = ice_aq_add_lan_txq(hw, num_qgrps, buf, buf_size, cd);
|
||||
if (status)
|
||||
goto ena_txq_exit;
|
||||
|
||||
node.node_teid = buf->txqs[0].q_teid;
|
||||
node.data.elem_type = ICE_AQC_ELEM_TYPE_LEAF;
|
||||
|
||||
/* add a leaf node into schduler tree q layer */
|
||||
status = ice_sched_add_node(pi, hw->num_tx_sched_layers - 1, &node);
|
||||
|
||||
ena_txq_exit:
|
||||
mutex_unlock(&pi->sched_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_dis_vsi_txq
|
||||
* @pi: port information structure
|
||||
* @num_queues: number of queues
|
||||
* @q_ids: pointer to the q_id array
|
||||
* @q_teids: pointer to queue node teids
|
||||
* @cd: pointer to command details structure or NULL
|
||||
*
|
||||
* This function removes queues and their corresponding nodes in SW DB
|
||||
*/
|
||||
enum ice_status
|
||||
ice_dis_vsi_txq(struct ice_port_info *pi, u8 num_queues, u16 *q_ids,
|
||||
u32 *q_teids, struct ice_sq_cd *cd)
|
||||
{
|
||||
enum ice_status status = ICE_ERR_DOES_NOT_EXIST;
|
||||
struct ice_aqc_dis_txq_item qg_list;
|
||||
u16 i;
|
||||
|
||||
if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
|
||||
return ICE_ERR_CFG;
|
||||
|
||||
mutex_lock(&pi->sched_lock);
|
||||
|
||||
for (i = 0; i < num_queues; i++) {
|
||||
struct ice_sched_node *node;
|
||||
|
||||
node = ice_sched_find_node_by_teid(pi->root, q_teids[i]);
|
||||
if (!node)
|
||||
continue;
|
||||
qg_list.parent_teid = node->info.parent_teid;
|
||||
qg_list.num_qs = 1;
|
||||
qg_list.q_id[0] = cpu_to_le16(q_ids[i]);
|
||||
status = ice_aq_dis_lan_txq(pi->hw, 1, &qg_list,
|
||||
sizeof(qg_list), cd);
|
||||
|
||||
if (status)
|
||||
break;
|
||||
ice_free_sched_node(pi, node);
|
||||
}
|
||||
mutex_unlock(&pi->sched_lock);
|
||||
return status;
|
||||
}
|
||||
|
@ -30,9 +30,15 @@ ice_sq_send_cmd(struct ice_hw *hw, struct ice_ctl_q_info *cq,
|
||||
struct ice_sq_cd *cd);
|
||||
void ice_clear_pxe_mode(struct ice_hw *hw);
|
||||
enum ice_status ice_get_caps(struct ice_hw *hw);
|
||||
enum ice_status
|
||||
ice_write_rxq_ctx(struct ice_hw *hw, struct ice_rlan_ctx *rlan_ctx,
|
||||
u32 rxq_index);
|
||||
bool ice_check_sq_alive(struct ice_hw *hw, struct ice_ctl_q_info *cq);
|
||||
enum ice_status ice_aq_q_shutdown(struct ice_hw *hw, bool unloading);
|
||||
void ice_fill_dflt_direct_cmd_desc(struct ice_aq_desc *desc, u16 opcode);
|
||||
extern const struct ice_ctx_ele ice_tlan_ctx_info[];
|
||||
enum ice_status
|
||||
ice_set_ctx(u8 *src_ctx, u8 *dest_ctx, const struct ice_ctx_ele *ce_info);
|
||||
enum ice_status
|
||||
ice_aq_send_cmd(struct ice_hw *hw, struct ice_aq_desc *desc,
|
||||
void *buf, u16 buf_size, struct ice_sq_cd *cd);
|
||||
@ -41,4 +47,11 @@ enum ice_status ice_clear_pf_cfg(struct ice_hw *hw);
|
||||
enum ice_status
|
||||
ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse,
|
||||
struct ice_link_status *link, struct ice_sq_cd *cd);
|
||||
enum ice_status
|
||||
ice_dis_vsi_txq(struct ice_port_info *pi, u8 num_queues, u16 *q_ids,
|
||||
u32 *q_teids, struct ice_sq_cd *cmd_details);
|
||||
enum ice_status
|
||||
ice_ena_vsi_txq(struct ice_port_info *pi, u16 vsi_id, u8 tc, u8 num_qgrps,
|
||||
struct ice_aqc_add_tx_qgrp *buf, u16 buf_size,
|
||||
struct ice_sq_cd *cd);
|
||||
#endif /* _ICE_COMMON_H_ */
|
||||
|
@ -6,6 +6,7 @@
|
||||
#ifndef _ICE_HW_AUTOGEN_H_
|
||||
#define _ICE_HW_AUTOGEN_H_
|
||||
|
||||
#define QTX_COMM_DBELL(_DBQM) (0x002C0000 + ((_DBQM) * 4))
|
||||
#define PF_FW_ARQBAH 0x00080180
|
||||
#define PF_FW_ARQBAL 0x00080080
|
||||
#define PF_FW_ARQH 0x00080380
|
||||
@ -40,6 +41,44 @@
|
||||
#define PF_FW_ATQLEN_ATQENABLE_S 31
|
||||
#define PF_FW_ATQLEN_ATQENABLE_M BIT(PF_FW_ATQLEN_ATQENABLE_S)
|
||||
#define PF_FW_ATQT 0x00080400
|
||||
|
||||
#define GLFLXP_RXDID_FLAGS(_i, _j) (0x0045D000 + ((_i) * 4 + (_j) * 256))
|
||||
#define GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_S 0
|
||||
#define GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_M ICE_M(0x3F, GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_S)
|
||||
#define GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_1_S 8
|
||||
#define GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_1_M ICE_M(0x3F, GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_1_S)
|
||||
#define GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_2_S 16
|
||||
#define GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_2_M ICE_M(0x3F, GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_2_S)
|
||||
#define GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_3_S 24
|
||||
#define GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_3_M ICE_M(0x3F, GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_3_S)
|
||||
#define GLFLXP_RXDID_FLX_WRD_0(_i) (0x0045c800 + ((_i) * 4))
|
||||
#define GLFLXP_RXDID_FLX_WRD_0_PROT_MDID_S 0
|
||||
#define GLFLXP_RXDID_FLX_WRD_0_PROT_MDID_M ICE_M(0xFF, GLFLXP_RXDID_FLX_WRD_0_PROT_MDID_S)
|
||||
#define GLFLXP_RXDID_FLX_WRD_0_RXDID_OPCODE_S 30
|
||||
#define GLFLXP_RXDID_FLX_WRD_0_RXDID_OPCODE_M ICE_M(0x3, GLFLXP_RXDID_FLX_WRD_0_RXDID_OPCODE_S)
|
||||
#define GLFLXP_RXDID_FLX_WRD_1(_i) (0x0045c900 + ((_i) * 4))
|
||||
#define GLFLXP_RXDID_FLX_WRD_1_PROT_MDID_S 0
|
||||
#define GLFLXP_RXDID_FLX_WRD_1_PROT_MDID_M ICE_M(0xFF, GLFLXP_RXDID_FLX_WRD_1_PROT_MDID_S)
|
||||
#define GLFLXP_RXDID_FLX_WRD_1_RXDID_OPCODE_S 30
|
||||
#define GLFLXP_RXDID_FLX_WRD_1_RXDID_OPCODE_M ICE_M(0x3, GLFLXP_RXDID_FLX_WRD_1_RXDID_OPCODE_S)
|
||||
#define GLFLXP_RXDID_FLX_WRD_2(_i) (0x0045ca00 + ((_i) * 4))
|
||||
#define GLFLXP_RXDID_FLX_WRD_2_PROT_MDID_S 0
|
||||
#define GLFLXP_RXDID_FLX_WRD_2_PROT_MDID_M ICE_M(0xFF, GLFLXP_RXDID_FLX_WRD_2_PROT_MDID_S)
|
||||
#define GLFLXP_RXDID_FLX_WRD_2_RXDID_OPCODE_S 30
|
||||
#define GLFLXP_RXDID_FLX_WRD_2_RXDID_OPCODE_M ICE_M(0x3, GLFLXP_RXDID_FLX_WRD_2_RXDID_OPCODE_S)
|
||||
#define GLFLXP_RXDID_FLX_WRD_3(_i) (0x0045cb00 + ((_i) * 4))
|
||||
#define GLFLXP_RXDID_FLX_WRD_3_PROT_MDID_S 0
|
||||
#define GLFLXP_RXDID_FLX_WRD_3_PROT_MDID_M ICE_M(0xFF, GLFLXP_RXDID_FLX_WRD_3_PROT_MDID_S)
|
||||
#define GLFLXP_RXDID_FLX_WRD_3_RXDID_OPCODE_S 30
|
||||
#define GLFLXP_RXDID_FLX_WRD_3_RXDID_OPCODE_M ICE_M(0x3, GLFLXP_RXDID_FLX_WRD_3_RXDID_OPCODE_S)
|
||||
|
||||
#define QRXFLXP_CNTXT(_QRX) (0x00480000 + ((_QRX) * 4))
|
||||
#define QRXFLXP_CNTXT_RXDID_IDX_S 0
|
||||
#define QRXFLXP_CNTXT_RXDID_IDX_M ICE_M(0x3F, QRXFLXP_CNTXT_RXDID_IDX_S)
|
||||
#define QRXFLXP_CNTXT_RXDID_PRIO_S 8
|
||||
#define QRXFLXP_CNTXT_RXDID_PRIO_M ICE_M(0x7, QRXFLXP_CNTXT_RXDID_PRIO_S)
|
||||
#define QRXFLXP_CNTXT_TS_S 11
|
||||
#define QRXFLXP_CNTXT_TS_M BIT(QRXFLXP_CNTXT_TS_S)
|
||||
#define GLGEN_RSTAT 0x000B8188
|
||||
#define GLGEN_RSTAT_DEVSTATE_S 0
|
||||
#define GLGEN_RSTAT_DEVSTATE_M ICE_M(0x3, GLGEN_RSTAT_DEVSTATE_S)
|
||||
@ -62,6 +101,8 @@
|
||||
#define GLINT_DYN_CTL_INTENA_M BIT(GLINT_DYN_CTL_INTENA_S)
|
||||
#define GLINT_DYN_CTL_CLEARPBA_S 1
|
||||
#define GLINT_DYN_CTL_CLEARPBA_M BIT(GLINT_DYN_CTL_CLEARPBA_S)
|
||||
#define GLINT_DYN_CTL_SWINT_TRIG_S 2
|
||||
#define GLINT_DYN_CTL_SWINT_TRIG_M BIT(GLINT_DYN_CTL_SWINT_TRIG_S)
|
||||
#define GLINT_DYN_CTL_ITR_INDX_S 3
|
||||
#define GLINT_DYN_CTL_SW_ITR_INDX_S 25
|
||||
#define GLINT_DYN_CTL_SW_ITR_INDX_M ICE_M(0x3, GLINT_DYN_CTL_SW_ITR_INDX_S)
|
||||
@ -106,7 +147,25 @@
|
||||
#define PFINT_OICR_CTL_CAUSE_ENA_S 30
|
||||
#define PFINT_OICR_CTL_CAUSE_ENA_M BIT(PFINT_OICR_CTL_CAUSE_ENA_S)
|
||||
#define PFINT_OICR_ENA 0x0016C900
|
||||
#define QINT_RQCTL(_QRX) (0x00150000 + ((_QRX) * 4))
|
||||
#define QINT_RQCTL_MSIX_INDX_S 0
|
||||
#define QINT_RQCTL_ITR_INDX_S 11
|
||||
#define QINT_RQCTL_CAUSE_ENA_S 30
|
||||
#define QINT_RQCTL_CAUSE_ENA_M BIT(QINT_RQCTL_CAUSE_ENA_S)
|
||||
#define QINT_TQCTL(_DBQM) (0x00140000 + ((_DBQM) * 4))
|
||||
#define QINT_TQCTL_MSIX_INDX_S 0
|
||||
#define QINT_TQCTL_ITR_INDX_S 11
|
||||
#define QINT_TQCTL_CAUSE_ENA_S 30
|
||||
#define QINT_TQCTL_CAUSE_ENA_M BIT(QINT_TQCTL_CAUSE_ENA_S)
|
||||
#define GLLAN_RCTL_0 0x002941F8
|
||||
#define QRX_CONTEXT(_i, _QRX) (0x00280000 + ((_i) * 8192 + (_QRX) * 4))
|
||||
#define QRX_CTRL(_QRX) (0x00120000 + ((_QRX) * 4))
|
||||
#define QRX_CTRL_MAX_INDEX 2047
|
||||
#define QRX_CTRL_QENA_REQ_S 0
|
||||
#define QRX_CTRL_QENA_REQ_M BIT(QRX_CTRL_QENA_REQ_S)
|
||||
#define QRX_CTRL_QENA_STAT_S 2
|
||||
#define QRX_CTRL_QENA_STAT_M BIT(QRX_CTRL_QENA_STAT_S)
|
||||
#define QRX_TAIL(_QRX) (0x00290000 + ((_QRX) * 4))
|
||||
#define GLNVM_FLA 0x000B6108
|
||||
#define GLNVM_FLA_LOCKED_S 6
|
||||
#define GLNVM_FLA_LOCKED_M BIT(GLNVM_FLA_LOCKED_S)
|
||||
|
246
drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h
Normal file
246
drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h
Normal file
@ -0,0 +1,246 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (c) 2018, Intel Corporation. */
|
||||
|
||||
#ifndef _ICE_LAN_TX_RX_H_
|
||||
#define _ICE_LAN_TX_RX_H_
|
||||
|
||||
union ice_32byte_rx_desc {
|
||||
struct {
|
||||
__le64 pkt_addr; /* Packet buffer address */
|
||||
__le64 hdr_addr; /* Header buffer address */
|
||||
/* bit 0 of hdr_addr is DD bit */
|
||||
__le64 rsvd1;
|
||||
__le64 rsvd2;
|
||||
} read;
|
||||
struct {
|
||||
struct {
|
||||
struct {
|
||||
__le16 mirroring_status;
|
||||
__le16 l2tag1;
|
||||
} lo_dword;
|
||||
union {
|
||||
__le32 rss; /* RSS Hash */
|
||||
__le32 fd_id; /* Flow Director filter id */
|
||||
} hi_dword;
|
||||
} qword0;
|
||||
struct {
|
||||
/* status/error/PTYPE/length */
|
||||
__le64 status_error_len;
|
||||
} qword1;
|
||||
struct {
|
||||
__le16 ext_status; /* extended status */
|
||||
__le16 rsvd;
|
||||
__le16 l2tag2_1;
|
||||
__le16 l2tag2_2;
|
||||
} qword2;
|
||||
struct {
|
||||
__le32 reserved;
|
||||
__le32 fd_id;
|
||||
} qword3;
|
||||
} wb; /* writeback */
|
||||
};
|
||||
|
||||
/* RX Flex Descriptor
|
||||
* This descriptor is used instead of the legacy version descriptor when
|
||||
* ice_rlan_ctx.adv_desc is set
|
||||
*/
|
||||
union ice_32b_rx_flex_desc {
|
||||
struct {
|
||||
__le64 pkt_addr; /* Packet buffer address */
|
||||
__le64 hdr_addr; /* Header buffer address */
|
||||
/* bit 0 of hdr_addr is DD bit */
|
||||
__le64 rsvd1;
|
||||
__le64 rsvd2;
|
||||
} read;
|
||||
struct {
|
||||
/* Qword 0 */
|
||||
u8 rxdid; /* descriptor builder profile id */
|
||||
u8 mir_id_umb_cast; /* mirror=[5:0], umb=[7:6] */
|
||||
__le16 ptype_flex_flags0; /* ptype=[9:0], ff0=[15:10] */
|
||||
__le16 pkt_len; /* [15:14] are reserved */
|
||||
__le16 hdr_len_sph_flex_flags1; /* header=[10:0] */
|
||||
/* sph=[11:11] */
|
||||
/* ff1/ext=[15:12] */
|
||||
|
||||
/* Qword 1 */
|
||||
__le16 status_error0;
|
||||
__le16 l2tag1;
|
||||
__le16 flex_meta0;
|
||||
__le16 flex_meta1;
|
||||
|
||||
/* Qword 2 */
|
||||
__le16 status_error1;
|
||||
u8 flex_flags2;
|
||||
u8 time_stamp_low;
|
||||
__le16 l2tag2_1st;
|
||||
__le16 l2tag2_2nd;
|
||||
|
||||
/* Qword 3 */
|
||||
__le16 flex_meta2;
|
||||
__le16 flex_meta3;
|
||||
union {
|
||||
struct {
|
||||
__le16 flex_meta4;
|
||||
__le16 flex_meta5;
|
||||
} flex;
|
||||
__le32 ts_high;
|
||||
} flex_ts;
|
||||
} wb; /* writeback */
|
||||
};
|
||||
|
||||
/* Receive Flex Descriptor profile IDs: There are a total
|
||||
* of 64 profiles where profile IDs 0/1 are for legacy; and
|
||||
* profiles 2-63 are flex profiles that can be programmed
|
||||
* with a specific metadata (profile 7 reserved for HW)
|
||||
*/
|
||||
enum ice_rxdid {
|
||||
ICE_RXDID_START = 0,
|
||||
ICE_RXDID_LEGACY_0 = ICE_RXDID_START,
|
||||
ICE_RXDID_LEGACY_1,
|
||||
ICE_RXDID_FLX_START,
|
||||
ICE_RXDID_FLEX_NIC = ICE_RXDID_FLX_START,
|
||||
ICE_RXDID_FLX_LAST = 63,
|
||||
ICE_RXDID_LAST = ICE_RXDID_FLX_LAST
|
||||
};
|
||||
|
||||
/* Receive Flex Descriptor Rx opcode values */
|
||||
#define ICE_RX_OPC_MDID 0x01
|
||||
|
||||
/* Receive Descriptor MDID values */
|
||||
#define ICE_RX_MDID_FLOW_ID_LOWER 5
|
||||
#define ICE_RX_MDID_FLOW_ID_HIGH 6
|
||||
#define ICE_RX_MDID_HASH_LOW 56
|
||||
#define ICE_RX_MDID_HASH_HIGH 57
|
||||
|
||||
/* Rx Flag64 packet flag bits */
|
||||
enum ice_rx_flg64_bits {
|
||||
ICE_RXFLG_PKT_DSI = 0,
|
||||
ICE_RXFLG_EVLAN_x8100 = 15,
|
||||
ICE_RXFLG_EVLAN_x9100,
|
||||
ICE_RXFLG_VLAN_x8100,
|
||||
ICE_RXFLG_TNL_MAC = 22,
|
||||
ICE_RXFLG_TNL_VLAN,
|
||||
ICE_RXFLG_PKT_FRG,
|
||||
ICE_RXFLG_FIN = 32,
|
||||
ICE_RXFLG_SYN,
|
||||
ICE_RXFLG_RST,
|
||||
ICE_RXFLG_TNL0 = 38,
|
||||
ICE_RXFLG_TNL1,
|
||||
ICE_RXFLG_TNL2,
|
||||
ICE_RXFLG_UDP_GRE,
|
||||
ICE_RXFLG_RSVD = 63
|
||||
};
|
||||
|
||||
#define ICE_RXQ_CTX_SIZE_DWORDS 8
|
||||
#define ICE_RXQ_CTX_SZ (ICE_RXQ_CTX_SIZE_DWORDS * sizeof(u32))
|
||||
|
||||
/* RLAN Rx queue context data
|
||||
*
|
||||
* The sizes of the variables may be larger than needed due to crossing byte
|
||||
* boundaries. If we do not have the width of the variable set to the correct
|
||||
* size then we could end up shifting bits off the top of the variable when the
|
||||
* variable is at the top of a byte and crosses over into the next byte.
|
||||
*/
|
||||
struct ice_rlan_ctx {
|
||||
u16 head;
|
||||
u16 cpuid; /* bigger than needed, see above for reason */
|
||||
u64 base;
|
||||
u16 qlen;
|
||||
#define ICE_RLAN_CTX_DBUF_S 7
|
||||
u16 dbuf; /* bigger than needed, see above for reason */
|
||||
#define ICE_RLAN_CTX_HBUF_S 6
|
||||
u16 hbuf; /* bigger than needed, see above for reason */
|
||||
u8 dtype;
|
||||
u8 dsize;
|
||||
u8 crcstrip;
|
||||
u8 l2tsel;
|
||||
u8 hsplit_0;
|
||||
u8 hsplit_1;
|
||||
u8 showiv;
|
||||
u32 rxmax; /* bigger than needed, see above for reason */
|
||||
u8 tphrdesc_ena;
|
||||
u8 tphwdesc_ena;
|
||||
u8 tphdata_ena;
|
||||
u8 tphhead_ena;
|
||||
u16 lrxqthresh; /* bigger than needed, see above for reason */
|
||||
};
|
||||
|
||||
struct ice_ctx_ele {
|
||||
u16 offset;
|
||||
u16 size_of;
|
||||
u16 width;
|
||||
u16 lsb;
|
||||
};
|
||||
|
||||
#define ICE_CTX_STORE(_struct, _ele, _width, _lsb) { \
|
||||
.offset = offsetof(struct _struct, _ele), \
|
||||
.size_of = FIELD_SIZEOF(struct _struct, _ele), \
|
||||
.width = _width, \
|
||||
.lsb = _lsb, \
|
||||
}
|
||||
|
||||
/* for hsplit_0 field of Rx RLAN context */
|
||||
enum ice_rlan_ctx_rx_hsplit_0 {
|
||||
ICE_RLAN_RX_HSPLIT_0_NO_SPLIT = 0,
|
||||
ICE_RLAN_RX_HSPLIT_0_SPLIT_L2 = 1,
|
||||
ICE_RLAN_RX_HSPLIT_0_SPLIT_IP = 2,
|
||||
ICE_RLAN_RX_HSPLIT_0_SPLIT_TCP_UDP = 4,
|
||||
ICE_RLAN_RX_HSPLIT_0_SPLIT_SCTP = 8,
|
||||
};
|
||||
|
||||
/* for hsplit_1 field of Rx RLAN context */
|
||||
enum ice_rlan_ctx_rx_hsplit_1 {
|
||||
ICE_RLAN_RX_HSPLIT_1_NO_SPLIT = 0,
|
||||
ICE_RLAN_RX_HSPLIT_1_SPLIT_L2 = 1,
|
||||
ICE_RLAN_RX_HSPLIT_1_SPLIT_ALWAYS = 2,
|
||||
};
|
||||
|
||||
/* TX Descriptor */
|
||||
struct ice_tx_desc {
|
||||
__le64 buf_addr; /* Address of descriptor's data buf */
|
||||
__le64 cmd_type_offset_bsz;
|
||||
};
|
||||
|
||||
#define ICE_LAN_TXQ_MAX_QGRPS 127
|
||||
#define ICE_LAN_TXQ_MAX_QDIS 1023
|
||||
|
||||
/* Tx queue context data
|
||||
*
|
||||
* The sizes of the variables may be larger than needed due to crossing byte
|
||||
* boundaries. If we do not have the width of the variable set to the correct
|
||||
* size then we could end up shifting bits off the top of the variable when the
|
||||
* variable is at the top of a byte and crosses over into the next byte.
|
||||
*/
|
||||
struct ice_tlan_ctx {
|
||||
#define ICE_TLAN_CTX_BASE_S 7
|
||||
u64 base; /* base is defined in 128-byte units */
|
||||
u8 port_num;
|
||||
u16 cgd_num; /* bigger than needed, see above for reason */
|
||||
u8 pf_num;
|
||||
u16 vmvf_num;
|
||||
u8 vmvf_type;
|
||||
#define ICE_TLAN_CTX_VMVF_TYPE_VMQ 1
|
||||
#define ICE_TLAN_CTX_VMVF_TYPE_PF 2
|
||||
u16 src_vsi;
|
||||
u8 tsyn_ena;
|
||||
u8 alt_vlan;
|
||||
u16 cpuid; /* bigger than needed, see above for reason */
|
||||
u8 wb_mode;
|
||||
u8 tphrd_desc;
|
||||
u8 tphrd;
|
||||
u8 tphwr_desc;
|
||||
u16 cmpq_id;
|
||||
u16 qnum_in_func;
|
||||
u8 itr_notification_mode;
|
||||
u8 adjust_prof_id;
|
||||
u32 qlen; /* bigger than needed, see above for reason */
|
||||
u8 quanta_prof_idx;
|
||||
u8 tso_ena;
|
||||
u16 tso_qnum;
|
||||
u8 legacy_int;
|
||||
u8 drop_ena;
|
||||
u8 cache_prof_idx;
|
||||
u8 pkt_shaper_prof_idx;
|
||||
u8 int_q_state; /* width not needed - internal do not write */
|
||||
};
|
||||
#endif /* _ICE_LAN_TX_RX_H_ */
|
File diff suppressed because it is too large
Load Diff
@ -462,6 +462,18 @@ void ice_sched_cleanup_all(struct ice_hw *hw)
|
||||
hw->max_cgds = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_sched_get_qgrp_layer - get the current queue group layer number
|
||||
* @hw: pointer to the hw struct
|
||||
*
|
||||
* This function returns the current queue group layer number
|
||||
*/
|
||||
static u8 ice_sched_get_qgrp_layer(struct ice_hw *hw)
|
||||
{
|
||||
/* It's always total layers - 1, the array is 0 relative so -2 */
|
||||
return hw->num_tx_sched_layers - ICE_QGRP_LAYER_OFFSET;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_rm_dflt_leaf_node - remove the default leaf node in the tree
|
||||
* @pi: port information structure
|
||||
@ -666,3 +678,96 @@ sched_query_out:
|
||||
devm_kfree(ice_hw_to_dev(hw), buf);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_sched_get_vsi_info_entry - Get the vsi entry list for given vsi_id
|
||||
* @pi: port information structure
|
||||
* @vsi_id: vsi id
|
||||
*
|
||||
* This function retrieves the vsi list for the given vsi id
|
||||
*/
|
||||
static struct ice_sched_vsi_info *
|
||||
ice_sched_get_vsi_info_entry(struct ice_port_info *pi, u16 vsi_id)
|
||||
{
|
||||
struct ice_sched_vsi_info *list_elem;
|
||||
|
||||
if (!pi)
|
||||
return NULL;
|
||||
|
||||
list_for_each_entry(list_elem, &pi->vsi_info_list, list_entry)
|
||||
if (list_elem->vsi_id == vsi_id)
|
||||
return list_elem;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_sched_find_node_in_subtree - Find node in part of base node subtree
|
||||
* @hw: pointer to the hw struct
|
||||
* @base: pointer to the base node
|
||||
* @node: pointer to the node to search
|
||||
*
|
||||
* This function checks whether a given node is part of the base node
|
||||
* subtree or not
|
||||
*/
|
||||
static bool
|
||||
ice_sched_find_node_in_subtree(struct ice_hw *hw, struct ice_sched_node *base,
|
||||
struct ice_sched_node *node)
|
||||
{
|
||||
u8 i;
|
||||
|
||||
for (i = 0; i < base->num_children; i++) {
|
||||
struct ice_sched_node *child = base->children[i];
|
||||
|
||||
if (node == child)
|
||||
return true;
|
||||
if (child->tx_sched_layer > node->tx_sched_layer)
|
||||
return false;
|
||||
/* this recursion is intentional, and wouldn't
|
||||
* go more than 8 calls
|
||||
*/
|
||||
if (ice_sched_find_node_in_subtree(hw, child, node))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_sched_get_free_qparent - Get a free lan or rdma q group node
|
||||
* @pi: port information structure
|
||||
* @vsi_id: vsi id
|
||||
* @tc: branch number
|
||||
* @owner: lan or rdma
|
||||
*
|
||||
* This function retrieves a free lan or rdma q group node
|
||||
*/
|
||||
struct ice_sched_node *
|
||||
ice_sched_get_free_qparent(struct ice_port_info *pi, u16 vsi_id, u8 tc,
|
||||
u8 owner)
|
||||
{
|
||||
struct ice_sched_node *vsi_node, *qgrp_node = NULL;
|
||||
struct ice_sched_vsi_info *list_elem;
|
||||
u16 max_children;
|
||||
u8 qgrp_layer;
|
||||
|
||||
qgrp_layer = ice_sched_get_qgrp_layer(pi->hw);
|
||||
max_children = le16_to_cpu(pi->hw->layer_info[qgrp_layer].max_children);
|
||||
list_elem = ice_sched_get_vsi_info_entry(pi, vsi_id);
|
||||
if (!list_elem)
|
||||
goto lan_q_exit;
|
||||
vsi_node = list_elem->vsi_node[tc];
|
||||
/* validate invalid VSI id */
|
||||
if (!vsi_node)
|
||||
goto lan_q_exit;
|
||||
/* get the first q group node from VSI sub-tree */
|
||||
qgrp_node = ice_sched_get_first_node(pi->hw, vsi_node, qgrp_layer);
|
||||
while (qgrp_node) {
|
||||
/* make sure the qgroup node is part of the VSI subtree */
|
||||
if (ice_sched_find_node_in_subtree(pi->hw, vsi_node, qgrp_node))
|
||||
if (qgrp_node->num_children < max_children &&
|
||||
qgrp_node->owner == owner)
|
||||
break;
|
||||
qgrp_node = qgrp_node->sibling;
|
||||
}
|
||||
lan_q_exit:
|
||||
return qgrp_node;
|
||||
}
|
||||
|
@ -6,6 +6,8 @@
|
||||
|
||||
#include "ice_common.h"
|
||||
|
||||
#define ICE_QGRP_LAYER_OFFSET 2
|
||||
|
||||
struct ice_sched_agg_vsi_info {
|
||||
struct list_head list_entry;
|
||||
DECLARE_BITMAP(tc_bitmap, ICE_MAX_TRAFFIC_CLASS);
|
||||
@ -31,4 +33,7 @@ ice_sched_add_node(struct ice_port_info *pi, u8 layer,
|
||||
struct ice_aqc_txsched_elem_data *info);
|
||||
void ice_free_sched_node(struct ice_port_info *pi, struct ice_sched_node *node);
|
||||
struct ice_sched_node *ice_sched_get_tc_node(struct ice_port_info *pi, u8 tc);
|
||||
struct ice_sched_node *
|
||||
ice_sched_get_free_qparent(struct ice_port_info *pi, u16 vsi_id, u8 tc,
|
||||
u8 owner);
|
||||
#endif /* _ICE_SCHED_H_ */
|
||||
|
@ -9,6 +9,7 @@ enum ice_status {
|
||||
ICE_ERR_PARAM = -1,
|
||||
ICE_ERR_NOT_IMPL = -2,
|
||||
ICE_ERR_NOT_READY = -3,
|
||||
ICE_ERR_BAD_PTR = -5,
|
||||
ICE_ERR_INVAL_SIZE = -6,
|
||||
ICE_ERR_DEVICE_NOT_SUPPORTED = -8,
|
||||
ICE_ERR_RESET_FAILED = -9,
|
||||
@ -18,6 +19,7 @@ enum ice_status {
|
||||
ICE_ERR_OUT_OF_RANGE = -13,
|
||||
ICE_ERR_ALREADY_EXISTS = -14,
|
||||
ICE_ERR_DOES_NOT_EXIST = -15,
|
||||
ICE_ERR_MAX_LIMIT = -17,
|
||||
ICE_ERR_BUF_TOO_SHORT = -52,
|
||||
ICE_ERR_NVM_BLANK_MODE = -53,
|
||||
ICE_ERR_AQ_ERROR = -100,
|
||||
|
361
drivers/net/ethernet/intel/ice/ice_txrx.c
Normal file
361
drivers/net/ethernet/intel/ice/ice_txrx.c
Normal file
@ -0,0 +1,361 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) 2018, Intel Corporation. */
|
||||
|
||||
/* The driver transmit and receive code */
|
||||
|
||||
#include <linux/prefetch.h>
|
||||
#include <linux/mm.h>
|
||||
#include "ice.h"
|
||||
|
||||
/**
|
||||
* ice_unmap_and_free_tx_buf - Release a Tx buffer
|
||||
* @ring: the ring that owns the buffer
|
||||
* @tx_buf: the buffer to free
|
||||
*/
|
||||
static void
|
||||
ice_unmap_and_free_tx_buf(struct ice_ring *ring, struct ice_tx_buf *tx_buf)
|
||||
{
|
||||
if (tx_buf->skb) {
|
||||
dev_kfree_skb_any(tx_buf->skb);
|
||||
if (dma_unmap_len(tx_buf, len))
|
||||
dma_unmap_single(ring->dev,
|
||||
dma_unmap_addr(tx_buf, dma),
|
||||
dma_unmap_len(tx_buf, len),
|
||||
DMA_TO_DEVICE);
|
||||
} else if (dma_unmap_len(tx_buf, len)) {
|
||||
dma_unmap_page(ring->dev,
|
||||
dma_unmap_addr(tx_buf, dma),
|
||||
dma_unmap_len(tx_buf, len),
|
||||
DMA_TO_DEVICE);
|
||||
}
|
||||
|
||||
tx_buf->next_to_watch = NULL;
|
||||
tx_buf->skb = NULL;
|
||||
dma_unmap_len_set(tx_buf, len, 0);
|
||||
/* tx_buf must be completely set up in the transmit path */
|
||||
}
|
||||
|
||||
static struct netdev_queue *txring_txq(const struct ice_ring *ring)
|
||||
{
|
||||
return netdev_get_tx_queue(ring->netdev, ring->q_index);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_clean_tx_ring - Free any empty Tx buffers
|
||||
* @tx_ring: ring to be cleaned
|
||||
*/
|
||||
void ice_clean_tx_ring(struct ice_ring *tx_ring)
|
||||
{
|
||||
unsigned long size;
|
||||
u16 i;
|
||||
|
||||
/* ring already cleared, nothing to do */
|
||||
if (!tx_ring->tx_buf)
|
||||
return;
|
||||
|
||||
/* Free all the Tx ring sk_bufss */
|
||||
for (i = 0; i < tx_ring->count; i++)
|
||||
ice_unmap_and_free_tx_buf(tx_ring, &tx_ring->tx_buf[i]);
|
||||
|
||||
size = sizeof(struct ice_tx_buf) * tx_ring->count;
|
||||
memset(tx_ring->tx_buf, 0, size);
|
||||
|
||||
/* Zero out the descriptor ring */
|
||||
memset(tx_ring->desc, 0, tx_ring->size);
|
||||
|
||||
tx_ring->next_to_use = 0;
|
||||
tx_ring->next_to_clean = 0;
|
||||
|
||||
if (!tx_ring->netdev)
|
||||
return;
|
||||
|
||||
/* cleanup Tx queue statistics */
|
||||
netdev_tx_reset_queue(txring_txq(tx_ring));
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_free_tx_ring - Free Tx resources per queue
|
||||
* @tx_ring: Tx descriptor ring for a specific queue
|
||||
*
|
||||
* Free all transmit software resources
|
||||
*/
|
||||
void ice_free_tx_ring(struct ice_ring *tx_ring)
|
||||
{
|
||||
ice_clean_tx_ring(tx_ring);
|
||||
devm_kfree(tx_ring->dev, tx_ring->tx_buf);
|
||||
tx_ring->tx_buf = NULL;
|
||||
|
||||
if (tx_ring->desc) {
|
||||
dmam_free_coherent(tx_ring->dev, tx_ring->size,
|
||||
tx_ring->desc, tx_ring->dma);
|
||||
tx_ring->desc = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_setup_tx_ring - Allocate the Tx descriptors
|
||||
* @tx_ring: the tx ring to set up
|
||||
*
|
||||
* Return 0 on success, negative on error
|
||||
*/
|
||||
int ice_setup_tx_ring(struct ice_ring *tx_ring)
|
||||
{
|
||||
struct device *dev = tx_ring->dev;
|
||||
int bi_size;
|
||||
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
|
||||
/* warn if we are about to overwrite the pointer */
|
||||
WARN_ON(tx_ring->tx_buf);
|
||||
bi_size = sizeof(struct ice_tx_buf) * tx_ring->count;
|
||||
tx_ring->tx_buf = devm_kzalloc(dev, bi_size, GFP_KERNEL);
|
||||
if (!tx_ring->tx_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
/* round up to nearest 4K */
|
||||
tx_ring->size = tx_ring->count * sizeof(struct ice_tx_desc);
|
||||
tx_ring->size = ALIGN(tx_ring->size, 4096);
|
||||
tx_ring->desc = dmam_alloc_coherent(dev, tx_ring->size, &tx_ring->dma,
|
||||
GFP_KERNEL);
|
||||
if (!tx_ring->desc) {
|
||||
dev_err(dev, "Unable to allocate memory for the Tx descriptor ring, size=%d\n",
|
||||
tx_ring->size);
|
||||
goto err;
|
||||
}
|
||||
|
||||
tx_ring->next_to_use = 0;
|
||||
tx_ring->next_to_clean = 0;
|
||||
return 0;
|
||||
|
||||
err:
|
||||
devm_kfree(dev, tx_ring->tx_buf);
|
||||
tx_ring->tx_buf = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_clean_rx_ring - Free Rx buffers
|
||||
* @rx_ring: ring to be cleaned
|
||||
*/
|
||||
void ice_clean_rx_ring(struct ice_ring *rx_ring)
|
||||
{
|
||||
struct device *dev = rx_ring->dev;
|
||||
unsigned long size;
|
||||
u16 i;
|
||||
|
||||
/* ring already cleared, nothing to do */
|
||||
if (!rx_ring->rx_buf)
|
||||
return;
|
||||
|
||||
/* Free all the Rx ring sk_buffs */
|
||||
for (i = 0; i < rx_ring->count; i++) {
|
||||
struct ice_rx_buf *rx_buf = &rx_ring->rx_buf[i];
|
||||
|
||||
if (rx_buf->skb) {
|
||||
dev_kfree_skb(rx_buf->skb);
|
||||
rx_buf->skb = NULL;
|
||||
}
|
||||
if (!rx_buf->page)
|
||||
continue;
|
||||
|
||||
dma_unmap_page(dev, rx_buf->dma, PAGE_SIZE, DMA_FROM_DEVICE);
|
||||
__free_pages(rx_buf->page, 0);
|
||||
|
||||
rx_buf->page = NULL;
|
||||
rx_buf->page_offset = 0;
|
||||
}
|
||||
|
||||
size = sizeof(struct ice_rx_buf) * rx_ring->count;
|
||||
memset(rx_ring->rx_buf, 0, size);
|
||||
|
||||
/* Zero out the descriptor ring */
|
||||
memset(rx_ring->desc, 0, rx_ring->size);
|
||||
|
||||
rx_ring->next_to_alloc = 0;
|
||||
rx_ring->next_to_clean = 0;
|
||||
rx_ring->next_to_use = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_free_rx_ring - Free Rx resources
|
||||
* @rx_ring: ring to clean the resources from
|
||||
*
|
||||
* Free all receive software resources
|
||||
*/
|
||||
void ice_free_rx_ring(struct ice_ring *rx_ring)
|
||||
{
|
||||
ice_clean_rx_ring(rx_ring);
|
||||
devm_kfree(rx_ring->dev, rx_ring->rx_buf);
|
||||
rx_ring->rx_buf = NULL;
|
||||
|
||||
if (rx_ring->desc) {
|
||||
dmam_free_coherent(rx_ring->dev, rx_ring->size,
|
||||
rx_ring->desc, rx_ring->dma);
|
||||
rx_ring->desc = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_setup_rx_ring - Allocate the Rx descriptors
|
||||
* @rx_ring: the rx ring to set up
|
||||
*
|
||||
* Return 0 on success, negative on error
|
||||
*/
|
||||
int ice_setup_rx_ring(struct ice_ring *rx_ring)
|
||||
{
|
||||
struct device *dev = rx_ring->dev;
|
||||
int bi_size;
|
||||
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
|
||||
/* warn if we are about to overwrite the pointer */
|
||||
WARN_ON(rx_ring->rx_buf);
|
||||
bi_size = sizeof(struct ice_rx_buf) * rx_ring->count;
|
||||
rx_ring->rx_buf = devm_kzalloc(dev, bi_size, GFP_KERNEL);
|
||||
if (!rx_ring->rx_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
/* round up to nearest 4K */
|
||||
rx_ring->size = rx_ring->count * sizeof(union ice_32byte_rx_desc);
|
||||
rx_ring->size = ALIGN(rx_ring->size, 4096);
|
||||
rx_ring->desc = dmam_alloc_coherent(dev, rx_ring->size, &rx_ring->dma,
|
||||
GFP_KERNEL);
|
||||
if (!rx_ring->desc) {
|
||||
dev_err(dev, "Unable to allocate memory for the Rx descriptor ring, size=%d\n",
|
||||
rx_ring->size);
|
||||
goto err;
|
||||
}
|
||||
|
||||
rx_ring->next_to_use = 0;
|
||||
rx_ring->next_to_clean = 0;
|
||||
return 0;
|
||||
|
||||
err:
|
||||
devm_kfree(dev, rx_ring->rx_buf);
|
||||
rx_ring->rx_buf = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_release_rx_desc - Store the new tail and head values
|
||||
* @rx_ring: ring to bump
|
||||
* @val: new head index
|
||||
*/
|
||||
static void ice_release_rx_desc(struct ice_ring *rx_ring, u32 val)
|
||||
{
|
||||
rx_ring->next_to_use = val;
|
||||
|
||||
/* update next to alloc since we have filled the ring */
|
||||
rx_ring->next_to_alloc = val;
|
||||
|
||||
/* Force memory writes to complete before letting h/w
|
||||
* know there are new descriptors to fetch. (Only
|
||||
* applicable for weak-ordered memory model archs,
|
||||
* such as IA-64).
|
||||
*/
|
||||
wmb();
|
||||
writel(val, rx_ring->tail);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_alloc_mapped_page - recycle or make a new page
|
||||
* @rx_ring: ring to use
|
||||
* @bi: rx_buf struct to modify
|
||||
*
|
||||
* Returns true if the page was successfully allocated or
|
||||
* reused.
|
||||
*/
|
||||
static bool ice_alloc_mapped_page(struct ice_ring *rx_ring,
|
||||
struct ice_rx_buf *bi)
|
||||
{
|
||||
struct page *page = bi->page;
|
||||
dma_addr_t dma;
|
||||
|
||||
/* since we are recycling buffers we should seldom need to alloc */
|
||||
if (likely(page))
|
||||
return true;
|
||||
|
||||
/* alloc new page for storage */
|
||||
page = alloc_page(GFP_ATOMIC | __GFP_NOWARN);
|
||||
if (unlikely(!page))
|
||||
return false;
|
||||
|
||||
/* map page for use */
|
||||
dma = dma_map_page(rx_ring->dev, page, 0, PAGE_SIZE, DMA_FROM_DEVICE);
|
||||
|
||||
/* if mapping failed free memory back to system since
|
||||
* there isn't much point in holding memory we can't use
|
||||
*/
|
||||
if (dma_mapping_error(rx_ring->dev, dma)) {
|
||||
__free_pages(page, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
bi->dma = dma;
|
||||
bi->page = page;
|
||||
bi->page_offset = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_alloc_rx_bufs - Replace used receive buffers
|
||||
* @rx_ring: ring to place buffers on
|
||||
* @cleaned_count: number of buffers to replace
|
||||
*
|
||||
* Returns false if all allocations were successful, true if any fail
|
||||
*/
|
||||
bool ice_alloc_rx_bufs(struct ice_ring *rx_ring, u16 cleaned_count)
|
||||
{
|
||||
union ice_32b_rx_flex_desc *rx_desc;
|
||||
u16 ntu = rx_ring->next_to_use;
|
||||
struct ice_rx_buf *bi;
|
||||
|
||||
/* do nothing if no valid netdev defined */
|
||||
if (!rx_ring->netdev || !cleaned_count)
|
||||
return false;
|
||||
|
||||
/* get the RX descriptor and buffer based on next_to_use */
|
||||
rx_desc = ICE_RX_DESC(rx_ring, ntu);
|
||||
bi = &rx_ring->rx_buf[ntu];
|
||||
|
||||
do {
|
||||
if (!ice_alloc_mapped_page(rx_ring, bi))
|
||||
goto no_bufs;
|
||||
|
||||
/* Refresh the desc even if buffer_addrs didn't change
|
||||
* because each write-back erases this info.
|
||||
*/
|
||||
rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset);
|
||||
|
||||
rx_desc++;
|
||||
bi++;
|
||||
ntu++;
|
||||
if (unlikely(ntu == rx_ring->count)) {
|
||||
rx_desc = ICE_RX_DESC(rx_ring, 0);
|
||||
bi = rx_ring->rx_buf;
|
||||
ntu = 0;
|
||||
}
|
||||
|
||||
/* clear the status bits for the next_to_use descriptor */
|
||||
rx_desc->wb.status_error0 = 0;
|
||||
|
||||
cleaned_count--;
|
||||
} while (cleaned_count);
|
||||
|
||||
if (rx_ring->next_to_use != ntu)
|
||||
ice_release_rx_desc(rx_ring, ntu);
|
||||
|
||||
return false;
|
||||
|
||||
no_bufs:
|
||||
if (rx_ring->next_to_use != ntu)
|
||||
ice_release_rx_desc(rx_ring, ntu);
|
||||
|
||||
/* make sure to come back via polling to try again after
|
||||
* allocation failure
|
||||
*/
|
||||
return true;
|
||||
}
|
@ -5,6 +5,30 @@
|
||||
#define _ICE_TXRX_H_
|
||||
|
||||
#define ICE_DFLT_IRQ_WORK 256
|
||||
#define ICE_RXBUF_2048 2048
|
||||
#define ICE_MAX_CHAINED_RX_BUFS 5
|
||||
#define ICE_MAX_TXQ_PER_TXQG 128
|
||||
|
||||
#define ICE_DESC_UNUSED(R) \
|
||||
((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \
|
||||
(R)->next_to_clean - (R)->next_to_use - 1)
|
||||
|
||||
struct ice_tx_buf {
|
||||
struct ice_tx_desc *next_to_watch;
|
||||
struct sk_buff *skb;
|
||||
unsigned int bytecount;
|
||||
unsigned short gso_segs;
|
||||
u32 tx_flags;
|
||||
DEFINE_DMA_UNMAP_ADDR(dma);
|
||||
DEFINE_DMA_UNMAP_LEN(len);
|
||||
};
|
||||
|
||||
struct ice_rx_buf {
|
||||
struct sk_buff *skb;
|
||||
dma_addr_t dma;
|
||||
struct page *page;
|
||||
unsigned int page_offset;
|
||||
};
|
||||
|
||||
/* this enum matches hardware bits and is meant to be used by DYN_CTLN
|
||||
* registers and QINT registers or more generally anywhere in the manual
|
||||
@ -18,33 +42,77 @@ enum ice_dyn_idx_t {
|
||||
ICE_ITR_NONE = 3 /* ITR_NONE must not be used as an index */
|
||||
};
|
||||
|
||||
/* Header split modes defined by DTYPE field of Rx RLAN context */
|
||||
enum ice_rx_dtype {
|
||||
ICE_RX_DTYPE_NO_SPLIT = 0,
|
||||
ICE_RX_DTYPE_HEADER_SPLIT = 1,
|
||||
ICE_RX_DTYPE_SPLIT_ALWAYS = 2,
|
||||
};
|
||||
|
||||
/* indices into GLINT_ITR registers */
|
||||
#define ICE_RX_ITR ICE_IDX_ITR0
|
||||
#define ICE_TX_ITR ICE_IDX_ITR1
|
||||
#define ICE_ITR_DYNAMIC 0x8000 /* use top bit as a flag */
|
||||
#define ICE_ITR_8K 0x003E
|
||||
|
||||
/* apply ITR HW granularity translation to program the HW registers */
|
||||
#define ITR_TO_REG(val, itr_gran) (((val) & ~ICE_ITR_DYNAMIC) >> (itr_gran))
|
||||
|
||||
/* Legacy or Advanced Mode Queue */
|
||||
#define ICE_TX_ADVANCED 0
|
||||
#define ICE_TX_LEGACY 1
|
||||
|
||||
/* descriptor ring, associated with a VSI */
|
||||
struct ice_ring {
|
||||
struct ice_ring *next; /* pointer to next ring in q_vector */
|
||||
void *desc; /* Descriptor ring memory */
|
||||
struct device *dev; /* Used for DMA mapping */
|
||||
struct net_device *netdev; /* netdev ring maps to */
|
||||
struct ice_vsi *vsi; /* Backreference to associated VSI */
|
||||
struct ice_q_vector *q_vector; /* Backreference to associated vector */
|
||||
u8 __iomem *tail;
|
||||
union {
|
||||
struct ice_tx_buf *tx_buf;
|
||||
struct ice_rx_buf *rx_buf;
|
||||
};
|
||||
u16 q_index; /* Queue number of ring */
|
||||
u32 txq_teid; /* Added Tx queue TEID */
|
||||
|
||||
/* high bit set means dynamic, use accessor routines to read/write.
|
||||
* hardware supports 2us/1us resolution for the ITR registers.
|
||||
* these values always store the USER setting, and must be converted
|
||||
* before programming to a register.
|
||||
*/
|
||||
u16 rx_itr_setting;
|
||||
u16 tx_itr_setting;
|
||||
|
||||
u16 count; /* Number of descriptors */
|
||||
u16 reg_idx; /* HW register index of the ring */
|
||||
|
||||
/* used in interrupt processing */
|
||||
u16 next_to_use;
|
||||
u16 next_to_clean;
|
||||
|
||||
bool ring_active; /* is ring online or not */
|
||||
unsigned int size; /* length of descriptor ring in bytes */
|
||||
dma_addr_t dma; /* physical address of ring */
|
||||
struct rcu_head rcu; /* to avoid race on free */
|
||||
u16 next_to_alloc;
|
||||
} ____cacheline_internodealigned_in_smp;
|
||||
|
||||
enum ice_latency_range {
|
||||
ICE_LOWEST_LATENCY = 0,
|
||||
ICE_LOW_LATENCY = 1,
|
||||
ICE_BULK_LATENCY = 2,
|
||||
ICE_ULTRA_LATENCY = 3,
|
||||
};
|
||||
|
||||
struct ice_ring_container {
|
||||
/* array of pointers to rings */
|
||||
struct ice_ring *ring;
|
||||
unsigned int total_bytes; /* total bytes processed this int */
|
||||
unsigned int total_pkts; /* total packets processed this int */
|
||||
enum ice_latency_range latency_range;
|
||||
u16 itr;
|
||||
};
|
||||
|
||||
@ -52,4 +120,11 @@ struct ice_ring_container {
|
||||
#define ice_for_each_ring(pos, head) \
|
||||
for (pos = (head).ring; pos; pos = pos->next)
|
||||
|
||||
bool ice_alloc_rx_bufs(struct ice_ring *rxr, u16 cleaned_count);
|
||||
void ice_clean_tx_ring(struct ice_ring *tx_ring);
|
||||
void ice_clean_rx_ring(struct ice_ring *rx_ring);
|
||||
int ice_setup_tx_ring(struct ice_ring *tx_ring);
|
||||
int ice_setup_rx_ring(struct ice_ring *rx_ring);
|
||||
void ice_free_tx_ring(struct ice_ring *tx_ring);
|
||||
void ice_free_rx_ring(struct ice_ring *rx_ring);
|
||||
#endif /* _ICE_TXRX_H_ */
|
||||
|
@ -8,9 +8,11 @@
|
||||
#include "ice_hw_autogen.h"
|
||||
#include "ice_osdep.h"
|
||||
#include "ice_controlq.h"
|
||||
#include "ice_lan_tx_rx.h"
|
||||
|
||||
/* debug masks - set these bits in hw->debug_mask to control output */
|
||||
#define ICE_DBG_INIT BIT_ULL(1)
|
||||
#define ICE_DBG_QCTX BIT_ULL(6)
|
||||
#define ICE_DBG_NVM BIT_ULL(7)
|
||||
#define ICE_DBG_LAN BIT_ULL(8)
|
||||
#define ICE_DBG_SW BIT_ULL(13)
|
||||
|
Loading…
Reference in New Issue
Block a user