[PATCH v1 07/12] PCI: hotplug: add register/unregister function for BMC device

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Introduce new APIs to register/unregister a BMC device instance
for fpgahp driver.

The fpgahp_bmc_device data structure represents a FPGA BMC device
which has some specific callbacks for FPGA hotplug operations.
The first one is available_images, which will return a list of
available images for FPGA. The second one is the image_load,
which will provide a reload trigger operation to BMC via secure
update driver for Intel PAC N3000 Card.

Signed-off-by: Tianfei Zhang <tianfei.zhang@xxxxxxxxx>
---
 drivers/pci/hotplug/fpgahp.c        | 78 +++++++++++++++++++++++++++++
 include/linux/fpga/fpgahp_manager.h | 38 ++++++++++++++
 2 files changed, 116 insertions(+)

diff --git a/drivers/pci/hotplug/fpgahp.c b/drivers/pci/hotplug/fpgahp.c
index 71cee65383e2..79bae97a1d39 100644
--- a/drivers/pci/hotplug/fpgahp.c
+++ b/drivers/pci/hotplug/fpgahp.c
@@ -34,6 +34,84 @@ static void fpgahp_add_fhpc(struct fpgahp_controller *fhpc)
 	mutex_unlock(&fhpc_lock);
 }
 
+static struct fpgahp_bmc_device *fpgahp_find_bmc(struct device *bmc_device)
+{
+	struct fpgahp_bmc_device *bmc = NULL;
+	struct fpgahp_controller *fhpc;
+
+	mutex_lock(&fhpc_lock);
+
+	list_for_each_entry(fhpc, &fhpc_list, node) {
+		struct fpgahp_manager *mgr = &fhpc->mgr;
+		struct pci_dev *pcidev = mgr->priv;
+
+		if (!mgr->registered)
+			continue;
+
+		/*
+		 * BMC device (like security dev) is a subordinate device under
+		 * PCI device, so check if the parent device of BMC device recursively
+		 */
+		if (device_is_ancestor(&pcidev->dev, bmc_device)) {
+			bmc = &mgr->bmc;
+			break;
+		}
+	}
+
+	mutex_unlock(&fhpc_lock);
+
+	return bmc;
+}
+
+/**
+ * fpgahp_bmc_device_register - register FPGA BMC device into fpgahp driver
+ * @ops: pointer to structure of fpgahp manager ops
+ * @dev: device struct of BMC device
+ * @priv: private data for FPGA device
+ *
+ * Return: pointer to struct fpgahp_manager pointer or ERR_PTR()
+ */
+struct fpgahp_bmc_device *
+fpgahp_bmc_device_register(const struct fpgahp_bmc_ops *ops,
+			   struct device *dev, void *priv)
+{
+	struct fpgahp_manager *mgr;
+	struct fpgahp_bmc_device *bmc;
+
+	if (!ops)
+		return ERR_PTR(-EINVAL);
+
+	bmc = fpgahp_find_bmc(dev);
+	if (!bmc)
+		return ERR_PTR(-EINVAL);
+
+	mgr = to_fpgahp_mgr(bmc);
+
+	mutex_lock(&mgr->lock);
+	bmc->priv = priv;
+	bmc->device = dev;
+	bmc->ops = ops;
+	bmc->registered = true;
+	mutex_unlock(&mgr->lock);
+
+	return bmc;
+}
+EXPORT_SYMBOL_NS_GPL(fpgahp_bmc_device_register, FPGAHP);
+
+/**
+ * fpgahp_bmc_device_unregister - unregister FPGA BMC device from fpgahp driver
+ * @bmc: point to the fpgahp_bmc_device
+ */
+void fpgahp_bmc_device_unregister(struct fpgahp_bmc_device *bmc)
+{
+	struct fpgahp_manager *mgr = to_fpgahp_mgr(bmc);
+
+	mutex_lock(&mgr->lock);
+	bmc->registered = false;
+	mutex_unlock(&mgr->lock);
+}
+EXPORT_SYMBOL_NS_GPL(fpgahp_bmc_device_unregister, FPGAHP);
+
 static int fpgahp_init_controller(struct controller *ctrl, struct pcie_device *dev)
 {
 	struct pci_dev *hotplug_bridge = dev->port;
diff --git a/include/linux/fpga/fpgahp_manager.h b/include/linux/fpga/fpgahp_manager.h
index 5e31877f03de..982fbc661f55 100644
--- a/include/linux/fpga/fpgahp_manager.h
+++ b/include/linux/fpga/fpgahp_manager.h
@@ -11,6 +11,33 @@
 
 struct pci_dev;
 struct fpgahp_manager;
+struct fpgahp_bmc_device;
+
+/**
+ * struct fpgahp_bmc_ops - fpga hotplug BMC specific operations
+ * @available_images: Required: available images for fpgahp trigger
+ * @image_trigger: Required: trigger the image reload on BMC
+ */
+struct fpgahp_bmc_ops {
+	ssize_t (*available_images)(struct fpgahp_bmc_device *bmc, char *buf);
+	int (*image_trigger)(struct fpgahp_bmc_device *bmc, const char *buf,
+			     u32 *wait_time_msec);
+};
+
+/**
+ * struct fpgahp_bmc_device - represent a fpga hotplug BMC device
+ *
+ * @ops: ops of this fpgahp_bmc_device
+ * @priv: private data for fpgahp_bmc_device
+ * @device: device of BMC device
+ * @registered: register status
+ */
+struct fpgahp_bmc_device {
+	const struct fpgahp_bmc_ops *ops;
+	void *priv;
+	struct device *device;
+	bool registered;
+};
 
 /**
  * struct fpgahp_manager_ops - fpgahp manager specific operations
@@ -43,6 +70,7 @@ enum fpgahp_manager_states {
  * @ops: ops of this fpgahp_manager
  * @state: the status of fpgahp_manager
  * @name: name of the fpgahp_manager
+ * @bmc: fpgahp BMC device
  * @registered: register status
  */
 struct fpgahp_manager {
@@ -51,12 +79,22 @@ struct fpgahp_manager {
 	const struct fpgahp_manager_ops *ops;
 	enum fpgahp_manager_states state;
 	const char *name;
+	struct fpgahp_bmc_device bmc;
 	bool registered;
 };
 
+static inline struct fpgahp_manager *to_fpgahp_mgr(struct fpgahp_bmc_device *bmc)
+{
+	return container_of(bmc, struct fpgahp_manager, bmc);
+}
+
 struct fpgahp_manager *fpgahp_register(struct pci_dev *hotplug_bridge,
 				       const char *name, const struct fpgahp_manager_ops *ops,
 				       void *priv);
 void fpgahp_unregister(struct fpgahp_manager *mgr);
 
+struct fpgahp_bmc_device *fpgahp_bmc_device_register(const struct fpgahp_bmc_ops *ops,
+						     struct device *dev, void *priv);
+void fpgahp_bmc_device_unregister(struct fpgahp_bmc_device *bmc);
+
 #endif
-- 
2.38.1




[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux