[v6,5/5] net/enetfec: add features
Checks
Commit Message
This patch adds checksum and VLAN offloads in enetfec network
poll mode driver.
Signed-off-by: Sachin Saxena <sachin.saxena@nxp.com>
Signed-off-by: Apeksha Gupta <apeksha.gupta@nxp.com>
---
doc/guides/nics/enetfec.rst | 2 ++
doc/guides/nics/features/enetfec.ini | 3 ++
drivers/net/enetfec/enet_ethdev.c | 17 ++++++++-
drivers/net/enetfec/enet_regs.h | 10 ++++++
drivers/net/enetfec/enet_rxtx.c | 53 +++++++++++++++++++++++++++-
5 files changed, 83 insertions(+), 2 deletions(-)
Comments
On 10/21/2021 5:47 AM, Apeksha Gupta wrote:
> This patch adds checksum and VLAN offloads in enetfec network
> poll mode driver.
>
> Signed-off-by: Sachin Saxena <sachin.saxena@nxp.com>
> Signed-off-by: Apeksha Gupta <apeksha.gupta@nxp.com>
<...>
> @@ -611,9 +615,20 @@ static int
> enetfec_eth_init(struct rte_eth_dev *dev)
> {
> struct enetfec_private *fep = dev->data->dev_private;
> + struct rte_eth_conf *eth_conf = &fep->dev->data->dev_conf;
> + uint64_t rx_offloads = eth_conf->rxmode.offloads;
>
> fep->full_duplex = FULL_DUPLEX;
> dev->dev_ops = &enetfec_ops;
> + if (fep->quirks & QUIRK_VLAN)
> + /* enable hw VLAN support */
> + rx_offloads |= DEV_RX_OFFLOAD_VLAN;
> +
> + if (fep->quirks & QUIRK_CSUM) {
> + /* enable hw accelerator */
> + rx_offloads |= DEV_RX_OFFLOAD_CHECKSUM;
> + fep->flag_csum |= RX_FLAG_CSUM_EN;
> + }
Driver is force enabling these Rx offloads even user is not asking for them?
Is it because HW doesn't support disabling them?
If it is configurable it should honor user configuration,
if not configurable please document as limitation.
<...>
> +
> + if (rxq->fep->bufdesc_ex &&
> + (rxq->fep->flag_csum & RX_FLAG_CSUM_EN)) {
> + if ((rte_read32(&ebdp->bd_esc) &
> + rte_cpu_to_le_32(RX_FLAG_CSUM_ERR)) == 0) {
> + /* don't check it */
> + mbuf->ol_flags = PKT_RX_IP_CKSUM_BAD;
warning: "PKT_RX_IP_CKSUM_BAD" is deprecated
> + } else {
> + mbuf->ol_flags = PKT_RX_IP_CKSUM_GOOD;
warning: "PKT_RX_IP_CKSUM_GOOD" is deprecated
> + }
> + }
> +
> + /* Handle received VLAN packets */
> + if (vlan_packet_rcvd) {
> + mbuf->vlan_tci = vlan_tag;
> + mbuf->ol_flags |= PKT_RX_VLAN_STRIPPED | PKT_RX_VLAN;
warning: "PKT_RX_VLAN_STRIPPED" is deprecated
warning: "PKT_RX_VLAN" is deprecated
> + }
> +
> rxq->rx_mbuf[index] = new_mbuf;
> rte_write32(rte_cpu_to_le_32(rte_pktmbuf_iova(new_mbuf)),
> &bdp->bd_bufaddr);
> @@ -411,6 +458,10 @@ enetfec_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
>
> if (txq->fep->bufdesc_ex) {
> struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
> +
> + if (mbuf->ol_flags == PKT_RX_IP_CKSUM_GOOD)
Why checking Rx flag on the transmit function? Is it typo?
@@ -84,6 +84,8 @@ ENETFEC Features
- Basic stats
- Promiscuous
+- VLAN offload
+- L3/L4 checksum offload
- Linux
- ARMv8
@@ -6,6 +6,9 @@
[Features]
Basic stats = Y
Promiscuous mode = Y
+VLAN offload = Y
+L3 checksum offload = Y
+L4 checksum offload = Y
Linux = Y
ARMv8 = Y
Usage doc = Y
@@ -106,7 +106,11 @@ enetfec_restart(struct rte_eth_dev *dev)
val = rte_read32((uint8_t *)fep->hw_baseaddr_v + ENETFEC_RACC);
/* align IP header */
val |= ENETFEC_RACC_SHIFT16;
- val &= ~ENETFEC_RACC_OPTIONS;
+ if (fep->flag_csum & RX_FLAG_CSUM_EN)
+ /* set RX checksum */
+ val |= ENETFEC_RACC_OPTIONS;
+ else
+ val &= ~ENETFEC_RACC_OPTIONS;
rte_write32(rte_cpu_to_le_32(val),
(uint8_t *)fep->hw_baseaddr_v + ENETFEC_RACC);
rte_write32(rte_cpu_to_le_32(PKT_MAX_BUF_SIZE),
@@ -611,9 +615,20 @@ static int
enetfec_eth_init(struct rte_eth_dev *dev)
{
struct enetfec_private *fep = dev->data->dev_private;
+ struct rte_eth_conf *eth_conf = &fep->dev->data->dev_conf;
+ uint64_t rx_offloads = eth_conf->rxmode.offloads;
fep->full_duplex = FULL_DUPLEX;
dev->dev_ops = &enetfec_ops;
+ if (fep->quirks & QUIRK_VLAN)
+ /* enable hw VLAN support */
+ rx_offloads |= DEV_RX_OFFLOAD_VLAN;
+
+ if (fep->quirks & QUIRK_CSUM) {
+ /* enable hw accelerator */
+ rx_offloads |= DEV_RX_OFFLOAD_CHECKSUM;
+ fep->flag_csum |= RX_FLAG_CSUM_EN;
+ }
rte_eth_dev_probing_finish(dev);
return 0;
@@ -27,6 +27,12 @@
#define RX_BD_EMPTY ((ushort)0x8000) /* BD is empty */
#define RX_BD_STATS ((ushort)0x013f) /* All buffer descriptor status bits */
+/* Ethernet receive use control and status of enhanced buffer descriptor */
+#define BD_ENETFEC_RX_VLAN 0x00000004
+
+#define RX_FLAG_CSUM_EN (RX_BD_ICE | RX_BD_PCR)
+#define RX_FLAG_CSUM_ERR (RX_BD_ICE | RX_BD_PCR)
+
/* Ethernet transmit use control and status of buffer descriptor */
#define TX_BD_TC ((ushort)0x0400) /* Transmit CRC */
#define TX_BD_LAST ((ushort)0x0800) /* Last in frame */
@@ -56,6 +62,10 @@
#define QUIRK_HAS_ENETFEC_MAC (1 << 0)
/* GBIT supported in controller */
#define QUIRK_GBIT (1 << 3)
+/* Controller support hardware checksum */
+#define QUIRK_CSUM (1 << 5)
+/* Controller support hardware vlan */
+#define QUIRK_VLAN (1 << 6)
/* RACC register supported by controller */
#define QUIRK_RACC (1 << 12)
/* i.MX8 ENETFEC IP version added the feature to generate the delayed TXC or
@@ -245,9 +245,14 @@ enetfec_recv_pkts(void *rxq1, __rte_unused struct rte_mbuf **rx_pkts,
unsigned short status;
unsigned short pkt_len;
int pkt_received = 0, index = 0;
- void *data;
+ void *data, *mbuf_data;
+ uint16_t vlan_tag;
+ struct bufdesc_ex *ebdp = NULL;
+ bool vlan_packet_rcvd = false;
struct enetfec_priv_rx_q *rxq = (struct enetfec_priv_rx_q *)rxq1;
struct rte_eth_stats *stats = &rxq->fep->stats;
+ struct rte_eth_conf *eth_conf = &rxq->fep->dev->data->dev_conf;
+ uint64_t rx_offloads = eth_conf->rxmode.offloads;
pool = rxq->pool;
bdp = rxq->bd.cur;
#if ENETFEC_LOOPBACK
@@ -302,6 +307,7 @@ enetfec_recv_pkts(void *rxq1, __rte_unused struct rte_mbuf **rx_pkts,
mbuf = rxq->rx_mbuf[index];
data = rte_pktmbuf_mtod(mbuf, uint8_t *);
+ mbuf_data = data;
rte_prefetch0(data);
rte_pktmbuf_append((struct rte_mbuf *)mbuf,
pkt_len - 4);
@@ -311,6 +317,47 @@ enetfec_recv_pkts(void *rxq1, __rte_unused struct rte_mbuf **rx_pkts,
rx_pkts[pkt_received] = mbuf;
pkt_received++;
+
+ /* Extract the enhanced buffer descriptor */
+ ebdp = NULL;
+ if (rxq->fep->bufdesc_ex)
+ ebdp = (struct bufdesc_ex *)bdp;
+
+ /* If this is a VLAN packet remove the VLAN Tag */
+ vlan_packet_rcvd = false;
+ if ((rx_offloads & DEV_RX_OFFLOAD_VLAN) &&
+ rxq->fep->bufdesc_ex &&
+ (rte_read32(&ebdp->bd_esc) &
+ rte_cpu_to_le_32(BD_ENETFEC_RX_VLAN))) {
+ /* Push and remove the vlan tag */
+ struct rte_vlan_hdr *vlan_header =
+ (struct rte_vlan_hdr *)
+ ((uint8_t *)data + ETH_HLEN);
+ vlan_tag = rte_be_to_cpu_16(vlan_header->vlan_tci);
+
+ vlan_packet_rcvd = true;
+ memmove((uint8_t *)mbuf_data + VLAN_HLEN,
+ data, ETH_ALEN * 2);
+ rte_pktmbuf_adj(mbuf, VLAN_HLEN);
+ }
+
+ if (rxq->fep->bufdesc_ex &&
+ (rxq->fep->flag_csum & RX_FLAG_CSUM_EN)) {
+ if ((rte_read32(&ebdp->bd_esc) &
+ rte_cpu_to_le_32(RX_FLAG_CSUM_ERR)) == 0) {
+ /* don't check it */
+ mbuf->ol_flags = PKT_RX_IP_CKSUM_BAD;
+ } else {
+ mbuf->ol_flags = PKT_RX_IP_CKSUM_GOOD;
+ }
+ }
+
+ /* Handle received VLAN packets */
+ if (vlan_packet_rcvd) {
+ mbuf->vlan_tci = vlan_tag;
+ mbuf->ol_flags |= PKT_RX_VLAN_STRIPPED | PKT_RX_VLAN;
+ }
+
rxq->rx_mbuf[index] = new_mbuf;
rte_write32(rte_cpu_to_le_32(rte_pktmbuf_iova(new_mbuf)),
&bdp->bd_bufaddr);
@@ -411,6 +458,10 @@ enetfec_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
if (txq->fep->bufdesc_ex) {
struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
+
+ if (mbuf->ol_flags == PKT_RX_IP_CKSUM_GOOD)
+ estatus |= TX_BD_PINS | TX_BD_IINS;
+
rte_write32(0, &ebdp->bd_bdu);
rte_write32(rte_cpu_to_le_32(estatus),
&ebdp->bd_esc);