@@ -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;
@@ -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
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@intel.com> --- drivers/pci/hotplug/fpgahp.c | 78 +++++++++++++++++++++++++++++ include/linux/fpga/fpgahp_manager.h | 38 ++++++++++++++ 2 files changed, 116 insertions(+)