1 /*******************************************************************************
2 This contains the functions to handle the enhanced descriptors.
3
4 Copyright (C) 2007-2014 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 The full GNU General Public License is included in this distribution in
16 the file called "COPYING".
17
18 Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
19 *******************************************************************************/
20
21 #include <linux/stmmac.h>
22 #include "common.h"
23 #include "descs_com.h"
24
enh_desc_get_tx_status(void * data,struct stmmac_extra_stats * x,struct dma_desc * p,void __iomem * ioaddr)25 static int enh_desc_get_tx_status(void *data, struct stmmac_extra_stats *x,
26 struct dma_desc *p, void __iomem *ioaddr)
27 {
28 struct net_device_stats *stats = (struct net_device_stats *)data;
29 unsigned int tdes0 = le32_to_cpu(p->des0);
30 int ret = tx_done;
31
32 /* Get tx owner first */
33 if (unlikely(tdes0 & ETDES0_OWN))
34 return tx_dma_own;
35
36 /* Verify tx error by looking at the last segment. */
37 if (likely(!(tdes0 & ETDES0_LAST_SEGMENT)))
38 return tx_not_ls;
39
40 if (unlikely(tdes0 & ETDES0_ERROR_SUMMARY)) {
41 if (unlikely(tdes0 & ETDES0_JABBER_TIMEOUT))
42 x->tx_jabber++;
43
44 if (unlikely(tdes0 & ETDES0_FRAME_FLUSHED)) {
45 x->tx_frame_flushed++;
46 dwmac_dma_flush_tx_fifo(ioaddr);
47 }
48
49 if (unlikely(tdes0 & ETDES0_LOSS_CARRIER)) {
50 x->tx_losscarrier++;
51 stats->tx_carrier_errors++;
52 }
53 if (unlikely(tdes0 & ETDES0_NO_CARRIER)) {
54 x->tx_carrier++;
55 stats->tx_carrier_errors++;
56 }
57 if (unlikely((tdes0 & ETDES0_LATE_COLLISION) ||
58 (tdes0 & ETDES0_EXCESSIVE_COLLISIONS)))
59 stats->collisions +=
60 (tdes0 & ETDES0_COLLISION_COUNT_MASK) >> 3;
61
62 if (unlikely(tdes0 & ETDES0_EXCESSIVE_DEFERRAL))
63 x->tx_deferred++;
64
65 if (unlikely(tdes0 & ETDES0_UNDERFLOW_ERROR)) {
66 dwmac_dma_flush_tx_fifo(ioaddr);
67 x->tx_underflow++;
68 }
69
70 if (unlikely(tdes0 & ETDES0_IP_HEADER_ERROR))
71 x->tx_ip_header_error++;
72
73 if (unlikely(tdes0 & ETDES0_PAYLOAD_ERROR)) {
74 x->tx_payload_error++;
75 dwmac_dma_flush_tx_fifo(ioaddr);
76 }
77
78 ret = tx_err;
79 }
80
81 if (unlikely(tdes0 & ETDES0_DEFERRED))
82 x->tx_deferred++;
83
84 #ifdef STMMAC_VLAN_TAG_USED
85 if (tdes0 & ETDES0_VLAN_FRAME)
86 x->tx_vlan++;
87 #endif
88
89 return ret;
90 }
91
enh_desc_get_tx_len(struct dma_desc * p)92 static int enh_desc_get_tx_len(struct dma_desc *p)
93 {
94 return (le32_to_cpu(p->des1) & ETDES1_BUFFER1_SIZE_MASK);
95 }
96
enh_desc_coe_rdes0(int ipc_err,int type,int payload_err)97 static int enh_desc_coe_rdes0(int ipc_err, int type, int payload_err)
98 {
99 int ret = good_frame;
100 u32 status = (type << 2 | ipc_err << 1 | payload_err) & 0x7;
101
102 /* bits 5 7 0 | Frame status
103 * ----------------------------------------------------------
104 * 0 0 0 | IEEE 802.3 Type frame (length < 1536 octects)
105 * 1 0 0 | IPv4/6 No CSUM errorS.
106 * 1 0 1 | IPv4/6 CSUM PAYLOAD error
107 * 1 1 0 | IPv4/6 CSUM IP HR error
108 * 1 1 1 | IPv4/6 IP PAYLOAD AND HEADER errorS
109 * 0 0 1 | IPv4/6 unsupported IP PAYLOAD
110 * 0 1 1 | COE bypassed.. no IPv4/6 frame
111 * 0 1 0 | Reserved.
112 */
113 if (status == 0x0)
114 ret = llc_snap;
115 else if (status == 0x4)
116 ret = good_frame;
117 else if (status == 0x5)
118 ret = csum_none;
119 else if (status == 0x6)
120 ret = csum_none;
121 else if (status == 0x7)
122 ret = csum_none;
123 else if (status == 0x1)
124 ret = discard_frame;
125 else if (status == 0x3)
126 ret = discard_frame;
127 return ret;
128 }
129
enh_desc_get_ext_status(void * data,struct stmmac_extra_stats * x,struct dma_extended_desc * p)130 static void enh_desc_get_ext_status(void *data, struct stmmac_extra_stats *x,
131 struct dma_extended_desc *p)
132 {
133 unsigned int rdes0 = le32_to_cpu(p->basic.des0);
134 unsigned int rdes4 = le32_to_cpu(p->des4);
135
136 if (unlikely(rdes0 & ERDES0_RX_MAC_ADDR)) {
137 int message_type = (rdes4 & ERDES4_MSG_TYPE_MASK) >> 8;
138
139 if (rdes4 & ERDES4_IP_HDR_ERR)
140 x->ip_hdr_err++;
141 if (rdes4 & ERDES4_IP_PAYLOAD_ERR)
142 x->ip_payload_err++;
143 if (rdes4 & ERDES4_IP_CSUM_BYPASSED)
144 x->ip_csum_bypassed++;
145 if (rdes4 & ERDES4_IPV4_PKT_RCVD)
146 x->ipv4_pkt_rcvd++;
147 if (rdes4 & ERDES4_IPV6_PKT_RCVD)
148 x->ipv6_pkt_rcvd++;
149
150 if (message_type == RDES_EXT_NO_PTP)
151 x->no_ptp_rx_msg_type_ext++;
152 else if (message_type == RDES_EXT_SYNC)
153 x->ptp_rx_msg_type_sync++;
154 else if (message_type == RDES_EXT_FOLLOW_UP)
155 x->ptp_rx_msg_type_follow_up++;
156 else if (message_type == RDES_EXT_DELAY_REQ)
157 x->ptp_rx_msg_type_delay_req++;
158 else if (message_type == RDES_EXT_DELAY_RESP)
159 x->ptp_rx_msg_type_delay_resp++;
160 else if (message_type == RDES_EXT_PDELAY_REQ)
161 x->ptp_rx_msg_type_pdelay_req++;
162 else if (message_type == RDES_EXT_PDELAY_RESP)
163 x->ptp_rx_msg_type_pdelay_resp++;
164 else if (message_type == RDES_EXT_PDELAY_FOLLOW_UP)
165 x->ptp_rx_msg_type_pdelay_follow_up++;
166 else if (message_type == RDES_PTP_ANNOUNCE)
167 x->ptp_rx_msg_type_announce++;
168 else if (message_type == RDES_PTP_MANAGEMENT)
169 x->ptp_rx_msg_type_management++;
170 else if (message_type == RDES_PTP_PKT_RESERVED_TYPE)
171 x->ptp_rx_msg_pkt_reserved_type++;
172
173 if (rdes4 & ERDES4_PTP_FRAME_TYPE)
174 x->ptp_frame_type++;
175 if (rdes4 & ERDES4_PTP_VER)
176 x->ptp_ver++;
177 if (rdes4 & ERDES4_TIMESTAMP_DROPPED)
178 x->timestamp_dropped++;
179 if (rdes4 & ERDES4_AV_PKT_RCVD)
180 x->av_pkt_rcvd++;
181 if (rdes4 & ERDES4_AV_TAGGED_PKT_RCVD)
182 x->av_tagged_pkt_rcvd++;
183 if ((rdes4 & ERDES4_VLAN_TAG_PRI_VAL_MASK) >> 18)
184 x->vlan_tag_priority_val++;
185 if (rdes4 & ERDES4_L3_FILTER_MATCH)
186 x->l3_filter_match++;
187 if (rdes4 & ERDES4_L4_FILTER_MATCH)
188 x->l4_filter_match++;
189 if ((rdes4 & ERDES4_L3_L4_FILT_NO_MATCH_MASK) >> 26)
190 x->l3_l4_filter_no_match++;
191 }
192 }
193
enh_desc_get_rx_status(void * data,struct stmmac_extra_stats * x,struct dma_desc * p)194 static int enh_desc_get_rx_status(void *data, struct stmmac_extra_stats *x,
195 struct dma_desc *p)
196 {
197 struct net_device_stats *stats = (struct net_device_stats *)data;
198 unsigned int rdes0 = le32_to_cpu(p->des0);
199 int ret = good_frame;
200
201 if (unlikely(rdes0 & RDES0_OWN))
202 return dma_own;
203
204 if (unlikely(!(rdes0 & RDES0_LAST_DESCRIPTOR))) {
205 stats->rx_length_errors++;
206 return discard_frame;
207 }
208
209 if (unlikely(rdes0 & RDES0_ERROR_SUMMARY)) {
210 if (unlikely(rdes0 & RDES0_DESCRIPTOR_ERROR)) {
211 x->rx_desc++;
212 stats->rx_length_errors++;
213 }
214 if (unlikely(rdes0 & RDES0_OVERFLOW_ERROR))
215 x->rx_gmac_overflow++;
216
217 if (unlikely(rdes0 & RDES0_IPC_CSUM_ERROR))
218 pr_err("\tIPC Csum Error/Giant frame\n");
219
220 if (unlikely(rdes0 & RDES0_COLLISION))
221 stats->collisions++;
222 if (unlikely(rdes0 & RDES0_RECEIVE_WATCHDOG))
223 x->rx_watchdog++;
224
225 if (unlikely(rdes0 & RDES0_MII_ERROR)) /* GMII */
226 x->rx_mii++;
227
228 if (unlikely(rdes0 & RDES0_CRC_ERROR)) {
229 x->rx_crc_errors++;
230 stats->rx_crc_errors++;
231 }
232 ret = discard_frame;
233 }
234
235 /* After a payload csum error, the ES bit is set.
236 * It doesn't match with the information reported into the databook.
237 * At any rate, we need to understand if the CSUM hw computation is ok
238 * and report this info to the upper layers. */
239 if (likely(ret == good_frame))
240 ret = enh_desc_coe_rdes0(!!(rdes0 & RDES0_IPC_CSUM_ERROR),
241 !!(rdes0 & RDES0_FRAME_TYPE),
242 !!(rdes0 & ERDES0_RX_MAC_ADDR));
243
244 if (unlikely(rdes0 & RDES0_DRIBBLING))
245 x->dribbling_bit++;
246
247 if (unlikely(rdes0 & RDES0_SA_FILTER_FAIL)) {
248 x->sa_rx_filter_fail++;
249 ret = discard_frame;
250 }
251 if (unlikely(rdes0 & RDES0_DA_FILTER_FAIL)) {
252 x->da_rx_filter_fail++;
253 ret = discard_frame;
254 }
255 if (unlikely(rdes0 & RDES0_LENGTH_ERROR)) {
256 x->rx_length++;
257 ret = discard_frame;
258 }
259 #ifdef STMMAC_VLAN_TAG_USED
260 if (rdes0 & RDES0_VLAN_TAG)
261 x->rx_vlan++;
262 #endif
263
264 return ret;
265 }
266
enh_desc_init_rx_desc(struct dma_desc * p,int disable_rx_ic,int mode,int end,int bfsize)267 static void enh_desc_init_rx_desc(struct dma_desc *p, int disable_rx_ic,
268 int mode, int end, int bfsize)
269 {
270 int bfsize1;
271
272 p->des0 |= cpu_to_le32(RDES0_OWN);
273
274 bfsize1 = min(bfsize, BUF_SIZE_8KiB);
275 p->des1 |= cpu_to_le32(bfsize1 & ERDES1_BUFFER1_SIZE_MASK);
276
277 if (mode == STMMAC_CHAIN_MODE)
278 ehn_desc_rx_set_on_chain(p);
279 else
280 ehn_desc_rx_set_on_ring(p, end, bfsize);
281
282 if (disable_rx_ic)
283 p->des1 |= cpu_to_le32(ERDES1_DISABLE_IC);
284 }
285
enh_desc_init_tx_desc(struct dma_desc * p,int mode,int end)286 static void enh_desc_init_tx_desc(struct dma_desc *p, int mode, int end)
287 {
288 p->des0 &= cpu_to_le32(~ETDES0_OWN);
289 if (mode == STMMAC_CHAIN_MODE)
290 enh_desc_end_tx_desc_on_chain(p);
291 else
292 enh_desc_end_tx_desc_on_ring(p, end);
293 }
294
enh_desc_get_tx_owner(struct dma_desc * p)295 static int enh_desc_get_tx_owner(struct dma_desc *p)
296 {
297 return (le32_to_cpu(p->des0) & ETDES0_OWN) >> 31;
298 }
299
enh_desc_set_tx_owner(struct dma_desc * p)300 static void enh_desc_set_tx_owner(struct dma_desc *p)
301 {
302 p->des0 |= cpu_to_le32(ETDES0_OWN);
303 }
304
enh_desc_set_rx_owner(struct dma_desc * p,int disable_rx_ic)305 static void enh_desc_set_rx_owner(struct dma_desc *p, int disable_rx_ic)
306 {
307 p->des0 |= cpu_to_le32(RDES0_OWN);
308 }
309
enh_desc_get_tx_ls(struct dma_desc * p)310 static int enh_desc_get_tx_ls(struct dma_desc *p)
311 {
312 return (le32_to_cpu(p->des0) & ETDES0_LAST_SEGMENT) >> 29;
313 }
314
enh_desc_release_tx_desc(struct dma_desc * p,int mode)315 static void enh_desc_release_tx_desc(struct dma_desc *p, int mode)
316 {
317 int ter = (le32_to_cpu(p->des0) & ETDES0_END_RING) >> 21;
318
319 memset(p, 0, offsetof(struct dma_desc, des2));
320 if (mode == STMMAC_CHAIN_MODE)
321 enh_desc_end_tx_desc_on_chain(p);
322 else
323 enh_desc_end_tx_desc_on_ring(p, ter);
324 }
325
enh_desc_prepare_tx_desc(struct dma_desc * p,int is_fs,int len,bool csum_flag,int mode,bool tx_own,bool ls,unsigned int tot_pkt_len)326 static void enh_desc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
327 bool csum_flag, int mode, bool tx_own,
328 bool ls, unsigned int tot_pkt_len)
329 {
330 unsigned int tdes0 = le32_to_cpu(p->des0);
331
332 if (mode == STMMAC_CHAIN_MODE)
333 enh_set_tx_desc_len_on_chain(p, len);
334 else
335 enh_set_tx_desc_len_on_ring(p, len);
336
337 if (is_fs)
338 tdes0 |= ETDES0_FIRST_SEGMENT;
339 else
340 tdes0 &= ~ETDES0_FIRST_SEGMENT;
341
342 if (likely(csum_flag))
343 tdes0 |= (TX_CIC_FULL << ETDES0_CHECKSUM_INSERTION_SHIFT);
344 else
345 tdes0 &= ~(TX_CIC_FULL << ETDES0_CHECKSUM_INSERTION_SHIFT);
346
347 if (ls)
348 tdes0 |= ETDES0_LAST_SEGMENT;
349
350 /* Finally set the OWN bit. Later the DMA will start! */
351 if (tx_own)
352 tdes0 |= ETDES0_OWN;
353
354 if (is_fs && tx_own)
355 /* When the own bit, for the first frame, has to be set, all
356 * descriptors for the same frame has to be set before, to
357 * avoid race condition.
358 */
359 dma_wmb();
360
361 p->des0 = cpu_to_le32(tdes0);
362 }
363
enh_desc_set_tx_ic(struct dma_desc * p)364 static void enh_desc_set_tx_ic(struct dma_desc *p)
365 {
366 p->des0 |= cpu_to_le32(ETDES0_INTERRUPT);
367 }
368
enh_desc_get_rx_frame_len(struct dma_desc * p,int rx_coe_type)369 static int enh_desc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type)
370 {
371 unsigned int csum = 0;
372 /* The type-1 checksum offload engines append the checksum at
373 * the end of frame and the two bytes of checksum are added in
374 * the length.
375 * Adjust for that in the framelen for type-1 checksum offload
376 * engines.
377 */
378 if (rx_coe_type == STMMAC_RX_COE_TYPE1)
379 csum = 2;
380
381 return (((le32_to_cpu(p->des0) & RDES0_FRAME_LEN_MASK)
382 >> RDES0_FRAME_LEN_SHIFT) - csum);
383 }
384
enh_desc_enable_tx_timestamp(struct dma_desc * p)385 static void enh_desc_enable_tx_timestamp(struct dma_desc *p)
386 {
387 p->des0 |= cpu_to_le32(ETDES0_TIME_STAMP_ENABLE);
388 }
389
enh_desc_get_tx_timestamp_status(struct dma_desc * p)390 static int enh_desc_get_tx_timestamp_status(struct dma_desc *p)
391 {
392 return (le32_to_cpu(p->des0) & ETDES0_TIME_STAMP_STATUS) >> 17;
393 }
394
enh_desc_get_timestamp(void * desc,u32 ats,u64 * ts)395 static void enh_desc_get_timestamp(void *desc, u32 ats, u64 *ts)
396 {
397 u64 ns;
398
399 if (ats) {
400 struct dma_extended_desc *p = (struct dma_extended_desc *)desc;
401 ns = le32_to_cpu(p->des6);
402 /* convert high/sec time stamp value to nanosecond */
403 ns += le32_to_cpu(p->des7) * 1000000000ULL;
404 } else {
405 struct dma_desc *p = (struct dma_desc *)desc;
406 ns = le32_to_cpu(p->des2);
407 ns += le32_to_cpu(p->des3) * 1000000000ULL;
408 }
409
410 *ts = ns;
411 }
412
enh_desc_get_rx_timestamp_status(void * desc,void * next_desc,u32 ats)413 static int enh_desc_get_rx_timestamp_status(void *desc, void *next_desc,
414 u32 ats)
415 {
416 if (ats) {
417 struct dma_extended_desc *p = (struct dma_extended_desc *)desc;
418 return (le32_to_cpu(p->basic.des0) & RDES0_IPC_CSUM_ERROR) >> 7;
419 } else {
420 struct dma_desc *p = (struct dma_desc *)desc;
421 if ((le32_to_cpu(p->des2) == 0xffffffff) &&
422 (le32_to_cpu(p->des3) == 0xffffffff))
423 /* timestamp is corrupted, hence don't store it */
424 return 0;
425 else
426 return 1;
427 }
428 }
429
enh_desc_display_ring(void * head,unsigned int size,bool rx)430 static void enh_desc_display_ring(void *head, unsigned int size, bool rx)
431 {
432 struct dma_extended_desc *ep = (struct dma_extended_desc *)head;
433 int i;
434
435 pr_info("Extended %s descriptor ring:\n", rx ? "RX" : "TX");
436
437 for (i = 0; i < size; i++) {
438 u64 x;
439
440 x = *(u64 *)ep;
441 pr_info("%03d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
442 i, (unsigned int)virt_to_phys(ep),
443 (unsigned int)x, (unsigned int)(x >> 32),
444 ep->basic.des2, ep->basic.des3);
445 ep++;
446 }
447 pr_info("\n");
448 }
449
enh_desc_get_addr(struct dma_desc * p,unsigned int * addr)450 static void enh_desc_get_addr(struct dma_desc *p, unsigned int *addr)
451 {
452 *addr = le32_to_cpu(p->des2);
453 }
454
enh_desc_set_addr(struct dma_desc * p,dma_addr_t addr)455 static void enh_desc_set_addr(struct dma_desc *p, dma_addr_t addr)
456 {
457 p->des2 = cpu_to_le32(addr);
458 }
459
enh_desc_clear(struct dma_desc * p)460 static void enh_desc_clear(struct dma_desc *p)
461 {
462 p->des2 = 0;
463 }
464
465 const struct stmmac_desc_ops enh_desc_ops = {
466 .tx_status = enh_desc_get_tx_status,
467 .rx_status = enh_desc_get_rx_status,
468 .get_tx_len = enh_desc_get_tx_len,
469 .init_rx_desc = enh_desc_init_rx_desc,
470 .init_tx_desc = enh_desc_init_tx_desc,
471 .get_tx_owner = enh_desc_get_tx_owner,
472 .release_tx_desc = enh_desc_release_tx_desc,
473 .prepare_tx_desc = enh_desc_prepare_tx_desc,
474 .set_tx_ic = enh_desc_set_tx_ic,
475 .get_tx_ls = enh_desc_get_tx_ls,
476 .set_tx_owner = enh_desc_set_tx_owner,
477 .set_rx_owner = enh_desc_set_rx_owner,
478 .get_rx_frame_len = enh_desc_get_rx_frame_len,
479 .rx_extended_status = enh_desc_get_ext_status,
480 .enable_tx_timestamp = enh_desc_enable_tx_timestamp,
481 .get_tx_timestamp_status = enh_desc_get_tx_timestamp_status,
482 .get_timestamp = enh_desc_get_timestamp,
483 .get_rx_timestamp_status = enh_desc_get_rx_timestamp_status,
484 .display_ring = enh_desc_display_ring,
485 .get_addr = enh_desc_get_addr,
486 .set_addr = enh_desc_set_addr,
487 .clear = enh_desc_clear,
488 };
489