Commit 91bf82ca authored by Simon Horman's avatar Simon Horman Committed by David S. Miller

nfp: add support for tx/rx with metadata portid

Allow tx/rx with metadata port id. This will be used for tx/rx of
representor netdevs acting as upper-devices while a pf netdev acts
as a lower-device.
Signed-off-by: default avatarSimon Horman <simon.horman@netronome.com>
Reviewed-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 93da7d96
...@@ -318,6 +318,7 @@ struct nfp_meta_parsed { ...@@ -318,6 +318,7 @@ struct nfp_meta_parsed {
u8 csum_type; u8 csum_type;
u32 hash; u32 hash;
u32 mark; u32 mark;
u32 portid;
__wsum csum; __wsum csum;
}; };
......
...@@ -755,6 +755,26 @@ static void nfp_net_tx_xmit_more_flush(struct nfp_net_tx_ring *tx_ring) ...@@ -755,6 +755,26 @@ static void nfp_net_tx_xmit_more_flush(struct nfp_net_tx_ring *tx_ring)
tx_ring->wr_ptr_add = 0; tx_ring->wr_ptr_add = 0;
} }
static int nfp_net_prep_port_id(struct sk_buff *skb)
{
struct metadata_dst *md_dst = skb_metadata_dst(skb);
unsigned char *data;
if (likely(!md_dst))
return 0;
if (unlikely(md_dst->type != METADATA_HW_PORT_MUX))
return 0;
if (unlikely(skb_cow_head(skb, 8)))
return -ENOMEM;
data = skb_push(skb, 8);
put_unaligned_be32(NFP_NET_META_PORTID, data);
put_unaligned_be32(md_dst->u.port_info.port_id, data + 4);
return 8;
}
/** /**
* nfp_net_tx() - Main transmit entry point * nfp_net_tx() - Main transmit entry point
* @skb: SKB to transmit * @skb: SKB to transmit
...@@ -767,6 +787,7 @@ static int nfp_net_tx(struct sk_buff *skb, struct net_device *netdev) ...@@ -767,6 +787,7 @@ static int nfp_net_tx(struct sk_buff *skb, struct net_device *netdev)
struct nfp_net *nn = netdev_priv(netdev); struct nfp_net *nn = netdev_priv(netdev);
const struct skb_frag_struct *frag; const struct skb_frag_struct *frag;
struct nfp_net_tx_desc *txd, txdg; struct nfp_net_tx_desc *txd, txdg;
int f, nr_frags, wr_idx, md_bytes;
struct nfp_net_tx_ring *tx_ring; struct nfp_net_tx_ring *tx_ring;
struct nfp_net_r_vector *r_vec; struct nfp_net_r_vector *r_vec;
struct nfp_net_tx_buf *txbuf; struct nfp_net_tx_buf *txbuf;
...@@ -774,8 +795,6 @@ static int nfp_net_tx(struct sk_buff *skb, struct net_device *netdev) ...@@ -774,8 +795,6 @@ static int nfp_net_tx(struct sk_buff *skb, struct net_device *netdev)
struct nfp_net_dp *dp; struct nfp_net_dp *dp;
dma_addr_t dma_addr; dma_addr_t dma_addr;
unsigned int fsize; unsigned int fsize;
int f, nr_frags;
int wr_idx;
u16 qidx; u16 qidx;
dp = &nn->dp; dp = &nn->dp;
...@@ -797,6 +816,13 @@ static int nfp_net_tx(struct sk_buff *skb, struct net_device *netdev) ...@@ -797,6 +816,13 @@ static int nfp_net_tx(struct sk_buff *skb, struct net_device *netdev)
return NETDEV_TX_BUSY; return NETDEV_TX_BUSY;
} }
md_bytes = nfp_net_prep_port_id(skb);
if (unlikely(md_bytes < 0)) {
nfp_net_tx_xmit_more_flush(tx_ring);
dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
}
/* Start with the head skbuf */ /* Start with the head skbuf */
dma_addr = dma_map_single(dp->dev, skb->data, skb_headlen(skb), dma_addr = dma_map_single(dp->dev, skb->data, skb_headlen(skb),
DMA_TO_DEVICE); DMA_TO_DEVICE);
...@@ -815,7 +841,7 @@ static int nfp_net_tx(struct sk_buff *skb, struct net_device *netdev) ...@@ -815,7 +841,7 @@ static int nfp_net_tx(struct sk_buff *skb, struct net_device *netdev)
/* Build TX descriptor */ /* Build TX descriptor */
txd = &tx_ring->txds[wr_idx]; txd = &tx_ring->txds[wr_idx];
txd->offset_eop = (nr_frags == 0) ? PCIE_DESC_TX_EOP : 0; txd->offset_eop = (nr_frags ? 0 : PCIE_DESC_TX_EOP) | md_bytes;
txd->dma_len = cpu_to_le16(skb_headlen(skb)); txd->dma_len = cpu_to_le16(skb_headlen(skb));
nfp_desc_set_dma_addr(txd, dma_addr); nfp_desc_set_dma_addr(txd, dma_addr);
txd->data_len = cpu_to_le16(skb->len); txd->data_len = cpu_to_le16(skb->len);
...@@ -855,7 +881,7 @@ static int nfp_net_tx(struct sk_buff *skb, struct net_device *netdev) ...@@ -855,7 +881,7 @@ static int nfp_net_tx(struct sk_buff *skb, struct net_device *netdev)
*txd = txdg; *txd = txdg;
txd->dma_len = cpu_to_le16(fsize); txd->dma_len = cpu_to_le16(fsize);
nfp_desc_set_dma_addr(txd, dma_addr); nfp_desc_set_dma_addr(txd, dma_addr);
txd->offset_eop = txd->offset_eop |=
(f == nr_frags - 1) ? PCIE_DESC_TX_EOP : 0; (f == nr_frags - 1) ? PCIE_DESC_TX_EOP : 0;
} }
...@@ -1450,6 +1476,10 @@ nfp_net_parse_meta(struct net_device *netdev, struct nfp_meta_parsed *meta, ...@@ -1450,6 +1476,10 @@ nfp_net_parse_meta(struct net_device *netdev, struct nfp_meta_parsed *meta,
meta->mark = get_unaligned_be32(data); meta->mark = get_unaligned_be32(data);
data += 4; data += 4;
break; break;
case NFP_NET_META_PORTID:
meta->portid = get_unaligned_be32(data);
data += 4;
break;
case NFP_NET_META_CSUM: case NFP_NET_META_CSUM:
meta->csum_type = CHECKSUM_COMPLETE; meta->csum_type = CHECKSUM_COMPLETE;
meta->csum = meta->csum =
...@@ -1594,6 +1624,7 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget) ...@@ -1594,6 +1624,7 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget)
struct nfp_net_rx_buf *rxbuf; struct nfp_net_rx_buf *rxbuf;
struct nfp_net_rx_desc *rxd; struct nfp_net_rx_desc *rxd;
struct nfp_meta_parsed meta; struct nfp_meta_parsed meta;
struct net_device *netdev;
dma_addr_t new_dma_addr; dma_addr_t new_dma_addr;
void *new_frag; void *new_frag;
...@@ -1672,7 +1703,7 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget) ...@@ -1672,7 +1703,7 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget)
} }
if (xdp_prog && !(rxd->rxd.flags & PCIE_DESC_RX_BPF && if (xdp_prog && !(rxd->rxd.flags & PCIE_DESC_RX_BPF &&
dp->bpf_offload_xdp)) { dp->bpf_offload_xdp) && !meta.portid) {
unsigned int dma_off; unsigned int dma_off;
void *hard_start; void *hard_start;
int act; int act;
...@@ -1718,6 +1749,20 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget) ...@@ -1718,6 +1749,20 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget)
continue; continue;
} }
if (likely(!meta.portid)) {
netdev = dp->netdev;
} else {
struct nfp_net *nn;
nn = netdev_priv(dp->netdev);
netdev = nfp_app_repr_get(nn->app, meta.portid);
if (unlikely(!netdev)) {
nfp_net_rx_drop(dp, r_vec, rx_ring, rxbuf, skb);
continue;
}
nfp_repr_inc_rx_stats(netdev, pkt_len);
}
nfp_net_dma_unmap_rx(dp, rxbuf->dma_addr); nfp_net_dma_unmap_rx(dp, rxbuf->dma_addr);
nfp_net_rx_give_one(dp, rx_ring, new_frag, new_dma_addr); nfp_net_rx_give_one(dp, rx_ring, new_frag, new_dma_addr);
...@@ -1729,7 +1774,7 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget) ...@@ -1729,7 +1774,7 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget)
skb_set_hash(skb, meta.hash, meta.hash_type); skb_set_hash(skb, meta.hash, meta.hash_type);
skb_record_rx_queue(skb, rx_ring->idx); skb_record_rx_queue(skb, rx_ring->idx);
skb->protocol = eth_type_trans(skb, dp->netdev); skb->protocol = eth_type_trans(skb, netdev);
nfp_net_rx_csum(dp, r_vec, rxd, &meta, skb); nfp_net_rx_csum(dp, r_vec, rxd, &meta, skb);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment