// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright(c) 2006 - 2007 Atheros Corporation. All rights reserved. * Copyright(c) 2007 - 2008 Chris Snook <[email protected]> * * Derived from Intel e1000 driver * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. */ #include <linux/atomic.h> #include <linux/crc32.h> #include <linux/dma-mapping.h> #include <linux/etherdevice.h> #include <linux/ethtool.h> #include <linux/hardirq.h> #include <linux/if_vlan.h> #include <linux/in.h> #include <linux/interrupt.h> #include <linux/ip.h> #include <linux/irqflags.h> #include <linux/irqreturn.h> #include <linux/mii.h> #include <linux/net.h> #include <linux/netdevice.h> #include <linux/pci.h> #include <linux/pci_ids.h> #include <linux/pm.h> #include <linux/skbuff.h> #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/string.h> #include <linux/tcp.h> #include <linux/timer.h> #include <linux/types.h> #include <linux/workqueue.h> #include "atl2.h" static const char atl2_driver_name[] = …; static const struct ethtool_ops atl2_ethtool_ops; MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …; /* * atl2_pci_tbl - PCI Device ID Table */ static const struct pci_device_id atl2_pci_tbl[] = …; MODULE_DEVICE_TABLE(pci, atl2_pci_tbl); static void atl2_check_options(struct atl2_adapter *adapter); /** * atl2_sw_init - Initialize general software structures (struct atl2_adapter) * @adapter: board private structure to initialize * * atl2_sw_init initializes the Adapter private data structure. * Fields are initialized based on PCI device information and * OS network device settings (MTU size). */ static int atl2_sw_init(struct atl2_adapter *adapter) { … } /** * atl2_set_multi - Multicast and Promiscuous mode set * @netdev: network interface device structure * * The set_multi entry point is called whenever the multicast address * list or the network interface flags are updated. This routine is * responsible for configuring the hardware for proper multicast, * promiscuous mode, and all-multi behavior. */ static void atl2_set_multi(struct net_device *netdev) { … } static void init_ring_ptrs(struct atl2_adapter *adapter) { … } /** * atl2_configure - Configure Transmit&Receive Unit after Reset * @adapter: board private structure * * Configure the Tx /Rx unit of the MAC after a reset. */ static int atl2_configure(struct atl2_adapter *adapter) { … } /** * atl2_setup_ring_resources - allocate Tx / RX descriptor resources * @adapter: board private structure * * Return 0 on success, negative on failure */ static s32 atl2_setup_ring_resources(struct atl2_adapter *adapter) { … } /** * atl2_irq_enable - Enable default interrupt generation settings * @adapter: board private structure */ static inline void atl2_irq_enable(struct atl2_adapter *adapter) { … } /** * atl2_irq_disable - Mask off interrupt generation on the NIC * @adapter: board private structure */ static inline void atl2_irq_disable(struct atl2_adapter *adapter) { … } static void __atl2_vlan_mode(netdev_features_t features, u32 *ctrl) { … } static void atl2_vlan_mode(struct net_device *netdev, netdev_features_t features) { … } static void atl2_restore_vlan(struct atl2_adapter *adapter) { … } static netdev_features_t atl2_fix_features(struct net_device *netdev, netdev_features_t features) { … } static int atl2_set_features(struct net_device *netdev, netdev_features_t features) { … } static void atl2_intr_rx(struct atl2_adapter *adapter) { … } static void atl2_intr_tx(struct atl2_adapter *adapter) { … } static void atl2_check_for_link(struct atl2_adapter *adapter) { … } static inline void atl2_clear_phy_int(struct atl2_adapter *adapter) { … } /** * atl2_intr - Interrupt Handler * @irq: interrupt number * @data: pointer to a network interface device structure */ static irqreturn_t atl2_intr(int irq, void *data) { … } static int atl2_request_irq(struct atl2_adapter *adapter) { … } /** * atl2_free_ring_resources - Free Tx / RX descriptor Resources * @adapter: board private structure * * Free all transmit software resources */ static void atl2_free_ring_resources(struct atl2_adapter *adapter) { … } /** * atl2_open - Called when a network interface is made active * @netdev: network interface device structure * * Returns 0 on success, negative value on failure * * The open entry point is called when a network interface is made * active by the system (IFF_UP). At this point all resources needed * for transmit and receive operations are allocated, the interrupt * handler is registered with the OS, the watchdog timer is started, * and the stack is notified that the interface is ready. */ static int atl2_open(struct net_device *netdev) { … } static void atl2_down(struct atl2_adapter *adapter) { … } static void atl2_free_irq(struct atl2_adapter *adapter) { … } /** * atl2_close - Disables a network interface * @netdev: network interface device structure * * Returns 0, this is not allowed to fail * * The close entry point is called when an interface is de-activated * by the OS. The hardware is still under the drivers control, but * needs to be disabled. A global MAC reset is issued to stop the * hardware, and all transmit and receive resources are freed. */ static int atl2_close(struct net_device *netdev) { … } static inline int TxsFreeUnit(struct atl2_adapter *adapter) { … } static inline int TxdFreeBytes(struct atl2_adapter *adapter) { … } static netdev_tx_t atl2_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { … } /** * atl2_change_mtu - Change the Maximum Transfer Unit * @netdev: network interface device structure * @new_mtu: new value for maximum frame size * * Returns 0 on success, negative on failure */ static int atl2_change_mtu(struct net_device *netdev, int new_mtu) { … } /** * atl2_set_mac - Change the Ethernet Address of the NIC * @netdev: network interface device structure * @p: pointer to an address structure * * Returns 0 on success, negative on failure */ static int atl2_set_mac(struct net_device *netdev, void *p) { … } static int atl2_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) { … } static int atl2_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) { … } /** * atl2_tx_timeout - Respond to a Tx Hang * @netdev: network interface device structure * @txqueue: index of the hanging transmit queue */ static void atl2_tx_timeout(struct net_device *netdev, unsigned int txqueue) { … } /** * atl2_watchdog - Timer Call-back * @t: timer list containing a pointer to netdev cast into an unsigned long */ static void atl2_watchdog(struct timer_list *t) { … } /** * atl2_phy_config - Timer Call-back * @t: timer list containing a pointer to netdev cast into an unsigned long */ static void atl2_phy_config(struct timer_list *t) { … } static int atl2_up(struct atl2_adapter *adapter) { … } static void atl2_reinit_locked(struct atl2_adapter *adapter) { … } static void atl2_reset_task(struct work_struct *work) { … } static void atl2_setup_mac_ctrl(struct atl2_adapter *adapter) { … } static int atl2_check_link(struct atl2_adapter *adapter) { … } /** * atl2_link_chg_task - deal with link change event Out of interrupt context * @work: pointer to work struct with private info */ static void atl2_link_chg_task(struct work_struct *work) { … } static void atl2_setup_pcicmd(struct pci_dev *pdev) { … } #ifdef CONFIG_NET_POLL_CONTROLLER static void atl2_poll_controller(struct net_device *netdev) { … } #endif static const struct net_device_ops atl2_netdev_ops = …; /** * atl2_probe - Device Initialization Routine * @pdev: PCI device information struct * @ent: entry in atl2_pci_tbl * * Returns 0 on success, negative on failure * * atl2_probe initializes an adapter identified by a pci_dev structure. * The OS initialization, configuring of the adapter private structure, * and a hardware reset occur. */ static int atl2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { … } /** * atl2_remove - Device Removal Routine * @pdev: PCI device information struct * * atl2_remove is called by the PCI subsystem to alert the driver * that it should release a PCI device. The could be caused by a * Hot-Plug event, or because the driver is going to be removed from * memory. */ /* FIXME: write the original MAC address back in case it was changed from a * BIOS-set value, as in atl1 -- CHS */ static void atl2_remove(struct pci_dev *pdev) { … } static int atl2_suspend(struct pci_dev *pdev, pm_message_t state) { … } #ifdef CONFIG_PM static int atl2_resume(struct pci_dev *pdev) { … } #endif static void atl2_shutdown(struct pci_dev *pdev) { … } static struct pci_driver atl2_driver = …; module_pci_driver(…) …; static void atl2_read_pci_cfg(struct atl2_hw *hw, u32 reg, u16 *value) { … } static void atl2_write_pci_cfg(struct atl2_hw *hw, u32 reg, u16 *value) { … } static int atl2_get_link_ksettings(struct net_device *netdev, struct ethtool_link_ksettings *cmd) { … } static int atl2_set_link_ksettings(struct net_device *netdev, const struct ethtool_link_ksettings *cmd) { … } static u32 atl2_get_msglevel(struct net_device *netdev) { … } /* * It's sane for this to be empty, but we might want to take advantage of this. */ static void atl2_set_msglevel(struct net_device *netdev, u32 data) { … } static int atl2_get_regs_len(struct net_device *netdev) { … } static void atl2_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *p) { … } static int atl2_get_eeprom_len(struct net_device *netdev) { … } static int atl2_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, u8 *bytes) { … } static int atl2_set_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, u8 *bytes) { … } static void atl2_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) { … } static void atl2_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) { … } static int atl2_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) { … } static int atl2_nway_reset(struct net_device *netdev) { … } static const struct ethtool_ops atl2_ethtool_ops = …; #define LBYTESWAP(a) … #define LONGSWAP(a) … #define SHORTSWAP(a) … /* * Reset the transmit and receive units; mask and clear all interrupts. * * hw - Struct containing variables accessed by shared code * return : 0 or idle status (if error) */ static s32 atl2_reset_hw(struct atl2_hw *hw) { … } #define CUSTOM_SPI_CS_SETUP … #define CUSTOM_SPI_CLK_HI … #define CUSTOM_SPI_CLK_LO … #define CUSTOM_SPI_CS_HOLD … #define CUSTOM_SPI_CS_HI … static struct atl2_spi_flash_dev flash_table[] = …; static bool atl2_spi_read(struct atl2_hw *hw, u32 addr, u32 *buf) { … } /* * get_permanent_address * return 0 if get valid mac address, */ static int get_permanent_address(struct atl2_hw *hw) { … } /* * Reads the adapter's MAC address from the EEPROM * * hw - Struct containing variables accessed by shared code */ static s32 atl2_read_mac_addr(struct atl2_hw *hw) { … } /* * Hashes an address to determine its location in the multicast table * * hw - Struct containing variables accessed by shared code * mc_addr - the multicast address to hash * * atl2_hash_mc_addr * purpose * set hash value for a multicast address * hash calcu processing : * 1. calcu 32bit CRC for multicast address * 2. reverse crc with MSB to LSB */ static u32 atl2_hash_mc_addr(struct atl2_hw *hw, u8 *mc_addr) { … } /* * Sets the bit in the multicast table corresponding to the hash value. * * hw - Struct containing variables accessed by shared code * hash_value - Multicast address hash value */ static void atl2_hash_set(struct atl2_hw *hw, u32 hash_value) { … } /* * atl2_init_pcie - init PCIE module */ static void atl2_init_pcie(struct atl2_hw *hw) { … } static void atl2_init_flash_opcode(struct atl2_hw *hw) { … } /******************************************************************** * Performs basic configuration of the adapter. * * hw - Struct containing variables accessed by shared code * Assumes that the controller has previously been reset and is in a * post-reset uninitialized state. Initializes multicast table, * and Calls routines to setup link * Leaves the transmit and receive units disabled and uninitialized. ********************************************************************/ static s32 atl2_init_hw(struct atl2_hw *hw) { … } /* * Detects the current speed and duplex settings of the hardware. * * hw - Struct containing variables accessed by shared code * speed - Speed of the connection * duplex - Duplex setting of the connection */ static s32 atl2_get_speed_and_duplex(struct atl2_hw *hw, u16 *speed, u16 *duplex) { … } /* * Reads the value from a PHY register * hw - Struct containing variables accessed by shared code * reg_addr - address of the PHY register to read */ static s32 atl2_read_phy_reg(struct atl2_hw *hw, u16 reg_addr, u16 *phy_data) { … } /* * Writes a value to a PHY register * hw - Struct containing variables accessed by shared code * reg_addr - address of the PHY register to write * data - data to write to the PHY */ static s32 atl2_write_phy_reg(struct atl2_hw *hw, u32 reg_addr, u16 phy_data) { … } /* * Configures PHY autoneg and flow control advertisement settings * * hw - Struct containing variables accessed by shared code */ static s32 atl2_phy_setup_autoneg_adv(struct atl2_hw *hw) { … } /* * Resets the PHY and make all config validate * * hw - Struct containing variables accessed by shared code * * Sets bit 15 and 12 of the MII Control regiser (for F001 bug) */ static s32 atl2_phy_commit(struct atl2_hw *hw) { … } static s32 atl2_phy_init(struct atl2_hw *hw) { … } static void atl2_set_mac_addr(struct atl2_hw *hw) { … } /* * check_eeprom_exist * return 0 if eeprom exist */ static int atl2_check_eeprom_exist(struct atl2_hw *hw) { … } /* FIXME: This doesn't look right. -- CHS */ static bool atl2_write_eeprom(struct atl2_hw *hw, u32 offset, u32 value) { … } static bool atl2_read_eeprom(struct atl2_hw *hw, u32 Offset, u32 *pValue) { … } static void atl2_force_ps(struct atl2_hw *hw) { … } /* This is the only thing that needs to be changed to adjust the * maximum number of ports that the driver can manage. */ #define ATL2_MAX_NIC … #define OPTION_UNSET … #define OPTION_DISABLED … #define OPTION_ENABLED … /* All parameters are treated the same, as an integer array of values. * This macro just reduces the need to repeat the same declaration code * over and over (plus this helps to avoid typo bugs). */ #define ATL2_PARAM_INIT … #ifndef module_param_array /* Module Parameters are always initialized to -1, so that the driver * can tell the difference between no user specified value or the * user asking for the default value. * The true default values are loaded in when atl2_check_options is called. * * This is a GCC extension to ANSI C. * See the item "Labeled Elements in Initializers" in the section * "Extensions to the C Language Family" of the GCC documentation. */ #define ATL2_PARAM … #else #define ATL2_PARAM(X, desc) … #endif /* * Transmit Memory Size * Valid Range: 64-2048 * Default Value: 128 */ #define ATL2_MIN_TX_MEMSIZE … #define ATL2_MAX_TX_MEMSIZE … #define ATL2_DEFAULT_TX_MEMSIZE … ATL2_PARAM(TxMemSize, "Bytes of Transmit Memory"); /* * Receive Memory Block Count * Valid Range: 16-512 * Default Value: 128 */ #define ATL2_MIN_RXD_COUNT … #define ATL2_MAX_RXD_COUNT … #define ATL2_DEFAULT_RXD_COUNT … ATL2_PARAM(RxMemBlock, "Number of receive memory block"); /* * User Specified MediaType Override * * Valid Range: 0-5 * - 0 - auto-negotiate at all supported speeds * - 1 - only link at 1000Mbps Full Duplex * - 2 - only link at 100Mbps Full Duplex * - 3 - only link at 100Mbps Half Duplex * - 4 - only link at 10Mbps Full Duplex * - 5 - only link at 10Mbps Half Duplex * Default Value: 0 */ ATL2_PARAM(MediaType, "MediaType Select"); /* * Interrupt Moderate Timer in units of 2048 ns (~2 us) * Valid Range: 10-65535 * Default Value: 45000(90ms) */ #define INT_MOD_DEFAULT_CNT … #define INT_MOD_MAX_CNT … #define INT_MOD_MIN_CNT … ATL2_PARAM(IntModTimer, "Interrupt Moderator Timer"); /* * FlashVendor * Valid Range: 0-2 * 0 - Atmel * 1 - SST * 2 - ST */ ATL2_PARAM(FlashVendor, "SPI Flash Vendor"); #define AUTONEG_ADV_DEFAULT … #define AUTONEG_ADV_MASK … #define FLOW_CONTROL_DEFAULT … #define FLASH_VENDOR_DEFAULT … #define FLASH_VENDOR_MIN … #define FLASH_VENDOR_MAX … struct atl2_option { … }; static int atl2_validate_option(int *value, struct atl2_option *opt) { … } /** * atl2_check_options - Range Checking for Command Line Parameters * @adapter: board private structure * * This routine checks all command line parameters for valid user * input. If an invalid value is given, or if no user specified * value exists, a default value is used. The final value is stored * in a variable in the adapter structure. */ static void atl2_check_options(struct atl2_adapter *adapter) { … }