From: Alexander Graf <agraf@suse.de>
To: qemu-devel Developers <qemu-devel@nongnu.org>
Cc: blauwirbel@gmail.com, qemu-ppc@nongnu.org,
David Gibson <david@gibson.dropbear.id.au>
Subject: [Qemu-devel] [PATCH 5/8] pseries: Use the same interrupt swizzling for host bridges as p2p bridges
Date: Tue, 1 May 2012 21:50:54 +0200 [thread overview]
Message-ID: <1335901857-29799-6-git-send-email-agraf@suse.de> (raw)
In-Reply-To: <1335901857-29799-1-git-send-email-agraf@suse.de>
From: David Gibson <david@gibson.dropbear.id.au>
Currently the pseries PCI code uses a somewhat strange scheme of PCI irq
allocation - one per slot up to a maximum that's greater than the usual 4.
This scheme more or less worked, because we were able to tell the guest the
irq mapping in the device tree, however it's a bit odd and may break
assumptions in the future. Worse, the array used to construct the dev
tree interrupt map was mis-sized, we got away with it only because it
happened that our SPAPR_PCI_NUM_LSI value was greater than 7.
This patch changes the pseries PCI code to use the same interrupt swizzling
scheme as is standardized for PCI to PCI bridges. This makes for better
consistency, deals better with any devices which use multiple interrupt
pins and will make life easier in the future when we add passthrough of
what may be either a host bridge or a PCI to PCI bridge. This won't break
existing guests, because they don't assume a particular mapping scheme for
host bridges, but just follow what we tell them in the device tree (also
updated to match, of course). This patch also fixes the allocation of the
irq map.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
hw/spapr_pci.c | 49 ++++++++++++++++++++++++++++---------------------
hw/spapr_pci.h | 5 ++---
2 files changed, 30 insertions(+), 24 deletions(-)
diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
index a564c00..25b400a 100644
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@ -198,16 +198,20 @@ static void rtas_write_pci_config(sPAPREnvironment *spapr,
finish_write_pci_config(spapr, 0, addr, size, val, rets);
}
+static int pci_spapr_swizzle(int slot, int pin)
+{
+ return (slot + pin) % PCI_NUM_PINS;
+}
+
static int pci_spapr_map_irq(PCIDevice *pci_dev, int irq_num)
{
/*
* Here we need to convert pci_dev + irq_num to some unique value
- * which is less than number of IRQs on the specific bus (now it
- * is 16). At the moment irq_num == device_id (number of the
- * slot?)
- * FIXME: we should swizzle in fn and irq_num
+ * which is less than number of IRQs on the specific bus (4). We
+ * use standard PCI swizzling, that is (slot number + pin number)
+ * % 4.
*/
- return (pci_dev->devfn >> 3) % SPAPR_PCI_NUM_LSI;
+ return pci_spapr_swizzle(PCI_SLOT(pci_dev->devfn), irq_num);
}
static void pci_spapr_set_irq(void *opaque, int irq_num, int level)
@@ -304,13 +308,13 @@ static int spapr_phb_init(SysBusDevice *s)
phb->busname ? phb->busname : phb->dtbusname,
pci_spapr_set_irq, pci_spapr_map_irq, phb,
&phb->memspace, &phb->iospace,
- PCI_DEVFN(0, 0), SPAPR_PCI_NUM_LSI);
+ PCI_DEVFN(0, 0), PCI_NUM_PINS);
phb->host_state.bus = bus;
QLIST_INSERT_HEAD(&spapr->phbs, phb, list);
/* Initialize the LSI table */
- for (i = 0; i < SPAPR_PCI_NUM_LSI; i++) {
+ for (i = 0; i < PCI_NUM_PINS; i++) {
qemu_irq qirq;
uint32_t num;
@@ -392,8 +396,7 @@ int spapr_populate_pci_devices(sPAPRPHBState *phb,
uint32_t xics_phandle,
void *fdt)
{
- PCIBus *bus = phb->host_state.bus;
- int bus_off, i;
+ int bus_off, i, j;
char nodename[256];
uint32_t bus_range[] = { cpu_to_be32(0), cpu_to_be32(0xff) };
struct {
@@ -415,8 +418,8 @@ int spapr_populate_pci_devices(sPAPRPHBState *phb,
};
uint64_t bus_reg[] = { cpu_to_be64(phb->buid), 0 };
uint32_t interrupt_map_mask[] = {
- cpu_to_be32(b_ddddd(-1)|b_fff(0)), 0x0, 0x0, 0x0};
- uint32_t interrupt_map[bus->nirq][7];
+ cpu_to_be32(b_ddddd(-1)|b_fff(0)), 0x0, 0x0, cpu_to_be32(-1)};
+ uint32_t interrupt_map[PCI_SLOT_MAX * PCI_NUM_PINS][7];
/* Start populating the FDT */
sprintf(nodename, "pci@%" PRIx64, phb->buid);
@@ -450,19 +453,23 @@ int spapr_populate_pci_devices(sPAPRPHBState *phb,
*/
_FDT(fdt_setprop(fdt, bus_off, "interrupt-map-mask",
&interrupt_map_mask, sizeof(interrupt_map_mask)));
- for (i = 0; i < 7; i++) {
- uint32_t *irqmap = interrupt_map[i];
- irqmap[0] = cpu_to_be32(b_ddddd(i)|b_fff(0));
- irqmap[1] = 0;
- irqmap[2] = 0;
- irqmap[3] = 0;
- irqmap[4] = cpu_to_be32(xics_phandle);
- irqmap[5] = cpu_to_be32(phb->lsi_table[i % SPAPR_PCI_NUM_LSI].dt_irq);
- irqmap[6] = cpu_to_be32(0x8);
+ for (i = 0; i < PCI_SLOT_MAX; i++) {
+ for (j = 0; j < PCI_NUM_PINS; j++) {
+ uint32_t *irqmap = interrupt_map[i*PCI_NUM_PINS + j];
+ int lsi_num = pci_spapr_swizzle(i, j);
+
+ irqmap[0] = cpu_to_be32(b_ddddd(i)|b_fff(0));
+ irqmap[1] = 0;
+ irqmap[2] = 0;
+ irqmap[3] = cpu_to_be32(j+1);
+ irqmap[4] = cpu_to_be32(xics_phandle);
+ irqmap[5] = cpu_to_be32(phb->lsi_table[lsi_num].dt_irq);
+ irqmap[6] = cpu_to_be32(0x8);
+ }
}
/* Write interrupt map */
_FDT(fdt_setprop(fdt, bus_off, "interrupt-map", &interrupt_map,
- 7 * sizeof(interrupt_map[0])));
+ sizeof(interrupt_map)));
return 0;
}
diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h
index 039f85b..f54c2e8 100644
--- a/hw/spapr_pci.h
+++ b/hw/spapr_pci.h
@@ -23,11 +23,10 @@
#if !defined(__HW_SPAPR_PCI_H__)
#define __HW_SPAPR_PCI_H__
+#include "hw/pci.h"
#include "hw/pci_host.h"
#include "hw/xics.h"
-#define SPAPR_PCI_NUM_LSI 16
-
typedef struct sPAPRPHBState {
SysBusDevice busdev;
PCIHostState host_state;
@@ -43,7 +42,7 @@ typedef struct sPAPRPHBState {
struct {
uint32_t dt_irq;
qemu_irq qirq;
- } lsi_table[SPAPR_PCI_NUM_LSI];
+ } lsi_table[PCI_NUM_PINS];
QLIST_ENTRY(sPAPRPHBState) list;
} sPAPRPHBState;
--
1.6.0.2
next prev parent reply other threads:[~2012-05-01 19:51 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-05-01 19:50 [Qemu-devel] [PULL 0/8] ppc patch queue 2012-05-01 Alexander Graf
2012-05-01 19:50 ` [Qemu-devel] [PATCH 1/8] booke:Use MMU API for creating initial mapping for secondary cpus Alexander Graf
2012-05-01 19:50 ` [Qemu-devel] [PATCH 2/8] PPC: Fix up e500 cache size setting Alexander Graf
2012-05-01 19:50 ` [Qemu-devel] [PATCH 3/8] linux-user: Fix undefined HOST_LONG_SIZE on PPC hosts Alexander Graf
2012-05-01 20:51 ` Stefan Weil
2012-05-01 21:02 ` Andreas Färber
2012-05-01 19:50 ` [Qemu-devel] [PATCH 4/8] pseries: Implement automatic PAPR VIO address allocation Alexander Graf
2012-05-01 19:50 ` Alexander Graf [this message]
2012-05-01 19:50 ` [Qemu-devel] [PATCH 6/8] pseries: Fix use of global CPU state Alexander Graf
2012-05-01 19:50 ` [Qemu-devel] [PATCH 7/8] ppce500_spin: Replace assert by hw_error (fixes compiler warning) Alexander Graf
2012-05-01 19:50 ` [Qemu-devel] [PATCH 8/8] target-ppc: Some support for dumping TLB_EMB TLBs Alexander Graf
-- strict thread matches above, loose matches on Subject: below --
2012-05-01 8:58 [Qemu-devel] [PULL 0/8] ppc patch queue 2012-05-01 Alexander Graf
2012-05-01 8:58 ` [Qemu-devel] [PATCH 5/8] pseries: Use the same interrupt swizzling for host bridges as p2p bridges Alexander Graf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1335901857-29799-6-git-send-email-agraf@suse.de \
--to=agraf@suse.de \
--cc=blauwirbel@gmail.com \
--cc=david@gibson.dropbear.id.au \
--cc=qemu-devel@nongnu.org \
--cc=qemu-ppc@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).