linux/drivers/net/ethernet/sfc/falcon/falcon.c

// SPDX-License-Identifier: GPL-2.0-only
/****************************************************************************
 * Driver for Solarflare network controllers and boards
 * Copyright 2005-2006 Fen Systems Ltd.
 * Copyright 2006-2013 Solarflare Communications Inc.
 */

#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/pci.h>
#include <linux/module.h>
#include <linux/seq_file.h>
#include <linux/i2c.h>
#include <linux/mii.h>
#include <linux/slab.h>
#include <linux/sched/signal.h>

#include "net_driver.h"
#include "bitfield.h"
#include "efx.h"
#include "nic.h"
#include "farch_regs.h"
#include "io.h"
#include "phy.h"
#include "workarounds.h"
#include "selftest.h"
#include "mdio_10g.h"

/* Hardware control for SFC4000 (aka Falcon). */

/**************************************************************************
 *
 * NIC stats
 *
 **************************************************************************
 */

#define FALCON_MAC_STATS_SIZE

#define XgRxOctets_offset
#define XgRxOctets_WIDTH
#define XgRxOctetsOK_offset
#define XgRxOctetsOK_WIDTH
#define XgRxPkts_offset
#define XgRxPkts_WIDTH
#define XgRxPktsOK_offset
#define XgRxPktsOK_WIDTH
#define XgRxBroadcastPkts_offset
#define XgRxBroadcastPkts_WIDTH
#define XgRxMulticastPkts_offset
#define XgRxMulticastPkts_WIDTH
#define XgRxUnicastPkts_offset
#define XgRxUnicastPkts_WIDTH
#define XgRxUndersizePkts_offset
#define XgRxUndersizePkts_WIDTH
#define XgRxOversizePkts_offset
#define XgRxOversizePkts_WIDTH
#define XgRxJabberPkts_offset
#define XgRxJabberPkts_WIDTH
#define XgRxUndersizeFCSerrorPkts_offset
#define XgRxUndersizeFCSerrorPkts_WIDTH
#define XgRxDropEvents_offset
#define XgRxDropEvents_WIDTH
#define XgRxFCSerrorPkts_offset
#define XgRxFCSerrorPkts_WIDTH
#define XgRxAlignError_offset
#define XgRxAlignError_WIDTH
#define XgRxSymbolError_offset
#define XgRxSymbolError_WIDTH
#define XgRxInternalMACError_offset
#define XgRxInternalMACError_WIDTH
#define XgRxControlPkts_offset
#define XgRxControlPkts_WIDTH
#define XgRxPausePkts_offset
#define XgRxPausePkts_WIDTH
#define XgRxPkts64Octets_offset
#define XgRxPkts64Octets_WIDTH
#define XgRxPkts65to127Octets_offset
#define XgRxPkts65to127Octets_WIDTH
#define XgRxPkts128to255Octets_offset
#define XgRxPkts128to255Octets_WIDTH
#define XgRxPkts256to511Octets_offset
#define XgRxPkts256to511Octets_WIDTH
#define XgRxPkts512to1023Octets_offset
#define XgRxPkts512to1023Octets_WIDTH
#define XgRxPkts1024to15xxOctets_offset
#define XgRxPkts1024to15xxOctets_WIDTH
#define XgRxPkts15xxtoMaxOctets_offset
#define XgRxPkts15xxtoMaxOctets_WIDTH
#define XgRxLengthError_offset
#define XgRxLengthError_WIDTH
#define XgTxPkts_offset
#define XgTxPkts_WIDTH
#define XgTxOctets_offset
#define XgTxOctets_WIDTH
#define XgTxMulticastPkts_offset
#define XgTxMulticastPkts_WIDTH
#define XgTxBroadcastPkts_offset
#define XgTxBroadcastPkts_WIDTH
#define XgTxUnicastPkts_offset
#define XgTxUnicastPkts_WIDTH
#define XgTxControlPkts_offset
#define XgTxControlPkts_WIDTH
#define XgTxPausePkts_offset
#define XgTxPausePkts_WIDTH
#define XgTxPkts64Octets_offset
#define XgTxPkts64Octets_WIDTH
#define XgTxPkts65to127Octets_offset
#define XgTxPkts65to127Octets_WIDTH
#define XgTxPkts128to255Octets_offset
#define XgTxPkts128to255Octets_WIDTH
#define XgTxPkts256to511Octets_offset
#define XgTxPkts256to511Octets_WIDTH
#define XgTxPkts512to1023Octets_offset
#define XgTxPkts512to1023Octets_WIDTH
#define XgTxPkts1024to15xxOctets_offset
#define XgTxPkts1024to15xxOctets_WIDTH
#define XgTxPkts1519toMaxOctets_offset
#define XgTxPkts1519toMaxOctets_WIDTH
#define XgTxUndersizePkts_offset
#define XgTxUndersizePkts_WIDTH
#define XgTxOversizePkts_offset
#define XgTxOversizePkts_WIDTH
#define XgTxNonTcpUdpPkt_offset
#define XgTxNonTcpUdpPkt_WIDTH
#define XgTxMacSrcErrPkt_offset
#define XgTxMacSrcErrPkt_WIDTH
#define XgTxIpSrcErrPkt_offset
#define XgTxIpSrcErrPkt_WIDTH
#define XgDmaDone_offset
#define XgDmaDone_WIDTH

#define FALCON_XMAC_STATS_DMA_FLAG(efx)

#define FALCON_DMA_STAT(ext_name, hw_name)
#define FALCON_OTHER_STAT(ext_name)
#define GENERIC_SW_STAT(ext_name)

static const struct ef4_hw_stat_desc falcon_stat_desc[FALCON_STAT_COUNT] =;
static const unsigned long falcon_stat_mask[] =;

/**************************************************************************
 *
 * Basic SPI command set and bit definitions
 *
 *************************************************************************/

#define SPI_WRSR
#define SPI_WRITE
#define SPI_READ
#define SPI_WRDI
#define SPI_RDSR
#define SPI_WREN
#define SPI_SST_EWSR

#define SPI_STATUS_WPEN
#define SPI_STATUS_BP2
#define SPI_STATUS_BP1
#define SPI_STATUS_BP0
#define SPI_STATUS_WEN
#define SPI_STATUS_NRDY

/**************************************************************************
 *
 * Non-volatile memory layout
 *
 **************************************************************************
 */

/* SFC4000 flash is partitioned into:
 *     0-0x400       chip and board config (see struct falcon_nvconfig)
 *     0x400-0x8000  unused (or may contain VPD if EEPROM not present)
 *     0x8000-end    boot code (mapped to PCI expansion ROM)
 * SFC4000 small EEPROM (size < 0x400) is used for VPD only.
 * SFC4000 large EEPROM (size >= 0x400) is partitioned into:
 *     0-0x400       chip and board config
 *     configurable  VPD
 *     0x800-0x1800  boot config
 * Aside from the chip and board config, all of these are optional and may
 * be absent or truncated depending on the devices used.
 */
#define FALCON_NVCONFIG_END
#define FALCON_FLASH_BOOTCODE_START
#define FALCON_EEPROM_BOOTCONFIG_START
#define FALCON_EEPROM_BOOTCONFIG_END

/* Board configuration v2 (v1 is obsolete; later versions are compatible) */
struct falcon_nvconfig_board_v2 {} __packed;

/* Board configuration v3 extra information */
struct falcon_nvconfig_board_v3 {} __packed;

/* Bit numbers for spi_device_type */
#define SPI_DEV_TYPE_SIZE_LBN
#define SPI_DEV_TYPE_SIZE_WIDTH
#define SPI_DEV_TYPE_ADDR_LEN_LBN
#define SPI_DEV_TYPE_ADDR_LEN_WIDTH
#define SPI_DEV_TYPE_ERASE_CMD_LBN
#define SPI_DEV_TYPE_ERASE_CMD_WIDTH
#define SPI_DEV_TYPE_ERASE_SIZE_LBN
#define SPI_DEV_TYPE_ERASE_SIZE_WIDTH
#define SPI_DEV_TYPE_BLOCK_SIZE_LBN
#define SPI_DEV_TYPE_BLOCK_SIZE_WIDTH
#define SPI_DEV_TYPE_FIELD(type, field)

#define FALCON_NVCONFIG_OFFSET

#define FALCON_NVCONFIG_BOARD_MAGIC_NUM
struct falcon_nvconfig {} __packed;

/*************************************************************************/

static int falcon_reset_hw(struct ef4_nic *efx, enum reset_type method);
static void falcon_reconfigure_mac_wrapper(struct ef4_nic *efx);

static const unsigned int
/* "Large" EEPROM device: Atmel AT25640 or similar
 * 8 KB, 16-bit address, 32 B write block */
large_eeprom_type =,
/* Default flash device: Atmel AT25F1024
 * 128 KB, 24-bit address, 32 KB erase block, 256 B write block */
default_flash_type =;

/**************************************************************************
 *
 * I2C bus - this is a bit-bashing interface using GPIO pins
 * Note that it uses the output enables to tristate the outputs
 * SDA is the data pin and SCL is the clock
 *
 **************************************************************************
 */
static void falcon_setsda(void *data, int state)
{}

static void falcon_setscl(void *data, int state)
{}

static int falcon_getsda(void *data)
{}

static int falcon_getscl(void *data)
{}

static const struct i2c_algo_bit_data falcon_i2c_bit_operations =;

static void falcon_push_irq_moderation(struct ef4_channel *channel)
{}

static void falcon_deconfigure_mac_wrapper(struct ef4_nic *efx);

static void falcon_prepare_flush(struct ef4_nic *efx)
{}

/* Acknowledge a legacy interrupt from Falcon
 *
 * This acknowledges a legacy (not MSI) interrupt via INT_ACK_KER_REG.
 *
 * Due to SFC bug 3706 (silicon revision <=A1) reads can be duplicated in the
 * BIU. Interrupt acknowledge is read sensitive so must write instead
 * (then read to ensure the BIU collector is flushed)
 *
 * NB most hardware supports MSI interrupts
 */
static inline void falcon_irq_ack_a1(struct ef4_nic *efx)
{}

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

/**************************************************************************
 *
 * RSS
 *
 **************************************************************************
 */
static int dummy_rx_push_rss_config(struct ef4_nic *efx, bool user,
				    const u32 *rx_indir_table)
{}

static int falcon_b0_rx_push_rss_config(struct ef4_nic *efx, bool user,
					const u32 *rx_indir_table)
{}

/**************************************************************************
 *
 * EEPROM/flash
 *
 **************************************************************************
 */

#define FALCON_SPI_MAX_LEN

static int falcon_spi_poll(struct ef4_nic *efx)
{}

/* Wait for SPI command completion */
static int falcon_spi_wait(struct ef4_nic *efx)
{}

static int
falcon_spi_cmd(struct ef4_nic *efx, const struct falcon_spi_device *spi,
	       unsigned int command, int address,
	       const void *in, void *out, size_t len)
{}

static inline u8
falcon_spi_munge_command(const struct falcon_spi_device *spi,
			 const u8 command, const unsigned int address)
{}

static int
falcon_spi_read(struct ef4_nic *efx, const struct falcon_spi_device *spi,
		loff_t start, size_t len, size_t *retlen, u8 *buffer)
{}

#ifdef CONFIG_SFC_FALCON_MTD

struct falcon_mtd_partition {};

#define to_falcon_mtd_partition(mtd)

static size_t
falcon_spi_write_limit(const struct falcon_spi_device *spi, size_t start)
{}

/* Wait up to 10 ms for buffered write completion */
static int
falcon_spi_wait_write(struct ef4_nic *efx, const struct falcon_spi_device *spi)
{}

static int
falcon_spi_write(struct ef4_nic *efx, const struct falcon_spi_device *spi,
		 loff_t start, size_t len, size_t *retlen, const u8 *buffer)
{}

static int
falcon_spi_slow_wait(struct falcon_mtd_partition *part, bool uninterruptible)
{}

static int
falcon_spi_unlock(struct ef4_nic *efx, const struct falcon_spi_device *spi)
{}

#define FALCON_SPI_VERIFY_BUF_LEN

static int
falcon_spi_erase(struct falcon_mtd_partition *part, loff_t start, size_t len)
{}

static void falcon_mtd_rename(struct ef4_mtd_partition *part)
{}

static int falcon_mtd_read(struct mtd_info *mtd, loff_t start,
			   size_t len, size_t *retlen, u8 *buffer)
{}

static int falcon_mtd_erase(struct mtd_info *mtd, loff_t start, size_t len)
{}

static int falcon_mtd_write(struct mtd_info *mtd, loff_t start,
			    size_t len, size_t *retlen, const u8 *buffer)
{}

static int falcon_mtd_sync(struct mtd_info *mtd)
{}

static int falcon_mtd_probe(struct ef4_nic *efx)
{}

#endif /* CONFIG_SFC_FALCON_MTD */

/**************************************************************************
 *
 * XMAC operations
 *
 **************************************************************************
 */

/* Configure the XAUI driver that is an output from Falcon */
static void falcon_setup_xaui(struct ef4_nic *efx)
{}

int falcon_reset_xaui(struct ef4_nic *efx)
{}

static void falcon_ack_status_intr(struct ef4_nic *efx)
{}

static bool falcon_xgxs_link_ok(struct ef4_nic *efx)
{}

static bool falcon_xmac_link_ok(struct ef4_nic *efx)
{}

static void falcon_reconfigure_xmac_core(struct ef4_nic *efx)
{}

static void falcon_reconfigure_xgxs_core(struct ef4_nic *efx)
{}


/* Try to bring up the Falcon side of the Falcon-Phy XAUI link */
static bool falcon_xmac_link_ok_retry(struct ef4_nic *efx, int tries)
{}

static bool falcon_xmac_check_fault(struct ef4_nic *efx)
{}

static int falcon_reconfigure_xmac(struct ef4_nic *efx)
{}

static void falcon_poll_xmac(struct ef4_nic *efx)
{}

/**************************************************************************
 *
 * MAC wrapper
 *
 **************************************************************************
 */

static void falcon_push_multicast_hash(struct ef4_nic *efx)
{}

static void falcon_reset_macs(struct ef4_nic *efx)
{}

static void falcon_drain_tx_fifo(struct ef4_nic *efx)
{}

static void falcon_deconfigure_mac_wrapper(struct ef4_nic *efx)
{}

static void falcon_reconfigure_mac_wrapper(struct ef4_nic *efx)
{}

static void falcon_stats_request(struct ef4_nic *efx)
{}

static void falcon_stats_complete(struct ef4_nic *efx)
{}

static void falcon_stats_timer_func(struct timer_list *t)
{}

static bool falcon_loopback_link_poll(struct ef4_nic *efx)
{}

static int falcon_reconfigure_port(struct ef4_nic *efx)
{}

/* TX flow control may automatically turn itself off if the link
 * partner (intermittently) stops responding to pause frames. There
 * isn't any indication that this has happened, so the best we do is
 * leave it up to the user to spot this and fix it by cycling transmit
 * flow control on this end.
 */

static void falcon_a1_prepare_enable_fc_tx(struct ef4_nic *efx)
{}

static void falcon_b0_prepare_enable_fc_tx(struct ef4_nic *efx)
{}

/**************************************************************************
 *
 * PHY access via GMII
 *
 **************************************************************************
 */

/* Wait for GMII access to complete */
static int falcon_gmii_wait(struct ef4_nic *efx)
{}

/* Write an MDIO register of a PHY connected to Falcon. */
static int falcon_mdio_write(struct net_device *net_dev,
			     int prtad, int devad, u16 addr, u16 value)
{}

/* Read an MDIO register of a PHY connected to Falcon. */
static int falcon_mdio_read(struct net_device *net_dev,
			    int prtad, int devad, u16 addr)
{}

/* This call is responsible for hooking in the MAC and PHY operations */
static int falcon_probe_port(struct ef4_nic *efx)
{}

static void falcon_remove_port(struct ef4_nic *efx)
{}

/* Global events are basically PHY events */
static bool
falcon_handle_global_event(struct ef4_channel *channel, ef4_qword_t *event)
{}

/**************************************************************************
 *
 * Falcon test code
 *
 **************************************************************************/

static int
falcon_read_nvram(struct ef4_nic *efx, struct falcon_nvconfig *nvconfig_out)
{}

static int falcon_test_nvram(struct ef4_nic *efx)
{}

static const struct ef4_farch_register_test falcon_b0_register_tests[] =;

static int
falcon_b0_test_chip(struct ef4_nic *efx, struct ef4_self_tests *tests)
{}

/**************************************************************************
 *
 * Device reset
 *
 **************************************************************************
 */

static enum reset_type falcon_map_reset_reason(enum reset_type reason)
{}

static int falcon_map_reset_flags(u32 *flags)
{}

/* Resets NIC to known state.  This routine must be called in process
 * context and is allowed to sleep. */
static int __falcon_reset_hw(struct ef4_nic *efx, enum reset_type method)
{}

static int falcon_reset_hw(struct ef4_nic *efx, enum reset_type method)
{}

static void falcon_monitor(struct ef4_nic *efx)
{}

/* Zeroes out the SRAM contents.  This routine must be called in
 * process context and is allowed to sleep.
 */
static int falcon_reset_sram(struct ef4_nic *efx)
{}

static void falcon_spi_device_init(struct ef4_nic *efx,
				  struct falcon_spi_device *spi_device,
				  unsigned int device_id, u32 device_type)
{}

/* Extract non-volatile configuration */
static int falcon_probe_nvconfig(struct ef4_nic *efx)
{}

static int falcon_dimension_resources(struct ef4_nic *efx)
{}

/* Probe all SPI devices on the NIC */
static void falcon_probe_spi_devices(struct ef4_nic *efx)
{}

static unsigned int falcon_a1_mem_map_size(struct ef4_nic *efx)
{}

static unsigned int falcon_b0_mem_map_size(struct ef4_nic *efx)
{}

static int falcon_probe_nic(struct ef4_nic *efx)
{}

static void falcon_init_rx_cfg(struct ef4_nic *efx)
{}

/* This call performs hardware-specific global initialisation, such as
 * defining the descriptor cache sizes and number of RSS channels.
 * It does not set up any buffers, descriptor rings or event queues.
 */
static int falcon_init_nic(struct ef4_nic *efx)
{}

static void falcon_remove_nic(struct ef4_nic *efx)
{}

static size_t falcon_describe_nic_stats(struct ef4_nic *efx, u8 *names)
{}

static size_t falcon_update_nic_stats(struct ef4_nic *efx, u64 *full_stats,
				      struct rtnl_link_stats64 *core_stats)
{}

void falcon_start_nic_stats(struct ef4_nic *efx)
{}

/* We don't acutally pull stats on falcon. Wait 10ms so that
 * they arrive when we call this just after start_stats
 */
static void falcon_pull_nic_stats(struct ef4_nic *efx)
{}

void falcon_stop_nic_stats(struct ef4_nic *efx)
{}

static void falcon_set_id_led(struct ef4_nic *efx, enum ef4_led_mode mode)
{}

/**************************************************************************
 *
 * Wake on LAN
 *
 **************************************************************************
 */

static void falcon_get_wol(struct ef4_nic *efx, struct ethtool_wolinfo *wol)
{}

static int falcon_set_wol(struct ef4_nic *efx, u32 type)
{}

/**************************************************************************
 *
 * Revision-dependent attributes used by efx.c and nic.c
 *
 **************************************************************************
 */

const struct ef4_nic_type falcon_a1_nic_type =;

const struct ef4_nic_type falcon_b0_nic_type =;