@@ -623,6 +623,7 @@ struct rtl8169_private {
623
623
int cfg9346_usage_count ;
624
624
625
625
unsigned supports_gmii :1 ;
626
+ unsigned aspm_manageable :1 ;
626
627
dma_addr_t counters_phys_addr ;
627
628
struct rtl8169_counters * counters ;
628
629
struct rtl8169_tc_offsets tc_offset ;
@@ -2746,7 +2747,8 @@ static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
2746
2747
if (tp -> mac_version < RTL_GIGA_MAC_VER_32 )
2747
2748
return ;
2748
2749
2749
- if (enable ) {
2750
+ /* Don't enable ASPM in the chip if OS can't control ASPM */
2751
+ if (enable && tp -> aspm_manageable ) {
2750
2752
/* On these chip versions ASPM can even harm
2751
2753
* bus communication of other PCI devices.
2752
2754
*/
@@ -5165,6 +5167,16 @@ static void rtl_init_mac_address(struct rtl8169_private *tp)
5165
5167
rtl_rar_set (tp , mac_addr );
5166
5168
}
5167
5169
5170
+ /* register is set if system vendor successfully tested ASPM 1.2 */
5171
+ static bool rtl_aspm_is_safe (struct rtl8169_private * tp )
5172
+ {
5173
+ if (tp -> mac_version >= RTL_GIGA_MAC_VER_61 &&
5174
+ r8168_mac_ocp_read (tp , 0xc0b2 ) & 0xf )
5175
+ return true;
5176
+
5177
+ return false;
5178
+ }
5179
+
5168
5180
static int rtl_init_one (struct pci_dev * pdev , const struct pci_device_id * ent )
5169
5181
{
5170
5182
struct rtl8169_private * tp ;
@@ -5234,6 +5246,19 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
5234
5246
xid );
5235
5247
tp -> mac_version = chipset ;
5236
5248
5249
+ /* Disable ASPM L1 as that cause random device stop working
5250
+ * problems as well as full system hangs for some PCIe devices users.
5251
+ * Chips from RTL8168h partially have issues with L1.2, but seem
5252
+ * to work fine with L1 and L1.1.
5253
+ */
5254
+ if (rtl_aspm_is_safe (tp ))
5255
+ rc = 0 ;
5256
+ else if (tp -> mac_version >= RTL_GIGA_MAC_VER_46 )
5257
+ rc = pci_disable_link_state (pdev , PCIE_LINK_STATE_L1_2 );
5258
+ else
5259
+ rc = pci_disable_link_state (pdev , PCIE_LINK_STATE_L1 );
5260
+ tp -> aspm_manageable = !rc ;
5261
+
5237
5262
tp -> dash_type = rtl_check_dash (tp );
5238
5263
5239
5264
tp -> cp_cmd = RTL_R16 (tp , CPlusCmd ) & CPCMD_MASK ;
0 commit comments