summaryrefslogtreecommitdiff
path: root/drivers/vbus
diff options
context:
space:
mode:
authorGregory Haskins <ghaskins@novell.com>2009-12-07 11:46:38 -0500
committerGregory Haskins <ghaskins@novell.com>2009-12-07 11:46:38 -0500
commitab8ccab252121a22a74be5d1fef7882bc4b76a57 (patch)
tree96715c150939e154e9608587c86322690551690e /drivers/vbus
parent275732e4c0715ceed7b1d0af358b12ec6c7bc67e (diff)
vbus: register shm-signal events as standard Linux IRQ vectors
This will allow us to view the vector statistics in a uniform way, as well as pave the way for supporting irqbalance in the future. The VBUS PCI-BRIDGE will present itself as an irqchip device to the kernel proper. Each shm-signal that is created by a specific driver will show up as a "VBUS-edge" IRQ in /proc/interrupts. For instane, here is example output from running a venet device as "eth1" (see vectors 28-31): vbus-guest:/home/ghaskins # cat /proc/interrupts CPU0 0: 89 IO-APIC-edge timer 1: 6 IO-APIC-edge i8042 4: 1620 IO-APIC-edge serial 6: 2 IO-APIC-edge floppy 7: 0 IO-APIC-edge parport0 8: 0 IO-APIC-edge rtc0 9: 0 IO-APIC-fasteoi acpi 10: 0 IO-APIC-fasteoi virtio1 12: 90 IO-APIC-edge i8042 14: 3474 IO-APIC-edge ata_piix 15: 7778 IO-APIC-edge ata_piix 24: 185849 PCI-MSI-edge vbus 25: 0 PCI-MSI-edge virtio0-config 26: 210 PCI-MSI-edge virtio0-input 27: 28 PCI-MSI-edge virtio0-output 28: 167062 VBUS-edge eth1-evq 29: 0 VBUS-edge eth1-pageq 30: 161593 VBUS-edge eth1-rx 31: 0 VBUS-edge eth1-tx NMI: 0 Non-maskable interrupts LOC: 72010 Local timer interrupts SPU: 0 Spurious interrupts CNT: 0 Performance counter interrupts PND: 0 Performance pending work RES: 0 Rescheduling interrupts CAL: 0 Function call interrupts TLB: 0 TLB shootdowns TRM: 0 Thermal event interrupts THR: 0 Threshold APIC interrupts MCE: 0 Machine check exceptions MCP: 20 Machine check polls ERR: 0 MIS: 0 Signed-off-by: Gregory Haskins <ghaskins@novell.com>
Diffstat (limited to 'drivers/vbus')
-rw-r--r--drivers/vbus/Kconfig4
-rw-r--r--drivers/vbus/pci-bridge.c91
2 files changed, 74 insertions, 21 deletions
diff --git a/drivers/vbus/Kconfig b/drivers/vbus/Kconfig
index 08667aaed47e..f51cba10913e 100644
--- a/drivers/vbus/Kconfig
+++ b/drivers/vbus/Kconfig
@@ -3,7 +3,7 @@
#
config VBUS_PROXY
- tristate "Virtual-Bus support"
+ bool "Virtual-Bus support"
select SHM_SIGNAL
select IOQ
default n
@@ -14,7 +14,7 @@ config VBUS_PROXY
on the backend, say Y. If unsure, say N.
config VBUS_PCIBRIDGE
- tristate "PCI to Virtual-Bus bridge"
+ bool "PCI to Virtual-Bus bridge"
depends on PCI
depends on VBUS_PROXY
select IOQ
diff --git a/drivers/vbus/pci-bridge.c b/drivers/vbus/pci-bridge.c
index fa77318c2a04..fcde49525886 100644
--- a/drivers/vbus/pci-bridge.c
+++ b/drivers/vbus/pci-bridge.c
@@ -147,15 +147,14 @@ _signal_init(struct shm_signal *signal, struct shm_signal_desc *desc,
*/
struct _signal {
+ char name[64];
struct vbus_pci *pcivbus;
struct shm_signal signal;
u32 handle;
struct rb_node node;
struct list_head list;
- struct {
- int notify;
- int inject;
- } stats;
+ int irq;
+ struct irq_desc *desc;
};
static struct _signal *
@@ -170,7 +169,6 @@ _signal_inject(struct shm_signal *signal)
struct _signal *_signal = to_signal(signal);
vbus_pci.stats.inject++;
- _signal->stats.inject++;
iowrite32(_signal->handle, &vbus_pci.signals->shmsignal);
return 0;
@@ -236,6 +234,7 @@ vbus_pci_device_close(struct vbus_device_proxy *vdev, int flags)
_signal = list_first_entry(&dev->shms, struct _signal, list);
list_del(&_signal->list);
+ free_irq(_signal->irq, _signal);
spin_unlock_irqrestore(&vbus_pci.lock, iflags);
shm_signal_put(&_signal->signal);
@@ -261,6 +260,27 @@ vbus_pci_device_close(struct vbus_device_proxy *vdev, int flags)
return 0;
}
+static void vbus_irq_chip_noop(unsigned int irq)
+{
+}
+
+static struct irq_chip vbus_irq_chip = {
+ .name = "VBUS",
+ .mask = vbus_irq_chip_noop,
+ .unmask = vbus_irq_chip_noop,
+ .eoi = vbus_irq_chip_noop,
+};
+
+irqreturn_t
+shm_signal_intr(int irq, void *dev)
+{
+ struct _signal *_signal = (struct _signal *)dev;
+
+ _shm_signal_wakeup(&_signal->signal);
+
+ return IRQ_HANDLED;
+}
+
static int
vbus_pci_device_shm(struct vbus_device_proxy *vdev, const char *name,
int id, int prio,
@@ -315,24 +335,45 @@ vbus_pci_device_shm(struct vbus_device_proxy *vdev, const char *name,
ret = vbus_pci_buscall(VBUS_PCI_HC_DEVSHM,
&params, sizeof(params));
- if (ret < 0) {
- if (_signal) {
- /*
- * We held two references above, so we need to drop
- * both of them
- */
- shm_signal_put(&_signal->signal);
- shm_signal_put(&_signal->signal);
- }
-
- return ret;
- }
+ if (ret < 0)
+ goto fail;
if (signal) {
+ int irq;
+
BUG_ON(ret < 0);
_signal->handle = ret;
+ irq = create_irq();
+ if (irq < 0) {
+ printk(KERN_ERR "Failed to create IRQ: %d\n", irq);
+ ret = -ENOSPC;
+ goto fail;
+ }
+
+ _signal->irq = irq;
+ _signal->desc = irq_to_desc(irq);
+
+ set_irq_chip_and_handler_name(irq,
+ &vbus_irq_chip,
+ handle_percpu_irq,
+ "edge");
+
+ if (!name)
+ snprintf(_signal->name, sizeof(_signal->name),
+ "dev%lld-id%d", vdev->id, id);
+ else
+ snprintf(_signal->name, sizeof(_signal->name),
+ "%s", name);
+
+ ret = request_irq(irq, shm_signal_intr, 0,
+ _signal->name, _signal);
+ if (ret) {
+ printk(KERN_ERR "Failed to request irq: %d\n", irq);
+ goto fail;
+ }
+
spin_lock_irqsave(&vbus_pci.lock, iflags);
list_add_tail(&_signal->list, &dev->shms);
@@ -344,6 +385,18 @@ vbus_pci_device_shm(struct vbus_device_proxy *vdev, const char *name,
}
return 0;
+
+fail:
+ if (_signal) {
+ /*
+ * We held two references above, so we need to drop
+ * both of them
+ */
+ shm_signal_put(&_signal->signal);
+ shm_signal_put(&_signal->signal);
+ }
+
+ return ret;
}
static int
@@ -454,10 +507,10 @@ static void
event_shmsignal(struct vbus_pci_handle_event *event)
{
struct _signal *_signal = (struct _signal *)event->handle;
+ struct irq_desc *desc = _signal->desc;
vbus_pci.stats.notify++;
- _signal->stats.notify++;
- _shm_signal_wakeup(&_signal->signal);
+ desc->handle_irq(_signal->irq, desc);
}
static void