dc85786be29470ef54d3f4fbcaf5fa075de0ed4f
[openwrt/staging/xback.git] /
1 From: Lorenzo Bianconi <lorenzo@kernel.org>
2 Date: Fri, 20 May 2022 20:11:27 +0200
3 Subject: [PATCH] net: ethernet: mtk_eth_soc: move tx dma desc configuration in
4 mtk_tx_set_dma_desc
5
6 Move tx dma descriptor configuration in mtk_tx_set_dma_desc routine.
7 This is a preliminary patch to introduce mt7986 ethernet support since
8 it relies on a different tx dma descriptor layout.
9
10 Tested-by: Sam Shih <sam.shih@mediatek.com>
11 Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
12 Signed-off-by: David S. Miller <davem@davemloft.net>
13 ---
14
15 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
16 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
17 @@ -982,18 +982,51 @@ static void setup_tx_buf(struct mtk_eth
18 }
19 }
20
21 +static void mtk_tx_set_dma_desc(struct net_device *dev, struct mtk_tx_dma *desc,
22 + struct mtk_tx_dma_desc_info *info)
23 +{
24 + struct mtk_mac *mac = netdev_priv(dev);
25 + u32 data;
26 +
27 + WRITE_ONCE(desc->txd1, info->addr);
28 +
29 + data = TX_DMA_SWC | TX_DMA_PLEN0(info->size);
30 + if (info->last)
31 + data |= TX_DMA_LS0;
32 + WRITE_ONCE(desc->txd3, data);
33 +
34 + data = (mac->id + 1) << TX_DMA_FPORT_SHIFT; /* forward port */
35 + if (info->first) {
36 + if (info->gso)
37 + data |= TX_DMA_TSO;
38 + /* tx checksum offload */
39 + if (info->csum)
40 + data |= TX_DMA_CHKSUM;
41 + /* vlan header offload */
42 + if (info->vlan)
43 + data |= TX_DMA_INS_VLAN | info->vlan_tci;
44 + }
45 + WRITE_ONCE(desc->txd4, data);
46 +}
47 +
48 static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev,
49 int tx_num, struct mtk_tx_ring *ring, bool gso)
50 {
51 + struct mtk_tx_dma_desc_info txd_info = {
52 + .size = skb_headlen(skb),
53 + .gso = gso,
54 + .csum = skb->ip_summed == CHECKSUM_PARTIAL,
55 + .vlan = skb_vlan_tag_present(skb),
56 + .vlan_tci = skb_vlan_tag_get(skb),
57 + .first = true,
58 + .last = !skb_is_nonlinear(skb),
59 + };
60 struct mtk_mac *mac = netdev_priv(dev);
61 struct mtk_eth *eth = mac->hw;
62 struct mtk_tx_dma *itxd, *txd;
63 struct mtk_tx_dma *itxd_pdma, *txd_pdma;
64 struct mtk_tx_buf *itx_buf, *tx_buf;
65 - dma_addr_t mapped_addr;
66 - unsigned int nr_frags;
67 int i, n_desc = 1;
68 - u32 txd4 = 0, fport;
69 int k = 0;
70
71 itxd = ring->next_free;
72 @@ -1001,49 +1034,32 @@ static int mtk_tx_map(struct sk_buff *sk
73 if (itxd == ring->last_free)
74 return -ENOMEM;
75
76 - /* set the forward port */
77 - fport = (mac->id + 1) << TX_DMA_FPORT_SHIFT;
78 - txd4 |= fport;
79 -
80 itx_buf = mtk_desc_to_tx_buf(ring, itxd);
81 memset(itx_buf, 0, sizeof(*itx_buf));
82
83 - if (gso)
84 - txd4 |= TX_DMA_TSO;
85 -
86 - /* TX Checksum offload */
87 - if (skb->ip_summed == CHECKSUM_PARTIAL)
88 - txd4 |= TX_DMA_CHKSUM;
89 -
90 - /* VLAN header offload */
91 - if (skb_vlan_tag_present(skb))
92 - txd4 |= TX_DMA_INS_VLAN | skb_vlan_tag_get(skb);
93 -
94 - mapped_addr = dma_map_single(eth->dma_dev, skb->data,
95 - skb_headlen(skb), DMA_TO_DEVICE);
96 - if (unlikely(dma_mapping_error(eth->dma_dev, mapped_addr)))
97 + txd_info.addr = dma_map_single(eth->dma_dev, skb->data, txd_info.size,
98 + DMA_TO_DEVICE);
99 + if (unlikely(dma_mapping_error(eth->dma_dev, txd_info.addr)))
100 return -ENOMEM;
101
102 - WRITE_ONCE(itxd->txd1, mapped_addr);
103 + mtk_tx_set_dma_desc(dev, itxd, &txd_info);
104 +
105 itx_buf->flags |= MTK_TX_FLAGS_SINGLE0;
106 itx_buf->flags |= (!mac->id) ? MTK_TX_FLAGS_FPORT0 :
107 MTK_TX_FLAGS_FPORT1;
108 - setup_tx_buf(eth, itx_buf, itxd_pdma, mapped_addr, skb_headlen(skb),
109 + setup_tx_buf(eth, itx_buf, itxd_pdma, txd_info.addr, txd_info.size,
110 k++);
111
112 /* TX SG offload */
113 txd = itxd;
114 txd_pdma = qdma_to_pdma(ring, txd);
115 - nr_frags = skb_shinfo(skb)->nr_frags;
116
117 - for (i = 0; i < nr_frags; i++) {
118 + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
119 skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
120 unsigned int offset = 0;
121 int frag_size = skb_frag_size(frag);
122
123 while (frag_size) {
124 - bool last_frag = false;
125 - unsigned int frag_map_size;
126 bool new_desc = true;
127
128 if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA) ||
129 @@ -1058,23 +1074,17 @@ static int mtk_tx_map(struct sk_buff *sk
130 new_desc = false;
131 }
132
133 -
134 - frag_map_size = min(frag_size, MTK_TX_DMA_BUF_LEN);
135 - mapped_addr = skb_frag_dma_map(eth->dma_dev, frag, offset,
136 - frag_map_size,
137 - DMA_TO_DEVICE);
138 - if (unlikely(dma_mapping_error(eth->dma_dev, mapped_addr)))
139 + memset(&txd_info, 0, sizeof(struct mtk_tx_dma_desc_info));
140 + txd_info.size = min(frag_size, MTK_TX_DMA_BUF_LEN);
141 + txd_info.last = i == skb_shinfo(skb)->nr_frags - 1 &&
142 + !(frag_size - txd_info.size);
143 + txd_info.addr = skb_frag_dma_map(eth->dma_dev, frag,
144 + offset, txd_info.size,
145 + DMA_TO_DEVICE);
146 + if (unlikely(dma_mapping_error(eth->dma_dev, txd_info.addr)))
147 goto err_dma;
148
149 - if (i == nr_frags - 1 &&
150 - (frag_size - frag_map_size) == 0)
151 - last_frag = true;
152 -
153 - WRITE_ONCE(txd->txd1, mapped_addr);
154 - WRITE_ONCE(txd->txd3, (TX_DMA_SWC |
155 - TX_DMA_PLEN0(frag_map_size) |
156 - last_frag * TX_DMA_LS0));
157 - WRITE_ONCE(txd->txd4, fport);
158 + mtk_tx_set_dma_desc(dev, txd, &txd_info);
159
160 tx_buf = mtk_desc_to_tx_buf(ring, txd);
161 if (new_desc)
162 @@ -1084,20 +1094,17 @@ static int mtk_tx_map(struct sk_buff *sk
163 tx_buf->flags |= (!mac->id) ? MTK_TX_FLAGS_FPORT0 :
164 MTK_TX_FLAGS_FPORT1;
165
166 - setup_tx_buf(eth, tx_buf, txd_pdma, mapped_addr,
167 - frag_map_size, k++);
168 + setup_tx_buf(eth, tx_buf, txd_pdma, txd_info.addr,
169 + txd_info.size, k++);
170
171 - frag_size -= frag_map_size;
172 - offset += frag_map_size;
173 + frag_size -= txd_info.size;
174 + offset += txd_info.size;
175 }
176 }
177
178 /* store skb to cleanup */
179 itx_buf->skb = skb;
180
181 - WRITE_ONCE(itxd->txd4, txd4);
182 - WRITE_ONCE(itxd->txd3, (TX_DMA_SWC | TX_DMA_PLEN0(skb_headlen(skb)) |
183 - (!nr_frags * TX_DMA_LS0)));
184 if (!MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) {
185 if (k & 0x1)
186 txd_pdma->txd2 |= TX_DMA_LS0;
187 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
188 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
189 @@ -843,6 +843,17 @@ enum mkt_eth_capabilities {
190 MTK_MUX_U3_GMAC2_TO_QPHY | \
191 MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA)
192
193 +struct mtk_tx_dma_desc_info {
194 + dma_addr_t addr;
195 + u32 size;
196 + u16 vlan_tci;
197 + u8 gso:1;
198 + u8 csum:1;
199 + u8 vlan:1;
200 + u8 first:1;
201 + u8 last:1;
202 +};
203 +
204 /* struct mtk_eth_data - This is the structure holding all differences
205 * among various plaforms
206 * @ana_rgc3: The offset for register ANA_RGC3 related to