Commit 9d08aa71 authored by Federico Vaga's avatar Federico Vaga Committed by Adam Wujek

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's avatarFederico Vaga <federico.vaga@cern.ch>
parent 1d99d072
......@@ -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;
......
......@@ -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 + )
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment