GNU Linux-libre 4.9.308-gnu1
[releases.git] / drivers / net / ethernet / stmicro / stmmac / norm_desc.c
1 /*******************************************************************************
2   This contains the functions to handle the normal descriptors.
3
4   Copyright (C) 2007-2009  STMicroelectronics Ltd
5
6   This program is free software; you can redistribute it and/or modify it
7   under the terms and conditions of the GNU General Public License,
8   version 2, as published by the Free Software Foundation.
9
10   This program is distributed in the hope it will be useful, but WITHOUT
11   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13   more details.
14
15   You should have received a copy of the GNU General Public License along with
16   this program; if not, write to the Free Software Foundation, Inc.,
17   51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18
19   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 <linux/stmmac.h>
26 #include "common.h"
27 #include "descs_com.h"
28
29 static int ndesc_get_tx_status(void *data, struct stmmac_extra_stats *x,
30                                struct dma_desc *p, void __iomem *ioaddr)
31 {
32         struct net_device_stats *stats = (struct net_device_stats *)data;
33         unsigned int tdes0 = le32_to_cpu(p->des0);
34         unsigned int tdes1 = le32_to_cpu(p->des1);
35         int ret = tx_done;
36
37         /* Get tx owner first */
38         if (unlikely(tdes0 & TDES0_OWN))
39                 return tx_dma_own;
40
41         /* Verify tx error by looking at the last segment. */
42         if (likely(!(tdes1 & TDES1_LAST_SEGMENT)))
43                 return tx_not_ls;
44
45         if (unlikely(tdes0 & TDES0_ERROR_SUMMARY)) {
46                 if (unlikely(tdes0 & TDES0_UNDERFLOW_ERROR)) {
47                         x->tx_underflow++;
48                         stats->tx_fifo_errors++;
49                 }
50                 if (unlikely(tdes0 & TDES0_NO_CARRIER)) {
51                         x->tx_carrier++;
52                         stats->tx_carrier_errors++;
53                 }
54                 if (unlikely(tdes0 & TDES0_LOSS_CARRIER)) {
55                         x->tx_losscarrier++;
56                         stats->tx_carrier_errors++;
57                 }
58                 if (unlikely((tdes0 & TDES0_EXCESSIVE_DEFERRAL) ||
59                              (tdes0 & TDES0_EXCESSIVE_COLLISIONS) ||
60                              (tdes0 & TDES0_LATE_COLLISION))) {
61                         unsigned int collisions;
62
63                         collisions = (tdes0 & TDES0_COLLISION_COUNT_MASK) >> 3;
64                         stats->collisions += collisions;
65                 }
66                 ret = tx_err;
67         }
68
69         if (tdes0 & TDES0_VLAN_FRAME)
70                 x->tx_vlan++;
71
72         if (unlikely(tdes0 & TDES0_DEFERRED))
73                 x->tx_deferred++;
74
75         return ret;
76 }
77
78 static int ndesc_get_tx_len(struct dma_desc *p)
79 {
80         return (le32_to_cpu(p->des1) & RDES1_BUFFER1_SIZE_MASK);
81 }
82
83 /* This function verifies if each incoming frame has some errors
84  * and, if required, updates the multicast statistics.
85  * In case of success, it returns good_frame because the GMAC device
86  * is supposed to be able to compute the csum in HW. */
87 static int ndesc_get_rx_status(void *data, struct stmmac_extra_stats *x,
88                                struct dma_desc *p)
89 {
90         int ret = good_frame;
91         unsigned int rdes0 = le32_to_cpu(p->des0);
92         struct net_device_stats *stats = (struct net_device_stats *)data;
93
94         if (unlikely(rdes0 & RDES0_OWN))
95                 return dma_own;
96
97         if (unlikely(!(rdes0 & RDES0_LAST_DESCRIPTOR))) {
98                 stats->rx_length_errors++;
99                 return discard_frame;
100         }
101
102         if (unlikely(rdes0 & RDES0_ERROR_SUMMARY)) {
103                 if (unlikely(rdes0 & RDES0_DESCRIPTOR_ERROR))
104                         x->rx_desc++;
105                 if (unlikely(rdes0 & RDES0_SA_FILTER_FAIL))
106                         x->sa_filter_fail++;
107                 if (unlikely(rdes0 & RDES0_OVERFLOW_ERROR))
108                         x->overflow_error++;
109                 if (unlikely(rdes0 & RDES0_IPC_CSUM_ERROR))
110                         x->ipc_csum_error++;
111                 if (unlikely(rdes0 & RDES0_COLLISION)) {
112                         x->rx_collision++;
113                         stats->collisions++;
114                 }
115                 if (unlikely(rdes0 & RDES0_CRC_ERROR)) {
116                         x->rx_crc++;
117                         stats->rx_crc_errors++;
118                 }
119                 ret = discard_frame;
120         }
121         if (unlikely(rdes0 & RDES0_DRIBBLING))
122                 x->dribbling_bit++;
123
124         if (unlikely(rdes0 & RDES0_LENGTH_ERROR)) {
125                 x->rx_length++;
126                 ret = discard_frame;
127         }
128         if (unlikely(rdes0 & RDES0_MII_ERROR)) {
129                 x->rx_mii++;
130                 ret = discard_frame;
131         }
132 #ifdef STMMAC_VLAN_TAG_USED
133         if (rdes0 & RDES0_VLAN_TAG)
134                 x->vlan_tag++;
135 #endif
136         return ret;
137 }
138
139 static void ndesc_init_rx_desc(struct dma_desc *p, int disable_rx_ic, int mode,
140                                int end, int bfsize)
141 {
142         int bfsize1;
143
144         p->des0 |= cpu_to_le32(RDES0_OWN);
145
146         bfsize1 = min(bfsize, BUF_SIZE_2KiB - 1);
147         p->des1 |= cpu_to_le32(bfsize1 & RDES1_BUFFER1_SIZE_MASK);
148
149         if (mode == STMMAC_CHAIN_MODE)
150                 ndesc_rx_set_on_chain(p, end);
151         else
152                 ndesc_rx_set_on_ring(p, end, bfsize);
153
154         if (disable_rx_ic)
155                 p->des1 |= cpu_to_le32(RDES1_DISABLE_IC);
156 }
157
158 static void ndesc_init_tx_desc(struct dma_desc *p, int mode, int end)
159 {
160         p->des0 &= cpu_to_le32(~TDES0_OWN);
161         if (mode == STMMAC_CHAIN_MODE)
162                 ndesc_tx_set_on_chain(p);
163         else
164                 ndesc_end_tx_desc_on_ring(p, end);
165 }
166
167 static int ndesc_get_tx_owner(struct dma_desc *p)
168 {
169         return (le32_to_cpu(p->des0) & TDES0_OWN) >> 31;
170 }
171
172 static void ndesc_set_tx_owner(struct dma_desc *p)
173 {
174         p->des0 |= cpu_to_le32(TDES0_OWN);
175 }
176
177 static void ndesc_set_rx_owner(struct dma_desc *p)
178 {
179         p->des0 |= cpu_to_le32(RDES0_OWN);
180 }
181
182 static int ndesc_get_tx_ls(struct dma_desc *p)
183 {
184         return (le32_to_cpu(p->des1) & TDES1_LAST_SEGMENT) >> 30;
185 }
186
187 static void ndesc_release_tx_desc(struct dma_desc *p, int mode)
188 {
189         int ter = (le32_to_cpu(p->des1) & TDES1_END_RING) >> 25;
190
191         memset(p, 0, offsetof(struct dma_desc, des2));
192         if (mode == STMMAC_CHAIN_MODE)
193                 ndesc_tx_set_on_chain(p);
194         else
195                 ndesc_end_tx_desc_on_ring(p, ter);
196 }
197
198 static void ndesc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
199                                   bool csum_flag, int mode, bool tx_own,
200                                   bool ls)
201 {
202         unsigned int tdes1 = le32_to_cpu(p->des1);
203
204         if (is_fs)
205                 tdes1 |= TDES1_FIRST_SEGMENT;
206         else
207                 tdes1 &= ~TDES1_FIRST_SEGMENT;
208
209         if (likely(csum_flag))
210                 tdes1 |= (TX_CIC_FULL) << TDES1_CHECKSUM_INSERTION_SHIFT;
211         else
212                 tdes1 &= ~(TX_CIC_FULL << TDES1_CHECKSUM_INSERTION_SHIFT);
213
214         if (ls)
215                 tdes1 |= TDES1_LAST_SEGMENT;
216
217         p->des1 = cpu_to_le32(tdes1);
218
219         if (mode == STMMAC_CHAIN_MODE)
220                 norm_set_tx_desc_len_on_chain(p, len);
221         else
222                 norm_set_tx_desc_len_on_ring(p, len);
223
224         if (tx_own)
225                 p->des0 |= cpu_to_le32(TDES0_OWN);
226 }
227
228 static void ndesc_set_tx_ic(struct dma_desc *p)
229 {
230         p->des1 |= cpu_to_le32(TDES1_INTERRUPT);
231 }
232
233 static int ndesc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type)
234 {
235         unsigned int csum = 0;
236
237         /* The type-1 checksum offload engines append the checksum at
238          * the end of frame and the two bytes of checksum are added in
239          * the length.
240          * Adjust for that in the framelen for type-1 checksum offload
241          * engines
242          */
243         if (rx_coe_type == STMMAC_RX_COE_TYPE1)
244                 csum = 2;
245
246         return (((le32_to_cpu(p->des0) & RDES0_FRAME_LEN_MASK)
247                                 >> RDES0_FRAME_LEN_SHIFT) -
248                 csum);
249
250 }
251
252 static void ndesc_enable_tx_timestamp(struct dma_desc *p)
253 {
254         p->des1 |= cpu_to_le32(TDES1_TIME_STAMP_ENABLE);
255 }
256
257 static int ndesc_get_tx_timestamp_status(struct dma_desc *p)
258 {
259         return (le32_to_cpu(p->des0) & TDES0_TIME_STAMP_STATUS) >> 17;
260 }
261
262 static u64 ndesc_get_timestamp(void *desc, u32 ats)
263 {
264         struct dma_desc *p = (struct dma_desc *)desc;
265         u64 ns;
266
267         ns = le32_to_cpu(p->des2);
268         /* convert high/sec time stamp value to nanosecond */
269         ns += le32_to_cpu(p->des3) * 1000000000ULL;
270
271         return ns;
272 }
273
274 static int ndesc_get_rx_timestamp_status(void *desc, u32 ats)
275 {
276         struct dma_desc *p = (struct dma_desc *)desc;
277
278         if ((le32_to_cpu(p->des2) == 0xffffffff) &&
279             (le32_to_cpu(p->des3) == 0xffffffff))
280                 /* timestamp is corrupted, hence don't store it */
281                 return 0;
282         else
283                 return 1;
284 }
285
286 static void ndesc_display_ring(void *head, unsigned int size, bool rx)
287 {
288         struct dma_desc *p = (struct dma_desc *)head;
289         int i;
290
291         pr_info("%s descriptor ring:\n", rx ? "RX" : "TX");
292
293         for (i = 0; i < size; i++) {
294                 u64 x;
295
296                 x = *(u64 *)p;
297                 pr_info("%d [0x%x]: 0x%x 0x%x 0x%x 0x%x",
298                         i, (unsigned int)virt_to_phys(p),
299                         (unsigned int)x, (unsigned int)(x >> 32),
300                         p->des2, p->des3);
301                 p++;
302         }
303         pr_info("\n");
304 }
305
306 const struct stmmac_desc_ops ndesc_ops = {
307         .tx_status = ndesc_get_tx_status,
308         .rx_status = ndesc_get_rx_status,
309         .get_tx_len = ndesc_get_tx_len,
310         .init_rx_desc = ndesc_init_rx_desc,
311         .init_tx_desc = ndesc_init_tx_desc,
312         .get_tx_owner = ndesc_get_tx_owner,
313         .release_tx_desc = ndesc_release_tx_desc,
314         .prepare_tx_desc = ndesc_prepare_tx_desc,
315         .set_tx_ic = ndesc_set_tx_ic,
316         .get_tx_ls = ndesc_get_tx_ls,
317         .set_tx_owner = ndesc_set_tx_owner,
318         .set_rx_owner = ndesc_set_rx_owner,
319         .get_rx_frame_len = ndesc_get_rx_frame_len,
320         .enable_tx_timestamp = ndesc_enable_tx_timestamp,
321         .get_tx_timestamp_status = ndesc_get_tx_timestamp_status,
322         .get_timestamp = ndesc_get_timestamp,
323         .get_rx_timestamp_status = ndesc_get_rx_timestamp_status,
324         .display_ring = ndesc_display_ring,
325 };