linux/drivers/net/ethernet/marvell/skge.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * New driver for Marvell Yukon chipset and SysKonnect Gigabit
 * Ethernet adapters. Based on earlier sk98lin, e100 and
 * FreeBSD if_sk drivers.
 *
 * This driver intentionally does not support all the features
 * of the original driver such as link fail-over and link management because
 * those should be done at higher levels.
 *
 * Copyright (C) 2004, 2005 Stephen Hemminger <[email protected]>
 */

#define pr_fmt(fmt)

#include <linux/in.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/pci.h>
#include <linux/if_vlan.h>
#include <linux/ip.h>
#include <linux/delay.h>
#include <linux/crc32.h>
#include <linux/dma-mapping.h>
#include <linux/debugfs.h>
#include <linux/sched.h>
#include <linux/seq_file.h>
#include <linux/mii.h>
#include <linux/slab.h>
#include <linux/dmi.h>
#include <linux/prefetch.h>
#include <asm/irq.h>

#include "skge.h"

#define DRV_NAME
#define DRV_VERSION

#define DEFAULT_TX_RING_SIZE
#define DEFAULT_RX_RING_SIZE
#define MAX_TX_RING_SIZE
#define TX_LOW_WATER
#define MAX_RX_RING_SIZE
#define RX_COPY_THRESHOLD
#define RX_BUF_SIZE
#define PHY_RETRIES
#define ETH_JUMBO_MTU
#define TX_WATCHDOG
#define BLINK_MS
#define LINK_HZ

#define SKGE_EEPROM_MAGIC


MODULE_DESCRIPTION();
MODULE_AUTHOR();
MODULE_LICENSE();
MODULE_VERSION();

static const u32 default_msg =;

static int debug =;	/* defaults above */
module_param(debug, int, 0);
MODULE_PARM_DESC();

static const struct pci_device_id skge_id_table[] =;
MODULE_DEVICE_TABLE(pci, skge_id_table);

static int skge_up(struct net_device *dev);
static int skge_down(struct net_device *dev);
static void skge_phy_reset(struct skge_port *skge);
static void skge_tx_clean(struct net_device *dev);
static int xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val);
static int gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val);
static void genesis_get_stats(struct skge_port *skge, u64 *data);
static void yukon_get_stats(struct skge_port *skge, u64 *data);
static void yukon_init(struct skge_hw *hw, int port);
static void genesis_mac_init(struct skge_hw *hw, int port);
static void genesis_link_up(struct skge_port *skge);
static void skge_set_multicast(struct net_device *dev);
static irqreturn_t skge_intr(int irq, void *dev_id);

/* Avoid conditionals by using array */
static const int txqaddr[] =;
static const int rxqaddr[] =;
static const u32 rxirqmask[] =;
static const u32 txirqmask[] =;
static const u32 napimask[] =;
static const u32 portmask[] =;

static inline bool is_genesis(const struct skge_hw *hw)
{}

static int skge_get_regs_len(struct net_device *dev)
{}

/*
 * Returns copy of whole control register region
 * Note: skip RAM address register because accessing it will
 * 	 cause bus hangs!
 */
static void skge_get_regs(struct net_device *dev, struct ethtool_regs *regs,
			  void *p)
{}

/* Wake on Lan only supported on Yukon chips with rev 1 or above */
static u32 wol_supported(const struct skge_hw *hw)
{}

static void skge_wol_init(struct skge_port *skge)
{}

static void skge_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{}

static int skge_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{}

/* Determine supported/advertised modes based on hardware.
 * Note: ethtool ADVERTISED_xxx == SUPPORTED_xxx
 */
static u32 skge_supported_modes(const struct skge_hw *hw)
{}

static int skge_get_link_ksettings(struct net_device *dev,
				   struct ethtool_link_ksettings *cmd)
{}

static int skge_set_link_ksettings(struct net_device *dev,
				   const struct ethtool_link_ksettings *cmd)
{}

static void skge_get_drvinfo(struct net_device *dev,
			     struct ethtool_drvinfo *info)
{}

static const struct skge_stat {} skge_stats[] =;

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

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

/* Use hardware MIB variables for critical path statistics and
 * transmit feedback not reported at interrupt.
 * Other errors are accounted for in interrupt handler.
 */
static struct net_device_stats *skge_get_stats(struct net_device *dev)
{}

static void skge_get_strings(struct net_device *dev, u32 stringset, u8 *data)
{}

static void skge_get_ring_param(struct net_device *dev,
				struct ethtool_ringparam *p,
				struct kernel_ethtool_ringparam *kernel_p,
				struct netlink_ext_ack *extack)
{}

static int skge_set_ring_param(struct net_device *dev,
			       struct ethtool_ringparam *p,
			       struct kernel_ethtool_ringparam *kernel_p,
			       struct netlink_ext_ack *extack)
{}

static u32 skge_get_msglevel(struct net_device *netdev)
{}

static void skge_set_msglevel(struct net_device *netdev, u32 value)
{}

static int skge_nway_reset(struct net_device *dev)
{}

static void skge_get_pauseparam(struct net_device *dev,
				struct ethtool_pauseparam *ecmd)
{}

static int skge_set_pauseparam(struct net_device *dev,
			       struct ethtool_pauseparam *ecmd)
{}

/* Chip internal frequency for clock calculations */
static inline u32 hwkhz(const struct skge_hw *hw)
{}

/* Chip HZ to microseconds */
static inline u32 skge_clk2usec(const struct skge_hw *hw, u32 ticks)
{}

/* Microseconds to chip HZ */
static inline u32 skge_usecs2clk(const struct skge_hw *hw, u32 usec)
{}

static int skge_get_coalesce(struct net_device *dev,
			     struct ethtool_coalesce *ecmd,
			     struct kernel_ethtool_coalesce *kernel_coal,
			     struct netlink_ext_ack *extack)
{}

/* Note: interrupt timer is per board, but can turn on/off per port */
static int skge_set_coalesce(struct net_device *dev,
			     struct ethtool_coalesce *ecmd,
			     struct kernel_ethtool_coalesce *kernel_coal,
			     struct netlink_ext_ack *extack)
{}

enum led_mode {};
static void skge_led(struct skge_port *skge, enum led_mode mode)
{}

/* blink LED's for finding board */
static int skge_set_phys_id(struct net_device *dev,
			    enum ethtool_phys_id_state state)
{}

static int skge_get_eeprom_len(struct net_device *dev)
{}

static u32 skge_vpd_read(struct pci_dev *pdev, int cap, u16 offset)
{}

static void skge_vpd_write(struct pci_dev *pdev, int cap, u16 offset, u32 val)
{}

static int skge_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
			   u8 *data)
{}

static int skge_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
			   u8 *data)
{}

static const struct ethtool_ops skge_ethtool_ops =;

/*
 * Allocate ring elements and chain them together
 * One-to-one association of board descriptors with ring elements
 */
static int skge_ring_alloc(struct skge_ring *ring, void *vaddr, u32 base)
{}

/* Allocate and setup a new buffer for receiving */
static int skge_rx_setup(struct skge_port *skge, struct skge_element *e,
			 struct sk_buff *skb, unsigned int bufsize)
{}

/* Resume receiving using existing skb,
 * Note: DMA address is not changed by chip.
 * 	 MTU not changed while receiver active.
 */
static inline void skge_rx_reuse(struct skge_element *e, unsigned int size)
{}


/* Free all  buffers in receive ring, assumes receiver stopped */
static void skge_rx_clean(struct skge_port *skge)
{}


/* Allocate buffers for receive ring
 * For receive:  to_clean is next received frame.
 */
static int skge_rx_fill(struct net_device *dev)
{}

static const char *skge_pause(enum pause_status status)
{}


static void skge_link_up(struct skge_port *skge)
{}

static void skge_link_down(struct skge_port *skge)
{}

static void xm_link_down(struct skge_hw *hw, int port)
{}

static int __xm_phy_read(struct skge_hw *hw, int port, u16 reg, u16 *val)
{}

static u16 xm_phy_read(struct skge_hw *hw, int port, u16 reg)
{}

static int xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val)
{}

static void genesis_init(struct skge_hw *hw)
{}

static void genesis_reset(struct skge_hw *hw, int port)
{}

/* Convert mode to MII values  */
static const u16 phy_pause_map[] =;

/* special defines for FIBER (88E1011S only) */
static const u16 fiber_pause_map[] =;


/* Check status of Broadcom phy link */
static void bcom_check_link(struct skge_hw *hw, int port)
{}

/* Broadcom 5400 only supports giagabit! SysKonnect did not put an additional
 * Phy on for 100 or 10Mbit operation
 */
static void bcom_phy_init(struct skge_port *skge)
{}

static void xm_phy_init(struct skge_port *skge)
{}

static int xm_check_link(struct net_device *dev)
{}

/* Poll to check for link coming up.
 *
 * Since internal PHY is wired to a level triggered pin, can't
 * get an interrupt when carrier is detected, need to poll for
 * link coming up.
 */
static void xm_link_timer(struct timer_list *t)
{}

static void genesis_mac_init(struct skge_hw *hw, int port)
{}

static void genesis_stop(struct skge_port *skge)
{}


static void genesis_get_stats(struct skge_port *skge, u64 *data)
{}

static void genesis_mac_intr(struct skge_hw *hw, int port)
{}

static void genesis_link_up(struct skge_port *skge)
{}


static inline void bcom_phy_intr(struct skge_port *skge)
{}

static int gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val)
{}

static int __gm_phy_read(struct skge_hw *hw, int port, u16 reg, u16 *val)
{}

static u16 gm_phy_read(struct skge_hw *hw, int port, u16 reg)
{}

/* Marvell Phy Initialization */
static void yukon_init(struct skge_hw *hw, int port)
{}

static void yukon_reset(struct skge_hw *hw, int port)
{}

/* Apparently, early versions of Yukon-Lite had wrong chip_id? */
static int is_yukon_lite_a0(struct skge_hw *hw)
{}

static void yukon_mac_init(struct skge_hw *hw, int port)
{}

/* Go into power down mode */
static void yukon_suspend(struct skge_hw *hw, int port)
{}

static void yukon_stop(struct skge_port *skge)
{}

static void yukon_get_stats(struct skge_port *skge, u64 *data)
{}

static void yukon_mac_intr(struct skge_hw *hw, int port)
{}

static u16 yukon_speed(const struct skge_hw *hw, u16 aux)
{}

static void yukon_link_up(struct skge_port *skge)
{}

static void yukon_link_down(struct skge_port *skge)
{}

static void yukon_phy_intr(struct skge_port *skge)
{}

static void skge_phy_reset(struct skge_port *skge)
{}

/* Basic MII support */
static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{}

static void skge_ramset(struct skge_hw *hw, u16 q, u32 start, size_t len)
{}

/* Setup Bus Memory Interface */
static void skge_qset(struct skge_port *skge, u16 q,
		      const struct skge_element *e)
{}

static int skge_up(struct net_device *dev)
{}

/* stop receiver */
static void skge_rx_stop(struct skge_hw *hw, int port)
{}

static int skge_down(struct net_device *dev)
{}

static inline int skge_avail(const struct skge_ring *ring)
{}

static netdev_tx_t skge_xmit_frame(struct sk_buff *skb,
				   struct net_device *dev)
{}


/* Free resources associated with this reing element */
static inline void skge_tx_unmap(struct pci_dev *pdev, struct skge_element *e,
				 u32 control)
{}

/* Free all buffers in transmit ring */
static void skge_tx_clean(struct net_device *dev)
{}

static void skge_tx_timeout(struct net_device *dev, unsigned int txqueue)
{}

static int skge_change_mtu(struct net_device *dev, int new_mtu)
{}

static const u8 pause_mc_addr[ETH_ALEN] =;

static void genesis_add_filter(u8 filter[8], const u8 *addr)
{}

static void genesis_set_multicast(struct net_device *dev)
{}

static void yukon_add_filter(u8 filter[8], const u8 *addr)
{}

static void yukon_set_multicast(struct net_device *dev)
{}

static inline u16 phy_length(const struct skge_hw *hw, u32 status)
{}

static inline int bad_phy_status(const struct skge_hw *hw, u32 status)
{}

static void skge_set_multicast(struct net_device *dev)
{}


/* Get receive buffer from descriptor.
 * Handles copy of small buffers and reallocation failures
 */
static struct sk_buff *skge_rx_get(struct net_device *dev,
				   struct skge_element *e,
				   u32 control, u32 status, u16 csum)
{}

/* Free all buffers in Tx ring which are no longer owned by device */
static void skge_tx_done(struct net_device *dev)
{}

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

/* Parity errors seem to happen when Genesis is connected to a switch
 * with no other ports present. Heartbeat error??
 */
static void skge_mac_parity(struct skge_hw *hw, int port)
{}

static void skge_mac_intr(struct skge_hw *hw, int port)
{}

/* Handle device specific framing and timeout interrupts */
static void skge_error_irq(struct skge_hw *hw)
{}

/*
 * Interrupt from PHY are handled in tasklet (softirq)
 * because accessing phy registers requires spin wait which might
 * cause excess interrupt latency.
 */
static void skge_extirq(struct tasklet_struct *t)
{}

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

#ifdef CONFIG_NET_POLL_CONTROLLER
static void skge_netpoll(struct net_device *dev)
{}
#endif

static int skge_set_mac_address(struct net_device *dev, void *p)
{}

static const struct {} skge_chips[] =;

static const char *skge_board_name(const struct skge_hw *hw)
{}


/*
 * Setup the board data structure, but don't bring up
 * the port(s)
 */
static int skge_reset(struct skge_hw *hw)
{}


#ifdef CONFIG_SKGE_DEBUG

static struct dentry *skge_debug;

static int skge_debug_show(struct seq_file *seq, void *v)
{}
DEFINE_SHOW_ATTRIBUTE();

/*
 * Use network device events to create/remove/rename
 * debugfs file entries
 */
static int skge_device_event(struct notifier_block *unused,
			     unsigned long event, void *ptr)
{}

static struct notifier_block skge_notifier =;


static __init void skge_debug_init(void)
{}

static __exit void skge_debug_cleanup(void)
{}

#else
#define skge_debug_init
#define skge_debug_cleanup
#endif

static const struct net_device_ops skge_netdev_ops =;


/* Initialize network device */
static struct net_device *skge_devinit(struct skge_hw *hw, int port,
				       int highmem)
{}

static void skge_show_addr(struct net_device *dev)
{}

static int only_32bit_dma;

static int skge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{}

static void skge_remove(struct pci_dev *pdev)
{}

#ifdef CONFIG_PM_SLEEP
static int skge_suspend(struct device *dev)
{}

static int skge_resume(struct device *dev)
{}

static SIMPLE_DEV_PM_OPS(skge_pm_ops, skge_suspend, skge_resume);
#define SKGE_PM_OPS

#else

#define SKGE_PM_OPS
#endif /* CONFIG_PM_SLEEP */

static void skge_shutdown(struct pci_dev *pdev)
{}

static struct pci_driver skge_driver =;

static const struct dmi_system_id skge_32bit_dma_boards[] =;

static int __init skge_init_module(void)
{}

static void __exit skge_cleanup_module(void)
{}

module_init();
module_exit(skge_cleanup_module);