1 /*******************************************************************************
2 This contains the functions to handle the enhanced descriptors.
4 Copyright (C) 2007-2009 STMicroelectronics Ltd
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.
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
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.
19 The full GNU General Public License is included in this distribution in
20 the file called "COPYING".
22 Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
23 *******************************************************************************/
27 static int enh_desc_get_tx_status(void *data
, struct stmmac_extra_stats
*x
,
28 struct dma_desc
*p
, void __iomem
*ioaddr
)
31 struct net_device_stats
*stats
= (struct net_device_stats
*)data
;
33 if (unlikely(p
->des01
.etx
.error_summary
)) {
34 CHIP_DBG(KERN_ERR
"GMAC TX error... 0x%08x\n", p
->des01
.etx
);
35 if (unlikely(p
->des01
.etx
.jabber_timeout
)) {
36 CHIP_DBG(KERN_ERR
"\tjabber_timeout error\n");
40 if (unlikely(p
->des01
.etx
.frame_flushed
)) {
41 CHIP_DBG(KERN_ERR
"\tframe_flushed error\n");
42 x
->tx_frame_flushed
++;
43 dwmac_dma_flush_tx_fifo(ioaddr
);
46 if (unlikely(p
->des01
.etx
.loss_carrier
)) {
47 CHIP_DBG(KERN_ERR
"\tloss_carrier error\n");
49 stats
->tx_carrier_errors
++;
51 if (unlikely(p
->des01
.etx
.no_carrier
)) {
52 CHIP_DBG(KERN_ERR
"\tno_carrier error\n");
54 stats
->tx_carrier_errors
++;
56 if (unlikely(p
->des01
.etx
.late_collision
)) {
57 CHIP_DBG(KERN_ERR
"\tlate_collision error\n");
58 stats
->collisions
+= p
->des01
.etx
.collision_count
;
60 if (unlikely(p
->des01
.etx
.excessive_collisions
)) {
61 CHIP_DBG(KERN_ERR
"\texcessive_collisions\n");
62 stats
->collisions
+= p
->des01
.etx
.collision_count
;
64 if (unlikely(p
->des01
.etx
.excessive_deferral
)) {
65 CHIP_DBG(KERN_INFO
"\texcessive tx_deferral\n");
69 if (unlikely(p
->des01
.etx
.underflow_error
)) {
70 CHIP_DBG(KERN_ERR
"\tunderflow error\n");
71 dwmac_dma_flush_tx_fifo(ioaddr
);
75 if (unlikely(p
->des01
.etx
.ip_header_error
)) {
76 CHIP_DBG(KERN_ERR
"\tTX IP header csum error\n");
77 x
->tx_ip_header_error
++;
80 if (unlikely(p
->des01
.etx
.payload_error
)) {
81 CHIP_DBG(KERN_ERR
"\tAddr/Payload csum error\n");
82 x
->tx_payload_error
++;
83 dwmac_dma_flush_tx_fifo(ioaddr
);
89 if (unlikely(p
->des01
.etx
.deferred
)) {
90 CHIP_DBG(KERN_INFO
"GMAC TX status: tx deferred\n");
93 #ifdef STMMAC_VLAN_TAG_USED
94 if (p
->des01
.etx
.vlan_frame
) {
95 CHIP_DBG(KERN_INFO
"GMAC TX status: VLAN frame\n");
103 static int enh_desc_get_tx_len(struct dma_desc
*p
)
105 return p
->des01
.etx
.buffer1_size
;
108 static int enh_desc_coe_rdes0(int ipc_err
, int type
, int payload_err
)
110 int ret
= good_frame
;
111 u32 status
= (type
<< 2 | ipc_err
<< 1 | payload_err
) & 0x7;
113 /* bits 5 7 0 | Frame status
114 * ----------------------------------------------------------
115 * 0 0 0 | IEEE 802.3 Type frame (length < 1536 octects)
116 * 1 0 0 | IPv4/6 No CSUM errorS.
117 * 1 0 1 | IPv4/6 CSUM PAYLOAD error
118 * 1 1 0 | IPv4/6 CSUM IP HR error
119 * 1 1 1 | IPv4/6 IP PAYLOAD AND HEADER errorS
120 * 0 0 1 | IPv4/6 unsupported IP PAYLOAD
121 * 0 1 1 | COE bypassed.. no IPv4/6 frame
125 CHIP_DBG(KERN_INFO
"RX Des0 status: IEEE 802.3 Type frame.\n");
127 } else if (status
== 0x4) {
128 CHIP_DBG(KERN_INFO
"RX Des0 status: IPv4/6 No CSUM errorS.\n");
130 } else if (status
== 0x5) {
131 CHIP_DBG(KERN_ERR
"RX Des0 status: IPv4/6 Payload Error.\n");
133 } else if (status
== 0x6) {
134 CHIP_DBG(KERN_ERR
"RX Des0 status: IPv4/6 Header Error.\n");
136 } else if (status
== 0x7) {
138 "RX Des0 status: IPv4/6 Header and Payload Error.\n");
140 } else if (status
== 0x1) {
142 "RX Des0 status: IPv4/6 unsupported IP PAYLOAD.\n");
144 } else if (status
== 0x3) {
145 CHIP_DBG(KERN_ERR
"RX Des0 status: No IPv4, IPv6 frame.\n");
151 static int enh_desc_get_rx_status(void *data
, struct stmmac_extra_stats
*x
,
154 int ret
= good_frame
;
155 struct net_device_stats
*stats
= (struct net_device_stats
*)data
;
157 if (unlikely(p
->des01
.erx
.error_summary
)) {
158 CHIP_DBG(KERN_ERR
"GMAC RX Error Summary 0x%08x\n",
160 if (unlikely(p
->des01
.erx
.descriptor_error
)) {
161 CHIP_DBG(KERN_ERR
"\tdescriptor error\n");
163 stats
->rx_length_errors
++;
165 if (unlikely(p
->des01
.erx
.overflow_error
)) {
166 CHIP_DBG(KERN_ERR
"\toverflow error\n");
167 x
->rx_gmac_overflow
++;
170 if (unlikely(p
->des01
.erx
.ipc_csum_error
))
171 CHIP_DBG(KERN_ERR
"\tIPC Csum Error/Giant frame\n");
173 if (unlikely(p
->des01
.erx
.late_collision
)) {
174 CHIP_DBG(KERN_ERR
"\tlate_collision error\n");
178 if (unlikely(p
->des01
.erx
.receive_watchdog
)) {
179 CHIP_DBG(KERN_ERR
"\treceive_watchdog error\n");
182 if (unlikely(p
->des01
.erx
.error_gmii
)) {
183 CHIP_DBG(KERN_ERR
"\tReceive Error\n");
186 if (unlikely(p
->des01
.erx
.crc_error
)) {
187 CHIP_DBG(KERN_ERR
"\tCRC error\n");
189 stats
->rx_crc_errors
++;
194 /* After a payload csum error, the ES bit is set.
195 * It doesn't match with the information reported into the databook.
196 * At any rate, we need to understand if the CSUM hw computation is ok
197 * and report this info to the upper layers. */
198 ret
= enh_desc_coe_rdes0(p
->des01
.erx
.ipc_csum_error
,
199 p
->des01
.erx
.frame_type
, p
->des01
.erx
.payload_csum_error
);
201 if (unlikely(p
->des01
.erx
.dribbling
)) {
202 CHIP_DBG(KERN_ERR
"GMAC RX: dribbling error\n");
205 if (unlikely(p
->des01
.erx
.sa_filter_fail
)) {
206 CHIP_DBG(KERN_ERR
"GMAC RX : Source Address filter fail\n");
207 x
->sa_rx_filter_fail
++;
210 if (unlikely(p
->des01
.erx
.da_filter_fail
)) {
211 CHIP_DBG(KERN_ERR
"GMAC RX : Dest Address filter fail\n");
212 x
->da_rx_filter_fail
++;
215 if (unlikely(p
->des01
.erx
.length_error
)) {
216 CHIP_DBG(KERN_ERR
"GMAC RX: length_error error\n");
220 #ifdef STMMAC_VLAN_TAG_USED
221 if (p
->des01
.erx
.vlan_tag
) {
222 CHIP_DBG(KERN_INFO
"GMAC RX: VLAN frame tagged\n");
229 static void enh_desc_init_rx_desc(struct dma_desc
*p
, unsigned int ring_size
,
233 for (i
= 0; i
< ring_size
; i
++) {
234 p
->des01
.erx
.own
= 1;
235 p
->des01
.erx
.buffer1_size
= BUF_SIZE_8KiB
- 1;
236 /* To support jumbo frames */
237 p
->des01
.erx
.buffer2_size
= BUF_SIZE_8KiB
- 1;
238 if (i
== ring_size
- 1)
239 p
->des01
.erx
.end_ring
= 1;
241 p
->des01
.erx
.disable_ic
= 1;
246 static void enh_desc_init_tx_desc(struct dma_desc
*p
, unsigned int ring_size
)
250 for (i
= 0; i
< ring_size
; i
++) {
251 p
->des01
.etx
.own
= 0;
252 if (i
== ring_size
- 1)
253 p
->des01
.etx
.end_ring
= 1;
258 static int enh_desc_get_tx_owner(struct dma_desc
*p
)
260 return p
->des01
.etx
.own
;
263 static int enh_desc_get_rx_owner(struct dma_desc
*p
)
265 return p
->des01
.erx
.own
;
268 static void enh_desc_set_tx_owner(struct dma_desc
*p
)
270 p
->des01
.etx
.own
= 1;
273 static void enh_desc_set_rx_owner(struct dma_desc
*p
)
275 p
->des01
.erx
.own
= 1;
278 static int enh_desc_get_tx_ls(struct dma_desc
*p
)
280 return p
->des01
.etx
.last_segment
;
283 static void enh_desc_release_tx_desc(struct dma_desc
*p
)
285 int ter
= p
->des01
.etx
.end_ring
;
287 memset(p
, 0, offsetof(struct dma_desc
, des2
));
288 p
->des01
.etx
.end_ring
= ter
;
291 static void enh_desc_prepare_tx_desc(struct dma_desc
*p
, int is_fs
, int len
,
294 p
->des01
.etx
.first_segment
= is_fs
;
295 if (unlikely(len
> BUF_SIZE_4KiB
)) {
296 p
->des01
.etx
.buffer1_size
= BUF_SIZE_4KiB
;
297 p
->des01
.etx
.buffer2_size
= len
- BUF_SIZE_4KiB
;
299 p
->des01
.etx
.buffer1_size
= len
;
301 if (likely(csum_flag
))
302 p
->des01
.etx
.checksum_insertion
= cic_full
;
305 static void enh_desc_clear_tx_ic(struct dma_desc
*p
)
307 p
->des01
.etx
.interrupt
= 0;
310 static void enh_desc_close_tx_desc(struct dma_desc
*p
)
312 p
->des01
.etx
.last_segment
= 1;
313 p
->des01
.etx
.interrupt
= 1;
316 static int enh_desc_get_rx_frame_len(struct dma_desc
*p
)
318 return p
->des01
.erx
.frame_length
;
321 const struct stmmac_desc_ops enh_desc_ops
= {
322 .tx_status
= enh_desc_get_tx_status
,
323 .rx_status
= enh_desc_get_rx_status
,
324 .get_tx_len
= enh_desc_get_tx_len
,
325 .init_rx_desc
= enh_desc_init_rx_desc
,
326 .init_tx_desc
= enh_desc_init_tx_desc
,
327 .get_tx_owner
= enh_desc_get_tx_owner
,
328 .get_rx_owner
= enh_desc_get_rx_owner
,
329 .release_tx_desc
= enh_desc_release_tx_desc
,
330 .prepare_tx_desc
= enh_desc_prepare_tx_desc
,
331 .clear_tx_ic
= enh_desc_clear_tx_ic
,
332 .close_tx_desc
= enh_desc_close_tx_desc
,
333 .get_tx_ls
= enh_desc_get_tx_ls
,
334 .set_tx_owner
= enh_desc_set_tx_owner
,
335 .set_rx_owner
= enh_desc_set_rx_owner
,
336 .get_rx_frame_len
= enh_desc_get_rx_frame_len
,