123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- From: Lorenzo Bianconi <[email protected]>
- Date: Fri, 20 May 2022 20:11:27 +0200
- Subject: [PATCH] net: ethernet: mtk_eth_soc: move tx dma desc configuration in
- mtk_tx_set_dma_desc
- Move tx dma descriptor configuration in mtk_tx_set_dma_desc routine.
- This is a preliminary patch to introduce mt7986 ethernet support since
- it relies on a different tx dma descriptor layout.
- Tested-by: Sam Shih <[email protected]>
- Signed-off-by: Lorenzo Bianconi <[email protected]>
- Signed-off-by: David S. Miller <[email protected]>
- ---
- --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
- +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
- @@ -982,18 +982,51 @@ static void setup_tx_buf(struct mtk_eth
- }
- }
-
- +static void mtk_tx_set_dma_desc(struct net_device *dev, struct mtk_tx_dma *desc,
- + struct mtk_tx_dma_desc_info *info)
- +{
- + struct mtk_mac *mac = netdev_priv(dev);
- + u32 data;
- +
- + WRITE_ONCE(desc->txd1, info->addr);
- +
- + data = TX_DMA_SWC | TX_DMA_PLEN0(info->size);
- + if (info->last)
- + data |= TX_DMA_LS0;
- + WRITE_ONCE(desc->txd3, data);
- +
- + data = (mac->id + 1) << TX_DMA_FPORT_SHIFT; /* forward port */
- + if (info->first) {
- + if (info->gso)
- + data |= TX_DMA_TSO;
- + /* tx checksum offload */
- + if (info->csum)
- + data |= TX_DMA_CHKSUM;
- + /* vlan header offload */
- + if (info->vlan)
- + data |= TX_DMA_INS_VLAN | info->vlan_tci;
- + }
- + WRITE_ONCE(desc->txd4, data);
- +}
- +
- static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev,
- int tx_num, struct mtk_tx_ring *ring, bool gso)
- {
- + struct mtk_tx_dma_desc_info txd_info = {
- + .size = skb_headlen(skb),
- + .gso = gso,
- + .csum = skb->ip_summed == CHECKSUM_PARTIAL,
- + .vlan = skb_vlan_tag_present(skb),
- + .vlan_tci = skb_vlan_tag_get(skb),
- + .first = true,
- + .last = !skb_is_nonlinear(skb),
- + };
- struct mtk_mac *mac = netdev_priv(dev);
- struct mtk_eth *eth = mac->hw;
- struct mtk_tx_dma *itxd, *txd;
- struct mtk_tx_dma *itxd_pdma, *txd_pdma;
- struct mtk_tx_buf *itx_buf, *tx_buf;
- - dma_addr_t mapped_addr;
- - unsigned int nr_frags;
- int i, n_desc = 1;
- - u32 txd4 = 0, fport;
- int k = 0;
-
- itxd = ring->next_free;
- @@ -1001,49 +1034,32 @@ static int mtk_tx_map(struct sk_buff *sk
- if (itxd == ring->last_free)
- return -ENOMEM;
-
- - /* set the forward port */
- - fport = (mac->id + 1) << TX_DMA_FPORT_SHIFT;
- - txd4 |= fport;
- -
- itx_buf = mtk_desc_to_tx_buf(ring, itxd);
- memset(itx_buf, 0, sizeof(*itx_buf));
-
- - if (gso)
- - txd4 |= TX_DMA_TSO;
- -
- - /* TX Checksum offload */
- - if (skb->ip_summed == CHECKSUM_PARTIAL)
- - txd4 |= TX_DMA_CHKSUM;
- -
- - /* VLAN header offload */
- - if (skb_vlan_tag_present(skb))
- - txd4 |= TX_DMA_INS_VLAN | skb_vlan_tag_get(skb);
- -
- - mapped_addr = dma_map_single(eth->dma_dev, skb->data,
- - skb_headlen(skb), DMA_TO_DEVICE);
- - if (unlikely(dma_mapping_error(eth->dma_dev, mapped_addr)))
- + txd_info.addr = dma_map_single(eth->dma_dev, skb->data, txd_info.size,
- + DMA_TO_DEVICE);
- + if (unlikely(dma_mapping_error(eth->dma_dev, txd_info.addr)))
- return -ENOMEM;
-
- - WRITE_ONCE(itxd->txd1, mapped_addr);
- + mtk_tx_set_dma_desc(dev, itxd, &txd_info);
- +
- itx_buf->flags |= MTK_TX_FLAGS_SINGLE0;
- itx_buf->flags |= (!mac->id) ? MTK_TX_FLAGS_FPORT0 :
- MTK_TX_FLAGS_FPORT1;
- - setup_tx_buf(eth, itx_buf, itxd_pdma, mapped_addr, skb_headlen(skb),
- + setup_tx_buf(eth, itx_buf, itxd_pdma, txd_info.addr, txd_info.size,
- k++);
-
- /* TX SG offload */
- txd = itxd;
- txd_pdma = qdma_to_pdma(ring, txd);
- - nr_frags = skb_shinfo(skb)->nr_frags;
-
- - for (i = 0; i < nr_frags; i++) {
- + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
- unsigned int offset = 0;
- int frag_size = skb_frag_size(frag);
-
- while (frag_size) {
- - bool last_frag = false;
- - unsigned int frag_map_size;
- bool new_desc = true;
-
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA) ||
- @@ -1058,23 +1074,17 @@ static int mtk_tx_map(struct sk_buff *sk
- new_desc = false;
- }
-
- -
- - frag_map_size = min(frag_size, MTK_TX_DMA_BUF_LEN);
- - mapped_addr = skb_frag_dma_map(eth->dma_dev, frag, offset,
- - frag_map_size,
- - DMA_TO_DEVICE);
- - if (unlikely(dma_mapping_error(eth->dma_dev, mapped_addr)))
- + memset(&txd_info, 0, sizeof(struct mtk_tx_dma_desc_info));
- + txd_info.size = min(frag_size, MTK_TX_DMA_BUF_LEN);
- + txd_info.last = i == skb_shinfo(skb)->nr_frags - 1 &&
- + !(frag_size - txd_info.size);
- + txd_info.addr = skb_frag_dma_map(eth->dma_dev, frag,
- + offset, txd_info.size,
- + DMA_TO_DEVICE);
- + if (unlikely(dma_mapping_error(eth->dma_dev, txd_info.addr)))
- goto err_dma;
-
- - if (i == nr_frags - 1 &&
- - (frag_size - frag_map_size) == 0)
- - last_frag = true;
- -
- - WRITE_ONCE(txd->txd1, mapped_addr);
- - WRITE_ONCE(txd->txd3, (TX_DMA_SWC |
- - TX_DMA_PLEN0(frag_map_size) |
- - last_frag * TX_DMA_LS0));
- - WRITE_ONCE(txd->txd4, fport);
- + mtk_tx_set_dma_desc(dev, txd, &txd_info);
-
- tx_buf = mtk_desc_to_tx_buf(ring, txd);
- if (new_desc)
- @@ -1084,20 +1094,17 @@ static int mtk_tx_map(struct sk_buff *sk
- tx_buf->flags |= (!mac->id) ? MTK_TX_FLAGS_FPORT0 :
- MTK_TX_FLAGS_FPORT1;
-
- - setup_tx_buf(eth, tx_buf, txd_pdma, mapped_addr,
- - frag_map_size, k++);
- + setup_tx_buf(eth, tx_buf, txd_pdma, txd_info.addr,
- + txd_info.size, k++);
-
- - frag_size -= frag_map_size;
- - offset += frag_map_size;
- + frag_size -= txd_info.size;
- + offset += txd_info.size;
- }
- }
-
- /* store skb to cleanup */
- itx_buf->skb = skb;
-
- - WRITE_ONCE(itxd->txd4, txd4);
- - WRITE_ONCE(itxd->txd3, (TX_DMA_SWC | TX_DMA_PLEN0(skb_headlen(skb)) |
- - (!nr_frags * TX_DMA_LS0)));
- if (!MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) {
- if (k & 0x1)
- txd_pdma->txd2 |= TX_DMA_LS0;
- --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
- +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
- @@ -843,6 +843,17 @@ enum mkt_eth_capabilities {
- MTK_MUX_U3_GMAC2_TO_QPHY | \
- MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA)
-
- +struct mtk_tx_dma_desc_info {
- + dma_addr_t addr;
- + u32 size;
- + u16 vlan_tci;
- + u8 gso:1;
- + u8 csum:1;
- + u8 vlan:1;
- + u8 first:1;
- + u8 last:1;
- +};
- +
- /* struct mtk_eth_data - This is the structure holding all differences
- * among various plaforms
- * @ana_rgc3: The offset for register ANA_RGC3 related to
|