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: Simon Horman <simon.horman@netronome.com> Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
93da7d9660
commit
91bf82ca9e
@ -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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
/* 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)
|
|||||||
*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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user