#define HNS3_CFG_NIC_ROCE_SEL_B 4
#define HNS3_ACCEPT_TAG2_B 5
#define HNS3_ACCEPT_UNTAG2_B 6
+#define HNS3_TAG_SHIFT_MODE_EN_B 7
#define HNS3_REM_TAG1_EN_B 0
#define HNS3_REM_TAG2_EN_B 1
#define HNS3_SHOW_TAG1_EN_B 2
#define HNS3_SHOW_TAG2_EN_B 3
+#define HNS3_DISCARD_TAG1_EN_B 5
+#define HNS3_DISCARD_TAG2_EN_B 6
/* Factor used to calculate offset and bitmap of VF num */
#define HNS3_VF_NUM_PER_CMD 64
hns3_set_bit(req->vport_vlan_cfg, HNS3_SHOW_TAG2_EN_B,
vcfg->vlan2_vlan_prionly ? 1 : 0);
+ /* firmwall will ignore this configuration for PCI_REVISION_ID_HIP08 */
+ hns3_set_bit(req->vport_vlan_cfg, HNS3_DISCARD_TAG1_EN_B,
+ vcfg->strip_tag1_discard_en ? 1 : 0);
+ hns3_set_bit(req->vport_vlan_cfg, HNS3_DISCARD_TAG2_EN_B,
+ vcfg->strip_tag2_discard_en ? 1 : 0);
/*
* In current version VF is not supported when PF is driven by DPDK
* driver, just need to configure parameters for PF vport.
if (hw->port_base_vlan_cfg.state == HNS3_PORT_BASE_VLAN_DISABLE) {
rxvlan_cfg.strip_tag1_en = false;
rxvlan_cfg.strip_tag2_en = enable;
+ rxvlan_cfg.strip_tag2_discard_en = false;
} else {
rxvlan_cfg.strip_tag1_en = enable;
rxvlan_cfg.strip_tag2_en = true;
+ rxvlan_cfg.strip_tag2_discard_en = true;
}
+ rxvlan_cfg.strip_tag1_discard_en = false;
rxvlan_cfg.vlan1_vlan_prionly = false;
rxvlan_cfg.vlan2_vlan_prionly = false;
rxvlan_cfg.rx_vlan_offload_en = enable;
vcfg->insert_tag2_en ? 1 : 0);
hns3_set_bit(req->vport_vlan_cfg, HNS3_CFG_NIC_ROCE_SEL_B, 0);
+ /* firmwall will ignore this configuration for PCI_REVISION_ID_HIP08 */
+ hns3_set_bit(req->vport_vlan_cfg, HNS3_TAG_SHIFT_MODE_EN_B,
+ vcfg->tag_shift_mode_en ? 1 : 0);
+
/*
* In current version VF is not supported when PF is driven by DPDK
* driver, just need to configure parameters for PF vport.
txvlan_cfg.insert_tag1_en = false;
txvlan_cfg.default_tag1 = 0;
} else {
- txvlan_cfg.accept_tag1 = false;
+ txvlan_cfg.accept_tag1 =
+ hw->vlan_mode == HNS3_HW_SHIFT_AND_DISCARD_MODE;
txvlan_cfg.insert_tag1_en = true;
txvlan_cfg.default_tag1 = pvid;
}
txvlan_cfg.accept_untag2 = true;
txvlan_cfg.insert_tag2_en = false;
txvlan_cfg.default_tag2 = 0;
+ txvlan_cfg.tag_shift_mode_en = true;
ret = hns3_set_vlan_tx_offload_cfg(hns, &txvlan_cfg);
if (ret) {
bool rx_strip_en;
int ret;
- rx_strip_en = old_cfg->rx_vlan_offload_en ? true : false;
+ rx_strip_en = old_cfg->rx_vlan_offload_en;
if (on) {
rx_vlan_cfg.strip_tag1_en = rx_strip_en;
rx_vlan_cfg.strip_tag2_en = true;
+ rx_vlan_cfg.strip_tag2_discard_en = true;
} else {
rx_vlan_cfg.strip_tag1_en = false;
rx_vlan_cfg.strip_tag2_en = rx_strip_en;
+ rx_vlan_cfg.strip_tag2_discard_en = false;
}
+ rx_vlan_cfg.strip_tag1_discard_en = false;
rx_vlan_cfg.vlan1_vlan_prionly = false;
rx_vlan_cfg.vlan2_vlan_prionly = false;
rx_vlan_cfg.rx_vlan_offload_en = old_cfg->rx_vlan_offload_en;
rte_spinlock_unlock(&hw->lock);
if (ret)
return ret;
-
- if (pvid_en_state_change)
- hns3_update_all_queues_pvid_state(hw);
+ /*
+ * Only in HNS3_SW_SHIFT_AND_MODE the PVID related operation in Tx/Rx
+ * need be processed by PMD driver.
+ */
+ if (pvid_en_state_change &&
+ hw->vlan_mode == HNS3_SW_SHIFT_AND_DISCARD_MODE)
+ hns3_update_all_queues_pvid_proc_en(hw);
return 0;
}
hw->intr.mapping_mode = HNS3_INTR_MAPPING_VEC_RSV_ONE;
hw->intr.coalesce_mode = HNS3_INTR_COALESCE_NON_QL;
hw->intr.gl_unit = HNS3_INTR_COALESCE_GL_UINT_2US;
+ hw->vlan_mode = HNS3_SW_SHIFT_AND_DISCARD_MODE;
hw->min_tx_pkt_len = HNS3_HIP08_MIN_TX_PKT_LEN;
return 0;
}
hw->intr.mapping_mode = HNS3_INTR_MAPPING_VEC_ALL;
hw->intr.coalesce_mode = HNS3_INTR_COALESCE_QL;
hw->intr.gl_unit = HNS3_INTR_COALESCE_GL_UINT_1US;
+ hw->vlan_mode = HNS3_HW_SHIFT_AND_DISCARD_MODE;
hw->min_tx_pkt_len = HNS3_HIP09_MIN_TX_PKT_LEN;
return 0;
#define HNS3_PF_FUNC_ID 0
#define HNS3_1ST_VF_FUNC_ID 1
+#define HNS3_SW_SHIFT_AND_DISCARD_MODE 0
+#define HNS3_HW_SHIFT_AND_DISCARD_MODE 1
+
#define HNS3_UC_MACADDR_NUM 128
#define HNS3_VF_UC_MACADDR_NUM 48
#define HNS3_MC_MACADDR_NUM 128
struct hns3_queue_intr intr;
+ /*
+ * vlan mode.
+ * value range:
+ * HNS3_SW_SHIFT_AND_DISCARD_MODE/HNS3_HW_SHFIT_AND_DISCARD_MODE
+ *
+ * - HNS3_SW_SHIFT_AND_DISCARD_MODE
+ * For some versions of hardware network engine, because of the
+ * hardware limitation, PMD driver needs to detect the PVID status
+ * to work with haredware to implement PVID-related functions.
+ * For example, driver need discard the stripped PVID tag to ensure
+ * the PVID will not report to mbuf and shift the inserted VLAN tag
+ * to avoid port based VLAN covering it.
+ *
+ * - HNS3_HW_SHIT_AND_DISCARD_MODE
+ * PMD driver does not need to process PVID-related functions in
+ * I/O process, Hardware will adjust the sequence between port based
+ * VLAN tag and BD VLAN tag automatically and VLAN tag stripped by
+ * PVID will be invisible to driver. And in this mode, hns3 is able
+ * to send a multi-layer VLAN packets when hw VLAN insert offload
+ * is enabled.
+ */
+ uint8_t vlan_mode;
uint8_t max_non_tso_bd_num; /* max BD number of one non-TSO packet */
struct hns3_port_base_vlan_config port_base_vlan_cfg;
/* Vlan tag configuration for RX direction */
struct hns3_rx_vtag_cfg {
- uint8_t rx_vlan_offload_en; /* Whether enable rx vlan offload */
- uint8_t strip_tag1_en; /* Whether strip inner vlan tag */
- uint8_t strip_tag2_en; /* Whether strip outer vlan tag */
- uint8_t vlan1_vlan_prionly; /* Inner VLAN Tag up to descriptor Enable */
- uint8_t vlan2_vlan_prionly; /* Outer VLAN Tag up to descriptor Enable */
+ bool rx_vlan_offload_en; /* Whether enable rx vlan offload */
+ bool strip_tag1_en; /* Whether strip inner vlan tag */
+ bool strip_tag2_en; /* Whether strip outer vlan tag */
+ /*
+ * If strip_tag_en is enabled, this bit decide whether to map the vlan
+ * tag to descriptor.
+ */
+ bool strip_tag1_discard_en;
+ bool strip_tag2_discard_en;
+ /*
+ * If this bit is enabled, only map inner/outer priority to descriptor
+ * and the vlan tag is always 0.
+ */
+ bool vlan1_vlan_prionly;
+ bool vlan2_vlan_prionly;
};
/* Vlan tag configuration for TX direction */
bool accept_untag1; /* Whether accept untag1 packet from host */
bool accept_tag2;
bool accept_untag2;
- bool insert_tag1_en; /* Whether insert inner vlan tag */
- bool insert_tag2_en; /* Whether insert outer vlan tag */
- uint16_t default_tag1; /* The default inner vlan tag to insert */
- uint16_t default_tag2; /* The default outer vlan tag to insert */
+ bool insert_tag1_en; /* Whether insert outer vlan tag */
+ bool insert_tag2_en; /* Whether insert inner vlan tag */
+ /*
+ * In shift mode, hw will shift the sequence of port based VLAN and
+ * BD VLAN.
+ */
+ bool tag_shift_mode_en; /* hw shift vlan tag automatically */
+ uint16_t default_tag1; /* The default outer vlan tag to insert */
+ uint16_t default_tag2; /* The default inner vlan tag to insert */
};
struct hns3_vtag_cfg {
*/
if (hw->port_base_vlan_cfg.state != new_pvid_state) {
hw->port_base_vlan_cfg.state = new_pvid_state;
- hns3_update_all_queues_pvid_state(hw);
+ hns3_update_all_queues_pvid_proc_en(hw);
}
}
}
void
-hns3_update_all_queues_pvid_state(struct hns3_hw *hw)
+hns3_update_all_queues_pvid_proc_en(struct hns3_hw *hw)
{
uint16_t nb_rx_q = hw->data->nb_rx_queues;
uint16_t nb_tx_q = hw->data->nb_tx_queues;
struct hns3_rx_queue *rxq;
struct hns3_tx_queue *txq;
- int pvid_state;
+ bool pvid_en;
int i;
- pvid_state = hw->port_base_vlan_cfg.state;
+ pvid_en = hw->port_base_vlan_cfg.state == HNS3_PORT_BASE_VLAN_ENABLE;
for (i = 0; i < hw->cfg_max_queues; i++) {
if (i < nb_rx_q) {
rxq = hw->data->rx_queues[i];
if (rxq != NULL)
- rxq->pvid_state = pvid_state;
+ rxq->pvid_sw_discard_en = pvid_en;
}
if (i < nb_tx_q) {
txq = hw->data->tx_queues[i];
if (txq != NULL)
- txq->pvid_state = pvid_state;
+ txq->pvid_sw_shift_en = pvid_en;
}
}
}
rxq->pkt_first_seg = NULL;
rxq->pkt_last_seg = NULL;
rxq->port_id = dev->data->port_id;
- rxq->pvid_state = hw->port_base_vlan_cfg.state;
+ /*
+ * For hns3 PF device, if the VLAN mode is HW_SHIFT_AND_DISCARD_MODE,
+ * the pvid_sw_discard_en in the queue struct should not be changed,
+ * because PVID-related operations do not need to be processed by PMD
+ * driver. For hns3 VF device, whether it needs to process PVID depends
+ * on the configuration of PF kernel mode netdevice driver. And the
+ * related PF configuration is delivered through the mailbox and finally
+ * reflectd in port_base_vlan_cfg.
+ */
+ if (hns->is_vf || hw->vlan_mode == HNS3_SW_SHIFT_AND_DISCARD_MODE)
+ rxq->pvid_sw_discard_en = hw->port_base_vlan_cfg.state ==
+ HNS3_PORT_BASE_VLAN_ENABLE;
+ else
+ rxq->pvid_sw_discard_en = false;
rxq->configured = true;
rxq->io_base = (void *)((char *)hw->io_base + HNS3_TQP_REG_OFFSET +
idx * HNS3_TQP_REG_SIZE);
};
strip_status = hns3_get_field(l234_info, HNS3_RXD_STRP_TAGP_M,
HNS3_RXD_STRP_TAGP_S);
- report_mode = report_type[rxq->pvid_state][strip_status];
+ report_mode = report_type[rxq->pvid_sw_discard_en][strip_status];
switch (report_mode) {
case HNS3_NO_STRP_VLAN_VLD:
mb->vlan_tci = 0;
}
txq->port_id = dev->data->port_id;
- txq->pvid_state = hw->port_base_vlan_cfg.state;
+ /*
+ * For hns3 PF device, if the VLAN mode is HW_SHIFT_AND_DISCARD_MODE,
+ * the pvid_sw_shift_en in the queue struct should not be changed,
+ * because PVID-related operations do not need to be processed by PMD
+ * driver. For hns3 VF device, whether it needs to process PVID depends
+ * on the configuration of PF kernel mode netdev driver. And the
+ * related PF configuration is delivered through the mailbox and finally
+ * reflectd in port_base_vlan_cfg.
+ */
+ if (hns->is_vf || hw->vlan_mode == HNS3_SW_SHIFT_AND_DISCARD_MODE)
+ txq->pvid_sw_shift_en = hw->port_base_vlan_cfg.state ==
+ HNS3_PORT_BASE_VLAN_ENABLE;
+ else
+ txq->pvid_sw_shift_en = false;
txq->configured = true;
txq->io_base = (void *)((char *)hw->io_base + HNS3_TQP_REG_OFFSET +
idx * HNS3_TQP_REG_SIZE);
* To avoid the VLAN of Tx descriptor is overwritten by PVID, it should
* be added to the position close to the IP header when PVID is enabled.
*/
- if (!txq->pvid_state && ol_flags & (PKT_TX_VLAN_PKT |
+ if (!txq->pvid_sw_shift_en && ol_flags & (PKT_TX_VLAN_PKT |
PKT_TX_QINQ_PKT)) {
desc->tx.ol_type_vlan_len_msec |=
rte_cpu_to_le_32(BIT(HNS3_TXD_OVLAN_B));
}
if (ol_flags & PKT_TX_QINQ_PKT ||
- ((ol_flags & PKT_TX_VLAN_PKT) && txq->pvid_state)) {
+ ((ol_flags & PKT_TX_VLAN_PKT) && txq->pvid_sw_shift_en)) {
desc->tx.type_cs_vlan_tso_len |=
rte_cpu_to_le_32(BIT(HNS3_TXD_VLAN_B));
desc->tx.vlan_tag = rte_cpu_to_le_16(rxm->vlan_tci);
struct rte_ether_hdr *eh;
struct rte_vlan_hdr *vh;
- if (!txq->pvid_state)
+ if (!txq->pvid_sw_shift_en)
return 0;
/*
uint64_t rx_ring_phys_addr; /* RX ring DMA address */
const struct rte_memzone *mz;
struct hns3_entry *sw_ring;
-
struct rte_mbuf *pkt_first_seg;
struct rte_mbuf *pkt_last_seg;
uint16_t rx_free_hold; /* num of BDs waited to passed to hardware */
uint16_t rx_rearm_start; /* index of BD that driver re-arming from */
uint16_t rx_rearm_nb; /* number of remaining BDs to be re-armed */
- /*
- * port based vlan configuration state.
- * value range: HNS3_PORT_BASE_VLAN_DISABLE / HNS3_PORT_BASE_VLAN_ENABLE
- */
- uint16_t pvid_state;
/* 4 if DEV_RX_OFFLOAD_KEEP_CRC offload set, 0 otherwise */
uint8_t crc_len;
bool rx_deferred_start; /* don't start this queue in dev start */
bool configured; /* indicate if rx queue has been configured */
+ /*
+ * Indicate whether ignore the outer VLAN field in the Rx BD reported
+ * by the Hardware. Because the outer VLAN is the PVID if the PVID is
+ * set for some version of hardware network engine whose vlan mode is
+ * HNS3_SW_SHIFT_AND_DISCARD_MODE, such as kunpeng 920. And this VLAN
+ * should not be transitted to the upper-layer application. For hardware
+ * network engine whose vlan mode is HNS3_HW_SHIFT_AND_DISCARD_MODE,
+ * such as kunpeng 930, PVID will not be reported to the BDs. So, PMD
+ * driver does not need to perform PVID-related operation in Rx. At this
+ * point, the pvid_sw_discard_en will be false.
+ */
+ bool pvid_sw_discard_en;
uint64_t l2_errors;
uint64_t pkt_len_errors;
uint16_t tx_rs_thresh;
struct rte_mbuf **free;
- /*
- * port based vlan configuration state.
- * value range: HNS3_PORT_BASE_VLAN_DISABLE / HNS3_PORT_BASE_VLAN_ENABLE
- */
- uint16_t pvid_state;
-
/*
* The minimum length of the packet supported by hardware in the Tx
* direction.
bool tx_deferred_start; /* don't start this queue in dev start */
bool configured; /* indicate if tx queue has been configured */
+ /*
+ * Indicate whether add the vlan_tci of the mbuf to the inner VLAN field
+ * of Tx BD. Because the outer VLAN will always be the PVID when the
+ * PVID is set and for some version of hardware network engine whose
+ * vlan mode is HNS3_SW_SHIFT_AND_DISCARD_MODE, such as kunpeng 920, the
+ * PVID will overwrite the outer VLAN field of Tx BD. For the hardware
+ * network engine whose vlan mode is HNS3_HW_SHIFT_AND_DISCARD_MODE,
+ * such as kunpeng 930, if the PVID is set, the hardware will shift the
+ * VLAN field automatically. So, PMD driver does not need to do
+ * PVID-related operations in Tx. And pvid_sw_shift_en will be false at
+ * this point.
+ */
+ bool pvid_sw_shift_en;
/*
* The following items are used for the abnormal errors statistics in
uint16_t nb_tx_q);
int hns3_config_gro(struct hns3_hw *hw, bool en);
int hns3_restore_gro_conf(struct hns3_hw *hw);
-void hns3_update_all_queues_pvid_state(struct hns3_hw *hw);
+void hns3_update_all_queues_pvid_proc_en(struct hns3_hw *hw);
void hns3_rx_scattered_reset(struct rte_eth_dev *dev);
void hns3_rx_scattered_calc(struct rte_eth_dev *dev);
int hns3_rx_check_vec_support(struct rte_eth_dev *dev);