Skip to content

Commit 031337a

Browse files
Honghui ZhangLorenzo Pieralisi
authored andcommitted
PCI: mediatek: Add loadable kernel module support
Implement remove() callback function for the Mediatek PCIe controller driver to add loadable kernel module support. Save the PCIe's GIC IRQ at probe so that it can be retrieved to call dispose_irq() to tear down the IRQ upon module removal. Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com> [lorenzo.pieralisi@arm.com: updated commit log] Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Reviewed-by: Ryder Lee <ryder.lee@mediatek.com>
1 parent 97d2932 commit 031337a

File tree

2 files changed

+57
-5
lines changed

2 files changed

+57
-5
lines changed

drivers/pci/controller/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ config PCIE_ROCKCHIP_EP
231231
available to support GEN2 with 4 slots.
232232

233233
config PCIE_MEDIATEK
234-
bool "MediaTek PCIe controller"
234+
tristate "MediaTek PCIe controller"
235235
depends on ARCH_MEDIATEK || COMPILE_TEST
236236
depends on OF
237237
depends on PCI_MSI_IRQ_DOMAIN

drivers/pci/controller/pcie-mediatek.c

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <linux/irqdomain.h>
1616
#include <linux/kernel.h>
1717
#include <linux/msi.h>
18+
#include <linux/module.h>
1819
#include <linux/of_address.h>
1920
#include <linux/of_pci.h>
2021
#include <linux/of_platform.h>
@@ -162,6 +163,7 @@ struct mtk_pcie_soc {
162163
* @phy: pointer to PHY control block
163164
* @lane: lane count
164165
* @slot: port slot
166+
* @irq: GIC irq
165167
* @irq_domain: legacy INTx IRQ domain
166168
* @inner_domain: inner IRQ domain
167169
* @msi_domain: MSI IRQ domain
@@ -182,6 +184,7 @@ struct mtk_pcie_port {
182184
struct phy *phy;
183185
u32 lane;
184186
u32 slot;
187+
int irq;
185188
struct irq_domain *irq_domain;
186189
struct irq_domain *inner_domain;
187190
struct irq_domain *msi_domain;
@@ -530,6 +533,27 @@ static void mtk_pcie_enable_msi(struct mtk_pcie_port *port)
530533
writel(val, port->base + PCIE_INT_MASK);
531534
}
532535

536+
static void mtk_pcie_irq_teardown(struct mtk_pcie *pcie)
537+
{
538+
struct mtk_pcie_port *port, *tmp;
539+
540+
list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
541+
irq_set_chained_handler_and_data(port->irq, NULL, NULL);
542+
543+
if (port->irq_domain)
544+
irq_domain_remove(port->irq_domain);
545+
546+
if (IS_ENABLED(CONFIG_PCI_MSI)) {
547+
if (port->msi_domain)
548+
irq_domain_remove(port->msi_domain);
549+
if (port->inner_domain)
550+
irq_domain_remove(port->inner_domain);
551+
}
552+
553+
irq_dispose_mapping(port->irq);
554+
}
555+
}
556+
533557
static int mtk_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
534558
irq_hw_number_t hwirq)
535559
{
@@ -620,16 +644,17 @@ static int mtk_pcie_setup_irq(struct mtk_pcie_port *port,
620644
struct mtk_pcie *pcie = port->pcie;
621645
struct device *dev = pcie->dev;
622646
struct platform_device *pdev = to_platform_device(dev);
623-
int err, irq;
647+
int err;
624648

625649
err = mtk_pcie_init_irq_domain(port, node);
626650
if (err) {
627651
dev_err(dev, "failed to init PCIe IRQ domain\n");
628652
return err;
629653
}
630654

631-
irq = platform_get_irq(pdev, port->slot);
632-
irq_set_chained_handler_and_data(irq, mtk_pcie_intr_handler, port);
655+
port->irq = platform_get_irq(pdev, port->slot);
656+
irq_set_chained_handler_and_data(port->irq,
657+
mtk_pcie_intr_handler, port);
633658

634659
return 0;
635660
}
@@ -1168,6 +1193,31 @@ static int mtk_pcie_probe(struct platform_device *pdev)
11681193
return err;
11691194
}
11701195

1196+
1197+
static void mtk_pcie_free_resources(struct mtk_pcie *pcie)
1198+
{
1199+
struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie);
1200+
struct list_head *windows = &host->windows;
1201+
1202+
pci_free_resource_list(windows);
1203+
}
1204+
1205+
static int mtk_pcie_remove(struct platform_device *pdev)
1206+
{
1207+
struct mtk_pcie *pcie = platform_get_drvdata(pdev);
1208+
struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie);
1209+
1210+
pci_stop_root_bus(host->bus);
1211+
pci_remove_root_bus(host->bus);
1212+
mtk_pcie_free_resources(pcie);
1213+
1214+
mtk_pcie_irq_teardown(pcie);
1215+
1216+
mtk_pcie_put_resources(pcie);
1217+
1218+
return 0;
1219+
}
1220+
11711221
static int __maybe_unused mtk_pcie_suspend_noirq(struct device *dev)
11721222
{
11731223
struct mtk_pcie *pcie = dev_get_drvdata(dev);
@@ -1245,11 +1295,13 @@ static const struct of_device_id mtk_pcie_ids[] = {
12451295

12461296
static struct platform_driver mtk_pcie_driver = {
12471297
.probe = mtk_pcie_probe,
1298+
.remove = mtk_pcie_remove,
12481299
.driver = {
12491300
.name = "mtk-pcie",
12501301
.of_match_table = mtk_pcie_ids,
12511302
.suppress_bind_attrs = true,
12521303
.pm = &mtk_pcie_pm_ops,
12531304
},
12541305
};
1255-
builtin_platform_driver(mtk_pcie_driver);
1306+
module_platform_driver(mtk_pcie_driver);
1307+
MODULE_LICENSE("GPL v2");

0 commit comments

Comments
 (0)