diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c
index 5a4a8b0be6262..d336a99c6a94f 100644
--- a/drivers/pci/endpoint/pci-epc-core.c
+++ b/drivers/pci/endpoint/pci-epc-core.c
@@ -10,6 +10,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 
+#include <linux/msi.h>
 #include <linux/pci-epc.h>
 #include <linux/pci-epf.h>
 #include <linux/pci-ep-cfs.h>
@@ -783,6 +784,197 @@ void pci_epc_bme_notify(struct pci_epc *epc)
 }
 EXPORT_SYMBOL_GPL(pci_epc_bme_notify);
 
+/**
+ * pci_epc_alloc_doorbell() - alloc an address space to let RC trigger EP side IRQ by write data to
+ *			      the space.
+ *
+ * @epc: the EPC device that need doorbell address and data from RC.
+ * @func_no: the physical endpoint function number in the EPC device.
+ * @vfunc_no: the virtual endpoint function number in the physical function.
+ * @num_msgs: the total number of doorbell messages
+ *
+ * Return: 0 success, other is failure
+ */
+int pci_epc_alloc_doorbell(struct pci_epc *epc, u8 func_no, u8 vfunc_no, int num_msgs)
+{
+	int ret;
+
+	if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions)
+		return -EINVAL;
+
+	if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no]))
+		return -EINVAL;
+
+	if (!epc->ops->alloc_doorbell)
+		return 0;
+
+	mutex_lock(&epc->lock);
+	ret = epc->ops->alloc_doorbell(epc, func_no, vfunc_no, num_msgs);
+	mutex_unlock(&epc->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(pci_epc_alloc_doorbell);
+
+/**
+ * pci_epc_free_doorbell() - free resource allocated by pci_epc_alloc_doorbell()
+ *
+ * @epc: the EPC device that need doorbell address and data from RC.
+ * @func_no: the physical endpoint function number in the EPC device.
+ * @vfunc_no: the virtual endpoint function number in the physical function.
+ *
+ * Return: 0 success, other is failure
+ */
+void pci_epc_free_doorbell(struct pci_epc *epc, u8 func_no, u8 vfunc_no)
+{
+	if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions)
+		return;
+
+	if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no]))
+		return;
+
+	if (!epc->ops->free_doorbell)
+		return;
+
+	mutex_lock(&epc->lock);
+	epc->ops->free_doorbell(epc, func_no, vfunc_no);
+	mutex_unlock(&epc->lock);
+}
+EXPORT_SYMBOL_GPL(pci_epc_free_doorbell);
+
+static irqreturn_t pci_epf_generic_doorbell_handler(int irq, void *data)
+{
+	struct pci_epf *epf = data;
+
+	if (epf->event_ops && epf->event_ops->doorbell)
+		epf->event_ops->doorbell(epf, irq - epf->virq_base);
+
+	return IRQ_HANDLED;
+}
+
+static void pci_epc_generic_write_msi_msg(struct msi_desc *desc, struct msi_msg *msg)
+{
+	struct pci_epc *epc = NULL;
+	struct class_dev_iter iter;
+	struct pci_epf *epf;
+	struct device *dev;
+
+	class_dev_iter_init(&iter, pci_epc_class, NULL, NULL);
+	while ((dev = class_dev_iter_next(&iter))) {
+		if (dev->parent != desc->dev)
+			continue;
+
+		epc = to_pci_epc(dev);
+
+		class_dev_iter_exit(&iter);
+		break;
+	}
+
+	if (!epc)
+		return;
+
+	/* Only support one EPF for doorbell */
+	epf = list_first_entry_or_null(&epc->pci_epf, struct pci_epf, list);
+
+	if (!epf)
+		return;
+
+	if (epf->msg && desc->msi_index < epf->num_msgs)
+		epf->msg[desc->msi_index] = *msg;
+}
+
+
+/**
+ * pci_epc_generic_alloc_doorbell() - Common help function. Allocate address space from MSI
+ *                                    controller
+ *
+ * @epc: the EPC device that need doorbell address and data from RC.
+ * @func_no: the physical endpoint function number in the EPC device.
+ * @vfunc_no: the virtual endpoint function number in the physical function.
+ * @num_msgs: the total number of doorbell messages
+ *
+ * Remark: use this function only if EPC driver just register one EPC device.
+ *
+ * Return: 0 success, other is failure
+ */
+int pci_epc_generic_alloc_doorbell(struct pci_epc *epc, u8 func_no, u8 vfunc_no, int num_msgs)
+{
+	struct pci_epf *epf;
+	struct device *dev;
+	int virq, last;
+	int ret;
+	int i;
+
+	if (IS_ERR_OR_NULL(epc))
+		return -EINVAL;
+
+	/* Currently only support one func and one vfunc for doorbell */
+	if (func_no || vfunc_no)
+		return -EINVAL;
+
+	epf = list_first_entry_or_null(&epc->pci_epf, struct pci_epf, list);
+	if (!epf)
+		return -EINVAL;
+
+	dev = epc->dev.parent;
+	ret = platform_msi_domain_alloc_irqs(dev, num_msgs, pci_epc_generic_write_msi_msg);
+	if (ret) {
+		dev_err(dev, "Failed to allocate MSI\n");
+		return -ENOMEM;
+	}
+
+	last = -1;
+	for (i = 0; i < num_msgs; i++) {
+		virq = msi_get_virq(dev, i);
+		if (i == 0)
+			epf->virq_base = virq;
+
+		ret = request_irq(virq, pci_epf_generic_doorbell_handler, 0,
+				  kasprintf(GFP_KERNEL, "pci-epc-doorbell%d", i), epf);
+
+		if (ret) {
+			dev_err(dev, "Failed to request doorbell\n");
+			goto err_free_irq;
+		}
+		last = i;
+	}
+
+	return 0;
+
+err_free_irq:
+	for (i = 0; i < last; i++)
+		kfree(free_irq(epf->virq_base + i, epf));
+	platform_msi_domain_free_irqs(dev);
+
+	return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(pci_epc_generic_alloc_doorbell);
+
+/**
+ * pci_epc_generic_free_doorbell() - Common help function. Free resource created by
+ *				     pci_epc_generic_alloc_doorbell()
+ *
+ * @epc: the EPC device that need doorbell address and data from RC.
+ * @func_no: the physical endpoint function number in the EPC device.
+ * @vfunc_no: the virtual endpoint function number in the physical function.
+ * @num_msgs: the total number of doorbell messages
+ */
+void pci_epc_generic_free_doorbell(struct pci_epc *epc, u8 func_no, u8 vfunc_no)
+{
+	struct pci_epf *epf;
+	int i;
+
+	epf = list_first_entry_or_null(&epc->pci_epf, struct pci_epf, list);
+	if (!epf)
+		return;
+
+	for (i = 0; i < epf->num_msgs; i++)
+		kfree(free_irq(epf->virq_base + i, epf));
+
+	platform_msi_domain_free_irqs(epc->dev.parent);
+}
+EXPORT_SYMBOL_GPL(pci_epc_generic_free_doorbell);
+
 /**
  * pci_epc_destroy() - destroy the EPC device
  * @epc: the EPC device that has to be destroyed
diff --git a/drivers/pci/endpoint/pci-epf-core.c b/drivers/pci/endpoint/pci-epf-core.c
index 2c32de6679377..eab82c6b0119a 100644
--- a/drivers/pci/endpoint/pci-epf-core.c
+++ b/drivers/pci/endpoint/pci-epf-core.c
@@ -10,6 +10,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/msi.h>
 
 #include <linux/pci-epc.h>
 #include <linux/pci-epf.h>
@@ -300,6 +301,49 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
 }
 EXPORT_SYMBOL_GPL(pci_epf_alloc_space);
 
+int pci_epf_alloc_doorbell(struct pci_epf *epf, u16 num_msgs)
+{
+	struct pci_epc *epc;
+	struct device *dev;
+	int ret;
+
+	epc = epf->epc;
+	dev = &epc->dev;
+
+	epf->msg = kcalloc(num_msgs, sizeof(struct msi_msg), GFP_KERNEL);
+	if (!epf->msg)
+		return -ENOMEM;
+
+	epf->num_msgs = num_msgs;
+
+	ret = pci_epc_alloc_doorbell(epc, epf->func_no, epf->vfunc_no, num_msgs);
+	if (ret)
+		goto err_free_mem;
+
+	return ret;
+
+err_free_mem:
+	kfree(epf->msg);
+	epf->msg = NULL;
+	epf->num_msgs = 0;
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(pci_epf_alloc_doorbell);
+
+void pci_epf_free_doorbell(struct pci_epf *epf)
+{
+	struct pci_epc *epc;
+
+	epc = epf->epc;
+	pci_epc_free_doorbell(epc, epf->func_no, epf->vfunc_no);
+
+	kfree(epf->msg);
+	epf->msg = NULL;
+	epf->num_msgs = 0;
+}
+EXPORT_SYMBOL_GPL(pci_epf_free_doorbell);
+
 static void pci_epf_remove_cfs(struct pci_epf_driver *driver)
 {
 	struct config_group *group, *tmp;
diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h
index 5cb6940310729..605fb0debd6bc 100644
--- a/include/linux/pci-epc.h
+++ b/include/linux/pci-epc.h
@@ -88,6 +88,8 @@ struct pci_epc_ops {
 	void	(*stop)(struct pci_epc *epc);
 	const struct pci_epc_features* (*get_features)(struct pci_epc *epc,
 						       u8 func_no, u8 vfunc_no);
+	int	(*alloc_doorbell)(struct pci_epc *epc, u8 func_no, u8 vfunc_no, int num_msgs);
+	void	(*free_doorbell)(struct pci_epc *epc, u8 func_no, u8 vfunc_no);
 	struct module *owner;
 };
 
@@ -251,4 +253,8 @@ void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc,
 				     phys_addr_t *phys_addr, size_t size);
 void pci_epc_mem_free_addr(struct pci_epc *epc, phys_addr_t phys_addr,
 			   void __iomem *virt_addr, size_t size);
+int pci_epc_alloc_doorbell(struct pci_epc *epc, u8 func_no, u8 vfunc_no, int num_msgs);
+void pci_epc_free_doorbell(struct pci_epc *epc, u8 func_no, u8 vfunc_no);
+int pci_epc_generic_alloc_doorbell(struct pci_epc *epc, u8 func_no, u8 vfunc_no, int num_msgs);
+void pci_epc_generic_free_doorbell(struct pci_epc *epc, u8 func_no, u8 vfunc_no);
 #endif /* __LINUX_PCI_EPC_H */
diff --git a/include/linux/pci-epf.h b/include/linux/pci-epf.h
index 3f44b6aec4770..485c146a5efe2 100644
--- a/include/linux/pci-epf.h
+++ b/include/linux/pci-epf.h
@@ -79,6 +79,7 @@ struct pci_epc_event_ops {
 	int (*link_up)(struct pci_epf *epf);
 	int (*link_down)(struct pci_epf *epf);
 	int (*bme)(struct pci_epf *epf);
+	int (*doorbell)(struct pci_epf *epf, int index);
 };
 
 /**
@@ -180,6 +181,9 @@ struct pci_epf {
 	unsigned long		vfunction_num_map;
 	struct list_head	pci_vepf;
 	const struct pci_epc_event_ops *event_ops;
+	struct msi_msg *msg;
+	u16 num_msgs;
+	int virq_base;
 };
 
 /**
@@ -223,4 +227,7 @@ int pci_epf_bind(struct pci_epf *epf);
 void pci_epf_unbind(struct pci_epf *epf);
 int pci_epf_add_vepf(struct pci_epf *epf_pf, struct pci_epf *epf_vf);
 void pci_epf_remove_vepf(struct pci_epf *epf_pf, struct pci_epf *epf_vf);
+int pci_epf_alloc_doorbell(struct pci_epf *epf, u16 nums);
+void pci_epf_free_doorbell(struct pci_epf *epf);
+
 #endif /* __LINUX_PCI_EPF_H */
