blob: e93c40b4631ecfd706cb0b7c16d58fa5089aa35f [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
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +000019 The full GNU General Public License is included in this distribution in
20 the file called "COPYING".
21
22 Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
23*******************************************************************************/
24
25#include "stmmac.h"
26
Giuseppe CAVALLARO362b37b2014-08-27 11:27:00 +020027static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +000028{
Joao Pintoce736782017-04-06 09:49:10 +010029 struct stmmac_tx_queue *tx_q = (struct stmmac_tx_queue *)p;
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +000030 unsigned int nopaged_len = skb_headlen(skb);
Joao Pintoce736782017-04-06 09:49:10 +010031 struct stmmac_priv *priv = tx_q->priv_data;
32 unsigned int entry = tx_q->cur_tx;
Michael Weiserf8be0d72016-11-14 18:58:05 +010033 unsigned int bmax, des2;
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +000034 unsigned int i = 1, len;
Joao Pintoce736782017-04-06 09:49:10 +010035 struct dma_desc *desc;
36
37 desc = tx_q->dma_tx + entry;
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +000038
39 if (priv->plat->enh_desc)
40 bmax = BUF_SIZE_8KiB;
41 else
42 bmax = BUF_SIZE_2KiB;
43
44 len = nopaged_len - bmax;
45
Michael Weiserf8be0d72016-11-14 18:58:05 +010046 des2 = dma_map_single(priv->device, skb->data,
47 bmax, DMA_TO_DEVICE);
48 desc->des2 = cpu_to_le32(des2);
49 if (dma_mapping_error(priv->device, des2))
Giuseppe CAVALLARO362b37b2014-08-27 11:27:00 +020050 return -1;
Joao Pintoce736782017-04-06 09:49:10 +010051 tx_q->tx_skbuff_dma[entry].buf = des2;
52 tx_q->tx_skbuff_dma[entry].len = bmax;
Giuseppe Cavallarobe434d52016-02-29 14:27:35 +010053 /* do not close the descriptor and do not set own bit */
54 priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum, STMMAC_CHAIN_MODE,
Niklas Casselfe6af0e2017-04-10 20:33:29 +020055 0, false, skb->len);
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +000056
57 while (len != 0) {
Joao Pintoce736782017-04-06 09:49:10 +010058 tx_q->tx_skbuff[entry] = NULL;
Giuseppe Cavallaroe3ad57c2016-02-29 14:27:30 +010059 entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE);
Joao Pintoce736782017-04-06 09:49:10 +010060 desc = tx_q->dma_tx + entry;
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +000061
62 if (len > bmax) {
Michael Weiserf8be0d72016-11-14 18:58:05 +010063 des2 = dma_map_single(priv->device,
64 (skb->data + bmax * i),
65 bmax, DMA_TO_DEVICE);
66 desc->des2 = cpu_to_le32(des2);
67 if (dma_mapping_error(priv->device, des2))
Giuseppe CAVALLARO362b37b2014-08-27 11:27:00 +020068 return -1;
Joao Pintoce736782017-04-06 09:49:10 +010069 tx_q->tx_skbuff_dma[entry].buf = des2;
70 tx_q->tx_skbuff_dma[entry].len = bmax;
Giuseppe CAVALLARO4a7d6662013-03-26 04:43:05 +000071 priv->hw->desc->prepare_tx_desc(desc, 0, bmax, csum,
Giuseppe Cavallarobe434d52016-02-29 14:27:35 +010072 STMMAC_CHAIN_MODE, 1,
Niklas Casselfe6af0e2017-04-10 20:33:29 +020073 false, skb->len);
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +000074 len -= bmax;
75 i++;
76 } else {
Michael Weiserf8be0d72016-11-14 18:58:05 +010077 des2 = dma_map_single(priv->device,
78 (skb->data + bmax * i), len,
79 DMA_TO_DEVICE);
80 desc->des2 = cpu_to_le32(des2);
81 if (dma_mapping_error(priv->device, des2))
Giuseppe CAVALLARO362b37b2014-08-27 11:27:00 +020082 return -1;
Joao Pintoce736782017-04-06 09:49:10 +010083 tx_q->tx_skbuff_dma[entry].buf = des2;
84 tx_q->tx_skbuff_dma[entry].len = len;
Giuseppe Cavallarobe434d52016-02-29 14:27:35 +010085 /* last descriptor can be set now */
Giuseppe CAVALLARO4a7d6662013-03-26 04:43:05 +000086 priv->hw->desc->prepare_tx_desc(desc, 0, len, csum,
Giuseppe Cavallarobe434d52016-02-29 14:27:35 +010087 STMMAC_CHAIN_MODE, 1,
Niklas Casselfe6af0e2017-04-10 20:33:29 +020088 true, skb->len);
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +000089 len = 0;
90 }
91 }
Giuseppe Cavallaroe3ad57c2016-02-29 14:27:30 +010092
Joao Pintoce736782017-04-06 09:49:10 +010093 tx_q->cur_tx = entry;
Giuseppe Cavallaroe3ad57c2016-02-29 14:27:30 +010094
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +000095 return entry;
96}
97
98static unsigned int stmmac_is_jumbo_frm(int len, int enh_desc)
99{
100 unsigned int ret = 0;
101
102 if ((enh_desc && (len > BUF_SIZE_8KiB)) ||
103 (!enh_desc && (len > BUF_SIZE_2KiB))) {
104 ret = 1;
105 }
106
107 return ret;
108}
109
Giuseppe CAVALLAROc24602e2013-03-26 04:43:06 +0000110static void stmmac_init_dma_chain(void *des, dma_addr_t phy_addr,
111 unsigned int size, unsigned int extend_desc)
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +0000112{
113 /*
114 * In chained mode the des3 points to the next element in the ring.
115 * The latest element has to point to the head.
116 */
117 int i;
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +0000118 dma_addr_t dma_phy = phy_addr;
119
Giuseppe CAVALLAROc24602e2013-03-26 04:43:06 +0000120 if (extend_desc) {
Giuseppe CAVALLAROceb694992013-04-08 02:10:01 +0000121 struct dma_extended_desc *p = (struct dma_extended_desc *)des;
Giuseppe CAVALLAROc24602e2013-03-26 04:43:06 +0000122 for (i = 0; i < (size - 1); i++) {
123 dma_phy += sizeof(struct dma_extended_desc);
Michael Weiserf8be0d72016-11-14 18:58:05 +0100124 p->basic.des3 = cpu_to_le32((unsigned int)dma_phy);
Giuseppe CAVALLAROc24602e2013-03-26 04:43:06 +0000125 p++;
126 }
Michael Weiserf8be0d72016-11-14 18:58:05 +0100127 p->basic.des3 = cpu_to_le32((unsigned int)phy_addr);
Giuseppe CAVALLAROc24602e2013-03-26 04:43:06 +0000128
129 } else {
Giuseppe CAVALLAROceb694992013-04-08 02:10:01 +0000130 struct dma_desc *p = (struct dma_desc *)des;
Giuseppe CAVALLAROc24602e2013-03-26 04:43:06 +0000131 for (i = 0; i < (size - 1); i++) {
132 dma_phy += sizeof(struct dma_desc);
Michael Weiserf8be0d72016-11-14 18:58:05 +0100133 p->des3 = cpu_to_le32((unsigned int)dma_phy);
Giuseppe CAVALLAROc24602e2013-03-26 04:43:06 +0000134 p++;
135 }
Michael Weiserf8be0d72016-11-14 18:58:05 +0100136 p->des3 = cpu_to_le32((unsigned int)phy_addr);
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +0000137 }
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +0000138}
139
Rayagond Kokatanur891434b2013-03-26 04:43:10 +0000140static void stmmac_refill_desc3(void *priv_ptr, struct dma_desc *p)
141{
Joao Pinto54139cf2017-04-06 09:49:09 +0100142 struct stmmac_rx_queue *rx_q = (struct stmmac_rx_queue *)priv_ptr;
143 struct stmmac_priv *priv = rx_q->priv_data;
Rayagond Kokatanur891434b2013-03-26 04:43:10 +0000144
145 if (priv->hwts_rx_en && !priv->extend_desc)
146 /* NOTE: Device will overwrite des3 with timestamp value if
147 * 1588-2002 time stamping is enabled, hence reinitialize it
148 * to keep explicit chaining in the descriptor.
149 */
Joao Pinto54139cf2017-04-06 09:49:09 +0100150 p->des3 = cpu_to_le32((unsigned int)(rx_q->dma_rx_phy +
151 (((rx_q->dirty_rx) + 1) %
Michael Weiserf8be0d72016-11-14 18:58:05 +0100152 DMA_RX_SIZE) *
153 sizeof(struct dma_desc)));
Rayagond Kokatanur891434b2013-03-26 04:43:10 +0000154}
155
156static void stmmac_clean_desc3(void *priv_ptr, struct dma_desc *p)
157{
Joao Pintoce736782017-04-06 09:49:10 +0100158 struct stmmac_tx_queue *tx_q = (struct stmmac_tx_queue *)priv_ptr;
159 struct stmmac_priv *priv = tx_q->priv_data;
160 unsigned int entry = tx_q->dirty_tx;
Rayagond Kokatanur891434b2013-03-26 04:43:10 +0000161
Joao Pintoce736782017-04-06 09:49:10 +0100162 if (tx_q->tx_skbuff_dma[entry].last_segment && !priv->extend_desc &&
Giuseppe Cavallaro96951362016-02-29 14:27:33 +0100163 priv->hwts_tx_en)
Rayagond Kokatanur891434b2013-03-26 04:43:10 +0000164 /* NOTE: Device will overwrite des3 with timestamp value if
165 * 1588-2002 time stamping is enabled, hence reinitialize it
166 * to keep explicit chaining in the descriptor.
167 */
Joao Pintoce736782017-04-06 09:49:10 +0100168 p->des3 = cpu_to_le32((unsigned int)((tx_q->dma_tx_phy +
169 ((tx_q->dirty_tx + 1) % DMA_TX_SIZE))
Michael Weiserf8be0d72016-11-14 18:58:05 +0100170 * sizeof(struct dma_desc)));
Rayagond Kokatanur891434b2013-03-26 04:43:10 +0000171}
172
Giuseppe CAVALLARO29896a62014-03-10 13:40:33 +0100173const struct stmmac_mode_ops chain_mode_ops = {
Giuseppe CAVALLAROc24602e2013-03-26 04:43:06 +0000174 .init = stmmac_init_dma_chain,
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +0000175 .is_jumbo_frm = stmmac_is_jumbo_frm,
176 .jumbo_frm = stmmac_jumbo_frm,
Rayagond Kokatanur891434b2013-03-26 04:43:10 +0000177 .refill_desc3 = stmmac_refill_desc3,
178 .clean_desc3 = stmmac_clean_desc3,
Giuseppe CAVALLARO286a8372011-10-18 00:01:24 +0000179};