@@ -4879,6 +4879,7 @@ void __weak pcibios_reset_secondary_bus(struct pci_dev *dev)
48794879 */
48804880int pci_bridge_secondary_bus_reset (struct pci_dev * dev )
48814881{
4882+ lock_map_assert_held (& dev -> cfg_access_lock );
48824883 pcibios_reset_secondary_bus (dev );
48834884
48844885 return pci_bridge_wait_for_secondary_bus (dev , "bus reset" );
@@ -4927,16 +4928,96 @@ static int pci_dev_reset_slot_function(struct pci_dev *dev, bool probe)
49274928 return pci_reset_hotplug_slot (dev -> slot -> hotplug , probe );
49284929}
49294930
4931+ static u16 cxl_port_dvsec (struct pci_dev * dev )
4932+ {
4933+ return pci_find_dvsec_capability (dev , PCI_VENDOR_ID_CXL ,
4934+ PCI_DVSEC_CXL_PORT );
4935+ }
4936+
4937+ static bool cxl_sbr_masked (struct pci_dev * dev )
4938+ {
4939+ u16 dvsec , reg ;
4940+ int rc ;
4941+
4942+ dvsec = cxl_port_dvsec (dev );
4943+ if (!dvsec )
4944+ return false;
4945+
4946+ rc = pci_read_config_word (dev , dvsec + PCI_DVSEC_CXL_PORT_CTL , & reg );
4947+ if (rc || PCI_POSSIBLE_ERROR (reg ))
4948+ return false;
4949+
4950+ /*
4951+ * Per CXL spec r3.1, sec 8.1.5.2, when "Unmask SBR" is 0, the SBR
4952+ * bit in Bridge Control has no effect. When 1, the Port generates
4953+ * hot reset when the SBR bit is set to 1.
4954+ */
4955+ if (reg & PCI_DVSEC_CXL_PORT_CTL_UNMASK_SBR )
4956+ return false;
4957+
4958+ return true;
4959+ }
4960+
49304961static int pci_reset_bus_function (struct pci_dev * dev , bool probe )
49314962{
4963+ struct pci_dev * bridge = pci_upstream_bridge (dev );
49324964 int rc ;
49334965
4966+ /*
4967+ * If "dev" is below a CXL port that has SBR control masked, SBR
4968+ * won't do anything, so return error.
4969+ */
4970+ if (bridge && cxl_sbr_masked (bridge )) {
4971+ if (probe )
4972+ return 0 ;
4973+
4974+ return - ENOTTY ;
4975+ }
4976+
49344977 rc = pci_dev_reset_slot_function (dev , probe );
49354978 if (rc != - ENOTTY )
49364979 return rc ;
49374980 return pci_parent_bus_reset (dev , probe );
49384981}
49394982
4983+ static int cxl_reset_bus_function (struct pci_dev * dev , bool probe )
4984+ {
4985+ struct pci_dev * bridge ;
4986+ u16 dvsec , reg , val ;
4987+ int rc ;
4988+
4989+ bridge = pci_upstream_bridge (dev );
4990+ if (!bridge )
4991+ return - ENOTTY ;
4992+
4993+ dvsec = cxl_port_dvsec (bridge );
4994+ if (!dvsec )
4995+ return - ENOTTY ;
4996+
4997+ if (probe )
4998+ return 0 ;
4999+
5000+ rc = pci_read_config_word (bridge , dvsec + PCI_DVSEC_CXL_PORT_CTL , & reg );
5001+ if (rc )
5002+ return - ENOTTY ;
5003+
5004+ if (reg & PCI_DVSEC_CXL_PORT_CTL_UNMASK_SBR ) {
5005+ val = reg ;
5006+ } else {
5007+ val = reg | PCI_DVSEC_CXL_PORT_CTL_UNMASK_SBR ;
5008+ pci_write_config_word (bridge , dvsec + PCI_DVSEC_CXL_PORT_CTL ,
5009+ val );
5010+ }
5011+
5012+ rc = pci_reset_bus_function (dev , probe );
5013+
5014+ if (reg != val )
5015+ pci_write_config_word (bridge , dvsec + PCI_DVSEC_CXL_PORT_CTL ,
5016+ reg );
5017+
5018+ return rc ;
5019+ }
5020+
49405021void pci_dev_lock (struct pci_dev * dev )
49415022{
49425023 /* block PM suspend, driver probe, etc. */
@@ -5021,6 +5102,7 @@ static const struct pci_reset_fn_method pci_reset_fn_methods[] = {
50215102 { pci_af_flr , .name = "af_flr" },
50225103 { pci_pm_reset , .name = "pm" },
50235104 { pci_reset_bus_function , .name = "bus" },
5105+ { cxl_reset_bus_function , .name = "cxl_bus" },
50245106};
50255107
50265108static ssize_t reset_method_show (struct device * dev ,
@@ -5245,11 +5327,20 @@ void pci_init_reset_methods(struct pci_dev *dev)
52455327 */
52465328int pci_reset_function (struct pci_dev * dev )
52475329{
5330+ struct pci_dev * bridge ;
52485331 int rc ;
52495332
52505333 if (!pci_reset_supported (dev ))
52515334 return - ENOTTY ;
52525335
5336+ /*
5337+ * If there's no upstream bridge, no locking is needed since there is
5338+ * no upstream bridge configuration to hold consistent.
5339+ */
5340+ bridge = pci_upstream_bridge (dev );
5341+ if (bridge )
5342+ pci_dev_lock (bridge );
5343+
52535344 pci_dev_lock (dev );
52545345 pci_dev_save_and_disable (dev );
52555346
@@ -5258,6 +5349,9 @@ int pci_reset_function(struct pci_dev *dev)
52585349 pci_dev_restore (dev );
52595350 pci_dev_unlock (dev );
52605351
5352+ if (bridge )
5353+ pci_dev_unlock (bridge );
5354+
52615355 return rc ;
52625356}
52635357EXPORT_SYMBOL_GPL (pci_reset_function );
0 commit comments