root/drivers/net/ethernet/atheros/atlx/atlx.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. atlx_ioctl
  2. atlx_set_mac
  3. atlx_check_for_link
  4. atlx_set_multi
  5. atlx_imr_set
  6. atlx_irq_enable
  7. atlx_irq_disable
  8. atlx_clear_phy_int
  9. atlx_tx_timeout
  10. atlx_link_chg_task
  11. __atlx_vlan_mode
  12. atlx_vlan_mode
  13. atlx_restore_vlan
  14. atlx_fix_features
  15. atlx_set_features

   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 
  31 static s32 atlx_read_phy_reg(struct atl1_hw *hw, u16 reg_addr, u16 *phy_data);
  32 static u32 atlx_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr);
  33 static void atlx_set_mac_addr(struct atl1_hw *hw);
  34 
  35 static 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 
  42 static 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  */
  61 static 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         memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
  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 
  79 static 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  */
 113 static 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 
 144 static 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  */
 155 static 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  */
 165 static 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 
 172 static 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  */
 186 static void atlx_tx_timeout(struct net_device *netdev)
 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  */
 196 static 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 
 208 static 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 
 219 static 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 
 235 static void atlx_restore_vlan(struct atlx_adapter *adapter)
 236 {
 237         atlx_vlan_mode(adapter->netdev, adapter->netdev->features);
 238 }
 239 
 240 static 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 
 255 static 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 */

/* [<][>][^][v][top][bottom][index][help] */