cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

atlx.c (7438B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/* atlx.c -- common functions for Attansic network drivers
      3 *
      4 * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
      5 * Copyright(c) 2006 - 2007 Chris Snook <csnook@redhat.com>
      6 * Copyright(c) 2006 - 2008 Jay Cliburn <jcliburn@gmail.com>
      7 * Copyright(c) 2007 Atheros Corporation. All rights reserved.
      8 *
      9 * Derived from Intel e1000 driver
     10 * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
     11 */
     12
     13/* Including this file like a header is a temporary hack, I promise. -- CHS */
     14#ifndef ATLX_C
     15#define ATLX_C
     16
     17#include <linux/device.h>
     18#include <linux/errno.h>
     19#include <linux/etherdevice.h>
     20#include <linux/if.h>
     21#include <linux/netdevice.h>
     22#include <linux/socket.h>
     23#include <linux/sockios.h>
     24#include <linux/spinlock.h>
     25#include <linux/string.h>
     26#include <linux/types.h>
     27#include <linux/workqueue.h>
     28
     29#include "atlx.h"
     30
     31static s32 atlx_read_phy_reg(struct atl1_hw *hw, u16 reg_addr, u16 *phy_data);
     32static u32 atlx_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr);
     33static void atlx_set_mac_addr(struct atl1_hw *hw);
     34
     35static struct atlx_spi_flash_dev flash_table[] = {
     36/*	MFR_NAME  WRSR  READ  PRGM  WREN  WRDI  RDSR  RDID  SEC_ERS CHIP_ERS */
     37	{"Atmel", 0x00, 0x03, 0x02, 0x06, 0x04, 0x05, 0x15, 0x52,   0x62},
     38	{"SST",   0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0x90, 0x20,   0x60},
     39	{"ST",    0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0xAB, 0xD8,   0xC7},
     40};
     41
     42static int atlx_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
     43{
     44	switch (cmd) {
     45	case SIOCGMIIPHY:
     46	case SIOCGMIIREG:
     47	case SIOCSMIIREG:
     48		return atlx_mii_ioctl(netdev, ifr, cmd);
     49	default:
     50		return -EOPNOTSUPP;
     51	}
     52}
     53
     54/**
     55 * atlx_set_mac - Change the Ethernet Address of the NIC
     56 * @netdev: network interface device structure
     57 * @p: pointer to an address structure
     58 *
     59 * Returns 0 on success, negative on failure
     60 */
     61static int atlx_set_mac(struct net_device *netdev, void *p)
     62{
     63	struct atlx_adapter *adapter = netdev_priv(netdev);
     64	struct sockaddr *addr = p;
     65
     66	if (netif_running(netdev))
     67		return -EBUSY;
     68
     69	if (!is_valid_ether_addr(addr->sa_data))
     70		return -EADDRNOTAVAIL;
     71
     72	eth_hw_addr_set(netdev, addr->sa_data);
     73	memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
     74
     75	atlx_set_mac_addr(&adapter->hw);
     76	return 0;
     77}
     78
     79static void atlx_check_for_link(struct atlx_adapter *adapter)
     80{
     81	struct net_device *netdev = adapter->netdev;
     82	u16 phy_data = 0;
     83
     84	spin_lock(&adapter->lock);
     85	adapter->phy_timer_pending = false;
     86	atlx_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
     87	atlx_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
     88	spin_unlock(&adapter->lock);
     89
     90	/* notify upper layer link down ASAP */
     91	if (!(phy_data & BMSR_LSTATUS)) {
     92		/* Link Down */
     93		if (netif_carrier_ok(netdev)) {
     94			/* old link state: Up */
     95			dev_info(&adapter->pdev->dev, "%s link is down\n",
     96				netdev->name);
     97			adapter->link_speed = SPEED_0;
     98			netif_carrier_off(netdev);
     99		}
    100	}
    101	schedule_work(&adapter->link_chg_task);
    102}
    103
    104/**
    105 * atlx_set_multi - Multicast and Promiscuous mode set
    106 * @netdev: network interface device structure
    107 *
    108 * The set_multi entry point is called whenever the multicast address
    109 * list or the network interface flags are updated.  This routine is
    110 * responsible for configuring the hardware for proper multicast,
    111 * promiscuous mode, and all-multi behavior.
    112 */
    113static void atlx_set_multi(struct net_device *netdev)
    114{
    115	struct atlx_adapter *adapter = netdev_priv(netdev);
    116	struct atlx_hw *hw = &adapter->hw;
    117	struct netdev_hw_addr *ha;
    118	u32 rctl;
    119	u32 hash_value;
    120
    121	/* Check for Promiscuous and All Multicast modes */
    122	rctl = ioread32(hw->hw_addr + REG_MAC_CTRL);
    123	if (netdev->flags & IFF_PROMISC)
    124		rctl |= MAC_CTRL_PROMIS_EN;
    125	else if (netdev->flags & IFF_ALLMULTI) {
    126		rctl |= MAC_CTRL_MC_ALL_EN;
    127		rctl &= ~MAC_CTRL_PROMIS_EN;
    128	} else
    129		rctl &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN);
    130
    131	iowrite32(rctl, hw->hw_addr + REG_MAC_CTRL);
    132
    133	/* clear the old settings from the multicast hash table */
    134	iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE);
    135	iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2));
    136
    137	/* compute mc addresses' hash value ,and put it into hash table */
    138	netdev_for_each_mc_addr(ha, netdev) {
    139		hash_value = atlx_hash_mc_addr(hw, ha->addr);
    140		atlx_hash_set(hw, hash_value);
    141	}
    142}
    143
    144static inline void atlx_imr_set(struct atlx_adapter *adapter,
    145				unsigned int imr)
    146{
    147	iowrite32(imr, adapter->hw.hw_addr + REG_IMR);
    148	ioread32(adapter->hw.hw_addr + REG_IMR);
    149}
    150
    151/**
    152 * atlx_irq_enable - Enable default interrupt generation settings
    153 * @adapter: board private structure
    154 */
    155static void atlx_irq_enable(struct atlx_adapter *adapter)
    156{
    157	atlx_imr_set(adapter, IMR_NORMAL_MASK);
    158	adapter->int_enabled = true;
    159}
    160
    161/**
    162 * atlx_irq_disable - Mask off interrupt generation on the NIC
    163 * @adapter: board private structure
    164 */
    165static void atlx_irq_disable(struct atlx_adapter *adapter)
    166{
    167	adapter->int_enabled = false;
    168	atlx_imr_set(adapter, 0);
    169	synchronize_irq(adapter->pdev->irq);
    170}
    171
    172static void atlx_clear_phy_int(struct atlx_adapter *adapter)
    173{
    174	u16 phy_data;
    175	unsigned long flags;
    176
    177	spin_lock_irqsave(&adapter->lock, flags);
    178	atlx_read_phy_reg(&adapter->hw, 19, &phy_data);
    179	spin_unlock_irqrestore(&adapter->lock, flags);
    180}
    181
    182/**
    183 * atlx_tx_timeout - Respond to a Tx Hang
    184 * @netdev: network interface device structure
    185 */
    186static void atlx_tx_timeout(struct net_device *netdev, unsigned int txqueue)
    187{
    188	struct atlx_adapter *adapter = netdev_priv(netdev);
    189	/* Do the reset outside of interrupt context */
    190	schedule_work(&adapter->reset_dev_task);
    191}
    192
    193/*
    194 * atlx_link_chg_task - deal with link change event Out of interrupt context
    195 */
    196static void atlx_link_chg_task(struct work_struct *work)
    197{
    198	struct atlx_adapter *adapter;
    199	unsigned long flags;
    200
    201	adapter = container_of(work, struct atlx_adapter, link_chg_task);
    202
    203	spin_lock_irqsave(&adapter->lock, flags);
    204	atlx_check_link(adapter);
    205	spin_unlock_irqrestore(&adapter->lock, flags);
    206}
    207
    208static void __atlx_vlan_mode(netdev_features_t features, u32 *ctrl)
    209{
    210	if (features & NETIF_F_HW_VLAN_CTAG_RX) {
    211		/* enable VLAN tag insert/strip */
    212		*ctrl |= MAC_CTRL_RMV_VLAN;
    213	} else {
    214		/* disable VLAN tag insert/strip */
    215		*ctrl &= ~MAC_CTRL_RMV_VLAN;
    216	}
    217}
    218
    219static void atlx_vlan_mode(struct net_device *netdev,
    220	netdev_features_t features)
    221{
    222	struct atlx_adapter *adapter = netdev_priv(netdev);
    223	unsigned long flags;
    224	u32 ctrl;
    225
    226	spin_lock_irqsave(&adapter->lock, flags);
    227	/* atlx_irq_disable(adapter); FIXME: confirm/remove */
    228	ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
    229	__atlx_vlan_mode(features, &ctrl);
    230	iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
    231	/* atlx_irq_enable(adapter); FIXME */
    232	spin_unlock_irqrestore(&adapter->lock, flags);
    233}
    234
    235static void atlx_restore_vlan(struct atlx_adapter *adapter)
    236{
    237	atlx_vlan_mode(adapter->netdev, adapter->netdev->features);
    238}
    239
    240static netdev_features_t atlx_fix_features(struct net_device *netdev,
    241	netdev_features_t features)
    242{
    243	/*
    244	 * Since there is no support for separate rx/tx vlan accel
    245	 * enable/disable make sure tx flag is always in same state as rx.
    246	 */
    247	if (features & NETIF_F_HW_VLAN_CTAG_RX)
    248		features |= NETIF_F_HW_VLAN_CTAG_TX;
    249	else
    250		features &= ~NETIF_F_HW_VLAN_CTAG_TX;
    251
    252	return features;
    253}
    254
    255static int atlx_set_features(struct net_device *netdev,
    256	netdev_features_t features)
    257{
    258	netdev_features_t changed = netdev->features ^ features;
    259
    260	if (changed & NETIF_F_HW_VLAN_CTAG_RX)
    261		atlx_vlan_mode(netdev, features);
    262
    263	return 0;
    264}
    265
    266#endif /* ATLX_C */