Loading...
1// SPDX-License-Identifier: GPL-2.0-only
2/*******************************************************************************
3 Specialised functions for managing Ring mode
4
5 Copyright(C) 2011 STMicroelectronics Ltd
6
7 It defines all the functions used to handle the normal/enhanced
8 descriptors in case of the DMA is configured to work in chained or
9 in ring mode.
10
11
12 Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
13*******************************************************************************/
14
15#include "stmmac.h"
16
17static int jumbo_frm(struct stmmac_tx_queue *tx_q, struct sk_buff *skb,
18 int csum)
19{
20 unsigned int nopaged_len = skb_headlen(skb);
21 struct stmmac_priv *priv = tx_q->priv_data;
22 unsigned int entry = tx_q->cur_tx;
23 unsigned int bmax, len, des2;
24 struct dma_desc *desc;
25
26 if (priv->extend_desc)
27 desc = (struct dma_desc *)(tx_q->dma_etx + entry);
28 else
29 desc = tx_q->dma_tx + entry;
30
31 if (priv->plat->enh_desc)
32 bmax = BUF_SIZE_8KiB;
33 else
34 bmax = BUF_SIZE_2KiB;
35
36 len = nopaged_len - bmax;
37
38 if (nopaged_len > BUF_SIZE_8KiB) {
39
40 des2 = dma_map_single(priv->device, skb->data, bmax,
41 DMA_TO_DEVICE);
42 desc->des2 = cpu_to_le32(des2);
43 if (dma_mapping_error(priv->device, des2))
44 return -1;
45
46 tx_q->tx_skbuff_dma[entry].buf = des2;
47 tx_q->tx_skbuff_dma[entry].len = bmax;
48 tx_q->tx_skbuff_dma[entry].is_jumbo = true;
49
50 desc->des3 = cpu_to_le32(des2 + BUF_SIZE_4KiB);
51 stmmac_prepare_tx_desc(priv, desc, 1, bmax, csum,
52 STMMAC_RING_MODE, 0, false, skb->len);
53 tx_q->tx_skbuff[entry] = NULL;
54 entry = STMMAC_GET_ENTRY(entry, priv->dma_conf.dma_tx_size);
55
56 if (priv->extend_desc)
57 desc = (struct dma_desc *)(tx_q->dma_etx + entry);
58 else
59 desc = tx_q->dma_tx + entry;
60
61 des2 = dma_map_single(priv->device, skb->data + bmax, len,
62 DMA_TO_DEVICE);
63 desc->des2 = cpu_to_le32(des2);
64 if (dma_mapping_error(priv->device, des2))
65 return -1;
66 tx_q->tx_skbuff_dma[entry].buf = des2;
67 tx_q->tx_skbuff_dma[entry].len = len;
68 tx_q->tx_skbuff_dma[entry].is_jumbo = true;
69
70 desc->des3 = cpu_to_le32(des2 + BUF_SIZE_4KiB);
71 stmmac_prepare_tx_desc(priv, desc, 0, len, csum,
72 STMMAC_RING_MODE, 1, !skb_is_nonlinear(skb),
73 skb->len);
74 } else {
75 des2 = dma_map_single(priv->device, skb->data,
76 nopaged_len, DMA_TO_DEVICE);
77 desc->des2 = cpu_to_le32(des2);
78 if (dma_mapping_error(priv->device, des2))
79 return -1;
80 tx_q->tx_skbuff_dma[entry].buf = des2;
81 tx_q->tx_skbuff_dma[entry].len = nopaged_len;
82 tx_q->tx_skbuff_dma[entry].is_jumbo = true;
83 desc->des3 = cpu_to_le32(des2 + BUF_SIZE_4KiB);
84 stmmac_prepare_tx_desc(priv, desc, 1, nopaged_len, csum,
85 STMMAC_RING_MODE, 0, !skb_is_nonlinear(skb),
86 skb->len);
87 }
88
89 tx_q->cur_tx = entry;
90
91 return entry;
92}
93
94static unsigned int is_jumbo_frm(int len, int enh_desc)
95{
96 unsigned int ret = 0;
97
98 if (len >= BUF_SIZE_4KiB)
99 ret = 1;
100
101 return ret;
102}
103
104static void refill_desc3(struct stmmac_rx_queue *rx_q, struct dma_desc *p)
105{
106 struct stmmac_priv *priv = rx_q->priv_data;
107
108 /* Fill DES3 in case of RING mode */
109 if (priv->dma_conf.dma_buf_sz == BUF_SIZE_16KiB)
110 p->des3 = cpu_to_le32(le32_to_cpu(p->des2) + BUF_SIZE_8KiB);
111}
112
113/* In ring mode we need to fill the desc3 because it is used as buffer */
114static void init_desc3(struct dma_desc *p)
115{
116 p->des3 = cpu_to_le32(le32_to_cpu(p->des2) + BUF_SIZE_8KiB);
117}
118
119static void clean_desc3(struct stmmac_tx_queue *tx_q, struct dma_desc *p)
120{
121 struct stmmac_priv *priv = tx_q->priv_data;
122 unsigned int entry = tx_q->dirty_tx;
123
124 /* des3 is only used for jumbo frames tx or time stamping */
125 if (unlikely(tx_q->tx_skbuff_dma[entry].is_jumbo ||
126 (tx_q->tx_skbuff_dma[entry].last_segment &&
127 !priv->extend_desc && priv->hwts_tx_en)))
128 p->des3 = 0;
129}
130
131static int set_16kib_bfsize(int mtu)
132{
133 int ret = 0;
134 if (unlikely(mtu > BUF_SIZE_8KiB))
135 ret = BUF_SIZE_16KiB;
136 return ret;
137}
138
139const struct stmmac_mode_ops ring_mode_ops = {
140 .is_jumbo_frm = is_jumbo_frm,
141 .jumbo_frm = jumbo_frm,
142 .refill_desc3 = refill_desc3,
143 .init_desc3 = init_desc3,
144 .clean_desc3 = clean_desc3,
145 .set_16kib_bfsize = set_16kib_bfsize,
146};
1/*******************************************************************************
2 Specialised functions for managing Ring mode
3
4 Copyright(C) 2011 STMicroelectronics Ltd
5
6 It defines all the functions used to handle the normal/enhanced
7 descriptors in case of the DMA is configured to work in chained or
8 in ring mode.
9
10 This program is free software; you can redistribute it and/or modify it
11 under the terms and conditions of the GNU General Public License,
12 version 2, as published by the Free Software Foundation.
13
14 This program is distributed in the hope it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 more details.
18
19 You should have received a copy of the GNU General Public License along with
20 this program; if not, write to the Free Software Foundation, Inc.,
21 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
22
23 The full GNU General Public License is included in this distribution in
24 the file called "COPYING".
25
26 Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
27*******************************************************************************/
28
29#include "stmmac.h"
30
31static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
32{
33 struct stmmac_priv *priv = (struct stmmac_priv *)p;
34 unsigned int txsize = priv->dma_tx_size;
35 unsigned int entry = priv->cur_tx % txsize;
36 struct dma_desc *desc;
37 unsigned int nopaged_len = skb_headlen(skb);
38 unsigned int bmax, len;
39
40 if (priv->extend_desc)
41 desc = (struct dma_desc *)(priv->dma_etx + entry);
42 else
43 desc = priv->dma_tx + entry;
44
45 if (priv->plat->enh_desc)
46 bmax = BUF_SIZE_8KiB;
47 else
48 bmax = BUF_SIZE_2KiB;
49
50 len = nopaged_len - bmax;
51
52 if (nopaged_len > BUF_SIZE_8KiB) {
53
54 desc->des2 = dma_map_single(priv->device, skb->data,
55 bmax, DMA_TO_DEVICE);
56 priv->tx_skbuff_dma[entry] = desc->des2;
57 desc->des3 = desc->des2 + BUF_SIZE_4KiB;
58 priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum,
59 STMMAC_RING_MODE);
60 wmb();
61 priv->tx_skbuff[entry] = NULL;
62 entry = (++priv->cur_tx) % txsize;
63
64 if (priv->extend_desc)
65 desc = (struct dma_desc *)(priv->dma_etx + entry);
66 else
67 desc = priv->dma_tx + entry;
68
69 desc->des2 = dma_map_single(priv->device, skb->data + bmax,
70 len, DMA_TO_DEVICE);
71 priv->tx_skbuff_dma[entry] = desc->des2;
72 desc->des3 = desc->des2 + BUF_SIZE_4KiB;
73 priv->hw->desc->prepare_tx_desc(desc, 0, len, csum,
74 STMMAC_RING_MODE);
75 wmb();
76 priv->hw->desc->set_tx_owner(desc);
77 } else {
78 desc->des2 = dma_map_single(priv->device, skb->data,
79 nopaged_len, DMA_TO_DEVICE);
80 priv->tx_skbuff_dma[entry] = desc->des2;
81 desc->des3 = desc->des2 + BUF_SIZE_4KiB;
82 priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len, csum,
83 STMMAC_RING_MODE);
84 }
85
86 return entry;
87}
88
89static unsigned int stmmac_is_jumbo_frm(int len, int enh_desc)
90{
91 unsigned int ret = 0;
92
93 if (len >= BUF_SIZE_4KiB)
94 ret = 1;
95
96 return ret;
97}
98
99static void stmmac_refill_desc3(void *priv_ptr, struct dma_desc *p)
100{
101 struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr;
102
103 /* Fill DES3 in case of RING mode */
104 if (priv->dma_buf_sz >= BUF_SIZE_8KiB)
105 p->des3 = p->des2 + BUF_SIZE_8KiB;
106}
107
108/* In ring mode we need to fill the desc3 because it is used as buffer */
109static void stmmac_init_desc3(struct dma_desc *p)
110{
111 p->des3 = p->des2 + BUF_SIZE_8KiB;
112}
113
114static void stmmac_clean_desc3(void *priv_ptr, struct dma_desc *p)
115{
116 if (unlikely(p->des3))
117 p->des3 = 0;
118}
119
120static int stmmac_set_16kib_bfsize(int mtu)
121{
122 int ret = 0;
123 if (unlikely(mtu >= BUF_SIZE_8KiB))
124 ret = BUF_SIZE_16KiB;
125 return ret;
126}
127
128const struct stmmac_mode_ops ring_mode_ops = {
129 .is_jumbo_frm = stmmac_is_jumbo_frm,
130 .jumbo_frm = stmmac_jumbo_frm,
131 .refill_desc3 = stmmac_refill_desc3,
132 .init_desc3 = stmmac_init_desc3,
133 .clean_desc3 = stmmac_clean_desc3,
134 .set_16kib_bfsize = stmmac_set_16kib_bfsize,
135};