|
@@ -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);
|