brintos

brintos / linux-shallow public Read only

0
0
Text · 12.8 KiB · b33ebf2 Raw
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