1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* 10G controller driver for Samsung SoCs |
3 | * |
4 | * Copyright (C) 2013 Samsung Electronics Co., Ltd. |
5 | * http://www.samsung.com |
6 | * |
7 | * Author: Siva Reddy Kallam <siva.kallam@samsung.com> |
8 | */ |
9 | |
10 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
11 | |
12 | #include <linux/bitops.h> |
13 | #include <linux/export.h> |
14 | #include <linux/io.h> |
15 | #include <linux/netdevice.h> |
16 | #include <linux/phy.h> |
17 | |
18 | #include "sxgbe_common.h" |
19 | #include "sxgbe_dma.h" |
20 | #include "sxgbe_desc.h" |
21 | |
22 | /* DMA TX descriptor ring initialization */ |
23 | static void sxgbe_init_tx_desc(struct sxgbe_tx_norm_desc *p) |
24 | { |
25 | p->tdes23.tx_rd_des23.own_bit = 0; |
26 | } |
27 | |
28 | static void sxgbe_tx_desc_enable_tse(struct sxgbe_tx_norm_desc *p, u8 is_tse, |
29 | u32 total_hdr_len, u32 tcp_hdr_len, |
30 | u32 tcp_payload_len) |
31 | { |
32 | p->tdes23.tx_rd_des23.tse_bit = is_tse; |
33 | p->tdes23.tx_rd_des23.buf1_size = total_hdr_len; |
34 | p->tdes23.tx_rd_des23.tcp_hdr_len = tcp_hdr_len / 4; |
35 | p->tdes23.tx_rd_des23.tx_pkt_len.tcp_payload_len = tcp_payload_len; |
36 | } |
37 | |
38 | /* Assign buffer lengths for descriptor */ |
39 | static void sxgbe_prepare_tx_desc(struct sxgbe_tx_norm_desc *p, u8 is_fd, |
40 | int buf1_len, int pkt_len, int cksum) |
41 | { |
42 | p->tdes23.tx_rd_des23.first_desc = is_fd; |
43 | p->tdes23.tx_rd_des23.buf1_size = buf1_len; |
44 | |
45 | p->tdes23.tx_rd_des23.tx_pkt_len.pkt_len.total_pkt_len = pkt_len; |
46 | |
47 | if (cksum) |
48 | p->tdes23.tx_rd_des23.cksum_ctl = cic_full; |
49 | } |
50 | |
51 | /* Set VLAN control information */ |
52 | static void sxgbe_tx_vlanctl_desc(struct sxgbe_tx_norm_desc *p, int vlan_ctl) |
53 | { |
54 | p->tdes23.tx_rd_des23.vlan_tag_ctl = vlan_ctl; |
55 | } |
56 | |
57 | /* Set the owner of Normal descriptor */ |
58 | static void sxgbe_set_tx_owner(struct sxgbe_tx_norm_desc *p) |
59 | { |
60 | p->tdes23.tx_rd_des23.own_bit = 1; |
61 | } |
62 | |
63 | /* Get the owner of Normal descriptor */ |
64 | static int sxgbe_get_tx_owner(struct sxgbe_tx_norm_desc *p) |
65 | { |
66 | return p->tdes23.tx_rd_des23.own_bit; |
67 | } |
68 | |
69 | /* Invoked by the xmit function to close the tx descriptor */ |
70 | static void sxgbe_close_tx_desc(struct sxgbe_tx_norm_desc *p) |
71 | { |
72 | p->tdes23.tx_rd_des23.last_desc = 1; |
73 | p->tdes23.tx_rd_des23.int_on_com = 1; |
74 | } |
75 | |
76 | /* Clean the tx descriptor as soon as the tx irq is received */ |
77 | static void sxgbe_release_tx_desc(struct sxgbe_tx_norm_desc *p) |
78 | { |
79 | memset(p, 0, sizeof(*p)); |
80 | } |
81 | |
82 | /* Clear interrupt on tx frame completion. When this bit is |
83 | * set an interrupt happens as soon as the frame is transmitted |
84 | */ |
85 | static void sxgbe_clear_tx_ic(struct sxgbe_tx_norm_desc *p) |
86 | { |
87 | p->tdes23.tx_rd_des23.int_on_com = 0; |
88 | } |
89 | |
90 | /* Last tx segment reports the transmit status */ |
91 | static int sxgbe_get_tx_ls(struct sxgbe_tx_norm_desc *p) |
92 | { |
93 | return p->tdes23.tx_rd_des23.last_desc; |
94 | } |
95 | |
96 | /* Get the buffer size from the descriptor */ |
97 | static int sxgbe_get_tx_len(struct sxgbe_tx_norm_desc *p) |
98 | { |
99 | return p->tdes23.tx_rd_des23.buf1_size; |
100 | } |
101 | |
102 | /* Set tx timestamp enable bit */ |
103 | static void sxgbe_tx_enable_tstamp(struct sxgbe_tx_norm_desc *p) |
104 | { |
105 | p->tdes23.tx_rd_des23.timestmp_enable = 1; |
106 | } |
107 | |
108 | /* get tx timestamp status */ |
109 | static int sxgbe_get_tx_timestamp_status(struct sxgbe_tx_norm_desc *p) |
110 | { |
111 | return p->tdes23.tx_rd_des23.timestmp_enable; |
112 | } |
113 | |
114 | /* TX Context Descripto Specific */ |
115 | static void sxgbe_tx_ctxt_desc_set_ctxt(struct sxgbe_tx_ctxt_desc *p) |
116 | { |
117 | p->ctxt_bit = 1; |
118 | } |
119 | |
120 | /* Set the owner of TX context descriptor */ |
121 | static void sxgbe_tx_ctxt_desc_set_owner(struct sxgbe_tx_ctxt_desc *p) |
122 | { |
123 | p->own_bit = 1; |
124 | } |
125 | |
126 | /* Get the owner of TX context descriptor */ |
127 | static int sxgbe_tx_ctxt_desc_get_owner(struct sxgbe_tx_ctxt_desc *p) |
128 | { |
129 | return p->own_bit; |
130 | } |
131 | |
132 | /* Set TX mss in TX context Descriptor */ |
133 | static void sxgbe_tx_ctxt_desc_set_mss(struct sxgbe_tx_ctxt_desc *p, u16 mss) |
134 | { |
135 | p->maxseg_size = mss; |
136 | } |
137 | |
138 | /* Get TX mss from TX context Descriptor */ |
139 | static int sxgbe_tx_ctxt_desc_get_mss(struct sxgbe_tx_ctxt_desc *p) |
140 | { |
141 | return p->maxseg_size; |
142 | } |
143 | |
144 | /* Set TX tcmssv in TX context Descriptor */ |
145 | static void sxgbe_tx_ctxt_desc_set_tcmssv(struct sxgbe_tx_ctxt_desc *p) |
146 | { |
147 | p->tcmssv = 1; |
148 | } |
149 | |
150 | /* Reset TX ostc in TX context Descriptor */ |
151 | static void sxgbe_tx_ctxt_desc_reset_ostc(struct sxgbe_tx_ctxt_desc *p) |
152 | { |
153 | p->ostc = 0; |
154 | } |
155 | |
156 | /* Set IVLAN information */ |
157 | static void sxgbe_tx_ctxt_desc_set_ivlantag(struct sxgbe_tx_ctxt_desc *p, |
158 | int is_ivlanvalid, int ivlan_tag, |
159 | int ivlan_ctl) |
160 | { |
161 | if (is_ivlanvalid) { |
162 | p->ivlan_tag_valid = is_ivlanvalid; |
163 | p->ivlan_tag = ivlan_tag; |
164 | p->ivlan_tag_ctl = ivlan_ctl; |
165 | } |
166 | } |
167 | |
168 | /* Return IVLAN Tag */ |
169 | static int sxgbe_tx_ctxt_desc_get_ivlantag(struct sxgbe_tx_ctxt_desc *p) |
170 | { |
171 | return p->ivlan_tag; |
172 | } |
173 | |
174 | /* Set VLAN Tag */ |
175 | static void sxgbe_tx_ctxt_desc_set_vlantag(struct sxgbe_tx_ctxt_desc *p, |
176 | int is_vlanvalid, int vlan_tag) |
177 | { |
178 | if (is_vlanvalid) { |
179 | p->vltag_valid = is_vlanvalid; |
180 | p->vlan_tag = vlan_tag; |
181 | } |
182 | } |
183 | |
184 | /* Return VLAN Tag */ |
185 | static int sxgbe_tx_ctxt_desc_get_vlantag(struct sxgbe_tx_ctxt_desc *p) |
186 | { |
187 | return p->vlan_tag; |
188 | } |
189 | |
190 | /* Set Time stamp */ |
191 | static void sxgbe_tx_ctxt_desc_set_tstamp(struct sxgbe_tx_ctxt_desc *p, |
192 | u8 ostc_enable, u64 tstamp) |
193 | { |
194 | if (ostc_enable) { |
195 | p->ostc = ostc_enable; |
196 | p->tstamp_lo = (u32) tstamp; |
197 | p->tstamp_hi = (u32) (tstamp>>32); |
198 | } |
199 | } |
200 | /* Close TX context descriptor */ |
201 | static void sxgbe_tx_ctxt_desc_close(struct sxgbe_tx_ctxt_desc *p) |
202 | { |
203 | p->own_bit = 1; |
204 | } |
205 | |
206 | /* WB status of context descriptor */ |
207 | static int sxgbe_tx_ctxt_desc_get_cde(struct sxgbe_tx_ctxt_desc *p) |
208 | { |
209 | return p->ctxt_desc_err; |
210 | } |
211 | |
212 | /* DMA RX descriptor ring initialization */ |
213 | static void sxgbe_init_rx_desc(struct sxgbe_rx_norm_desc *p, int disable_rx_ic, |
214 | int mode, int end) |
215 | { |
216 | p->rdes23.rx_rd_des23.own_bit = 1; |
217 | if (disable_rx_ic) |
218 | p->rdes23.rx_rd_des23.int_on_com = disable_rx_ic; |
219 | } |
220 | |
221 | /* Get RX own bit */ |
222 | static int sxgbe_get_rx_owner(struct sxgbe_rx_norm_desc *p) |
223 | { |
224 | return p->rdes23.rx_rd_des23.own_bit; |
225 | } |
226 | |
227 | /* Set RX own bit */ |
228 | static void sxgbe_set_rx_owner(struct sxgbe_rx_norm_desc *p) |
229 | { |
230 | p->rdes23.rx_rd_des23.own_bit = 1; |
231 | } |
232 | |
233 | /* Set Interrupt on completion bit */ |
234 | static void sxgbe_set_rx_int_on_com(struct sxgbe_rx_norm_desc *p) |
235 | { |
236 | p->rdes23.rx_rd_des23.int_on_com = 1; |
237 | } |
238 | |
239 | /* Get the receive frame size */ |
240 | static int sxgbe_get_rx_frame_len(struct sxgbe_rx_norm_desc *p) |
241 | { |
242 | return p->rdes23.rx_wb_des23.pkt_len; |
243 | } |
244 | |
245 | /* Return first Descriptor status */ |
246 | static int sxgbe_get_rx_fd_status(struct sxgbe_rx_norm_desc *p) |
247 | { |
248 | return p->rdes23.rx_wb_des23.first_desc; |
249 | } |
250 | |
251 | /* Return Last Descriptor status */ |
252 | static int sxgbe_get_rx_ld_status(struct sxgbe_rx_norm_desc *p) |
253 | { |
254 | return p->rdes23.rx_wb_des23.last_desc; |
255 | } |
256 | |
257 | |
258 | /* Return the RX status looking at the WB fields */ |
259 | static int sxgbe_rx_wbstatus(struct sxgbe_rx_norm_desc *p, |
260 | struct sxgbe_extra_stats *x, int *checksum) |
261 | { |
262 | int status = 0; |
263 | |
264 | *checksum = CHECKSUM_UNNECESSARY; |
265 | if (p->rdes23.rx_wb_des23.err_summary) { |
266 | switch (p->rdes23.rx_wb_des23.err_l2_type) { |
267 | case RX_GMII_ERR: |
268 | status = -EINVAL; |
269 | x->rx_code_gmii_err++; |
270 | break; |
271 | case RX_WATCHDOG_ERR: |
272 | status = -EINVAL; |
273 | x->rx_watchdog_err++; |
274 | break; |
275 | case RX_CRC_ERR: |
276 | status = -EINVAL; |
277 | x->rx_crc_err++; |
278 | break; |
279 | case RX_GAINT_ERR: |
280 | status = -EINVAL; |
281 | x->rx_gaint_pkt_err++; |
282 | break; |
283 | case RX_IP_HDR_ERR: |
284 | *checksum = CHECKSUM_NONE; |
285 | x->ip_hdr_err++; |
286 | break; |
287 | case RX_PAYLOAD_ERR: |
288 | *checksum = CHECKSUM_NONE; |
289 | x->ip_payload_err++; |
290 | break; |
291 | case RX_OVERFLOW_ERR: |
292 | status = -EINVAL; |
293 | x->overflow_error++; |
294 | break; |
295 | default: |
296 | pr_err("Invalid Error type\n" ); |
297 | break; |
298 | } |
299 | } else { |
300 | switch (p->rdes23.rx_wb_des23.err_l2_type) { |
301 | case RX_LEN_PKT: |
302 | x->len_pkt++; |
303 | break; |
304 | case RX_MACCTL_PKT: |
305 | x->mac_ctl_pkt++; |
306 | break; |
307 | case RX_DCBCTL_PKT: |
308 | x->dcb_ctl_pkt++; |
309 | break; |
310 | case RX_ARP_PKT: |
311 | x->arp_pkt++; |
312 | break; |
313 | case RX_OAM_PKT: |
314 | x->oam_pkt++; |
315 | break; |
316 | case RX_UNTAG_PKT: |
317 | x->untag_okt++; |
318 | break; |
319 | case RX_OTHER_PKT: |
320 | x->other_pkt++; |
321 | break; |
322 | case RX_SVLAN_PKT: |
323 | x->svlan_tag_pkt++; |
324 | break; |
325 | case RX_CVLAN_PKT: |
326 | x->cvlan_tag_pkt++; |
327 | break; |
328 | case RX_DVLAN_OCVLAN_ICVLAN_PKT: |
329 | x->dvlan_ocvlan_icvlan_pkt++; |
330 | break; |
331 | case RX_DVLAN_OSVLAN_ISVLAN_PKT: |
332 | x->dvlan_osvlan_isvlan_pkt++; |
333 | break; |
334 | case RX_DVLAN_OSVLAN_ICVLAN_PKT: |
335 | x->dvlan_osvlan_icvlan_pkt++; |
336 | break; |
337 | case RX_DVLAN_OCVLAN_ISVLAN_PKT: |
338 | x->dvlan_ocvlan_icvlan_pkt++; |
339 | break; |
340 | default: |
341 | pr_err("Invalid L2 Packet type\n" ); |
342 | break; |
343 | } |
344 | } |
345 | |
346 | /* L3/L4 Pkt type */ |
347 | switch (p->rdes23.rx_wb_des23.layer34_pkt_type) { |
348 | case RX_NOT_IP_PKT: |
349 | x->not_ip_pkt++; |
350 | break; |
351 | case RX_IPV4_TCP_PKT: |
352 | x->ip4_tcp_pkt++; |
353 | break; |
354 | case RX_IPV4_UDP_PKT: |
355 | x->ip4_udp_pkt++; |
356 | break; |
357 | case RX_IPV4_ICMP_PKT: |
358 | x->ip4_icmp_pkt++; |
359 | break; |
360 | case RX_IPV4_UNKNOWN_PKT: |
361 | x->ip4_unknown_pkt++; |
362 | break; |
363 | case RX_IPV6_TCP_PKT: |
364 | x->ip6_tcp_pkt++; |
365 | break; |
366 | case RX_IPV6_UDP_PKT: |
367 | x->ip6_udp_pkt++; |
368 | break; |
369 | case RX_IPV6_ICMP_PKT: |
370 | x->ip6_icmp_pkt++; |
371 | break; |
372 | case RX_IPV6_UNKNOWN_PKT: |
373 | x->ip6_unknown_pkt++; |
374 | break; |
375 | default: |
376 | pr_err("Invalid L3/L4 Packet type\n" ); |
377 | break; |
378 | } |
379 | |
380 | /* Filter */ |
381 | if (p->rdes23.rx_wb_des23.vlan_filter_match) |
382 | x->vlan_filter_match++; |
383 | |
384 | if (p->rdes23.rx_wb_des23.sa_filter_fail) { |
385 | status = -EINVAL; |
386 | x->sa_filter_fail++; |
387 | } |
388 | if (p->rdes23.rx_wb_des23.da_filter_fail) { |
389 | status = -EINVAL; |
390 | x->da_filter_fail++; |
391 | } |
392 | if (p->rdes23.rx_wb_des23.hash_filter_pass) |
393 | x->hash_filter_pass++; |
394 | |
395 | if (p->rdes23.rx_wb_des23.l3_filter_match) |
396 | x->l3_filter_match++; |
397 | |
398 | if (p->rdes23.rx_wb_des23.l4_filter_match) |
399 | x->l4_filter_match++; |
400 | |
401 | return status; |
402 | } |
403 | |
404 | /* Get own bit of context descriptor */ |
405 | static int sxgbe_get_rx_ctxt_owner(struct sxgbe_rx_ctxt_desc *p) |
406 | { |
407 | return p->own_bit; |
408 | } |
409 | |
410 | /* Set own bit for context descriptor */ |
411 | static void sxgbe_set_ctxt_rx_owner(struct sxgbe_rx_ctxt_desc *p) |
412 | { |
413 | p->own_bit = 1; |
414 | } |
415 | |
416 | |
417 | /* Return the reception status looking at Context control information */ |
418 | static void sxgbe_rx_ctxt_wbstatus(struct sxgbe_rx_ctxt_desc *p, |
419 | struct sxgbe_extra_stats *x) |
420 | { |
421 | if (p->tstamp_dropped) |
422 | x->timestamp_dropped++; |
423 | |
424 | /* ptp */ |
425 | if (p->ptp_msgtype == RX_NO_PTP) |
426 | x->rx_msg_type_no_ptp++; |
427 | else if (p->ptp_msgtype == RX_PTP_SYNC) |
428 | x->rx_ptp_type_sync++; |
429 | else if (p->ptp_msgtype == RX_PTP_FOLLOW_UP) |
430 | x->rx_ptp_type_follow_up++; |
431 | else if (p->ptp_msgtype == RX_PTP_DELAY_REQ) |
432 | x->rx_ptp_type_delay_req++; |
433 | else if (p->ptp_msgtype == RX_PTP_DELAY_RESP) |
434 | x->rx_ptp_type_delay_resp++; |
435 | else if (p->ptp_msgtype == RX_PTP_PDELAY_REQ) |
436 | x->rx_ptp_type_pdelay_req++; |
437 | else if (p->ptp_msgtype == RX_PTP_PDELAY_RESP) |
438 | x->rx_ptp_type_pdelay_resp++; |
439 | else if (p->ptp_msgtype == RX_PTP_PDELAY_FOLLOW_UP) |
440 | x->rx_ptp_type_pdelay_follow_up++; |
441 | else if (p->ptp_msgtype == RX_PTP_ANNOUNCE) |
442 | x->rx_ptp_announce++; |
443 | else if (p->ptp_msgtype == RX_PTP_MGMT) |
444 | x->rx_ptp_mgmt++; |
445 | else if (p->ptp_msgtype == RX_PTP_SIGNAL) |
446 | x->rx_ptp_signal++; |
447 | else if (p->ptp_msgtype == RX_PTP_RESV_MSG) |
448 | x->rx_ptp_resv_msg_type++; |
449 | } |
450 | |
451 | /* Get rx timestamp status */ |
452 | static int sxgbe_get_rx_ctxt_tstamp_status(struct sxgbe_rx_ctxt_desc *p) |
453 | { |
454 | if ((p->tstamp_hi == 0xffffffff) && (p->tstamp_lo == 0xffffffff)) { |
455 | pr_err("Time stamp corrupted\n" ); |
456 | return 0; |
457 | } |
458 | |
459 | return p->tstamp_available; |
460 | } |
461 | |
462 | |
463 | static u64 sxgbe_get_rx_timestamp(struct sxgbe_rx_ctxt_desc *p) |
464 | { |
465 | u64 ns; |
466 | |
467 | ns = p->tstamp_lo; |
468 | ns |= ((u64)p->tstamp_hi) << 32; |
469 | |
470 | return ns; |
471 | } |
472 | |
473 | static const struct sxgbe_desc_ops desc_ops = { |
474 | .init_tx_desc = sxgbe_init_tx_desc, |
475 | .tx_desc_enable_tse = sxgbe_tx_desc_enable_tse, |
476 | .prepare_tx_desc = sxgbe_prepare_tx_desc, |
477 | .tx_vlanctl_desc = sxgbe_tx_vlanctl_desc, |
478 | .set_tx_owner = sxgbe_set_tx_owner, |
479 | .get_tx_owner = sxgbe_get_tx_owner, |
480 | .close_tx_desc = sxgbe_close_tx_desc, |
481 | .release_tx_desc = sxgbe_release_tx_desc, |
482 | .clear_tx_ic = sxgbe_clear_tx_ic, |
483 | .get_tx_ls = sxgbe_get_tx_ls, |
484 | .get_tx_len = sxgbe_get_tx_len, |
485 | .tx_enable_tstamp = sxgbe_tx_enable_tstamp, |
486 | .get_tx_timestamp_status = sxgbe_get_tx_timestamp_status, |
487 | .tx_ctxt_desc_set_ctxt = sxgbe_tx_ctxt_desc_set_ctxt, |
488 | .tx_ctxt_desc_set_owner = sxgbe_tx_ctxt_desc_set_owner, |
489 | .get_tx_ctxt_owner = sxgbe_tx_ctxt_desc_get_owner, |
490 | .tx_ctxt_desc_set_mss = sxgbe_tx_ctxt_desc_set_mss, |
491 | .tx_ctxt_desc_get_mss = sxgbe_tx_ctxt_desc_get_mss, |
492 | .tx_ctxt_desc_set_tcmssv = sxgbe_tx_ctxt_desc_set_tcmssv, |
493 | .tx_ctxt_desc_reset_ostc = sxgbe_tx_ctxt_desc_reset_ostc, |
494 | .tx_ctxt_desc_set_ivlantag = sxgbe_tx_ctxt_desc_set_ivlantag, |
495 | .tx_ctxt_desc_get_ivlantag = sxgbe_tx_ctxt_desc_get_ivlantag, |
496 | .tx_ctxt_desc_set_vlantag = sxgbe_tx_ctxt_desc_set_vlantag, |
497 | .tx_ctxt_desc_get_vlantag = sxgbe_tx_ctxt_desc_get_vlantag, |
498 | .tx_ctxt_set_tstamp = sxgbe_tx_ctxt_desc_set_tstamp, |
499 | .close_tx_ctxt_desc = sxgbe_tx_ctxt_desc_close, |
500 | .get_tx_ctxt_cde = sxgbe_tx_ctxt_desc_get_cde, |
501 | .init_rx_desc = sxgbe_init_rx_desc, |
502 | .get_rx_owner = sxgbe_get_rx_owner, |
503 | .set_rx_owner = sxgbe_set_rx_owner, |
504 | .set_rx_int_on_com = sxgbe_set_rx_int_on_com, |
505 | .get_rx_frame_len = sxgbe_get_rx_frame_len, |
506 | .get_rx_fd_status = sxgbe_get_rx_fd_status, |
507 | .get_rx_ld_status = sxgbe_get_rx_ld_status, |
508 | .rx_wbstatus = sxgbe_rx_wbstatus, |
509 | .get_rx_ctxt_owner = sxgbe_get_rx_ctxt_owner, |
510 | .set_rx_ctxt_owner = sxgbe_set_ctxt_rx_owner, |
511 | .rx_ctxt_wbstatus = sxgbe_rx_ctxt_wbstatus, |
512 | .get_rx_ctxt_tstamp_status = sxgbe_get_rx_ctxt_tstamp_status, |
513 | .get_timestamp = sxgbe_get_rx_timestamp, |
514 | }; |
515 | |
516 | const struct sxgbe_desc_ops *sxgbe_get_desc_ops(void) |
517 | { |
518 | return &desc_ops; |
519 | } |
520 | |