From 9d08aa71a705d6b8c903691d1549085b0f0625d3 Mon Sep 17 00:00:00 2001 From: Federico Vaga <federico.vaga@cern.ch> Date: Fri, 21 Oct 2016 11:11:29 +0200 Subject: [PATCH] kernel:*: get IRQ numbers from the VIC domain Actually, this is not what I want. I would like to just use an IRQ resource with the correct IRQ number. What I want is to hide the IRQ domain knowledge elsewhere. For instance, in the wrs_device module that register all our devices. But, since I have to update the kernel with the least number of changes I will leave this for the future. Signed-off-by: Federico Vaga <federico.vaga@cern.ch> --- kernel/wr_nic/device.c | 38 +++++++++++++++++++++++++++++++----- kernel/wr_nic/nic-hardware.h | 2 +- kernel/wr_pstats/wr_pstats.c | 34 +++++++++++++++++++++++++++++--- 3 files changed, 65 insertions(+), 9 deletions(-) diff --git a/kernel/wr_nic/device.c b/kernel/wr_nic/device.c index d3f61b56f..20aef6531 100644 --- a/kernel/wr_nic/device.c +++ b/kernel/wr_nic/device.c @@ -20,10 +20,19 @@ #include <linux/spinlock.h> #include <linux/delay.h> #include <linux/io.h> +#include <linux/irqdomain.h> #include "wr-nic.h" #include "nic-mem.h" +/** + * IRQ domain to be used. This is static here but in general it should be + * a module parameter or somehow configurable. For the time being we keep + * it hard-coded here. + */ +static const char *irqdomain_name = "htvic-wr-swi.0"; + + #if WR_IS_NODE /* Our platform_data is different in node vs switch */ #include "../spec-nic.h" static inline struct wrn_dev *wrn_from_pdev(struct platform_device *pdev) @@ -42,7 +51,15 @@ static inline struct wrn_dev *wrn_from_pdev(struct platform_device *pdev) static int wrn_remove(struct platform_device *pdev) { struct wrn_dev *wrn = wrn_from_pdev(pdev); - int i; + int i, irq; + struct irq_domain *irqdomain; + + irqdomain = irq_find_host((struct device_node *)irqdomain_name); + if (!irqdomain) { + dev_err(&pdev->dev, "The IRQ domain %s does not exist\n", + irqdomain_name); + return -EINVAL; + } if (WR_IS_SWITCH) { spin_lock(&wrn->lock); @@ -71,8 +88,10 @@ static int wrn_remove(struct platform_device *pdev) /* Unregister all interrupts that were registered */ for (i = 0; wrn->irq_registered; i++) { static int irqs[] = WRN_IRQ_NUMBERS; - if (wrn->irq_registered & (1 << i)) - free_irq(irqs[i], wrn); + if (wrn->irq_registered & (1 << i)) { + irq = irq_find_mapping(irqdomain, irqs[i]); + free_irq(irq, wrn); + } wrn->irq_registered &= ~(1 << i); } return 0; @@ -113,12 +132,20 @@ static int wrn_probe(struct platform_device *pdev) struct net_device *netdev; struct wrn_ep *ep; struct wrn_dev *wrn = wrn_from_pdev(pdev); - int i, err = 0; + int i, err = 0, irq; /* Lazily: irqs are not in the resource list */ static int irqs[] = WRN_IRQ_NUMBERS; static char *irq_names[] = WRN_IRQ_NAMES; static irq_handler_t irq_handlers[] = WRN_IRQ_HANDLERS; + struct irq_domain *irqdomain; + + irqdomain = irq_find_host((struct device_node *)irqdomain_name); + if (!irqdomain) { + dev_err(&pdev->dev, "The IRQ domain %s does not exist\n", + irqdomain_name); + return -EINVAL; + } /* No need to lock_irq: we only protect count and continue unlocked */ if (WR_IS_SWITCH) { @@ -148,7 +175,8 @@ static int wrn_probe(struct platform_device *pdev) if (WR_IS_SWITCH) { /* Register the interrupt handlers (not shared) */ for (i = 0; i < ARRAY_SIZE(irq_names); i++) { - err = request_irq(irqs[i], irq_handlers[i], + irq = irq_find_mapping(irqdomain, irqs[i]); + err = request_irq(irq, irq_handlers[i], IRQF_TRIGGER_LOW, irq_names[i], wrn); if (err) goto out; diff --git a/kernel/wr_nic/nic-hardware.h b/kernel/wr_nic/nic-hardware.h index ecaa2f107..a51a4bd13 100644 --- a/kernel/wr_nic/nic-hardware.h +++ b/kernel/wr_nic/nic-hardware.h @@ -20,7 +20,7 @@ #define NSEC_PER_TICK (NSEC_PER_SEC / REFCLK_FREQ) /* The interrupt is one of those managed by our WRVIC device */ -#define WRN_IRQ_BASE 192 +#define WRN_IRQ_BASE 0 #define WRN_IRQ_NIC (WRN_IRQ_BASE + 0) #define WRN_IRQ_TSTAMP (WRN_IRQ_BASE + 1) //#define WRN_IRQ_PPSG (WRN_IRQ_BASE + ) diff --git a/kernel/wr_pstats/wr_pstats.c b/kernel/wr_pstats/wr_pstats.c index 1842c71ac..5d12f2a79 100644 --- a/kernel/wr_pstats/wr_pstats.c +++ b/kernel/wr_pstats/wr_pstats.c @@ -28,6 +28,7 @@ #include <linux/spinlock.h> #include <linux/moduleparam.h> #include <linux/netdevice.h> +#include <linux/irqdomain.h> /* * Ugly trick to be able to use headers that have been moved out @@ -41,6 +42,13 @@ #define pstats_readl(device, r) __raw_readl(&device.regs->r) #define pstats_writel(val, device, r) __raw_writel(val, &device.regs->r) +/** + * IRQ domain to be used. This is static here but in general it should be + * a module parameter or somehow configurable. For the time being we keep + * it hard-coded here. + */ +static const char *irqdomain_name = "htvic-wr-swi.0"; + static int pstats_nports = PSTATS_DEFAULT_NPORTS; static uint32_t portmsk; static unsigned int firmware_version; /* FPGA firmware version */ @@ -442,8 +450,16 @@ static struct ctl_table_header *pstats_header; static int __init pstats_init(void) { - int i, err = 0; + int i, err = 0, irq; unsigned int data; + struct irq_domain *irqdomain; + + irqdomain = irq_find_host((struct device_node *)irqdomain_name); + if (!irqdomain) { + pr_err("pstat: The IRQ domain %s does not exist\n", + irqdomain_name); + return -EINVAL; + } if (pstats_nports > PSTATS_MAX_NPORTS) { printk(KERN_ERR "%s: Too many ports for pstats %u," @@ -531,7 +547,8 @@ static int __init pstats_init(void) /*request pstats IRQ*/ pstats_irq_disable(PSTATS_ALL_MSK); - err = request_irq(WRVIC_BASE_IRQ+WR_PSTATS_IRQ, pstats_irq_handler, + irq = irq_find_mapping(irqdomain, WR_PSTATS_IRQ); + err = request_irq(irq, pstats_irq_handler, IRQF_SHARED, "wr_pstats", &pstats_dev); if (err) { printk(KERN_ERR "%s: cannot request interrupt\n", @@ -559,8 +576,19 @@ err_exit: static void __exit pstats_exit(void) { + int irq; + struct irq_domain *irqdomain; + pstats_irq_disable(PSTATS_ALL_MSK); - free_irq(WRVIC_BASE_IRQ+WR_PSTATS_IRQ, &pstats_dev); + + irqdomain = irq_find_host((struct device_node *)irqdomain_name); + if (!irqdomain) { + pr_err("pstat: The IRQ domain %s does not exist\n", + irqdomain_name); + } else { + irq = irq_find_mapping(irqdomain, WR_PSTATS_IRQ); + free_irq(irq, &pstats_dev); + } wr_nic_pstats_callback = NULL; -- GitLab