lkml.org 
[lkml]   [2010]   [May]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH net-next]atl1c: Add AR8151 v2 support and change L0s/L1 routine
    Date
    From: Jie.Yang@atheros.com

    Add AR8151 v2.0 Gigabit 1000 support
    Change jumbo frame size to 6K
    Update L0s/L1 rountine
    Update atl1c_suspend routine.

    Signed-off-by: Jie.Yang@atheros.com
    ---
    drivers/net/atl1c/atl1c.h | 9 +-
    drivers/net/atl1c/atl1c_hw.c | 107 +++++++++++--
    drivers/net/atl1c/atl1c_hw.h | 49 ++++++-
    drivers/net/atl1c/atl1c_main.c | 348 +++++++++++++++++++++++-----------------
    4 files changed, 345 insertions(+), 168 deletions(-)

    diff --git a/drivers/net/atl1c/atl1c.h b/drivers/net/atl1c/atl1c.h
    index 84ae905..52abbbd 100644
    --- a/drivers/net/atl1c/atl1c.h
    +++ b/drivers/net/atl1c/atl1c.h
    @@ -73,7 +73,8 @@
    #define FULL_DUPLEX 2

    #define AT_RX_BUF_SIZE (ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN)
    -#define MAX_JUMBO_FRAME_SIZE (9*1024)
    +#define MAX_JUMBO_FRAME_SIZE (6*1024)
    +#define MAX_TSO_FRAME_SIZE (7*1024)
    #define MAX_TX_OFFLOAD_THRESH (9*1024)

    #define AT_MAX_RECEIVE_QUEUE 4
    @@ -87,10 +88,11 @@
    #define AT_MAX_INT_WORK 5
    #define AT_TWSI_EEPROM_TIMEOUT 100
    #define AT_HW_MAX_IDLE_DELAY 10
    -#define AT_SUSPEND_LINK_TIMEOUT 28
    +#define AT_SUSPEND_LINK_TIMEOUT 100

    #define AT_ASPM_L0S_TIMER 6
    #define AT_ASPM_L1_TIMER 12
    +#define AT_LCKDET_TIMER 12

    #define ATL1C_PCIE_L0S_L1_DISABLE 0x01
    #define ATL1C_PCIE_PHY_RESET 0x02
    @@ -316,6 +318,7 @@ enum atl1c_nic_type {
    athr_l2c_b,
    athr_l2c_b2,
    athr_l1d,
    + athr_l1d_2,
    };

    enum atl1c_trans_queue {
    @@ -392,6 +395,8 @@ struct atl1c_hw {
    u16 subsystem_id;
    u16 subsystem_vendor_id;
    u8 revision_id;
    + u16 phy_id1;
    + u16 phy_id2;

    u32 intr_mask;
    u8 dmaw_dly_cnt;
    diff --git a/drivers/net/atl1c/atl1c_hw.c b/drivers/net/atl1c/atl1c_hw.c
    index f1389d6..d8501f0 100644
    --- a/drivers/net/atl1c/atl1c_hw.c
    +++ b/drivers/net/atl1c/atl1c_hw.c
    @@ -37,6 +37,9 @@ int atl1c_check_eeprom_exist(struct atl1c_hw *hw)
    if (data & TWSI_DEBUG_DEV_EXIST)
    return 1;

    + AT_READ_REG(hw, REG_MASTER_CTRL, &data);
    + if (data & MASTER_CTRL_OTP_SEL)
    + return 1;
    return 0;
    }

    @@ -69,6 +72,8 @@ static int atl1c_get_permanent_address(struct atl1c_hw *hw)
    u32 i;
    u32 otp_ctrl_data;
    u32 twsi_ctrl_data;
    + u32 ltssm_ctrl_data;
    + u32 wol_data;
    u8 eth_addr[ETH_ALEN];
    u16 phy_data;
    bool raise_vol = false;
    @@ -104,6 +109,15 @@ static int atl1c_get_permanent_address(struct atl1c_hw *hw)
    udelay(20);
    raise_vol = true;
    }
    + /* close open bit of ReadOnly*/
    + AT_READ_REG(hw, REG_LTSSM_ID_CTRL, &ltssm_ctrl_data);
    + ltssm_ctrl_data &= ~LTSSM_ID_EN_WRO;
    + AT_WRITE_REG(hw, REG_LTSSM_ID_CTRL, ltssm_ctrl_data);
    +
    + /* clear any WOL settings */
    + AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
    + AT_READ_REG(hw, REG_WOL_CTRL, &wol_data);
    +

    AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data);
    twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART;
    @@ -119,17 +133,15 @@ static int atl1c_get_permanent_address(struct atl1c_hw *hw)
    }
    /* Disable OTP_CLK */
    if ((hw->nic_type == athr_l1c || hw->nic_type == athr_l2c)) {
    - if (otp_ctrl_data & OTP_CTRL_CLK_EN) {
    - otp_ctrl_data &= ~OTP_CTRL_CLK_EN;
    - AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data);
    - AT_WRITE_FLUSH(hw);
    - msleep(1);
    - }
    + otp_ctrl_data &= ~OTP_CTRL_CLK_EN;
    + AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data);
    + msleep(1);
    }
    if (raise_vol) {
    if (hw->nic_type == athr_l2c_b ||
    hw->nic_type == athr_l2c_b2 ||
    - hw->nic_type == athr_l1d) {
    + hw->nic_type == athr_l1d ||
    + hw->nic_type == athr_l1d_2) {
    atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x00);
    if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data))
    goto out;
    @@ -456,14 +468,22 @@ int atl1c_phy_reset(struct atl1c_hw *hw)

    if (hw->nic_type == athr_l2c_b ||
    hw->nic_type == athr_l2c_b2 ||
    - hw->nic_type == athr_l1d) {
    + hw->nic_type == athr_l1d ||
    + hw->nic_type == athr_l1d_2) {
    atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x3B);
    atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data);
    atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data & 0xFFF7);
    msleep(20);
    }
    -
    - /*Enable PHY LinkChange Interrupt */
    + if (hw->nic_type == athr_l1d) {
    + atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x29);
    + atl1c_write_phy_reg(hw, MII_DBG_DATA, 0x929D);
    + }
    + if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c_b2
    + || hw->nic_type == athr_l2c || hw->nic_type == athr_l2c) {
    + atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x29);
    + atl1c_write_phy_reg(hw, MII_DBG_DATA, 0xB6DD);
    + }
    err = atl1c_write_phy_reg(hw, MII_IER, mii_ier_data);
    if (err) {
    if (netif_msg_hw(adapter))
    @@ -482,12 +502,10 @@ int atl1c_phy_init(struct atl1c_hw *hw)
    struct pci_dev *pdev = adapter->pdev;
    int ret_val;
    u16 mii_bmcr_data = BMCR_RESET;
    - u16 phy_id1, phy_id2;

    - if ((atl1c_read_phy_reg(hw, MII_PHYSID1, &phy_id1) != 0) ||
    - (atl1c_read_phy_reg(hw, MII_PHYSID2, &phy_id2) != 0)) {
    - if (netif_msg_link(adapter))
    - dev_err(&pdev->dev, "Error get phy ID\n");
    + if ((atl1c_read_phy_reg(hw, MII_PHYSID1, &hw->phy_id1) != 0) ||
    + (atl1c_read_phy_reg(hw, MII_PHYSID2, &hw->phy_id2) != 0)) {
    + dev_err(&pdev->dev, "Error get phy ID\n");
    return -1;
    }
    switch (hw->media_type) {
    @@ -572,6 +590,65 @@ int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex)
    return 0;
    }

    +int atl1c_phy_power_saving(struct atl1c_hw *hw)
    +{
    + struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter;
    + struct pci_dev *pdev = adapter->pdev;
    + int ret = 0;
    + u16 autoneg_advertised = ADVERTISED_10baseT_Half;
    + u16 save_autoneg_advertised;
    + u16 phy_data;
    + u16 mii_lpa_data;
    + u16 speed = SPEED_0;
    + u16 duplex = FULL_DUPLEX;
    + int i;
    +
    + atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
    + atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
    + if (phy_data & BMSR_LSTATUS) {
    + atl1c_read_phy_reg(hw, MII_LPA, &mii_lpa_data);
    + if (mii_lpa_data & LPA_10FULL)
    + autoneg_advertised = ADVERTISED_10baseT_Full;
    + else if (mii_lpa_data & LPA_10HALF)
    + autoneg_advertised = ADVERTISED_10baseT_Half;
    + else if (mii_lpa_data & LPA_100HALF)
    + autoneg_advertised = ADVERTISED_100baseT_Half;
    + else if (mii_lpa_data & LPA_100FULL)
    + autoneg_advertised = ADVERTISED_100baseT_Full;
    +
    + save_autoneg_advertised = hw->autoneg_advertised;
    + hw->phy_configured = false;
    + hw->autoneg_advertised = autoneg_advertised;
    + if (atl1c_restart_autoneg(hw) != 0) {
    + dev_dbg(&pdev->dev, "phy autoneg failed\n");
    + ret = -1;
    + }
    + hw->autoneg_advertised = save_autoneg_advertised;
    +
    + if (mii_lpa_data) {
    + for (i = 0; i < AT_SUSPEND_LINK_TIMEOUT; i++) {
    + mdelay(100);
    + atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
    + atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
    + if (phy_data & BMSR_LSTATUS) {
    + if (atl1c_get_speed_and_duplex(hw, &speed,
    + &duplex) != 0)
    + dev_dbg(&pdev->dev,
    + "get speed and duplex failed\n");
    + break;
    + }
    + }
    + }
    + } else {
    + speed = SPEED_10;
    + duplex = HALF_DUPLEX;
    + }
    + adapter->link_speed = speed;
    + adapter->link_duplex = duplex;
    +
    + return ret;
    +}
    +
    int atl1c_restart_autoneg(struct atl1c_hw *hw)
    {
    int err = 0;
    diff --git a/drivers/net/atl1c/atl1c_hw.h b/drivers/net/atl1c/atl1c_hw.h
    index 1eeb3ed..3dd6759 100644
    --- a/drivers/net/atl1c/atl1c_hw.h
    +++ b/drivers/net/atl1c/atl1c_hw.h
    @@ -42,7 +42,7 @@ bool atl1c_read_eeprom(struct atl1c_hw *hw, u32 offset, u32 *p_value);
    int atl1c_phy_init(struct atl1c_hw *hw);
    int atl1c_check_eeprom_exist(struct atl1c_hw *hw);
    int atl1c_restart_autoneg(struct atl1c_hw *hw);
    -
    +int atl1c_phy_power_saving(struct atl1c_hw *hw);
    /* register definition */
    #define REG_DEVICE_CAP 0x5C
    #define DEVICE_CAP_MAX_PAYLOAD_MASK 0x7
    @@ -120,6 +120,12 @@ int atl1c_restart_autoneg(struct atl1c_hw *hw);
    #define REG_PCIE_PHYMISC 0x1000
    #define PCIE_PHYMISC_FORCE_RCV_DET 0x4

    +#define REG_PCIE_PHYMISC2 0x1004
    +#define PCIE_PHYMISC2_SERDES_CDR_MASK 0x3
    +#define PCIE_PHYMISC2_SERDES_CDR_SHIFT 16
    +#define PCIE_PHYMISC2_SERDES_TH_MASK 0x3
    +#define PCIE_PHYMISC2_SERDES_TH_SHIFT 18
    +
    #define REG_TWSI_DEBUG 0x1108
    #define TWSI_DEBUG_DEV_EXIST 0x20000000

    @@ -150,24 +156,28 @@ int atl1c_restart_autoneg(struct atl1c_hw *hw);
    #define PM_CTRL_ASPM_L0S_EN 0x00001000
    #define PM_CTRL_CLK_SWH_L1 0x00002000
    #define PM_CTRL_CLK_PWM_VER1_1 0x00004000
    -#define PM_CTRL_PCIE_RECV 0x00008000
    +#define PM_CTRL_RCVR_WT_TIMER 0x00008000
    #define PM_CTRL_L1_ENTRY_TIMER_MASK 0xF
    #define PM_CTRL_L1_ENTRY_TIMER_SHIFT 16
    #define PM_CTRL_PM_REQ_TIMER_MASK 0xF
    #define PM_CTRL_PM_REQ_TIMER_SHIFT 20
    -#define PM_CTRL_LCKDET_TIMER_MASK 0x3F
    +#define PM_CTRL_LCKDET_TIMER_MASK 0xF
    #define PM_CTRL_LCKDET_TIMER_SHIFT 24
    #define PM_CTRL_EN_BUFS_RX_L0S 0x10000000
    #define PM_CTRL_SA_DLY_EN 0x20000000
    #define PM_CTRL_MAC_ASPM_CHK 0x40000000
    #define PM_CTRL_HOTRST 0x80000000

    +#define REG_LTSSM_ID_CTRL 0x12FC
    +#define LTSSM_ID_EN_WRO 0x1000
    /* Selene Master Control Register */
    #define REG_MASTER_CTRL 0x1400
    #define MASTER_CTRL_SOFT_RST 0x1
    #define MASTER_CTRL_TEST_MODE_MASK 0x3
    #define MASTER_CTRL_TEST_MODE_SHIFT 2
    #define MASTER_CTRL_BERT_START 0x10
    +#define MASTER_CTRL_OOB_DIS_OFF 0x40
    +#define MASTER_CTRL_SA_TIMER_EN 0x80
    #define MASTER_CTRL_MTIMER_EN 0x100
    #define MASTER_CTRL_MANUAL_INT 0x200
    #define MASTER_CTRL_TX_ITIMER_EN 0x400
    @@ -220,6 +230,12 @@ int atl1c_restart_autoneg(struct atl1c_hw *hw);
    GPHY_CTRL_PWDOWN_HW |\
    GPHY_CTRL_PHY_IDDQ)

    +#define GPHY_CTRL_POWER_SAVING ( \
    + GPHY_CTRL_SEL_ANA_RST |\
    + GPHY_CTRL_HIB_EN |\
    + GPHY_CTRL_HIB_PULSE |\
    + GPHY_CTRL_PWDOWN_HW |\
    + GPHY_CTRL_PHY_IDDQ)
    /* Block IDLE Status Register */
    #define REG_IDLE_STATUS 0x1410
    #define IDLE_STATUS_MASK 0x00FF
    @@ -287,6 +303,14 @@ int atl1c_restart_autoneg(struct atl1c_hw *hw);
    #define SERDES_LOCK_DETECT 0x1 /* SerDes lock detected. This signal
    * comes from Analog SerDes */
    #define SERDES_LOCK_DETECT_EN 0x2 /* 1: Enable SerDes Lock detect function */
    +#define SERDES_LOCK_STS_SELFB_PLL_SHIFT 0xE
    +#define SERDES_LOCK_STS_SELFB_PLL_MASK 0x3
    +#define SERDES_OVCLK_18_25 0x0
    +#define SERDES_OVCLK_12_18 0x1
    +#define SERDES_OVCLK_0_4 0x2
    +#define SERDES_OVCLK_4_12 0x3
    +#define SERDES_MAC_CLK_SLOWDOWN 0x20000
    +#define SERDES_PYH_CLK_SLOWDOWN 0x40000

    /* MAC Control Register */
    #define REG_MAC_CTRL 0x1480
    @@ -693,6 +717,21 @@ int atl1c_restart_autoneg(struct atl1c_hw *hw);
    #define REG_MAC_TX_STATUS_BIN 0x1760
    #define REG_MAC_TX_STATUS_END 0x17c0

    +#define REG_CLK_GATING_CTRL 0x1814
    +#define CLK_GATING_DMAW_EN 0x0001
    +#define CLK_GATING_DMAR_EN 0x0002
    +#define CLK_GATING_TXQ_EN 0x0004
    +#define CLK_GATING_RXQ_EN 0x0008
    +#define CLK_GATING_TXMAC_EN 0x0010
    +#define CLK_GATING_RXMAC_EN 0x0020
    +
    +#define CLK_GATING_EN_ALL (CLK_GATING_DMAW_EN |\
    + CLK_GATING_DMAR_EN |\
    + CLK_GATING_TXQ_EN |\
    + CLK_GATING_RXQ_EN |\
    + CLK_GATING_TXMAC_EN|\
    + CLK_GATING_RXMAC_EN)
    +
    /* DEBUG ADDR */
    #define REG_DEBUG_DATA0 0x1900
    #define REG_DEBUG_DATA1 0x1904
    @@ -734,6 +773,10 @@ int atl1c_restart_autoneg(struct atl1c_hw *hw);

    #define MII_PHYSID1 0x02
    #define MII_PHYSID2 0x03
    +#define L1D_MPW_PHYID1 0xD01C /* V7 */
    +#define L1D_MPW_PHYID2 0xD01D /* V1-V6 */
    +#define L1D_MPW_PHYID3 0xD01E /* V8 */
    +

    /* Autoneg Advertisement Register */
    #define MII_ADVERTISE 0x04
    diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c
    index 1c3c046..c7b8ef5 100644
    --- a/drivers/net/atl1c/atl1c_main.c
    +++ b/drivers/net/atl1c/atl1c_main.c
    @@ -21,7 +21,7 @@

    #include "atl1c.h"

    -#define ATL1C_DRV_VERSION "1.0.0.2-NAPI"
    +#define ATL1C_DRV_VERSION "1.0.1.0-NAPI"
    char atl1c_driver_name[] = "atl1c";
    char atl1c_driver_version[] = ATL1C_DRV_VERSION;
    #define PCI_DEVICE_ID_ATTANSIC_L2C 0x1062
    @@ -29,7 +29,7 @@ char atl1c_driver_version[] = ATL1C_DRV_VERSION;
    #define PCI_DEVICE_ID_ATHEROS_L2C_B 0x2060 /* AR8152 v1.1 Fast 10/100 */
    #define PCI_DEVICE_ID_ATHEROS_L2C_B2 0x2062 /* AR8152 v2.0 Fast 10/100 */
    #define PCI_DEVICE_ID_ATHEROS_L1D 0x1073 /* AR8151 v1.0 Gigabit 1000 */
    -
    +#define PCI_DEVICE_ID_ATHEROS_L1D_2_0 0x1083 /* AR8151 v2.0 Gigabit 1000 */
    #define L2CB_V10 0xc0
    #define L2CB_V11 0xc1

    @@ -97,7 +97,28 @@ static const u16 atl1c_rrd_addr_lo_regs[AT_MAX_RECEIVE_QUEUE] =

    static const u32 atl1c_default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE |
    NETIF_MSG_LINK | NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP;
    +static void atl1c_pcie_patch(struct atl1c_hw *hw)
    +{
    + u32 data;

    + AT_READ_REG(hw, REG_PCIE_PHYMISC, &data);
    + data |= PCIE_PHYMISC_FORCE_RCV_DET;
    + AT_WRITE_REG(hw, REG_PCIE_PHYMISC, data);
    +
    + if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V10) {
    + AT_READ_REG(hw, REG_PCIE_PHYMISC2, &data);
    +
    + data &= ~(PCIE_PHYMISC2_SERDES_CDR_MASK <<
    + PCIE_PHYMISC2_SERDES_CDR_SHIFT);
    + data |= 3 << PCIE_PHYMISC2_SERDES_CDR_SHIFT;
    + data &= ~(PCIE_PHYMISC2_SERDES_TH_MASK <<
    + PCIE_PHYMISC2_SERDES_TH_SHIFT);
    + data |= 3 << PCIE_PHYMISC2_SERDES_TH_SHIFT;
    + AT_WRITE_REG(hw, REG_PCIE_PHYMISC2, data);
    + }
    +}
    +
    +/* FIXME: no need any more ? */
    /*
    * atl1c_init_pcie - init PCIE module
    */
    @@ -127,6 +148,11 @@ static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag)
    data &= ~PCIE_UC_SERVRITY_FCP;
    AT_WRITE_REG(hw, REG_PCIE_UC_SEVERITY, data);

    + AT_READ_REG(hw, REG_LTSSM_ID_CTRL, &data);
    + data &= ~LTSSM_ID_EN_WRO;
    + AT_WRITE_REG(hw, REG_LTSSM_ID_CTRL, data);
    +
    + atl1c_pcie_patch(hw);
    if (flag & ATL1C_PCIE_L0S_L1_DISABLE)
    atl1c_disable_l0s_l1(hw);
    if (flag & ATL1C_PCIE_PHY_RESET)
    @@ -135,7 +161,7 @@ static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag)
    AT_WRITE_REG(hw, REG_GPHY_CTRL,
    GPHY_CTRL_DEFAULT | GPHY_CTRL_EXT_RESET);

    - msleep(1);
    + msleep(5);
    }

    /*
    @@ -159,6 +185,7 @@ static inline void atl1c_irq_disable(struct atl1c_adapter *adapter)
    {
    atomic_inc(&adapter->irq_sem);
    AT_WRITE_REG(&adapter->hw, REG_IMR, 0);
    + AT_WRITE_REG(&adapter->hw, REG_ISR, ISR_DIS_INT);
    AT_WRITE_FLUSH(&adapter->hw);
    synchronize_irq(adapter->pdev->irq);
    }
    @@ -231,15 +258,15 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter)

    if ((phy_data & BMSR_LSTATUS) == 0) {
    /* link down */
    - if (netif_carrier_ok(netdev)) {
    - hw->hibernate = true;
    - if (atl1c_stop_mac(hw) != 0)
    - if (netif_msg_hw(adapter))
    - dev_warn(&pdev->dev,
    - "stop mac failed\n");
    - atl1c_set_aspm(hw, false);
    - }
    + hw->hibernate = true;
    + if (atl1c_stop_mac(hw) != 0)
    + if (netif_msg_hw(adapter))
    + dev_warn(&pdev->dev, "stop mac failed\n");
    + atl1c_set_aspm(hw, false);
    netif_carrier_off(netdev);
    + netif_stop_queue(netdev);
    + atl1c_phy_reset(hw);
    + atl1c_phy_init(&adapter->hw);
    } else {
    /* Link Up */
    hw->hibernate = false;
    @@ -308,6 +335,7 @@ static void atl1c_common_task(struct work_struct *work)
    netdev = adapter->netdev;

    if (adapter->work_event & ATL1C_WORK_EVENT_RESET) {
    + adapter->work_event &= ~ATL1C_WORK_EVENT_RESET;
    netif_device_detach(netdev);
    atl1c_down(adapter);
    atl1c_up(adapter);
    @@ -315,8 +343,11 @@ static void atl1c_common_task(struct work_struct *work)
    return;
    }

    - if (adapter->work_event & ATL1C_WORK_EVENT_LINK_CHANGE)
    + if (adapter->work_event & ATL1C_WORK_EVENT_LINK_CHANGE) {
    + adapter->work_event &= ~ATL1C_WORK_EVENT_LINK_CHANGE;
    atl1c_check_link_status(adapter);
    + }
    + return;
    }


    @@ -476,6 +507,13 @@ static int atl1c_change_mtu(struct net_device *netdev, int new_mtu)
    netdev->mtu = new_mtu;
    adapter->hw.max_frame_size = new_mtu;
    atl1c_set_rxbufsize(adapter, netdev);
    + if (new_mtu > MAX_TSO_FRAME_SIZE) {
    + adapter->netdev->features &= ~NETIF_F_TSO;
    + adapter->netdev->features &= ~NETIF_F_TSO6;
    + } else {
    + adapter->netdev->features |= NETIF_F_TSO;
    + adapter->netdev->features |= NETIF_F_TSO6;
    + }
    atl1c_down(adapter);
    atl1c_up(adapter);
    clear_bit(__AT_RESETTING, &adapter->flags);
    @@ -613,6 +651,9 @@ static void atl1c_set_mac_type(struct atl1c_hw *hw)
    case PCI_DEVICE_ID_ATHEROS_L1D:
    hw->nic_type = athr_l1d;
    break;
    + case PCI_DEVICE_ID_ATHEROS_L1D_2_0:
    + hw->nic_type = athr_l1d_2;
    + break;
    default:
    break;
    }
    @@ -627,9 +668,7 @@ static int atl1c_setup_mac_funcs(struct atl1c_hw *hw)
    AT_READ_REG(hw, REG_PHY_STATUS, &phy_status_data);
    AT_READ_REG(hw, REG_LINK_CTRL, &link_ctrl_data);

    - hw->ctrl_flags = ATL1C_INTR_CLEAR_ON_READ |
    - ATL1C_INTR_MODRT_ENABLE |
    - ATL1C_RX_IPV6_CHKSUM |
    + hw->ctrl_flags = ATL1C_INTR_MODRT_ENABLE |
    ATL1C_TXQ_MODE_ENHANCE;
    if (link_ctrl_data & LINK_CTRL_L0S_EN)
    hw->ctrl_flags |= ATL1C_ASPM_L0S_SUPPORT;
    @@ -637,12 +676,12 @@ static int atl1c_setup_mac_funcs(struct atl1c_hw *hw)
    hw->ctrl_flags |= ATL1C_ASPM_L1_SUPPORT;
    if (link_ctrl_data & LINK_CTRL_EXT_SYNC)
    hw->ctrl_flags |= ATL1C_LINK_EXT_SYNC;
    + hw->ctrl_flags |= ATL1C_ASPM_CTRL_MON;

    if (hw->nic_type == athr_l1c ||
    - hw->nic_type == athr_l1d) {
    - hw->ctrl_flags |= ATL1C_ASPM_CTRL_MON;
    + hw->nic_type == athr_l1d ||
    + hw->nic_type == athr_l1d_2)
    hw->link_cap_flags |= ATL1C_LINK_CAP_1000M;
    - }
    return 0;
    }
    /*
    @@ -657,6 +696,8 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter)
    {
    struct atl1c_hw *hw = &adapter->hw;
    struct pci_dev *pdev = adapter->pdev;
    + u32 revision;
    +

    adapter->wol = 0;
    adapter->link_speed = SPEED_0;
    @@ -669,7 +710,8 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter)
    hw->device_id = pdev->device;
    hw->subsystem_vendor_id = pdev->subsystem_vendor;
    hw->subsystem_id = pdev->subsystem_device;
    -
    + AT_READ_REG(hw, PCI_CLASS_REVISION, &revision);
    + hw->revision_id = revision & 0xFF;
    /* before link up, we assume hibernate is true */
    hw->hibernate = true;
    hw->media_type = MEDIA_TYPE_AUTO_SENSOR;
    @@ -974,6 +1016,7 @@ static void atl1c_configure_des_ring(struct atl1c_adapter *adapter)
    struct atl1c_cmb *cmb = (struct atl1c_cmb *) &adapter->cmb;
    struct atl1c_smb *smb = (struct atl1c_smb *) &adapter->smb;
    int i;
    + u32 data;

    /* TPD */
    AT_WRITE_REG(hw, REG_TX_BASE_ADDR_HI,
    @@ -1017,6 +1060,23 @@ static void atl1c_configure_des_ring(struct atl1c_adapter *adapter)
    (u32)((smb->dma & AT_DMA_HI_ADDR_MASK) >> 32));
    AT_WRITE_REG(hw, REG_SMB_BASE_ADDR_LO,
    (u32)(smb->dma & AT_DMA_LO_ADDR_MASK));
    + if (hw->nic_type == athr_l2c_b) {
    + AT_WRITE_REG(hw, REG_SRAM_RXF_LEN, 0x02a0L);
    + AT_WRITE_REG(hw, REG_SRAM_TXF_LEN, 0x0100L);
    + AT_WRITE_REG(hw, REG_SRAM_RXF_ADDR, 0x029f0000L);
    + AT_WRITE_REG(hw, REG_SRAM_RFD0_INFO, 0x02bf02a0L);
    + AT_WRITE_REG(hw, REG_SRAM_TXF_ADDR, 0x03bf02c0L);
    + AT_WRITE_REG(hw, REG_SRAM_TRD_ADDR, 0x03df03c0L);
    + AT_WRITE_REG(hw, REG_TXF_WATER_MARK, 0); /* TX watermark, to enter l1 state.*/
    + AT_WRITE_REG(hw, REG_RXD_DMA_CTRL, 0); /* RXD threshold.*/
    + }
    + if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d_2) {
    + /* Power Saving for L2c_B */
    + AT_READ_REG(hw, REG_SERDES_LOCK, &data);
    + data |= SERDES_MAC_CLK_SLOWDOWN;
    + data |= SERDES_PYH_CLK_SLOWDOWN;
    + AT_WRITE_REG(hw, REG_SERDES_LOCK, data);
    + }
    /* Load all of base address above */
    AT_WRITE_REG(hw, REG_LOAD_PTR, 1);
    }
    @@ -1029,6 +1089,7 @@ static void atl1c_configure_tx(struct atl1c_adapter *adapter)
    u16 tx_offload_thresh;
    u32 txq_ctrl_data;
    u32 extra_size = 0; /* Jumbo frame threshold in QWORD unit */
    + u32 max_pay_load_data;

    extra_size = ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN;
    tx_offload_thresh = MAX_TX_OFFLOAD_THRESH;
    @@ -1046,8 +1107,11 @@ static void atl1c_configure_tx(struct atl1c_adapter *adapter)
    TXQ_NUM_TPD_BURST_SHIFT;
    if (hw->ctrl_flags & ATL1C_TXQ_MODE_ENHANCE)
    txq_ctrl_data |= TXQ_CTRL_ENH_MODE;
    - txq_ctrl_data |= (atl1c_pay_load_size[hw->dmar_block] &
    + max_pay_load_data = (atl1c_pay_load_size[hw->dmar_block] &
    TXQ_TXF_BURST_NUM_MASK) << TXQ_TXF_BURST_NUM_SHIFT;
    + if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2)
    + max_pay_load_data >>= 1;
    + txq_ctrl_data |= max_pay_load_data;

    AT_WRITE_REG(hw, REG_TXQ_CTRL, txq_ctrl_data);
    }
    @@ -1078,7 +1142,7 @@ static void atl1c_configure_rx(struct atl1c_adapter *adapter)
    rxq_ctrl_data |= (hw->rss_hash_bits & RSS_HASH_BITS_MASK) <<
    RSS_HASH_BITS_SHIFT;
    if (hw->ctrl_flags & ATL1C_ASPM_CTRL_MON)
    - rxq_ctrl_data |= (ASPM_THRUPUT_LIMIT_100M &
    + rxq_ctrl_data |= (ASPM_THRUPUT_LIMIT_1M &
    ASPM_THRUPUT_LIMIT_MASK) << ASPM_THRUPUT_LIMIT_SHIFT;

    AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq_ctrl_data);
    @@ -1198,21 +1262,23 @@ static int atl1c_reset_mac(struct atl1c_hw *hw)
    {
    struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter;
    struct pci_dev *pdev = adapter->pdev;
    - int ret;
    + u32 master_ctrl_data = 0;

    AT_WRITE_REG(hw, REG_IMR, 0);
    AT_WRITE_REG(hw, REG_ISR, ISR_DIS_INT);

    - ret = atl1c_stop_mac(hw);
    - if (ret)
    - return ret;
    + atl1c_stop_mac(hw);
    /*
    * Issue Soft Reset to the MAC. This will reset the chip's
    * transmit, receive, DMA. It will not effect
    * the current PCI configuration. The global reset bit is self-
    * clearing, and should clear within a microsecond.
    */
    - AT_WRITE_REGW(hw, REG_MASTER_CTRL, MASTER_CTRL_SOFT_RST);
    + AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data);
    + master_ctrl_data |= MASTER_CTRL_OOB_DIS_OFF;
    + AT_WRITE_REGW(hw, REG_MASTER_CTRL, ((master_ctrl_data | MASTER_CTRL_SOFT_RST)
    + & 0xFFFF));
    +
    AT_WRITE_FLUSH(hw);
    msleep(10);
    /* Wait at least 10ms for All module to be Idle */
    @@ -1253,42 +1319,39 @@ static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup)
    {
    u32 pm_ctrl_data;
    u32 link_ctrl_data;
    + u32 link_l1_timer = 0xF;

    AT_READ_REG(hw, REG_PM_CTRL, &pm_ctrl_data);
    AT_READ_REG(hw, REG_LINK_CTRL, &link_ctrl_data);
    - pm_ctrl_data &= ~PM_CTRL_SERDES_PD_EX_L1;

    + pm_ctrl_data &= ~PM_CTRL_SERDES_PD_EX_L1;
    pm_ctrl_data &= ~(PM_CTRL_L1_ENTRY_TIMER_MASK <<
    PM_CTRL_L1_ENTRY_TIMER_SHIFT);
    pm_ctrl_data &= ~(PM_CTRL_LCKDET_TIMER_MASK <<
    - PM_CTRL_LCKDET_TIMER_SHIFT);
    -
    - pm_ctrl_data |= PM_CTRL_MAC_ASPM_CHK;
    - pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN;
    - pm_ctrl_data |= PM_CTRL_RBER_EN;
    - pm_ctrl_data |= PM_CTRL_SDES_EN;
    + PM_CTRL_LCKDET_TIMER_SHIFT);
    + pm_ctrl_data |= AT_LCKDET_TIMER << PM_CTRL_LCKDET_TIMER_SHIFT;

    - if (hw->nic_type == athr_l2c_b ||
    - hw->nic_type == athr_l1d ||
    - hw->nic_type == athr_l2c_b2) {
    + if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d ||
    + hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) {
    link_ctrl_data &= ~LINK_CTRL_EXT_SYNC;
    if (!(hw->ctrl_flags & ATL1C_APS_MODE_ENABLE)) {
    - if (hw->nic_type == athr_l2c_b &&
    - hw->revision_id == L2CB_V10)
    + if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V10)
    link_ctrl_data |= LINK_CTRL_EXT_SYNC;
    }

    AT_WRITE_REG(hw, REG_LINK_CTRL, link_ctrl_data);

    - pm_ctrl_data |= PM_CTRL_PCIE_RECV;
    - pm_ctrl_data |= AT_ASPM_L1_TIMER << PM_CTRL_PM_REQ_TIMER_SHIFT;
    - pm_ctrl_data &= ~PM_CTRL_EN_BUFS_RX_L0S;
    + pm_ctrl_data |= PM_CTRL_RCVR_WT_TIMER;
    + pm_ctrl_data &= ~(PM_CTRL_PM_REQ_TIMER_MASK <<
    + PM_CTRL_PM_REQ_TIMER_SHIFT);
    + pm_ctrl_data |= AT_ASPM_L1_TIMER <<
    + PM_CTRL_PM_REQ_TIMER_SHIFT;
    pm_ctrl_data &= ~PM_CTRL_SA_DLY_EN;
    pm_ctrl_data &= ~PM_CTRL_HOTRST;
    pm_ctrl_data |= 1 << PM_CTRL_L1_ENTRY_TIMER_SHIFT;
    pm_ctrl_data |= PM_CTRL_SERDES_PD_EX_L1;
    }
    -
    + pm_ctrl_data |= PM_CTRL_MAC_ASPM_CHK;
    if (linkup) {
    pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN;
    pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN;
    @@ -1297,27 +1360,26 @@ static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup)
    if (hw->ctrl_flags & ATL1C_ASPM_L0S_SUPPORT)
    pm_ctrl_data |= PM_CTRL_ASPM_L0S_EN;

    - if (hw->nic_type == athr_l2c_b ||
    - hw->nic_type == athr_l1d ||
    - hw->nic_type == athr_l2c_b2) {
    + if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d ||
    + hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) {
    if (hw->nic_type == athr_l2c_b)
    if (!(hw->ctrl_flags & ATL1C_APS_MODE_ENABLE))
    - pm_ctrl_data &= PM_CTRL_ASPM_L0S_EN;
    + pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN;
    pm_ctrl_data &= ~PM_CTRL_SERDES_L1_EN;
    pm_ctrl_data &= ~PM_CTRL_SERDES_PLL_L1_EN;
    pm_ctrl_data &= ~PM_CTRL_SERDES_BUDS_RX_L1_EN;
    pm_ctrl_data |= PM_CTRL_CLK_SWH_L1;
    - if (hw->adapter->link_speed == SPEED_100 ||
    - hw->adapter->link_speed == SPEED_1000) {
    - pm_ctrl_data &=
    - ~(PM_CTRL_L1_ENTRY_TIMER_MASK <<
    - PM_CTRL_L1_ENTRY_TIMER_SHIFT);
    - if (hw->nic_type == athr_l1d)
    - pm_ctrl_data |= 0xF <<
    - PM_CTRL_L1_ENTRY_TIMER_SHIFT;
    - else
    - pm_ctrl_data |= 7 <<
    - PM_CTRL_L1_ENTRY_TIMER_SHIFT;
    + if (hw->adapter->link_speed == SPEED_100 ||
    + hw->adapter->link_speed == SPEED_1000) {
    + pm_ctrl_data &= ~(PM_CTRL_L1_ENTRY_TIMER_MASK <<
    + PM_CTRL_L1_ENTRY_TIMER_SHIFT);
    + if (hw->nic_type == athr_l2c_b)
    + link_l1_timer = 7;
    + else if (hw->nic_type == athr_l2c_b2 ||
    + hw->nic_type == athr_l1d_2)
    + link_l1_timer = 4;
    + pm_ctrl_data |= link_l1_timer <<
    + PM_CTRL_L1_ENTRY_TIMER_SHIFT;
    }
    } else {
    pm_ctrl_data |= PM_CTRL_SERDES_L1_EN;
    @@ -1326,24 +1388,12 @@ static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup)
    pm_ctrl_data &= ~PM_CTRL_CLK_SWH_L1;
    pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN;
    pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN;
    - }
    - atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x29);
    - if (hw->adapter->link_speed == SPEED_10)
    - if (hw->nic_type == athr_l1d)
    - atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0xB69D);
    - else
    - atl1c_write_phy_reg(hw, MII_DBG_DATA, 0xB6DD);
    - else if (hw->adapter->link_speed == SPEED_100)
    - atl1c_write_phy_reg(hw, MII_DBG_DATA, 0xB2DD);
    - else
    - atl1c_write_phy_reg(hw, MII_DBG_DATA, 0x96DD);

    + }
    } else {
    - pm_ctrl_data &= ~PM_CTRL_SERDES_BUDS_RX_L1_EN;
    pm_ctrl_data &= ~PM_CTRL_SERDES_L1_EN;
    pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN;
    pm_ctrl_data &= ~PM_CTRL_SERDES_PLL_L1_EN;
    -
    pm_ctrl_data |= PM_CTRL_CLK_SWH_L1;

    if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT)
    @@ -1351,8 +1401,9 @@ static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup)
    else
    pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN;
    }
    -
    AT_WRITE_REG(hw, REG_PM_CTRL, pm_ctrl_data);
    +
    + return;
    }

    static void atl1c_setup_mac_ctrl(struct atl1c_adapter *adapter)
    @@ -1391,7 +1442,8 @@ static void atl1c_setup_mac_ctrl(struct atl1c_adapter *adapter)
    mac_ctrl_data |= MAC_CTRL_MC_ALL_EN;

    mac_ctrl_data |= MAC_CTRL_SINGLE_PAUSE_EN;
    - if (hw->nic_type == athr_l1d || hw->nic_type == athr_l2c_b2) {
    + if (hw->nic_type == athr_l1d || hw->nic_type == athr_l2c_b2 ||
    + hw->nic_type == athr_l1d_2) {
    mac_ctrl_data |= MAC_CTRL_SPEED_MODE_SW;
    mac_ctrl_data |= MAC_CTRL_HASH_ALG_CRC32;
    }
    @@ -1409,6 +1461,7 @@ static int atl1c_configure(struct atl1c_adapter *adapter)
    struct atl1c_hw *hw = &adapter->hw;
    u32 master_ctrl_data = 0;
    u32 intr_modrt_data;
    + u32 data;

    /* clear interrupt status */
    AT_WRITE_REG(hw, REG_ISR, 0xFFFFFFFF);
    @@ -1418,6 +1471,15 @@ static int atl1c_configure(struct atl1c_adapter *adapter)
    * HW will enable self to assert interrupt event to system after
    * waiting x-time for software to notify it accept interrupt.
    */
    +
    + data = CLK_GATING_EN_ALL;
    + if (hw->ctrl_flags & ATL1C_CLK_GATING_EN) {
    + if (hw->nic_type == athr_l2c_b)
    + data &= ~CLK_GATING_RXMAC_EN;
    + } else
    + data = 0;
    + AT_WRITE_REG(hw, REG_CLK_GATING_CTRL, data);
    +
    AT_WRITE_REG(hw, REG_INT_RETRIG_TIMER,
    hw->ict & INT_RETRIG_TIMER_MASK);

    @@ -1436,6 +1498,7 @@ static int atl1c_configure(struct atl1c_adapter *adapter)
    if (hw->ctrl_flags & ATL1C_INTR_CLEAR_ON_READ)
    master_ctrl_data |= MASTER_CTRL_INT_RDCLR;

    + master_ctrl_data |= MASTER_CTRL_SA_TIMER_EN;
    AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data);

    if (hw->ctrl_flags & ATL1C_CMB_ENABLE) {
    @@ -1624,11 +1687,9 @@ static irqreturn_t atl1c_intr(int irq, void *data)
    "atl1c hardware error (status = 0x%x)\n",
    status & ISR_ERROR);
    /* reset MAC */
    - hw->intr_mask &= ~ISR_ERROR;
    - AT_WRITE_REG(hw, REG_IMR, hw->intr_mask);
    adapter->work_event |= ATL1C_WORK_EVENT_RESET;
    schedule_work(&adapter->common_task);
    - break;
    + return IRQ_HANDLED;
    }

    if (status & ISR_OVER)
    @@ -2303,7 +2364,6 @@ void atl1c_down(struct atl1c_adapter *adapter)
    napi_disable(&adapter->napi);
    atl1c_irq_disable(adapter);
    atl1c_free_irq(adapter);
    - AT_WRITE_REG(&adapter->hw, REG_ISR, ISR_DIS_INT);
    /* reset MAC to disable all RX/TX */
    atl1c_reset_mac(&adapter->hw);
    msleep(1);
    @@ -2387,79 +2447,68 @@ static int atl1c_suspend(struct pci_dev *pdev, pm_message_t state)
    struct net_device *netdev = pci_get_drvdata(pdev);
    struct atl1c_adapter *adapter = netdev_priv(netdev);
    struct atl1c_hw *hw = &adapter->hw;
    - u32 ctrl;
    - u32 mac_ctrl_data;
    - u32 master_ctrl_data;
    + u32 mac_ctrl_data = 0;
    + u32 master_ctrl_data = 0;
    u32 wol_ctrl_data = 0;
    - u16 mii_bmsr_data;
    - u16 save_autoneg_advertised;
    - u16 mii_intr_status_data;
    + u16 mii_intr_status_data = 0;
    u32 wufc = adapter->wol;
    - u32 i;
    int retval = 0;

    + atl1c_disable_l0s_l1(hw);
    if (netif_running(netdev)) {
    WARN_ON(test_bit(__AT_RESETTING, &adapter->flags));
    atl1c_down(adapter);
    }
    netif_device_detach(netdev);
    - atl1c_disable_l0s_l1(hw);
    retval = pci_save_state(pdev);
    if (retval)
    return retval;
    +
    + if (wufc)
    + if (atl1c_phy_power_saving(hw) != 0)
    + dev_dbg(&pdev->dev, "phy power saving failed");
    +
    + AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data);
    + AT_READ_REG(hw, REG_MAC_CTRL, &mac_ctrl_data);
    +
    + master_ctrl_data &= ~MASTER_CTRL_CLK_SEL_DIS;
    + mac_ctrl_data &= ~(MAC_CTRL_PRMLEN_MASK << MAC_CTRL_PRMLEN_SHIFT);
    + mac_ctrl_data |= (((u32)adapter->hw.preamble_len &
    + MAC_CTRL_PRMLEN_MASK) <<
    + MAC_CTRL_PRMLEN_SHIFT);
    + mac_ctrl_data &= ~(MAC_CTRL_SPEED_MASK << MAC_CTRL_SPEED_SHIFT);
    + mac_ctrl_data &= ~MAC_CTRL_DUPLX;
    +
    if (wufc) {
    - AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data);
    - master_ctrl_data &= ~MASTER_CTRL_CLK_SEL_DIS;
    -
    - /* get link status */
    - atl1c_read_phy_reg(hw, MII_BMSR, (u16 *)&mii_bmsr_data);
    - atl1c_read_phy_reg(hw, MII_BMSR, (u16 *)&mii_bmsr_data);
    - save_autoneg_advertised = hw->autoneg_advertised;
    - hw->autoneg_advertised = ADVERTISED_10baseT_Half;
    - if (atl1c_restart_autoneg(hw) != 0)
    - if (netif_msg_link(adapter))
    - dev_warn(&pdev->dev, "phy autoneg failed\n");
    - hw->phy_configured = false; /* re-init PHY when resume */
    - hw->autoneg_advertised = save_autoneg_advertised;
    + mac_ctrl_data |= MAC_CTRL_RX_EN;
    + if (adapter->link_speed == SPEED_1000 ||
    + adapter->link_speed == SPEED_0) {
    + mac_ctrl_data |= atl1c_mac_speed_1000 <<
    + MAC_CTRL_SPEED_SHIFT;
    + mac_ctrl_data |= MAC_CTRL_DUPLX;
    + } else
    + mac_ctrl_data |= atl1c_mac_speed_10_100 <<
    + MAC_CTRL_SPEED_SHIFT;
    +
    + if (adapter->link_duplex == DUPLEX_FULL)
    + mac_ctrl_data |= MAC_CTRL_DUPLX;
    +
    /* turn on magic packet wol */
    if (wufc & AT_WUFC_MAG)
    - wol_ctrl_data = WOL_MAGIC_EN | WOL_MAGIC_PME_EN;
    + wol_ctrl_data |= WOL_MAGIC_EN | WOL_MAGIC_PME_EN;

    if (wufc & AT_WUFC_LNKC) {
    - for (i = 0; i < AT_SUSPEND_LINK_TIMEOUT; i++) {
    - msleep(100);
    - atl1c_read_phy_reg(hw, MII_BMSR,
    - (u16 *)&mii_bmsr_data);
    - if (mii_bmsr_data & BMSR_LSTATUS)
    - break;
    - }
    - if ((mii_bmsr_data & BMSR_LSTATUS) == 0)
    - if (netif_msg_link(adapter))
    - dev_warn(&pdev->dev,
    - "%s: Link may change"
    - "when suspend\n",
    - atl1c_driver_name);
    wol_ctrl_data |= WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN;
    /* only link up can wake up */
    if (atl1c_write_phy_reg(hw, MII_IER, IER_LINK_UP) != 0) {
    - if (netif_msg_link(adapter))
    - dev_err(&pdev->dev,
    - "%s: read write phy "
    - "register failed.\n",
    - atl1c_driver_name);
    - goto wol_dis;
    + dev_dbg(&pdev->dev, "%s: read write phy "
    + "register failed.\n",
    + atl1c_driver_name);
    }
    }
    /* clear phy interrupt */
    atl1c_read_phy_reg(hw, MII_ISR, &mii_intr_status_data);
    /* Config MAC Ctrl register */
    - mac_ctrl_data = MAC_CTRL_RX_EN;
    - /* set to 10/100M halt duplex */
    - mac_ctrl_data |= atl1c_mac_speed_10_100 << MAC_CTRL_SPEED_SHIFT;
    - mac_ctrl_data |= (((u32)adapter->hw.preamble_len &
    - MAC_CTRL_PRMLEN_MASK) <<
    - MAC_CTRL_PRMLEN_SHIFT);
    -
    if (adapter->vlgrp)
    mac_ctrl_data |= MAC_CTRL_RMV_VLAN;

    @@ -2467,37 +2516,30 @@ static int atl1c_suspend(struct pci_dev *pdev, pm_message_t state)
    if (wufc & AT_WUFC_MAG)
    mac_ctrl_data |= MAC_CTRL_BC_EN;

    - if (netif_msg_hw(adapter))
    - dev_dbg(&pdev->dev,
    - "%s: suspend MAC=0x%x\n",
    - atl1c_driver_name, mac_ctrl_data);
    + dev_dbg(&pdev->dev,
    + "%s: suspend MAC=0x%x\n",
    + atl1c_driver_name, mac_ctrl_data);
    AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data);
    AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl_data);
    AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);

    /* pcie patch */
    - AT_READ_REG(hw, REG_PCIE_PHYMISC, &ctrl);
    - ctrl |= PCIE_PHYMISC_FORCE_RCV_DET;
    - AT_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl);
    + device_set_wakeup_enable(&pdev->dev, 1);

    - pci_enable_wake(pdev, pci_choose_state(pdev, state), 1);
    - goto suspend_exit;
    + AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT |
    + GPHY_CTRL_EXT_RESET);
    + pci_prepare_to_sleep(pdev);
    + } else {
    + AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_POWER_SAVING);
    + master_ctrl_data |= MASTER_CTRL_CLK_SEL_DIS;
    + mac_ctrl_data |= atl1c_mac_speed_10_100 << MAC_CTRL_SPEED_SHIFT;
    + mac_ctrl_data |= MAC_CTRL_DUPLX;
    + AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data);
    + AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
    + AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
    + hw->phy_configured = false; /* re-init PHY when resume */
    + pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
    }
    -wol_dis:
    -
    - /* WOL disabled */
    - AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
    -
    - /* pcie patch */
    - AT_READ_REG(hw, REG_PCIE_PHYMISC, &ctrl);
    - ctrl |= PCIE_PHYMISC_FORCE_RCV_DET;
    - AT_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl);
    -
    - atl1c_phy_disable(hw);
    - hw->phy_configured = false; /* re-init PHY when resume */
    -
    - pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
    -suspend_exit:

    pci_disable_device(pdev);
    pci_set_power_state(pdev, pci_choose_state(pdev, state));
    @@ -2516,9 +2558,19 @@ static int atl1c_resume(struct pci_dev *pdev)
    pci_enable_wake(pdev, PCI_D3cold, 0);

    AT_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0);
    + atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE |
    + ATL1C_PCIE_PHY_RESET);

    atl1c_phy_reset(&adapter->hw);
    atl1c_reset_mac(&adapter->hw);
    + atl1c_phy_init(&adapter->hw);
    +
    +#if 0
    + AT_READ_REG(&adapter->hw, REG_PM_CTRLSTAT, &pm_data);
    + pm_data &= ~PM_CTRLSTAT_PME_EN;
    + AT_WRITE_REG(&adapter->hw, REG_PM_CTRLSTAT, pm_data);
    +#endif
    +
    netif_device_attach(netdev);
    if (netif_running(netdev))
    atl1c_up(adapter);

    \
     
     \ /
      Last update: 2010-05-28 09:45    [W:0.077 / U:30.656 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site