All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 01/11] PCI: Expose reset_type to users of __pci_reset_function_locked()
@ 2018-10-11  4:49 Sinan Kaya
  2018-10-11  4:49 ` [PATCH v5 02/11] PCI: Expose reset_type to users of pci_reset_function() Sinan Kaya
                   ` (9 more replies)
  0 siblings, 10 replies; 19+ messages in thread
From: Sinan Kaya @ 2018-10-11  4:49 UTC (permalink / raw)
  To: linux-pci
  Cc: Sinan Kaya, Derek Chickles, Satanand Burla, Felix Manlunas,
	Raghu Vatsavayi, David S. Miller, Bjorn Helgaas, Boris Ostrovsky,
	Juergen Gross, Jia-Ju Bai

We need a contract between the reset API users and the PCI core about the
types of reset that a user needs vs. what PCI core can do internally.
If a platform supports hotplug, we need to do hotplug reset as an example.

Expose the reset types to the drivers and try different reset types based
on the new reset_type parameter.

Most users are expected to use PCI_RESET_ANY, PCI_RESET_FUNC or
PCI_RESET_LINK parameters.

Link: https://www.spinics.net/lists/linux-pci/msg75828.html
Suggested-by: Alex Williamson <alex.williamson@redhat.com>
Signed-off-by: Sinan Kaya <okaya@kernel.org>
---
 .../net/ethernet/cavium/liquidio/lio_main.c   |  2 +-
 drivers/pci/pci.c                             | 59 ++++++++++++-------
 drivers/xen/xen-pciback/pci_stub.c            |  6 +-
 include/linux/pci.h                           | 56 +++++++++++++++++-
 4 files changed, 98 insertions(+), 25 deletions(-)

diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c
index 6fb13fa73b27..0ff76722734d 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -989,7 +989,7 @@ static void octeon_pci_flr(struct octeon_device *oct)
 	pci_write_config_word(oct->pci_dev, PCI_COMMAND,
 			      PCI_COMMAND_INTX_DISABLE);
 
-	rc = __pci_reset_function_locked(oct->pci_dev);
+	rc = __pci_reset_function_locked(oct->pci_dev, PCI_RESET_ANY);
 
 	if (rc != 0)
 		dev_err(&oct->pci_dev->dev, "Error %d resetting PCI function %d\n",
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 1835f3a7aa8d..e292ea589d3e 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -4673,6 +4673,7 @@ static void pci_dev_restore(struct pci_dev *dev)
  * __pci_reset_function_locked - reset a PCI device function while holding
  * the @dev mutex lock.
  * @dev: PCI device to reset
+ * @reset_type: reset mask to try
  *
  * Some devices allow an individual function to be reset without affecting
  * other functions in the same device.  The PCI device must be responsive
@@ -4688,9 +4689,9 @@ static void pci_dev_restore(struct pci_dev *dev)
  * Returns 0 if the device function was successfully reset or negative if the
  * device doesn't support resetting a single function.
  */
-int __pci_reset_function_locked(struct pci_dev *dev)
+int __pci_reset_function_locked(struct pci_dev *dev, u32 reset_type)
 {
-	int rc;
+	int rc = -EINVAL;
 
 	might_sleep();
 
@@ -4702,24 +4703,42 @@ int __pci_reset_function_locked(struct pci_dev *dev)
 	 * other error, we're also finished: this indicates that further
 	 * reset mechanisms might be broken on the device.
 	 */
-	rc = pci_dev_specific_reset(dev, 0);
-	if (rc != -ENOTTY)
-		return rc;
-	if (pcie_has_flr(dev)) {
-		rc = pcie_flr(dev);
+	if (reset_type & PCI_RESET_DEV_SPECIFIC) {
+		rc = pci_dev_specific_reset(dev, 0);
 		if (rc != -ENOTTY)
 			return rc;
 	}
-	rc = pci_af_flr(dev, 0);
-	if (rc != -ENOTTY)
-		return rc;
-	rc = pci_pm_reset(dev, 0);
-	if (rc != -ENOTTY)
-		return rc;
-	rc = pci_dev_reset_slot_function(dev, 0);
-	if (rc != -ENOTTY)
-		return rc;
-	return pci_parent_bus_reset(dev, 0);
+
+	if (reset_type & PCI_RESET_FLR) {
+		if (pcie_has_flr(dev)) {
+			rc = pcie_flr(dev);
+			if (rc != -ENOTTY)
+				return rc;
+		}
+		rc = pci_af_flr(dev, 0);
+		if (rc != -ENOTTY)
+			return rc;
+	}
+
+	if (reset_type & PCI_RESET_PM) {
+		rc = pci_pm_reset(dev, 0);
+		if (rc != -ENOTTY)
+			return rc;
+	}
+
+	if (reset_type & PCI_RESET_SLOT) {
+		rc = pci_dev_reset_slot_function(dev, 0);
+		if (rc != -ENOTTY)
+			return rc;
+	}
+
+	if (reset_type & PCI_RESET_BUS) {
+		rc = pci_parent_bus_reset(dev, 0);
+		if (rc != -ENOTTY)
+			return rc;
+	}
+
+	return rc;
 }
 EXPORT_SYMBOL_GPL(__pci_reset_function_locked);
 
@@ -4784,7 +4803,7 @@ int pci_reset_function(struct pci_dev *dev)
 	pci_dev_lock(dev);
 	pci_dev_save_and_disable(dev);
 
-	rc = __pci_reset_function_locked(dev);
+	rc = __pci_reset_function_locked(dev, PCI_RESET_ANY);
 
 	pci_dev_restore(dev);
 	pci_dev_unlock(dev);
@@ -4819,7 +4838,7 @@ int pci_reset_function_locked(struct pci_dev *dev)
 
 	pci_dev_save_and_disable(dev);
 
-	rc = __pci_reset_function_locked(dev);
+	rc = __pci_reset_function_locked(dev, PCI_RESET_ANY);
 
 	pci_dev_restore(dev);
 
@@ -4844,7 +4863,7 @@ int pci_try_reset_function(struct pci_dev *dev)
 		return -EAGAIN;
 
 	pci_dev_save_and_disable(dev);
-	rc = __pci_reset_function_locked(dev);
+	rc = __pci_reset_function_locked(dev, PCI_RESET_ANY);
 	pci_dev_restore(dev);
 	pci_dev_unlock(dev);
 
diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c
index 59661db144e5..6dfb805bcb19 100644
--- a/drivers/xen/xen-pciback/pci_stub.c
+++ b/drivers/xen/xen-pciback/pci_stub.c
@@ -105,7 +105,7 @@ static void pcistub_device_release(struct kref *kref)
 	/* Call the reset function which does not take lock as this
 	 * is called from "unbind" which takes a device_lock mutex.
 	 */
-	__pci_reset_function_locked(dev);
+	__pci_reset_function_locked(dev, PCI_RESET_ANY);
 	if (pci_load_and_free_saved_state(dev, &dev_data->pci_saved_state))
 		dev_info(&dev->dev, "Could not reload PCI state\n");
 	else
@@ -283,7 +283,7 @@ void pcistub_put_pci_dev(struct pci_dev *dev)
 	 * (so it's ready for the next domain)
 	 */
 	device_lock_assert(&dev->dev);
-	__pci_reset_function_locked(dev);
+	__pci_reset_function_locked(dev, PCI_RESET_ANY);
 
 	dev_data = pci_get_drvdata(dev);
 	ret = pci_load_saved_state(dev, dev_data->pci_saved_state);
@@ -417,7 +417,7 @@ static int pcistub_init_device(struct pci_dev *dev)
 		dev_err(&dev->dev, "Could not store PCI conf saved state!\n");
 	else {
 		dev_dbg(&dev->dev, "resetting (FLR, D3, etc) the device\n");
-		__pci_reset_function_locked(dev);
+		__pci_reset_function_locked(dev, PCI_RESET_ANY);
 		pci_restore_state(dev);
 	}
 	/* Now disable the device (this also ensures some private device
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 6925828f9f25..0967e6bad421 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -849,6 +849,60 @@ enum {
 	PCI_SCAN_ALL_PCIE_DEVS	= 0x00000040,	/* Scan all, not just dev 0 */
 };
 
+/*
+ * A common theme here is that the driver wants some degree of
+ * control of the type of reset used, vfio specifically wants to specify a
+ * bus or slot reset while hfi1 just wants to specify that the link is
+ * reset and doesn't care if it's a bus or slot reset that accomplishes
+ * that.  The right "unified" interface is one that takes a parameter
+ * allowing the caller to specify the scope or type of reset
+ * with aliases so drivers can ignore the hotplug interface if they wish
+ * for special cases.
+ *
+ * PCI_RESET_ANY tries all reset type one by one until device is successfully
+ * reset. Under normal circumstances, most drivers are expected to use
+ * PCI_RESET_ANY as they don't usually care about the type of reset as long
+ * as device is reset.
+ *
+ * PCI_RESET_FUNC is useful when you want to reset one particular PCI device
+ * but you don't want to impact other devices or cause a temporary service
+ * outage.
+ *
+ * PCI_RESET_LINK can be used to cause a link retraining. This operation will
+ * cause service outage for the PCI bus if there are other devices on the same
+ * bus. PCI_RESET_LINK determines if a platform supports hotplug or not and
+ * suppresses hotplug interrupts during secondary bus reset.
+ *
+ * PCI_RESET_DEV_SPECIFIC can be used to reset a device by help from the
+ * device driver. Not all device drivers support this option.
+ *
+ * PCI_RESET_FLR can be used to issue a Function Level Reset to a device. This
+ * option will fail if FLR is not supported.
+ *
+ * PCI_RESET_PM can be used to reset the device via D3->D0 and D0->D3 sleep
+ * transition. This assumes that device supports PM based reset.
+ *
+ * PCI_RESET_SLOT forces a slot/hotplug reset. This will not work on platforms
+ * without hotplug capability and assumes hotplug capability from a platform
+ * This option should only be used for advanced use-cases.
+ * Not recommended for scalability. Please refer to PCI_RESET_LINK.
+ *
+ * PCI_RESET_BUS performs a secondary bus reset on the link and causes a link
+ * recovery. Using this option directly and bypassing hotplug driver may
+ * cause a deadlock if platform supports hotplug. Please refer to
+ * PCI_RESET_LINK above.
+ */
+#define PCI_RESET_DEV_SPECIFIC	(1 << 0)
+#define PCI_RESET_FLR		(1 << 1)
+#define PCI_RESET_PM		(1 << 2)
+#define PCI_RESET_SLOT		(1 << 3)
+#define PCI_RESET_BUS		(1 << 4)
+
+#define PCI_RESET_ANY		(~0)
+#define PCI_RESET_FUNC		(PCI_RESET_DEV_SPECIFIC | \
+				 PCI_RESET_FLR | PCI_RESET_PM)
+#define PCI_RESET_LINK		(PCI_RESET_SLOT | PCI_RESET_BUS)
+
 /* These external functions are only available when PCI support is enabled */
 #ifdef CONFIG_PCI
 
@@ -1111,7 +1165,7 @@ u32 pcie_bandwidth_available(struct pci_dev *dev, struct pci_dev **limiting_dev,
 void pcie_print_link_status(struct pci_dev *dev);
 bool pcie_has_flr(struct pci_dev *dev);
 int pcie_flr(struct pci_dev *dev);
-int __pci_reset_function_locked(struct pci_dev *dev);
+int __pci_reset_function_locked(struct pci_dev *dev, u32 reset_type);
 int pci_reset_function(struct pci_dev *dev);
 int pci_reset_function_locked(struct pci_dev *dev);
 int pci_try_reset_function(struct pci_dev *dev);
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v5 02/11] PCI: Expose reset_type to users of pci_reset_function()
  2018-10-11  4:49 [PATCH v5 01/11] PCI: Expose reset_type to users of __pci_reset_function_locked() Sinan Kaya
@ 2018-10-11  4:49 ` Sinan Kaya
  2018-10-11  4:49 ` [PATCH v5 03/11] PCI: Expose reset_type to users of pci_reset_function_locked() Sinan Kaya
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Sinan Kaya @ 2018-10-11  4:49 UTC (permalink / raw)
  To: linux-pci
  Cc: Sinan Kaya, Srinivas Pandruvada, Jiri Kosina, Benjamin Tissoires,
	Frank Haverkamp, Guilherme G. Piccoli, Arnd Bergmann,
	Greg Kroah-Hartman, Harish Patil, Manish Chopra,
	Dept-GELinuxNICDev, David S. Miller,
	Solarflare linux maintainers, Edward Cree, Bert Kenward,
	Bjorn Helgaas, Anton Vasilyev

Looking to have more control between the users of the API vs. what the API
can do internally. The new reset_type tells the PCI core about the bounds
of the request.

PCI_RESET_ANY was chosen to match the existing behavior in the code.
Current pci_reset_function() tries all reset types one by one until
it returns 0. By specifying PCI_RESET_ANY, we get the same behavior like
before.

Signed-off-by: Sinan Kaya <okaya@kernel.org>
Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> (drivers/hid/intel-ish-hid/ipc/ipc.c)
---
 drivers/hid/intel-ish-hid/ipc/ipc.c             | 2 +-
 drivers/misc/genwqe/card_base.c                 | 2 +-
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c | 2 +-
 drivers/net/ethernet/sfc/mcdi.c                 | 2 +-
 drivers/pci/pci-sysfs.c                         | 2 +-
 drivers/pci/pci.c                               | 5 +++--
 include/linux/pci.h                             | 2 +-
 7 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/drivers/hid/intel-ish-hid/ipc/ipc.c b/drivers/hid/intel-ish-hid/ipc/ipc.c
index bfbca7ec54ce..18312969f1b3 100644
--- a/drivers/hid/intel-ish-hid/ipc/ipc.c
+++ b/drivers/hid/intel-ish-hid/ipc/ipc.c
@@ -754,7 +754,7 @@ static int _ish_hw_reset(struct ishtp_device *dev)
 	if (!pdev)
 		return	-ENODEV;
 
-	rv = pci_reset_function(pdev);
+	rv = pci_reset_function(pdev, PCI_RESET_ANY);
 	if (!rv)
 		dev->dev_state = ISHTP_DEV_RESETTING;
 
diff --git a/drivers/misc/genwqe/card_base.c b/drivers/misc/genwqe/card_base.c
index c7cd3675bcd1..cc78ef28ee38 100644
--- a/drivers/misc/genwqe/card_base.c
+++ b/drivers/misc/genwqe/card_base.c
@@ -201,7 +201,7 @@ static int genwqe_bus_reset(struct genwqe_dev *cd)
 	 * restored by the pci_reset_function().
 	 */
 	dev_dbg(&pci_dev->dev, "[%s] pci_reset function ...\n", __func__);
-	rc = pci_reset_function(pci_dev);
+	rc = pci_reset_function(pci_dev, PCI_RESET_ANY);
 	if (rc) {
 		dev_err(&pci_dev->dev,
 			"[%s] err: failed reset func (rc %d)\n", __func__, rc);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
index d344e9d43832..bb737725f175 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
@@ -629,7 +629,7 @@ int qlcnic_fw_create_ctx(struct qlcnic_adapter *dev)
 	int i, err, ring;
 
 	if (dev->flags & QLCNIC_NEED_FLR) {
-		pci_reset_function(dev->pdev);
+		pci_reset_function(dev->pdev, PCI_RESET_ANY);
 		dev->flags &= ~QLCNIC_NEED_FLR;
 	}
 
diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c
index dfad93fca0a6..7f95e17b8a48 100644
--- a/drivers/net/ethernet/sfc/mcdi.c
+++ b/drivers/net/ethernet/sfc/mcdi.c
@@ -1862,7 +1862,7 @@ int efx_mcdi_reset(struct efx_nic *efx, enum reset_type method)
 
 	/* If MCDI is down, we can't handle_assertion */
 	if (method == RESET_TYPE_MCDI_TIMEOUT) {
-		rc = pci_reset_function(efx->pci_dev);
+		rc = pci_reset_function(efx->pci_dev, PCI_RESET_ANY);
 		if (rc)
 			return rc;
 		/* Re-enable polled MCDI completion */
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 9ecfe13157c0..9569664ec4b2 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -1449,7 +1449,7 @@ static ssize_t reset_store(struct device *dev, struct device_attribute *attr,
 		return -EINVAL;
 
 	pm_runtime_get_sync(dev);
-	result = pci_reset_function(pdev);
+	result = pci_reset_function(pdev, PCI_RESET_ANY);
 	pm_runtime_put(dev);
 	if (result < 0)
 		return result;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index e292ea589d3e..66f102b7ed4e 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -4780,6 +4780,7 @@ int pci_probe_reset_function(struct pci_dev *dev)
 /**
  * pci_reset_function - quiesce and reset a PCI device function
  * @dev: PCI device to reset
+ * @reset_type: reset type to apply
  *
  * Some devices allow an individual function to be reset without affecting
  * other functions in the same device.  The PCI device must be responsive
@@ -4793,7 +4794,7 @@ int pci_probe_reset_function(struct pci_dev *dev)
  * Returns 0 if the device function was successfully reset or negative if the
  * device doesn't support resetting a single function.
  */
-int pci_reset_function(struct pci_dev *dev)
+int pci_reset_function(struct pci_dev *dev, u32 reset_type)
 {
 	int rc;
 
@@ -4803,7 +4804,7 @@ int pci_reset_function(struct pci_dev *dev)
 	pci_dev_lock(dev);
 	pci_dev_save_and_disable(dev);
 
-	rc = __pci_reset_function_locked(dev, PCI_RESET_ANY);
+	rc = __pci_reset_function_locked(dev, reset_type);
 
 	pci_dev_restore(dev);
 	pci_dev_unlock(dev);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 0967e6bad421..b72689f869db 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1166,7 +1166,7 @@ void pcie_print_link_status(struct pci_dev *dev);
 bool pcie_has_flr(struct pci_dev *dev);
 int pcie_flr(struct pci_dev *dev);
 int __pci_reset_function_locked(struct pci_dev *dev, u32 reset_type);
-int pci_reset_function(struct pci_dev *dev);
+int pci_reset_function(struct pci_dev *dev, u32 reset_type);
 int pci_reset_function_locked(struct pci_dev *dev);
 int pci_try_reset_function(struct pci_dev *dev);
 int pci_probe_reset_slot(struct pci_slot *slot);
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v5 03/11] PCI: Expose reset_type to users of pci_reset_function_locked()
  2018-10-11  4:49 [PATCH v5 01/11] PCI: Expose reset_type to users of __pci_reset_function_locked() Sinan Kaya
  2018-10-11  4:49 ` [PATCH v5 02/11] PCI: Expose reset_type to users of pci_reset_function() Sinan Kaya
@ 2018-10-11  4:49 ` Sinan Kaya
  2018-10-11  4:49 ` [PATCH v5 04/11] PCI: Expose reset type to users of pci_try_reset_function() Sinan Kaya
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Sinan Kaya @ 2018-10-11  4:49 UTC (permalink / raw)
  To: linux-pci; +Cc: Sinan Kaya, Bjorn Helgaas

Looking to have more control between the users of the API vs. what the API
can do internally. The new reset_type tells the PCI core about the bounds
of the request.

Signed-off-by: Sinan Kaya <okaya@kernel.org>
---
 drivers/pci/pci.c   | 5 +++--
 include/linux/pci.h | 2 +-
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 66f102b7ed4e..9a649d1adb13 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -4816,6 +4816,7 @@ EXPORT_SYMBOL_GPL(pci_reset_function);
 /**
  * pci_reset_function_locked - quiesce and reset a PCI device function
  * @dev: PCI device to reset
+ * @reset_type: reset type to apply
  *
  * Some devices allow an individual function to be reset without affecting
  * other functions in the same device.  The PCI device must be responsive
@@ -4830,7 +4831,7 @@ EXPORT_SYMBOL_GPL(pci_reset_function);
  * Returns 0 if the device function was successfully reset or negative if the
  * device doesn't support resetting a single function.
  */
-int pci_reset_function_locked(struct pci_dev *dev)
+int pci_reset_function_locked(struct pci_dev *dev, u32 reset_type)
 {
 	int rc;
 
@@ -4839,7 +4840,7 @@ int pci_reset_function_locked(struct pci_dev *dev)
 
 	pci_dev_save_and_disable(dev);
 
-	rc = __pci_reset_function_locked(dev, PCI_RESET_ANY);
+	rc = __pci_reset_function_locked(dev, reset_type);
 
 	pci_dev_restore(dev);
 
diff --git a/include/linux/pci.h b/include/linux/pci.h
index b72689f869db..e1d1328172fa 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1167,7 +1167,7 @@ bool pcie_has_flr(struct pci_dev *dev);
 int pcie_flr(struct pci_dev *dev);
 int __pci_reset_function_locked(struct pci_dev *dev, u32 reset_type);
 int pci_reset_function(struct pci_dev *dev, u32 reset_type);
-int pci_reset_function_locked(struct pci_dev *dev);
+int pci_reset_function_locked(struct pci_dev *dev, u32 reset_type);
 int pci_try_reset_function(struct pci_dev *dev);
 int pci_probe_reset_slot(struct pci_slot *slot);
 int pci_probe_reset_bus(struct pci_bus *bus);
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v5 04/11] PCI: Expose reset type to users of pci_try_reset_function()
  2018-10-11  4:49 [PATCH v5 01/11] PCI: Expose reset_type to users of __pci_reset_function_locked() Sinan Kaya
  2018-10-11  4:49 ` [PATCH v5 02/11] PCI: Expose reset_type to users of pci_reset_function() Sinan Kaya
  2018-10-11  4:49 ` [PATCH v5 03/11] PCI: Expose reset_type to users of pci_reset_function_locked() Sinan Kaya
@ 2018-10-11  4:49 ` Sinan Kaya
  2018-10-11  4:49 ` [PATCH v5 05/11] PCI: Expose reset type to users of pci_probe_reset_function() Sinan Kaya
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Sinan Kaya @ 2018-10-11  4:49 UTC (permalink / raw)
  To: linux-pci
  Cc: Sinan Kaya, Bjorn Helgaas, Alex Williamson, Alexey Kardashevskiy,
	Peter Xu, Gustavo A. R. Silva

Looking to have more control between the users of the API vs. what the API
can do internally. The new reset_type tells the PCI core about the bounds
of the request.

Signed-off-by: Sinan Kaya <okaya@kernel.org>
---
 drivers/pci/pci.c                  | 5 +++--
 drivers/vfio/pci/vfio_pci.c        | 7 ++++---
 drivers/vfio/pci/vfio_pci_config.c | 4 ++--
 include/linux/pci.h                | 2 +-
 4 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 9a649d1adb13..7739f28988ae 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -4851,10 +4851,11 @@ EXPORT_SYMBOL_GPL(pci_reset_function_locked);
 /**
  * pci_try_reset_function - quiesce and reset a PCI device function
  * @dev: PCI device to reset
+ * @reset_type: reset type to apply
  *
  * Same as above, except return -EAGAIN if unable to lock device.
  */
-int pci_try_reset_function(struct pci_dev *dev)
+int pci_try_reset_function(struct pci_dev *dev, u32 reset_type)
 {
 	int rc;
 
@@ -4865,7 +4866,7 @@ int pci_try_reset_function(struct pci_dev *dev)
 		return -EAGAIN;
 
 	pci_dev_save_and_disable(dev);
-	rc = __pci_reset_function_locked(dev, PCI_RESET_ANY);
+	rc = __pci_reset_function_locked(dev, reset_type);
 	pci_dev_restore(dev);
 	pci_dev_unlock(dev);
 
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
index cddb453a1ba5..fe7ada997c51 100644
--- a/drivers/vfio/pci/vfio_pci.c
+++ b/drivers/vfio/pci/vfio_pci.c
@@ -228,7 +228,7 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev)
 		return ret;
 
 	/* If reset fails because of the device lock, fail this path entirely */
-	ret = pci_try_reset_function(pdev);
+	ret = pci_try_reset_function(pdev, PCI_RESET_ANY);
 	if (ret == -EAGAIN) {
 		pci_disable_device(pdev);
 		return ret;
@@ -376,7 +376,7 @@ static void vfio_pci_disable(struct vfio_pci_device *vdev)
 	 * Try to reset the device.  The success of this is dependent on
 	 * being able to lock the device, which is not always possible.
 	 */
-	if (vdev->reset_works && !pci_try_reset_function(pdev))
+	if (vdev->reset_works && !pci_try_reset_function(pdev, PCI_RESET_ANY))
 		vdev->needs_reset = false;
 
 	pci_restore_state(pdev);
@@ -844,7 +844,8 @@ static long vfio_pci_ioctl(void *device_data,
 
 	} else if (cmd == VFIO_DEVICE_RESET) {
 		return vdev->reset_works ?
-			pci_try_reset_function(vdev->pdev) : -EINVAL;
+			pci_try_reset_function(vdev->pdev, PCI_RESET_ANY) :
+			 -EINVAL;
 
 	} else if (cmd == VFIO_DEVICE_GET_PCI_HOT_RESET_INFO) {
 		struct vfio_pci_hot_reset_info hdr;
diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c
index 115a36f6f403..0d66bac66211 100644
--- a/drivers/vfio/pci/vfio_pci_config.c
+++ b/drivers/vfio/pci/vfio_pci_config.c
@@ -831,7 +831,7 @@ static int vfio_exp_config_write(struct vfio_pci_device *vdev, int pos,
 						 &cap);
 
 		if (!ret && (cap & PCI_EXP_DEVCAP_FLR))
-			pci_try_reset_function(vdev->pdev);
+			pci_try_reset_function(vdev->pdev, PCI_RESET_ANY);
 	}
 
 	/*
@@ -910,7 +910,7 @@ static int vfio_af_config_write(struct vfio_pci_device *vdev, int pos,
 						&cap);
 
 		if (!ret && (cap & PCI_AF_CAP_FLR) && (cap & PCI_AF_CAP_TP))
-			pci_try_reset_function(vdev->pdev);
+			pci_try_reset_function(vdev->pdev, PCI_RESET_ANY);
 	}
 
 	return count;
diff --git a/include/linux/pci.h b/include/linux/pci.h
index e1d1328172fa..1c120cf00dd8 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1168,7 +1168,7 @@ int pcie_flr(struct pci_dev *dev);
 int __pci_reset_function_locked(struct pci_dev *dev, u32 reset_type);
 int pci_reset_function(struct pci_dev *dev, u32 reset_type);
 int pci_reset_function_locked(struct pci_dev *dev, u32 reset_type);
-int pci_try_reset_function(struct pci_dev *dev);
+int pci_try_reset_function(struct pci_dev *dev, u32 reset_type);
 int pci_probe_reset_slot(struct pci_slot *slot);
 int pci_probe_reset_bus(struct pci_bus *bus);
 int pci_reset_bus(struct pci_dev *dev);
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v5 05/11] PCI: Expose reset type to users of pci_probe_reset_function()
  2018-10-11  4:49 [PATCH v5 01/11] PCI: Expose reset_type to users of __pci_reset_function_locked() Sinan Kaya
                   ` (2 preceding siblings ...)
  2018-10-11  4:49 ` [PATCH v5 04/11] PCI: Expose reset type to users of pci_try_reset_function() Sinan Kaya
@ 2018-10-11  4:49 ` Sinan Kaya
  2018-10-11  4:49 ` [PATCH v5 06/11] PCI: Expose reset type to users of pci_reset_bus() Sinan Kaya
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Sinan Kaya @ 2018-10-11  4:49 UTC (permalink / raw)
  To: linux-pci; +Cc: Sinan Kaya, Bjorn Helgaas

Looking to have more control between the users of the API vs. what the API
can do internally. The new reset_type tells the PCI core about the bounds
of the request.

Signed-off-by: Sinan Kaya <okaya@kernel.org>
---
 drivers/pci/pci.c   | 52 ++++++++++++++++++++++++++++++---------------
 drivers/pci/pci.h   |  2 +-
 drivers/pci/probe.c |  2 +-
 3 files changed, 37 insertions(+), 19 deletions(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 7739f28988ae..a1a7dd6988be 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -4745,6 +4745,7 @@ EXPORT_SYMBOL_GPL(__pci_reset_function_locked);
 /**
  * pci_probe_reset_function - check whether the device can be safely reset
  * @dev: PCI device to reset
+ * @reset_type: reset type to apply
  *
  * Some devices allow an individual function to be reset without affecting
  * other functions in the same device.  The PCI device must be responsive
@@ -4753,28 +4754,45 @@ EXPORT_SYMBOL_GPL(__pci_reset_function_locked);
  * Returns 0 if the device function can be reset or negative if the
  * device doesn't support resetting a single function.
  */
-int pci_probe_reset_function(struct pci_dev *dev)
+int pci_probe_reset_function(struct pci_dev *dev, u32 reset_type)
 {
-	int rc;
+	int rc = 0;
 
 	might_sleep();
 
-	rc = pci_dev_specific_reset(dev, 1);
-	if (rc != -ENOTTY)
-		return rc;
-	if (pcie_has_flr(dev))
-		return 0;
-	rc = pci_af_flr(dev, 1);
-	if (rc != -ENOTTY)
-		return rc;
-	rc = pci_pm_reset(dev, 1);
-	if (rc != -ENOTTY)
-		return rc;
-	rc = pci_dev_reset_slot_function(dev, 1);
-	if (rc != -ENOTTY)
-		return rc;
+	if (reset_type & PCI_RESET_DEV_SPECIFIC) {
+		rc = pci_dev_specific_reset(dev, 1);
+		if (rc != -ENOTTY)
+			return rc;
+	}
+
+	if (reset_type & PCI_RESET_FLR) {
+		if (pcie_has_flr(dev))
+			return 0;
+		rc = pci_af_flr(dev, 1);
+		if (rc != -ENOTTY)
+			return rc;
+	}
 
-	return pci_parent_bus_reset(dev, 1);
+	if (reset_type & PCI_RESET_PM) {
+		rc = pci_pm_reset(dev, 1);
+		if (rc != -ENOTTY)
+			return rc;
+	}
+
+	if (reset_type & PCI_RESET_SLOT) {
+		rc = pci_dev_reset_slot_function(dev, 1);
+		if (rc != -ENOTTY)
+			return rc;
+	}
+
+	if (reset_type & PCI_RESET_BUS) {
+		rc = pci_parent_bus_reset(dev, 1);
+		if (rc != -ENOTTY)
+			return rc;
+	}
+
+	return rc;
 }
 
 /**
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 6e0d1528d471..0444bfa51b52 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -33,7 +33,7 @@ enum pci_mmap_api {
 int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vmai,
 		  enum pci_mmap_api mmap_api);
 
-int pci_probe_reset_function(struct pci_dev *dev);
+int pci_probe_reset_function(struct pci_dev *dev, u32 reset_type);
 int pci_bridge_secondary_bus_reset(struct pci_dev *dev);
 
 /**
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 201f9e5ff55c..6c8f6af2d4aa 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -2335,7 +2335,7 @@ static void pci_init_capabilities(struct pci_dev *dev)
 
 	pcie_report_downtraining(dev);
 
-	if (pci_probe_reset_function(dev) == 0)
+	if (pci_probe_reset_function(dev, PCI_RESET_ANY) == 0)
 		dev->reset_fn = 1;
 }
 
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v5 06/11] PCI: Expose reset type to users of pci_reset_bus()
  2018-10-11  4:49 [PATCH v5 01/11] PCI: Expose reset_type to users of __pci_reset_function_locked() Sinan Kaya
                   ` (3 preceding siblings ...)
  2018-10-11  4:49 ` [PATCH v5 05/11] PCI: Expose reset type to users of pci_probe_reset_function() Sinan Kaya
@ 2018-10-11  4:49 ` Sinan Kaya
  2018-10-11 15:33   ` Alex Williamson
  2018-10-11  4:49 ` [PATCH v5 07/11] IB/hfi1,PCI: switch to __pci_function_locked() for reset request Sinan Kaya
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 19+ messages in thread
From: Sinan Kaya @ 2018-10-11  4:49 UTC (permalink / raw)
  To: linux-pci
  Cc: Sinan Kaya, Bjorn Helgaas, Alex Williamson, Alexey Kardashevskiy,
	Peter Xu, Gustavo A. R. Silva

Looking to have more control between the users of the API vs. what the API
can do internally. The new reset_type tells the PCI core about the bounds
of the request.

Signed-off-by: Sinan Kaya <okaya@kernel.org>
---
 drivers/pci/pci.c           | 17 ++++++++++++++---
 drivers/vfio/pci/vfio_pci.c |  6 ++++--
 include/linux/pci.h         |  2 +-
 3 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index a1a7dd6988be..a3a1c2a5e0cf 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -5236,13 +5236,24 @@ static int __pci_reset_bus(struct pci_bus *bus)
 /**
  * pci_reset_bus - Try to reset a PCI bus
  * @pdev: top level PCI device to reset via slot/bus
+ * @reset_type: resets to try
  *
  * Same as above except return -EAGAIN if the bus cannot be locked
  */
-int pci_reset_bus(struct pci_dev *pdev)
+int pci_reset_bus(struct pci_dev *pdev, u32 reset_type)
 {
-	return (!pci_probe_reset_slot(pdev->slot)) ?
-	    __pci_reset_slot(pdev->slot) : __pci_reset_bus(pdev->bus);
+	if ((reset_type & PCI_RESET_LINK) == PCI_RESET_LINK)
+		return (!pci_probe_reset_slot(pdev->slot)) ?
+				__pci_reset_slot(pdev->slot) :
+				__pci_reset_bus(pdev->bus);
+
+	if ((reset_type & PCI_RESET_BUS) == PCI_RESET_BUS)
+		return __pci_reset_bus(pdev->bus);
+
+	if ((reset_type & PCI_RESET_SLOT) == PCI_RESET_SLOT)
+		return __pci_reset_slot(pdev->slot);
+
+	return -EINVAL;
 }
 EXPORT_SYMBOL_GPL(pci_reset_bus);
 
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
index fe7ada997c51..0e80c72b1eaa 100644
--- a/drivers/vfio/pci/vfio_pci.c
+++ b/drivers/vfio/pci/vfio_pci.c
@@ -1015,7 +1015,8 @@ static long vfio_pci_ioctl(void *device_data,
 						    &info, slot);
 		if (!ret)
 			/* User has access, do the reset */
-			ret = pci_reset_bus(vdev->pdev);
+			ret = pci_reset_bus(vdev->pdev,
+				slot ? PCI_RESET_SLOT :	PCI_RESET_BUS);
 
 hot_reset_release:
 		for (i--; i >= 0; i--)
@@ -1390,7 +1391,8 @@ static void vfio_pci_try_bus_reset(struct vfio_pci_device *vdev)
 	}
 
 	if (needs_reset)
-		ret = pci_reset_bus(vdev->pdev);
+		ret = pci_reset_bus(vdev->pdev,
+				slot ? PCI_RESET_SLOT :	PCI_RESET_BUS);
 
 put_devs:
 	for (i = 0; i < devs.cur_index; i++) {
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 1c120cf00dd8..cf1e847ea02e 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1171,7 +1171,7 @@ int pci_reset_function_locked(struct pci_dev *dev, u32 reset_type);
 int pci_try_reset_function(struct pci_dev *dev, u32 reset_type);
 int pci_probe_reset_slot(struct pci_slot *slot);
 int pci_probe_reset_bus(struct pci_bus *bus);
-int pci_reset_bus(struct pci_dev *dev);
+int pci_reset_bus(struct pci_dev *dev, u32 reset_type);
 void pci_reset_secondary_bus(struct pci_dev *dev);
 void pcibios_reset_secondary_bus(struct pci_dev *dev);
 void pci_update_resource(struct pci_dev *dev, int resno);
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v5 07/11] IB/hfi1,PCI: switch to __pci_function_locked() for reset request
  2018-10-11  4:49 [PATCH v5 01/11] PCI: Expose reset_type to users of __pci_reset_function_locked() Sinan Kaya
                   ` (4 preceding siblings ...)
  2018-10-11  4:49 ` [PATCH v5 06/11] PCI: Expose reset type to users of pci_reset_bus() Sinan Kaya
@ 2018-10-11  4:49 ` Sinan Kaya
  2018-10-11  4:50 ` [PATCH v5 08/11] PCI: Unify pci_reset_function_locked() and __pci_reset_function_locked() Sinan Kaya
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Sinan Kaya @ 2018-10-11  4:49 UTC (permalink / raw)
  To: linux-pci
  Cc: Sinan Kaya, Mike Marciniszyn, Dennis Dalessandro, Doug Ledford,
	Jason Gunthorpe, Bjorn Helgaas

Start using the new reset API rather than the workaround.

Signed-off-by: Sinan Kaya <okaya@kernel.org>
---
 drivers/infiniband/hw/hfi1/pcie.c | 2 +-
 include/linux/pci.h               | 3 ---
 2 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/infiniband/hw/hfi1/pcie.c b/drivers/infiniband/hw/hfi1/pcie.c
index 6c967dde58e7..38f96192e5f0 100644
--- a/drivers/infiniband/hw/hfi1/pcie.c
+++ b/drivers/infiniband/hw/hfi1/pcie.c
@@ -897,7 +897,7 @@ static int trigger_sbr(struct hfi1_devdata *dd)
 	 * to be implemented to have cleaner interface but this fixes the
 	 * current brokenness
 	 */
-	return pci_bridge_secondary_bus_reset(dev->bus->self);
+	return __pci_reset_function_locked(dev, PCI_RESET_LINK);
 }
 
 /*
diff --git a/include/linux/pci.h b/include/linux/pci.h
index cf1e847ea02e..d4acdc400ef2 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1289,9 +1289,6 @@ void pci_bus_remove_resources(struct pci_bus *bus);
 int devm_request_pci_bus_resources(struct device *dev,
 				   struct list_head *resources);
 
-/* Temporary until new and working PCI SBR API in place */
-int pci_bridge_secondary_bus_reset(struct pci_dev *dev);
-
 #define pci_bus_for_each_resource(bus, res, i)				\
 	for (i = 0;							\
 	    (res = pci_bus_resource_n(bus, i)) || i < PCI_BRIDGE_RESOURCE_NUM; \
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v5 08/11] PCI: Unify pci_reset_function_locked() and __pci_reset_function_locked()
  2018-10-11  4:49 [PATCH v5 01/11] PCI: Expose reset_type to users of __pci_reset_function_locked() Sinan Kaya
                   ` (5 preceding siblings ...)
  2018-10-11  4:49 ` [PATCH v5 07/11] IB/hfi1,PCI: switch to __pci_function_locked() for reset request Sinan Kaya
@ 2018-10-11  4:50 ` Sinan Kaya
  2018-10-11 16:02   ` Alex Williamson
  2018-10-12  9:18   ` Christoph Hellwig
  2018-10-11  4:50 ` [PATCH v5 09/11] PCI: Add options to pci_reset_function Sinan Kaya
                   ` (2 subsequent siblings)
  9 siblings, 2 replies; 19+ messages in thread
From: Sinan Kaya @ 2018-10-11  4:50 UTC (permalink / raw)
  To: linux-pci
  Cc: Sinan Kaya, Mike Marciniszyn, Dennis Dalessandro, Doug Ledford,
	Jason Gunthorpe, Derek Chickles, Satanand Burla, Felix Manlunas,
	Raghu Vatsavayi, David S. Miller, Bjorn Helgaas, Boris Ostrovsky,
	Juergen Gross, Jia-Ju Bai

The difference between pci_reset_function_locked() and
__pci_reset_function_locked() is the saving and restoring of the registers.
Unify these API by adding saverestore argument that caller passes.

Signed-off-by: Sinan Kaya <okaya@kernel.org>
---
 drivers/infiniband/hw/hfi1/pcie.c               |  2 +-
 drivers/net/ethernet/cavium/liquidio/lio_main.c |  2 +-
 drivers/pci/pci.c                               | 10 +++++++---
 drivers/pci/pci.h                               |  1 +
 drivers/xen/xen-pciback/pci_stub.c              |  6 +++---
 include/linux/pci.h                             |  4 ++--
 6 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/drivers/infiniband/hw/hfi1/pcie.c b/drivers/infiniband/hw/hfi1/pcie.c
index 38f96192e5f0..73eced9c5523 100644
--- a/drivers/infiniband/hw/hfi1/pcie.c
+++ b/drivers/infiniband/hw/hfi1/pcie.c
@@ -897,7 +897,7 @@ static int trigger_sbr(struct hfi1_devdata *dd)
 	 * to be implemented to have cleaner interface but this fixes the
 	 * current brokenness
 	 */
-	return __pci_reset_function_locked(dev, PCI_RESET_LINK);
+	return pci_reset_function_locked(dev, PCI_RESET_LINK, false);
 }
 
 /*
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c
index 0ff76722734d..7e001382ad93 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -989,7 +989,7 @@ static void octeon_pci_flr(struct octeon_device *oct)
 	pci_write_config_word(oct->pci_dev, PCI_COMMAND,
 			      PCI_COMMAND_INTX_DISABLE);
 
-	rc = __pci_reset_function_locked(oct->pci_dev, PCI_RESET_ANY);
+	rc = pci_reset_function_locked(oct->pci_dev, PCI_RESET_ANY, false);
 
 	if (rc != 0)
 		dev_err(&oct->pci_dev->dev, "Error %d resetting PCI function %d\n",
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index a3a1c2a5e0cf..97328dc8e476 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -4835,6 +4835,7 @@ EXPORT_SYMBOL_GPL(pci_reset_function);
  * pci_reset_function_locked - quiesce and reset a PCI device function
  * @dev: PCI device to reset
  * @reset_type: reset type to apply
+ * @saverestore: Flag indicating whether device context should be saved.
  *
  * Some devices allow an individual function to be reset without affecting
  * other functions in the same device.  The PCI device must be responsive
@@ -4849,18 +4850,21 @@ EXPORT_SYMBOL_GPL(pci_reset_function);
  * Returns 0 if the device function was successfully reset or negative if the
  * device doesn't support resetting a single function.
  */
-int pci_reset_function_locked(struct pci_dev *dev, u32 reset_type)
+int pci_reset_function_locked(struct pci_dev *dev, u32 reset_type,
+			      bool saverestore)
 {
 	int rc;
 
 	if (!dev->reset_fn)
 		return -ENOTTY;
 
-	pci_dev_save_and_disable(dev);
+	if (saverestore)
+		pci_dev_save_and_disable(dev);
 
 	rc = __pci_reset_function_locked(dev, reset_type);
 
-	pci_dev_restore(dev);
+	if (saverestore)
+		pci_dev_restore(dev);
 
 	return rc;
 }
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 0444bfa51b52..fbfb44fb32b7 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -35,6 +35,7 @@ int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vmai,
 
 int pci_probe_reset_function(struct pci_dev *dev, u32 reset_type);
 int pci_bridge_secondary_bus_reset(struct pci_dev *dev);
+int __pci_reset_function_locked(struct pci_dev *dev, u32 reset_type);
 
 /**
  * struct pci_platform_pm_ops - Firmware PM callbacks
diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c
index 6dfb805bcb19..b68e811ab27f 100644
--- a/drivers/xen/xen-pciback/pci_stub.c
+++ b/drivers/xen/xen-pciback/pci_stub.c
@@ -105,7 +105,7 @@ static void pcistub_device_release(struct kref *kref)
 	/* Call the reset function which does not take lock as this
 	 * is called from "unbind" which takes a device_lock mutex.
 	 */
-	__pci_reset_function_locked(dev, PCI_RESET_ANY);
+	pci_reset_function_locked(dev, PCI_RESET_ANY, false);
 	if (pci_load_and_free_saved_state(dev, &dev_data->pci_saved_state))
 		dev_info(&dev->dev, "Could not reload PCI state\n");
 	else
@@ -283,7 +283,7 @@ void pcistub_put_pci_dev(struct pci_dev *dev)
 	 * (so it's ready for the next domain)
 	 */
 	device_lock_assert(&dev->dev);
-	__pci_reset_function_locked(dev, PCI_RESET_ANY);
+	pci_reset_function_locked(dev, PCI_RESET_ANY, false);
 
 	dev_data = pci_get_drvdata(dev);
 	ret = pci_load_saved_state(dev, dev_data->pci_saved_state);
@@ -417,7 +417,7 @@ static int pcistub_init_device(struct pci_dev *dev)
 		dev_err(&dev->dev, "Could not store PCI conf saved state!\n");
 	else {
 		dev_dbg(&dev->dev, "resetting (FLR, D3, etc) the device\n");
-		__pci_reset_function_locked(dev, PCI_RESET_ANY);
+		pci_reset_function_locked(dev, PCI_RESET_ANY, false);
 		pci_restore_state(dev);
 	}
 	/* Now disable the device (this also ensures some private device
diff --git a/include/linux/pci.h b/include/linux/pci.h
index d4acdc400ef2..84d08a9a01e3 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1165,9 +1165,9 @@ u32 pcie_bandwidth_available(struct pci_dev *dev, struct pci_dev **limiting_dev,
 void pcie_print_link_status(struct pci_dev *dev);
 bool pcie_has_flr(struct pci_dev *dev);
 int pcie_flr(struct pci_dev *dev);
-int __pci_reset_function_locked(struct pci_dev *dev, u32 reset_type);
 int pci_reset_function(struct pci_dev *dev, u32 reset_type);
-int pci_reset_function_locked(struct pci_dev *dev, u32 reset_type);
+int pci_reset_function_locked(struct pci_dev *dev, u32 reset_type,
+			      bool saverestore);
 int pci_try_reset_function(struct pci_dev *dev, u32 reset_type);
 int pci_probe_reset_slot(struct pci_slot *slot);
 int pci_probe_reset_bus(struct pci_bus *bus);
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v5 09/11] PCI: Add options to pci_reset_function
  2018-10-11  4:49 [PATCH v5 01/11] PCI: Expose reset_type to users of __pci_reset_function_locked() Sinan Kaya
                   ` (6 preceding siblings ...)
  2018-10-11  4:50 ` [PATCH v5 08/11] PCI: Unify pci_reset_function_locked() and __pci_reset_function_locked() Sinan Kaya
@ 2018-10-11  4:50 ` Sinan Kaya
  2018-10-12  9:18   ` Christoph Hellwig
  2018-10-11  4:50 ` [PATCH v5 10/11] PCI: Hide pci_reset_function_locked() Sinan Kaya
  2018-10-11  4:50 ` [PATCH v5 11/11] PCI: Hide pcie_flr() in favor of pci_reset_function() Sinan Kaya
  9 siblings, 1 reply; 19+ messages in thread
From: Sinan Kaya @ 2018-10-11  4:50 UTC (permalink / raw)
  To: linux-pci
  Cc: Sinan Kaya, Srinivas Pandruvada, Jiri Kosina, Benjamin Tissoires,
	Frank Haverkamp, Guilherme G. Piccoli, Arnd Bergmann,
	Greg Kroah-Hartman, Harish Patil, Manish Chopra,
	Dept-GELinuxNICDev, David S. Miller,
	Solarflare linux maintainers, Edward Cree, Bert Kenward,
	Bjorn Helgaas, Anton Vasilyev

Getting ready to deprecate pci_reset_function_locked(). Add
saverestore and locked parameters to pci_reset_function() function
and add saverestore = true and locked = false to all existing
callers.

Signed-off-by: Sinan Kaya <okaya@kernel.org>
---
 drivers/hid/intel-ish-hid/ipc/ipc.c           |  2 +-
 drivers/misc/genwqe/card_base.c               |  2 +-
 .../net/ethernet/qlogic/qlcnic/qlcnic_ctx.c   |  2 +-
 drivers/net/ethernet/sfc/mcdi.c               |  3 ++-
 drivers/pci/pci-sysfs.c                       |  2 +-
 drivers/pci/pci.c                             | 20 ++++++++++++++-----
 include/linux/pci.h                           |  3 ++-
 7 files changed, 23 insertions(+), 11 deletions(-)

diff --git a/drivers/hid/intel-ish-hid/ipc/ipc.c b/drivers/hid/intel-ish-hid/ipc/ipc.c
index 18312969f1b3..5fa7cdd136fe 100644
--- a/drivers/hid/intel-ish-hid/ipc/ipc.c
+++ b/drivers/hid/intel-ish-hid/ipc/ipc.c
@@ -754,7 +754,7 @@ static int _ish_hw_reset(struct ishtp_device *dev)
 	if (!pdev)
 		return	-ENODEV;
 
-	rv = pci_reset_function(pdev, PCI_RESET_ANY);
+	rv = pci_reset_function(pdev, PCI_RESET_ANY, true, false);
 	if (!rv)
 		dev->dev_state = ISHTP_DEV_RESETTING;
 
diff --git a/drivers/misc/genwqe/card_base.c b/drivers/misc/genwqe/card_base.c
index cc78ef28ee38..85eb3ca55ccb 100644
--- a/drivers/misc/genwqe/card_base.c
+++ b/drivers/misc/genwqe/card_base.c
@@ -201,7 +201,7 @@ static int genwqe_bus_reset(struct genwqe_dev *cd)
 	 * restored by the pci_reset_function().
 	 */
 	dev_dbg(&pci_dev->dev, "[%s] pci_reset function ...\n", __func__);
-	rc = pci_reset_function(pci_dev, PCI_RESET_ANY);
+	rc = pci_reset_function(pci_dev, PCI_RESET_ANY, true, false);
 	if (rc) {
 		dev_err(&pci_dev->dev,
 			"[%s] err: failed reset func (rc %d)\n", __func__, rc);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
index bb737725f175..4fb3ea301af8 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
@@ -629,7 +629,7 @@ int qlcnic_fw_create_ctx(struct qlcnic_adapter *dev)
 	int i, err, ring;
 
 	if (dev->flags & QLCNIC_NEED_FLR) {
-		pci_reset_function(dev->pdev, PCI_RESET_ANY);
+		pci_reset_function(dev->pdev, PCI_RESET_ANY, true, false);
 		dev->flags &= ~QLCNIC_NEED_FLR;
 	}
 
diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c
index 7f95e17b8a48..2406cd38f258 100644
--- a/drivers/net/ethernet/sfc/mcdi.c
+++ b/drivers/net/ethernet/sfc/mcdi.c
@@ -1862,7 +1862,8 @@ int efx_mcdi_reset(struct efx_nic *efx, enum reset_type method)
 
 	/* If MCDI is down, we can't handle_assertion */
 	if (method == RESET_TYPE_MCDI_TIMEOUT) {
-		rc = pci_reset_function(efx->pci_dev, PCI_RESET_ANY);
+		rc = pci_reset_function(efx->pci_dev, PCI_RESET_ANY, true,
+					false);
 		if (rc)
 			return rc;
 		/* Re-enable polled MCDI completion */
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 9569664ec4b2..939de1d323ad 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -1449,7 +1449,7 @@ static ssize_t reset_store(struct device *dev, struct device_attribute *attr,
 		return -EINVAL;
 
 	pm_runtime_get_sync(dev);
-	result = pci_reset_function(pdev, PCI_RESET_ANY);
+	result = pci_reset_function(pdev, PCI_RESET_ANY, true, false);
 	pm_runtime_put(dev);
 	if (result < 0)
 		return result;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 97328dc8e476..b34909376221 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -4799,6 +4799,9 @@ int pci_probe_reset_function(struct pci_dev *dev, u32 reset_type)
  * pci_reset_function - quiesce and reset a PCI device function
  * @dev: PCI device to reset
  * @reset_type: reset type to apply
+ * @saverestore: flag for save/restore the device state before and after reset
+ * @locked: flag for obtaining device lock. true if caller is already holding
+ *          the lock.
  *
  * Some devices allow an individual function to be reset without affecting
  * other functions in the same device.  The PCI device must be responsive
@@ -4812,20 +4815,27 @@ int pci_probe_reset_function(struct pci_dev *dev, u32 reset_type)
  * Returns 0 if the device function was successfully reset or negative if the
  * device doesn't support resetting a single function.
  */
-int pci_reset_function(struct pci_dev *dev, u32 reset_type)
+int pci_reset_function(struct pci_dev *dev, u32 reset_type, bool saverestore,
+		       bool locked)
 {
 	int rc;
 
 	if (!dev->reset_fn)
 		return -ENOTTY;
 
-	pci_dev_lock(dev);
-	pci_dev_save_and_disable(dev);
+	if (!locked)
+		pci_dev_lock(dev);
+
+	if (saverestore)
+		pci_dev_save_and_disable(dev);
 
 	rc = __pci_reset_function_locked(dev, reset_type);
 
-	pci_dev_restore(dev);
-	pci_dev_unlock(dev);
+	if (saverestore)
+		pci_dev_restore(dev);
+
+	if (!locked)
+		pci_dev_unlock(dev);
 
 	return rc;
 }
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 84d08a9a01e3..82b326eb624b 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1165,7 +1165,8 @@ u32 pcie_bandwidth_available(struct pci_dev *dev, struct pci_dev **limiting_dev,
 void pcie_print_link_status(struct pci_dev *dev);
 bool pcie_has_flr(struct pci_dev *dev);
 int pcie_flr(struct pci_dev *dev);
-int pci_reset_function(struct pci_dev *dev, u32 reset_type);
+int pci_reset_function(struct pci_dev *dev, u32 reset_type, bool saverestore,
+		       bool locked);
 int pci_reset_function_locked(struct pci_dev *dev, u32 reset_type,
 			      bool saverestore);
 int pci_try_reset_function(struct pci_dev *dev, u32 reset_type);
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v5 10/11] PCI: Hide pci_reset_function_locked()
  2018-10-11  4:49 [PATCH v5 01/11] PCI: Expose reset_type to users of __pci_reset_function_locked() Sinan Kaya
                   ` (7 preceding siblings ...)
  2018-10-11  4:50 ` [PATCH v5 09/11] PCI: Add options to pci_reset_function Sinan Kaya
@ 2018-10-11  4:50 ` Sinan Kaya
  2018-10-11  4:50 ` [PATCH v5 11/11] PCI: Hide pcie_flr() in favor of pci_reset_function() Sinan Kaya
  9 siblings, 0 replies; 19+ messages in thread
From: Sinan Kaya @ 2018-10-11  4:50 UTC (permalink / raw)
  To: linux-pci
  Cc: Sinan Kaya, Mike Marciniszyn, Dennis Dalessandro, Doug Ledford,
	Jason Gunthorpe, Derek Chickles, Satanand Burla, Felix Manlunas,
	Raghu Vatsavayi, David S. Miller, Bjorn Helgaas, Boris Ostrovsky,
	Juergen Gross, Jia-Ju Bai

It is time to hide pci_reset_function_locked() since pci_reset_function()
provides the same functionality. One less API to expose to the users.

Signed-off-by: Sinan Kaya <okaya@kernel.org>
---
 drivers/infiniband/hw/hfi1/pcie.c               | 2 +-
 drivers/net/ethernet/cavium/liquidio/lio_main.c | 2 +-
 drivers/pci/pci.h                               | 2 ++
 drivers/xen/xen-pciback/pci_stub.c              | 6 +++---
 include/linux/pci.h                             | 2 --
 5 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/infiniband/hw/hfi1/pcie.c b/drivers/infiniband/hw/hfi1/pcie.c
index 73eced9c5523..8fbcde36353d 100644
--- a/drivers/infiniband/hw/hfi1/pcie.c
+++ b/drivers/infiniband/hw/hfi1/pcie.c
@@ -897,7 +897,7 @@ static int trigger_sbr(struct hfi1_devdata *dd)
 	 * to be implemented to have cleaner interface but this fixes the
 	 * current brokenness
 	 */
-	return pci_reset_function_locked(dev, PCI_RESET_LINK, false);
+	return pci_reset_function(dev, PCI_RESET_LINK, false, true);
 }
 
 /*
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c
index 7e001382ad93..e1ff9818ed6b 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -989,7 +989,7 @@ static void octeon_pci_flr(struct octeon_device *oct)
 	pci_write_config_word(oct->pci_dev, PCI_COMMAND,
 			      PCI_COMMAND_INTX_DISABLE);
 
-	rc = pci_reset_function_locked(oct->pci_dev, PCI_RESET_ANY, false);
+	rc = pci_reset_function(oct->pci_dev, PCI_RESET_ANY, false, true);
 
 	if (rc != 0)
 		dev_err(&oct->pci_dev->dev, "Error %d resetting PCI function %d\n",
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index fbfb44fb32b7..737fdc36fe36 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -36,6 +36,8 @@ int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vmai,
 int pci_probe_reset_function(struct pci_dev *dev, u32 reset_type);
 int pci_bridge_secondary_bus_reset(struct pci_dev *dev);
 int __pci_reset_function_locked(struct pci_dev *dev, u32 reset_type);
+int pci_reset_function_locked(struct pci_dev *dev, u32 reset_type,
+			      bool saverestore);
 
 /**
  * struct pci_platform_pm_ops - Firmware PM callbacks
diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c
index b68e811ab27f..6806a58c30d5 100644
--- a/drivers/xen/xen-pciback/pci_stub.c
+++ b/drivers/xen/xen-pciback/pci_stub.c
@@ -105,7 +105,7 @@ static void pcistub_device_release(struct kref *kref)
 	/* Call the reset function which does not take lock as this
 	 * is called from "unbind" which takes a device_lock mutex.
 	 */
-	pci_reset_function_locked(dev, PCI_RESET_ANY, false);
+	pci_reset_function(dev, PCI_RESET_ANY, false, true);
 	if (pci_load_and_free_saved_state(dev, &dev_data->pci_saved_state))
 		dev_info(&dev->dev, "Could not reload PCI state\n");
 	else
@@ -283,7 +283,7 @@ void pcistub_put_pci_dev(struct pci_dev *dev)
 	 * (so it's ready for the next domain)
 	 */
 	device_lock_assert(&dev->dev);
-	pci_reset_function_locked(dev, PCI_RESET_ANY, false);
+	pci_reset_function(dev, PCI_RESET_ANY, false, true);
 
 	dev_data = pci_get_drvdata(dev);
 	ret = pci_load_saved_state(dev, dev_data->pci_saved_state);
@@ -417,7 +417,7 @@ static int pcistub_init_device(struct pci_dev *dev)
 		dev_err(&dev->dev, "Could not store PCI conf saved state!\n");
 	else {
 		dev_dbg(&dev->dev, "resetting (FLR, D3, etc) the device\n");
-		pci_reset_function_locked(dev, PCI_RESET_ANY, false);
+		pci_reset_function(dev, PCI_RESET_ANY, false, true);
 		pci_restore_state(dev);
 	}
 	/* Now disable the device (this also ensures some private device
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 82b326eb624b..95efffd09690 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1167,8 +1167,6 @@ bool pcie_has_flr(struct pci_dev *dev);
 int pcie_flr(struct pci_dev *dev);
 int pci_reset_function(struct pci_dev *dev, u32 reset_type, bool saverestore,
 		       bool locked);
-int pci_reset_function_locked(struct pci_dev *dev, u32 reset_type,
-			      bool saverestore);
 int pci_try_reset_function(struct pci_dev *dev, u32 reset_type);
 int pci_probe_reset_slot(struct pci_slot *slot);
 int pci_probe_reset_bus(struct pci_bus *bus);
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v5 11/11] PCI: Hide pcie_flr() in favor of pci_reset_function()
  2018-10-11  4:49 [PATCH v5 01/11] PCI: Expose reset_type to users of __pci_reset_function_locked() Sinan Kaya
                   ` (8 preceding siblings ...)
  2018-10-11  4:50 ` [PATCH v5 10/11] PCI: Hide pci_reset_function_locked() Sinan Kaya
@ 2018-10-11  4:50 ` Sinan Kaya
  2018-10-11 15:41   ` Sinan Kaya
  9 siblings, 1 reply; 19+ messages in thread
From: Sinan Kaya @ 2018-10-11  4:50 UTC (permalink / raw)
  To: linux-pci
  Cc: Sinan Kaya, Giovanni Cabiddu, Herbert Xu, David S. Miller,
	Mike Marciniszyn, Dennis Dalessandro, Doug Ledford,
	Jason Gunthorpe, Derek Chickles, Satanand Burla, Felix Manlunas,
	Raghu Vatsavayi, Jeff Kirsher, Bjorn Helgaas, Jia-Ju Bai

Now that we have a unified API for device reset, let's eliminate
one duplication by hiding pcie_flr().

Signed-off-by: Sinan Kaya <okaya@kernel.org>
---
 drivers/crypto/qat/qat_common/adf_aer.c            | 3 ++-
 drivers/infiniband/hw/hfi1/chip.c                  | 5 +++--
 drivers/net/ethernet/cavium/liquidio/lio_vf_main.c | 3 ++-
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c      | 6 ++++--
 drivers/pci/pci.h                                  | 1 +
 include/linux/pci.h                                | 1 -
 6 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/crypto/qat/qat_common/adf_aer.c b/drivers/crypto/qat/qat_common/adf_aer.c
index 9225d060e18f..9326685dd89f 100644
--- a/drivers/crypto/qat/qat_common/adf_aer.c
+++ b/drivers/crypto/qat/qat_common/adf_aer.c
@@ -109,7 +109,8 @@ EXPORT_SYMBOL_GPL(adf_reset_sbr);
 
 void adf_reset_flr(struct adf_accel_dev *accel_dev)
 {
-	pcie_flr(accel_to_pci_dev(accel_dev));
+	pci_reset_function(accel_to_pci_dev(accel_dev), PCI_RESET_FLR,
+			   false, true);
 }
 EXPORT_SYMBOL_GPL(adf_reset_flr);
 
diff --git a/drivers/infiniband/hw/hfi1/chip.c b/drivers/infiniband/hw/hfi1/chip.c
index e1668bcc2d13..12bc5ef81e12 100644
--- a/drivers/infiniband/hw/hfi1/chip.c
+++ b/drivers/infiniband/hw/hfi1/chip.c
@@ -14077,7 +14077,7 @@ static int init_chip(struct hfi1_devdata *dd)
 		dd_dev_info(dd, "Resetting CSRs with FLR\n");
 
 		/* do the FLR, the DC reset will remain */
-		pcie_flr(dd->pcidev);
+		pci_reset_function(dd->pcidev, PCI_RESET_FLR, false, true);
 
 		/* restore command and BARs */
 		ret = restore_pci_variables(dd);
@@ -14089,7 +14089,8 @@ static int init_chip(struct hfi1_devdata *dd)
 
 		if (is_ax(dd)) {
 			dd_dev_info(dd, "Resetting CSRs with FLR\n");
-			pcie_flr(dd->pcidev);
+			pci_reset_function(dd->pcidev, PCI_RESET_FLR, false,
+					   true);
 			ret = restore_pci_variables(dd);
 			if (ret) {
 				dd_dev_err(dd, "%s: Could not restore PCI variables\n",
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
index b77835724dc8..6af086337359 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
@@ -438,7 +438,8 @@ static void octeon_pci_flr(struct octeon_device *oct)
 	pci_write_config_word(oct->pci_dev, PCI_COMMAND,
 			      PCI_COMMAND_INTX_DISABLE);
 
-	pcie_flr(oct->pci_dev);
+	pci_reset_function(oct->pci_dev, PCI_RESET_FUNCTION,
+			   false, true);
 
 	pci_cfg_access_unlock(oct->pci_dev);
 
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index f27d73a7bf16..6345c2c11c62 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -7539,7 +7539,8 @@ static void ixgbe_check_for_bad_vf(struct ixgbe_adapter *adapter)
 		pci_read_config_word(vfdev, PCI_STATUS, &status_reg);
 		if (status_reg != IXGBE_FAILED_READ_CFG_WORD &&
 		    status_reg & PCI_STATUS_REC_MASTER_ABORT)
-			pcie_flr(vfdev);
+			pci_reset_function(vfdev, PCI_RESET_FLR, false
+					   true);
 	}
 }
 
@@ -11046,7 +11047,8 @@ static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev,
 		 * VFLR.  Just clean up the AER in that case.
 		 */
 		if (vfdev) {
-			pcie_flr(vfdev);
+			pci_reset_function(vfdev, PCI_RESET_FUNCTION, false,
+					   true);
 			/* Free device reference count */
 			pci_dev_put(vfdev);
 		}
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 737fdc36fe36..c1dc92b1cc1e 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -38,6 +38,7 @@ int pci_bridge_secondary_bus_reset(struct pci_dev *dev);
 int __pci_reset_function_locked(struct pci_dev *dev, u32 reset_type);
 int pci_reset_function_locked(struct pci_dev *dev, u32 reset_type,
 			      bool saverestore);
+int pcie_flr(struct pci_dev *dev);
 
 /**
  * struct pci_platform_pm_ops - Firmware PM callbacks
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 95efffd09690..acaf115841cc 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1164,7 +1164,6 @@ u32 pcie_bandwidth_available(struct pci_dev *dev, struct pci_dev **limiting_dev,
 			     enum pcie_link_width *width);
 void pcie_print_link_status(struct pci_dev *dev);
 bool pcie_has_flr(struct pci_dev *dev);
-int pcie_flr(struct pci_dev *dev);
 int pci_reset_function(struct pci_dev *dev, u32 reset_type, bool saverestore,
 		       bool locked);
 int pci_try_reset_function(struct pci_dev *dev, u32 reset_type);
-- 
2.19.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH v5 06/11] PCI: Expose reset type to users of pci_reset_bus()
  2018-10-11  4:49 ` [PATCH v5 06/11] PCI: Expose reset type to users of pci_reset_bus() Sinan Kaya
@ 2018-10-11 15:33   ` Alex Williamson
  2018-10-11 15:36     ` Sinan Kaya
  0 siblings, 1 reply; 19+ messages in thread
From: Alex Williamson @ 2018-10-11 15:33 UTC (permalink / raw)
  To: Sinan Kaya
  Cc: linux-pci, Bjorn Helgaas, Alexey Kardashevskiy, Peter Xu,
	Gustavo A. R. Silva

On Thu, 11 Oct 2018 04:49:58 +0000
Sinan Kaya <okaya@kernel.org> wrote:

> Looking to have more control between the users of the API vs. what the API
> can do internally. The new reset_type tells the PCI core about the bounds
> of the request.
> 
> Signed-off-by: Sinan Kaya <okaya@kernel.org>
> ---
>  drivers/pci/pci.c           | 17 ++++++++++++++---
>  drivers/vfio/pci/vfio_pci.c |  6 ++++--
>  include/linux/pci.h         |  2 +-
>  3 files changed, 19 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index a1a7dd6988be..a3a1c2a5e0cf 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -5236,13 +5236,24 @@ static int __pci_reset_bus(struct pci_bus *bus)
>  /**
>   * pci_reset_bus - Try to reset a PCI bus
>   * @pdev: top level PCI device to reset via slot/bus
> + * @reset_type: resets to try
>   *
>   * Same as above except return -EAGAIN if the bus cannot be locked
>   */
> -int pci_reset_bus(struct pci_dev *pdev)
> +int pci_reset_bus(struct pci_dev *pdev, u32 reset_type)
>  {
> -	return (!pci_probe_reset_slot(pdev->slot)) ?
> -	    __pci_reset_slot(pdev->slot) : __pci_reset_bus(pdev->bus);
> +	if ((reset_type & PCI_RESET_LINK) == PCI_RESET_LINK)
> +		return (!pci_probe_reset_slot(pdev->slot)) ?
> +				__pci_reset_slot(pdev->slot) :
> +				__pci_reset_bus(pdev->bus);
> +
> +	if ((reset_type & PCI_RESET_BUS) == PCI_RESET_BUS)
> +		return __pci_reset_bus(pdev->bus);
> +
> +	if ((reset_type & PCI_RESET_SLOT) == PCI_RESET_SLOT)
> +		return __pci_reset_slot(pdev->slot);
> +
> +	return -EINVAL;


Having three cases here still seems strange.  The below still has some
duplicate probing but doesn't it do the same thing with less redundancy?

if ((reset_type & PCI_RESET_SLOT) && !pci_probe_reset_slot(pdev->slot))
	return __pci_reset_slot(pdev->slot);

if ((reset_type & PCI_RESET_BUS) && !pci_probe_reset_bus(pdev->slot))
	return __pci_reset_bus(pdev->bus);

return -EINVAL;

Thanks,
Alex

>  }
>  EXPORT_SYMBOL_GPL(pci_reset_bus);
>  
> diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
> index fe7ada997c51..0e80c72b1eaa 100644
> --- a/drivers/vfio/pci/vfio_pci.c
> +++ b/drivers/vfio/pci/vfio_pci.c
> @@ -1015,7 +1015,8 @@ static long vfio_pci_ioctl(void *device_data,
>  						    &info, slot);
>  		if (!ret)
>  			/* User has access, do the reset */
> -			ret = pci_reset_bus(vdev->pdev);
> +			ret = pci_reset_bus(vdev->pdev,
> +				slot ? PCI_RESET_SLOT :	PCI_RESET_BUS);
>  
>  hot_reset_release:
>  		for (i--; i >= 0; i--)
> @@ -1390,7 +1391,8 @@ static void vfio_pci_try_bus_reset(struct vfio_pci_device *vdev)
>  	}
>  
>  	if (needs_reset)
> -		ret = pci_reset_bus(vdev->pdev);
> +		ret = pci_reset_bus(vdev->pdev,
> +				slot ? PCI_RESET_SLOT :	PCI_RESET_BUS);
>  
>  put_devs:
>  	for (i = 0; i < devs.cur_index; i++) {
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 1c120cf00dd8..cf1e847ea02e 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -1171,7 +1171,7 @@ int pci_reset_function_locked(struct pci_dev *dev, u32 reset_type);
>  int pci_try_reset_function(struct pci_dev *dev, u32 reset_type);
>  int pci_probe_reset_slot(struct pci_slot *slot);
>  int pci_probe_reset_bus(struct pci_bus *bus);
> -int pci_reset_bus(struct pci_dev *dev);
> +int pci_reset_bus(struct pci_dev *dev, u32 reset_type);
>  void pci_reset_secondary_bus(struct pci_dev *dev);
>  void pcibios_reset_secondary_bus(struct pci_dev *dev);
>  void pci_update_resource(struct pci_dev *dev, int resno);


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v5 06/11] PCI: Expose reset type to users of pci_reset_bus()
  2018-10-11 15:33   ` Alex Williamson
@ 2018-10-11 15:36     ` Sinan Kaya
  0 siblings, 0 replies; 19+ messages in thread
From: Sinan Kaya @ 2018-10-11 15:36 UTC (permalink / raw)
  To: Alex Williamson
  Cc: linux-pci, Bjorn Helgaas, Alexey Kardashevskiy, Peter Xu,
	Gustavo A. R. Silva

On 10/11/2018 11:33 AM, Alex Williamson wrote:
> Having three cases here still seems strange.  The below still has some
> duplicate probing but doesn't it do the same thing with less redundancy?
> 
> if ((reset_type & PCI_RESET_SLOT) && !pci_probe_reset_slot(pdev->slot))
> 	return __pci_reset_slot(pdev->slot);
> 
> if ((reset_type & PCI_RESET_BUS) && !pci_probe_reset_bus(pdev->slot))
> 	return __pci_reset_bus(pdev->bus);

I agree this looks cleaner. I'll fold it in on the next rev.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v5 11/11] PCI: Hide pcie_flr() in favor of pci_reset_function()
  2018-10-11  4:50 ` [PATCH v5 11/11] PCI: Hide pcie_flr() in favor of pci_reset_function() Sinan Kaya
@ 2018-10-11 15:41   ` Sinan Kaya
  0 siblings, 0 replies; 19+ messages in thread
From: Sinan Kaya @ 2018-10-11 15:41 UTC (permalink / raw)
  To: linux-pci
  Cc: Giovanni Cabiddu, Herbert Xu, David S. Miller, Mike Marciniszyn,
	Dennis Dalessandro, Doug Ledford, Jason Gunthorpe,
	Derek Chickles, Satanand Burla, Felix Manlunas, Raghu Vatsavayi,
	Jeff Kirsher, Bjorn Helgaas, Jia-Ju Bai

On 10/11/2018 12:50 AM, Sinan Kaya wrote:
> Now that we have a unified API for device reset, let's eliminate
> one duplication by hiding pcie_flr().
> 
> Signed-off-by: Sinan Kaya<okaya@kernel.org>

This patch might have gone too far. I'm willing to drop it.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v5 08/11] PCI: Unify pci_reset_function_locked() and __pci_reset_function_locked()
  2018-10-11  4:50 ` [PATCH v5 08/11] PCI: Unify pci_reset_function_locked() and __pci_reset_function_locked() Sinan Kaya
@ 2018-10-11 16:02   ` Alex Williamson
  2018-10-11 16:11     ` Sinan Kaya
  2018-10-12  9:18   ` Christoph Hellwig
  1 sibling, 1 reply; 19+ messages in thread
From: Alex Williamson @ 2018-10-11 16:02 UTC (permalink / raw)
  To: Sinan Kaya
  Cc: linux-pci, Mike Marciniszyn, Dennis Dalessandro, Doug Ledford,
	Jason Gunthorpe, Derek Chickles, Satanand Burla, Felix Manlunas,
	Raghu Vatsavayi, David S. Miller, Bjorn Helgaas, Boris Ostrovsky,
	Juergen Gross, Jia-Ju Bai

On Thu, 11 Oct 2018 04:50:00 +0000
Sinan Kaya <okaya@kernel.org> wrote:

> The difference between pci_reset_function_locked() and
> __pci_reset_function_locked() is the saving and restoring of the registers.
> Unify these API by adding saverestore argument that caller passes.
> 
> Signed-off-by: Sinan Kaya <okaya@kernel.org>
> ---
>  drivers/infiniband/hw/hfi1/pcie.c               |  2 +-
>  drivers/net/ethernet/cavium/liquidio/lio_main.c |  2 +-
>  drivers/pci/pci.c                               | 10 +++++++---
>  drivers/pci/pci.h                               |  1 +
>  drivers/xen/xen-pciback/pci_stub.c              |  6 +++---
>  include/linux/pci.h                             |  4 ++--
>  6 files changed, 15 insertions(+), 10 deletions(-)

TBH, I'm not a fan of this patch or the remainder in this series.
Having a function prefixed with underscored or specifically indicate
locked tells callers that these are special cases and should be
understood before using.  Adding bool parameters to the common
functions ensures that every caller now needs to understand those
special cases and potentially get them wrong.  Also, a string of random
bool options to a function means that any time we want to use it we
need to go reexamine the function definition.  It's not intuitive to
use or review.  Thanks,

Alex

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v5 08/11] PCI: Unify pci_reset_function_locked() and __pci_reset_function_locked()
  2018-10-11 16:02   ` Alex Williamson
@ 2018-10-11 16:11     ` Sinan Kaya
  0 siblings, 0 replies; 19+ messages in thread
From: Sinan Kaya @ 2018-10-11 16:11 UTC (permalink / raw)
  To: Alex Williamson
  Cc: linux-pci, Mike Marciniszyn, Dennis Dalessandro, Doug Ledford,
	Jason Gunthorpe, Derek Chickles, Satanand Burla, Felix Manlunas,
	Raghu Vatsavayi, David S. Miller, Bjorn Helgaas, Boris Ostrovsky,
	Juergen Gross, Jia-Ju Bai

On 10/11/2018 12:02 PM, Alex Williamson wrote:
>> The difference between pci_reset_function_locked() and
>> __pci_reset_function_locked() is the saving and restoring of the registers.
>> Unify these API by adding saverestore argument that caller passes.
>>
>> Signed-off-by: Sinan Kaya<okaya@kernel.org>
>> ---
>>   drivers/infiniband/hw/hfi1/pcie.c               |  2 +-
>>   drivers/net/ethernet/cavium/liquidio/lio_main.c |  2 +-
>>   drivers/pci/pci.c                               | 10 +++++++---
>>   drivers/pci/pci.h                               |  1 +
>>   drivers/xen/xen-pciback/pci_stub.c              |  6 +++---
>>   include/linux/pci.h                             |  4 ++--
>>   6 files changed, 15 insertions(+), 10 deletions(-)
> TBH, I'm not a fan of this patch or the remainder in this series.
> Having a function prefixed with underscored or specifically indicate
> locked tells callers that these are special cases and should be
> understood before using.  Adding bool parameters to the common
> functions ensures that every caller now needs to understand those
> special cases and potentially get them wrong.  Also, a string of random
> bool options to a function means that any time we want to use it we
> need to go reexamine the function definition.  It's not intuitive to
> use or review.  Thanks,

Thanks for the feedback. I wanted to get it out to gather feedback.

I think it is quite straightforward for people familiar with the existing
API to know what they are dealing with. I didn't know the difference
between

__pci_reset_function_locked() and pci_reset_function_locked()

for a long time. This was an attempt to minimize reset function flavors
and ask explicitly what user wants rather than having them use the wrong
function and suffer the consequence with random failures.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v5 08/11] PCI: Unify pci_reset_function_locked() and __pci_reset_function_locked()
  2018-10-11  4:50 ` [PATCH v5 08/11] PCI: Unify pci_reset_function_locked() and __pci_reset_function_locked() Sinan Kaya
  2018-10-11 16:02   ` Alex Williamson
@ 2018-10-12  9:18   ` Christoph Hellwig
  2018-10-12 14:46     ` Sinan Kaya
  1 sibling, 1 reply; 19+ messages in thread
From: Christoph Hellwig @ 2018-10-12  9:18 UTC (permalink / raw)
  To: Sinan Kaya
  Cc: linux-pci, Mike Marciniszyn, Dennis Dalessandro, Doug Ledford,
	Jason Gunthorpe, Derek Chickles, Satanand Burla, Felix Manlunas,
	Raghu Vatsavayi, David S. Miller, Bjorn Helgaas, Boris Ostrovsky,
	Juergen Gross, Jia-Ju Bai

On Thu, Oct 11, 2018 at 04:50:00AM +0000, Sinan Kaya wrote:
> The difference between pci_reset_function_locked() and
> __pci_reset_function_locked() is the saving and restoring of the registers.
> Unify these API by adding saverestore argument that caller passes.

Adding random boolean arguments doesn't really help the API.  Either
make this another flag for reset_type or if there is a clear benefit
add an additional flags parameter with well described flags.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v5 09/11] PCI: Add options to pci_reset_function
  2018-10-11  4:50 ` [PATCH v5 09/11] PCI: Add options to pci_reset_function Sinan Kaya
@ 2018-10-12  9:18   ` Christoph Hellwig
  0 siblings, 0 replies; 19+ messages in thread
From: Christoph Hellwig @ 2018-10-12  9:18 UTC (permalink / raw)
  To: Sinan Kaya
  Cc: linux-pci, Srinivas Pandruvada, Jiri Kosina, Benjamin Tissoires,
	Frank Haverkamp, Guilherme G. Piccoli, Arnd Bergmann,
	Greg Kroah-Hartman, Harish Patil, Manish Chopra,
	Dept-GELinuxNICDev, David S. Miller,
	Solarflare linux maintainers, Edward Cree, Bert Kenward,
	Bjorn Helgaas, Anton Vasilyev

On Thu, Oct 11, 2018 at 04:50:01AM +0000, Sinan Kaya wrote:
> Getting ready to deprecate pci_reset_function_locked(). Add
> saverestore and locked parameters to pci_reset_function() function
> and add saverestore = true and locked = false to all existing
> callers.

NAK - no conditional locking based on a parameter, please.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v5 08/11] PCI: Unify pci_reset_function_locked() and __pci_reset_function_locked()
  2018-10-12  9:18   ` Christoph Hellwig
@ 2018-10-12 14:46     ` Sinan Kaya
  0 siblings, 0 replies; 19+ messages in thread
From: Sinan Kaya @ 2018-10-12 14:46 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: linux-pci, Mike Marciniszyn, Dennis Dalessandro, Doug Ledford,
	Jason Gunthorpe, Derek Chickles, Satanand Burla, Felix Manlunas,
	Raghu Vatsavayi, David S. Miller, Bjorn Helgaas, Boris Ostrovsky,
	Juergen Gross, Jia-Ju Bai

On 10/12/2018 5:18 AM, Christoph Hellwig wrote:
> On Thu, Oct 11, 2018 at 04:50:00AM +0000, Sinan Kaya wrote:
>> The difference between pci_reset_function_locked() and
>> __pci_reset_function_locked() is the saving and restoring of the registers.
>> Unify these API by adding saverestore argument that caller passes.
> 
> Adding random boolean arguments doesn't really help the API.  Either
> make this another flag for reset_type or if there is a clear benefit
> add an additional flags parameter with well described flags.
> 

Good idea. This is the kind of feedback I was looking for. Here is what I
collected so far.

Alex doesn't like the API changes as it should be obvious that there are
differences between pci_reset_function_locked() and
__pci_reset_function_locked(). Sinan thinks that the difference is not that
obvious as some drivers implemented their own save/restore mechanism using
__pci_reset_function_locked(). Sinan would rather reduce the reset API flavors
and give a unified interface where user specifies what they are interested in.

Christoph asked for additional flags to be rolled into the reset_type argument.
Sinan thinks that this is a good idea.

Anybody else?

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2018-10-12 14:47 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-10-11  4:49 [PATCH v5 01/11] PCI: Expose reset_type to users of __pci_reset_function_locked() Sinan Kaya
2018-10-11  4:49 ` [PATCH v5 02/11] PCI: Expose reset_type to users of pci_reset_function() Sinan Kaya
2018-10-11  4:49 ` [PATCH v5 03/11] PCI: Expose reset_type to users of pci_reset_function_locked() Sinan Kaya
2018-10-11  4:49 ` [PATCH v5 04/11] PCI: Expose reset type to users of pci_try_reset_function() Sinan Kaya
2018-10-11  4:49 ` [PATCH v5 05/11] PCI: Expose reset type to users of pci_probe_reset_function() Sinan Kaya
2018-10-11  4:49 ` [PATCH v5 06/11] PCI: Expose reset type to users of pci_reset_bus() Sinan Kaya
2018-10-11 15:33   ` Alex Williamson
2018-10-11 15:36     ` Sinan Kaya
2018-10-11  4:49 ` [PATCH v5 07/11] IB/hfi1,PCI: switch to __pci_function_locked() for reset request Sinan Kaya
2018-10-11  4:50 ` [PATCH v5 08/11] PCI: Unify pci_reset_function_locked() and __pci_reset_function_locked() Sinan Kaya
2018-10-11 16:02   ` Alex Williamson
2018-10-11 16:11     ` Sinan Kaya
2018-10-12  9:18   ` Christoph Hellwig
2018-10-12 14:46     ` Sinan Kaya
2018-10-11  4:50 ` [PATCH v5 09/11] PCI: Add options to pci_reset_function Sinan Kaya
2018-10-12  9:18   ` Christoph Hellwig
2018-10-11  4:50 ` [PATCH v5 10/11] PCI: Hide pci_reset_function_locked() Sinan Kaya
2018-10-11  4:50 ` [PATCH v5 11/11] PCI: Hide pcie_flr() in favor of pci_reset_function() Sinan Kaya
2018-10-11 15:41   ` Sinan Kaya

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.