diff options
Diffstat (limited to 'drivers/net/atl1c/atl1c_main.c')
| -rw-r--r-- | drivers/net/atl1c/atl1c_main.c | 346 | 
1 files changed, 199 insertions, 147 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_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) +		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; +		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; -		/* 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;  		/* 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);  |