520 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* 10G controller driver for Samsung SoCs3 *4 * Copyright (C) 2013 Samsung Electronics Co., Ltd.5 * http://www.samsung.com6 *7 * Author: Siva Reddy Kallam <siva.kallam@samsung.com>8 */9 10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt11 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 */23static void sxgbe_init_tx_desc(struct sxgbe_tx_norm_desc *p)24{25 p->tdes23.tx_rd_des23.own_bit = 0;26}27 28static 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 */39static 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 */52static 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 */58static 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 */64static 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 */70static 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 */77static 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 is83 * set an interrupt happens as soon as the frame is transmitted84 */85static 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 */91static 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 */97static 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 */103static 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 */109static 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 */115static 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 */121static 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 */127static 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 */133static 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 */139static 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 */145static 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 */151static void sxgbe_tx_ctxt_desc_reset_ostc(struct sxgbe_tx_ctxt_desc *p)152{153 p->ostc = 0;154}155 156/* Set IVLAN information */157static 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 */169static 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 */175static 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 */185static 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 */191static 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 */201static 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 */207static 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 */213static 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 */222static 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 */228static 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 */234static 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 */240static 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 */246static 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 */252static 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 */259static 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 */405static 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 */411static 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 */418static 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 */452static 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 463static 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 473static 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 516const struct sxgbe_desc_ops *sxgbe_get_desc_ops(void)517{518 return &desc_ops;519}520