@@ -66,8 +66,23 @@ enum vmd_features {
66
66
* interrupt handling.
67
67
*/
68
68
VMD_FEAT_CAN_BYPASS_MSI_REMAP = (1 << 4 ),
69
+
70
+ /*
71
+ * Enable ASPM on the PCIE root ports and set the default LTR of the
72
+ * storage devices on platforms where these values are not configured by
73
+ * BIOS. This is needed for laptops, which require these settings for
74
+ * proper power management of the SoC.
75
+ */
76
+ VMD_FEAT_BIOS_PM_QUIRK = (1 << 5 ),
69
77
};
70
78
79
+ #define VMD_BIOS_PM_QUIRK_LTR 0x1003 /* 3145728 ns */
80
+
81
+ #define VMD_FEATS_CLIENT (VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP | \
82
+ VMD_FEAT_HAS_BUS_RESTRICTIONS | \
83
+ VMD_FEAT_OFFSET_FIRST_VECTOR | \
84
+ VMD_FEAT_BIOS_PM_QUIRK)
85
+
71
86
static DEFINE_IDA (vmd_instance_ida );
72
87
73
88
/*
@@ -709,6 +724,46 @@ static void vmd_copy_host_bridge_flags(struct pci_host_bridge *root_bridge,
709
724
vmd_bridge -> native_dpc = root_bridge -> native_dpc ;
710
725
}
711
726
727
+ /*
728
+ * Enable ASPM and LTR settings on devices that aren't configured by BIOS.
729
+ */
730
+ static int vmd_pm_enable_quirk (struct pci_dev * pdev , void * userdata )
731
+ {
732
+ unsigned long features = * (unsigned long * )userdata ;
733
+ u16 ltr = VMD_BIOS_PM_QUIRK_LTR ;
734
+ u32 ltr_reg ;
735
+ int pos ;
736
+
737
+ if (!(features & VMD_FEAT_BIOS_PM_QUIRK ))
738
+ return 0 ;
739
+
740
+ pci_enable_link_state (pdev , PCIE_LINK_STATE_ALL );
741
+
742
+ pos = pci_find_ext_capability (pdev , PCI_EXT_CAP_ID_LTR );
743
+ if (!pos )
744
+ return 0 ;
745
+
746
+ /*
747
+ * Skip if the max snoop LTR is non-zero, indicating BIOS has set it
748
+ * so the LTR quirk is not needed.
749
+ */
750
+ pci_read_config_dword (pdev , pos + PCI_LTR_MAX_SNOOP_LAT , & ltr_reg );
751
+ if (!!(ltr_reg & (PCI_LTR_VALUE_MASK | PCI_LTR_SCALE_MASK )))
752
+ return 0 ;
753
+
754
+ /*
755
+ * Set the default values to the maximum required by the platform to
756
+ * allow the deepest power management savings. Write as a DWORD where
757
+ * the lower word is the max snoop latency and the upper word is the
758
+ * max non-snoop latency.
759
+ */
760
+ ltr_reg = (ltr << 16 ) | ltr ;
761
+ pci_write_config_dword (pdev , pos + PCI_LTR_MAX_SNOOP_LAT , ltr_reg );
762
+ pci_info (pdev , "VMD: Default LTR value set by driver\n" );
763
+
764
+ return 0 ;
765
+ }
766
+
712
767
static int vmd_enable_domain (struct vmd_dev * vmd , unsigned long features )
713
768
{
714
769
struct pci_sysdata * sd = & vmd -> sysdata ;
@@ -881,6 +936,8 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)
881
936
882
937
pci_assign_unassigned_bus_resources (vmd -> bus );
883
938
939
+ pci_walk_bus (vmd -> bus , vmd_pm_enable_quirk , & features );
940
+
884
941
/*
885
942
* VMD root buses are virtual and don't return true on pci_is_pcie()
886
943
* and will fail pcie_bus_configure_settings() early. It can instead be
@@ -1017,36 +1074,24 @@ static int vmd_resume(struct device *dev)
1017
1074
static SIMPLE_DEV_PM_OPS (vmd_dev_pm_ops , vmd_suspend , vmd_resume ) ;
1018
1075
1019
1076
static const struct pci_device_id vmd_ids [] = {
1020
- {PCI_DEVICE ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_VMD_201D ),
1077
+ {PCI_VDEVICE ( INTEL , PCI_DEVICE_ID_INTEL_VMD_201D ),
1021
1078
.driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP ,},
1022
- {PCI_DEVICE ( PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_VMD_28C0 ),
1079
+ {PCI_VDEVICE ( INTEL , PCI_DEVICE_ID_INTEL_VMD_28C0 ),
1023
1080
.driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW |
1024
1081
VMD_FEAT_HAS_BUS_RESTRICTIONS |
1025
1082
VMD_FEAT_CAN_BYPASS_MSI_REMAP ,},
1026
- {PCI_DEVICE (PCI_VENDOR_ID_INTEL , 0x467f ),
1027
- .driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP |
1028
- VMD_FEAT_HAS_BUS_RESTRICTIONS |
1029
- VMD_FEAT_OFFSET_FIRST_VECTOR ,},
1030
- {PCI_DEVICE (PCI_VENDOR_ID_INTEL , 0x4c3d ),
1031
- .driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP |
1032
- VMD_FEAT_HAS_BUS_RESTRICTIONS |
1033
- VMD_FEAT_OFFSET_FIRST_VECTOR ,},
1034
- {PCI_DEVICE (PCI_VENDOR_ID_INTEL , 0xa77f ),
1035
- .driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP |
1036
- VMD_FEAT_HAS_BUS_RESTRICTIONS |
1037
- VMD_FEAT_OFFSET_FIRST_VECTOR ,},
1038
- {PCI_DEVICE (PCI_VENDOR_ID_INTEL , 0x7d0b ),
1039
- .driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP |
1040
- VMD_FEAT_HAS_BUS_RESTRICTIONS |
1041
- VMD_FEAT_OFFSET_FIRST_VECTOR ,},
1042
- {PCI_DEVICE (PCI_VENDOR_ID_INTEL , 0xad0b ),
1043
- .driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP |
1044
- VMD_FEAT_HAS_BUS_RESTRICTIONS |
1045
- VMD_FEAT_OFFSET_FIRST_VECTOR ,},
1046
- {PCI_DEVICE (PCI_VENDOR_ID_INTEL , PCI_DEVICE_ID_INTEL_VMD_9A0B ),
1047
- .driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP |
1048
- VMD_FEAT_HAS_BUS_RESTRICTIONS |
1049
- VMD_FEAT_OFFSET_FIRST_VECTOR ,},
1083
+ {PCI_VDEVICE (INTEL , 0x467f ),
1084
+ .driver_data = VMD_FEATS_CLIENT ,},
1085
+ {PCI_VDEVICE (INTEL , 0x4c3d ),
1086
+ .driver_data = VMD_FEATS_CLIENT ,},
1087
+ {PCI_VDEVICE (INTEL , 0xa77f ),
1088
+ .driver_data = VMD_FEATS_CLIENT ,},
1089
+ {PCI_VDEVICE (INTEL , 0x7d0b ),
1090
+ .driver_data = VMD_FEATS_CLIENT ,},
1091
+ {PCI_VDEVICE (INTEL , 0xad0b ),
1092
+ .driver_data = VMD_FEATS_CLIENT ,},
1093
+ {PCI_VDEVICE (INTEL , PCI_DEVICE_ID_INTEL_VMD_9A0B ),
1094
+ .driver_data = VMD_FEATS_CLIENT ,},
1050
1095
{0 ,}
1051
1096
};
1052
1097
MODULE_DEVICE_TABLE (pci , vmd_ids );
0 commit comments