Hello,
This series adds support for Modem Host Interface (MHI) Endpoint function
driver and few updates to the PCI endpoint core.
MHI
===
MHI is the communication protocol used by the host machines to control and
communicate with the Qualcomm modems/WLAN devices over any high speed physical
bus like PCIe. In Linux kernel, MHI is modeled as a bus driver [1] and there
are two instances of MHI used in a typical setup.
1. MHI host - MHI implementation for the host machines like x86/ARM64.
2. MHI Endpoint - MHI implementation for the endpoint devices like modems.
MHI EPF
=======
The MHI Endpoint function driver (MHI EPF) is used on the MHI endpoint devices
like modems. The MHI EPF driver sits in between the PCIe EP and MHI EP bus and
carries out all of the PCIe related activities like BAR config, PCIe Event
handling, MMIO read/write etc,... for the MHI EP bus.
Below is the simple representation of the setup:
+----------------------------------------------------+
| Endpoint CPU |
| |
+------------+ | +------------+ +-----------+ +-----------+ |
| | | | | | | | | |
| | | | MHI EP | | | | | | PCIe Bus
| Modem DSP +---+---+ Bus +---+ MHI EPF +---+ PCIe EP +---+---------
| | | | | | | | | |
| | | | | | | | | |
+------------+ | +------------+ +-----------+ +-----------+ |
| |
| |
+----------------------------------------------------+
The data packets will be read from the Modem DSP by the MHI stack and will be
transmitted to the host machine over PCIe bus with the help of MHI EPF driver.
Test setup
==========
This series has been tested on Snapdragon X55 modem a.k.a SDX55 connected to
the ARM64 host machine.
Thanks,
Mani
[1] https://www.kernel.org/doc/html/latest/mhi/mhi.html
Changes in v6:
* Moved the alloc/map and unmap/free code to separate helper functions and used
them to avoid code duplication in epf driver.
* Removed superfluous WARN_ON_ONCE() from epf driver.
Changes in v5:
* Moved the PCI EPF driver match logic to pci_epf_match_id() function and used
that to get the matched driver ID for passing to driver probe instead of
storing the id during match.
* Added a patch to fix the missing documentation about MSI/MSI-X start vector.
* Addressed the review comments on the MHI EPF driver. Most notably, got rid of
local variable for tracking MHI registration and used the mhi_dev pointer.
Also, modified the MSI vector increment comment to make it clear.
* Added a patch for adding MHI EPF driver to MAINTAINERS file
Changes in v4:
* Collected review tag from Kishon
* Changed the IP_SW0 channel numbers as per latest MHI spec
Changes in v3:
* Fixed the probe function of EPF_VNTB driver
Changes in v2:
* Rebased on top of v6.3-rc1
* Switched to the new callback interface for passing events from EPC to EPF
* Dropped one patch related to notifier
Manivannan Sadhasivam (9):
PCI: endpoint: Add missing documentation about the MSI/MSI-X range
PCI: endpoint: Pass EPF device ID to the probe function
PCI: endpoint: Return error if EPC is started/stopped multiple times
PCI: endpoint: Add linkdown notifier support
PCI: endpoint: Add BME notifier support
PCI: qcom-ep: Add support for Link down notification
PCI: qcom-ep: Add support for BME notification
PCI: endpoint: Add PCI Endpoint function driver for MHI bus
MAINTAINERS: Add PCI MHI endpoint function driver under MHI bus
MAINTAINERS | 1 +
drivers/pci/controller/dwc/pcie-qcom-ep.c | 2 +
drivers/pci/endpoint/functions/Kconfig | 10 +
drivers/pci/endpoint/functions/Makefile | 1 +
drivers/pci/endpoint/functions/pci-epf-mhi.c | 465 ++++++++++++++++++
drivers/pci/endpoint/functions/pci-epf-ntb.c | 3 +-
drivers/pci/endpoint/functions/pci-epf-test.c | 2 +-
drivers/pci/endpoint/functions/pci-epf-vntb.c | 2 +-
drivers/pci/endpoint/pci-ep-cfs.c | 3 +
drivers/pci/endpoint/pci-epc-core.c | 56 ++-
drivers/pci/endpoint/pci-epf-core.c | 18 +-
include/linux/pci-epc.h | 2 +
include/linux/pci-epf.h | 8 +-
13 files changed, 560 insertions(+), 13 deletions(-)
create mode 100644 drivers/pci/endpoint/functions/pci-epf-mhi.c
--
2.25.1
Add PCI Endpoint driver for the Qualcomm MHI (Modem Host Interface) bus.
The driver implements the MHI function over PCI in the endpoint device
such as SDX55 modem. The MHI endpoint function driver acts as a
controller driver for the MHI Endpoint stack and carries out all PCI
related activities like mapping the host memory using iATU, triggering
MSIs etc...
Reviewed-by: Kishon Vijay Abraham I <[email protected]>
Reviewed-by: Damien Le Moal <[email protected]>
Signed-off-by: Manivannan Sadhasivam <[email protected]>
---
drivers/pci/endpoint/functions/Kconfig | 10 +
drivers/pci/endpoint/functions/Makefile | 1 +
drivers/pci/endpoint/functions/pci-epf-mhi.c | 465 +++++++++++++++++++
3 files changed, 476 insertions(+)
create mode 100644 drivers/pci/endpoint/functions/pci-epf-mhi.c
diff --git a/drivers/pci/endpoint/functions/Kconfig b/drivers/pci/endpoint/functions/Kconfig
index 9fd560886871..f5171b4fabbe 100644
--- a/drivers/pci/endpoint/functions/Kconfig
+++ b/drivers/pci/endpoint/functions/Kconfig
@@ -37,3 +37,13 @@ config PCI_EPF_VNTB
between PCI Root Port and PCIe Endpoint.
If in doubt, say "N" to disable Endpoint NTB driver.
+
+config PCI_EPF_MHI
+ tristate "PCI Endpoint driver for MHI bus"
+ depends on PCI_ENDPOINT && MHI_BUS_EP
+ help
+ Enable this configuration option to enable the PCI Endpoint
+ driver for Modem Host Interface (MHI) bus in Qualcomm Endpoint
+ devices such as SDX55.
+
+ If in doubt, say "N" to disable Endpoint driver for MHI bus.
diff --git a/drivers/pci/endpoint/functions/Makefile b/drivers/pci/endpoint/functions/Makefile
index 5c13001deaba..696473fce50e 100644
--- a/drivers/pci/endpoint/functions/Makefile
+++ b/drivers/pci/endpoint/functions/Makefile
@@ -6,3 +6,4 @@
obj-$(CONFIG_PCI_EPF_TEST) += pci-epf-test.o
obj-$(CONFIG_PCI_EPF_NTB) += pci-epf-ntb.o
obj-$(CONFIG_PCI_EPF_VNTB) += pci-epf-vntb.o
+obj-$(CONFIG_PCI_EPF_MHI) += pci-epf-mhi.o
diff --git a/drivers/pci/endpoint/functions/pci-epf-mhi.c b/drivers/pci/endpoint/functions/pci-epf-mhi.c
new file mode 100644
index 000000000000..0504ee13f692
--- /dev/null
+++ b/drivers/pci/endpoint/functions/pci-epf-mhi.c
@@ -0,0 +1,465 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PCI EPF driver for MHI Endpoint devices
+ *
+ * Copyright (C) 2023 Linaro Ltd.
+ * Author: Manivannan Sadhasivam <[email protected]>
+ */
+
+#include <linux/mhi_ep.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pci-epc.h>
+#include <linux/pci-epf.h>
+
+#define MHI_VERSION_1_0 0x01000000
+
+#define to_epf_mhi(cntrl) container_of(cntrl, struct pci_epf_mhi, cntrl)
+
+struct pci_epf_mhi_ep_info {
+ const struct mhi_ep_cntrl_config *config;
+ struct pci_epf_header *epf_header;
+ enum pci_barno bar_num;
+ u32 epf_flags;
+ u32 msi_count;
+ u32 mru;
+};
+
+#define MHI_EP_CHANNEL_CONFIG(ch_num, ch_name, direction) \
+ { \
+ .num = ch_num, \
+ .name = ch_name, \
+ .dir = direction, \
+ }
+
+#define MHI_EP_CHANNEL_CONFIG_UL(ch_num, ch_name) \
+ MHI_EP_CHANNEL_CONFIG(ch_num, ch_name, DMA_TO_DEVICE)
+
+#define MHI_EP_CHANNEL_CONFIG_DL(ch_num, ch_name) \
+ MHI_EP_CHANNEL_CONFIG(ch_num, ch_name, DMA_FROM_DEVICE)
+
+static const struct mhi_ep_channel_config mhi_v1_channels[] = {
+ MHI_EP_CHANNEL_CONFIG_UL(0, "LOOPBACK"),
+ MHI_EP_CHANNEL_CONFIG_DL(1, "LOOPBACK"),
+ MHI_EP_CHANNEL_CONFIG_UL(2, "SAHARA"),
+ MHI_EP_CHANNEL_CONFIG_DL(3, "SAHARA"),
+ MHI_EP_CHANNEL_CONFIG_UL(4, "DIAG"),
+ MHI_EP_CHANNEL_CONFIG_DL(5, "DIAG"),
+ MHI_EP_CHANNEL_CONFIG_UL(6, "SSR"),
+ MHI_EP_CHANNEL_CONFIG_DL(7, "SSR"),
+ MHI_EP_CHANNEL_CONFIG_UL(8, "QDSS"),
+ MHI_EP_CHANNEL_CONFIG_DL(9, "QDSS"),
+ MHI_EP_CHANNEL_CONFIG_UL(10, "EFS"),
+ MHI_EP_CHANNEL_CONFIG_DL(11, "EFS"),
+ MHI_EP_CHANNEL_CONFIG_UL(12, "MBIM"),
+ MHI_EP_CHANNEL_CONFIG_DL(13, "MBIM"),
+ MHI_EP_CHANNEL_CONFIG_UL(14, "QMI"),
+ MHI_EP_CHANNEL_CONFIG_DL(15, "QMI"),
+ MHI_EP_CHANNEL_CONFIG_UL(16, "QMI"),
+ MHI_EP_CHANNEL_CONFIG_DL(17, "QMI"),
+ MHI_EP_CHANNEL_CONFIG_UL(18, "IP-CTRL-1"),
+ MHI_EP_CHANNEL_CONFIG_DL(19, "IP-CTRL-1"),
+ MHI_EP_CHANNEL_CONFIG_UL(20, "IPCR"),
+ MHI_EP_CHANNEL_CONFIG_DL(21, "IPCR"),
+ MHI_EP_CHANNEL_CONFIG_UL(32, "DUN"),
+ MHI_EP_CHANNEL_CONFIG_DL(33, "DUN"),
+ MHI_EP_CHANNEL_CONFIG_UL(46, "IP_SW0"),
+ MHI_EP_CHANNEL_CONFIG_DL(47, "IP_SW0"),
+};
+
+static const struct mhi_ep_cntrl_config mhi_v1_config = {
+ .max_channels = 128,
+ .num_channels = ARRAY_SIZE(mhi_v1_channels),
+ .ch_cfg = mhi_v1_channels,
+ .mhi_version = MHI_VERSION_1_0,
+};
+
+static struct pci_epf_header sdx55_header = {
+ .vendorid = PCI_VENDOR_ID_QCOM,
+ .deviceid = 0x0306,
+ .baseclass_code = PCI_BASE_CLASS_COMMUNICATION,
+ .subclass_code = PCI_CLASS_COMMUNICATION_MODEM & 0xff,
+ .interrupt_pin = PCI_INTERRUPT_INTA,
+};
+
+static const struct pci_epf_mhi_ep_info sdx55_info = {
+ .config = &mhi_v1_config,
+ .epf_header = &sdx55_header,
+ .bar_num = BAR_0,
+ .epf_flags = PCI_BASE_ADDRESS_MEM_TYPE_32,
+ .msi_count = 32,
+ .mru = 0x8000,
+};
+
+struct pci_epf_mhi {
+ const struct pci_epf_mhi_ep_info *info;
+ struct mhi_ep_cntrl mhi_cntrl;
+ struct pci_epf *epf;
+ struct mutex lock;
+ void __iomem *mmio;
+ resource_size_t mmio_phys;
+ u32 mmio_size;
+ int irq;
+};
+
+static int __pci_epf_mhi_alloc_map(struct mhi_ep_cntrl *mhi_cntrl, u64 pci_addr,
+ phys_addr_t *paddr, void __iomem **vaddr,
+ size_t offset, size_t size)
+{
+ struct pci_epf_mhi *epf_mhi = to_epf_mhi(mhi_cntrl);
+ struct pci_epf *epf = epf_mhi->epf;
+ struct pci_epc *epc = epf->epc;
+ int ret;
+
+ *vaddr = pci_epc_mem_alloc_addr(epc, paddr, size + offset);
+ if (!vaddr)
+ return -ENOMEM;
+
+ ret = pci_epc_map_addr(epc, epf->func_no, epf->vfunc_no, *paddr,
+ pci_addr - offset, size + offset);
+ if (ret) {
+ pci_epc_mem_free_addr(epc, *paddr, *vaddr, size + offset);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int pci_epf_mhi_alloc_map(struct mhi_ep_cntrl *mhi_cntrl, u64 pci_addr,
+ phys_addr_t *paddr, void __iomem **vaddr,
+ size_t size)
+{
+ struct pci_epf_mhi *epf_mhi = to_epf_mhi(mhi_cntrl);
+ struct pci_epc *epc = epf_mhi->epf->epc;
+ size_t offset = pci_addr & (epc->mem->window.page_size - 1);
+ int ret;
+
+ ret = __pci_epf_mhi_alloc_map(mhi_cntrl, pci_addr, paddr, vaddr,
+ offset, size);
+ if (ret)
+ return ret;
+
+ *paddr = *paddr + offset;
+ *vaddr = *vaddr + offset;
+
+ return 0;
+}
+
+static void __pci_epf_mhi_unmap_free(struct mhi_ep_cntrl *mhi_cntrl,
+ u64 pci_addr, phys_addr_t paddr,
+ void __iomem *vaddr, size_t offset,
+ size_t size)
+{
+ struct pci_epf_mhi *epf_mhi = to_epf_mhi(mhi_cntrl);
+ struct pci_epf *epf = epf_mhi->epf;
+ struct pci_epc *epc = epf->epc;
+
+ pci_epc_unmap_addr(epc, epf->func_no, epf->vfunc_no, paddr - offset);
+ pci_epc_mem_free_addr(epc, paddr - offset, vaddr - offset,
+ size + offset);
+}
+
+static void pci_epf_mhi_unmap_free(struct mhi_ep_cntrl *mhi_cntrl, u64 pci_addr,
+ phys_addr_t paddr, void __iomem *vaddr,
+ size_t size)
+{
+ struct pci_epf_mhi *epf_mhi = to_epf_mhi(mhi_cntrl);
+ struct pci_epf *epf = epf_mhi->epf;
+ struct pci_epc *epc = epf->epc;
+ size_t offset = pci_addr & (epc->mem->window.page_size - 1);
+
+ __pci_epf_mhi_unmap_free(mhi_cntrl, pci_addr, paddr, vaddr, offset,
+ size);
+}
+
+static void pci_epf_mhi_raise_irq(struct mhi_ep_cntrl *mhi_cntrl, u32 vector)
+{
+ struct pci_epf_mhi *epf_mhi = to_epf_mhi(mhi_cntrl);
+ struct pci_epf *epf = epf_mhi->epf;
+ struct pci_epc *epc = epf->epc;
+
+ /*
+ * MHI supplies 0 based MSI vector but the API expects the vector to be
+ * 1 based, so we need to increment the vector by 1.
+ */
+ pci_epc_raise_irq(epc, epf->func_no, epf->vfunc_no, PCI_EPC_IRQ_MSI,
+ vector + 1);
+}
+
+static int pci_epf_mhi_read_from_host(struct mhi_ep_cntrl *mhi_cntrl, u64 from,
+ void *to, size_t size)
+{
+ struct pci_epf_mhi *epf_mhi = to_epf_mhi(mhi_cntrl);
+ size_t offset = from % SZ_4K;
+ void __iomem *tre_buf;
+ phys_addr_t tre_phys;
+ int ret;
+
+ mutex_lock(&epf_mhi->lock);
+
+ ret = __pci_epf_mhi_alloc_map(mhi_cntrl, from, &tre_phys, &tre_buf,
+ offset, size);
+ if (ret) {
+ mutex_unlock(&epf_mhi->lock);
+ return ret;
+ }
+
+ memcpy_fromio(to, tre_buf + offset, size);
+
+ __pci_epf_mhi_unmap_free(mhi_cntrl, from, tre_phys, tre_buf, offset,
+ size);
+
+ mutex_unlock(&epf_mhi->lock);
+
+ return 0;
+}
+
+static int pci_epf_mhi_write_to_host(struct mhi_ep_cntrl *mhi_cntrl,
+ void *from, u64 to, size_t size)
+{
+ struct pci_epf_mhi *epf_mhi = to_epf_mhi(mhi_cntrl);
+ size_t offset = to % SZ_4K;
+ void __iomem *tre_buf;
+ phys_addr_t tre_phys;
+ int ret;
+
+ mutex_lock(&epf_mhi->lock);
+
+ ret = __pci_epf_mhi_alloc_map(mhi_cntrl, to, &tre_phys, &tre_buf,
+ offset, size);
+ if (ret) {
+ mutex_unlock(&epf_mhi->lock);
+ return ret;
+ }
+
+ memcpy_toio(tre_buf + offset, from, size);
+
+ __pci_epf_mhi_unmap_free(mhi_cntrl, to, tre_phys, tre_buf, offset,
+ size);
+
+ mutex_unlock(&epf_mhi->lock);
+
+ return 0;
+}
+
+static int pci_epf_mhi_core_init(struct pci_epf *epf)
+{
+ struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf);
+ const struct pci_epf_mhi_ep_info *info = epf_mhi->info;
+ struct pci_epf_bar *epf_bar = &epf->bar[info->bar_num];
+ struct pci_epc *epc = epf->epc;
+ struct device *dev = &epf->dev;
+ int ret;
+
+ epf_bar->phys_addr = epf_mhi->mmio_phys;
+ epf_bar->size = epf_mhi->mmio_size;
+ epf_bar->barno = info->bar_num;
+ epf_bar->flags = info->epf_flags;
+ ret = pci_epc_set_bar(epc, epf->func_no, epf->vfunc_no, epf_bar);
+ if (ret) {
+ dev_err(dev, "Failed to set BAR: %d\n", ret);
+ return ret;
+ }
+
+ ret = pci_epc_set_msi(epc, epf->func_no, epf->vfunc_no,
+ order_base_2(info->msi_count));
+ if (ret) {
+ dev_err(dev, "Failed to set MSI configuration: %d\n", ret);
+ return ret;
+ }
+
+ ret = pci_epc_write_header(epc, epf->func_no, epf->vfunc_no,
+ epf->header);
+ if (ret) {
+ dev_err(dev, "Failed to set Configuration header: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int pci_epf_mhi_link_up(struct pci_epf *epf)
+{
+ struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf);
+ const struct pci_epf_mhi_ep_info *info = epf_mhi->info;
+ struct mhi_ep_cntrl *mhi_cntrl = &epf_mhi->mhi_cntrl;
+ struct pci_epc *epc = epf->epc;
+ struct device *dev = &epf->dev;
+ int ret;
+
+ mhi_cntrl->mmio = epf_mhi->mmio;
+ mhi_cntrl->irq = epf_mhi->irq;
+ mhi_cntrl->mru = info->mru;
+
+ /* Assign the struct dev of PCI EP as MHI controller device */
+ mhi_cntrl->cntrl_dev = epc->dev.parent;
+ mhi_cntrl->raise_irq = pci_epf_mhi_raise_irq;
+ mhi_cntrl->alloc_map = pci_epf_mhi_alloc_map;
+ mhi_cntrl->unmap_free = pci_epf_mhi_unmap_free;
+ mhi_cntrl->read_from_host = pci_epf_mhi_read_from_host;
+ mhi_cntrl->write_to_host = pci_epf_mhi_write_to_host;
+
+ /* Register the MHI EP controller */
+ ret = mhi_ep_register_controller(mhi_cntrl, info->config);
+ if (ret) {
+ dev_err(dev, "Failed to register MHI EP controller: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int pci_epf_mhi_link_down(struct pci_epf *epf)
+{
+ struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf);
+ struct mhi_ep_cntrl *mhi_cntrl = &epf_mhi->mhi_cntrl;
+
+ if (mhi_cntrl->mhi_dev) {
+ mhi_ep_power_down(mhi_cntrl);
+ mhi_ep_unregister_controller(mhi_cntrl);
+ }
+
+ return 0;
+}
+
+static int pci_epf_mhi_bme(struct pci_epf *epf)
+{
+ struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf);
+ struct mhi_ep_cntrl *mhi_cntrl = &epf_mhi->mhi_cntrl;
+ struct device *dev = &epf->dev;
+ int ret;
+
+ /*
+ * Power up the MHI EP stack if link is up and stack is in power down
+ * state.
+ */
+ if (!mhi_cntrl->enabled && mhi_cntrl->mhi_dev) {
+ ret = mhi_ep_power_up(mhi_cntrl);
+ if (ret) {
+ dev_err(dev, "Failed to power up MHI EP: %d\n", ret);
+ mhi_ep_unregister_controller(mhi_cntrl);
+ }
+ }
+
+ return 0;
+}
+
+static int pci_epf_mhi_bind(struct pci_epf *epf)
+{
+ struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf);
+ struct pci_epc *epc = epf->epc;
+ struct platform_device *pdev = to_platform_device(epc->dev.parent);
+ struct device *dev = &epf->dev;
+ struct resource *res;
+ int ret;
+
+ /* Get MMIO base address from Endpoint controller */
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mmio");
+ epf_mhi->mmio_phys = res->start;
+ epf_mhi->mmio_size = resource_size(res);
+
+ epf_mhi->mmio = ioremap(epf_mhi->mmio_phys, epf_mhi->mmio_size);
+ if (IS_ERR(epf_mhi->mmio))
+ return PTR_ERR(epf_mhi->mmio);
+
+ ret = platform_get_irq_byname(pdev, "doorbell");
+ if (ret < 0) {
+ dev_err(dev, "Failed to get Doorbell IRQ\n");
+ iounmap(epf_mhi->mmio);
+ return ret;
+ }
+
+ epf_mhi->irq = ret;
+
+ return 0;
+}
+
+static void pci_epf_mhi_unbind(struct pci_epf *epf)
+{
+ struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf);
+ const struct pci_epf_mhi_ep_info *info = epf_mhi->info;
+ struct pci_epf_bar *epf_bar = &epf->bar[info->bar_num];
+ struct mhi_ep_cntrl *mhi_cntrl = &epf_mhi->mhi_cntrl;
+ struct pci_epc *epc = epf->epc;
+
+ /*
+ * Forcefully power down the MHI EP stack. Only way to bring the MHI EP
+ * stack back to working state after successive bind is by getting BME
+ * from host.
+ */
+ if (mhi_cntrl->mhi_dev) {
+ mhi_ep_power_down(mhi_cntrl);
+ mhi_ep_unregister_controller(mhi_cntrl);
+ }
+
+ iounmap(epf_mhi->mmio);
+ pci_epc_clear_bar(epc, epf->func_no, epf->vfunc_no, epf_bar);
+}
+
+static struct pci_epc_event_ops pci_epf_mhi_event_ops = {
+ .core_init = pci_epf_mhi_core_init,
+ .link_up = pci_epf_mhi_link_up,
+ .link_down = pci_epf_mhi_link_down,
+ .bme = pci_epf_mhi_bme,
+};
+
+static int pci_epf_mhi_probe(struct pci_epf *epf,
+ const struct pci_epf_device_id *id)
+{
+ struct pci_epf_mhi_ep_info *info =
+ (struct pci_epf_mhi_ep_info *)id->driver_data;
+ struct pci_epf_mhi *epf_mhi;
+ struct device *dev = &epf->dev;
+
+ epf_mhi = devm_kzalloc(dev, sizeof(*epf_mhi), GFP_KERNEL);
+ if (!epf_mhi)
+ return -ENOMEM;
+
+ epf->header = info->epf_header;
+ epf_mhi->info = info;
+ epf_mhi->epf = epf;
+
+ epf->event_ops = &pci_epf_mhi_event_ops;
+
+ mutex_init(&epf_mhi->lock);
+
+ epf_set_drvdata(epf, epf_mhi);
+
+ return 0;
+}
+
+static const struct pci_epf_device_id pci_epf_mhi_ids[] = {
+ {
+ .name = "sdx55", .driver_data = (kernel_ulong_t)&sdx55_info,
+ },
+ {},
+};
+
+static struct pci_epf_ops pci_epf_mhi_ops = {
+ .unbind = pci_epf_mhi_unbind,
+ .bind = pci_epf_mhi_bind,
+};
+
+static struct pci_epf_driver pci_epf_mhi_driver = {
+ .driver.name = "pci_epf_mhi",
+ .probe = pci_epf_mhi_probe,
+ .id_table = pci_epf_mhi_ids,
+ .ops = &pci_epf_mhi_ops,
+ .owner = THIS_MODULE,
+};
+
+static int __init pci_epf_mhi_init(void)
+{
+ return pci_epf_register_driver(&pci_epf_mhi_driver);
+}
+module_init(pci_epf_mhi_init);
+
+static void __exit pci_epf_mhi_exit(void)
+{
+ pci_epf_unregister_driver(&pci_epf_mhi_driver);
+}
+module_exit(pci_epf_mhi_exit);
+
+MODULE_DESCRIPTION("PCI EPF driver for MHI Endpoint devices");
+MODULE_AUTHOR("Manivannan Sadhasivam <[email protected]>");
+MODULE_LICENSE("GPL");
--
2.25.1
Add support to pass Link down notification to Endpoint function driver
so that the LINK_DOWN event can be processed by the function.
Reviewed-by: Kishon Vijay Abraham I <[email protected]>
Reviewed-by: Damien Le Moal <[email protected]>
Signed-off-by: Manivannan Sadhasivam <[email protected]>
---
drivers/pci/controller/dwc/pcie-qcom-ep.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/pci/controller/dwc/pcie-qcom-ep.c b/drivers/pci/controller/dwc/pcie-qcom-ep.c
index 19b32839ea26..4ce01ff7527c 100644
--- a/drivers/pci/controller/dwc/pcie-qcom-ep.c
+++ b/drivers/pci/controller/dwc/pcie-qcom-ep.c
@@ -569,6 +569,7 @@ static irqreturn_t qcom_pcie_ep_global_irq_thread(int irq, void *data)
if (FIELD_GET(PARF_INT_ALL_LINK_DOWN, status)) {
dev_dbg(dev, "Received Linkdown event\n");
pcie_ep->link_status = QCOM_PCIE_EP_LINK_DOWN;
+ pci_epc_linkdown(pci->ep.epc);
} else if (FIELD_GET(PARF_INT_ALL_BME, status)) {
dev_dbg(dev, "Received BME event. Link is enabled!\n");
pcie_ep->link_status = QCOM_PCIE_EP_LINK_ENABLED;
--
2.25.1
Add PCI endpoint driver for MHI bus under the MHI bus entry in MAINTAINERS
file.
Signed-off-by: Manivannan Sadhasivam <[email protected]>
---
MAINTAINERS | 1 +
1 file changed, 1 insertion(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 07625a47cf08..a4ac2d567334 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13630,6 +13630,7 @@ F: Documentation/ABI/stable/sysfs-bus-mhi
F: Documentation/mhi/
F: drivers/bus/mhi/
F: drivers/net/mhi_*
+F: drivers/pci/endpoint/functions/pci-epf-mhi.c
F: include/linux/mhi.h
MICROBLAZE ARCHITECTURE
--
2.25.1
On 6/2/23 20:47, Manivannan Sadhasivam wrote:
> Add PCI endpoint driver for MHI bus under the MHI bus entry in MAINTAINERS
> file.
>
> Signed-off-by: Manivannan Sadhasivam <[email protected]>
Reviewed-by: Damien Le Moal <[email protected]>
--
Damien Le Moal
Western Digital Research
On Fri, 02 Jun 2023 17:17:47 +0530, Manivannan Sadhasivam wrote:
> This series adds support for Modem Host Interface (MHI) Endpoint function
> driver and few updates to the PCI endpoint core.
>
> MHI
> ===
>
> MHI is the communication protocol used by the host machines to control and
> communicate with the Qualcomm modems/WLAN devices over any high speed physical
> bus like PCIe. In Linux kernel, MHI is modeled as a bus driver [1] and there
> are two instances of MHI used in a typical setup.
>
> [...]
Applied [with few changes, please check] to controller/endpoint, thanks!
[1/9] PCI: endpoint: Add missing documentation about the MSI/MSI-X range
https://git.kernel.org/pci/pci/c/4753e6a0fe22
[2/9] PCI: endpoint: Pass EPF device ID to the probe function
https://git.kernel.org/pci/pci/c/765b0e80681a
[3/9] PCI: endpoint: Return error if EPC is started/stopped multiple times
https://git.kernel.org/pci/pci/c/0ff3de7a6c87
[4/9] PCI: endpoint: Add linkdown notifier support
https://git.kernel.org/pci/pci/c/755cb1cc2615
[5/9] PCI: endpoint: Add BME notifier support
https://git.kernel.org/pci/pci/c/a2bd0e62f6fd
[6/9] PCI: qcom-ep: Add support for Link down notification
https://git.kernel.org/pci/pci/c/c53dc1547231
[7/9] PCI: qcom-ep: Add support for BME notification
https://git.kernel.org/pci/pci/c/258dfe82065c
[8/9] PCI: endpoint: Add PCI Endpoint function driver for MHI bus
https://git.kernel.org/pci/pci/c/fd0fda1ef61a
[9/9] MAINTAINERS: Add PCI MHI endpoint function driver under MHI bus
https://git.kernel.org/pci/pci/c/71f1861bb90d
Thanks,
Lorenzo
On Fri, Jun 02, 2023 at 05:17:55PM +0530, Manivannan Sadhasivam wrote:
> Add PCI Endpoint driver for the Qualcomm MHI (Modem Host Interface) bus.
> The driver implements the MHI function over PCI in the endpoint device
> such as SDX55 modem. The MHI endpoint function driver acts as a
> controller driver for the MHI Endpoint stack and carries out all PCI
> related activities like mapping the host memory using iATU, triggering
> MSIs etc...
> ...
> +static int pci_epf_mhi_bind(struct pci_epf *epf)
> +{
> ...
> + ret = platform_get_irq_byname(pdev, "doorbell");
> + if (ret < 0) {
> + dev_err(dev, "Failed to get Doorbell IRQ\n");
This dev_err() causes this new warning from the 0-day robot [1]:
drivers/pci/endpoint/functions/pci-epf-mhi.c:362:2-9: line 362 is redundant because platform_get_irq() already prints an error
Maybe we could drop it?
Bjorn
[1] https://lore.kernel.org/all/20230607163937.ZTc-D%[email protected]/
[+cc Yang Li, sorry I didn't notice your patch earlier:
https://lore.kernel.org/r/[email protected]]
I think we can squash this into the original commit since it hasn't
gone upstream yet. Also note that removing the dev_err() apparently
makes "dev" unused, so we'd have to remove that as well, based on this
report [2].
[2] https://lore.kernel.org/r/[email protected]
On Wed, Jun 07, 2023 at 03:49:25PM -0500, Bjorn Helgaas wrote:
> On Fri, Jun 02, 2023 at 05:17:55PM +0530, Manivannan Sadhasivam wrote:
> > Add PCI Endpoint driver for the Qualcomm MHI (Modem Host Interface) bus.
> > The driver implements the MHI function over PCI in the endpoint device
> > such as SDX55 modem. The MHI endpoint function driver acts as a
> > controller driver for the MHI Endpoint stack and carries out all PCI
> > related activities like mapping the host memory using iATU, triggering
> > MSIs etc...
> > ...
>
> > +static int pci_epf_mhi_bind(struct pci_epf *epf)
> > +{
> > ...
>
> > + ret = platform_get_irq_byname(pdev, "doorbell");
> > + if (ret < 0) {
> > + dev_err(dev, "Failed to get Doorbell IRQ\n");
>
> This dev_err() causes this new warning from the 0-day robot [1]:
>
> drivers/pci/endpoint/functions/pci-epf-mhi.c:362:2-9: line 362 is redundant because platform_get_irq() already prints an error
>
> Maybe we could drop it?
>
> Bjorn
>
> [1] https://lore.kernel.org/all/20230607163937.ZTc-D%[email protected]/
On Wed, Jun 07, 2023 at 04:19:41PM -0500, Bjorn Helgaas wrote:
> [+cc Yang Li, sorry I didn't notice your patch earlier:
> https://lore.kernel.org/r/[email protected]]
>
> I think we can squash this into the original commit since it hasn't
> gone upstream yet. Also note that removing the dev_err() apparently
> makes "dev" unused, so we'd have to remove that as well, based on this
> report [2].
>
> [2] https://lore.kernel.org/r/[email protected]
>
> On Wed, Jun 07, 2023 at 03:49:25PM -0500, Bjorn Helgaas wrote:
> > On Fri, Jun 02, 2023 at 05:17:55PM +0530, Manivannan Sadhasivam wrote:
> > > Add PCI Endpoint driver for the Qualcomm MHI (Modem Host Interface) bus.
> > > The driver implements the MHI function over PCI in the endpoint device
> > > such as SDX55 modem. The MHI endpoint function driver acts as a
> > > controller driver for the MHI Endpoint stack and carries out all PCI
> > > related activities like mapping the host memory using iATU, triggering
> > > MSIs etc...
> > > ...
> >
> > > +static int pci_epf_mhi_bind(struct pci_epf *epf)
> > > +{
> > > ...
> >
> > > + ret = platform_get_irq_byname(pdev, "doorbell");
> > > + if (ret < 0) {
> > > + dev_err(dev, "Failed to get Doorbell IRQ\n");
> >
> > This dev_err() causes this new warning from the 0-day robot [1]:
> >
> > drivers/pci/endpoint/functions/pci-epf-mhi.c:362:2-9: line 362 is redundant because platform_get_irq() already prints an error
> >
> > Maybe we could drop it?
> >
Right. I think Lorenzo can handle both while squashing.
- Mani
> > Bjorn
> >
> > [1] https://lore.kernel.org/all/20230607163937.ZTc-D%[email protected]/
--
மணிவண்ணன் சதாசிவம்
On Wed, Jun 07, 2023 at 04:19:41PM -0500, Bjorn Helgaas wrote:
> [+cc Yang Li, sorry I didn't notice your patch earlier:
> https://lore.kernel.org/r/[email protected]]
>
> I think we can squash this into the original commit since it hasn't
> gone upstream yet. Also note that removing the dev_err() apparently
> makes "dev" unused, so we'd have to remove that as well, based on this
> report [2].
>
> [2] https://lore.kernel.org/r/[email protected]
Done.
Thanks,
Lorenzo
> On Wed, Jun 07, 2023 at 03:49:25PM -0500, Bjorn Helgaas wrote:
> > On Fri, Jun 02, 2023 at 05:17:55PM +0530, Manivannan Sadhasivam wrote:
> > > Add PCI Endpoint driver for the Qualcomm MHI (Modem Host Interface) bus.
> > > The driver implements the MHI function over PCI in the endpoint device
> > > such as SDX55 modem. The MHI endpoint function driver acts as a
> > > controller driver for the MHI Endpoint stack and carries out all PCI
> > > related activities like mapping the host memory using iATU, triggering
> > > MSIs etc...
> > > ...
> >
> > > +static int pci_epf_mhi_bind(struct pci_epf *epf)
> > > +{
> > > ...
> >
> > > + ret = platform_get_irq_byname(pdev, "doorbell");
> > > + if (ret < 0) {
> > > + dev_err(dev, "Failed to get Doorbell IRQ\n");
> >
> > This dev_err() causes this new warning from the 0-day robot [1]:
> >
> > drivers/pci/endpoint/functions/pci-epf-mhi.c:362:2-9: line 362 is redundant because platform_get_irq() already prints an error
> >
> > Maybe we could drop it?
> >
> > Bjorn
> >
> > [1] https://lore.kernel.org/all/20230607163937.ZTc-D%[email protected]/