From ec95665467d262660582f5dff7624d461551c8a9 Mon Sep 17 00:00:00 2001 From: Bhadram Varka Date: Wed, 20 Mar 2019 10:11:06 +0530 Subject: [PATCH] nvethernet: support for VLAN Adds support for VLAN tag insertion on Tx path and parsing of VLAN tag on receive path. Bug 200511721 Change-Id: I07d4a576873bae61267244c9eb03a777f515a761 Signed-off-by: Bhadram Varka Reviewed-on: https://git-master.nvidia.com/r/2077037 Reviewed-by: Bitan Biswas Reviewed-by: mobile promotions Tested-by: mobile promotions --- .../ethernet/nvidia/nvethernet/ether_linux.c | 26 +++++++++++++++++++ .../ethernet/nvidia/nvethernet/ether_linux.h | 1 + drivers/net/ethernet/nvidia/nvethernet/osd.c | 11 ++++++-- 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/nvidia/nvethernet/ether_linux.c b/drivers/net/ethernet/nvidia/nvethernet/ether_linux.c index 1e9e4af6..591ff2c4 100644 --- a/drivers/net/ethernet/nvidia/nvethernet/ether_linux.c +++ b/drivers/net/ethernet/nvidia/nvethernet/ether_linux.c @@ -991,11 +991,29 @@ static int ether_tx_swcx_alloc(struct device *dev, struct osi_tx_ring *tx_ring, struct sk_buff *skb) { + struct osi_tx_pkt_cx *tx_pkt_cx = &tx_ring->tx_pkt_cx; unsigned int cur_tx_idx = tx_ring->cur_tx_idx; struct osi_tx_swcx *tx_swcx = NULL; unsigned int len = 0; int cnt = 0; + memset(tx_pkt_cx, 0, sizeof(*tx_pkt_cx)); + + if (unlikely(skb_vlan_tag_present(skb))) { + tx_pkt_cx->vtag_id = skb_vlan_tag_get(skb); + tx_pkt_cx->vtag_id |= (skb->priority << VLAN_PRIO_SHIFT); + tx_pkt_cx->flags = OSI_PKT_CX_VLAN; + + tx_swcx = tx_ring->tx_swcx + cur_tx_idx; + if (tx_swcx->len) { + return 0; + } + + tx_swcx->len = -1; + cnt++; + INCR_TX_DESC_INDEX(cur_tx_idx, 1U); + } + len = skb_headlen(skb); tx_swcx = tx_ring->tx_swcx + cur_tx_idx; @@ -1015,6 +1033,8 @@ static int ether_tx_swcx_alloc(struct device *dev, cnt++; + tx_pkt_cx->desc_cnt = cnt; + return cnt; } @@ -2016,6 +2036,12 @@ static int ether_probe(struct platform_device *pdev) } ndev->netdev_ops = ðer_netdev_ops; + ndev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX; + if (pdata->hw_feat.sa_vlan_ins) { + ndev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX; + } + + ndev->features |= ndev->hw_features; ret = ether_alloc_napi(pdata); if (ret < 0) { diff --git a/drivers/net/ethernet/nvidia/nvethernet/ether_linux.h b/drivers/net/ethernet/nvidia/nvethernet/ether_linux.h index c464edaf..6fc826e6 100644 --- a/drivers/net/ethernet/nvidia/nvethernet/ether_linux.h +++ b/drivers/net/ethernet/nvidia/nvethernet/ether_linux.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/net/ethernet/nvidia/nvethernet/osd.c b/drivers/net/ethernet/nvidia/nvethernet/osd.c index 992ef229..6154e269 100644 --- a/drivers/net/ethernet/nvidia/nvethernet/osd.c +++ b/drivers/net/ethernet/nvidia/nvethernet/osd.c @@ -212,18 +212,25 @@ static void ether_realloc_rx_skb(struct ether_priv_data *pdata, * Return: None. */ void osd_receive_packet(void *priv, void *rxring, unsigned int chan, - unsigned int dma_buf_len, unsigned int rx_pkt_len) + unsigned int dma_buf_len, void *rxpkt_cx) { struct ether_priv_data *pdata = (struct ether_priv_data *)priv; struct osi_rx_ring *rx_ring = (struct osi_rx_ring *)rxring; struct osi_rx_swcx *rx_swcx = rx_ring->rx_swcx + rx_ring->cur_rx_idx; + struct osi_rx_pkt_cx *rx_pkt_cx = (struct osi_rx_pkt_cx *)rxpkt_cx; struct sk_buff *skb = (struct sk_buff *)rx_swcx->buf_virt_addr; dma_addr_t dma_addr = (dma_addr_t)rx_swcx->buf_phy_addr; struct net_device *ndev = pdata->ndev; dma_unmap_single(pdata->dev, dma_addr, dma_buf_len, DMA_FROM_DEVICE); - skb_put(skb, rx_pkt_len); + skb_put(skb, rx_pkt_cx->pkt_len); + + if ((rx_pkt_cx->flags & OSI_PKT_CX_VLAN) == OSI_PKT_CX_VLAN) { + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), + rx_pkt_cx->vlan_tag); + } + skb->dev = ndev; skb->protocol = eth_type_trans(skb, ndev); ndev->stats.rx_packets++;