1c8349639SHoratiu Vultur // SPDX-License-Identifier: GPL-2.0+
2c8349639SHoratiu Vultur
37292bb06SHoratiu Vultur #include <linux/bpf.h>
4a825b611SHoratiu Vultur #include <linux/filter.h>
5*a9ca9f9cSYunsheng Lin #include <net/page_pool/helpers.h>
67292bb06SHoratiu Vultur
7c8349639SHoratiu Vultur #include "lan966x_main.h"
8c8349639SHoratiu Vultur
lan966x_fdma_channel_active(struct lan966x * lan966x)9c8349639SHoratiu Vultur static int lan966x_fdma_channel_active(struct lan966x *lan966x)
10c8349639SHoratiu Vultur {
11c8349639SHoratiu Vultur return lan_rd(lan966x, FDMA_CH_ACTIVE);
12c8349639SHoratiu Vultur }
13c8349639SHoratiu Vultur
lan966x_fdma_rx_alloc_page(struct lan966x_rx * rx,struct lan966x_db * db)14c8349639SHoratiu Vultur static struct page *lan966x_fdma_rx_alloc_page(struct lan966x_rx *rx,
15c8349639SHoratiu Vultur struct lan966x_db *db)
16c8349639SHoratiu Vultur {
17c8349639SHoratiu Vultur struct page *page;
18c8349639SHoratiu Vultur
1911871abaSHoratiu Vultur page = page_pool_dev_alloc_pages(rx->page_pool);
20c8349639SHoratiu Vultur if (unlikely(!page))
21c8349639SHoratiu Vultur return NULL;
22c8349639SHoratiu Vultur
237292bb06SHoratiu Vultur db->dataptr = page_pool_get_dma_addr(page) + XDP_PACKET_HEADROOM;
24c8349639SHoratiu Vultur
25c8349639SHoratiu Vultur return page;
26c8349639SHoratiu Vultur }
27c8349639SHoratiu Vultur
lan966x_fdma_rx_free_pages(struct lan966x_rx * rx)28c8349639SHoratiu Vultur static void lan966x_fdma_rx_free_pages(struct lan966x_rx *rx)
29c8349639SHoratiu Vultur {
30c8349639SHoratiu Vultur int i, j;
31c8349639SHoratiu Vultur
32c8349639SHoratiu Vultur for (i = 0; i < FDMA_DCB_MAX; ++i) {
3311871abaSHoratiu Vultur for (j = 0; j < FDMA_RX_DCB_MAX_DBS; ++j)
3411871abaSHoratiu Vultur page_pool_put_full_page(rx->page_pool,
3511871abaSHoratiu Vultur rx->page[i][j], false);
36c8349639SHoratiu Vultur }
37c8349639SHoratiu Vultur }
38c8349639SHoratiu Vultur
lan966x_fdma_rx_free_page(struct lan966x_rx * rx)394a00b0c7SHoratiu Vultur static void lan966x_fdma_rx_free_page(struct lan966x_rx *rx)
404a00b0c7SHoratiu Vultur {
414a00b0c7SHoratiu Vultur struct page *page;
424a00b0c7SHoratiu Vultur
434a00b0c7SHoratiu Vultur page = rx->page[rx->dcb_index][rx->db_index];
444a00b0c7SHoratiu Vultur if (unlikely(!page))
454a00b0c7SHoratiu Vultur return;
464a00b0c7SHoratiu Vultur
4711871abaSHoratiu Vultur page_pool_recycle_direct(rx->page_pool, page);
484a00b0c7SHoratiu Vultur }
494a00b0c7SHoratiu Vultur
lan966x_fdma_rx_add_dcb(struct lan966x_rx * rx,struct lan966x_rx_dcb * dcb,u64 nextptr)50c8349639SHoratiu Vultur static void lan966x_fdma_rx_add_dcb(struct lan966x_rx *rx,
51c8349639SHoratiu Vultur struct lan966x_rx_dcb *dcb,
52c8349639SHoratiu Vultur u64 nextptr)
53c8349639SHoratiu Vultur {
54c8349639SHoratiu Vultur struct lan966x_db *db;
55c8349639SHoratiu Vultur int i;
56c8349639SHoratiu Vultur
57c8349639SHoratiu Vultur for (i = 0; i < FDMA_RX_DCB_MAX_DBS; ++i) {
58c8349639SHoratiu Vultur db = &dcb->db[i];
59c8349639SHoratiu Vultur db->status = FDMA_DCB_STATUS_INTR;
60c8349639SHoratiu Vultur }
61c8349639SHoratiu Vultur
62c8349639SHoratiu Vultur dcb->nextptr = FDMA_DCB_INVALID_DATA;
63c8349639SHoratiu Vultur dcb->info = FDMA_DCB_INFO_DATAL(PAGE_SIZE << rx->page_order);
64c8349639SHoratiu Vultur
65c8349639SHoratiu Vultur rx->last_entry->nextptr = nextptr;
66c8349639SHoratiu Vultur rx->last_entry = dcb;
67c8349639SHoratiu Vultur }
68c8349639SHoratiu Vultur
lan966x_fdma_rx_alloc_page_pool(struct lan966x_rx * rx)6911871abaSHoratiu Vultur static int lan966x_fdma_rx_alloc_page_pool(struct lan966x_rx *rx)
7011871abaSHoratiu Vultur {
7111871abaSHoratiu Vultur struct lan966x *lan966x = rx->lan966x;
7211871abaSHoratiu Vultur struct page_pool_params pp_params = {
7311871abaSHoratiu Vultur .order = rx->page_order,
7411871abaSHoratiu Vultur .flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV,
7511871abaSHoratiu Vultur .pool_size = FDMA_DCB_MAX,
7611871abaSHoratiu Vultur .nid = NUMA_NO_NODE,
7711871abaSHoratiu Vultur .dev = lan966x->dev,
7811871abaSHoratiu Vultur .dma_dir = DMA_FROM_DEVICE,
797292bb06SHoratiu Vultur .offset = XDP_PACKET_HEADROOM,
8011871abaSHoratiu Vultur .max_len = rx->max_mtu -
8111871abaSHoratiu Vultur SKB_DATA_ALIGN(sizeof(struct skb_shared_info)),
8211871abaSHoratiu Vultur };
8311871abaSHoratiu Vultur
84560c7223SHoratiu Vultur if (lan966x_xdp_present(lan966x))
85560c7223SHoratiu Vultur pp_params.dma_dir = DMA_BIDIRECTIONAL;
86560c7223SHoratiu Vultur
8711871abaSHoratiu Vultur rx->page_pool = page_pool_create(&pp_params);
8877ddda44SHoratiu Vultur
8977ddda44SHoratiu Vultur for (int i = 0; i < lan966x->num_phys_ports; ++i) {
9077ddda44SHoratiu Vultur struct lan966x_port *port;
9177ddda44SHoratiu Vultur
9277ddda44SHoratiu Vultur if (!lan966x->ports[i])
9377ddda44SHoratiu Vultur continue;
9477ddda44SHoratiu Vultur
9577ddda44SHoratiu Vultur port = lan966x->ports[i];
9677ddda44SHoratiu Vultur xdp_rxq_info_unreg_mem_model(&port->xdp_rxq);
9777ddda44SHoratiu Vultur xdp_rxq_info_reg_mem_model(&port->xdp_rxq, MEM_TYPE_PAGE_POOL,
9877ddda44SHoratiu Vultur rx->page_pool);
9977ddda44SHoratiu Vultur }
10077ddda44SHoratiu Vultur
10111871abaSHoratiu Vultur return PTR_ERR_OR_ZERO(rx->page_pool);
10211871abaSHoratiu Vultur }
10311871abaSHoratiu Vultur
lan966x_fdma_rx_alloc(struct lan966x_rx * rx)104c8349639SHoratiu Vultur static int lan966x_fdma_rx_alloc(struct lan966x_rx *rx)
105c8349639SHoratiu Vultur {
106c8349639SHoratiu Vultur struct lan966x *lan966x = rx->lan966x;
107c8349639SHoratiu Vultur struct lan966x_rx_dcb *dcb;
108c8349639SHoratiu Vultur struct lan966x_db *db;
109c8349639SHoratiu Vultur struct page *page;
110c8349639SHoratiu Vultur int i, j;
111c8349639SHoratiu Vultur int size;
112c8349639SHoratiu Vultur
11311871abaSHoratiu Vultur if (lan966x_fdma_rx_alloc_page_pool(rx))
11411871abaSHoratiu Vultur return PTR_ERR(rx->page_pool);
11511871abaSHoratiu Vultur
116c8349639SHoratiu Vultur /* calculate how many pages are needed to allocate the dcbs */
117c8349639SHoratiu Vultur size = sizeof(struct lan966x_rx_dcb) * FDMA_DCB_MAX;
118c8349639SHoratiu Vultur size = ALIGN(size, PAGE_SIZE);
119c8349639SHoratiu Vultur
120c8349639SHoratiu Vultur rx->dcbs = dma_alloc_coherent(lan966x->dev, size, &rx->dma, GFP_KERNEL);
121c8349639SHoratiu Vultur if (!rx->dcbs)
122c8349639SHoratiu Vultur return -ENOMEM;
123c8349639SHoratiu Vultur
124c8349639SHoratiu Vultur rx->last_entry = rx->dcbs;
125c8349639SHoratiu Vultur rx->db_index = 0;
126c8349639SHoratiu Vultur rx->dcb_index = 0;
127c8349639SHoratiu Vultur
128c8349639SHoratiu Vultur /* Now for each dcb allocate the dbs */
129c8349639SHoratiu Vultur for (i = 0; i < FDMA_DCB_MAX; ++i) {
130c8349639SHoratiu Vultur dcb = &rx->dcbs[i];
131c8349639SHoratiu Vultur dcb->info = 0;
132c8349639SHoratiu Vultur
133c8349639SHoratiu Vultur /* For each db allocate a page and map it to the DB dataptr. */
134c8349639SHoratiu Vultur for (j = 0; j < FDMA_RX_DCB_MAX_DBS; ++j) {
135c8349639SHoratiu Vultur db = &dcb->db[j];
136c8349639SHoratiu Vultur page = lan966x_fdma_rx_alloc_page(rx, db);
137c8349639SHoratiu Vultur if (!page)
138c8349639SHoratiu Vultur return -ENOMEM;
139c8349639SHoratiu Vultur
140c8349639SHoratiu Vultur db->status = 0;
141c8349639SHoratiu Vultur rx->page[i][j] = page;
142c8349639SHoratiu Vultur }
143c8349639SHoratiu Vultur
144c8349639SHoratiu Vultur lan966x_fdma_rx_add_dcb(rx, dcb, rx->dma + sizeof(*dcb) * i);
145c8349639SHoratiu Vultur }
146c8349639SHoratiu Vultur
147c8349639SHoratiu Vultur return 0;
148c8349639SHoratiu Vultur }
149c8349639SHoratiu Vultur
lan966x_fdma_rx_advance_dcb(struct lan966x_rx * rx)1504a00b0c7SHoratiu Vultur static void lan966x_fdma_rx_advance_dcb(struct lan966x_rx *rx)
1514a00b0c7SHoratiu Vultur {
1524a00b0c7SHoratiu Vultur rx->dcb_index++;
1534a00b0c7SHoratiu Vultur rx->dcb_index &= FDMA_DCB_MAX - 1;
1544a00b0c7SHoratiu Vultur }
1554a00b0c7SHoratiu Vultur
lan966x_fdma_rx_free(struct lan966x_rx * rx)156c8349639SHoratiu Vultur static void lan966x_fdma_rx_free(struct lan966x_rx *rx)
157c8349639SHoratiu Vultur {
158c8349639SHoratiu Vultur struct lan966x *lan966x = rx->lan966x;
159c8349639SHoratiu Vultur u32 size;
160c8349639SHoratiu Vultur
161c8349639SHoratiu Vultur /* Now it is possible to do the cleanup of dcb */
162c8349639SHoratiu Vultur size = sizeof(struct lan966x_tx_dcb) * FDMA_DCB_MAX;
163c8349639SHoratiu Vultur size = ALIGN(size, PAGE_SIZE);
164c8349639SHoratiu Vultur dma_free_coherent(lan966x->dev, size, rx->dcbs, rx->dma);
165c8349639SHoratiu Vultur }
166c8349639SHoratiu Vultur
lan966x_fdma_rx_start(struct lan966x_rx * rx)167c8349639SHoratiu Vultur static void lan966x_fdma_rx_start(struct lan966x_rx *rx)
168c8349639SHoratiu Vultur {
169c8349639SHoratiu Vultur struct lan966x *lan966x = rx->lan966x;
170c8349639SHoratiu Vultur u32 mask;
171c8349639SHoratiu Vultur
172c8349639SHoratiu Vultur /* When activating a channel, first is required to write the first DCB
173c8349639SHoratiu Vultur * address and then to activate it
174c8349639SHoratiu Vultur */
175c8349639SHoratiu Vultur lan_wr(lower_32_bits((u64)rx->dma), lan966x,
176c8349639SHoratiu Vultur FDMA_DCB_LLP(rx->channel_id));
177c8349639SHoratiu Vultur lan_wr(upper_32_bits((u64)rx->dma), lan966x,
178c8349639SHoratiu Vultur FDMA_DCB_LLP1(rx->channel_id));
179c8349639SHoratiu Vultur
180c8349639SHoratiu Vultur lan_wr(FDMA_CH_CFG_CH_DCB_DB_CNT_SET(FDMA_RX_DCB_MAX_DBS) |
181c8349639SHoratiu Vultur FDMA_CH_CFG_CH_INTR_DB_EOF_ONLY_SET(1) |
182c8349639SHoratiu Vultur FDMA_CH_CFG_CH_INJ_PORT_SET(0) |
183c8349639SHoratiu Vultur FDMA_CH_CFG_CH_MEM_SET(1),
184c8349639SHoratiu Vultur lan966x, FDMA_CH_CFG(rx->channel_id));
185c8349639SHoratiu Vultur
186c8349639SHoratiu Vultur /* Start fdma */
187c8349639SHoratiu Vultur lan_rmw(FDMA_PORT_CTRL_XTR_STOP_SET(0),
188c8349639SHoratiu Vultur FDMA_PORT_CTRL_XTR_STOP,
189c8349639SHoratiu Vultur lan966x, FDMA_PORT_CTRL(0));
190c8349639SHoratiu Vultur
191c8349639SHoratiu Vultur /* Enable interrupts */
192c8349639SHoratiu Vultur mask = lan_rd(lan966x, FDMA_INTR_DB_ENA);
193c8349639SHoratiu Vultur mask = FDMA_INTR_DB_ENA_INTR_DB_ENA_GET(mask);
194c8349639SHoratiu Vultur mask |= BIT(rx->channel_id);
195c8349639SHoratiu Vultur lan_rmw(FDMA_INTR_DB_ENA_INTR_DB_ENA_SET(mask),
196c8349639SHoratiu Vultur FDMA_INTR_DB_ENA_INTR_DB_ENA,
197c8349639SHoratiu Vultur lan966x, FDMA_INTR_DB_ENA);
198c8349639SHoratiu Vultur
199c8349639SHoratiu Vultur /* Activate the channel */
200c8349639SHoratiu Vultur lan_rmw(FDMA_CH_ACTIVATE_CH_ACTIVATE_SET(BIT(rx->channel_id)),
201c8349639SHoratiu Vultur FDMA_CH_ACTIVATE_CH_ACTIVATE,
202c8349639SHoratiu Vultur lan966x, FDMA_CH_ACTIVATE);
203c8349639SHoratiu Vultur }
204c8349639SHoratiu Vultur
lan966x_fdma_rx_disable(struct lan966x_rx * rx)205c8349639SHoratiu Vultur static void lan966x_fdma_rx_disable(struct lan966x_rx *rx)
206c8349639SHoratiu Vultur {
207c8349639SHoratiu Vultur struct lan966x *lan966x = rx->lan966x;
208c8349639SHoratiu Vultur u32 val;
209c8349639SHoratiu Vultur
210c8349639SHoratiu Vultur /* Disable the channel */
211c8349639SHoratiu Vultur lan_rmw(FDMA_CH_DISABLE_CH_DISABLE_SET(BIT(rx->channel_id)),
212c8349639SHoratiu Vultur FDMA_CH_DISABLE_CH_DISABLE,
213c8349639SHoratiu Vultur lan966x, FDMA_CH_DISABLE);
214c8349639SHoratiu Vultur
215c8349639SHoratiu Vultur readx_poll_timeout_atomic(lan966x_fdma_channel_active, lan966x,
216c8349639SHoratiu Vultur val, !(val & BIT(rx->channel_id)),
217c8349639SHoratiu Vultur READL_SLEEP_US, READL_TIMEOUT_US);
218c8349639SHoratiu Vultur
219c8349639SHoratiu Vultur lan_rmw(FDMA_CH_DB_DISCARD_DB_DISCARD_SET(BIT(rx->channel_id)),
220c8349639SHoratiu Vultur FDMA_CH_DB_DISCARD_DB_DISCARD,
221c8349639SHoratiu Vultur lan966x, FDMA_CH_DB_DISCARD);
222c8349639SHoratiu Vultur }
223c8349639SHoratiu Vultur
lan966x_fdma_rx_reload(struct lan966x_rx * rx)224c8349639SHoratiu Vultur static void lan966x_fdma_rx_reload(struct lan966x_rx *rx)
225c8349639SHoratiu Vultur {
226c8349639SHoratiu Vultur struct lan966x *lan966x = rx->lan966x;
227c8349639SHoratiu Vultur
228c8349639SHoratiu Vultur lan_rmw(FDMA_CH_RELOAD_CH_RELOAD_SET(BIT(rx->channel_id)),
229c8349639SHoratiu Vultur FDMA_CH_RELOAD_CH_RELOAD,
230c8349639SHoratiu Vultur lan966x, FDMA_CH_RELOAD);
231c8349639SHoratiu Vultur }
232c8349639SHoratiu Vultur
lan966x_fdma_tx_add_dcb(struct lan966x_tx * tx,struct lan966x_tx_dcb * dcb)233c8349639SHoratiu Vultur static void lan966x_fdma_tx_add_dcb(struct lan966x_tx *tx,
234c8349639SHoratiu Vultur struct lan966x_tx_dcb *dcb)
235c8349639SHoratiu Vultur {
236c8349639SHoratiu Vultur dcb->nextptr = FDMA_DCB_INVALID_DATA;
237c8349639SHoratiu Vultur dcb->info = 0;
238c8349639SHoratiu Vultur }
239c8349639SHoratiu Vultur
lan966x_fdma_tx_alloc(struct lan966x_tx * tx)240c8349639SHoratiu Vultur static int lan966x_fdma_tx_alloc(struct lan966x_tx *tx)
241c8349639SHoratiu Vultur {
242c8349639SHoratiu Vultur struct lan966x *lan966x = tx->lan966x;
243c8349639SHoratiu Vultur struct lan966x_tx_dcb *dcb;
244c8349639SHoratiu Vultur struct lan966x_db *db;
245c8349639SHoratiu Vultur int size;
246c8349639SHoratiu Vultur int i, j;
247c8349639SHoratiu Vultur
248c8349639SHoratiu Vultur tx->dcbs_buf = kcalloc(FDMA_DCB_MAX, sizeof(struct lan966x_tx_dcb_buf),
249c8349639SHoratiu Vultur GFP_KERNEL);
250c8349639SHoratiu Vultur if (!tx->dcbs_buf)
251c8349639SHoratiu Vultur return -ENOMEM;
252c8349639SHoratiu Vultur
253c8349639SHoratiu Vultur /* calculate how many pages are needed to allocate the dcbs */
254c8349639SHoratiu Vultur size = sizeof(struct lan966x_tx_dcb) * FDMA_DCB_MAX;
255c8349639SHoratiu Vultur size = ALIGN(size, PAGE_SIZE);
256c8349639SHoratiu Vultur tx->dcbs = dma_alloc_coherent(lan966x->dev, size, &tx->dma, GFP_KERNEL);
257c8349639SHoratiu Vultur if (!tx->dcbs)
258c8349639SHoratiu Vultur goto out;
259c8349639SHoratiu Vultur
260c8349639SHoratiu Vultur /* Now for each dcb allocate the db */
261c8349639SHoratiu Vultur for (i = 0; i < FDMA_DCB_MAX; ++i) {
262c8349639SHoratiu Vultur dcb = &tx->dcbs[i];
263c8349639SHoratiu Vultur
264c8349639SHoratiu Vultur for (j = 0; j < FDMA_TX_DCB_MAX_DBS; ++j) {
265c8349639SHoratiu Vultur db = &dcb->db[j];
266c8349639SHoratiu Vultur db->dataptr = 0;
267c8349639SHoratiu Vultur db->status = 0;
268c8349639SHoratiu Vultur }
269c8349639SHoratiu Vultur
270c8349639SHoratiu Vultur lan966x_fdma_tx_add_dcb(tx, dcb);
271c8349639SHoratiu Vultur }
272c8349639SHoratiu Vultur
273c8349639SHoratiu Vultur return 0;
274c8349639SHoratiu Vultur
275c8349639SHoratiu Vultur out:
276c8349639SHoratiu Vultur kfree(tx->dcbs_buf);
277c8349639SHoratiu Vultur return -ENOMEM;
278c8349639SHoratiu Vultur }
279c8349639SHoratiu Vultur
lan966x_fdma_tx_free(struct lan966x_tx * tx)280c8349639SHoratiu Vultur static void lan966x_fdma_tx_free(struct lan966x_tx *tx)
281c8349639SHoratiu Vultur {
282c8349639SHoratiu Vultur struct lan966x *lan966x = tx->lan966x;
283c8349639SHoratiu Vultur int size;
284c8349639SHoratiu Vultur
285c8349639SHoratiu Vultur kfree(tx->dcbs_buf);
286c8349639SHoratiu Vultur
287c8349639SHoratiu Vultur size = sizeof(struct lan966x_tx_dcb) * FDMA_DCB_MAX;
288c8349639SHoratiu Vultur size = ALIGN(size, PAGE_SIZE);
289c8349639SHoratiu Vultur dma_free_coherent(lan966x->dev, size, tx->dcbs, tx->dma);
290c8349639SHoratiu Vultur }
291c8349639SHoratiu Vultur
lan966x_fdma_tx_activate(struct lan966x_tx * tx)292c8349639SHoratiu Vultur static void lan966x_fdma_tx_activate(struct lan966x_tx *tx)
293c8349639SHoratiu Vultur {
294c8349639SHoratiu Vultur struct lan966x *lan966x = tx->lan966x;
295c8349639SHoratiu Vultur u32 mask;
296c8349639SHoratiu Vultur
297c8349639SHoratiu Vultur /* When activating a channel, first is required to write the first DCB
298c8349639SHoratiu Vultur * address and then to activate it
299c8349639SHoratiu Vultur */
300c8349639SHoratiu Vultur lan_wr(lower_32_bits((u64)tx->dma), lan966x,
301c8349639SHoratiu Vultur FDMA_DCB_LLP(tx->channel_id));
302c8349639SHoratiu Vultur lan_wr(upper_32_bits((u64)tx->dma), lan966x,
303c8349639SHoratiu Vultur FDMA_DCB_LLP1(tx->channel_id));
304c8349639SHoratiu Vultur
305c8349639SHoratiu Vultur lan_wr(FDMA_CH_CFG_CH_DCB_DB_CNT_SET(FDMA_TX_DCB_MAX_DBS) |
306c8349639SHoratiu Vultur FDMA_CH_CFG_CH_INTR_DB_EOF_ONLY_SET(1) |
307c8349639SHoratiu Vultur FDMA_CH_CFG_CH_INJ_PORT_SET(0) |
308c8349639SHoratiu Vultur FDMA_CH_CFG_CH_MEM_SET(1),
309c8349639SHoratiu Vultur lan966x, FDMA_CH_CFG(tx->channel_id));
310c8349639SHoratiu Vultur
311c8349639SHoratiu Vultur /* Start fdma */
312c8349639SHoratiu Vultur lan_rmw(FDMA_PORT_CTRL_INJ_STOP_SET(0),
313c8349639SHoratiu Vultur FDMA_PORT_CTRL_INJ_STOP,
314c8349639SHoratiu Vultur lan966x, FDMA_PORT_CTRL(0));
315c8349639SHoratiu Vultur
316c8349639SHoratiu Vultur /* Enable interrupts */
317c8349639SHoratiu Vultur mask = lan_rd(lan966x, FDMA_INTR_DB_ENA);
318c8349639SHoratiu Vultur mask = FDMA_INTR_DB_ENA_INTR_DB_ENA_GET(mask);
319c8349639SHoratiu Vultur mask |= BIT(tx->channel_id);
320c8349639SHoratiu Vultur lan_rmw(FDMA_INTR_DB_ENA_INTR_DB_ENA_SET(mask),
321c8349639SHoratiu Vultur FDMA_INTR_DB_ENA_INTR_DB_ENA,
322c8349639SHoratiu Vultur lan966x, FDMA_INTR_DB_ENA);
323c8349639SHoratiu Vultur
324c8349639SHoratiu Vultur /* Activate the channel */
325c8349639SHoratiu Vultur lan_rmw(FDMA_CH_ACTIVATE_CH_ACTIVATE_SET(BIT(tx->channel_id)),
326c8349639SHoratiu Vultur FDMA_CH_ACTIVATE_CH_ACTIVATE,
327c8349639SHoratiu Vultur lan966x, FDMA_CH_ACTIVATE);
328c8349639SHoratiu Vultur }
329c8349639SHoratiu Vultur
lan966x_fdma_tx_disable(struct lan966x_tx * tx)330c8349639SHoratiu Vultur static void lan966x_fdma_tx_disable(struct lan966x_tx *tx)
331c8349639SHoratiu Vultur {
332c8349639SHoratiu Vultur struct lan966x *lan966x = tx->lan966x;
333c8349639SHoratiu Vultur u32 val;
334c8349639SHoratiu Vultur
335c8349639SHoratiu Vultur /* Disable the channel */
336c8349639SHoratiu Vultur lan_rmw(FDMA_CH_DISABLE_CH_DISABLE_SET(BIT(tx->channel_id)),
337c8349639SHoratiu Vultur FDMA_CH_DISABLE_CH_DISABLE,
338c8349639SHoratiu Vultur lan966x, FDMA_CH_DISABLE);
339c8349639SHoratiu Vultur
340c8349639SHoratiu Vultur readx_poll_timeout_atomic(lan966x_fdma_channel_active, lan966x,
341c8349639SHoratiu Vultur val, !(val & BIT(tx->channel_id)),
342c8349639SHoratiu Vultur READL_SLEEP_US, READL_TIMEOUT_US);
343c8349639SHoratiu Vultur
344c8349639SHoratiu Vultur lan_rmw(FDMA_CH_DB_DISCARD_DB_DISCARD_SET(BIT(tx->channel_id)),
345c8349639SHoratiu Vultur FDMA_CH_DB_DISCARD_DB_DISCARD,
346c8349639SHoratiu Vultur lan966x, FDMA_CH_DB_DISCARD);
347c8349639SHoratiu Vultur
348c8349639SHoratiu Vultur tx->activated = false;
3494a4b6848SHoratiu Vultur tx->last_in_use = -1;
350c8349639SHoratiu Vultur }
351c8349639SHoratiu Vultur
lan966x_fdma_tx_reload(struct lan966x_tx * tx)352c8349639SHoratiu Vultur static void lan966x_fdma_tx_reload(struct lan966x_tx *tx)
353c8349639SHoratiu Vultur {
354c8349639SHoratiu Vultur struct lan966x *lan966x = tx->lan966x;
355c8349639SHoratiu Vultur
356c8349639SHoratiu Vultur /* Write the registers to reload the channel */
357c8349639SHoratiu Vultur lan_rmw(FDMA_CH_RELOAD_CH_RELOAD_SET(BIT(tx->channel_id)),
358c8349639SHoratiu Vultur FDMA_CH_RELOAD_CH_RELOAD,
359c8349639SHoratiu Vultur lan966x, FDMA_CH_RELOAD);
360c8349639SHoratiu Vultur }
361c8349639SHoratiu Vultur
lan966x_fdma_wakeup_netdev(struct lan966x * lan966x)362c8349639SHoratiu Vultur static void lan966x_fdma_wakeup_netdev(struct lan966x *lan966x)
363c8349639SHoratiu Vultur {
364c8349639SHoratiu Vultur struct lan966x_port *port;
365c8349639SHoratiu Vultur int i;
366c8349639SHoratiu Vultur
367c8349639SHoratiu Vultur for (i = 0; i < lan966x->num_phys_ports; ++i) {
368c8349639SHoratiu Vultur port = lan966x->ports[i];
369c8349639SHoratiu Vultur if (!port)
370c8349639SHoratiu Vultur continue;
371c8349639SHoratiu Vultur
372c8349639SHoratiu Vultur if (netif_queue_stopped(port->dev))
373c8349639SHoratiu Vultur netif_wake_queue(port->dev);
374c8349639SHoratiu Vultur }
375c8349639SHoratiu Vultur }
376c8349639SHoratiu Vultur
lan966x_fdma_stop_netdev(struct lan966x * lan966x)3772ea1cbacSHoratiu Vultur static void lan966x_fdma_stop_netdev(struct lan966x *lan966x)
3782ea1cbacSHoratiu Vultur {
3792ea1cbacSHoratiu Vultur struct lan966x_port *port;
3802ea1cbacSHoratiu Vultur int i;
3812ea1cbacSHoratiu Vultur
3822ea1cbacSHoratiu Vultur for (i = 0; i < lan966x->num_phys_ports; ++i) {
3832ea1cbacSHoratiu Vultur port = lan966x->ports[i];
3842ea1cbacSHoratiu Vultur if (!port)
3852ea1cbacSHoratiu Vultur continue;
3862ea1cbacSHoratiu Vultur
3872ea1cbacSHoratiu Vultur netif_stop_queue(port->dev);
3882ea1cbacSHoratiu Vultur }
3892ea1cbacSHoratiu Vultur }
3902ea1cbacSHoratiu Vultur
lan966x_fdma_tx_clear_buf(struct lan966x * lan966x,int weight)391c8349639SHoratiu Vultur static void lan966x_fdma_tx_clear_buf(struct lan966x *lan966x, int weight)
392c8349639SHoratiu Vultur {
393c8349639SHoratiu Vultur struct lan966x_tx *tx = &lan966x->tx;
394700f11ebSHoratiu Vultur struct lan966x_rx *rx = &lan966x->rx;
395c8349639SHoratiu Vultur struct lan966x_tx_dcb_buf *dcb_buf;
396a825b611SHoratiu Vultur struct xdp_frame_bulk bq;
397c8349639SHoratiu Vultur struct lan966x_db *db;
398c8349639SHoratiu Vultur unsigned long flags;
399c8349639SHoratiu Vultur bool clear = false;
400c8349639SHoratiu Vultur int i;
401c8349639SHoratiu Vultur
402a825b611SHoratiu Vultur xdp_frame_bulk_init(&bq);
403a825b611SHoratiu Vultur
404c8349639SHoratiu Vultur spin_lock_irqsave(&lan966x->tx_lock, flags);
405c8349639SHoratiu Vultur for (i = 0; i < FDMA_DCB_MAX; ++i) {
406c8349639SHoratiu Vultur dcb_buf = &tx->dcbs_buf[i];
407c8349639SHoratiu Vultur
408c8349639SHoratiu Vultur if (!dcb_buf->used)
409c8349639SHoratiu Vultur continue;
410c8349639SHoratiu Vultur
411c8349639SHoratiu Vultur db = &tx->dcbs[i].db[0];
412c8349639SHoratiu Vultur if (!(db->status & FDMA_DCB_STATUS_DONE))
413c8349639SHoratiu Vultur continue;
414c8349639SHoratiu Vultur
415c8349639SHoratiu Vultur dcb_buf->dev->stats.tx_packets++;
41649f5eea8SHoratiu Vultur dcb_buf->dev->stats.tx_bytes += dcb_buf->len;
417c8349639SHoratiu Vultur
418c8349639SHoratiu Vultur dcb_buf->used = false;
41919c6f534SHoratiu Vultur if (dcb_buf->use_skb) {
420c8349639SHoratiu Vultur dma_unmap_single(lan966x->dev,
421c8349639SHoratiu Vultur dcb_buf->dma_addr,
42249f5eea8SHoratiu Vultur dcb_buf->len,
423c8349639SHoratiu Vultur DMA_TO_DEVICE);
42419c6f534SHoratiu Vultur
425c8349639SHoratiu Vultur if (!dcb_buf->ptp)
42619c6f534SHoratiu Vultur napi_consume_skb(dcb_buf->data.skb, weight);
42719c6f534SHoratiu Vultur } else {
428a825b611SHoratiu Vultur if (dcb_buf->xdp_ndo)
429a825b611SHoratiu Vultur dma_unmap_single(lan966x->dev,
430a825b611SHoratiu Vultur dcb_buf->dma_addr,
431a825b611SHoratiu Vultur dcb_buf->len,
432a825b611SHoratiu Vultur DMA_TO_DEVICE);
433a825b611SHoratiu Vultur
434a825b611SHoratiu Vultur if (dcb_buf->xdp_ndo)
435a825b611SHoratiu Vultur xdp_return_frame_bulk(dcb_buf->data.xdpf, &bq);
436a825b611SHoratiu Vultur else
437700f11ebSHoratiu Vultur page_pool_recycle_direct(rx->page_pool,
438700f11ebSHoratiu Vultur dcb_buf->data.page);
43919c6f534SHoratiu Vultur }
440c8349639SHoratiu Vultur
441c8349639SHoratiu Vultur clear = true;
442c8349639SHoratiu Vultur }
443c8349639SHoratiu Vultur
444a825b611SHoratiu Vultur xdp_flush_frame_bulk(&bq);
445a825b611SHoratiu Vultur
446c8349639SHoratiu Vultur if (clear)
447c8349639SHoratiu Vultur lan966x_fdma_wakeup_netdev(lan966x);
448c8349639SHoratiu Vultur
449c8349639SHoratiu Vultur spin_unlock_irqrestore(&lan966x->tx_lock, flags);
450c8349639SHoratiu Vultur }
451c8349639SHoratiu Vultur
lan966x_fdma_rx_more_frames(struct lan966x_rx * rx)452c8349639SHoratiu Vultur static bool lan966x_fdma_rx_more_frames(struct lan966x_rx *rx)
453c8349639SHoratiu Vultur {
454c8349639SHoratiu Vultur struct lan966x_db *db;
455c8349639SHoratiu Vultur
456c8349639SHoratiu Vultur /* Check if there is any data */
457c8349639SHoratiu Vultur db = &rx->dcbs[rx->dcb_index].db[rx->db_index];
458c8349639SHoratiu Vultur if (unlikely(!(db->status & FDMA_DCB_STATUS_DONE)))
459c8349639SHoratiu Vultur return false;
460c8349639SHoratiu Vultur
461c8349639SHoratiu Vultur return true;
462c8349639SHoratiu Vultur }
463c8349639SHoratiu Vultur
lan966x_fdma_rx_check_frame(struct lan966x_rx * rx,u64 * src_port)4644a00b0c7SHoratiu Vultur static int lan966x_fdma_rx_check_frame(struct lan966x_rx *rx, u64 *src_port)
465c8349639SHoratiu Vultur {
466c8349639SHoratiu Vultur struct lan966x *lan966x = rx->lan966x;
4676a2159beSHoratiu Vultur struct lan966x_port *port;
468c8349639SHoratiu Vultur struct lan966x_db *db;
469c8349639SHoratiu Vultur struct page *page;
470c8349639SHoratiu Vultur
471c8349639SHoratiu Vultur db = &rx->dcbs[rx->dcb_index].db[rx->db_index];
472c8349639SHoratiu Vultur page = rx->page[rx->dcb_index][rx->db_index];
4734a00b0c7SHoratiu Vultur if (unlikely(!page))
4744a00b0c7SHoratiu Vultur return FDMA_ERROR;
475fc57062fSHoratiu Vultur
4767292bb06SHoratiu Vultur dma_sync_single_for_cpu(lan966x->dev,
4777292bb06SHoratiu Vultur (dma_addr_t)db->dataptr + XDP_PACKET_HEADROOM,
478fc57062fSHoratiu Vultur FDMA_DCB_STATUS_BLOCKL(db->status),
479fc57062fSHoratiu Vultur DMA_FROM_DEVICE);
480fc57062fSHoratiu Vultur
4817292bb06SHoratiu Vultur lan966x_ifh_get_src_port(page_address(page) + XDP_PACKET_HEADROOM,
4827292bb06SHoratiu Vultur src_port);
4834a00b0c7SHoratiu Vultur if (WARN_ON(*src_port >= lan966x->num_phys_ports))
4844a00b0c7SHoratiu Vultur return FDMA_ERROR;
4854a00b0c7SHoratiu Vultur
4866a2159beSHoratiu Vultur port = lan966x->ports[*src_port];
4876a2159beSHoratiu Vultur if (!lan966x_xdp_port_present(port))
4884a00b0c7SHoratiu Vultur return FDMA_PASS;
4896a2159beSHoratiu Vultur
4906a2159beSHoratiu Vultur return lan966x_xdp_run(port, page, FDMA_DCB_STATUS_BLOCKL(db->status));
4914a00b0c7SHoratiu Vultur }
4924a00b0c7SHoratiu Vultur
lan966x_fdma_rx_get_frame(struct lan966x_rx * rx,u64 src_port)4934a00b0c7SHoratiu Vultur static struct sk_buff *lan966x_fdma_rx_get_frame(struct lan966x_rx *rx,
4944a00b0c7SHoratiu Vultur u64 src_port)
4954a00b0c7SHoratiu Vultur {
4964a00b0c7SHoratiu Vultur struct lan966x *lan966x = rx->lan966x;
4974a00b0c7SHoratiu Vultur struct lan966x_db *db;
4984a00b0c7SHoratiu Vultur struct sk_buff *skb;
4994a00b0c7SHoratiu Vultur struct page *page;
5004a00b0c7SHoratiu Vultur u64 timestamp;
5014a00b0c7SHoratiu Vultur
5024a00b0c7SHoratiu Vultur /* Get the received frame and unmap it */
5034a00b0c7SHoratiu Vultur db = &rx->dcbs[rx->dcb_index].db[rx->db_index];
5044a00b0c7SHoratiu Vultur page = rx->page[rx->dcb_index][rx->db_index];
5054a00b0c7SHoratiu Vultur
5064a00b0c7SHoratiu Vultur skb = build_skb(page_address(page), PAGE_SIZE << rx->page_order);
5074a00b0c7SHoratiu Vultur if (unlikely(!skb))
5084a00b0c7SHoratiu Vultur goto free_page;
5094a00b0c7SHoratiu Vultur
51011871abaSHoratiu Vultur skb_mark_for_recycle(skb);
51111871abaSHoratiu Vultur
5127292bb06SHoratiu Vultur skb_reserve(skb, XDP_PACKET_HEADROOM);
5134a00b0c7SHoratiu Vultur skb_put(skb, FDMA_DCB_STATUS_BLOCKL(db->status));
5144a00b0c7SHoratiu Vultur
5154a00b0c7SHoratiu Vultur lan966x_ifh_get_timestamp(skb->data, ×tamp);
5164a00b0c7SHoratiu Vultur
517c8349639SHoratiu Vultur skb->dev = lan966x->ports[src_port]->dev;
518e83163b6SHoratiu Vultur skb_pull(skb, IFH_LEN_BYTES);
519c8349639SHoratiu Vultur
520c8349639SHoratiu Vultur if (likely(!(skb->dev->features & NETIF_F_RXFCS)))
521c8349639SHoratiu Vultur skb_trim(skb, skb->len - ETH_FCS_LEN);
522c8349639SHoratiu Vultur
523ff89ac70SHoratiu Vultur lan966x_ptp_rxtstamp(lan966x, skb, src_port, timestamp);
524c8349639SHoratiu Vultur skb->protocol = eth_type_trans(skb, skb->dev);
525c8349639SHoratiu Vultur
526c8349639SHoratiu Vultur if (lan966x->bridge_mask & BIT(src_port)) {
527c8349639SHoratiu Vultur skb->offload_fwd_mark = 1;
528c8349639SHoratiu Vultur
529c8349639SHoratiu Vultur skb_reset_network_header(skb);
530c8349639SHoratiu Vultur if (!lan966x_hw_offload(lan966x, src_port, skb))
531c8349639SHoratiu Vultur skb->offload_fwd_mark = 0;
532c8349639SHoratiu Vultur }
533c8349639SHoratiu Vultur
534c8349639SHoratiu Vultur skb->dev->stats.rx_bytes += skb->len;
535c8349639SHoratiu Vultur skb->dev->stats.rx_packets++;
536c8349639SHoratiu Vultur
537c8349639SHoratiu Vultur return skb;
538c8349639SHoratiu Vultur
5394a00b0c7SHoratiu Vultur free_page:
54011871abaSHoratiu Vultur page_pool_recycle_direct(rx->page_pool, page);
541c8349639SHoratiu Vultur
542c8349639SHoratiu Vultur return NULL;
543c8349639SHoratiu Vultur }
544c8349639SHoratiu Vultur
lan966x_fdma_napi_poll(struct napi_struct * napi,int weight)545c8349639SHoratiu Vultur static int lan966x_fdma_napi_poll(struct napi_struct *napi, int weight)
546c8349639SHoratiu Vultur {
547c8349639SHoratiu Vultur struct lan966x *lan966x = container_of(napi, struct lan966x, napi);
548c8349639SHoratiu Vultur struct lan966x_rx *rx = &lan966x->rx;
549c8349639SHoratiu Vultur int dcb_reload = rx->dcb_index;
550c8349639SHoratiu Vultur struct lan966x_rx_dcb *old_dcb;
551c8349639SHoratiu Vultur struct lan966x_db *db;
552a825b611SHoratiu Vultur bool redirect = false;
553c8349639SHoratiu Vultur struct sk_buff *skb;
554c8349639SHoratiu Vultur struct page *page;
555c8349639SHoratiu Vultur int counter = 0;
5564a00b0c7SHoratiu Vultur u64 src_port;
557c8349639SHoratiu Vultur u64 nextptr;
558c8349639SHoratiu Vultur
559c8349639SHoratiu Vultur lan966x_fdma_tx_clear_buf(lan966x, weight);
560c8349639SHoratiu Vultur
561c8349639SHoratiu Vultur /* Get all received skb */
562c8349639SHoratiu Vultur while (counter < weight) {
563c8349639SHoratiu Vultur if (!lan966x_fdma_rx_more_frames(rx))
564c8349639SHoratiu Vultur break;
565c8349639SHoratiu Vultur
566c8349639SHoratiu Vultur counter++;
5674a00b0c7SHoratiu Vultur
5684a00b0c7SHoratiu Vultur switch (lan966x_fdma_rx_check_frame(rx, &src_port)) {
5694a00b0c7SHoratiu Vultur case FDMA_PASS:
5704a00b0c7SHoratiu Vultur break;
5714a00b0c7SHoratiu Vultur case FDMA_ERROR:
5724a00b0c7SHoratiu Vultur lan966x_fdma_rx_free_page(rx);
5734a00b0c7SHoratiu Vultur lan966x_fdma_rx_advance_dcb(rx);
5744a00b0c7SHoratiu Vultur goto allocate_new;
575a825b611SHoratiu Vultur case FDMA_REDIRECT:
576a825b611SHoratiu Vultur redirect = true;
577a825b611SHoratiu Vultur fallthrough;
57819c6f534SHoratiu Vultur case FDMA_TX:
57919c6f534SHoratiu Vultur lan966x_fdma_rx_advance_dcb(rx);
58019c6f534SHoratiu Vultur continue;
5816a2159beSHoratiu Vultur case FDMA_DROP:
5826a2159beSHoratiu Vultur lan966x_fdma_rx_free_page(rx);
5836a2159beSHoratiu Vultur lan966x_fdma_rx_advance_dcb(rx);
5846a2159beSHoratiu Vultur continue;
585c8349639SHoratiu Vultur }
586c8349639SHoratiu Vultur
5874a00b0c7SHoratiu Vultur skb = lan966x_fdma_rx_get_frame(rx, src_port);
5884a00b0c7SHoratiu Vultur lan966x_fdma_rx_advance_dcb(rx);
5894a00b0c7SHoratiu Vultur if (!skb)
5904a00b0c7SHoratiu Vultur goto allocate_new;
5914a00b0c7SHoratiu Vultur
5924a00b0c7SHoratiu Vultur napi_gro_receive(&lan966x->napi, skb);
5934a00b0c7SHoratiu Vultur }
5944a00b0c7SHoratiu Vultur
5954a00b0c7SHoratiu Vultur allocate_new:
596c8349639SHoratiu Vultur /* Allocate new pages and map them */
597c8349639SHoratiu Vultur while (dcb_reload != rx->dcb_index) {
598c8349639SHoratiu Vultur db = &rx->dcbs[dcb_reload].db[rx->db_index];
599c8349639SHoratiu Vultur page = lan966x_fdma_rx_alloc_page(rx, db);
600c8349639SHoratiu Vultur if (unlikely(!page))
601c8349639SHoratiu Vultur break;
602c8349639SHoratiu Vultur rx->page[dcb_reload][rx->db_index] = page;
603c8349639SHoratiu Vultur
604c8349639SHoratiu Vultur old_dcb = &rx->dcbs[dcb_reload];
605c8349639SHoratiu Vultur dcb_reload++;
606c8349639SHoratiu Vultur dcb_reload &= FDMA_DCB_MAX - 1;
607c8349639SHoratiu Vultur
608c8349639SHoratiu Vultur nextptr = rx->dma + ((unsigned long)old_dcb -
609c8349639SHoratiu Vultur (unsigned long)rx->dcbs);
610c8349639SHoratiu Vultur lan966x_fdma_rx_add_dcb(rx, old_dcb, nextptr);
611c8349639SHoratiu Vultur lan966x_fdma_rx_reload(rx);
612c8349639SHoratiu Vultur }
613c8349639SHoratiu Vultur
614a825b611SHoratiu Vultur if (redirect)
615a825b611SHoratiu Vultur xdp_do_flush();
616a825b611SHoratiu Vultur
61712b57179SMagnus Karlsson if (counter < weight && napi_complete_done(napi, counter))
61812b57179SMagnus Karlsson lan_wr(0xff, lan966x, FDMA_INTR_DB_ENA);
61912b57179SMagnus Karlsson
620c8349639SHoratiu Vultur return counter;
621c8349639SHoratiu Vultur }
622c8349639SHoratiu Vultur
lan966x_fdma_irq_handler(int irq,void * args)623c8349639SHoratiu Vultur irqreturn_t lan966x_fdma_irq_handler(int irq, void *args)
624c8349639SHoratiu Vultur {
625c8349639SHoratiu Vultur struct lan966x *lan966x = args;
626c8349639SHoratiu Vultur u32 db, err, err_type;
627c8349639SHoratiu Vultur
628c8349639SHoratiu Vultur db = lan_rd(lan966x, FDMA_INTR_DB);
629c8349639SHoratiu Vultur err = lan_rd(lan966x, FDMA_INTR_ERR);
630c8349639SHoratiu Vultur
631c8349639SHoratiu Vultur if (db) {
632c8349639SHoratiu Vultur lan_wr(0, lan966x, FDMA_INTR_DB_ENA);
633c8349639SHoratiu Vultur lan_wr(db, lan966x, FDMA_INTR_DB);
634c8349639SHoratiu Vultur
635c8349639SHoratiu Vultur napi_schedule(&lan966x->napi);
636c8349639SHoratiu Vultur }
637c8349639SHoratiu Vultur
638c8349639SHoratiu Vultur if (err) {
639c8349639SHoratiu Vultur err_type = lan_rd(lan966x, FDMA_ERRORS);
640c8349639SHoratiu Vultur
641c8349639SHoratiu Vultur WARN(1, "Unexpected error: %d, error_type: %d\n", err, err_type);
642c8349639SHoratiu Vultur
643c8349639SHoratiu Vultur lan_wr(err, lan966x, FDMA_INTR_ERR);
644c8349639SHoratiu Vultur lan_wr(err_type, lan966x, FDMA_ERRORS);
645c8349639SHoratiu Vultur }
646c8349639SHoratiu Vultur
647c8349639SHoratiu Vultur return IRQ_HANDLED;
648c8349639SHoratiu Vultur }
649c8349639SHoratiu Vultur
lan966x_fdma_get_next_dcb(struct lan966x_tx * tx)650c8349639SHoratiu Vultur static int lan966x_fdma_get_next_dcb(struct lan966x_tx *tx)
651c8349639SHoratiu Vultur {
652c8349639SHoratiu Vultur struct lan966x_tx_dcb_buf *dcb_buf;
653c8349639SHoratiu Vultur int i;
654c8349639SHoratiu Vultur
655c8349639SHoratiu Vultur for (i = 0; i < FDMA_DCB_MAX; ++i) {
656c8349639SHoratiu Vultur dcb_buf = &tx->dcbs_buf[i];
657c8349639SHoratiu Vultur if (!dcb_buf->used && i != tx->last_in_use)
658c8349639SHoratiu Vultur return i;
659c8349639SHoratiu Vultur }
660c8349639SHoratiu Vultur
661c8349639SHoratiu Vultur return -1;
662c8349639SHoratiu Vultur }
663c8349639SHoratiu Vultur
lan966x_fdma_tx_setup_dcb(struct lan966x_tx * tx,int next_to_use,int len,dma_addr_t dma_addr)6643d66bc57SHoratiu Vultur static void lan966x_fdma_tx_setup_dcb(struct lan966x_tx *tx,
6653d66bc57SHoratiu Vultur int next_to_use, int len,
6663d66bc57SHoratiu Vultur dma_addr_t dma_addr)
6673d66bc57SHoratiu Vultur {
6683d66bc57SHoratiu Vultur struct lan966x_tx_dcb *next_dcb;
6693d66bc57SHoratiu Vultur struct lan966x_db *next_db;
6703d66bc57SHoratiu Vultur
6713d66bc57SHoratiu Vultur next_dcb = &tx->dcbs[next_to_use];
6723d66bc57SHoratiu Vultur next_dcb->nextptr = FDMA_DCB_INVALID_DATA;
6733d66bc57SHoratiu Vultur
6743d66bc57SHoratiu Vultur next_db = &next_dcb->db[0];
6753d66bc57SHoratiu Vultur next_db->dataptr = dma_addr;
6763d66bc57SHoratiu Vultur next_db->status = FDMA_DCB_STATUS_SOF |
6773d66bc57SHoratiu Vultur FDMA_DCB_STATUS_EOF |
6783d66bc57SHoratiu Vultur FDMA_DCB_STATUS_INTR |
6793d66bc57SHoratiu Vultur FDMA_DCB_STATUS_BLOCKO(0) |
6803d66bc57SHoratiu Vultur FDMA_DCB_STATUS_BLOCKL(len);
6813d66bc57SHoratiu Vultur }
6823d66bc57SHoratiu Vultur
lan966x_fdma_tx_start(struct lan966x_tx * tx,int next_to_use)6833d66bc57SHoratiu Vultur static void lan966x_fdma_tx_start(struct lan966x_tx *tx, int next_to_use)
6843d66bc57SHoratiu Vultur {
6853d66bc57SHoratiu Vultur struct lan966x *lan966x = tx->lan966x;
6863d66bc57SHoratiu Vultur struct lan966x_tx_dcb *dcb;
6873d66bc57SHoratiu Vultur
6883d66bc57SHoratiu Vultur if (likely(lan966x->tx.activated)) {
6893d66bc57SHoratiu Vultur /* Connect current dcb to the next db */
6903d66bc57SHoratiu Vultur dcb = &tx->dcbs[tx->last_in_use];
6913d66bc57SHoratiu Vultur dcb->nextptr = tx->dma + (next_to_use *
6923d66bc57SHoratiu Vultur sizeof(struct lan966x_tx_dcb));
6933d66bc57SHoratiu Vultur
6943d66bc57SHoratiu Vultur lan966x_fdma_tx_reload(tx);
6953d66bc57SHoratiu Vultur } else {
6963d66bc57SHoratiu Vultur /* Because it is first time, then just activate */
6973d66bc57SHoratiu Vultur lan966x->tx.activated = true;
6983d66bc57SHoratiu Vultur lan966x_fdma_tx_activate(tx);
6993d66bc57SHoratiu Vultur }
7003d66bc57SHoratiu Vultur
7013d66bc57SHoratiu Vultur /* Move to next dcb because this last in use */
7023d66bc57SHoratiu Vultur tx->last_in_use = next_to_use;
7033d66bc57SHoratiu Vultur }
7043d66bc57SHoratiu Vultur
lan966x_fdma_xmit_xdpf(struct lan966x_port * port,void * ptr,u32 len)705700f11ebSHoratiu Vultur int lan966x_fdma_xmit_xdpf(struct lan966x_port *port, void *ptr, u32 len)
70619c6f534SHoratiu Vultur {
70719c6f534SHoratiu Vultur struct lan966x *lan966x = port->lan966x;
70819c6f534SHoratiu Vultur struct lan966x_tx_dcb_buf *next_dcb_buf;
70919c6f534SHoratiu Vultur struct lan966x_tx *tx = &lan966x->tx;
710700f11ebSHoratiu Vultur struct xdp_frame *xdpf;
71119c6f534SHoratiu Vultur dma_addr_t dma_addr;
712700f11ebSHoratiu Vultur struct page *page;
71319c6f534SHoratiu Vultur int next_to_use;
71419c6f534SHoratiu Vultur __be32 *ifh;
71519c6f534SHoratiu Vultur int ret = 0;
71619c6f534SHoratiu Vultur
71719c6f534SHoratiu Vultur spin_lock(&lan966x->tx_lock);
71819c6f534SHoratiu Vultur
71919c6f534SHoratiu Vultur /* Get next index */
72019c6f534SHoratiu Vultur next_to_use = lan966x_fdma_get_next_dcb(tx);
72119c6f534SHoratiu Vultur if (next_to_use < 0) {
72219c6f534SHoratiu Vultur netif_stop_queue(port->dev);
72319c6f534SHoratiu Vultur ret = NETDEV_TX_BUSY;
72419c6f534SHoratiu Vultur goto out;
72519c6f534SHoratiu Vultur }
72619c6f534SHoratiu Vultur
727700f11ebSHoratiu Vultur /* Get the next buffer */
728700f11ebSHoratiu Vultur next_dcb_buf = &tx->dcbs_buf[next_to_use];
729700f11ebSHoratiu Vultur
73019c6f534SHoratiu Vultur /* Generate new IFH */
731700f11ebSHoratiu Vultur if (!len) {
732700f11ebSHoratiu Vultur xdpf = ptr;
733700f11ebSHoratiu Vultur
734a825b611SHoratiu Vultur if (xdpf->headroom < IFH_LEN_BYTES) {
735a825b611SHoratiu Vultur ret = NETDEV_TX_OK;
736a825b611SHoratiu Vultur goto out;
737a825b611SHoratiu Vultur }
738a825b611SHoratiu Vultur
739a825b611SHoratiu Vultur ifh = xdpf->data - IFH_LEN_BYTES;
740a825b611SHoratiu Vultur memset(ifh, 0x0, sizeof(__be32) * IFH_LEN);
741a825b611SHoratiu Vultur lan966x_ifh_set_bypass(ifh, 1);
742a825b611SHoratiu Vultur lan966x_ifh_set_port(ifh, BIT_ULL(port->chip_port));
743a825b611SHoratiu Vultur
744a825b611SHoratiu Vultur dma_addr = dma_map_single(lan966x->dev,
745a825b611SHoratiu Vultur xdpf->data - IFH_LEN_BYTES,
746a825b611SHoratiu Vultur xdpf->len + IFH_LEN_BYTES,
747a825b611SHoratiu Vultur DMA_TO_DEVICE);
748a825b611SHoratiu Vultur if (dma_mapping_error(lan966x->dev, dma_addr)) {
749a825b611SHoratiu Vultur ret = NETDEV_TX_OK;
750a825b611SHoratiu Vultur goto out;
751a825b611SHoratiu Vultur }
752a825b611SHoratiu Vultur
753700f11ebSHoratiu Vultur next_dcb_buf->data.xdpf = xdpf;
754700f11ebSHoratiu Vultur next_dcb_buf->len = xdpf->len + IFH_LEN_BYTES;
755700f11ebSHoratiu Vultur
756a825b611SHoratiu Vultur /* Setup next dcb */
757a825b611SHoratiu Vultur lan966x_fdma_tx_setup_dcb(tx, next_to_use,
758a825b611SHoratiu Vultur xdpf->len + IFH_LEN_BYTES,
759a825b611SHoratiu Vultur dma_addr);
760a825b611SHoratiu Vultur } else {
761700f11ebSHoratiu Vultur page = ptr;
762700f11ebSHoratiu Vultur
76319c6f534SHoratiu Vultur ifh = page_address(page) + XDP_PACKET_HEADROOM;
76419c6f534SHoratiu Vultur memset(ifh, 0x0, sizeof(__be32) * IFH_LEN);
76519c6f534SHoratiu Vultur lan966x_ifh_set_bypass(ifh, 1);
76619c6f534SHoratiu Vultur lan966x_ifh_set_port(ifh, BIT_ULL(port->chip_port));
76719c6f534SHoratiu Vultur
76819c6f534SHoratiu Vultur dma_addr = page_pool_get_dma_addr(page);
769a825b611SHoratiu Vultur dma_sync_single_for_device(lan966x->dev,
770a825b611SHoratiu Vultur dma_addr + XDP_PACKET_HEADROOM,
771700f11ebSHoratiu Vultur len + IFH_LEN_BYTES,
77219c6f534SHoratiu Vultur DMA_TO_DEVICE);
77319c6f534SHoratiu Vultur
774700f11ebSHoratiu Vultur next_dcb_buf->data.page = page;
775700f11ebSHoratiu Vultur next_dcb_buf->len = len + IFH_LEN_BYTES;
776700f11ebSHoratiu Vultur
77719c6f534SHoratiu Vultur /* Setup next dcb */
778a825b611SHoratiu Vultur lan966x_fdma_tx_setup_dcb(tx, next_to_use,
779700f11ebSHoratiu Vultur len + IFH_LEN_BYTES,
78019c6f534SHoratiu Vultur dma_addr + XDP_PACKET_HEADROOM);
781a825b611SHoratiu Vultur }
78219c6f534SHoratiu Vultur
78319c6f534SHoratiu Vultur /* Fill up the buffer */
78419c6f534SHoratiu Vultur next_dcb_buf->use_skb = false;
785700f11ebSHoratiu Vultur next_dcb_buf->xdp_ndo = !len;
78619c6f534SHoratiu Vultur next_dcb_buf->dma_addr = dma_addr;
78719c6f534SHoratiu Vultur next_dcb_buf->used = true;
78819c6f534SHoratiu Vultur next_dcb_buf->ptp = false;
78919c6f534SHoratiu Vultur next_dcb_buf->dev = port->dev;
79019c6f534SHoratiu Vultur
79119c6f534SHoratiu Vultur /* Start the transmission */
79219c6f534SHoratiu Vultur lan966x_fdma_tx_start(tx, next_to_use);
79319c6f534SHoratiu Vultur
79419c6f534SHoratiu Vultur out:
79519c6f534SHoratiu Vultur spin_unlock(&lan966x->tx_lock);
79619c6f534SHoratiu Vultur
79719c6f534SHoratiu Vultur return ret;
79819c6f534SHoratiu Vultur }
79919c6f534SHoratiu Vultur
lan966x_fdma_xmit(struct sk_buff * skb,__be32 * ifh,struct net_device * dev)800c8349639SHoratiu Vultur int lan966x_fdma_xmit(struct sk_buff *skb, __be32 *ifh, struct net_device *dev)
801c8349639SHoratiu Vultur {
802c8349639SHoratiu Vultur struct lan966x_port *port = netdev_priv(dev);
803c8349639SHoratiu Vultur struct lan966x *lan966x = port->lan966x;
804c8349639SHoratiu Vultur struct lan966x_tx_dcb_buf *next_dcb_buf;
805c8349639SHoratiu Vultur struct lan966x_tx *tx = &lan966x->tx;
806c8349639SHoratiu Vultur int needed_headroom;
807c8349639SHoratiu Vultur int needed_tailroom;
808c8349639SHoratiu Vultur dma_addr_t dma_addr;
809c8349639SHoratiu Vultur int next_to_use;
810c8349639SHoratiu Vultur int err;
811c8349639SHoratiu Vultur
812c8349639SHoratiu Vultur /* Get next index */
813c8349639SHoratiu Vultur next_to_use = lan966x_fdma_get_next_dcb(tx);
814c8349639SHoratiu Vultur if (next_to_use < 0) {
815c8349639SHoratiu Vultur netif_stop_queue(dev);
816c8349639SHoratiu Vultur return NETDEV_TX_BUSY;
817c8349639SHoratiu Vultur }
818c8349639SHoratiu Vultur
819c8349639SHoratiu Vultur if (skb_put_padto(skb, ETH_ZLEN)) {
820c8349639SHoratiu Vultur dev->stats.tx_dropped++;
821c8349639SHoratiu Vultur return NETDEV_TX_OK;
822c8349639SHoratiu Vultur }
823c8349639SHoratiu Vultur
824c8349639SHoratiu Vultur /* skb processing */
825e83163b6SHoratiu Vultur needed_headroom = max_t(int, IFH_LEN_BYTES - skb_headroom(skb), 0);
826c8349639SHoratiu Vultur needed_tailroom = max_t(int, ETH_FCS_LEN - skb_tailroom(skb), 0);
827c8349639SHoratiu Vultur if (needed_headroom || needed_tailroom || skb_header_cloned(skb)) {
828c8349639SHoratiu Vultur err = pskb_expand_head(skb, needed_headroom, needed_tailroom,
829c8349639SHoratiu Vultur GFP_ATOMIC);
830c8349639SHoratiu Vultur if (unlikely(err)) {
831c8349639SHoratiu Vultur dev->stats.tx_dropped++;
832c8349639SHoratiu Vultur err = NETDEV_TX_OK;
833c8349639SHoratiu Vultur goto release;
834c8349639SHoratiu Vultur }
835c8349639SHoratiu Vultur }
836c8349639SHoratiu Vultur
837c8349639SHoratiu Vultur skb_tx_timestamp(skb);
838e83163b6SHoratiu Vultur skb_push(skb, IFH_LEN_BYTES);
839e83163b6SHoratiu Vultur memcpy(skb->data, ifh, IFH_LEN_BYTES);
840c8349639SHoratiu Vultur skb_put(skb, 4);
841c8349639SHoratiu Vultur
842c8349639SHoratiu Vultur dma_addr = dma_map_single(lan966x->dev, skb->data, skb->len,
843c8349639SHoratiu Vultur DMA_TO_DEVICE);
844c8349639SHoratiu Vultur if (dma_mapping_error(lan966x->dev, dma_addr)) {
845c8349639SHoratiu Vultur dev->stats.tx_dropped++;
846c8349639SHoratiu Vultur err = NETDEV_TX_OK;
847c8349639SHoratiu Vultur goto release;
848c8349639SHoratiu Vultur }
849c8349639SHoratiu Vultur
850c8349639SHoratiu Vultur /* Setup next dcb */
8513d66bc57SHoratiu Vultur lan966x_fdma_tx_setup_dcb(tx, next_to_use, skb->len, dma_addr);
852c8349639SHoratiu Vultur
853c8349639SHoratiu Vultur /* Fill up the buffer */
854c8349639SHoratiu Vultur next_dcb_buf = &tx->dcbs_buf[next_to_use];
85519c6f534SHoratiu Vultur next_dcb_buf->use_skb = true;
85619c6f534SHoratiu Vultur next_dcb_buf->data.skb = skb;
857a825b611SHoratiu Vultur next_dcb_buf->xdp_ndo = false;
85849f5eea8SHoratiu Vultur next_dcb_buf->len = skb->len;
859c8349639SHoratiu Vultur next_dcb_buf->dma_addr = dma_addr;
860c8349639SHoratiu Vultur next_dcb_buf->used = true;
861c8349639SHoratiu Vultur next_dcb_buf->ptp = false;
862c8349639SHoratiu Vultur next_dcb_buf->dev = dev;
863c8349639SHoratiu Vultur
864c8349639SHoratiu Vultur if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP &&
865c8349639SHoratiu Vultur LAN966X_SKB_CB(skb)->rew_op == IFH_REW_OP_TWO_STEP_PTP)
866c8349639SHoratiu Vultur next_dcb_buf->ptp = true;
867c8349639SHoratiu Vultur
8683d66bc57SHoratiu Vultur /* Start the transmission */
8693d66bc57SHoratiu Vultur lan966x_fdma_tx_start(tx, next_to_use);
870c8349639SHoratiu Vultur
871c8349639SHoratiu Vultur return NETDEV_TX_OK;
872c8349639SHoratiu Vultur
873c8349639SHoratiu Vultur release:
874c8349639SHoratiu Vultur if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP &&
875c8349639SHoratiu Vultur LAN966X_SKB_CB(skb)->rew_op == IFH_REW_OP_TWO_STEP_PTP)
876c8349639SHoratiu Vultur lan966x_ptp_txtstamp_release(port, skb);
877c8349639SHoratiu Vultur
878c8349639SHoratiu Vultur dev_kfree_skb_any(skb);
879c8349639SHoratiu Vultur return err;
880c8349639SHoratiu Vultur }
881c8349639SHoratiu Vultur
lan966x_fdma_get_max_mtu(struct lan966x * lan966x)8822ea1cbacSHoratiu Vultur static int lan966x_fdma_get_max_mtu(struct lan966x *lan966x)
8832ea1cbacSHoratiu Vultur {
8842ea1cbacSHoratiu Vultur int max_mtu = 0;
8852ea1cbacSHoratiu Vultur int i;
8862ea1cbacSHoratiu Vultur
8872ea1cbacSHoratiu Vultur for (i = 0; i < lan966x->num_phys_ports; ++i) {
888872ad758SHoratiu Vultur struct lan966x_port *port;
8892ea1cbacSHoratiu Vultur int mtu;
8902ea1cbacSHoratiu Vultur
891872ad758SHoratiu Vultur port = lan966x->ports[i];
892872ad758SHoratiu Vultur if (!port)
8932ea1cbacSHoratiu Vultur continue;
8942ea1cbacSHoratiu Vultur
895872ad758SHoratiu Vultur mtu = lan_rd(lan966x, DEV_MAC_MAXLEN_CFG(port->chip_port));
8962ea1cbacSHoratiu Vultur if (mtu > max_mtu)
8972ea1cbacSHoratiu Vultur max_mtu = mtu;
8982ea1cbacSHoratiu Vultur }
8992ea1cbacSHoratiu Vultur
9002ea1cbacSHoratiu Vultur return max_mtu;
9012ea1cbacSHoratiu Vultur }
9022ea1cbacSHoratiu Vultur
lan966x_qsys_sw_status(struct lan966x * lan966x)9032ea1cbacSHoratiu Vultur static int lan966x_qsys_sw_status(struct lan966x *lan966x)
9042ea1cbacSHoratiu Vultur {
9052ea1cbacSHoratiu Vultur return lan_rd(lan966x, QSYS_SW_STATUS(CPU_PORT));
9062ea1cbacSHoratiu Vultur }
9072ea1cbacSHoratiu Vultur
lan966x_fdma_reload(struct lan966x * lan966x,int new_mtu)9082ea1cbacSHoratiu Vultur static int lan966x_fdma_reload(struct lan966x *lan966x, int new_mtu)
9092ea1cbacSHoratiu Vultur {
91011871abaSHoratiu Vultur struct page_pool *page_pool;
9114a4b6848SHoratiu Vultur dma_addr_t rx_dma;
9124a4b6848SHoratiu Vultur void *rx_dcbs;
9132ea1cbacSHoratiu Vultur u32 size;
9142ea1cbacSHoratiu Vultur int err;
9152ea1cbacSHoratiu Vultur
9162ea1cbacSHoratiu Vultur /* Store these for later to free them */
9172ea1cbacSHoratiu Vultur rx_dma = lan966x->rx.dma;
9182ea1cbacSHoratiu Vultur rx_dcbs = lan966x->rx.dcbs;
91911871abaSHoratiu Vultur page_pool = lan966x->rx.page_pool;
9202ea1cbacSHoratiu Vultur
9212ea1cbacSHoratiu Vultur napi_synchronize(&lan966x->napi);
9222ea1cbacSHoratiu Vultur napi_disable(&lan966x->napi);
9232ea1cbacSHoratiu Vultur lan966x_fdma_stop_netdev(lan966x);
9242ea1cbacSHoratiu Vultur
9252ea1cbacSHoratiu Vultur lan966x_fdma_rx_disable(&lan966x->rx);
9262ea1cbacSHoratiu Vultur lan966x_fdma_rx_free_pages(&lan966x->rx);
9272ea1cbacSHoratiu Vultur lan966x->rx.page_order = round_up(new_mtu, PAGE_SIZE) / PAGE_SIZE - 1;
92811871abaSHoratiu Vultur lan966x->rx.max_mtu = new_mtu;
9292ea1cbacSHoratiu Vultur err = lan966x_fdma_rx_alloc(&lan966x->rx);
9302ea1cbacSHoratiu Vultur if (err)
9312ea1cbacSHoratiu Vultur goto restore;
9322ea1cbacSHoratiu Vultur lan966x_fdma_rx_start(&lan966x->rx);
9332ea1cbacSHoratiu Vultur
9342ea1cbacSHoratiu Vultur size = sizeof(struct lan966x_rx_dcb) * FDMA_DCB_MAX;
9352ea1cbacSHoratiu Vultur size = ALIGN(size, PAGE_SIZE);
9362ea1cbacSHoratiu Vultur dma_free_coherent(lan966x->dev, size, rx_dcbs, rx_dma);
9372ea1cbacSHoratiu Vultur
93811871abaSHoratiu Vultur page_pool_destroy(page_pool);
93911871abaSHoratiu Vultur
9402ea1cbacSHoratiu Vultur lan966x_fdma_wakeup_netdev(lan966x);
9412ea1cbacSHoratiu Vultur napi_enable(&lan966x->napi);
9422ea1cbacSHoratiu Vultur
9432ea1cbacSHoratiu Vultur return err;
9442ea1cbacSHoratiu Vultur restore:
94511871abaSHoratiu Vultur lan966x->rx.page_pool = page_pool;
9462ea1cbacSHoratiu Vultur lan966x->rx.dma = rx_dma;
947f0a65f81SHoratiu Vultur lan966x->rx.dcbs = rx_dcbs;
9482ea1cbacSHoratiu Vultur lan966x_fdma_rx_start(&lan966x->rx);
9492ea1cbacSHoratiu Vultur
9502ea1cbacSHoratiu Vultur return err;
9512ea1cbacSHoratiu Vultur }
9522ea1cbacSHoratiu Vultur
lan966x_fdma_get_max_frame(struct lan966x * lan966x)95311871abaSHoratiu Vultur static int lan966x_fdma_get_max_frame(struct lan966x *lan966x)
95411871abaSHoratiu Vultur {
95511871abaSHoratiu Vultur return lan966x_fdma_get_max_mtu(lan966x) +
95611871abaSHoratiu Vultur IFH_LEN_BYTES +
95711871abaSHoratiu Vultur SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) +
9587292bb06SHoratiu Vultur VLAN_HLEN * 2 +
9597292bb06SHoratiu Vultur XDP_PACKET_HEADROOM;
96011871abaSHoratiu Vultur }
96111871abaSHoratiu Vultur
__lan966x_fdma_reload(struct lan966x * lan966x,int max_mtu)962560c7223SHoratiu Vultur static int __lan966x_fdma_reload(struct lan966x *lan966x, int max_mtu)
9632ea1cbacSHoratiu Vultur {
9642ea1cbacSHoratiu Vultur int err;
9652ea1cbacSHoratiu Vultur u32 val;
9662ea1cbacSHoratiu Vultur
9672ea1cbacSHoratiu Vultur /* Disable the CPU port */
9682ea1cbacSHoratiu Vultur lan_rmw(QSYS_SW_PORT_MODE_PORT_ENA_SET(0),
9692ea1cbacSHoratiu Vultur QSYS_SW_PORT_MODE_PORT_ENA,
9702ea1cbacSHoratiu Vultur lan966x, QSYS_SW_PORT_MODE(CPU_PORT));
9712ea1cbacSHoratiu Vultur
9722ea1cbacSHoratiu Vultur /* Flush the CPU queues */
9732ea1cbacSHoratiu Vultur readx_poll_timeout(lan966x_qsys_sw_status, lan966x,
9742ea1cbacSHoratiu Vultur val, !(QSYS_SW_STATUS_EQ_AVAIL_GET(val)),
9752ea1cbacSHoratiu Vultur READL_SLEEP_US, READL_TIMEOUT_US);
9762ea1cbacSHoratiu Vultur
9772ea1cbacSHoratiu Vultur /* Add a sleep in case there are frames between the queues and the CPU
9782ea1cbacSHoratiu Vultur * port
9792ea1cbacSHoratiu Vultur */
9802ea1cbacSHoratiu Vultur usleep_range(1000, 2000);
9812ea1cbacSHoratiu Vultur
9822ea1cbacSHoratiu Vultur err = lan966x_fdma_reload(lan966x, max_mtu);
9832ea1cbacSHoratiu Vultur
9842ea1cbacSHoratiu Vultur /* Enable back the CPU port */
9852ea1cbacSHoratiu Vultur lan_rmw(QSYS_SW_PORT_MODE_PORT_ENA_SET(1),
9862ea1cbacSHoratiu Vultur QSYS_SW_PORT_MODE_PORT_ENA,
9872ea1cbacSHoratiu Vultur lan966x, QSYS_SW_PORT_MODE(CPU_PORT));
9882ea1cbacSHoratiu Vultur
9892ea1cbacSHoratiu Vultur return err;
9902ea1cbacSHoratiu Vultur }
9912ea1cbacSHoratiu Vultur
lan966x_fdma_change_mtu(struct lan966x * lan966x)992560c7223SHoratiu Vultur int lan966x_fdma_change_mtu(struct lan966x *lan966x)
993560c7223SHoratiu Vultur {
994560c7223SHoratiu Vultur int max_mtu;
995560c7223SHoratiu Vultur
996560c7223SHoratiu Vultur max_mtu = lan966x_fdma_get_max_frame(lan966x);
997560c7223SHoratiu Vultur if (max_mtu == lan966x->rx.max_mtu)
998560c7223SHoratiu Vultur return 0;
999560c7223SHoratiu Vultur
1000560c7223SHoratiu Vultur return __lan966x_fdma_reload(lan966x, max_mtu);
1001560c7223SHoratiu Vultur }
1002560c7223SHoratiu Vultur
lan966x_fdma_reload_page_pool(struct lan966x * lan966x)1003560c7223SHoratiu Vultur int lan966x_fdma_reload_page_pool(struct lan966x *lan966x)
1004560c7223SHoratiu Vultur {
1005560c7223SHoratiu Vultur int max_mtu;
1006560c7223SHoratiu Vultur
1007560c7223SHoratiu Vultur max_mtu = lan966x_fdma_get_max_frame(lan966x);
1008560c7223SHoratiu Vultur return __lan966x_fdma_reload(lan966x, max_mtu);
1009560c7223SHoratiu Vultur }
1010560c7223SHoratiu Vultur
lan966x_fdma_netdev_init(struct lan966x * lan966x,struct net_device * dev)1011c8349639SHoratiu Vultur void lan966x_fdma_netdev_init(struct lan966x *lan966x, struct net_device *dev)
1012c8349639SHoratiu Vultur {
1013c8349639SHoratiu Vultur if (lan966x->fdma_ndev)
1014c8349639SHoratiu Vultur return;
1015c8349639SHoratiu Vultur
1016c8349639SHoratiu Vultur lan966x->fdma_ndev = dev;
1017b48b89f9SJakub Kicinski netif_napi_add(dev, &lan966x->napi, lan966x_fdma_napi_poll);
1018c8349639SHoratiu Vultur napi_enable(&lan966x->napi);
1019c8349639SHoratiu Vultur }
1020c8349639SHoratiu Vultur
lan966x_fdma_netdev_deinit(struct lan966x * lan966x,struct net_device * dev)1021c8349639SHoratiu Vultur void lan966x_fdma_netdev_deinit(struct lan966x *lan966x, struct net_device *dev)
1022c8349639SHoratiu Vultur {
1023c8349639SHoratiu Vultur if (lan966x->fdma_ndev == dev) {
1024c8349639SHoratiu Vultur netif_napi_del(&lan966x->napi);
1025c8349639SHoratiu Vultur lan966x->fdma_ndev = NULL;
1026c8349639SHoratiu Vultur }
1027c8349639SHoratiu Vultur }
1028c8349639SHoratiu Vultur
lan966x_fdma_init(struct lan966x * lan966x)1029c8349639SHoratiu Vultur int lan966x_fdma_init(struct lan966x *lan966x)
1030c8349639SHoratiu Vultur {
1031c8349639SHoratiu Vultur int err;
1032c8349639SHoratiu Vultur
1033c8349639SHoratiu Vultur if (!lan966x->fdma)
1034c8349639SHoratiu Vultur return 0;
1035c8349639SHoratiu Vultur
1036c8349639SHoratiu Vultur lan966x->rx.lan966x = lan966x;
1037c8349639SHoratiu Vultur lan966x->rx.channel_id = FDMA_XTR_CHANNEL;
103811871abaSHoratiu Vultur lan966x->rx.max_mtu = lan966x_fdma_get_max_frame(lan966x);
1039c8349639SHoratiu Vultur lan966x->tx.lan966x = lan966x;
1040c8349639SHoratiu Vultur lan966x->tx.channel_id = FDMA_INJ_CHANNEL;
1041c8349639SHoratiu Vultur lan966x->tx.last_in_use = -1;
1042c8349639SHoratiu Vultur
1043c8349639SHoratiu Vultur err = lan966x_fdma_rx_alloc(&lan966x->rx);
1044c8349639SHoratiu Vultur if (err)
1045c8349639SHoratiu Vultur return err;
1046c8349639SHoratiu Vultur
1047c8349639SHoratiu Vultur err = lan966x_fdma_tx_alloc(&lan966x->tx);
1048c8349639SHoratiu Vultur if (err) {
1049c8349639SHoratiu Vultur lan966x_fdma_rx_free(&lan966x->rx);
1050c8349639SHoratiu Vultur return err;
1051c8349639SHoratiu Vultur }
1052c8349639SHoratiu Vultur
1053c8349639SHoratiu Vultur lan966x_fdma_rx_start(&lan966x->rx);
1054c8349639SHoratiu Vultur
1055c8349639SHoratiu Vultur return 0;
1056c8349639SHoratiu Vultur }
1057c8349639SHoratiu Vultur
lan966x_fdma_deinit(struct lan966x * lan966x)1058c8349639SHoratiu Vultur void lan966x_fdma_deinit(struct lan966x *lan966x)
1059c8349639SHoratiu Vultur {
1060c8349639SHoratiu Vultur if (!lan966x->fdma)
1061c8349639SHoratiu Vultur return;
1062c8349639SHoratiu Vultur
1063c8349639SHoratiu Vultur lan966x_fdma_rx_disable(&lan966x->rx);
1064c8349639SHoratiu Vultur lan966x_fdma_tx_disable(&lan966x->tx);
1065c8349639SHoratiu Vultur
1066c8349639SHoratiu Vultur napi_synchronize(&lan966x->napi);
1067c8349639SHoratiu Vultur napi_disable(&lan966x->napi);
1068c8349639SHoratiu Vultur
1069c8349639SHoratiu Vultur lan966x_fdma_rx_free_pages(&lan966x->rx);
1070c8349639SHoratiu Vultur lan966x_fdma_rx_free(&lan966x->rx);
107111871abaSHoratiu Vultur page_pool_destroy(lan966x->rx.page_pool);
1072c8349639SHoratiu Vultur lan966x_fdma_tx_free(&lan966x->tx);
1073c8349639SHoratiu Vultur }
1074