linux/drivers/net/ethernet/freescale/fec_main.c

// SPDX-License-Identifier: GPL-2.0+
/*
 * Fast Ethernet Controller (FEC) driver for Motorola MPC8xx.
 * Copyright (c) 1997 Dan Malek ([email protected])
 *
 * Right now, I am very wasteful with the buffers.  I allocate memory
 * pages and then divide them into 2K frame buffers.  This way I know I
 * have buffers large enough to hold one frame within one buffer descriptor.
 * Once I get this working, I will use 64 or 128 byte CPM buffers, which
 * will be much more memory efficient and will easily handle lots of
 * small packets.
 *
 * Much better multiple PHY support by Magnus Damm.
 * Copyright (c) 2000 Ericsson Radio Systems AB.
 *
 * Support for FEC controller of ColdFire processors.
 * Copyright (c) 2001-2005 Greg Ungerer ([email protected])
 *
 * Bug fixes and cleanup by Philippe De Muyter ([email protected])
 * Copyright (c) 2004-2006 Macq Electronique SA.
 *
 * Copyright (C) 2010-2011 Freescale Semiconductor, Inc.
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/pm_runtime.h>
#include <linux/ptrace.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <net/ip.h>
#include <net/page_pool/helpers.h>
#include <net/selftests.h>
#include <net/tso.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/icmp.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
#include <linux/bitops.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/clk.h>
#include <linux/crc32.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/mdio.h>
#include <linux/phy.h>
#include <linux/fec.h>
#include <linux/of.h>
#include <linux/of_mdio.h>
#include <linux/of_net.h>
#include <linux/regulator/consumer.h>
#include <linux/if_vlan.h>
#include <linux/pinctrl/consumer.h>
#include <linux/gpio/consumer.h>
#include <linux/prefetch.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include <soc/imx/cpuidle.h>
#include <linux/filter.h>
#include <linux/bpf.h>
#include <linux/bpf_trace.h>

#include <asm/cacheflush.h>

#include "fec.h"

static void set_multicast_list(struct net_device *ndev);
static void fec_enet_itr_coal_set(struct net_device *ndev);
static int fec_enet_xdp_tx_xmit(struct fec_enet_private *fep,
				int cpu, struct xdp_buff *xdp,
				u32 dma_sync_len);

#define DRIVER_NAME

static const u16 fec_enet_vlan_pri_to_queue[8] =;

#define FEC_ENET_RSEM_V
#define FEC_ENET_RSFL_V
#define FEC_ENET_RAEM_V
#define FEC_ENET_RAFL_V
#define FEC_ENET_OPD_V
#define FEC_MDIO_PM_TIMEOUT

#define FEC_ENET_XDP_PASS
#define FEC_ENET_XDP_CONSUMED
#define FEC_ENET_XDP_TX
#define FEC_ENET_XDP_REDIR

struct fec_devinfo {};

static const struct fec_devinfo fec_imx25_info =;

static const struct fec_devinfo fec_imx27_info =;

static const struct fec_devinfo fec_imx28_info =;

static const struct fec_devinfo fec_imx6q_info =;

static const struct fec_devinfo fec_mvf600_info =;

static const struct fec_devinfo fec_imx6x_info =;

static const struct fec_devinfo fec_imx6ul_info =;

static const struct fec_devinfo fec_imx8mq_info =;

static const struct fec_devinfo fec_imx8qm_info =;

static const struct fec_devinfo fec_s32v234_info =;

static struct platform_device_id fec_devtype[] =;
MODULE_DEVICE_TABLE(platform, fec_devtype);

static const struct of_device_id fec_dt_ids[] =;
MODULE_DEVICE_TABLE(of, fec_dt_ids);

static unsigned char macaddr[ETH_ALEN];
module_param_array();
MODULE_PARM_DESC();

#if defined(CONFIG_M5272)
/*
 * Some hardware gets it MAC address out of local flash memory.
 * if this is non-zero then assume it is the address to get MAC from.
 */
#if defined(CONFIG_NETtel)
#define FEC_FLASHMAC
#elif defined(CONFIG_GILBARCONAP) || defined(CONFIG_SCALES)
#define FEC_FLASHMAC
#elif defined(CONFIG_CANCam)
#define FEC_FLASHMAC
#elif defined (CONFIG_M5272C3)
#define FEC_FLASHMAC
#elif defined(CONFIG_MOD5272)
#define FEC_FLASHMAC
#else
#define FEC_FLASHMAC
#endif
#endif /* CONFIG_M5272 */

/* The FEC stores dest/src/type/vlan, data, and checksum for receive packets.
 *
 * 2048 byte skbufs are allocated. However, alignment requirements
 * varies between FEC variants. Worst case is 64, so round down by 64.
 */
#define PKT_MAXBUF_SIZE
#define PKT_MINBUF_SIZE

/* FEC receive acceleration */
#define FEC_RACC_IPDIS
#define FEC_RACC_PRODIS
#define FEC_RACC_SHIFT16
#define FEC_RACC_OPTIONS

/* MIB Control Register */
#define FEC_MIB_CTRLSTAT_DISABLE

/*
 * The 5270/5271/5280/5282/532x RX control register also contains maximum frame
 * size bits. Other FEC hardware does not, so we need to take that into
 * account when setting it.
 */
#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
    defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM) || \
    defined(CONFIG_ARM64)
#define OPT_FRAME_SIZE
#else
#define OPT_FRAME_SIZE
#endif

/* FEC MII MMFR bits definition */
#define FEC_MMFR_ST
#define FEC_MMFR_ST_C45
#define FEC_MMFR_OP_READ
#define FEC_MMFR_OP_READ_C45
#define FEC_MMFR_OP_WRITE
#define FEC_MMFR_OP_ADDR_WRITE
#define FEC_MMFR_PA(v)
#define FEC_MMFR_RA(v)
#define FEC_MMFR_TA
#define FEC_MMFR_DATA(v)
/* FEC ECR bits definition */
#define FEC_ECR_RESET
#define FEC_ECR_ETHEREN
#define FEC_ECR_MAGICEN
#define FEC_ECR_SLEEP
#define FEC_ECR_EN1588
#define FEC_ECR_BYTESWP
/* FEC RCR bits definition */
#define FEC_RCR_LOOP
#define FEC_RCR_HALFDPX
#define FEC_RCR_MII
#define FEC_RCR_PROMISC
#define FEC_RCR_BC_REJ
#define FEC_RCR_FLOWCTL
#define FEC_RCR_RMII
#define FEC_RCR_10BASET
/* TX WMARK bits */
#define FEC_TXWMRK_STRFWD

#define FEC_MII_TIMEOUT

/* Transmitter timeout */
#define TX_TIMEOUT

#define FEC_PAUSE_FLAG_AUTONEG
#define FEC_PAUSE_FLAG_ENABLE
#define FEC_WOL_HAS_MAGIC_PACKET
#define FEC_WOL_FLAG_ENABLE
#define FEC_WOL_FLAG_SLEEP_ON

/* Max number of allowed TCP segments for software TSO */
#define FEC_MAX_TSO_SEGS
#define FEC_MAX_SKB_DESCS

#define IS_TSO_HEADER(txq, addr)

static int mii_cnt;

static struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp,
					     struct bufdesc_prop *bd)
{}

static struct bufdesc *fec_enet_get_prevdesc(struct bufdesc *bdp,
					     struct bufdesc_prop *bd)
{}

static int fec_enet_get_bd_index(struct bufdesc *bdp,
				 struct bufdesc_prop *bd)
{}

static int fec_enet_get_free_txdesc_num(struct fec_enet_priv_tx_q *txq)
{}

static void swap_buffer(void *bufaddr, int len)
{}

static void fec_dump(struct net_device *ndev)
{}

/*
 * Coldfire does not support DMA coherent allocations, and has historically used
 * a band-aid with a manual flush in fec_enet_rx_queue.
 */
#if defined(CONFIG_COLDFIRE) && !defined(CONFIG_COLDFIRE_COHERENT_DMA)
static void *fec_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
		gfp_t gfp)
{
	return dma_alloc_noncoherent(dev, size, handle, DMA_BIDIRECTIONAL, gfp);
}

static void fec_dma_free(struct device *dev, size_t size, void *cpu_addr,
		dma_addr_t handle)
{
	dma_free_noncoherent(dev, size, cpu_addr, handle, DMA_BIDIRECTIONAL);
}
#else /* !CONFIG_COLDFIRE || CONFIG_COLDFIRE_COHERENT_DMA */
static void *fec_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
		gfp_t gfp)
{}

static void fec_dma_free(struct device *dev, size_t size, void *cpu_addr,
		dma_addr_t handle)
{}
#endif /* !CONFIG_COLDFIRE || CONFIG_COLDFIRE_COHERENT_DMA */

struct fec_dma_devres {};

static void fec_dmam_release(struct device *dev, void *res)
{}

static void *fec_dmam_alloc(struct device *dev, size_t size, dma_addr_t *handle,
		gfp_t gfp)
{}

static inline bool is_ipv4_pkt(struct sk_buff *skb)
{}

static int
fec_enet_clear_csum(struct sk_buff *skb, struct net_device *ndev)
{}

static int
fec_enet_create_page_pool(struct fec_enet_private *fep,
			  struct fec_enet_priv_rx_q *rxq, int size)
{}

static struct bufdesc *
fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
			     struct sk_buff *skb,
			     struct net_device *ndev)
{}

static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
				   struct sk_buff *skb, struct net_device *ndev)
{}

static int
fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb,
			  struct net_device *ndev,
			  struct bufdesc *bdp, int index, char *data,
			  int size, bool last_tcp, bool is_last)
{}

static int
fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq,
			 struct sk_buff *skb, struct net_device *ndev,
			 struct bufdesc *bdp, int index)
{}

static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq,
				   struct sk_buff *skb,
				   struct net_device *ndev)
{}

static netdev_tx_t
fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
{}

/* Init RX & TX buffer descriptors
 */
static void fec_enet_bd_init(struct net_device *dev)
{}

static void fec_enet_active_rxring(struct net_device *ndev)
{}

static void fec_enet_enable_ring(struct net_device *ndev)
{}

/*
 * This function is called to start or restart the FEC during a link
 * change, transmit timeout, or to reconfigure the FEC.  The network
 * packet processing for this device must be stopped before this call.
 */
static void
fec_restart(struct net_device *ndev)
{}

static int fec_enet_ipc_handle_init(struct fec_enet_private *fep)
{}

static void fec_enet_ipg_stop_set(struct fec_enet_private *fep, bool enabled)
{}

static void fec_enet_stop_mode(struct fec_enet_private *fep, bool enabled)
{}

static void fec_irqs_disable(struct net_device *ndev)
{}

static void fec_irqs_disable_except_wakeup(struct net_device *ndev)
{}

static void
fec_stop(struct net_device *ndev)
{}

static void
fec_timeout(struct net_device *ndev, unsigned int txqueue)
{}

static void fec_enet_timeout_work(struct work_struct *work)
{}

static void
fec_enet_hwtstamp(struct fec_enet_private *fep, unsigned ts,
	struct skb_shared_hwtstamps *hwtstamps)
{}

static void
fec_enet_tx_queue(struct net_device *ndev, u16 queue_id, int budget)
{}

static void fec_enet_tx(struct net_device *ndev, int budget)
{}

static void fec_enet_update_cbd(struct fec_enet_priv_rx_q *rxq,
				struct bufdesc *bdp, int index)
{}

static u32
fec_enet_run_xdp(struct fec_enet_private *fep, struct bpf_prog *prog,
		 struct xdp_buff *xdp, struct fec_enet_priv_rx_q *rxq, int cpu)
{}

/* During a receive, the bd_rx.cur points to the current incoming buffer.
 * When we update through the ring, if the next incoming buffer has
 * not been given to the system, we just set the empty indicator,
 * effectively tossing the packet.
 */
static int
fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
{}

static int fec_enet_rx(struct net_device *ndev, int budget)
{}

static bool fec_enet_collect_events(struct fec_enet_private *fep)
{}

static irqreturn_t
fec_enet_interrupt(int irq, void *dev_id)
{}

static int fec_enet_rx_napi(struct napi_struct *napi, int budget)
{}

/* ------------------------------------------------------------------------- */
static int fec_get_mac(struct net_device *ndev)
{}

/* ------------------------------------------------------------------------- */

/*
 * Phy section
 */

/* LPI Sleep Ts count base on tx clk (clk_ref).
 * The lpi sleep cnt value = X us / (cycle_ns).
 */
static int fec_enet_us_to_tx_cycle(struct net_device *ndev, int us)
{}

static int fec_enet_eee_mode_set(struct net_device *ndev, bool enable)
{}

static void fec_enet_adjust_link(struct net_device *ndev)
{}

static int fec_enet_mdio_wait(struct fec_enet_private *fep)
{}

static int fec_enet_mdio_read_c22(struct mii_bus *bus, int mii_id, int regnum)
{}

static int fec_enet_mdio_read_c45(struct mii_bus *bus, int mii_id,
				  int devad, int regnum)
{}

static int fec_enet_mdio_write_c22(struct mii_bus *bus, int mii_id, int regnum,
				   u16 value)
{}

static int fec_enet_mdio_write_c45(struct mii_bus *bus, int mii_id,
				   int devad, int regnum, u16 value)
{}

static void fec_enet_phy_reset_after_clk_enable(struct net_device *ndev)
{}

static int fec_enet_clk_enable(struct net_device *ndev, bool enable)
{}

static int fec_enet_parse_rgmii_delay(struct fec_enet_private *fep,
				      struct device_node *np)
{}

static int fec_enet_mii_probe(struct net_device *ndev)
{}

static int fec_enet_mii_init(struct platform_device *pdev)
{}

static void fec_enet_mii_remove(struct fec_enet_private *fep)
{}

static void fec_enet_get_drvinfo(struct net_device *ndev,
				 struct ethtool_drvinfo *info)
{}

static int fec_enet_get_regs_len(struct net_device *ndev)
{}

/* List of registers that can be safety be read to dump them with ethtool */
#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
	defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM) || \
	defined(CONFIG_ARM64) || defined(CONFIG_COMPILE_TEST)
static __u32 fec_enet_register_version =;
static u32 fec_enet_register_offset[] =;
/* for i.MX6ul */
static u32 fec_enet_register_offset_6ul[] =;
#else
static __u32 fec_enet_register_version = 1;
static u32 fec_enet_register_offset[] = {
	FEC_ECNTRL, FEC_IEVENT, FEC_IMASK, FEC_IVEC, FEC_R_DES_ACTIVE_0,
	FEC_R_DES_ACTIVE_1, FEC_R_DES_ACTIVE_2, FEC_X_DES_ACTIVE_0,
	FEC_X_DES_ACTIVE_1, FEC_X_DES_ACTIVE_2, FEC_MII_DATA, FEC_MII_SPEED,
	FEC_R_BOUND, FEC_R_FSTART, FEC_X_WMRK, FEC_X_FSTART, FEC_R_CNTRL,
	FEC_MAX_FRM_LEN, FEC_X_CNTRL, FEC_ADDR_LOW, FEC_ADDR_HIGH,
	FEC_GRP_HASH_TABLE_HIGH, FEC_GRP_HASH_TABLE_LOW, FEC_R_DES_START_0,
	FEC_R_DES_START_1, FEC_R_DES_START_2, FEC_X_DES_START_0,
	FEC_X_DES_START_1, FEC_X_DES_START_2, FEC_R_BUFF_SIZE_0,
	FEC_R_BUFF_SIZE_1, FEC_R_BUFF_SIZE_2
};
#endif

static void fec_enet_get_regs(struct net_device *ndev,
			      struct ethtool_regs *regs, void *regbuf)
{}

static int fec_enet_get_ts_info(struct net_device *ndev,
				struct kernel_ethtool_ts_info *info)
{}

#if !defined(CONFIG_M5272)

static void fec_enet_get_pauseparam(struct net_device *ndev,
				    struct ethtool_pauseparam *pause)
{}

static int fec_enet_set_pauseparam(struct net_device *ndev,
				   struct ethtool_pauseparam *pause)
{}

static const struct fec_stat {} fec_stats[] =;

#define FEC_STATS_SIZE

static const char *fec_xdp_stat_strs[XDP_STATS_TOTAL] =;

static void fec_enet_update_ethtool_stats(struct net_device *dev)
{}

static void fec_enet_get_xdp_stats(struct fec_enet_private *fep, u64 *data)
{}

static void fec_enet_page_pool_stats(struct fec_enet_private *fep, u64 *data)
{}

static void fec_enet_get_ethtool_stats(struct net_device *dev,
				       struct ethtool_stats *stats, u64 *data)
{}

static void fec_enet_get_strings(struct net_device *netdev,
	u32 stringset, u8 *data)
{}

static int fec_enet_get_sset_count(struct net_device *dev, int sset)
{}

static void fec_enet_clear_ethtool_stats(struct net_device *dev)
{}

#else	/* !defined(CONFIG_M5272) */
#define FEC_STATS_SIZE
static inline void fec_enet_update_ethtool_stats(struct net_device *dev)
{
}

static inline void fec_enet_clear_ethtool_stats(struct net_device *dev)
{
}
#endif /* !defined(CONFIG_M5272) */

/* ITR clock source is enet system clock (clk_ahb).
 * TCTT unit is cycle_ns * 64 cycle
 * So, the ICTT value = X us / (cycle_ns * 64)
 */
static int fec_enet_us_to_itr_clock(struct net_device *ndev, int us)
{}

/* Set threshold for interrupt coalescing */
static void fec_enet_itr_coal_set(struct net_device *ndev)
{}

static int fec_enet_get_coalesce(struct net_device *ndev,
				 struct ethtool_coalesce *ec,
				 struct kernel_ethtool_coalesce *kernel_coal,
				 struct netlink_ext_ack *extack)
{}

static int fec_enet_set_coalesce(struct net_device *ndev,
				 struct ethtool_coalesce *ec,
				 struct kernel_ethtool_coalesce *kernel_coal,
				 struct netlink_ext_ack *extack)
{}

static int
fec_enet_get_eee(struct net_device *ndev, struct ethtool_keee *edata)
{}

static int
fec_enet_set_eee(struct net_device *ndev, struct ethtool_keee *edata)
{}

static void
fec_enet_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
{}

static int
fec_enet_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
{}

static const struct ethtool_ops fec_enet_ethtool_ops =;

static void fec_enet_free_buffers(struct net_device *ndev)
{}

static void fec_enet_free_queue(struct net_device *ndev)
{}

static int fec_enet_alloc_queue(struct net_device *ndev)
{}

static int
fec_enet_alloc_rxq_buffers(struct net_device *ndev, unsigned int queue)
{}

static int
fec_enet_alloc_txq_buffers(struct net_device *ndev, unsigned int queue)
{}

static int fec_enet_alloc_buffers(struct net_device *ndev)
{}

static int
fec_enet_open(struct net_device *ndev)
{}

static int
fec_enet_close(struct net_device *ndev)
{}

/* Set or clear the multicast filter for this adaptor.
 * Skeleton taken from sunlance driver.
 * The CPM Ethernet implementation allows Multicast as well as individual
 * MAC address filtering.  Some of the drivers check to make sure it is
 * a group multicast address, and discard those that are not.  I guess I
 * will do the same for now, but just remove the test if you want
 * individual filtering as well (do the upper net layers want or support
 * this kind of feature?).
 */

#define FEC_HASH_BITS

static void set_multicast_list(struct net_device *ndev)
{}

/* Set a MAC change in hardware. */
static int
fec_set_mac_address(struct net_device *ndev, void *p)
{}

static inline void fec_enet_set_netdev_features(struct net_device *netdev,
	netdev_features_t features)
{}

static int fec_set_features(struct net_device *netdev,
	netdev_features_t features)
{}

static u16 fec_enet_select_queue(struct net_device *ndev, struct sk_buff *skb,
				 struct net_device *sb_dev)
{}

static int fec_enet_bpf(struct net_device *dev, struct netdev_bpf *bpf)
{}

static int
fec_enet_xdp_get_tx_queue(struct fec_enet_private *fep, int index)
{}

static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep,
				   struct fec_enet_priv_tx_q *txq,
				   void *frame, u32 dma_sync_len,
				   bool ndo_xmit)
{}

static int fec_enet_xdp_tx_xmit(struct fec_enet_private *fep,
				int cpu, struct xdp_buff *xdp,
				u32 dma_sync_len)
{}

static int fec_enet_xdp_xmit(struct net_device *dev,
			     int num_frames,
			     struct xdp_frame **frames,
			     u32 flags)
{}

static int fec_hwtstamp_get(struct net_device *ndev,
			    struct kernel_hwtstamp_config *config)
{}

static int fec_hwtstamp_set(struct net_device *ndev,
			    struct kernel_hwtstamp_config *config,
			    struct netlink_ext_ack *extack)
{}

static const struct net_device_ops fec_netdev_ops =;

static const unsigned short offset_des_active_rxq[] =;

static const unsigned short offset_des_active_txq[] =;

 /*
  * XXX:  We need to clean up on failure exits here.
  *
  */
static int fec_enet_init(struct net_device *ndev)
{}

static void fec_enet_deinit(struct net_device *ndev)
{}

#ifdef CONFIG_OF
static int fec_reset_phy(struct platform_device *pdev)
{}
#else /* CONFIG_OF */
static int fec_reset_phy(struct platform_device *pdev)
{
	/*
	 * In case of platform probe, the reset has been done
	 * by machine code.
	 */
	return 0;
}
#endif /* CONFIG_OF */

static void
fec_enet_get_queue_num(struct platform_device *pdev, int *num_tx, int *num_rx)
{}

static int fec_enet_get_irq_cnt(struct platform_device *pdev)
{}

static void fec_enet_get_wakeup_irq(struct platform_device *pdev)
{}

static int fec_enet_init_stop_mode(struct fec_enet_private *fep,
				   struct device_node *np)
{}

static int
fec_probe(struct platform_device *pdev)
{}

static void
fec_drv_remove(struct platform_device *pdev)
{}

static int fec_suspend(struct device *dev)
{}

static int fec_resume(struct device *dev)
{}

static int fec_runtime_suspend(struct device *dev)
{}

static int fec_runtime_resume(struct device *dev)
{}

static const struct dev_pm_ops fec_pm_ops =;

static struct platform_driver fec_driver =;

module_platform_driver();

MODULE_DESCRIPTION();
MODULE_LICENSE();