]> err.no Git - linux-2.6/blobdiff - drivers/net/forcedeth.c
ath5k: Update register list
[linux-2.6] / drivers / net / forcedeth.c
index 786d668c612e897781ef9e91b3445591a66d5527..01b38b092c76e4e00994ef493ca9d88b3d381e55 100644 (file)
@@ -333,6 +333,7 @@ enum {
        NvRegPowerState2 = 0x600,
 #define NVREG_POWERSTATE2_POWERUP_MASK         0x0F11
 #define NVREG_POWERSTATE2_POWERUP_REV_A3       0x0001
+#define NVREG_POWERSTATE2_PHY_RESET            0x0004
 };
 
 /* Big endian: should work, but is untested */
@@ -529,6 +530,7 @@ union ring_type {
 #define PHY_REALTEK_INIT_REG4  0x14
 #define PHY_REALTEK_INIT_REG5  0x18
 #define PHY_REALTEK_INIT_REG6  0x11
+#define PHY_REALTEK_INIT_REG7  0x01
 #define PHY_REALTEK_INIT1      0x0000
 #define PHY_REALTEK_INIT2      0x8e00
 #define PHY_REALTEK_INIT3      0x0001
@@ -537,6 +539,9 @@ union ring_type {
 #define PHY_REALTEK_INIT6      0xf5c7
 #define PHY_REALTEK_INIT7      0x1000
 #define PHY_REALTEK_INIT8      0x0003
+#define PHY_REALTEK_INIT9      0x0008
+#define PHY_REALTEK_INIT10     0x0005
+#define PHY_REALTEK_INIT11     0x0200
 #define PHY_REALTEK_INIT_MSK1  0x0003
 
 #define PHY_GIGABIT    0x0100
@@ -1149,6 +1154,42 @@ static int phy_init(struct net_device *dev)
                                return PHY_ERROR;
                        }
                }
+               if (np->phy_model == PHY_MODEL_REALTEK_8211 &&
+                   np->phy_rev == PHY_REV_REALTEK_8211C) {
+                       u32 powerstate = readl(base + NvRegPowerState2);
+
+                       /* need to perform hw phy reset */
+                       powerstate |= NVREG_POWERSTATE2_PHY_RESET;
+                       writel(powerstate, base + NvRegPowerState2);
+                       msleep(25);
+
+                       powerstate &= ~NVREG_POWERSTATE2_PHY_RESET;
+                       writel(powerstate, base + NvRegPowerState2);
+                       msleep(25);
+
+                       reg = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, MII_READ);
+                       reg |= PHY_REALTEK_INIT9;
+                       if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, reg)) {
+                               printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                               return PHY_ERROR;
+                       }
+                       if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT10)) {
+                               printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                               return PHY_ERROR;
+                       }
+                       reg = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG7, MII_READ);
+                       if (!(reg & PHY_REALTEK_INIT11)) {
+                               reg |= PHY_REALTEK_INIT11;
+                               if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG7, reg)) {
+                                       printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                                       return PHY_ERROR;
+                               }
+                       }
+                       if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
+                               printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
+                               return PHY_ERROR;
+                       }
+               }
                if (np->phy_model == PHY_MODEL_REALTEK_8201) {
                        if (np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_32 ||
                            np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_33 ||
@@ -1201,12 +1242,23 @@ static int phy_init(struct net_device *dev)
        mii_control = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
        mii_control |= BMCR_ANENABLE;
 
-       /* reset the phy
-        * (certain phys need bmcr to be setup with reset)
-        */
-       if (phy_reset(dev, mii_control)) {
-               printk(KERN_INFO "%s: phy reset failed\n", pci_name(np->pci_dev));
-               return PHY_ERROR;
+       if (np->phy_oui == PHY_OUI_REALTEK &&
+           np->phy_model == PHY_MODEL_REALTEK_8211 &&
+           np->phy_rev == PHY_REV_REALTEK_8211C) {
+               /* start autoneg since we already performed hw reset above */
+               mii_control |= BMCR_ANRESTART;
+               if (mii_rw(dev, np->phyaddr, MII_BMCR, mii_control)) {
+                       printk(KERN_INFO "%s: phy init failed\n", pci_name(np->pci_dev));
+                       return PHY_ERROR;
+               }
+       } else {
+               /* reset the phy
+                * (certain phys need bmcr to be setup with reset)
+                */
+               if (phy_reset(dev, mii_control)) {
+                       printk(KERN_INFO "%s: phy reset failed\n", pci_name(np->pci_dev));
+                       return PHY_ERROR;
+               }
        }
 
        /* phy vendor specific configuration */
@@ -2831,6 +2883,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
                 */
                nv_disable_irq(dev);
                netif_tx_lock_bh(dev);
+               netif_addr_lock(dev);
                spin_lock(&np->lock);
                /* stop engines */
                nv_stop_rxtx(dev);
@@ -2855,6 +2908,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
                /* restart rx engine */
                nv_start_rxtx(dev);
                spin_unlock(&np->lock);
+               netif_addr_unlock(dev);
                netif_tx_unlock_bh(dev);
                nv_enable_irq(dev);
        }
@@ -2891,6 +2945,7 @@ static int nv_set_mac_address(struct net_device *dev, void *addr)
 
        if (netif_running(dev)) {
                netif_tx_lock_bh(dev);
+               netif_addr_lock(dev);
                spin_lock_irq(&np->lock);
 
                /* stop rx engine */
@@ -2902,6 +2957,7 @@ static int nv_set_mac_address(struct net_device *dev, void *addr)
                /* restart rx engine */
                nv_start_rx(dev);
                spin_unlock_irq(&np->lock);
+               netif_addr_unlock(dev);
                netif_tx_unlock_bh(dev);
        } else {
                nv_copy_mac_to_hw(dev);
@@ -3971,6 +4027,7 @@ static void nv_do_nic_poll(unsigned long data)
                printk(KERN_INFO "forcedeth: MAC in recoverable error state\n");
                if (netif_running(dev)) {
                        netif_tx_lock_bh(dev);
+                       netif_addr_lock(dev);
                        spin_lock(&np->lock);
                        /* stop engines */
                        nv_stop_rxtx(dev);
@@ -3995,6 +4052,7 @@ static void nv_do_nic_poll(unsigned long data)
                        /* restart rx engine */
                        nv_start_rxtx(dev);
                        spin_unlock(&np->lock);
+                       netif_addr_unlock(dev);
                        netif_tx_unlock_bh(dev);
                }
        }
@@ -4202,6 +4260,7 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 
                nv_disable_irq(dev);
                netif_tx_lock_bh(dev);
+               netif_addr_lock(dev);
                /* with plain spinlock lockdep complains */
                spin_lock_irqsave(&np->lock, flags);
                /* stop engines */
@@ -4215,6 +4274,7 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
                 */
                nv_stop_rxtx(dev);
                spin_unlock_irqrestore(&np->lock, flags);
+               netif_addr_unlock(dev);
                netif_tx_unlock_bh(dev);
        }
 
@@ -4360,10 +4420,12 @@ static int nv_nway_reset(struct net_device *dev)
                if (netif_running(dev)) {
                        nv_disable_irq(dev);
                        netif_tx_lock_bh(dev);
+                       netif_addr_lock(dev);
                        spin_lock(&np->lock);
                        /* stop engines */
                        nv_stop_rxtx(dev);
                        spin_unlock(&np->lock);
+                       netif_addr_unlock(dev);
                        netif_tx_unlock_bh(dev);
                        printk(KERN_INFO "%s: link down.\n", dev->name);
                }
@@ -4471,6 +4533,7 @@ static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ri
        if (netif_running(dev)) {
                nv_disable_irq(dev);
                netif_tx_lock_bh(dev);
+               netif_addr_lock(dev);
                spin_lock(&np->lock);
                /* stop engines */
                nv_stop_rxtx(dev);
@@ -4519,6 +4582,7 @@ static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ri
                /* restart engines */
                nv_start_rxtx(dev);
                spin_unlock(&np->lock);
+               netif_addr_unlock(dev);
                netif_tx_unlock_bh(dev);
                nv_enable_irq(dev);
        }
@@ -4556,10 +4620,12 @@ static int nv_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam*
        if (netif_running(dev)) {
                nv_disable_irq(dev);
                netif_tx_lock_bh(dev);
+               netif_addr_lock(dev);
                spin_lock(&np->lock);
                /* stop engines */
                nv_stop_rxtx(dev);
                spin_unlock(&np->lock);
+               netif_addr_unlock(dev);
                netif_tx_unlock_bh(dev);
        }
 
@@ -4946,6 +5012,7 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64
                        napi_disable(&np->napi);
 #endif
                        netif_tx_lock_bh(dev);
+                       netif_addr_lock(dev);
                        spin_lock_irq(&np->lock);
                        nv_disable_hw_interrupts(dev, np->irqmask);
                        if (!(np->msi_flags & NV_MSI_X_ENABLED)) {
@@ -4959,6 +5026,7 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64
                        /* drain rx queue */
                        nv_drain_rxtx(dev);
                        spin_unlock_irq(&np->lock);
+                       netif_addr_unlock(dev);
                        netif_tx_unlock_bh(dev);
                }