atl1c: Add AR8151 v2 support and change L0s/L1 routine
Add AR8151 v2.0 Gigabit 1000 support Change jumbo frame size to 6K Update L0s/L1 rountine when link speed is 100M or 1G, set L1 link timer to 4 for l1d_2 and l2c_b2 set L1 link timer to 7 for l2c_b, set L1 link timer to 0xF for others. Update atl1c_suspend routine just refactory the function, add atl1c_phy_power_saving routine, when Wake On Lan enable, this func will be called to save power, it will reautoneg PHY to 10/100M speed depend on the link partners link capability. Update atl1c_configure_des_ring do not use l2c_b default SRAM configuration. Signed-off-by: Jie Yang <Jie.Yang@atheros.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
aac4dddc35
commit
8f574b35f2
|
@ -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;
|
||||
|
|
|
@ -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, <ssm_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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_LCKDET_TIMER_SHIFT);
|
||||
pm_ctrl_data |= AT_LCKDET_TIMER << 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;
|
||||
|
||||
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) {
|
||||
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;
|
||||
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) {
|
||||
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);
|
||||
|
|
Loading…
Reference in a new issue