blob: 7723b5d2499a1f8e7111d0e74eb8e5634726b30f [file] [log] [blame]
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +00001/*******************************************************************************
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
Giuseppe CAVALLARO362b37b2014-08-27 11:27:00 +020031static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +000032{
Giuseppe CAVALLAROceb694992013-04-08 02:10:01 +000033 struct stmmac_priv *priv = (struct stmmac_priv *)p;
Giuseppe Cavallaroe3ad57c2016-02-29 14:27:30 +010034 unsigned int entry = priv->cur_tx;
Byungho An21ff0192013-08-08 15:30:26 +090035 struct dma_desc *desc;
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +000036 unsigned int nopaged_len = skb_headlen(skb);
37 unsigned int bmax, len;
38
Byungho An21ff0192013-08-08 15:30:26 +090039 if (priv->extend_desc)
40 desc = (struct dma_desc *)(priv->dma_etx + entry);
41 else
42 desc = priv->dma_tx + entry;
43
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +000044 if (priv->plat->enh_desc)
45 bmax = BUF_SIZE_8KiB;
46 else
47 bmax = BUF_SIZE_2KiB;
48
49 len = nopaged_len - bmax;
50
51 if (nopaged_len > BUF_SIZE_8KiB) {
52
53 desc->des2 = dma_map_single(priv->device, skb->data,
54 bmax, DMA_TO_DEVICE);
Giuseppe CAVALLARO362b37b2014-08-27 11:27:00 +020055 if (dma_mapping_error(priv->device, desc->des2))
56 return -1;
57
58 priv->tx_skbuff_dma[entry].buf = desc->des2;
Giuseppe Cavallaro553e2ab2016-02-29 14:27:31 +010059 priv->tx_skbuff_dma[entry].len = bmax;
Giuseppe Cavallaro96951362016-02-29 14:27:33 +010060 priv->tx_skbuff_dma[entry].is_jumbo = true;
Giuseppe Cavallaro553e2ab2016-02-29 14:27:31 +010061
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +000062 desc->des3 = desc->des2 + BUF_SIZE_4KiB;
Giuseppe CAVALLARO4a7d6662013-03-26 04:43:05 +000063 priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum,
Giuseppe Cavallarobe434d52016-02-29 14:27:35 +010064 STMMAC_RING_MODE, 0, false);
damuzi00075e43642014-01-17 23:47:59 +080065 priv->tx_skbuff[entry] = NULL;
Giuseppe Cavallaroe3ad57c2016-02-29 14:27:30 +010066 entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE);
Byungho An21ff0192013-08-08 15:30:26 +090067
68 if (priv->extend_desc)
69 desc = (struct dma_desc *)(priv->dma_etx + entry);
70 else
71 desc = priv->dma_tx + entry;
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +000072
73 desc->des2 = dma_map_single(priv->device, skb->data + bmax,
74 len, DMA_TO_DEVICE);
Giuseppe CAVALLARO362b37b2014-08-27 11:27:00 +020075 if (dma_mapping_error(priv->device, desc->des2))
76 return -1;
77 priv->tx_skbuff_dma[entry].buf = desc->des2;
Giuseppe Cavallaro553e2ab2016-02-29 14:27:31 +010078 priv->tx_skbuff_dma[entry].len = len;
Giuseppe Cavallaro96951362016-02-29 14:27:33 +010079 priv->tx_skbuff_dma[entry].is_jumbo = true;
Giuseppe Cavallaro553e2ab2016-02-29 14:27:31 +010080
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +000081 desc->des3 = desc->des2 + BUF_SIZE_4KiB;
Giuseppe CAVALLARO4a7d6662013-03-26 04:43:05 +000082 priv->hw->desc->prepare_tx_desc(desc, 0, len, csum,
Giuseppe Cavallarobe434d52016-02-29 14:27:35 +010083 STMMAC_RING_MODE, 1, true);
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +000084 } else {
85 desc->des2 = dma_map_single(priv->device, skb->data,
86 nopaged_len, DMA_TO_DEVICE);
Giuseppe CAVALLARO362b37b2014-08-27 11:27:00 +020087 if (dma_mapping_error(priv->device, desc->des2))
88 return -1;
89 priv->tx_skbuff_dma[entry].buf = desc->des2;
Giuseppe Cavallaro553e2ab2016-02-29 14:27:31 +010090 priv->tx_skbuff_dma[entry].len = nopaged_len;
Giuseppe Cavallaro96951362016-02-29 14:27:33 +010091 priv->tx_skbuff_dma[entry].is_jumbo = true;
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +000092 desc->des3 = desc->des2 + BUF_SIZE_4KiB;
Giuseppe CAVALLARO4a7d6662013-03-26 04:43:05 +000093 priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len, csum,
Giuseppe Cavallarobe434d52016-02-29 14:27:35 +010094 STMMAC_RING_MODE, 0, true);
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +000095 }
96
Giuseppe Cavallaroe3ad57c2016-02-29 14:27:30 +010097 priv->cur_tx = entry;
98
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +000099 return entry;
100}
101
102static unsigned int stmmac_is_jumbo_frm(int len, int enh_desc)
103{
104 unsigned int ret = 0;
105
106 if (len >= BUF_SIZE_4KiB)
107 ret = 1;
108
109 return ret;
110}
111
Rayagond Kokatanur891434b2013-03-26 04:43:10 +0000112static void stmmac_refill_desc3(void *priv_ptr, struct dma_desc *p)
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +0000113{
Rayagond Kokatanur891434b2013-03-26 04:43:10 +0000114 struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr;
115
Giuseppe CAVALLARO29896a62014-03-10 13:40:33 +0100116 /* Fill DES3 in case of RING mode */
117 if (priv->dma_buf_sz >= BUF_SIZE_8KiB)
118 p->des3 = p->des2 + BUF_SIZE_8KiB;
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +0000119}
120
Giuseppe CAVALLARO4a7d6662013-03-26 04:43:05 +0000121/* In ring mode we need to fill the desc3 because it is used as buffer */
122static void stmmac_init_desc3(struct dma_desc *p)
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +0000123{
Giuseppe CAVALLARO4a7d6662013-03-26 04:43:05 +0000124 p->des3 = p->des2 + BUF_SIZE_8KiB;
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +0000125}
126
Rayagond Kokatanur891434b2013-03-26 04:43:10 +0000127static void stmmac_clean_desc3(void *priv_ptr, struct dma_desc *p)
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +0000128{
Giuseppe Cavallaro96951362016-02-29 14:27:33 +0100129 struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr;
130 unsigned int entry = priv->dirty_tx;
131
132 /* des3 is only used for jumbo frames tx or time stamping */
133 if (unlikely(priv->tx_skbuff_dma[entry].is_jumbo ||
134 (priv->tx_skbuff_dma[entry].last_segment &&
135 !priv->extend_desc && priv->hwts_tx_en)))
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +0000136 p->des3 = 0;
137}
138
139static int stmmac_set_16kib_bfsize(int mtu)
140{
141 int ret = 0;
142 if (unlikely(mtu >= BUF_SIZE_8KiB))
143 ret = BUF_SIZE_16KiB;
144 return ret;
145}
146
Giuseppe CAVALLARO29896a62014-03-10 13:40:33 +0100147const struct stmmac_mode_ops ring_mode_ops = {
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +0000148 .is_jumbo_frm = stmmac_is_jumbo_frm,
149 .jumbo_frm = stmmac_jumbo_frm,
150 .refill_desc3 = stmmac_refill_desc3,
151 .init_desc3 = stmmac_init_desc3,
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +0000152 .clean_desc3 = stmmac_clean_desc3,
153 .set_16kib_bfsize = stmmac_set_16kib_bfsize,
154};