77914c89d7497de6f9a251196fe079f49364ee13
[sfrench/cifs-2.6.git] / drivers / net / ethernet / stmicro / stmmac / enh_desc.c
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
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
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
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
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
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_ERROR_SUMMARY)) {
205                 if (unlikely(rdes0 & RDES0_DESCRIPTOR_ERROR)) {
206                         x->rx_desc++;
207                         stats->rx_length_errors++;
208                 }
209                 if (unlikely(rdes0 & RDES0_OVERFLOW_ERROR))
210                         x->rx_gmac_overflow++;
211
212                 if (unlikely(rdes0 & RDES0_IPC_CSUM_ERROR))
213                         pr_err("\tIPC Csum Error/Giant frame\n");
214
215                 if (unlikely(rdes0 & RDES0_COLLISION))
216                         stats->collisions++;
217                 if (unlikely(rdes0 & RDES0_RECEIVE_WATCHDOG))
218                         x->rx_watchdog++;
219
220                 if (unlikely(rdes0 & RDES0_MII_ERROR))  /* GMII */
221                         x->rx_mii++;
222
223                 if (unlikely(rdes0 & RDES0_CRC_ERROR)) {
224                         x->rx_crc_errors++;
225                         stats->rx_crc_errors++;
226                 }
227                 ret = discard_frame;
228         }
229
230         /* After a payload csum error, the ES bit is set.
231          * It doesn't match with the information reported into the databook.
232          * At any rate, we need to understand if the CSUM hw computation is ok
233          * and report this info to the upper layers. */
234         ret = enh_desc_coe_rdes0(!!(rdes0 & RDES0_IPC_CSUM_ERROR),
235                                  !!(rdes0 & RDES0_FRAME_TYPE),
236                                  !!(rdes0 & ERDES0_RX_MAC_ADDR));
237
238         if (unlikely(rdes0 & RDES0_DRIBBLING))
239                 x->dribbling_bit++;
240
241         if (unlikely(rdes0 & RDES0_SA_FILTER_FAIL)) {
242                 x->sa_rx_filter_fail++;
243                 ret = discard_frame;
244         }
245         if (unlikely(rdes0 & RDES0_DA_FILTER_FAIL)) {
246                 x->da_rx_filter_fail++;
247                 ret = discard_frame;
248         }
249         if (unlikely(rdes0 & RDES0_LENGTH_ERROR)) {
250                 x->rx_length++;
251                 ret = discard_frame;
252         }
253 #ifdef STMMAC_VLAN_TAG_USED
254         if (rdes0 & RDES0_VLAN_TAG)
255                 x->rx_vlan++;
256 #endif
257
258         return ret;
259 }
260
261 static void enh_desc_init_rx_desc(struct dma_desc *p, int disable_rx_ic,
262                                   int mode, int end)
263 {
264         p->des0 |= cpu_to_le32(RDES0_OWN);
265         p->des1 |= cpu_to_le32((BUF_SIZE_8KiB - 1) & ERDES1_BUFFER1_SIZE_MASK);
266
267         if (mode == STMMAC_CHAIN_MODE)
268                 ehn_desc_rx_set_on_chain(p);
269         else
270                 ehn_desc_rx_set_on_ring(p, end);
271
272         if (disable_rx_ic)
273                 p->des1 |= cpu_to_le32(ERDES1_DISABLE_IC);
274 }
275
276 static void enh_desc_init_tx_desc(struct dma_desc *p, int mode, int end)
277 {
278         p->des0 &= cpu_to_le32(~ETDES0_OWN);
279         if (mode == STMMAC_CHAIN_MODE)
280                 enh_desc_end_tx_desc_on_chain(p);
281         else
282                 enh_desc_end_tx_desc_on_ring(p, end);
283 }
284
285 static int enh_desc_get_tx_owner(struct dma_desc *p)
286 {
287         return (le32_to_cpu(p->des0) & ETDES0_OWN) >> 31;
288 }
289
290 static void enh_desc_set_tx_owner(struct dma_desc *p)
291 {
292         p->des0 |= cpu_to_le32(ETDES0_OWN);
293 }
294
295 static void enh_desc_set_rx_owner(struct dma_desc *p, int disable_rx_ic)
296 {
297         p->des0 |= cpu_to_le32(RDES0_OWN);
298 }
299
300 static int enh_desc_get_tx_ls(struct dma_desc *p)
301 {
302         return (le32_to_cpu(p->des0) & ETDES0_LAST_SEGMENT) >> 29;
303 }
304
305 static void enh_desc_release_tx_desc(struct dma_desc *p, int mode)
306 {
307         int ter = (le32_to_cpu(p->des0) & ETDES0_END_RING) >> 21;
308
309         memset(p, 0, offsetof(struct dma_desc, des2));
310         if (mode == STMMAC_CHAIN_MODE)
311                 enh_desc_end_tx_desc_on_chain(p);
312         else
313                 enh_desc_end_tx_desc_on_ring(p, ter);
314 }
315
316 static void enh_desc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
317                                      bool csum_flag, int mode, bool tx_own,
318                                      bool ls, unsigned int tot_pkt_len)
319 {
320         unsigned int tdes0 = le32_to_cpu(p->des0);
321
322         if (mode == STMMAC_CHAIN_MODE)
323                 enh_set_tx_desc_len_on_chain(p, len);
324         else
325                 enh_set_tx_desc_len_on_ring(p, len);
326
327         if (is_fs)
328                 tdes0 |= ETDES0_FIRST_SEGMENT;
329         else
330                 tdes0 &= ~ETDES0_FIRST_SEGMENT;
331
332         if (likely(csum_flag))
333                 tdes0 |= (TX_CIC_FULL << ETDES0_CHECKSUM_INSERTION_SHIFT);
334         else
335                 tdes0 &= ~(TX_CIC_FULL << ETDES0_CHECKSUM_INSERTION_SHIFT);
336
337         if (ls)
338                 tdes0 |= ETDES0_LAST_SEGMENT;
339
340         /* Finally set the OWN bit. Later the DMA will start! */
341         if (tx_own)
342                 tdes0 |= ETDES0_OWN;
343
344         if (is_fs && tx_own)
345                 /* When the own bit, for the first frame, has to be set, all
346                  * descriptors for the same frame has to be set before, to
347                  * avoid race condition.
348                  */
349                 dma_wmb();
350
351         p->des0 = cpu_to_le32(tdes0);
352 }
353
354 static void enh_desc_set_tx_ic(struct dma_desc *p)
355 {
356         p->des0 |= cpu_to_le32(ETDES0_INTERRUPT);
357 }
358
359 static int enh_desc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type)
360 {
361         unsigned int csum = 0;
362         /* The type-1 checksum offload engines append the checksum at
363          * the end of frame and the two bytes of checksum are added in
364          * the length.
365          * Adjust for that in the framelen for type-1 checksum offload
366          * engines.
367          */
368         if (rx_coe_type == STMMAC_RX_COE_TYPE1)
369                 csum = 2;
370
371         return (((le32_to_cpu(p->des0) & RDES0_FRAME_LEN_MASK)
372                                 >> RDES0_FRAME_LEN_SHIFT) - csum);
373 }
374
375 static void enh_desc_enable_tx_timestamp(struct dma_desc *p)
376 {
377         p->des0 |= cpu_to_le32(ETDES0_TIME_STAMP_ENABLE);
378 }
379
380 static int enh_desc_get_tx_timestamp_status(struct dma_desc *p)
381 {
382         return (le32_to_cpu(p->des0) & ETDES0_TIME_STAMP_STATUS) >> 17;
383 }
384
385 static void enh_desc_get_timestamp(void *desc, u32 ats, u64 *ts)
386 {
387         u64 ns;
388
389         if (ats) {
390                 struct dma_extended_desc *p = (struct dma_extended_desc *)desc;
391                 ns = le32_to_cpu(p->des6);
392                 /* convert high/sec time stamp value to nanosecond */
393                 ns += le32_to_cpu(p->des7) * 1000000000ULL;
394         } else {
395                 struct dma_desc *p = (struct dma_desc *)desc;
396                 ns = le32_to_cpu(p->des2);
397                 ns += le32_to_cpu(p->des3) * 1000000000ULL;
398         }
399
400         *ts = ns;
401 }
402
403 static int enh_desc_get_rx_timestamp_status(void *desc, void *next_desc,
404                                             u32 ats)
405 {
406         if (ats) {
407                 struct dma_extended_desc *p = (struct dma_extended_desc *)desc;
408                 return (le32_to_cpu(p->basic.des0) & RDES0_IPC_CSUM_ERROR) >> 7;
409         } else {
410                 struct dma_desc *p = (struct dma_desc *)desc;
411                 if ((le32_to_cpu(p->des2) == 0xffffffff) &&
412                     (le32_to_cpu(p->des3) == 0xffffffff))
413                         /* timestamp is corrupted, hence don't store it */
414                         return 0;
415                 else
416                         return 1;
417         }
418 }
419
420 static void enh_desc_display_ring(void *head, unsigned int size, bool rx)
421 {
422         struct dma_extended_desc *ep = (struct dma_extended_desc *)head;
423         int i;
424
425         pr_info("Extended %s descriptor ring:\n", rx ? "RX" : "TX");
426
427         for (i = 0; i < size; i++) {
428                 u64 x;
429
430                 x = *(u64 *)ep;
431                 pr_info("%03d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
432                         i, (unsigned int)virt_to_phys(ep),
433                         (unsigned int)x, (unsigned int)(x >> 32),
434                         ep->basic.des2, ep->basic.des3);
435                 ep++;
436         }
437         pr_info("\n");
438 }
439
440 static void enh_desc_get_addr(struct dma_desc *p, unsigned int *addr)
441 {
442         *addr = le32_to_cpu(p->des2);
443 }
444
445 static void enh_desc_set_addr(struct dma_desc *p, dma_addr_t addr)
446 {
447         p->des2 = cpu_to_le32(addr);
448 }
449
450 static void enh_desc_clear(struct dma_desc *p)
451 {
452         p->des2 = 0;
453 }
454
455 const struct stmmac_desc_ops enh_desc_ops = {
456         .tx_status = enh_desc_get_tx_status,
457         .rx_status = enh_desc_get_rx_status,
458         .get_tx_len = enh_desc_get_tx_len,
459         .init_rx_desc = enh_desc_init_rx_desc,
460         .init_tx_desc = enh_desc_init_tx_desc,
461         .get_tx_owner = enh_desc_get_tx_owner,
462         .release_tx_desc = enh_desc_release_tx_desc,
463         .prepare_tx_desc = enh_desc_prepare_tx_desc,
464         .set_tx_ic = enh_desc_set_tx_ic,
465         .get_tx_ls = enh_desc_get_tx_ls,
466         .set_tx_owner = enh_desc_set_tx_owner,
467         .set_rx_owner = enh_desc_set_rx_owner,
468         .get_rx_frame_len = enh_desc_get_rx_frame_len,
469         .rx_extended_status = enh_desc_get_ext_status,
470         .enable_tx_timestamp = enh_desc_enable_tx_timestamp,
471         .get_tx_timestamp_status = enh_desc_get_tx_timestamp_status,
472         .get_timestamp = enh_desc_get_timestamp,
473         .get_rx_timestamp_status = enh_desc_get_rx_timestamp_status,
474         .display_ring = enh_desc_display_ring,
475         .get_addr = enh_desc_get_addr,
476         .set_addr = enh_desc_set_addr,
477         .clear = enh_desc_clear,
478 };