blob: 2763772ef1d481b28e37a1a73c0fd9974506a3c7 [file] [log] [blame]
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +00001/*******************************************************************************
2 Specialised functions for managing Chained 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;
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +000035 struct dma_desc *desc = priv->dma_tx + entry;
36 unsigned int nopaged_len = skb_headlen(skb);
37 unsigned int bmax;
38 unsigned int i = 1, len;
39
40 if (priv->plat->enh_desc)
41 bmax = BUF_SIZE_8KiB;
42 else
43 bmax = BUF_SIZE_2KiB;
44
45 len = nopaged_len - bmax;
46
47 desc->des2 = dma_map_single(priv->device, skb->data,
48 bmax, DMA_TO_DEVICE);
Giuseppe CAVALLARO362b37b2014-08-27 11:27:00 +020049 if (dma_mapping_error(priv->device, desc->des2))
50 return -1;
51 priv->tx_skbuff_dma[entry].buf = desc->des2;
Giuseppe CAVALLARO4a7d6662013-03-26 04:43:05 +000052 priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum, STMMAC_CHAIN_MODE);
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +000053
54 while (len != 0) {
damuzi00075e43642014-01-17 23:47:59 +080055 priv->tx_skbuff[entry] = NULL;
Giuseppe Cavallaroe3ad57c2016-02-29 14:27:30 +010056 entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE);
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +000057 desc = priv->dma_tx + entry;
58
59 if (len > bmax) {
60 desc->des2 = dma_map_single(priv->device,
61 (skb->data + bmax * i),
62 bmax, DMA_TO_DEVICE);
Giuseppe CAVALLARO362b37b2014-08-27 11:27:00 +020063 if (dma_mapping_error(priv->device, desc->des2))
64 return -1;
65 priv->tx_skbuff_dma[entry].buf = desc->des2;
Giuseppe CAVALLARO4a7d6662013-03-26 04:43:05 +000066 priv->hw->desc->prepare_tx_desc(desc, 0, bmax, csum,
67 STMMAC_CHAIN_MODE);
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +000068 priv->hw->desc->set_tx_owner(desc);
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +000069 len -= bmax;
70 i++;
71 } else {
72 desc->des2 = dma_map_single(priv->device,
73 (skb->data + bmax * i), len,
74 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 CAVALLARO4a7d6662013-03-26 04:43:05 +000078 priv->hw->desc->prepare_tx_desc(desc, 0, len, csum,
79 STMMAC_CHAIN_MODE);
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +000080 priv->hw->desc->set_tx_owner(desc);
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +000081 len = 0;
82 }
83 }
Giuseppe Cavallaroe3ad57c2016-02-29 14:27:30 +010084
85 priv->cur_tx = entry;
86
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +000087 return entry;
88}
89
90static unsigned int stmmac_is_jumbo_frm(int len, int enh_desc)
91{
92 unsigned int ret = 0;
93
94 if ((enh_desc && (len > BUF_SIZE_8KiB)) ||
95 (!enh_desc && (len > BUF_SIZE_2KiB))) {
96 ret = 1;
97 }
98
99 return ret;
100}
101
Giuseppe CAVALLAROc24602e2013-03-26 04:43:06 +0000102static void stmmac_init_dma_chain(void *des, dma_addr_t phy_addr,
103 unsigned int size, unsigned int extend_desc)
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +0000104{
105 /*
106 * In chained mode the des3 points to the next element in the ring.
107 * The latest element has to point to the head.
108 */
109 int i;
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +0000110 dma_addr_t dma_phy = phy_addr;
111
Giuseppe CAVALLAROc24602e2013-03-26 04:43:06 +0000112 if (extend_desc) {
Giuseppe CAVALLAROceb694992013-04-08 02:10:01 +0000113 struct dma_extended_desc *p = (struct dma_extended_desc *)des;
Giuseppe CAVALLAROc24602e2013-03-26 04:43:06 +0000114 for (i = 0; i < (size - 1); i++) {
115 dma_phy += sizeof(struct dma_extended_desc);
116 p->basic.des3 = (unsigned int)dma_phy;
117 p++;
118 }
119 p->basic.des3 = (unsigned int)phy_addr;
120
121 } else {
Giuseppe CAVALLAROceb694992013-04-08 02:10:01 +0000122 struct dma_desc *p = (struct dma_desc *)des;
Giuseppe CAVALLAROc24602e2013-03-26 04:43:06 +0000123 for (i = 0; i < (size - 1); i++) {
124 dma_phy += sizeof(struct dma_desc);
125 p->des3 = (unsigned int)dma_phy;
126 p++;
127 }
128 p->des3 = (unsigned int)phy_addr;
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +0000129 }
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +0000130}
131
Rayagond Kokatanur891434b2013-03-26 04:43:10 +0000132static void stmmac_refill_desc3(void *priv_ptr, struct dma_desc *p)
133{
134 struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr;
135
136 if (priv->hwts_rx_en && !priv->extend_desc)
137 /* NOTE: Device will overwrite des3 with timestamp value if
138 * 1588-2002 time stamping is enabled, hence reinitialize it
139 * to keep explicit chaining in the descriptor.
140 */
141 p->des3 = (unsigned int)(priv->dma_rx_phy +
142 (((priv->dirty_rx) + 1) %
Giuseppe Cavallaroe3ad57c2016-02-29 14:27:30 +0100143 DMA_RX_SIZE) *
Rayagond Kokatanur891434b2013-03-26 04:43:10 +0000144 sizeof(struct dma_desc));
145}
146
147static void stmmac_clean_desc3(void *priv_ptr, struct dma_desc *p)
148{
149 struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr;
150
151 if (priv->hw->desc->get_tx_ls(p) && !priv->extend_desc)
152 /* NOTE: Device will overwrite des3 with timestamp value if
153 * 1588-2002 time stamping is enabled, hence reinitialize it
154 * to keep explicit chaining in the descriptor.
155 */
Giuseppe Cavallaroe3ad57c2016-02-29 14:27:30 +0100156 p->des3 = (unsigned int)((priv->dma_tx_phy +
157 ((priv->dirty_tx + 1) % DMA_TX_SIZE))
158 * sizeof(struct dma_desc));
Rayagond Kokatanur891434b2013-03-26 04:43:10 +0000159}
160
Giuseppe CAVALLARO29896a62014-03-10 13:40:33 +0100161const struct stmmac_mode_ops chain_mode_ops = {
Giuseppe CAVALLAROc24602e2013-03-26 04:43:06 +0000162 .init = stmmac_init_dma_chain,
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +0000163 .is_jumbo_frm = stmmac_is_jumbo_frm,
164 .jumbo_frm = stmmac_jumbo_frm,
Rayagond Kokatanur891434b2013-03-26 04:43:10 +0000165 .refill_desc3 = stmmac_refill_desc3,
166 .clean_desc3 = stmmac_clean_desc3,
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +0000167};