summaryrefslogtreecommitdiffstats
path: root/drivers/net/atl1c/atl1c_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/atl1c/atl1c_main.c')
-rw-r--r--drivers/net/atl1c/atl1c_main.c348
1 files changed, 200 insertions, 148 deletions
diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c
index 1c3c046d5f3..c7b8ef507eb 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);